refactor: remove dead code and enable noUnusedLocals (#292)

* refactor: remove dead code and enable noUnusedLocals

- delete launcher/jimaku.ts and the launcher Args/config jimaku* fields
  that only fed it (the SUBMINER_JIMAKU_* env vars had no effect)
- delete plugin/subminer/hover.lua; nothing has sent subminer-hover-token
  since Overlay 2.0
- drop never-read anilist.characterDictionary.refreshTtlHours and
  evictionPolicy (still hidden in the settings UI for old configs)
- drop unused root deps: eslint, @fontsource-variable/geist{,-mono}
  (stats/ declares its own)
- delete the committed draft renderer-performance plan doc
- turn on noUnusedLocals for typecheck and remove what it surfaced,
  including Windows focus-handoff values computed but never consumed

* docs(changes): add docs fragment and note retired hover messages
This commit is contained in:
sudacode authored and GitHub committed 2026-10-12 22:10:54 -07:00
1 parent ea2b3a9507
commit 8fc20b2499
52 files changed
+20 -1683

No files matched your search

-5
View File
@@ -41,7 +41,6 @@ import type { NPlusOneMatchMode, SubtitleMiningContext } from './types/subtitle'
import { DEFAULT_ANKI_CONNECT_CONFIG } from './config';
import {
getConfiguredWordFieldCandidates,
getConfiguredWordFieldName,
getPreferredWordValueFromExtractedFields,
} from './anki-field-config';
import { createLogger } from './logger';
@@ -1632,10 +1631,6 @@ export class AnkiIntegration {
return sentenceCardConfig.audioField || 'SentenceAudio';
}
private getConfiguredWordFieldName(): string {
return getConfiguredWordFieldName(this.config);
}
private getConfiguredWordFieldCandidates(): string[] {
return getConfiguredWordFieldCandidates(this.config);
}
+1 -13
View File
@@ -1,10 +1,6 @@
import { DEFAULT_ANKI_CONNECT_CONFIG } from '../config';
import type { AnkiConnectConfig } from '../types/anki';
import {
getKnownWordCacheLifecycleConfig,
getKnownWordCacheRefreshIntervalMinutes,
getKnownWordCacheScopeForConfig,
} from './known-word-cache';
import { getKnownWordCacheLifecycleConfig } from './known-word-cache';
export interface AnkiIntegrationRuntimeProxyServer {
start(options: { host: string; port: number; upstreamUrl: string }): void;
@@ -255,14 +251,6 @@ export class AnkiIntegrationRuntime {
return getKnownWordCacheLifecycleConfig(config);
}
private getKnownWordRefreshIntervalMinutes(config: AnkiConnectConfig): number {
return getKnownWordCacheRefreshIntervalMinutes(config);
}
private getKnownWordCacheScopeForConfig(config: AnkiConnectConfig): string {
return getKnownWordCacheScopeForConfig(config);
}
getOrCreateProxyServer(): AnkiIntegrationRuntimeProxyServer {
if (!this.proxyServer) {
this.proxyServer = this.deps.proxyServerFactory();
@@ -133,9 +133,7 @@ export const INTEGRATIONS_DEFAULT_CONFIG: Pick<
enabled: false,
accessToken: '',
characterDictionary: {
refreshTtlHours: 168,
maxLoaded: 3,
evictionPolicy: 'delete',
profileScope: 'all',
collapsibleSections: {
description: false,
@@ -37,8 +37,6 @@ function collectConfigLeafPaths(config: ResolvedConfig): string[] {
// an allowlist entry. Only allowlist a path when the registry is genuinely
// the wrong surface for it.
const UNDOCUMENTED_LEAVES: ReadonlySet<string> = new Set([
'anilist.characterDictionary.evictionPolicy',
'anilist.characterDictionary.refreshTtlHours',
'keybindings',
'subtitleStyle.backdropFilter',
'subtitleStyle.backgroundColor',
-43
View File
@@ -94,27 +94,6 @@ export function applyIntegrationConfig(context: ResolveContext): void {
if (isObject(src.anilist.characterDictionary)) {
const characterDictionary = src.anilist.characterDictionary;
const refreshTtlHours = asNumber(characterDictionary.refreshTtlHours);
if (refreshTtlHours !== undefined) {
const normalized = Math.min(24 * 365, Math.max(1, Math.floor(refreshTtlHours)));
if (normalized !== refreshTtlHours) {
warn(
'anilist.characterDictionary.refreshTtlHours',
characterDictionary.refreshTtlHours,
normalized,
'Out of range; clamped to 1..8760 hours.',
);
}
resolved.anilist.characterDictionary.refreshTtlHours = normalized;
} else if (characterDictionary.refreshTtlHours !== undefined) {
warn(
'anilist.characterDictionary.refreshTtlHours',
characterDictionary.refreshTtlHours,
resolved.anilist.characterDictionary.refreshTtlHours,
'Expected number.',
);
}
const maxLoaded = asNumber(characterDictionary.maxLoaded);
if (maxLoaded !== undefined) {
const normalized = Math.min(20, Math.max(1, Math.floor(maxLoaded)));
@@ -136,28 +115,6 @@ export function applyIntegrationConfig(context: ResolveContext): void {
);
}
const evictionPolicyRaw = asString(characterDictionary.evictionPolicy);
if (evictionPolicyRaw !== undefined) {
const evictionPolicy = evictionPolicyRaw.trim().toLowerCase();
if (evictionPolicy === 'disable' || evictionPolicy === 'delete') {
resolved.anilist.characterDictionary.evictionPolicy = evictionPolicy;
} else {
warn(
'anilist.characterDictionary.evictionPolicy',
characterDictionary.evictionPolicy,
resolved.anilist.characterDictionary.evictionPolicy,
"Expected one of: 'disable', 'delete'.",
);
}
} else if (characterDictionary.evictionPolicy !== undefined) {
warn(
'anilist.characterDictionary.evictionPolicy',
characterDictionary.evictionPolicy,
resolved.anilist.characterDictionary.evictionPolicy,
'Expected string.',
);
}
const profileScopeRaw = asString(characterDictionary.profileScope);
if (profileScopeRaw !== undefined) {
const profileScope = profileScopeRaw.trim().toLowerCase();
+1 -7
View File
@@ -97,9 +97,7 @@ test('anilist character dictionary fields are parsed, clamped, and enum-validate
const { context, warnings } = createResolveContext({
anilist: {
characterDictionary: {
refreshTtlHours: 0,
maxLoaded: 99,
evictionPolicy: 'purge' as never,
profileScope: 'global' as never,
collapsibleSections: {
description: true,
@@ -112,9 +110,7 @@ test('anilist character dictionary fields are parsed, clamped, and enum-validate
applyIntegrationConfig(context);
assert.equal(context.resolved.anilist.characterDictionary.refreshTtlHours, 1);
assert.equal(context.resolved.anilist.characterDictionary.maxLoaded, 20);
assert.equal(context.resolved.anilist.characterDictionary.evictionPolicy, 'delete');
assert.equal(context.resolved.anilist.characterDictionary.profileScope, 'all');
assert.equal(context.resolved.anilist.characterDictionary.collapsibleSections.description, true);
assert.equal(
@@ -124,9 +120,7 @@ test('anilist character dictionary fields are parsed, clamped, and enum-validate
assert.equal(context.resolved.anilist.characterDictionary.collapsibleSections.voicedBy, true);
const warnedPaths = warnings.map((warning) => warning.path);
assert.ok(warnedPaths.includes('anilist.characterDictionary.refreshTtlHours'));
assert.ok(warnedPaths.includes('anilist.characterDictionary.maxLoaded'));
assert.ok(warnedPaths.includes('anilist.characterDictionary.evictionPolicy'));
assert.ok(warnedPaths.includes('anilist.characterDictionary.profileScope'));
assert.ok(
warnedPaths.includes('anilist.characterDictionary.collapsibleSections.characterInformation'),
@@ -134,7 +128,7 @@ test('anilist character dictionary fields are parsed, clamped, and enum-validate
});
test('yomitan externalProfilePath is trimmed and invalid values warn', () => {
const { context, warnings } = createResolveContext({
const { context } = createResolveContext({
yomitan: {
externalProfilePath: ' /tmp/gsm-profile ',
},
-7
View File
@@ -18,10 +18,6 @@ const TOP_LEVEL_SECTION_DESCRIPTION_BY_KEY = new Map(
CONFIG_TEMPLATE_SECTIONS.map((section) => [String(section.key), section.description[0] ?? '']),
);
const SUBTITLE_CSS_SCOPES: SubtitleCssScope[] = ['primary', 'secondary', 'sidebar'];
const HIDDEN_TEMPLATE_PATHS = [
'anilist.characterDictionary.evictionPolicy',
'anilist.characterDictionary.refreshTtlHours',
];
function normalizeCommentText(value: string): string {
return value.replace(/\s+/g, ' ').replace(/\*\//g, '*\\/').trim();
@@ -176,9 +172,6 @@ function renderSection(
function createTemplateConfig(config: ResolvedConfig): ResolvedConfig {
const templateConfig = deepCloneConfig(config);
foldSubtitleCssManagedDefaults(templateConfig);
for (const hiddenPath of HIDDEN_TEMPLATE_PATHS) {
deleteValueAtPath(templateConfig, hiddenPath);
}
if (templateConfig.keybindings.length === 0) {
templateConfig.keybindings = DEFAULT_KEYBINDINGS.map((binding) => ({
key: binding.key,
@@ -87,20 +87,6 @@ export interface GuessAnilistMediaInfoDeps {
runGuessit: (target: string) => Promise<string>;
}
function firstString(value: unknown): string | null {
if (typeof value === 'string') {
const trimmed = value.trim();
return trimmed.length > 0 ? trimmed : null;
}
if (Array.isArray(value)) {
for (const item of value) {
const candidate = firstString(item);
if (candidate) return candidate;
}
}
return null;
}
function normalizeGuessitTitlePart(value: string): string {
return value.replace(/[._]+/g, ' ').replace(/-/g, ' ').replace(/\s+/g, ' ').trim();
}
@@ -147,16 +147,10 @@ import { enqueueWrite } from './immersion-tracker/queue';
import { nowMs } from './immersion-tracker/time';
import {
DEFAULT_BATCH_SIZE,
DEFAULT_DAILY_ROLLUP_RETENTION_MS,
DEFAULT_EVENTS_RETENTION_MS,
DEFAULT_FLUSH_INTERVAL_MS,
DEFAULT_MAINTENANCE_INTERVAL_MS,
DEFAULT_MAX_PAYLOAD_BYTES,
DEFAULT_MONTHLY_ROLLUP_RETENTION_MS,
DEFAULT_QUEUE_CAP,
DEFAULT_SESSIONS_RETENTION_MS,
DEFAULT_TELEMETRY_RETENTION_MS,
DEFAULT_VACUUM_INTERVAL_MS,
EVENT_CARD_MINED,
EVENT_LOOKUP,
EVENT_MEDIA_BUFFER,
@@ -2769,7 +2769,6 @@ test('getSessionWordsByLine joins word occurrences through imm_words.id', () =>
try {
ensureSchema(db);
const stmts = createTrackerPreparedStatements(db);
const startedAtMs = 1_735_732_800_000;
const videoId = getOrCreateVideoRecord(db, '/tmp/session-words-by-line.mkv', {
canonicalTitle: 'Episode',
@@ -18,7 +18,6 @@ import type {
} from './types';
import {
ACTIVE_SESSION_METRICS_CTE,
SESSION_WORD_COUNTS_CTE,
SESSION_WORD_COUNTS_SELECT,
fromDbTimestamp,
resolvedCoverBlobExpr,
@@ -16,7 +16,6 @@ import { deriveStoredPartOfSpeech } from '../tokenizer/part-of-speech';
import {
cleanupUnusedCoverArtBlobHash,
findSharedCoverBlobHash,
toDbMs,
toDbTimestamp,
} from './query-shared';
@@ -9,7 +9,7 @@ import { ensureLexicalDailyRollupTables, markLexicalDailyRollupsReady } from './
import { isVocabularyStatsRowVisible, type VocabularyVisibilityRow } from './vocabulary-visibility';
import { SCHEMA_VERSION } from './types';
import type { QueuedWrite, VideoMetadata, YoutubeVideoMetadata } from './types';
import { toDbMs, toDbTimestamp } from './query-shared';
import { toDbTimestamp } from './query-shared';
export interface TrackerPreparedStatements {
telemetryInsertStmt: ReturnType<DatabaseSync['prepare']>;
-30
View File
@@ -74,9 +74,6 @@ export function updateVisibleOverlayVisibility(args: {
overlayInteractionActive?: boolean;
mainWindow: BrowserWindow | null;
windowTracker: BaseWindowTracker | null;
lastKnownWindowsForegroundProcessName?: string | null;
windowsOverlayProcessName?: string | null;
windowsFocusHandoffGraceActive?: boolean;
macOSForegroundProbeActive?: boolean;
trackerNotReadyWarningShown: boolean;
setTrackerNotReadyWarningShown: (shown: boolean) => void;
@@ -168,26 +165,6 @@ export function updateVisibleOverlayVisibility(args: {
const shouldUseMacOSMousePassthrough = args.isMacOSPlatform && !overlayInteractionActive;
const shouldDefaultToPassthrough =
args.isWindowsPlatform || forceMousePassthrough || shouldReleaseMacOSOverlayLevel;
const windowsForegroundProcessName =
args.lastKnownWindowsForegroundProcessName?.trim().toLowerCase() ?? null;
const windowsOverlayProcessName = args.windowsOverlayProcessName?.trim().toLowerCase() ?? null;
const hasWindowsForegroundProcessSignal =
args.isWindowsPlatform && windowsForegroundProcessName !== null;
const isTrackedWindowsTargetFocused = args.windowTracker?.isTargetWindowFocused?.() ?? true;
const isTrackedWindowsTargetMinimized =
args.isWindowsPlatform &&
typeof args.windowTracker?.isTargetWindowMinimized === 'function' &&
args.windowTracker.isTargetWindowMinimized();
const shouldPreserveWindowsOverlayDuringFocusHandoff =
args.isWindowsPlatform &&
args.windowsFocusHandoffGraceActive === true &&
!!args.windowTracker &&
(!hasWindowsForegroundProcessSignal ||
windowsForegroundProcessName === 'mpv' ||
(windowsOverlayProcessName !== null &&
windowsForegroundProcessName === windowsOverlayProcessName)) &&
!isTrackedWindowsTargetMinimized &&
(args.windowTracker.isTracking() || args.windowTracker.getGeometry() !== null);
const shouldForcePassiveReshow = args.isWindowsPlatform && !wasVisible;
const isNonNativeOverlay = !args.isWindowsPlatform && !args.isMacOSPlatform;
const isNonNativePassiveOverlay = isNonNativeOverlay && !overlayInteractionActive;
@@ -208,13 +185,6 @@ export function updateVisibleOverlayVisibility(args: {
(isNonNativePassiveOverlay && !hasNonNativeInputRegion) ||
(shouldDefaultToPassthrough && (!isVisibleOverlayFocused || shouldForcePassiveReshow));
const shouldBindTrackedWindowsOverlay = args.isWindowsPlatform && !!args.windowTracker;
const shouldKeepTrackedWindowsOverlayTopmost =
!args.isWindowsPlatform ||
!args.windowTracker ||
isVisibleOverlayFocused ||
isTrackedWindowsTargetFocused ||
shouldPreserveWindowsOverlayDuringFocusHandoff ||
(hasWindowsForegroundProcessSignal && windowsForegroundProcessName === 'mpv');
if (shouldIgnoreMouseEvents) {
applyOverlayClickThrough(mainWindow, args.isWindowsPlatform);
} else {
-1
View File
@@ -1,5 +1,4 @@
import type { RuntimeOptionApplyResult, RuntimeOptionId } from '../../types';
import type { SessionActionId } from '../../types/session-bindings';
import type { SessionActionDispatchRequest } from '../../types/runtime';
export interface SessionActionExecutorDeps {
@@ -1,4 +1,4 @@
import { selectAll, type SqlRow, type SyncDb } from './libsql-driver';
import { selectAll, type SyncDb } from './libsql-driver';
import { nowDbTimestamp, tableExists, type SyncMergeSummary } from './shared';
const LOCAL_DAY_EXPR = `CAST(julianday(CAST(started_at_ms AS REAL) / 1000, 'unixepoch', 'localtime') - 2440587.5 AS INTEGER)`;
@@ -1,7 +1,6 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import { parseSrtCues, parseAssCues, parseSubtitleCues } from './subtitle-cue-parser';
import type { SubtitleCue } from '../../types';
test('parseSrtCues parses basic SRT content', () => {
const content = [
-8
View File
@@ -608,14 +608,6 @@ function getYomitanFrequencyRank(
return null;
}
const normalizedHeadword = token.headword.trim();
const normalizedSurface = token.surface.trim();
const isInflectedHeadwordFallback =
matchMode === 'headword' &&
normalizedCandidateText === normalizedHeadword &&
normalizedSurface.length > 0 &&
normalizedSurface !== normalizedHeadword;
return selectBestYomitanFrequencyRank(candidateEntries);
}
@@ -390,23 +390,6 @@ function isReduplicatedKanaSfx(text: string): boolean {
return chars.slice(0, half).join('') === chars.slice(half).join('');
}
function isReduplicatedKanaSfxWithOptionalTrailingTo(text: string): boolean {
const normalized = normalizeKana(text);
if (!normalized) {
return false;
}
if (isReduplicatedKanaSfx(normalized)) {
return true;
}
if (normalized.length <= 1 || !normalized.endsWith('と')) {
return false;
}
return isReduplicatedKanaSfx(normalized.slice(0, -1));
}
function hasAdjacentKanaRepeat(text: string): boolean {
const normalized = normalizeKana(text);
if (!normalized) {
-15
View File
@@ -193,14 +193,9 @@ import {
createBuildSetOverlayDebugVisualizationEnabledMainDepsHandler,
createTrayRuntimeHandlers,
createOverlayVisibilityRuntime,
createBroadcastRuntimeOptionsChangedHandler,
createGetRuntimeOptionsStateHandler,
createGetFieldGroupingResolverHandler,
createSetFieldGroupingResolverHandler,
createOpenRuntimeOptionsPaletteHandler,
createRestorePreviousSecondarySubVisibilityHandler,
createSendToActiveOverlayWindowHandler,
createSetOverlayDebugVisualizationEnabledHandler,
createLoadSubtitlePositionHandler,
createSaveSubtitlePositionHandler,
createAppendClipboardVideoToQueueHandler,
@@ -297,7 +292,6 @@ import {
handleMultiCopyDigit as handleMultiCopyDigitCore,
hasMpvWebsocketPlugin,
importYomitanDictionaryFromZip,
initializeOverlayAnkiIntegration as initializeOverlayAnkiIntegrationCore,
initializeOverlayRuntime as initializeOverlayRuntimeCore,
isSubtitleAnnotationUpgrade,
isOverlayWindowContentReady,
@@ -603,7 +597,6 @@ import {
} from './main/anilist-url-guard';
import {
ConfigService,
ConfigStartupParseError,
DEFAULT_CONFIG,
DEFAULT_KEYBINDINGS,
generateConfigTemplate,
@@ -615,7 +608,6 @@ import {
createSubtitlePrefetchService,
type SubtitlePrefetchService,
} from './core/services/subtitle-prefetch';
import { buildSubtitleSidebarSourceKey } from './main/runtime/subtitle-prefetch-source';
import { createSubtitlePrefetchInitController } from './main/runtime/subtitle-prefetch-init';
import {
createCachedInternalSubtitleTrackExtractor,
@@ -623,7 +615,6 @@ import {
} from './main/runtime/internal-subtitle-extraction';
import { createRemoteMediaPathDetector } from './main/runtime/network-media-path';
import { applyCharacterDictionarySelection } from './main/character-dictionary-selection';
import { getSubsyncConfig } from './subsync/utils';
if (process.platform === 'linux') {
app.commandLine.appendSwitch('enable-features', 'GlobalShortcutsPortal');
@@ -2798,11 +2789,6 @@ const overlayVisibilityRuntime = createOverlayVisibilityRuntimeService(
getOverlayInteractionActive: () =>
visibleOverlayInteractionRuntime.getVisibleOverlayInteractionActive(),
getWindowTracker: () => appState.windowTracker,
getLastKnownWindowsForegroundProcessName: () =>
visibleOverlayInteractionRuntime.getLastWindowsVisibleOverlayForegroundProcessName(),
getWindowsOverlayProcessName: () => path.parse(process.execPath).name.toLowerCase(),
getWindowsFocusHandoffGraceActive: () =>
visibleOverlayInteractionRuntime.hasWindowsVisibleOverlayFocusHandoffGrace(),
getMacOSForegroundProbeActive: () =>
visibleOverlayInteractionRuntime.getMacOSVisibleOverlayForegroundProbeActive(),
getTrackerNotReadyWarningShown: () => appState.trackerNotReadyWarningShown,
@@ -3233,7 +3219,6 @@ const {
cleanupJellyfinSubtitleCache,
runJellyfinCommand,
openJellyfinSetupWindow,
getJellyfinClientInfo,
ensureMpvConnectedForPlayback,
} = composeJellyfinRuntimeHandlers({
getResolvedJellyfinConfigMainDeps: {
-1
View File
@@ -49,7 +49,6 @@ import type {
CharacterDictionaryRuntimeDeps,
CharacterDictionarySnapshot,
CharacterDictionarySnapshotImage,
CharacterDictionarySnapshotProgress,
CharacterDictionarySnapshotProgressCallbacks,
CharacterDictionarySnapshotResult,
MergedCharacterDictionaryBuildResult,
-6
View File
@@ -15,9 +15,6 @@ export interface OverlayVisibilityRuntimeDeps {
getSuspendVisibleOverlay?: () => boolean;
getOverlayInteractionActive?: () => boolean;
getWindowTracker: () => BaseWindowTracker | null;
getLastKnownWindowsForegroundProcessName?: () => string | null;
getWindowsOverlayProcessName?: () => string | null;
getWindowsFocusHandoffGraceActive?: () => boolean;
getMacOSForegroundProbeActive?: () => boolean;
getTrackerNotReadyWarningShown: () => boolean;
setTrackerNotReadyWarningShown: (shown: boolean) => void;
@@ -61,9 +58,6 @@ export function createOverlayVisibilityRuntimeService(
overlayInteractionActive: deps.getOverlayInteractionActive?.() ?? false,
mainWindow,
windowTracker,
lastKnownWindowsForegroundProcessName: deps.getLastKnownWindowsForegroundProcessName?.(),
windowsOverlayProcessName: deps.getWindowsOverlayProcessName?.() ?? null,
windowsFocusHandoffGraceActive: deps.getWindowsFocusHandoffGraceActive?.() ?? false,
macOSForegroundProbeActive: deps.getMacOSForegroundProbeActive?.() ?? false,
trackerNotReadyWarningShown: deps.getTrackerNotReadyWarningShown(),
setTrackerNotReadyWarningShown: (shown: boolean) => {
@@ -14,10 +14,6 @@ export function createBuildOverlayVisibilityRuntimeMainDepsHandler(
getSuspendVisibleOverlay: () => deps.getSuspendVisibleOverlay?.() ?? false,
getOverlayInteractionActive: () => deps.getOverlayInteractionActive?.() ?? false,
getWindowTracker: () => deps.getWindowTracker(),
getLastKnownWindowsForegroundProcessName: () =>
deps.getLastKnownWindowsForegroundProcessName?.() ?? null,
getWindowsOverlayProcessName: () => deps.getWindowsOverlayProcessName?.() ?? null,
getWindowsFocusHandoffGraceActive: () => deps.getWindowsFocusHandoffGraceActive?.() ?? false,
getMacOSForegroundProbeActive: () => deps.getMacOSForegroundProbeActive?.() ?? false,
getTrackerNotReadyWarningShown: () => deps.getTrackerNotReadyWarningShown(),
setTrackerNotReadyWarningShown: (shown: boolean) => deps.setTrackerNotReadyWarningShown(shown),
@@ -78,7 +78,6 @@ export function createVisibleOverlayInteractionRuntime(deps: VisibleOverlayInter
const VISIBLE_OVERLAY_BLUR_REFRESH_DELAYS_MS = [0, 25, 100, 250] as const;
const WINDOWS_VISIBLE_OVERLAY_Z_ORDER_RETRY_DELAYS_MS = [0, 48, 120, 240, 480] as const;
const WINDOWS_VISIBLE_OVERLAY_FOREGROUND_POLL_INTERVAL_MS = 75;
const WINDOWS_VISIBLE_OVERLAY_FOCUS_HANDOFF_GRACE_MS = 200;
const LINUX_VISIBLE_OVERLAY_FOCUS_HANDOFF_GRACE_MS = 1_500;
// Ignore transient "neither mpv nor overlay is the active window" blips before suppressing
// subtitle pointer interaction. Right after playback starts the overlay can briefly become the
@@ -93,7 +92,6 @@ export function createVisibleOverlayInteractionRuntime(deps: VisibleOverlayInter
let windowsVisibleOverlayForegroundPollInterval: ReturnType<typeof setInterval> | null = null;
let windowsOverlayPointerInteractionActive = false;
let lastWindowsVisibleOverlayForegroundProcessName: string | null = null;
let lastWindowsVisibleOverlayBlurredAtMs = 0;
let lastLinuxVisibleOverlayFollowedMpvAtMs = 0;
const linuxPointerForegroundSuppressionGrace: ForegroundSuppressionGraceState = {
lossSinceMs: null,
@@ -482,15 +480,6 @@ export function createVisibleOverlayInteractionRuntime(deps: VisibleOverlayInter
}
}
function hasWindowsVisibleOverlayFocusHandoffGrace(): boolean {
return (
process.platform === 'win32' &&
lastWindowsVisibleOverlayBlurredAtMs > 0 &&
Date.now() - lastWindowsVisibleOverlayBlurredAtMs <=
WINDOWS_VISIBLE_OVERLAY_FOCUS_HANDOFF_GRACE_MS
);
}
function shouldPollWindowsVisibleOverlayForegroundProcess(): boolean {
if (process.platform !== 'win32' || !overlayManager.getVisibleOverlayVisible()) {
return false;
@@ -562,9 +551,6 @@ export function createVisibleOverlayInteractionRuntime(deps: VisibleOverlayInter
return;
}
if (process.platform === 'win32') {
lastWindowsVisibleOverlayBlurredAtMs = Date.now();
}
startMacOSVisibleOverlayForegroundProbe();
clearVisibleOverlayBlurRefreshTimeouts();
for (const delayMs of VISIBLE_OVERLAY_BLUR_REFRESH_DELAYS_MS) {
@@ -860,7 +846,6 @@ export function createVisibleOverlayInteractionRuntime(deps: VisibleOverlayInter
retargetOverlayWindowTrackerForMpvSocket,
requestWindowsVisibleOverlayZOrderSync,
scheduleWindowsVisibleOverlayZOrderSyncBurst,
hasWindowsVisibleOverlayFocusHandoffGrace,
ensureWindowsVisibleOverlayForegroundPollLoop,
clearWindowsVisibleOverlayForegroundPollLoop,
scheduleVisibleOverlayBlurRefresh,
@@ -881,8 +866,6 @@ export function createVisibleOverlayInteractionRuntime(deps: VisibleOverlayInter
windowsOverlayPointerInteractionActive = false;
},
getLinuxOverlayInputShapeActive: () => linuxOverlayInputShapeActive,
getLastWindowsVisibleOverlayForegroundProcessName: () =>
lastWindowsVisibleOverlayForegroundProcessName,
getMacOSVisibleOverlayForegroundProbeActive: () => macOSVisibleOverlayForegroundProbeActive,
setLinuxOverlayInteractiveHint: (interactive: boolean) => {
linuxOverlayInteractiveHint = interactive;
+1 -1
View File
@@ -1464,7 +1464,7 @@ test('keyboard mode: an open modal receives h/l/arrows instead of lookup control
});
test('keyboard mode: h/l/arrows typed into a text field are not consumed by lookup controls', async () => {
const { ctx, testGlobals, handlers, setWordCount } = createKeyboardHandlerHarness();
const { testGlobals, handlers, setWordCount } = createKeyboardHandlerHarness();
try {
await handlers.setupMpvInputForwarding();
@@ -31,12 +31,6 @@ export function createYoutubeTrackPickerModal(
ctx.dom.youtubePickerStatus.style.color = isError ? '#ed8796' : '#a5adcb';
}
function getTrackLabel(trackId: string): string {
return (
ctx.state.youtubePickerPayload?.tracks.find((track) => track.id === trackId)?.label ?? ''
);
}
function renderTrackList(): void {
ctx.dom.youtubePickerTracks.replaceChildren();
const payload = ctx.state.youtubePickerPayload;
-3
View File
@@ -4,7 +4,6 @@ import type {
AiConfig,
AiFeatureConfig,
AnilistCharacterDictionaryCollapsibleSectionsConfig,
AnilistCharacterDictionaryEvictionPolicy,
AnilistCharacterDictionaryProfileScope,
AnilistConfig,
DiscordPresenceConfig,
@@ -345,9 +344,7 @@ export interface ResolvedConfig {
enabled: boolean;
accessToken: string;
characterDictionary: {
refreshTtlHours: number;
maxLoaded: number;
evictionPolicy: AnilistCharacterDictionaryEvictionPolicy;
profileScope: AnilistCharacterDictionaryProfileScope;
collapsibleSections: Required<AnilistCharacterDictionaryCollapsibleSectionsConfig>;
};
-3
View File
@@ -50,7 +50,6 @@ export interface JimakuConfig {
maxEntryResults?: number;
}
export type AnilistCharacterDictionaryEvictionPolicy = 'disable' | 'delete';
export type AnilistCharacterDictionaryProfileScope = 'all' | 'active';
export type AnilistCharacterDictionaryCollapsibleSectionKey =
| 'description'
@@ -64,9 +63,7 @@ export interface AnilistCharacterDictionaryCollapsibleSectionsConfig {
}
export interface AnilistCharacterDictionaryConfig {
refreshTtlHours?: number;
maxLoaded?: number;
evictionPolicy?: AnilistCharacterDictionaryEvictionPolicy;
profileScope?: AnilistCharacterDictionaryProfileScope;
collapsibleSections?: AnilistCharacterDictionaryCollapsibleSectionsConfig;
}
-1
View File
@@ -58,7 +58,6 @@ import type {
SubtitleSidebarPlaybackState,
SubtitleSidebarSnapshot,
SubtitleRendererStyleConfig,
SubtitleStyleConfig,
} from './subtitle';
import type {
RuntimeOptionApplyResult,
+2 -1
View File
@@ -13,7 +13,8 @@ const RECT = koffi.struct('RECT', {
Bottom: 'int',
});
const MARGINS = koffi.struct('MARGINS', {
// Registered by name for the DwmExtendFrameIntoClientArea prototype below.
koffi.struct('MARGINS', {
cxLeftWidth: 'int',
cxRightWidth: 'int',
cyTopHeight: 'int',