mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-05-26 00:55:16 -07:00
migrate ankiConnect.knownWords.color to subtitleStyle.knownWordColor
- Add knownWords.color → subtitleStyle.knownWordColor migration path - Fix discordPresence.updateIntervalMs label/description to say ms not seconds - Add changelog frontmatter (type/area) to settings-modal-layout fragment
This commit is contained in:
@@ -1 +1,4 @@
|
||||
type: changed
|
||||
area: config
|
||||
|
||||
- Settings: reorganized playback, shortcut, WebSocket, tracking, Jellyfin, character dictionary, and Discord presence controls in the settings modal.
|
||||
|
||||
@@ -30,6 +30,8 @@ const LEGACY_N_PLUS_ONE_PATH_MAP = {
|
||||
nPlusOne: 'subtitleStyle.nPlusOneColor',
|
||||
} as const;
|
||||
|
||||
const hexColorPattern = /^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/;
|
||||
|
||||
function propertyKey(propertyNode: JsoncNode): string | undefined {
|
||||
return propertyNode.children?.[0]?.value;
|
||||
}
|
||||
@@ -82,6 +84,12 @@ function normalizeLegacyDecks(value: unknown): unknown {
|
||||
return normalized;
|
||||
}
|
||||
|
||||
function asLegacyColor(value: unknown): string | undefined {
|
||||
if (typeof value !== 'string') return undefined;
|
||||
const text = value.trim();
|
||||
return hexColorPattern.test(text) ? text : undefined;
|
||||
}
|
||||
|
||||
function buildLegacyNPlusOneMigrationOperations(root: JsoncNode | undefined): {
|
||||
operations: ConfigSettingsPatchOperation[];
|
||||
hasLegacy: boolean;
|
||||
@@ -90,9 +98,9 @@ function buildLegacyNPlusOneMigrationOperations(root: JsoncNode | undefined): {
|
||||
const ankiConnect = propertyValue(findLastProperty(root, 'ankiConnect'));
|
||||
const nPlusOneProperties = findProperties(ankiConnect, 'nPlusOne');
|
||||
const nPlusOneObjects = nPlusOneProperties.map(propertyValue).filter(Boolean) as JsoncNode[];
|
||||
if (nPlusOneObjects.length === 0) {
|
||||
return { operations, hasLegacy: false };
|
||||
}
|
||||
const knownWords = propertyValue(findLastProperty(ankiConnect, 'knownWords'));
|
||||
const knownWordsColorNode = propertyValue(findLastProperty(knownWords, 'color'));
|
||||
const knownWordsColor = knownWordsColorNode ? getNodeValue(knownWordsColorNode) : undefined;
|
||||
|
||||
const canonicalNPlusOneValues = new Map<string, unknown>();
|
||||
const legacyValues = new Map<keyof typeof LEGACY_N_PLUS_ONE_PATH_MAP, unknown>();
|
||||
@@ -144,6 +152,22 @@ function buildLegacyNPlusOneMigrationOperations(root: JsoncNode | undefined): {
|
||||
});
|
||||
}
|
||||
|
||||
const legacyKnownWordsColor = asLegacyColor(knownWordsColor);
|
||||
if (legacyKnownWordsColor !== undefined) {
|
||||
hasLegacy = true;
|
||||
if (!hasPath(root, 'subtitleStyle.knownWordColor')) {
|
||||
operations.push({
|
||||
op: 'set',
|
||||
path: 'subtitleStyle.knownWordColor',
|
||||
value: legacyKnownWordsColor,
|
||||
});
|
||||
}
|
||||
operations.push({
|
||||
op: 'reset',
|
||||
path: 'ankiConnect.knownWords.color',
|
||||
});
|
||||
}
|
||||
|
||||
return { operations, hasLegacy };
|
||||
}
|
||||
|
||||
|
||||
@@ -2096,6 +2096,7 @@ test('migrates legacy ankiConnect n+1 color value to subtitleStyle', () => {
|
||||
subtitleStyle: { nPlusOneColor?: string; knownWordColor?: string };
|
||||
};
|
||||
assert.equal(parsed.subtitleStyle.nPlusOneColor, '#c6a0f6');
|
||||
assert.equal(parsed.subtitleStyle.knownWordColor, '#a6da95');
|
||||
assert.equal(Object.hasOwn(parsed.ankiConnect.nPlusOne ?? {}, 'nPlusOne'), false);
|
||||
});
|
||||
|
||||
|
||||
@@ -229,7 +229,7 @@ const LABEL_OVERRIDES: Record<string, string> = {
|
||||
'mpv.pauseUntilOverlayReady': 'Pause Until Overlay Ready',
|
||||
'mpv.aniskipEnabled': 'Enable AniSkip',
|
||||
'mpv.aniskipButtonKey': 'AniSkip Button Key',
|
||||
'discordPresence.updateIntervalMs': 'Update Interval Seconds',
|
||||
'discordPresence.updateIntervalMs': 'Update Interval (ms)',
|
||||
};
|
||||
|
||||
const DESCRIPTION_OVERRIDES: Record<string, string> = {
|
||||
@@ -248,7 +248,7 @@ const DESCRIPTION_OVERRIDES: Record<string, string> = {
|
||||
'subtitleSidebar.css':
|
||||
'CSS declarations applied to the subtitle sidebar. Includes color, background-color, all font properties, and sidebar CSS variables.',
|
||||
'discordPresence.updateIntervalMs':
|
||||
'Minimum interval between presence payload updates, in seconds.',
|
||||
'Minimum interval between presence payload updates, in milliseconds.',
|
||||
};
|
||||
|
||||
function isRecord(value: unknown): value is Record<string, unknown> {
|
||||
|
||||
Reference in New Issue
Block a user