mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-05-26 12:55:16 -07:00
6ba91780c1
- 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
104 lines
3.3 KiB
TypeScript
104 lines
3.3 KiB
TypeScript
import type { ReloadConfigStrictResult } from '../../config';
|
|
import { applyConfigSettingsPatchToContent } from '../../config/settings/jsonc-edit';
|
|
import type { ConfigValidationWarning, ResolvedConfig } from '../../types/config';
|
|
import type {
|
|
ConfigSettingsPatch,
|
|
ConfigSettingsSaveResult,
|
|
ConfigSettingsSnapshot,
|
|
} from '../../types/settings';
|
|
|
|
export interface ConfigSettingsHotReloadDiff {
|
|
hotReloadFields: string[];
|
|
restartRequiredFields: string[];
|
|
}
|
|
|
|
export interface ConfigSettingsSaveDeps {
|
|
getConfigPath(): string;
|
|
getCurrentConfig(): ResolvedConfig;
|
|
getWarnings(): ConfigValidationWarning[];
|
|
getSnapshot(): ConfigSettingsSnapshot;
|
|
fileExists(path: string): boolean;
|
|
readText(path: string): string;
|
|
writeTextAtomically(path: string, content: string): void;
|
|
deleteFile?(path: string): void;
|
|
reloadConfigStrict(): ReloadConfigStrictResult;
|
|
classifyDiff(prev: ResolvedConfig, next: ResolvedConfig): ConfigSettingsHotReloadDiff;
|
|
getRestartRequiredSections(restartRequiredFields: string[]): string[];
|
|
onHotReloadApplied?: (diff: ConfigSettingsHotReloadDiff, config: ResolvedConfig) => void;
|
|
}
|
|
|
|
export function createSaveConfigSettingsPatchHandler(deps: ConfigSettingsSaveDeps) {
|
|
return (patch: ConfigSettingsPatch): ConfigSettingsSaveResult => {
|
|
if (patch.operations.length === 0) {
|
|
return {
|
|
ok: true,
|
|
snapshot: deps.getSnapshot(),
|
|
hotReloadFields: [],
|
|
restartRequiredFields: [],
|
|
restartRequiredSections: [],
|
|
};
|
|
}
|
|
|
|
const configPath = deps.getConfigPath();
|
|
const previousConfig = deps.getCurrentConfig();
|
|
const previousWarnings = deps.getWarnings();
|
|
const hadExistingConfig = deps.fileExists(configPath);
|
|
const content = hadExistingConfig ? deps.readText(configPath) : '{}\n';
|
|
const candidate = applyConfigSettingsPatchToContent({
|
|
content,
|
|
operations: patch.operations,
|
|
previousWarnings,
|
|
});
|
|
|
|
if (!candidate.ok) {
|
|
return {
|
|
ok: false,
|
|
warnings: candidate.warnings,
|
|
error: candidate.error,
|
|
hotReloadFields: [],
|
|
restartRequiredFields: [],
|
|
restartRequiredSections: [],
|
|
};
|
|
}
|
|
|
|
deps.writeTextAtomically(configPath, candidate.content);
|
|
const reloadResult = deps.reloadConfigStrict();
|
|
if (!reloadResult.ok) {
|
|
try {
|
|
if (hadExistingConfig) {
|
|
deps.writeTextAtomically(configPath, content);
|
|
} else if (deps.deleteFile) {
|
|
deps.deleteFile(configPath);
|
|
} else {
|
|
deps.writeTextAtomically(configPath, content);
|
|
}
|
|
deps.reloadConfigStrict();
|
|
} catch {
|
|
// Best-effort rollback; preserve original reload error for caller.
|
|
}
|
|
return {
|
|
ok: false,
|
|
warnings: [],
|
|
error: reloadResult.error,
|
|
hotReloadFields: [],
|
|
restartRequiredFields: [],
|
|
restartRequiredSections: [],
|
|
};
|
|
}
|
|
|
|
const diff = deps.classifyDiff(previousConfig, reloadResult.config);
|
|
if (diff.hotReloadFields.length > 0) {
|
|
deps.onHotReloadApplied?.(diff, reloadResult.config);
|
|
}
|
|
|
|
return {
|
|
ok: true,
|
|
snapshot: deps.getSnapshot(),
|
|
warnings: reloadResult.warnings,
|
|
hotReloadFields: diff.hotReloadFields,
|
|
restartRequiredFields: diff.restartRequiredFields,
|
|
restartRequiredSections: deps.getRestartRequiredSections(diff.restartRequiredFields),
|
|
};
|
|
};
|
|
}
|