mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-06-13 03:13:32 -07:00
fix: Kiku field grouping, frequency particles, sidebar media, Yomitan popup visibility (#91)
This commit is contained in:
@@ -104,6 +104,7 @@ test('loads defaults when config is missing', () => {
|
||||
assert.equal(config.subtitleStyle.preserveLineBreaks, false);
|
||||
assert.equal(config.subtitleStyle.autoPauseVideoOnHover, true);
|
||||
assert.equal(config.subtitleStyle.autoPauseVideoOnYomitanPopup, true);
|
||||
assert.equal(config.subtitleStyle.primaryVisibleOnYomitanPopup, true);
|
||||
assert.equal(config.subtitleSidebar.enabled, true);
|
||||
assert.equal(config.subtitleSidebar.pauseVideoOnHover, true);
|
||||
assert.equal(config.subtitleStyle.hoverTokenColor, '#f4dbd6');
|
||||
@@ -545,6 +546,44 @@ test('parses subtitleStyle.autoPauseVideoOnYomitanPopup and warns on invalid val
|
||||
);
|
||||
});
|
||||
|
||||
test('parses subtitleStyle.primaryVisibleOnYomitanPopup and warns on invalid values', () => {
|
||||
const validDir = makeTempDir();
|
||||
fs.writeFileSync(
|
||||
path.join(validDir, 'config.jsonc'),
|
||||
`{
|
||||
"subtitleStyle": {
|
||||
"primaryVisibleOnYomitanPopup": false
|
||||
}
|
||||
}`,
|
||||
'utf-8',
|
||||
);
|
||||
|
||||
const validService = new ConfigService(validDir);
|
||||
assert.equal(validService.getConfig().subtitleStyle.primaryVisibleOnYomitanPopup, false);
|
||||
|
||||
const invalidDir = makeTempDir();
|
||||
fs.writeFileSync(
|
||||
path.join(invalidDir, 'config.jsonc'),
|
||||
`{
|
||||
"subtitleStyle": {
|
||||
"primaryVisibleOnYomitanPopup": "yes"
|
||||
}
|
||||
}`,
|
||||
'utf-8',
|
||||
);
|
||||
|
||||
const invalidService = new ConfigService(invalidDir);
|
||||
assert.equal(
|
||||
invalidService.getConfig().subtitleStyle.primaryVisibleOnYomitanPopup,
|
||||
DEFAULT_CONFIG.subtitleStyle.primaryVisibleOnYomitanPopup,
|
||||
);
|
||||
assert.ok(
|
||||
invalidService
|
||||
.getWarnings()
|
||||
.some((warning) => warning.path === 'subtitleStyle.primaryVisibleOnYomitanPopup'),
|
||||
);
|
||||
});
|
||||
|
||||
test('parses subtitleStyle.hoverTokenColor and warns on invalid values', () => {
|
||||
const validDir = makeTempDir();
|
||||
fs.writeFileSync(
|
||||
|
||||
@@ -8,6 +8,7 @@ export const SUBTITLE_DEFAULT_CONFIG: Pick<ResolvedConfig, 'subtitleStyle' | 'su
|
||||
preserveLineBreaks: false,
|
||||
autoPauseVideoOnHover: true,
|
||||
autoPauseVideoOnYomitanPopup: true,
|
||||
primaryVisibleOnYomitanPopup: true,
|
||||
hoverTokenColor: '#f4dbd6',
|
||||
hoverTokenBackgroundColor: 'transparent',
|
||||
nameMatchEnabled: false,
|
||||
|
||||
@@ -57,6 +57,13 @@ export function buildSubtitleConfigOptionRegistry(
|
||||
description:
|
||||
'Automatically pause mpv playback while Yomitan popup is open, then resume when popup closes.',
|
||||
},
|
||||
{
|
||||
path: 'subtitleStyle.primaryVisibleOnYomitanPopup',
|
||||
kind: 'boolean',
|
||||
defaultValue: defaultConfig.subtitleStyle.primaryVisibleOnYomitanPopup,
|
||||
description:
|
||||
'Keep the primary subtitle bar visible while a Yomitan popup is open when primary subtitles are in hover mode.',
|
||||
},
|
||||
{
|
||||
path: 'subtitleStyle.hoverTokenColor',
|
||||
kind: 'string',
|
||||
|
||||
@@ -186,6 +186,8 @@ export function applySubtitleDomainConfig(context: ResolveContext): void {
|
||||
const fallbackSubtitleStyleAutoPauseVideoOnHover = resolved.subtitleStyle.autoPauseVideoOnHover;
|
||||
const fallbackSubtitleStyleAutoPauseVideoOnYomitanPopup =
|
||||
resolved.subtitleStyle.autoPauseVideoOnYomitanPopup;
|
||||
const fallbackSubtitleStylePrimaryVisibleOnYomitanPopup =
|
||||
resolved.subtitleStyle.primaryVisibleOnYomitanPopup;
|
||||
const fallbackSubtitleStyleHoverTokenColor = resolved.subtitleStyle.hoverTokenColor;
|
||||
const fallbackSubtitleStyleHoverTokenBackgroundColor =
|
||||
resolved.subtitleStyle.hoverTokenBackgroundColor;
|
||||
@@ -333,6 +335,27 @@ export function applySubtitleDomainConfig(context: ResolveContext): void {
|
||||
);
|
||||
}
|
||||
|
||||
const primaryVisibleOnYomitanPopup = asBoolean(
|
||||
(src.subtitleStyle as { primaryVisibleOnYomitanPopup?: unknown })
|
||||
.primaryVisibleOnYomitanPopup,
|
||||
);
|
||||
if (primaryVisibleOnYomitanPopup !== undefined) {
|
||||
resolved.subtitleStyle.primaryVisibleOnYomitanPopup = primaryVisibleOnYomitanPopup;
|
||||
} else if (
|
||||
(src.subtitleStyle as { primaryVisibleOnYomitanPopup?: unknown })
|
||||
.primaryVisibleOnYomitanPopup !== undefined
|
||||
) {
|
||||
resolved.subtitleStyle.primaryVisibleOnYomitanPopup =
|
||||
fallbackSubtitleStylePrimaryVisibleOnYomitanPopup;
|
||||
warn(
|
||||
'subtitleStyle.primaryVisibleOnYomitanPopup',
|
||||
(src.subtitleStyle as { primaryVisibleOnYomitanPopup?: unknown })
|
||||
.primaryVisibleOnYomitanPopup,
|
||||
resolved.subtitleStyle.primaryVisibleOnYomitanPopup,
|
||||
'Expected boolean.',
|
||||
);
|
||||
}
|
||||
|
||||
const hoverTokenColor = asColor(
|
||||
(src.subtitleStyle as { hoverTokenColor?: unknown }).hoverTokenColor,
|
||||
);
|
||||
|
||||
@@ -128,6 +128,33 @@ test('subtitleStyle autoPauseVideoOnYomitanPopup falls back on invalid value', (
|
||||
);
|
||||
});
|
||||
|
||||
test('subtitleStyle primaryVisibleOnYomitanPopup falls back on invalid value', () => {
|
||||
const valid = createResolveContext({
|
||||
subtitleStyle: {
|
||||
primaryVisibleOnYomitanPopup: false,
|
||||
},
|
||||
});
|
||||
applySubtitleDomainConfig(valid.context);
|
||||
assert.equal(valid.context.resolved.subtitleStyle.primaryVisibleOnYomitanPopup, false);
|
||||
|
||||
const { context, warnings } = createResolveContext({
|
||||
subtitleStyle: {
|
||||
primaryVisibleOnYomitanPopup: 'invalid' as unknown as boolean,
|
||||
},
|
||||
});
|
||||
|
||||
applySubtitleDomainConfig(context);
|
||||
|
||||
assert.equal(context.resolved.subtitleStyle.primaryVisibleOnYomitanPopup, true);
|
||||
assert.ok(
|
||||
warnings.some(
|
||||
(warning) =>
|
||||
warning.path === 'subtitleStyle.primaryVisibleOnYomitanPopup' &&
|
||||
warning.message === 'Expected boolean.',
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
test('subtitleStyle primaryDefaultMode accepts valid values and warns on invalid', () => {
|
||||
const valid = createResolveContext({
|
||||
subtitleStyle: {
|
||||
|
||||
@@ -15,6 +15,8 @@ test('settings registry splits viewing into appearance and behavior categories',
|
||||
assert.equal(field('subtitleStyle.fontSize').category, 'appearance');
|
||||
assert.equal(field('subtitleStyle.primaryDefaultMode').category, 'behavior');
|
||||
assert.equal(field('subtitleStyle.primaryDefaultMode').section, 'Subtitle Behavior');
|
||||
assert.equal(field('subtitleStyle.primaryVisibleOnYomitanPopup').category, 'behavior');
|
||||
assert.equal(field('subtitleStyle.primaryVisibleOnYomitanPopup').section, 'Subtitle Behavior');
|
||||
assert.equal(field('secondarySub.defaultMode').category, 'behavior');
|
||||
assert.equal(field('subtitlePosition.yPercent').label, 'Subtitle Position');
|
||||
assert.equal(field('subtitleStyle.frequencyDictionary.mode').label, 'Frequency Mode');
|
||||
@@ -28,7 +30,14 @@ test('settings registry splits viewing into appearance and behavior categories',
|
||||
assert.equal(field('mpv.profile').section, 'mpv Playback');
|
||||
assert.ok(
|
||||
fields.findIndex((candidate) => candidate.configPath === 'subtitleStyle.primaryDefaultMode') <
|
||||
fields.findIndex((candidate) => candidate.configPath === 'secondarySub.defaultMode'),
|
||||
fields.findIndex(
|
||||
(candidate) => candidate.configPath === 'subtitleStyle.primaryVisibleOnYomitanPopup',
|
||||
),
|
||||
);
|
||||
assert.ok(
|
||||
fields.findIndex(
|
||||
(candidate) => candidate.configPath === 'subtitleStyle.primaryVisibleOnYomitanPopup',
|
||||
) < fields.findIndex((candidate) => candidate.configPath === 'secondarySub.defaultMode'),
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -168,6 +168,7 @@ const PATH_ORDER = new Map<string, number>(
|
||||
'subtitleStyle.hoverTokenBackgroundColor',
|
||||
'subtitleStyle.css',
|
||||
'subtitleStyle.primaryDefaultMode',
|
||||
'subtitleStyle.primaryVisibleOnYomitanPopup',
|
||||
'subtitleStyle.secondary.fontColor',
|
||||
'subtitleStyle.secondary.backgroundColor',
|
||||
'subtitleStyle.secondary.css',
|
||||
@@ -218,6 +219,7 @@ const LABEL_OVERRIDES: Record<string, string> = {
|
||||
'subtitleSidebar.pauseVideoOnHover': 'Pause Video On Hover - Sidebar',
|
||||
'subtitleStyle.autoPauseVideoOnHover': 'Pause Video On Hover - Subtitles',
|
||||
'subtitleStyle.autoPauseVideoOnYomitanPopup': 'Pause Video On Yomitan Popup',
|
||||
'subtitleStyle.primaryVisibleOnYomitanPopup': 'Keep Primary Visible On Yomitan Popup',
|
||||
'subtitleStyle.primaryDefaultMode': 'Primary Subtitle Visibility Mode',
|
||||
'subtitleStyle.frequencyDictionary.mode': 'Frequency Mode',
|
||||
'subtitleStyle.css': 'CSS Declarations',
|
||||
@@ -251,6 +253,8 @@ const DESCRIPTION_OVERRIDES: Record<string, string> = {
|
||||
'CSS declarations applied to secondary subtitles. Includes color, background-color, and all font properties.',
|
||||
'subtitleSidebar.css':
|
||||
'CSS declarations applied to the subtitle sidebar. Includes color, background-color, all font properties, and sidebar CSS variables.',
|
||||
'subtitleStyle.primaryVisibleOnYomitanPopup':
|
||||
'When primary subtitles are in hover mode, keep the primary subtitle bar visible while a Yomitan popup is open.',
|
||||
'websocket.enabled':
|
||||
'Built-in subtitle WebSocket server mode. Auto starts the built-in server only when mpv_websocket is not detected; otherwise it defers to the plugin.',
|
||||
'discordPresence.updateIntervalMs':
|
||||
@@ -359,7 +363,10 @@ function categoryAndSection(path: string): { category: ConfigSettingsCategory; s
|
||||
if (path.startsWith('subtitleStyle.secondary.')) {
|
||||
return { category: 'appearance', section: 'Secondary Subtitle Appearance' };
|
||||
}
|
||||
if (path === 'subtitleStyle.primaryDefaultMode') {
|
||||
if (
|
||||
path === 'subtitleStyle.primaryDefaultMode' ||
|
||||
path === 'subtitleStyle.primaryVisibleOnYomitanPopup'
|
||||
) {
|
||||
return { category: 'behavior', section: 'Subtitle Behavior' };
|
||||
}
|
||||
if (path.startsWith('subtitleStyle.')) {
|
||||
@@ -603,6 +610,7 @@ function isFeatureToggle(field: ConfigSettingsField): boolean {
|
||||
}
|
||||
|
||||
function fieldTypeRank(field: ConfigSettingsField): number {
|
||||
if (field.configPath === 'subtitleStyle.primaryVisibleOnYomitanPopup') return 2;
|
||||
if (field.control !== 'boolean') return 2;
|
||||
return isFeatureToggle(field) ? 0 : 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user