mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-03-07 03:22:17 -08:00
feat(renderer): add optional yomitan popup auto-pause
This commit is contained in:
@@ -33,6 +33,7 @@ test('loads defaults when config is missing', () => {
|
||||
assert.equal(config.subtitleStyle.backgroundColor, 'rgb(30, 32, 48, 0.88)');
|
||||
assert.equal(config.subtitleStyle.preserveLineBreaks, false);
|
||||
assert.equal(config.subtitleStyle.autoPauseVideoOnHover, true);
|
||||
assert.equal(config.subtitleStyle.autoPauseVideoOnYomitanPopup, false);
|
||||
assert.equal(config.subtitleStyle.hoverTokenColor, '#f4dbd6');
|
||||
assert.equal(config.subtitleStyle.hoverTokenBackgroundColor, 'rgba(54, 58, 79, 0.84)');
|
||||
assert.equal(
|
||||
@@ -160,6 +161,44 @@ test('parses subtitleStyle.autoPauseVideoOnHover and warns on invalid values', (
|
||||
);
|
||||
});
|
||||
|
||||
test('parses subtitleStyle.autoPauseVideoOnYomitanPopup and warns on invalid values', () => {
|
||||
const validDir = makeTempDir();
|
||||
fs.writeFileSync(
|
||||
path.join(validDir, 'config.jsonc'),
|
||||
`{
|
||||
"subtitleStyle": {
|
||||
"autoPauseVideoOnYomitanPopup": true
|
||||
}
|
||||
}`,
|
||||
'utf-8',
|
||||
);
|
||||
|
||||
const validService = new ConfigService(validDir);
|
||||
assert.equal(validService.getConfig().subtitleStyle.autoPauseVideoOnYomitanPopup, true);
|
||||
|
||||
const invalidDir = makeTempDir();
|
||||
fs.writeFileSync(
|
||||
path.join(invalidDir, 'config.jsonc'),
|
||||
`{
|
||||
"subtitleStyle": {
|
||||
"autoPauseVideoOnYomitanPopup": "yes"
|
||||
}
|
||||
}`,
|
||||
'utf-8',
|
||||
);
|
||||
|
||||
const invalidService = new ConfigService(invalidDir);
|
||||
assert.equal(
|
||||
invalidService.getConfig().subtitleStyle.autoPauseVideoOnYomitanPopup,
|
||||
DEFAULT_CONFIG.subtitleStyle.autoPauseVideoOnYomitanPopup,
|
||||
);
|
||||
assert.ok(
|
||||
invalidService
|
||||
.getWarnings()
|
||||
.some((warning) => warning.path === 'subtitleStyle.autoPauseVideoOnYomitanPopup'),
|
||||
);
|
||||
});
|
||||
|
||||
test('parses subtitleStyle.hoverTokenColor and warns on invalid values', () => {
|
||||
const validDir = makeTempDir();
|
||||
fs.writeFileSync(
|
||||
|
||||
@@ -5,6 +5,7 @@ export const SUBTITLE_DEFAULT_CONFIG: Pick<ResolvedConfig, 'subtitleStyle'> = {
|
||||
enableJlpt: false,
|
||||
preserveLineBreaks: false,
|
||||
autoPauseVideoOnHover: true,
|
||||
autoPauseVideoOnYomitanPopup: false,
|
||||
hoverTokenColor: '#f4dbd6',
|
||||
hoverTokenBackgroundColor: 'rgba(54, 58, 79, 0.84)',
|
||||
fontFamily: 'M PLUS 1 Medium, Source Han Sans JP, Noto Sans CJK JP',
|
||||
|
||||
@@ -20,6 +20,7 @@ test('config option registry includes critical paths and has unique entries', ()
|
||||
'logging.level',
|
||||
'startupWarmups.lowPowerMode',
|
||||
'subtitleStyle.enableJlpt',
|
||||
'subtitleStyle.autoPauseVideoOnYomitanPopup',
|
||||
'ankiConnect.enabled',
|
||||
'immersionTracking.enabled',
|
||||
]) {
|
||||
|
||||
@@ -28,6 +28,13 @@ export function buildSubtitleConfigOptionRegistry(
|
||||
description:
|
||||
'Automatically pause mpv playback while hovering subtitle text, then resume on leave.',
|
||||
},
|
||||
{
|
||||
path: 'subtitleStyle.autoPauseVideoOnYomitanPopup',
|
||||
kind: 'boolean',
|
||||
defaultValue: defaultConfig.subtitleStyle.autoPauseVideoOnYomitanPopup,
|
||||
description:
|
||||
'Automatically pause mpv playback while Yomitan popup is open, then resume when popup closes.',
|
||||
},
|
||||
{
|
||||
path: 'subtitleStyle.hoverTokenColor',
|
||||
kind: 'string',
|
||||
|
||||
@@ -100,6 +100,8 @@ export function applySubtitleDomainConfig(context: ResolveContext): void {
|
||||
const fallbackSubtitleStyleEnableJlpt = resolved.subtitleStyle.enableJlpt;
|
||||
const fallbackSubtitleStylePreserveLineBreaks = resolved.subtitleStyle.preserveLineBreaks;
|
||||
const fallbackSubtitleStyleAutoPauseVideoOnHover = resolved.subtitleStyle.autoPauseVideoOnHover;
|
||||
const fallbackSubtitleStyleAutoPauseVideoOnYomitanPopup =
|
||||
resolved.subtitleStyle.autoPauseVideoOnYomitanPopup;
|
||||
const fallbackSubtitleStyleHoverTokenColor = resolved.subtitleStyle.hoverTokenColor;
|
||||
const fallbackSubtitleStyleHoverTokenBackgroundColor =
|
||||
resolved.subtitleStyle.hoverTokenBackgroundColor;
|
||||
@@ -171,6 +173,26 @@ export function applySubtitleDomainConfig(context: ResolveContext): void {
|
||||
);
|
||||
}
|
||||
|
||||
const autoPauseVideoOnYomitanPopup = asBoolean(
|
||||
(src.subtitleStyle as { autoPauseVideoOnYomitanPopup?: unknown }).autoPauseVideoOnYomitanPopup,
|
||||
);
|
||||
if (autoPauseVideoOnYomitanPopup !== undefined) {
|
||||
resolved.subtitleStyle.autoPauseVideoOnYomitanPopup = autoPauseVideoOnYomitanPopup;
|
||||
} else if (
|
||||
(src.subtitleStyle as { autoPauseVideoOnYomitanPopup?: unknown })
|
||||
.autoPauseVideoOnYomitanPopup !== undefined
|
||||
) {
|
||||
resolved.subtitleStyle.autoPauseVideoOnYomitanPopup =
|
||||
fallbackSubtitleStyleAutoPauseVideoOnYomitanPopup;
|
||||
warn(
|
||||
'subtitleStyle.autoPauseVideoOnYomitanPopup',
|
||||
(src.subtitleStyle as { autoPauseVideoOnYomitanPopup?: unknown })
|
||||
.autoPauseVideoOnYomitanPopup,
|
||||
resolved.subtitleStyle.autoPauseVideoOnYomitanPopup,
|
||||
'Expected boolean.',
|
||||
);
|
||||
}
|
||||
|
||||
const hoverTokenColor = asColor(
|
||||
(src.subtitleStyle as { hoverTokenColor?: unknown }).hoverTokenColor,
|
||||
);
|
||||
|
||||
@@ -47,6 +47,25 @@ test('subtitleStyle autoPauseVideoOnHover falls back on invalid value', () => {
|
||||
);
|
||||
});
|
||||
|
||||
test('subtitleStyle autoPauseVideoOnYomitanPopup falls back on invalid value', () => {
|
||||
const { context, warnings } = createResolveContext({
|
||||
subtitleStyle: {
|
||||
autoPauseVideoOnYomitanPopup: 'invalid' as unknown as boolean,
|
||||
},
|
||||
});
|
||||
|
||||
applySubtitleDomainConfig(context);
|
||||
|
||||
assert.equal(context.resolved.subtitleStyle.autoPauseVideoOnYomitanPopup, false);
|
||||
assert.ok(
|
||||
warnings.some(
|
||||
(warning) =>
|
||||
warning.path === 'subtitleStyle.autoPauseVideoOnYomitanPopup' &&
|
||||
warning.message === 'Expected boolean.',
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
test('subtitleStyle frequencyDictionary.matchMode accepts valid values and warns on invalid', () => {
|
||||
const valid = createResolveContext({
|
||||
subtitleStyle: {
|
||||
|
||||
Reference in New Issue
Block a user