feat(overlay): discover unclaimed mpv key bindings (#246)

This commit is contained in:
2026-09-15 18:26:45 -07:00
committed by GitHub
parent e6dc9dfec5
commit 7c1eac03dc
21 changed files with 674 additions and 5 deletions
@@ -0,0 +1,41 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import { readMpvInputBindings } from './mpv-input-bindings';
test('discovery reads the connected player and preserves configured keys including disabled bindings', async () => {
const client = {
connected: true,
requestProperty: async (name: string) => {
assert.equal(name, 'input-bindings');
return [{ key: 'r', cmd: 'script-binding replay/run', priority: 1 }];
},
};
assert.deepEqual(
await readMpvInputBindings({
getMpvClient: () => client,
getConfiguredKeybindings: () => [{ key: 'Ctrl+KeyR', command: null }],
platform: 'linux',
}),
{ keys: ['r'], blockedKeys: [{ code: 'KeyR', modifiers: ['ctrl'] }] },
);
});
test('discovery safely handles unsupported properties and disconnects during a request', async () => {
const client = {
connected: true,
requestProperty: async (): Promise<unknown> => {
throw new Error('property unavailable');
},
};
const deps = {
getMpvClient: () => client,
getConfiguredKeybindings: () => [],
platform: 'linux',
} satisfies Parameters<typeof readMpvInputBindings>[0];
assert.deepEqual((await readMpvInputBindings(deps)).keys, []);
client.requestProperty = async () => {
client.connected = false;
return [{ key: 'r', cmd: 'seek 5', priority: 1 }];
};
assert.deepEqual((await readMpvInputBindings(deps)).keys, []);
});
+31
View File
@@ -0,0 +1,31 @@
import type { Keybinding } from '../../types';
import { parseSessionBindingKey } from '../../core/services/session-bindings';
import { parseMpvInputBindingKeys } from '../../shared/mpv-input-bindings';
import type { MpvInputBindingsSnapshot } from '../../types/session-bindings';
export async function readMpvInputBindings(deps: {
getMpvClient: () => {
connected: boolean;
requestProperty: (name: string) => Promise<unknown>;
} | null;
getConfiguredKeybindings: () => Keybinding[];
platform: 'darwin' | 'win32' | 'linux';
}): Promise<MpvInputBindingsSnapshot> {
const blockedKeys = deps.getConfiguredKeybindings().flatMap((binding) => {
const { key } = parseSessionBindingKey(binding.key, deps.platform);
return key ? [key] : [];
});
const client = deps.getMpvClient();
if (!client?.connected) return { keys: [], blockedKeys };
try {
const value = await client.requestProperty('input-bindings');
return {
keys:
client === deps.getMpvClient() && client.connected ? parseMpvInputBindingKeys(value) : [],
blockedKeys,
};
} catch {
// Older mpv versions and disconnected sessions retain SubMiner's controls.
return { keys: [], blockedKeys };
}
}