feat(core): add Electron runtime, services, and app composition

This commit is contained in:
2026-02-22 21:43:43 -08:00
parent 448ce03fd4
commit d3fd47f0ec
562 changed files with 69719 additions and 0 deletions
+99
View File
@@ -0,0 +1,99 @@
import { MpvSubtitleRenderMetrics } from '../../types';
import { asBoolean, asFiniteNumber, asString } from '../utils/coerce';
export const DEFAULT_MPV_SUBTITLE_RENDER_METRICS: MpvSubtitleRenderMetrics = {
subPos: 100,
subFontSize: 38,
subScale: 1,
subMarginY: 34,
subMarginX: 19,
subFont: 'sans-serif',
subSpacing: 0,
subBold: false,
subItalic: false,
subBorderSize: 2.5,
subShadowOffset: 0,
subAssOverride: 'yes',
subScaleByWindow: true,
subUseMargins: true,
osdHeight: 720,
osdDimensions: null,
};
export function sanitizeMpvSubtitleRenderMetrics(
current: MpvSubtitleRenderMetrics,
patch: Partial<MpvSubtitleRenderMetrics> | null | undefined,
): MpvSubtitleRenderMetrics {
if (!patch) return current;
return updateMpvSubtitleRenderMetrics(current, patch);
}
export function updateMpvSubtitleRenderMetrics(
current: MpvSubtitleRenderMetrics,
patch: Partial<MpvSubtitleRenderMetrics>,
): MpvSubtitleRenderMetrics {
const patchOsd = patch.osdDimensions;
const nextOsdDimensions =
patchOsd &&
typeof patchOsd.w === 'number' &&
typeof patchOsd.h === 'number' &&
typeof patchOsd.ml === 'number' &&
typeof patchOsd.mr === 'number' &&
typeof patchOsd.mt === 'number' &&
typeof patchOsd.mb === 'number'
? {
w: asFiniteNumber(patchOsd.w, 0, 1, 100000),
h: asFiniteNumber(patchOsd.h, 0, 1, 100000),
ml: asFiniteNumber(patchOsd.ml, 0, 0, 100000),
mr: asFiniteNumber(patchOsd.mr, 0, 0, 100000),
mt: asFiniteNumber(patchOsd.mt, 0, 0, 100000),
mb: asFiniteNumber(patchOsd.mb, 0, 0, 100000),
}
: patchOsd === null
? null
: current.osdDimensions;
return {
subPos: asFiniteNumber(patch.subPos, current.subPos, 0, 150),
subFontSize: asFiniteNumber(patch.subFontSize, current.subFontSize, 1, 200),
subScale: asFiniteNumber(patch.subScale, current.subScale, 0.1, 10),
subMarginY: asFiniteNumber(patch.subMarginY, current.subMarginY, 0, 200),
subMarginX: asFiniteNumber(patch.subMarginX, current.subMarginX, 0, 200),
subFont: asString(patch.subFont, current.subFont),
subSpacing: asFiniteNumber(patch.subSpacing, current.subSpacing, -100, 100),
subBold: asBoolean(patch.subBold, current.subBold),
subItalic: asBoolean(patch.subItalic, current.subItalic),
subBorderSize: asFiniteNumber(patch.subBorderSize, current.subBorderSize, 0, 100),
subShadowOffset: asFiniteNumber(patch.subShadowOffset, current.subShadowOffset, 0, 100),
subAssOverride: asString(patch.subAssOverride, current.subAssOverride),
subScaleByWindow: asBoolean(patch.subScaleByWindow, current.subScaleByWindow),
subUseMargins: asBoolean(patch.subUseMargins, current.subUseMargins),
osdHeight: asFiniteNumber(patch.osdHeight, current.osdHeight, 1, 10000),
osdDimensions: nextOsdDimensions,
};
}
export function applyMpvSubtitleRenderMetricsPatch(
current: MpvSubtitleRenderMetrics,
patch: Partial<MpvSubtitleRenderMetrics>,
): { next: MpvSubtitleRenderMetrics; changed: boolean } {
const next = updateMpvSubtitleRenderMetrics(current, patch);
const changed =
next.subPos !== current.subPos ||
next.subFontSize !== current.subFontSize ||
next.subScale !== current.subScale ||
next.subMarginY !== current.subMarginY ||
next.subMarginX !== current.subMarginX ||
next.subFont !== current.subFont ||
next.subSpacing !== current.subSpacing ||
next.subBold !== current.subBold ||
next.subItalic !== current.subItalic ||
next.subBorderSize !== current.subBorderSize ||
next.subShadowOffset !== current.subShadowOffset ||
next.subAssOverride !== current.subAssOverride ||
next.subScaleByWindow !== current.subScaleByWindow ||
next.subUseMargins !== current.subUseMargins ||
next.osdHeight !== current.osdHeight ||
JSON.stringify(next.osdDimensions) !== JSON.stringify(current.osdDimensions);
return { next, changed };
}