fix(overlay): gate the maturity legend on known-word highlighting

The session help color legend showed the four tier rows whenever
maturityEnabled was on, even with known-word highlighting off, where no
token is ever tinted. Extract isKnownWordMaturityLegendEnabled so the
legend requires both toggles, matching getKnownWordMaturityEnabled.
This commit is contained in:
2026-07-26 01:33:04 -07:00
parent 38060e0ead
commit 75566a49bf
2 changed files with 45 additions and 5 deletions
+30
View File
@@ -9,7 +9,9 @@ import {
createSessionHelpModal, createSessionHelpModal,
describeSessionHelpCommand, describeSessionHelpCommand,
formatSessionHelpKeybinding, formatSessionHelpKeybinding,
isKnownWordMaturityLegendEnabled,
} from './session-help.js'; } from './session-help.js';
import type { RuntimeOptionId, RuntimeOptionState } from '../../types/runtime-options.js';
test('session help describes sub-seek commands as subtitle-line navigation', () => { test('session help describes sub-seek commands as subtitle-line navigation', () => {
assert.equal(describeSessionHelpCommand(['sub-seek', 1]), 'Jump to next subtitle'); assert.equal(describeSessionHelpCommand(['sub-seek', 1]), 'Jump to next subtitle');
@@ -104,6 +106,34 @@ test('session help builds rows from canonical session bindings and fixed overlay
assert.ok(rows.some((row) => row.shortcut === 'Y then D' && row.action === 'Toggle DevTools')); assert.ok(rows.some((row) => row.shortcut === 'Y then D' && row.action === 'Toggle DevTools'));
}); });
function booleanRuntimeOption(id: RuntimeOptionId, value: boolean): RuntimeOptionState {
return {
id,
label: id,
scope: 'subtitle',
valueType: 'boolean',
value,
allowedValues: [true, false],
requiresRestart: false,
};
}
test('maturity legend requires both known-word highlighting and maturity coloring', () => {
const highlightOn = booleanRuntimeOption('subtitle.annotation.knownWords.highlightEnabled', true);
const highlightOff = booleanRuntimeOption(
'subtitle.annotation.knownWords.highlightEnabled',
false,
);
const maturityOn = booleanRuntimeOption('subtitle.annotation.knownWords.maturityEnabled', true);
const maturityOff = booleanRuntimeOption('subtitle.annotation.knownWords.maturityEnabled', false);
assert.equal(isKnownWordMaturityLegendEnabled([highlightOn, maturityOn]), true);
assert.equal(isKnownWordMaturityLegendEnabled([highlightOff, maturityOn]), false);
assert.equal(isKnownWordMaturityLegendEnabled([highlightOn, maturityOff]), false);
assert.equal(isKnownWordMaturityLegendEnabled([maturityOn]), false);
assert.equal(isKnownWordMaturityLegendEnabled([]), false);
});
function colorLegendRows(input: Parameters<typeof buildSessionHelpSections>[0]) { function colorLegendRows(input: Parameters<typeof buildSessionHelpSections>[0]) {
const sections = buildSessionHelpSections(input); const sections = buildSessionHelpSections(input);
return sections.find((section) => section.title === 'Color legend')?.rows ?? []; return sections.find((section) => section.title === 'Color legend')?.rows ?? [];
+15 -5
View File
@@ -1,4 +1,5 @@
import type { ModalStateReader, RendererContext } from '../context'; import type { ModalStateReader, RendererContext } from '../context';
import type { RuntimeOptionId, RuntimeOptionState } from '../../types/runtime-options';
import { import {
buildSessionHelpSections, buildSessionHelpSections,
type SessionHelpSection, type SessionHelpSection,
@@ -19,6 +20,19 @@ type SessionHelpBindingInfo = {
fallbackUnavailable: boolean; fallbackUnavailable: boolean;
}; };
/**
* Tiers only render when known-word highlighting is also on, matching
* getKnownWordMaturityEnabled in anki-integration/known-word-maturity.
*/
export function isKnownWordMaturityLegendEnabled(runtimeOptions: RuntimeOptionState[]): boolean {
const isOn = (id: RuntimeOptionId): boolean =>
runtimeOptions.some((option) => option.id === id && option.value === true);
return (
isOn('subtitle.annotation.knownWords.highlightEnabled') &&
isOn('subtitle.annotation.knownWords.maturityEnabled')
);
}
/** /**
* Maturity coloring is a live runtime toggle, so the color legend reads it from * Maturity coloring is a live runtime toggle, so the color legend reads it from
* runtime options instead of the resolved subtitle style. A missing or failing * runtime options instead of the resolved subtitle style. A missing or failing
@@ -26,11 +40,7 @@ type SessionHelpBindingInfo = {
*/ */
async function readKnownWordMaturityEnabled(): Promise<boolean> { async function readKnownWordMaturityEnabled(): Promise<boolean> {
try { try {
const runtimeOptions = await window.electronAPI.getRuntimeOptions(); return isKnownWordMaturityLegendEnabled(await window.electronAPI.getRuntimeOptions());
return runtimeOptions.some(
(option) =>
option.id === 'subtitle.annotation.knownWords.maturityEnabled' && option.value === true,
);
} catch { } catch {
return false; return false;
} }