mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-03-20 12:11:28 -07:00
Add overlay gamepad support for keyboard-only mode (#17)
This commit is contained in:
@@ -1106,6 +1106,135 @@ test('parses global shortcuts and startup settings', () => {
|
||||
assert.equal(config.youtubeSubgen.fixWithAi, true);
|
||||
});
|
||||
|
||||
test('parses controller settings with logical bindings and tuning knobs', () => {
|
||||
const dir = makeTempDir();
|
||||
fs.writeFileSync(
|
||||
path.join(dir, 'config.jsonc'),
|
||||
`{
|
||||
"controller": {
|
||||
"enabled": true,
|
||||
"preferredGamepadId": "Xbox Wireless Controller (STANDARD GAMEPAD Vendor: 045e Product: 0b13)",
|
||||
"preferredGamepadLabel": "Xbox Wireless Controller",
|
||||
"smoothScroll": false,
|
||||
"scrollPixelsPerSecond": 1440,
|
||||
"horizontalJumpPixels": 180,
|
||||
"stickDeadzone": 0.3,
|
||||
"triggerInputMode": "analog",
|
||||
"triggerDeadzone": 0.4,
|
||||
"repeatDelayMs": 220,
|
||||
"repeatIntervalMs": 70,
|
||||
"buttonIndices": {
|
||||
"select": 6,
|
||||
"leftStickPress": 9,
|
||||
"rightStickPress": 10
|
||||
},
|
||||
"bindings": {
|
||||
"toggleLookup": "buttonWest",
|
||||
"closeLookup": "buttonEast",
|
||||
"toggleKeyboardOnlyMode": "buttonNorth",
|
||||
"mineCard": "buttonSouth",
|
||||
"quitMpv": "select",
|
||||
"previousAudio": "leftShoulder",
|
||||
"nextAudio": "rightShoulder",
|
||||
"playCurrentAudio": "none",
|
||||
"toggleMpvPause": "leftStickPress",
|
||||
"leftStickHorizontal": "rightStickX",
|
||||
"leftStickVertical": "rightStickY",
|
||||
"rightStickHorizontal": "leftStickX",
|
||||
"rightStickVertical": "leftStickY"
|
||||
}
|
||||
}
|
||||
}`,
|
||||
'utf-8',
|
||||
);
|
||||
|
||||
const service = new ConfigService(dir);
|
||||
const config = service.getConfig();
|
||||
|
||||
assert.equal(config.controller.enabled, true);
|
||||
assert.equal(
|
||||
config.controller.preferredGamepadId,
|
||||
'Xbox Wireless Controller (STANDARD GAMEPAD Vendor: 045e Product: 0b13)',
|
||||
);
|
||||
assert.equal(config.controller.preferredGamepadLabel, 'Xbox Wireless Controller');
|
||||
assert.equal(config.controller.smoothScroll, false);
|
||||
assert.equal(config.controller.scrollPixelsPerSecond, 1440);
|
||||
assert.equal(config.controller.horizontalJumpPixels, 180);
|
||||
assert.equal(config.controller.stickDeadzone, 0.3);
|
||||
assert.equal(config.controller.triggerInputMode, 'analog');
|
||||
assert.equal(config.controller.triggerDeadzone, 0.4);
|
||||
assert.equal(config.controller.repeatDelayMs, 220);
|
||||
assert.equal(config.controller.repeatIntervalMs, 70);
|
||||
assert.equal(config.controller.buttonIndices.select, 6);
|
||||
assert.equal(config.controller.buttonIndices.leftStickPress, 9);
|
||||
assert.equal(config.controller.bindings.toggleLookup, 'buttonWest');
|
||||
assert.equal(config.controller.bindings.quitMpv, 'select');
|
||||
assert.equal(config.controller.bindings.playCurrentAudio, 'none');
|
||||
assert.equal(config.controller.bindings.toggleMpvPause, 'leftStickPress');
|
||||
assert.equal(config.controller.bindings.leftStickHorizontal, 'rightStickX');
|
||||
assert.equal(config.controller.bindings.rightStickVertical, 'leftStickY');
|
||||
});
|
||||
|
||||
test('controller positive-number tuning rejects sub-unit values that floor to zero', () => {
|
||||
const dir = makeTempDir();
|
||||
fs.writeFileSync(
|
||||
path.join(dir, 'config.jsonc'),
|
||||
`{
|
||||
"controller": {
|
||||
"scrollPixelsPerSecond": 0.5,
|
||||
"horizontalJumpPixels": 0.2,
|
||||
"repeatDelayMs": 0.9,
|
||||
"repeatIntervalMs": 0.1
|
||||
}
|
||||
}`,
|
||||
'utf-8',
|
||||
);
|
||||
|
||||
const service = new ConfigService(dir);
|
||||
const config = service.getConfig();
|
||||
const warnings = service.getWarnings();
|
||||
|
||||
assert.equal(config.controller.scrollPixelsPerSecond, DEFAULT_CONFIG.controller.scrollPixelsPerSecond);
|
||||
assert.equal(config.controller.horizontalJumpPixels, DEFAULT_CONFIG.controller.horizontalJumpPixels);
|
||||
assert.equal(config.controller.repeatDelayMs, DEFAULT_CONFIG.controller.repeatDelayMs);
|
||||
assert.equal(config.controller.repeatIntervalMs, DEFAULT_CONFIG.controller.repeatIntervalMs);
|
||||
assert.equal(warnings.some((warning) => warning.path === 'controller.scrollPixelsPerSecond'), true);
|
||||
assert.equal(warnings.some((warning) => warning.path === 'controller.horizontalJumpPixels'), true);
|
||||
assert.equal(warnings.some((warning) => warning.path === 'controller.repeatDelayMs'), true);
|
||||
assert.equal(warnings.some((warning) => warning.path === 'controller.repeatIntervalMs'), true);
|
||||
});
|
||||
|
||||
test('controller button index config rejects fractional values', () => {
|
||||
const dir = makeTempDir();
|
||||
fs.writeFileSync(
|
||||
path.join(dir, 'config.jsonc'),
|
||||
`{
|
||||
"controller": {
|
||||
"buttonIndices": {
|
||||
"select": 6.5,
|
||||
"leftStickPress": 9.1
|
||||
}
|
||||
}
|
||||
}`,
|
||||
'utf-8',
|
||||
);
|
||||
|
||||
const service = new ConfigService(dir);
|
||||
const config = service.getConfig();
|
||||
const warnings = service.getWarnings();
|
||||
|
||||
assert.equal(config.controller.buttonIndices.select, DEFAULT_CONFIG.controller.buttonIndices.select);
|
||||
assert.equal(
|
||||
config.controller.buttonIndices.leftStickPress,
|
||||
DEFAULT_CONFIG.controller.buttonIndices.leftStickPress,
|
||||
);
|
||||
assert.equal(warnings.some((warning) => warning.path === 'controller.buttonIndices.select'), true);
|
||||
assert.equal(
|
||||
warnings.some((warning) => warning.path === 'controller.buttonIndices.leftStickPress'),
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
test('runtime options registry is centralized', () => {
|
||||
const ids = RUNTIME_OPTION_REGISTRY.map((entry) => entry.id);
|
||||
assert.deepEqual(ids, [
|
||||
@@ -1638,6 +1767,7 @@ test('template generator includes known keys', () => {
|
||||
const output = generateConfigTemplate(DEFAULT_CONFIG);
|
||||
assert.match(output, /"ai":/);
|
||||
assert.match(output, /"ankiConnect":/);
|
||||
assert.match(output, /"controller":/);
|
||||
assert.match(output, /"logging":/);
|
||||
assert.match(output, /"websocket":/);
|
||||
assert.match(output, /"discordPresence":/);
|
||||
@@ -1662,6 +1792,14 @@ test('template generator includes known keys', () => {
|
||||
output,
|
||||
/"enabled": true,? \/\/ Annotated subtitle websocket server enabled state\. Values: true \| false/,
|
||||
);
|
||||
assert.match(
|
||||
output,
|
||||
/"scrollPixelsPerSecond": 900,? \/\/ Base popup scroll speed for controller stick input\./,
|
||||
);
|
||||
assert.match(
|
||||
output,
|
||||
/"triggerInputMode": "auto",? \/\/ How controller triggers are interpreted: auto, pressed-only, or thresholded analog\. Values: auto \| digital \| analog/,
|
||||
);
|
||||
assert.match(output, /"port": 6678,? \/\/ Annotated subtitle websocket server port\./);
|
||||
assert.match(
|
||||
output,
|
||||
|
||||
Reference in New Issue
Block a user