mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-08-17 00:18:41 -07:00
fix(anki): keep media timing review keyboard-focused
- Route modal keydown events before later modal handlers - Restore focus and preserve visible focus styling
This commit is contained in:
@@ -452,6 +452,7 @@ function createKeyboardHandlerHarness() {
|
||||
const testGlobals = installKeyboardTestGlobals();
|
||||
const subtitleRootClassList = createClassList();
|
||||
const subtitleContainerClassList = createClassList();
|
||||
let mediaTimingReviewKeydownCount = 0;
|
||||
let controllerSelectKeydownCount = 0;
|
||||
let openControllerSelectCount = 0;
|
||||
let openControllerDebugCount = 0;
|
||||
@@ -494,7 +495,10 @@ function createKeyboardHandlerHarness() {
|
||||
handleKikuKeydown: () => false,
|
||||
handleJimakuKeydown: () => false,
|
||||
handleTsukihimeKeydown: () => false,
|
||||
handleMediaTimingReviewKeydown: () => false,
|
||||
handleMediaTimingReviewKeydown: () => {
|
||||
mediaTimingReviewKeydownCount += 1;
|
||||
return false;
|
||||
},
|
||||
handleControllerSelectKeydown: () => {
|
||||
controllerSelectKeydownCount += 1;
|
||||
return true;
|
||||
@@ -524,6 +528,7 @@ function createKeyboardHandlerHarness() {
|
||||
ctx,
|
||||
handlers,
|
||||
testGlobals,
|
||||
mediaTimingReviewKeydownCount: () => mediaTimingReviewKeydownCount,
|
||||
controllerSelectKeydownCount: () => controllerSelectKeydownCount,
|
||||
openControllerSelectCount: () => openControllerSelectCount,
|
||||
openControllerDebugCount: () => openControllerDebugCount,
|
||||
@@ -1368,6 +1373,29 @@ test('keyboard mode: controller select modal handles arrow keys before yomitan p
|
||||
}
|
||||
});
|
||||
|
||||
test('media timing review modal handles keys before later modal handlers', async () => {
|
||||
const {
|
||||
ctx,
|
||||
testGlobals,
|
||||
handlers,
|
||||
mediaTimingReviewKeydownCount,
|
||||
controllerSelectKeydownCount,
|
||||
} = createKeyboardHandlerHarness();
|
||||
|
||||
try {
|
||||
await handlers.setupMpvInputForwarding();
|
||||
ctx.state.mediaTimingReviewModalOpen = true;
|
||||
ctx.state.controllerSelectModalOpen = true;
|
||||
|
||||
testGlobals.dispatchKeydown({ key: 'ArrowDown', code: 'ArrowDown' });
|
||||
|
||||
assert.equal(mediaTimingReviewKeydownCount(), 1);
|
||||
assert.equal(controllerSelectKeydownCount(), 0);
|
||||
} finally {
|
||||
testGlobals.restore();
|
||||
}
|
||||
});
|
||||
|
||||
test('keyboard mode: playlist browser modal handles arrow keys before yomitan popup', async () => {
|
||||
const { ctx, testGlobals, handlers, playlistBrowserKeydownCount } =
|
||||
createKeyboardHandlerHarness();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { MediaTimingReviewDecision, MediaTimingReviewOpenPayload } from '../../types/anki';
|
||||
import type { ModalStateReader, RendererContext } from '../context';
|
||||
import { createModalFocusGuard } from './modal-focus-guard';
|
||||
|
||||
const MINIMUM_CLIP_SECONDS = 0.1;
|
||||
const FINE_ADJUST_SECONDS = 0.1;
|
||||
@@ -139,6 +140,17 @@ export function createMediaTimingReviewModal(
|
||||
trackWidth: number;
|
||||
grabOffset: number;
|
||||
} | null = null;
|
||||
|
||||
const focus = createModalFocusGuard({
|
||||
isOpen: () => ctx.state.mediaTimingReviewModalOpen,
|
||||
getModalRoot: () => ctx.dom.mediaTimingReviewModal,
|
||||
getPreferredFocusTargets: () => [
|
||||
ctx.dom.mediaTimingReviewStartHandle,
|
||||
ctx.dom.mediaTimingReviewCancelBack,
|
||||
],
|
||||
getFallbackFocusTarget: () => ctx.dom.mediaTimingReviewCancel,
|
||||
isModalLayer: ctx.platform.isModalLayer,
|
||||
});
|
||||
const previewRequest = createMediaTimingPreviewRequestGuard();
|
||||
|
||||
function setStatus(message: string, isError = false): void {
|
||||
@@ -453,6 +465,7 @@ export function createMediaTimingReviewModal(
|
||||
ctx.state.mediaTimingReviewModalOpen = false;
|
||||
ctx.dom.mediaTimingReviewModal.classList.add('hidden');
|
||||
ctx.dom.mediaTimingReviewModal.setAttribute('aria-hidden', 'true');
|
||||
focus.detach();
|
||||
window.electronAPI.notifyOverlayModalClosed('media-timing-review');
|
||||
options.syncSettingsModalSubtitleSuppression();
|
||||
payload = null;
|
||||
@@ -566,7 +579,10 @@ export function createMediaTimingReviewModal(
|
||||
ctx.dom.mediaTimingReviewModal.classList.remove('hidden');
|
||||
ctx.dom.mediaTimingReviewModal.setAttribute('aria-hidden', 'false');
|
||||
window.electronAPI.notifyOverlayModalOpened('media-timing-review');
|
||||
ctx.dom.mediaTimingReviewStartHandle.focus();
|
||||
focus.attach();
|
||||
focus.requestOverlayFocus();
|
||||
window.focus();
|
||||
focus.enforceModalFocus();
|
||||
queueWaveformLoad();
|
||||
}
|
||||
|
||||
|
||||
@@ -1711,7 +1711,7 @@ body:focus-visible,
|
||||
}
|
||||
|
||||
.media-timing-review-handle:focus-visible {
|
||||
outline: none;
|
||||
outline: 2px solid transparent;
|
||||
box-shadow:
|
||||
inset 0 0 0 2px var(--ctp-yellow),
|
||||
0 0 16px color-mix(in srgb, var(--ctp-yellow) 55%, transparent);
|
||||
|
||||
Reference in New Issue
Block a user