fix(jellyfin): fix discovery loop, device identity, tray state, and Disc

- Derive device identity from OS hostname; remove legacy configurable client/device fields
- Prevent discovery playback from reloading active item, misreporting pause state, and duplicate overlay restores
- Restart stale tray discovery sessions without re-login when server drops SubMiner cast target
- Sync tray discovery checkbox state on Linux after CLI/startup/remote-session changes
- Stop Discord presence falling back to stream URLs; prime title before tokenized stream loads
- Fix picker library discovery when log level is above info
- Fix config.example.jsonc trailing commas and array formatting
This commit is contained in:
2026-05-22 01:36:11 -07:00
parent 85d838ac96
commit 2f2dfa3e91
72 changed files with 2063 additions and 589 deletions
+16 -8
View File
@@ -361,6 +361,21 @@ export function classifyJellyfinChildSelection(
fail('Selected Jellyfin item is not playable.');
}
export function buildForwardedJellyfinAppArgs(args: Args, appArgs: string[]): string[] {
const forwarded = [...appArgs];
const serverOverride = sanitizeServerUrl(args.jellyfinServer || '');
if (serverOverride) {
forwarded.push('--jellyfin-server', serverOverride);
}
if (args.passwordStore) {
forwarded.push('--password-store', args.passwordStore);
}
if (!forwarded.some((arg) => arg === '--log-level' || arg.startsWith('--log-level='))) {
forwarded.push('--log-level', args.logLevel);
}
return forwarded;
}
async function runAppJellyfinListCommand(
appPath: string,
args: Args,
@@ -384,14 +399,7 @@ async function runAppJellyfinCommand(
appArgs: string[],
label: string,
): Promise<{ status: number; output: string; error: string; logOffset: number }> {
const forwardedBase = [...appArgs];
const serverOverride = sanitizeServerUrl(args.jellyfinServer || '');
if (serverOverride) {
forwardedBase.push('--jellyfin-server', serverOverride);
}
if (args.passwordStore) {
forwardedBase.push('--password-store', args.passwordStore);
}
const forwardedBase = buildForwardedJellyfinAppArgs(args, appArgs);
const readLogAppendedSince = (offset: number): string => {
const logPath = getMpvLogPath();
+22
View File
@@ -17,6 +17,7 @@ import {
parseEpisodePathFromDisplay,
buildRootSearchGroups,
classifyJellyfinChildSelection,
buildForwardedJellyfinAppArgs,
} from './jellyfin.js';
type RunResult = {
@@ -878,6 +879,27 @@ test('parseJellyfinItemsFromAppOutput parses item title/id/type tuples', () => {
]);
});
test('buildForwardedJellyfinAppArgs forces app log level for parseable list output', () => {
const forwarded = buildForwardedJellyfinAppArgs(
{
jellyfinServer: 'https://jf.example.test/',
passwordStore: 'gnome-libsecret',
logLevel: 'info',
} as never,
['--jellyfin-libraries'],
);
assert.deepEqual(forwarded, [
'--jellyfin-libraries',
'--jellyfin-server',
'https://jf.example.test',
'--password-store',
'gnome-libsecret',
'--log-level',
'info',
]);
});
test('parseJellyfinErrorFromAppOutput extracts bracketed error lines', () => {
const parsed = parseJellyfinErrorFromAppOutput(`
[subminer] - 2026-03-01 13:10:34 - WARN - [main] test warning