mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-03-22 00:11:27 -07:00
feat(controller): add inline remap modal with descriptor-based bindings (#21)
This commit is contained in:
@@ -19,6 +19,7 @@ export const IPC_CHANNELS = {
|
||||
toggleDevTools: 'toggle-dev-tools',
|
||||
toggleOverlay: 'toggle-overlay',
|
||||
saveSubtitlePosition: 'save-subtitle-position',
|
||||
saveControllerConfig: 'save-controller-config',
|
||||
saveControllerPreference: 'save-controller-preference',
|
||||
setMecabEnabled: 'set-mecab-enabled',
|
||||
mpvCommand: 'mpv-command',
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type {
|
||||
ControllerConfigUpdate,
|
||||
ControllerPreferenceUpdate,
|
||||
JimakuDownloadQuery,
|
||||
JimakuFilesQuery,
|
||||
@@ -59,6 +60,99 @@ export function parseControllerPreferenceUpdate(value: unknown): ControllerPrefe
|
||||
};
|
||||
}
|
||||
|
||||
function parseDiscreteBinding(value: unknown) {
|
||||
if (!isObject(value) || typeof value.kind !== 'string') return null;
|
||||
if (value.kind === 'none') {
|
||||
return { kind: 'none' };
|
||||
}
|
||||
if (value.kind === 'button') {
|
||||
if (!isInteger(value.buttonIndex) || value.buttonIndex < 0) return null;
|
||||
return { kind: 'button', buttonIndex: value.buttonIndex };
|
||||
}
|
||||
if (value.kind === 'axis') {
|
||||
if (!isInteger(value.axisIndex) || value.axisIndex < 0) return null;
|
||||
if (value.direction !== 'negative' && value.direction !== 'positive') return null;
|
||||
return { kind: 'axis', axisIndex: value.axisIndex, direction: value.direction };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function parseAxisBinding(value: unknown) {
|
||||
if (isObject(value) && value.kind === 'none') {
|
||||
return { kind: 'none' };
|
||||
}
|
||||
if (!isObject(value) || value.kind !== 'axis') return null;
|
||||
if (!isInteger(value.axisIndex) || value.axisIndex < 0) return null;
|
||||
if (
|
||||
value.dpadFallback !== undefined &&
|
||||
value.dpadFallback !== 'none' &&
|
||||
value.dpadFallback !== 'horizontal' &&
|
||||
value.dpadFallback !== 'vertical'
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
kind: 'axis',
|
||||
axisIndex: value.axisIndex,
|
||||
...(value.dpadFallback === undefined ? {} : { dpadFallback: value.dpadFallback }),
|
||||
};
|
||||
}
|
||||
|
||||
export function parseControllerConfigUpdate(value: unknown): ControllerConfigUpdate | null {
|
||||
if (!isObject(value)) return null;
|
||||
const update: ControllerConfigUpdate = {};
|
||||
|
||||
if (value.enabled !== undefined) {
|
||||
if (typeof value.enabled !== 'boolean') return null;
|
||||
update.enabled = value.enabled;
|
||||
}
|
||||
if (value.preferredGamepadId !== undefined) {
|
||||
if (typeof value.preferredGamepadId !== 'string') return null;
|
||||
update.preferredGamepadId = value.preferredGamepadId;
|
||||
}
|
||||
if (value.preferredGamepadLabel !== undefined) {
|
||||
if (typeof value.preferredGamepadLabel !== 'string') return null;
|
||||
update.preferredGamepadLabel = value.preferredGamepadLabel;
|
||||
}
|
||||
|
||||
if (value.bindings !== undefined) {
|
||||
if (!isObject(value.bindings)) return null;
|
||||
const bindings: NonNullable<ControllerConfigUpdate['bindings']> = {};
|
||||
const discreteKeys = [
|
||||
'toggleLookup',
|
||||
'closeLookup',
|
||||
'toggleKeyboardOnlyMode',
|
||||
'mineCard',
|
||||
'quitMpv',
|
||||
'previousAudio',
|
||||
'nextAudio',
|
||||
'playCurrentAudio',
|
||||
'toggleMpvPause',
|
||||
] as const;
|
||||
for (const key of discreteKeys) {
|
||||
if (value.bindings[key] === undefined) continue;
|
||||
const parsed = parseDiscreteBinding(value.bindings[key]);
|
||||
if (!parsed) return null;
|
||||
bindings[key] = parsed as NonNullable<ControllerConfigUpdate['bindings']>[typeof key];
|
||||
}
|
||||
const axisKeys = [
|
||||
'leftStickHorizontal',
|
||||
'leftStickVertical',
|
||||
'rightStickHorizontal',
|
||||
'rightStickVertical',
|
||||
] as const;
|
||||
for (const key of axisKeys) {
|
||||
if (value.bindings[key] === undefined) continue;
|
||||
const parsed = parseAxisBinding(value.bindings[key]);
|
||||
if (!parsed) return null;
|
||||
bindings[key] = parsed as NonNullable<ControllerConfigUpdate['bindings']>[typeof key];
|
||||
}
|
||||
update.bindings = bindings;
|
||||
}
|
||||
|
||||
return update;
|
||||
}
|
||||
|
||||
export function parseSubsyncManualRunRequest(value: unknown): SubsyncManualRunRequest | null {
|
||||
if (!isObject(value)) return null;
|
||||
const { engine, sourceTrackId } = value;
|
||||
|
||||
Reference in New Issue
Block a user