Fix secondary subtitle style parity and MPV visibility restore lifecycle

This commit is contained in:
2026-02-13 00:03:55 -08:00
parent f345547963
commit 978a859cc2
6 changed files with 129 additions and 54 deletions

View File

@@ -1,6 +1,10 @@
import test from "node:test";
import assert from "node:assert/strict";
import { MpvIpcClient, MpvIpcClientDeps } from "./mpv-service";
import {
MpvIpcClient,
MpvIpcClientDeps,
MPV_REQUEST_ID_SECONDARY_SUB_VISIBILITY,
} from "./mpv-service";
function makeDeps(
overrides: Partial<MpvIpcClientDeps> = {},
@@ -41,6 +45,7 @@ function makeDeps(
osdHeight: 720,
osdDimensions: null,
}),
getPreviousSecondarySubVisibility: () => null,
setPreviousSecondarySubVisibility: () => {},
showMpvOsd: () => {},
...overrides,
@@ -174,3 +179,62 @@ test("MpvIpcClient scheduleReconnect schedules timer and invokes connect", () =>
assert.equal(timers.length, 1);
assert.equal(connectCalled, true);
});
test("MpvIpcClient captures and disables secondary subtitle visibility on request", async () => {
const commands: unknown[] = [];
let previousSecondarySubVisibility: boolean | null = null;
const client = new MpvIpcClient(
"/tmp/mpv.sock",
makeDeps({
getPreviousSecondarySubVisibility: () => previousSecondarySubVisibility,
setPreviousSecondarySubVisibility: (value) => {
previousSecondarySubVisibility = value;
},
}),
);
(client as any).send = (payload: unknown) => {
commands.push(payload);
return true;
};
await (client as any).handleMessage({
request_id: MPV_REQUEST_ID_SECONDARY_SUB_VISIBILITY,
data: "yes",
});
assert.equal(previousSecondarySubVisibility, true);
assert.deepEqual(commands, [
{
command: ["set_property", "secondary-sub-visibility", "no"],
},
]);
});
test("MpvIpcClient restorePreviousSecondarySubVisibility restores and clears tracked value", () => {
const commands: unknown[] = [];
let previousSecondarySubVisibility: boolean | null = false;
const client = new MpvIpcClient(
"/tmp/mpv.sock",
makeDeps({
getPreviousSecondarySubVisibility: () => previousSecondarySubVisibility,
setPreviousSecondarySubVisibility: (value) => {
previousSecondarySubVisibility = value;
},
}),
);
(client as any).send = (payload: unknown) => {
commands.push(payload);
return true;
};
client.restorePreviousSecondarySubVisibility();
assert.deepEqual(commands, [
{
command: ["set_property", "secondary-sub-visibility", "no"],
},
]);
assert.equal(previousSecondarySubVisibility, null);
});

View File

@@ -65,6 +65,7 @@ export interface MpvIpcClientDeps {
patch: Partial<MpvSubtitleRenderMetrics>,
) => void;
getMpvSubtitleRenderMetrics: () => MpvSubtitleRenderMetrics;
getPreviousSecondarySubVisibility: () => boolean | null;
setPreviousSecondarySubVisibility: (value: boolean | null) => void;
showMpvOsd: (text: string) => void;
}
@@ -369,6 +370,8 @@ export class MpvIpcClient implements MpvClient {
});
}
}
} else if (msg.event === "shutdown") {
this.restorePreviousSecondarySubVisibility();
} else if (msg.request_id) {
const pending = this.pendingRequests.get(msg.request_id);
if (pending) {
@@ -440,10 +443,6 @@ export class MpvIpcClient implements MpvClient {
this.currentSecondarySubText,
);
} else if (msg.request_id === MPV_REQUEST_ID_SECONDARY_SUB_VISIBILITY) {
if (!this.deps.shouldBindVisibleOverlayToMpvSubVisibility()) {
this.deps.setPreviousSecondarySubVisibility(null);
return;
}
this.deps.setPreviousSecondarySubVisibility(
msg.data === true || msg.data === "yes",
);
@@ -673,6 +672,10 @@ export class MpvIpcClient implements MpvClient {
command: ["get_property", "secondary-sub-text"],
request_id: MPV_REQUEST_ID_SECONDARY_SUBTEXT,
});
this.send({
command: ["get_property", "secondary-sub-visibility"],
request_id: MPV_REQUEST_ID_SECONDARY_SUB_VISIBILITY,
});
this.send({
command: ["get_property", "aid"],
request_id: MPV_REQUEST_ID_AID,
@@ -758,4 +761,13 @@ export class MpvIpcClient implements MpvClient {
this.pendingPauseAtSubEnd = true;
this.send({ command: ["sub-seek", 1] });
}
restorePreviousSecondarySubVisibility(): void {
const previous = this.deps.getPreviousSecondarySubVisibility();
if (previous === null) return;
this.send({
command: ["set_property", "secondary-sub-visibility", previous ? "yes" : "no"],
});
this.deps.setPreviousSecondarySubVisibility(null);
}
}

View File

@@ -2,23 +2,12 @@ import { BrowserWindow, screen } from "electron";
import { BaseWindowTracker } from "../../window-trackers";
import { WindowGeometry } from "../../types";
interface MpvCommandSender {
command: Array<string | number>;
request_id?: number;
}
export function updateVisibleOverlayVisibilityService(args: {
visibleOverlayVisible: boolean;
mainWindow: BrowserWindow | null;
windowTracker: BaseWindowTracker | null;
trackerNotReadyWarningShown: boolean;
setTrackerNotReadyWarningShown: (shown: boolean) => void;
shouldBindVisibleOverlayToMpvSubVisibility: boolean;
previousSecondarySubVisibility: boolean | null;
setPreviousSecondarySubVisibility: (value: boolean | null) => void;
mpvConnected: boolean;
mpvSend: (payload: MpvCommandSender) => void;
secondarySubVisibilityRequestId: number;
updateVisibleOverlayBounds: (geometry: WindowGeometry) => void;
ensureOverlayWindowLevel: (window: BrowserWindow) => void;
enforceOverlayLayerOrder: () => void;
@@ -30,34 +19,10 @@ export function updateVisibleOverlayVisibilityService(args: {
if (!args.visibleOverlayVisible) {
args.mainWindow.hide();
if (
args.shouldBindVisibleOverlayToMpvSubVisibility &&
args.previousSecondarySubVisibility !== null &&
args.mpvConnected
) {
args.mpvSend({
command: [
"set_property",
"secondary-sub-visibility",
args.previousSecondarySubVisibility ? "yes" : "no",
],
});
args.setPreviousSecondarySubVisibility(null);
} else if (!args.shouldBindVisibleOverlayToMpvSubVisibility) {
args.setPreviousSecondarySubVisibility(null);
}
args.syncOverlayShortcuts();
return;
}
if (args.shouldBindVisibleOverlayToMpvSubVisibility && args.mpvConnected) {
args.mpvSend({
command: ["get_property", "secondary-sub-visibility"],
request_id: args.secondarySubVisibilityRequestId,
});
}
if (args.windowTracker && args.windowTracker.isTracking()) {
args.setTrackerNotReadyWarningShown(false);
const geometry = args.windowTracker.getGeometry();