forked from unom/punktfunk
The Identity card gains an "Operating system" row: the pretty name as text, the raw identity chain as its tooltip, and a leading OsIcon resolved by the same most-specific-first walk as the clients. lucide deliberately ships no brand marks, so os-icon.tsx vendors the ten as inline currentColor SVGs (the brand-mark precedent, the plugin-registry pattern), falling back to a generic monitor for a chain nothing recognizes. Row grows optional icon/title props rather than a fork; stories cover Bazzite, Windows and the unknown-distro degradation; labels land in both message files. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
300 lines
7.2 KiB
TypeScript
300 lines
7.2 KiB
TypeScript
// Mock API payloads for the page stories — typed against the generated models so
|
|
// they stay honest if the OpenAPI schema changes.
|
|
import type { AvailableCompositor } from "@/api/gen/model/availableCompositor";
|
|
import type { Capture } from "@/api/gen/model/capture";
|
|
import type { CaptureMeta } from "@/api/gen/model/captureMeta";
|
|
import type { GameEntry } from "@/api/gen/model/gameEntry";
|
|
import type { HostInfo } from "@/api/gen/model/hostInfo";
|
|
import type { NativeClient } from "@/api/gen/model/nativeClient";
|
|
import type { NativePairStatus } from "@/api/gen/model/nativePairStatus";
|
|
import type { PairedClient } from "@/api/gen/model/pairedClient";
|
|
import type { PairingStatus } from "@/api/gen/model/pairingStatus";
|
|
import type { PendingDevice } from "@/api/gen/model/pendingDevice";
|
|
import type { RuntimeStatus } from "@/api/gen/model/runtimeStatus";
|
|
import type { StatsSample } from "@/api/gen/model/statsSample";
|
|
import type { StatsStatus } from "@/api/gen/model/statsStatus";
|
|
|
|
export const hostInfo: HostInfo = {
|
|
abi_version: 2,
|
|
app_version: "7.1.450.0",
|
|
codecs: ["h264", "hevc", "av1"],
|
|
gamestream: true,
|
|
gfe_version: "3.23.0.74",
|
|
hostname: "ENRICOS-DESKTOP",
|
|
local_ip: "192.168.1.173",
|
|
os: "linux/fedora/bazzite",
|
|
os_name: "Bazzite 42 (Kinoite)",
|
|
ports: {
|
|
audio: 48000,
|
|
control: 47999,
|
|
http: 47989,
|
|
https: 47984,
|
|
mgmt: 47990,
|
|
rtsp: 48010,
|
|
video: 47998,
|
|
},
|
|
uniqueid: "0f8a1c3e9b7d4a62",
|
|
version: "0.2.0",
|
|
};
|
|
|
|
export const compositors: AvailableCompositor[] = [
|
|
{ id: "kwin", label: "KWin (Plasma)", available: true, default: true },
|
|
{ id: "gamescope", label: "gamescope", available: true, default: false },
|
|
{ id: "mutter", label: "Mutter (GNOME)", available: false, default: false },
|
|
{ id: "wlroots", label: "Sway / wlroots", available: false, default: false },
|
|
];
|
|
|
|
export const statusActive: RuntimeStatus = {
|
|
video_streaming: true,
|
|
audio_streaming: true,
|
|
paired_clients: 3,
|
|
native_paired_clients: 2,
|
|
pin_pending: false,
|
|
active_sessions: 1,
|
|
session: { width: 5120, height: 1440, fps: 240 },
|
|
stream: {
|
|
codec: "hevc",
|
|
width: 5120,
|
|
height: 1440,
|
|
fps: 240,
|
|
bitrate_kbps: 150_000,
|
|
min_fec: 5,
|
|
packet_size: 1392,
|
|
},
|
|
games: [
|
|
{
|
|
session_id: 1,
|
|
client: "Living room TV",
|
|
app_id: "steam:1145360",
|
|
title: "Hades",
|
|
store: "steam",
|
|
plane: "native",
|
|
state: "running",
|
|
},
|
|
],
|
|
};
|
|
|
|
export const statusIdle: RuntimeStatus = {
|
|
video_streaming: false,
|
|
audio_streaming: false,
|
|
paired_clients: 1,
|
|
native_paired_clients: 0,
|
|
pin_pending: true,
|
|
active_sessions: 0,
|
|
session: null,
|
|
stream: null,
|
|
games: [],
|
|
};
|
|
|
|
/**
|
|
* Idle, but a game its client walked away from is still running — on a countdown to being closed.
|
|
* The state the running-game card exists for.
|
|
*/
|
|
export const statusGrace: RuntimeStatus = {
|
|
...statusIdle,
|
|
games: [
|
|
{
|
|
client: "Living room TV",
|
|
app_id: "steam:1145360",
|
|
title: "Hades",
|
|
store: "steam",
|
|
plane: "native",
|
|
state: "grace",
|
|
grace_remaining_s: 252,
|
|
},
|
|
],
|
|
};
|
|
|
|
export const pairedClients: PairedClient[] = [
|
|
{
|
|
fingerprint:
|
|
"a1b2c3d4e5f60718293a4b5c6d7e8f90112233445566778899aabbccddeeff00",
|
|
subject: "enricos-macbook",
|
|
not_before_unix: 1_718_000_000,
|
|
not_after_unix: 2_030_000_000,
|
|
},
|
|
{
|
|
fingerprint:
|
|
"ff00eeddccbbaa998877665544332211009f8e7d6c5b4a39281706f5e4d3c2b1",
|
|
subject: "living-room-tv",
|
|
not_before_unix: 1_718_500_000,
|
|
not_after_unix: 2_030_000_000,
|
|
},
|
|
{
|
|
fingerprint:
|
|
"0011223344556677889900aabbccddeeff112233445566778899aabbccddeeff",
|
|
subject: null,
|
|
},
|
|
];
|
|
|
|
const noArt = { header: null, hero: null, logo: null, portrait: null };
|
|
export const library: GameEntry[] = [
|
|
{
|
|
id: "steam:1245620",
|
|
store: "steam",
|
|
title: "Elden Ring",
|
|
art: noArt,
|
|
launch: null,
|
|
},
|
|
{
|
|
id: "steam:1086940",
|
|
store: "steam",
|
|
title: "Baldur's Gate 3",
|
|
art: noArt,
|
|
launch: null,
|
|
},
|
|
{
|
|
id: "steam:413150",
|
|
store: "steam",
|
|
title: "Stardew Valley",
|
|
art: noArt,
|
|
launch: null,
|
|
},
|
|
{
|
|
id: "custom:retroarch",
|
|
store: "custom",
|
|
title: "RetroArch",
|
|
art: noArt,
|
|
launch: null,
|
|
},
|
|
// An emulated title with the metadata fields filled — exercises the platform
|
|
// badge (non-PC) and the year in the caption.
|
|
{
|
|
id: "custom:sotc",
|
|
store: "custom",
|
|
title: "Shadow of the Colossus",
|
|
art: noArt,
|
|
launch: null,
|
|
platform: "PS2",
|
|
developer: "Team Ico",
|
|
publisher: "Sony Computer Entertainment",
|
|
release_year: 2005,
|
|
genres: ["Adventure"],
|
|
tags: ["favorite"],
|
|
region: "PAL",
|
|
players: 1,
|
|
},
|
|
];
|
|
|
|
// --- Performance (stats) page ------------------------------------------------
|
|
|
|
export const statsStatusIdle: StatsStatus = {
|
|
armed: false,
|
|
kind: "native",
|
|
sample_count: 0,
|
|
started_unix_ms: 0,
|
|
elapsed_ms: 0,
|
|
};
|
|
|
|
// A native-path pipeline: capture → submit → encode → send. Deterministic (no
|
|
// Math.random) so the screenshot is byte-stable across CI runs; a gentle sine
|
|
// gives the charts a realistic shape without a live capture.
|
|
const STAGE_BASE_US: Record<string, number> = {
|
|
capture: 320,
|
|
submit: 90,
|
|
encode: 760,
|
|
send: 140,
|
|
};
|
|
const STAGE_ORDER = ["capture", "submit", "encode", "send"];
|
|
|
|
function buildSamples(n: number): StatsSample[] {
|
|
const out: StatsSample[] = [];
|
|
for (let i = 0; i < n; i++) {
|
|
const wobble = Math.sin(i / 4);
|
|
out.push({
|
|
t_ms: i * 1000,
|
|
session_id: 1,
|
|
fps: 240,
|
|
repeat_fps: i % 3 === 0 ? 2 : 1,
|
|
mbps: 920 + wobble * 55,
|
|
bitrate_kbps: 150_000,
|
|
frames_dropped: i % 17 === 0 ? 1 : 0,
|
|
packets_dropped: i % 9 === 0 ? 2 : 0,
|
|
send_dropped: 0,
|
|
fec_recovered: i % 5 === 0 ? 3 : 1,
|
|
stages: STAGE_ORDER.map((name) => {
|
|
const base = STAGE_BASE_US[name] ?? 100;
|
|
const p50 = Math.round(base + wobble * base * 0.15);
|
|
return { name, p50_us: p50, p99_us: Math.round(p50 * 1.8) };
|
|
}),
|
|
});
|
|
}
|
|
return out;
|
|
}
|
|
|
|
export const captureMetas: CaptureMeta[] = [
|
|
{
|
|
id: "cap-20260628-2041",
|
|
client: "enricos-macbook",
|
|
kind: "native",
|
|
codec: "hevc",
|
|
width: 5120,
|
|
height: 1440,
|
|
fps: 240,
|
|
duration_ms: 92_000,
|
|
sample_count: 92,
|
|
started_unix_ms: 1_782_415_260_000,
|
|
encoder_backend: "nvenc",
|
|
gpu: "NVIDIA GeForce RTX 4090",
|
|
},
|
|
{
|
|
id: "cap-20260628-1903",
|
|
client: "living-room-tv",
|
|
kind: "gamestream",
|
|
codec: "av1",
|
|
width: 3840,
|
|
height: 2160,
|
|
fps: 120,
|
|
duration_ms: 240_000,
|
|
sample_count: 240,
|
|
started_unix_ms: 1_782_409_380_000,
|
|
},
|
|
];
|
|
|
|
export const captureDetail: Capture = {
|
|
meta: captureMetas[0] as CaptureMeta,
|
|
samples: buildSamples(60),
|
|
};
|
|
|
|
// --- Pairing page ------------------------------------------------------------
|
|
|
|
export const nativePairArmed: NativePairStatus = {
|
|
enabled: true,
|
|
armed: true,
|
|
pin: "4827",
|
|
expires_in_secs: 98,
|
|
paired_clients: 2,
|
|
};
|
|
|
|
export const pendingDevices: PendingDevice[] = [
|
|
{
|
|
id: 1,
|
|
name: "studio-deck",
|
|
fingerprint:
|
|
"9f8e7d6c5b4a39281706f5e4d3c2b1a0998877665544332211ffeeddccbbaa00",
|
|
age_secs: 8,
|
|
},
|
|
{
|
|
id: 2,
|
|
name: "Mac Mini",
|
|
fingerprint:
|
|
"ff00eeddccbbaa998877665544332211009f8e7d6c5b4a39281706f5e4d3c2b1",
|
|
age_secs: 30,
|
|
},
|
|
];
|
|
|
|
export const nativeClients: NativeClient[] = [
|
|
{
|
|
name: "enricos-macbook",
|
|
fingerprint:
|
|
"a1b2c3d4e5f60718293a4b5c6d7e8f90112233445566778899aabbccddeeff00",
|
|
},
|
|
{
|
|
name: "living-room-tv",
|
|
fingerprint:
|
|
"ff00eeddccbbaa998877665544332211009f8e7d6c5b4a39281706f5e4d3c2b1",
|
|
},
|
|
];
|
|
|
|
export const pairingIdle: PairingStatus = { pin_pending: false };
|