1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
import type { FlatpakApp, RunningFlatpakApp } from "../api/lsfgApi";
import type { GameTarget } from "./gameTargets";
export type NowPlayingTarget =
| {
kind: "flatpak";
app: FlatpakApp;
launcher: GameTarget | null;
}
| {
kind: "steam";
game: GameTarget;
}
| {
kind: "nonSteam";
game: GameTarget;
};
function numericValue(value: number | null | undefined): number {
return typeof value === "number" && Number.isFinite(value) ? value : -1;
}
function numericPid(value: string | undefined): number {
return value && /^\d+$/.test(value) ? Number(value) : -1;
}
function compareRunningProcesses(a: RunningFlatpakApp, b: RunningFlatpakApp): number {
if (a.active !== b.active) return a.active ? -1 : 1;
const startDifference = numericValue(b.start_time) - numericValue(a.start_time);
if (startDifference !== 0) return startDifference;
return numericPid(b.pid) - numericPid(a.pid);
}
export function selectMostRecentRunningFlatpak(
apps: FlatpakApp[],
runningApps: RunningFlatpakApp[],
): FlatpakApp | null {
const newestProcessByApp = new Map<string, RunningFlatpakApp>();
for (const running of runningApps) {
const current = newestProcessByApp.get(running.app_id);
if (!current || compareRunningProcesses(running, current) < 0) {
newestProcessByApp.set(running.app_id, running);
}
}
const candidates = Array.from(newestProcessByApp.values())
.map((running) => ({
running,
app: apps.find((app) => app.app_id === running.app_id) || null,
}))
.filter((candidate): candidate is { running: RunningFlatpakApp; app: FlatpakApp } => candidate.app !== null);
const activeCandidates = candidates.filter(({ running }) => running.active);
const eligibleCandidates = activeCandidates.length > 0
? activeCandidates
: candidates.length === 1
? candidates
: [];
eligibleCandidates.sort((a, b) => {
const processDifference = compareRunningProcesses(a.running, b.running);
if (processDifference !== 0) return processDifference;
return a.running.app_id.localeCompare(b.running.app_id);
});
return eligibleCandidates[0]?.app || null;
}
export function resolveNowPlayingTarget(
runningGame: GameTarget | null,
runningFlatpak: FlatpakApp | null,
): NowPlayingTarget | null {
if (runningGame?.source === "steam") {
return runningGame.configured ? { kind: "steam", game: runningGame } : null;
}
if (runningFlatpak) {
return {
kind: "flatpak",
app: runningFlatpak,
launcher: runningGame?.source === "nonSteam" ? runningGame : null,
};
}
if (runningGame?.source === "nonSteam" && runningGame.configured) {
return { kind: "nonSteam", game: runningGame };
}
return null;
}
|