mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-05-27 00:55:16 -07:00
fix: managed playback overlay lifecycle for launcher-owned sessions
- Remove --background from launcher-owned mpv starts; quit only non-tray/non-background managed sessions - Defer autoplay-ready signal until overlay window content is loaded; retry after flush - Retry socket availability before auto-starting overlay (up to 25 attempts, 200ms apart) - Extract warm tokenization signal into autoplay-tokenization-warm-release with stale-media guard - Queue second-instance commands until app ready runtime completes - Guard globalShortcut cleanup with isAppReady check to avoid pre-ready crash - Recognize "osx" as a macOS platform alias in Lua environment detection
This commit is contained in:
@@ -168,3 +168,58 @@ test('startAppLifecycle app ping exits zero immediately when another instance ow
|
||||
assert.equal(lockCalls, 1);
|
||||
assert.deepEqual(calls, ['exit:0']);
|
||||
});
|
||||
|
||||
test('startAppLifecycle queues second-instance commands until app ready runtime completes', async () => {
|
||||
const handled: string[] = [];
|
||||
let secondInstanceHandler: ((_event: unknown, argv: string[]) => void) | null = null;
|
||||
let readyHandler: (() => Promise<void>) | null = null;
|
||||
let releaseReady: (() => void) | null = null;
|
||||
const readyFinished = new Promise<void>((resolve) => {
|
||||
releaseReady = resolve;
|
||||
});
|
||||
|
||||
const { deps } = createDeps({
|
||||
shouldStartApp: () => true,
|
||||
onSecondInstance: (handler) => {
|
||||
secondInstanceHandler = handler;
|
||||
},
|
||||
parseArgs: (argv) => makeArgs({ start: argv.includes('--start') }),
|
||||
handleCliCommand: (args, source) => {
|
||||
handled.push(`${source}:${args.start ? 'start' : 'other'}`);
|
||||
},
|
||||
whenReady: (handler) => {
|
||||
readyHandler = handler;
|
||||
},
|
||||
onReady: async () => {
|
||||
await readyFinished;
|
||||
handled.push('ready');
|
||||
},
|
||||
});
|
||||
|
||||
startAppLifecycle(makeArgs({ background: true }), deps);
|
||||
|
||||
const runSecondInstance = (argv: string[]) => {
|
||||
assert.ok(secondInstanceHandler);
|
||||
(secondInstanceHandler as (_event: unknown, argv: string[]) => void)({}, argv);
|
||||
};
|
||||
const runReady = () => {
|
||||
assert.ok(readyHandler);
|
||||
return (readyHandler as () => Promise<void>)();
|
||||
};
|
||||
|
||||
runSecondInstance(['SubMiner', '--start']);
|
||||
assert.deepEqual(handled, []);
|
||||
|
||||
const readyRun = runReady();
|
||||
await Promise.resolve();
|
||||
assert.deepEqual(handled, []);
|
||||
|
||||
assert.ok(releaseReady);
|
||||
(releaseReady as () => void)();
|
||||
await readyRun;
|
||||
|
||||
assert.deepEqual(handled, ['ready', 'second-instance:start']);
|
||||
|
||||
runSecondInstance(['SubMiner', '--start']);
|
||||
assert.deepEqual(handled, ['ready', 'second-instance:start', 'second-instance:start']);
|
||||
});
|
||||
|
||||
@@ -114,9 +114,34 @@ export function startAppLifecycle(initialArgs: CliArgs, deps: AppLifecycleServic
|
||||
return;
|
||||
}
|
||||
|
||||
let appReadyRuntimeComplete = false;
|
||||
const pendingSecondInstanceCommands: CliArgs[] = [];
|
||||
const handleSecondInstanceCommand = (args: CliArgs): void => {
|
||||
try {
|
||||
deps.handleCliCommand(args, 'second-instance');
|
||||
} catch (error) {
|
||||
logger.error('Failed to handle second-instance CLI command:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const flushPendingSecondInstanceCommands = (): void => {
|
||||
while (pendingSecondInstanceCommands.length > 0) {
|
||||
const nextArgs = pendingSecondInstanceCommands.shift();
|
||||
if (nextArgs) {
|
||||
handleSecondInstanceCommand(nextArgs);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
deps.onSecondInstance((_event, argv) => {
|
||||
try {
|
||||
deps.handleCliCommand(deps.parseArgs(argv), 'second-instance');
|
||||
const nextArgs = deps.parseArgs(argv);
|
||||
if (!appReadyRuntimeComplete) {
|
||||
pendingSecondInstanceCommands.push(nextArgs);
|
||||
return;
|
||||
}
|
||||
|
||||
handleSecondInstanceCommand(nextArgs);
|
||||
} catch (error) {
|
||||
logger.error('Failed to handle second-instance CLI command:', error);
|
||||
}
|
||||
@@ -134,6 +159,8 @@ export function startAppLifecycle(initialArgs: CliArgs, deps: AppLifecycleServic
|
||||
|
||||
deps.whenReady(async () => {
|
||||
await deps.onReady();
|
||||
appReadyRuntimeComplete = true;
|
||||
flushPendingSecondInstanceCommands();
|
||||
});
|
||||
|
||||
deps.onWindowAllClosed(() => {
|
||||
|
||||
Reference in New Issue
Block a user