mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-05-26 12:55:16 -07:00
feat(config): unify mpv plugin options under main config and add CSS/Ani
- Replace subminer.conf plugin config with mpv.* fields in config.jsonc - Add socketPath, backend, autoStartSubMiner, pauseUntilOverlayReady, aniskipEnabled/buttonKey, subminerBinaryPath to mpv config - Add subtitleSidebar.css field; migrate legacy sidebar appearance fields - Add paintOrder and WebkitTextStroke to subtitle style options - Update default subtitle/sidebar fontFamily to CJK-first stack - Fix overlay visible state surviving mpv y-r restart - Fix live config saves applying subtitle CSS immediately to open overlays - Migrate legacy primary/secondary subtitle appearance into subtitleStyle.css on load - Switch AniSkip button key setting to click-to-learn key capture
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
import type { RawConfig } from '../types/config';
|
||||
import type { ConfigSettingsPatchOperation } from '../types/settings';
|
||||
import {
|
||||
buildSubtitleCssDeclarationObject,
|
||||
getSubtitleCssManagedConfigPaths,
|
||||
getSubtitleCssPath,
|
||||
type SubtitleCssScope,
|
||||
} from '../settings/subtitle-style-css';
|
||||
import { applyConfigSettingsPatchToContent } from './settings/jsonc-edit';
|
||||
|
||||
const SUBTITLE_CSS_SCOPES: SubtitleCssScope[] = ['primary', 'secondary', 'sidebar'];
|
||||
const STARTUP_MIGRATION_EXCLUDED_PATHS = new Set([
|
||||
'subtitleStyle.hoverTokenColor',
|
||||
'subtitleStyle.hoverTokenBackgroundColor',
|
||||
]);
|
||||
|
||||
export type LegacySubtitleStyleCssMigrationResult =
|
||||
| {
|
||||
migrated: true;
|
||||
content: string;
|
||||
rawConfig: RawConfig;
|
||||
}
|
||||
| {
|
||||
migrated: false;
|
||||
content: string;
|
||||
rawConfig: RawConfig;
|
||||
};
|
||||
|
||||
function isRecord(value: unknown): value is Record<string, unknown> {
|
||||
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
||||
}
|
||||
|
||||
function getValueAtPath(root: unknown, path: string): unknown {
|
||||
let current = root;
|
||||
for (const segment of path.split('.')) {
|
||||
if (!isRecord(current)) return undefined;
|
||||
current = current[segment];
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
function hasPath(root: unknown, path: string): boolean {
|
||||
let current = root;
|
||||
const segments = path.split('.');
|
||||
for (const [index, segment] of segments.entries()) {
|
||||
if (!isRecord(current) || !Object.hasOwn(current, segment)) {
|
||||
return false;
|
||||
}
|
||||
if (index === segments.length - 1) {
|
||||
return true;
|
||||
}
|
||||
current = current[segment];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function buildLegacySubtitleStyleCssMigrationOperations(
|
||||
rawConfig: RawConfig,
|
||||
): ConfigSettingsPatchOperation[] {
|
||||
const operations: ConfigSettingsPatchOperation[] = [];
|
||||
|
||||
for (const scope of SUBTITLE_CSS_SCOPES) {
|
||||
const cssPath = getSubtitleCssPath(scope);
|
||||
const values: Record<string, unknown> = {
|
||||
[cssPath]: getValueAtPath(rawConfig, cssPath),
|
||||
};
|
||||
const legacyPaths = getSubtitleCssManagedConfigPaths(scope).filter(
|
||||
(legacyPath) =>
|
||||
!STARTUP_MIGRATION_EXCLUDED_PATHS.has(legacyPath) && hasPath(rawConfig, legacyPath),
|
||||
);
|
||||
if (legacyPaths.length === 0) continue;
|
||||
|
||||
for (const legacyPath of legacyPaths) {
|
||||
values[legacyPath] = getValueAtPath(rawConfig, legacyPath);
|
||||
}
|
||||
|
||||
operations.push({
|
||||
op: 'set',
|
||||
path: cssPath,
|
||||
value: buildSubtitleCssDeclarationObject(scope, values),
|
||||
});
|
||||
for (const legacyPath of legacyPaths) {
|
||||
operations.push({ op: 'reset', path: legacyPath });
|
||||
}
|
||||
}
|
||||
|
||||
return operations;
|
||||
}
|
||||
|
||||
export function applyLegacySubtitleStyleCssMigrationToContent(options: {
|
||||
content: string;
|
||||
rawConfig: RawConfig;
|
||||
}): LegacySubtitleStyleCssMigrationResult {
|
||||
const operations = buildLegacySubtitleStyleCssMigrationOperations(options.rawConfig);
|
||||
if (operations.length === 0) {
|
||||
return {
|
||||
migrated: false,
|
||||
content: options.content,
|
||||
rawConfig: options.rawConfig,
|
||||
};
|
||||
}
|
||||
|
||||
const result = applyConfigSettingsPatchToContent({
|
||||
content: options.content,
|
||||
operations,
|
||||
previousWarnings: [],
|
||||
});
|
||||
if (!result.ok) {
|
||||
return {
|
||||
migrated: false,
|
||||
content: options.content,
|
||||
rawConfig: options.rawConfig,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
migrated: true,
|
||||
content: result.content,
|
||||
rawConfig: result.rawConfig,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user