mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-11 02:46:16 -08:00
fix(playback): keep the saved Embedded MPV player when the mpv check is inconclusive
On Linux native-view the support check runs `mpv --version` by bare name and waits for the login shell PATH first. Since #1784 that lookup is asynchronous with a 10 s budget; when it ran out, the check ran on the inherited PATH and answered a plain `supported: false`. The settings store took that as a verdict and persisted the default player over a saved Embedded MPV selection. The main process probed again once the shell answered, but nothing restored the setting. `EmbeddedMpvSupport` now carries `inconclusive`. The native service sets it on a missing mpv while its probe has only seen the inherited PATH; the IPC handler declares that state before probing and registers the re-probe before the check, so a throwing check cannot leave it stuck. Every other answer stays final. Consumers no longer settle on an inconclusive answer: the settings store keeps the saved player, and the command palette and the settings search probe again on their next use instead of caching it for the session. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
8e1cb05913
commit
417eaf5005
14 files changed
+545
-16
No files matched your search
+49
-2
@@ -53,7 +53,7 @@ describe('WorkspacePlayerCommandsContributor', () => {
|
||||
let electronStub:
|
||||
| {
|
||||
getEmbeddedMpvSupport: jest.Mock<
|
||||
Promise<{ supported: boolean }>,
|
||||
Promise<{ supported: boolean; inconclusive?: boolean }>,
|
||||
[]
|
||||
>;
|
||||
}
|
||||
@@ -63,7 +63,10 @@ describe('WorkspacePlayerCommandsContributor', () => {
|
||||
function bootstrap(options: {
|
||||
supportsManagedExternalPlayers: boolean;
|
||||
supportsEmbeddedMpv?: boolean;
|
||||
embeddedMpvSupportResult?: { supported: boolean } | null;
|
||||
embeddedMpvSupportResult?: {
|
||||
supported: boolean;
|
||||
inconclusive?: boolean;
|
||||
} | null;
|
||||
}) {
|
||||
viewCommands = {
|
||||
registerCommand: jest.fn().mockReturnValue(() => undefined),
|
||||
@@ -200,6 +203,50 @@ describe('WorkspacePlayerCommandsContributor', () => {
|
||||
expect(resolveBoolean(embedded?.visible)).toBe(false);
|
||||
});
|
||||
|
||||
it('keeps a final unsupported answer, but asks again after an inconclusive one', async () => {
|
||||
const contributor = bootstrap({
|
||||
supportsManagedExternalPlayers: true,
|
||||
supportsEmbeddedMpv: true,
|
||||
// A slow login shell: mpv was looked up before its PATH arrived.
|
||||
embeddedMpvSupportResult: { supported: false, inconclusive: true },
|
||||
});
|
||||
const embedded = getRegistered(viewCommands).find(
|
||||
(c) => c.id === 'switch-player-embedded-mpv'
|
||||
);
|
||||
|
||||
await contributor.ensureEmbeddedMpvSupportLoaded();
|
||||
expect(resolveBoolean(embedded?.visible)).toBe(false);
|
||||
|
||||
// The shell answered without mpv: that answer is final.
|
||||
electronStub?.getEmbeddedMpvSupport.mockResolvedValue({
|
||||
supported: false,
|
||||
});
|
||||
await contributor.ensureEmbeddedMpvSupportLoaded();
|
||||
expect(resolveBoolean(embedded?.visible)).toBe(false);
|
||||
expect(contributor.ensureEmbeddedMpvSupportLoaded()).toBeUndefined();
|
||||
expect(electronStub?.getEmbeddedMpvSupport).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it('shows embedded MPV once an inconclusive answer turns into supported', async () => {
|
||||
const contributor = bootstrap({
|
||||
supportsManagedExternalPlayers: true,
|
||||
supportsEmbeddedMpv: true,
|
||||
embeddedMpvSupportResult: { supported: false, inconclusive: true },
|
||||
});
|
||||
const embedded = getRegistered(viewCommands).find(
|
||||
(c) => c.id === 'switch-player-embedded-mpv'
|
||||
);
|
||||
await contributor.ensureEmbeddedMpvSupportLoaded();
|
||||
|
||||
electronStub?.getEmbeddedMpvSupport.mockResolvedValue({
|
||||
supported: true,
|
||||
});
|
||||
await contributor.ensureEmbeddedMpvSupportLoaded();
|
||||
|
||||
expect(resolveBoolean(embedded?.visible)).toBe(true);
|
||||
expect(contributor.ensureEmbeddedMpvSupportLoaded()).toBeUndefined();
|
||||
});
|
||||
|
||||
it('switches to embedded MPV on run', () => {
|
||||
bootstrap({
|
||||
supportsManagedExternalPlayers: true,
|
||||
|
||||
+5
-1
@@ -120,16 +120,20 @@ export class WorkspacePlayerCommandsContributor {
|
||||
}
|
||||
|
||||
private async loadEmbeddedMpvSupport(): Promise<void> {
|
||||
// An inconclusive answer hides the command for now, but is not kept:
|
||||
// the next palette open asks again.
|
||||
let final = true;
|
||||
try {
|
||||
const support = await window.electron?.getEmbeddedMpvSupport?.();
|
||||
this.embeddedMpvSupported.set(!!support?.supported);
|
||||
final = !support?.inconclusive;
|
||||
} catch (error) {
|
||||
console.warn(
|
||||
'Failed to verify embedded MPV support for the command palette.',
|
||||
error
|
||||
);
|
||||
} finally {
|
||||
this.embeddedMpvSupportChecked = true;
|
||||
this.embeddedMpvSupportChecked = final;
|
||||
this.embeddedMpvSupportLoad = null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user