mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-03-21 00:11:27 -07:00
feat(controller): add inline remap modal with descriptor-based bindings (#21)
This commit is contained in:
54
src/main/controller-config-update.test.ts
Normal file
54
src/main/controller-config-update.test.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
|
||||
import { applyControllerConfigUpdate } from './controller-config-update.js';
|
||||
|
||||
test('applyControllerConfigUpdate replaces binding descriptors instead of deep-merging them', () => {
|
||||
const next = applyControllerConfigUpdate(
|
||||
{
|
||||
preferredGamepadId: 'pad-1',
|
||||
bindings: {
|
||||
toggleLookup: { kind: 'axis', axisIndex: 4, direction: 'positive' },
|
||||
closeLookup: { kind: 'button', buttonIndex: 1 },
|
||||
},
|
||||
},
|
||||
{
|
||||
bindings: {
|
||||
toggleLookup: { kind: 'button', buttonIndex: 11 },
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
assert.deepEqual(next.bindings?.toggleLookup, { kind: 'button', buttonIndex: 11 });
|
||||
assert.deepEqual(next.bindings?.closeLookup, { kind: 'button', buttonIndex: 1 });
|
||||
});
|
||||
|
||||
test('applyControllerConfigUpdate merges buttonIndices while replacing only updated binding leaves', () => {
|
||||
const next = applyControllerConfigUpdate(
|
||||
{
|
||||
buttonIndices: {
|
||||
select: 6,
|
||||
buttonSouth: 0,
|
||||
},
|
||||
bindings: {
|
||||
toggleLookup: { kind: 'button', buttonIndex: 0 },
|
||||
closeLookup: { kind: 'button', buttonIndex: 1 },
|
||||
},
|
||||
},
|
||||
{
|
||||
buttonIndices: {
|
||||
buttonSouth: 9,
|
||||
},
|
||||
bindings: {
|
||||
closeLookup: { kind: 'none' },
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
assert.deepEqual(next.buttonIndices, {
|
||||
select: 6,
|
||||
buttonSouth: 9,
|
||||
});
|
||||
assert.deepEqual(next.bindings?.toggleLookup, { kind: 'button', buttonIndex: 0 });
|
||||
assert.deepEqual(next.bindings?.closeLookup, { kind: 'none' });
|
||||
});
|
||||
38
src/main/controller-config-update.ts
Normal file
38
src/main/controller-config-update.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import type { ControllerConfigUpdate, RawConfig } from '../types';
|
||||
|
||||
type RawControllerConfig = NonNullable<RawConfig['controller']>;
|
||||
type RawControllerBindings = NonNullable<RawControllerConfig['bindings']>;
|
||||
|
||||
export function applyControllerConfigUpdate(
|
||||
currentController: RawConfig['controller'] | undefined,
|
||||
update: ControllerConfigUpdate,
|
||||
): RawControllerConfig {
|
||||
const nextController: RawControllerConfig = {
|
||||
...(currentController ?? {}),
|
||||
...update,
|
||||
};
|
||||
|
||||
if (currentController?.buttonIndices || update.buttonIndices) {
|
||||
nextController.buttonIndices = {
|
||||
...(currentController?.buttonIndices ?? {}),
|
||||
...(update.buttonIndices ?? {}),
|
||||
};
|
||||
}
|
||||
|
||||
if (currentController?.bindings || update.bindings) {
|
||||
const nextBindings: RawControllerBindings = {
|
||||
...(currentController?.bindings ?? {}),
|
||||
};
|
||||
|
||||
for (const [key, value] of Object.entries(update.bindings ?? {}) as Array<
|
||||
[keyof RawControllerBindings, RawControllerBindings[keyof RawControllerBindings] | undefined]
|
||||
>) {
|
||||
if (value === undefined) continue;
|
||||
(nextBindings as Record<string, unknown>)[key] = JSON.parse(JSON.stringify(value));
|
||||
}
|
||||
|
||||
nextController.bindings = nextBindings;
|
||||
}
|
||||
|
||||
return nextController;
|
||||
}
|
||||
@@ -73,6 +73,7 @@ export interface MainIpcRuntimeServiceDepsParams {
|
||||
getKeybindings: IpcDepsRuntimeOptions['getKeybindings'];
|
||||
getConfiguredShortcuts: IpcDepsRuntimeOptions['getConfiguredShortcuts'];
|
||||
getControllerConfig: IpcDepsRuntimeOptions['getControllerConfig'];
|
||||
saveControllerConfig: IpcDepsRuntimeOptions['saveControllerConfig'];
|
||||
saveControllerPreference: IpcDepsRuntimeOptions['saveControllerPreference'];
|
||||
getSecondarySubMode: IpcDepsRuntimeOptions['getSecondarySubMode'];
|
||||
getMpvClient: IpcDepsRuntimeOptions['getMpvClient'];
|
||||
@@ -216,6 +217,7 @@ export function createMainIpcRuntimeServiceDeps(
|
||||
getKeybindings: params.getKeybindings,
|
||||
getConfiguredShortcuts: params.getConfiguredShortcuts,
|
||||
getControllerConfig: params.getControllerConfig,
|
||||
saveControllerConfig: params.saveControllerConfig,
|
||||
saveControllerPreference: params.saveControllerPreference,
|
||||
focusMainWindow: params.focusMainWindow ?? (() => {}),
|
||||
getSecondarySubMode: params.getSecondarySubMode,
|
||||
|
||||
@@ -52,6 +52,7 @@ test('composeIpcRuntimeHandlers returns callable IPC handlers and registration b
|
||||
getKeybindings: () => [],
|
||||
getConfiguredShortcuts: () => ({}) as never,
|
||||
getControllerConfig: () => ({}) as never,
|
||||
saveControllerConfig: () => {},
|
||||
saveControllerPreference: () => {},
|
||||
getSecondarySubMode: () => 'hover' as never,
|
||||
getMpvClient: () => null,
|
||||
|
||||
Reference in New Issue
Block a user