From f64fc5723e925277012e026259030b5fbaf9e798 Mon Sep 17 00:00:00 2001 From: Huang Xin Date: Fri, 6 Feb 2026 01:18:45 +0800 Subject: [PATCH] fix(a11y): double tap to focus on current paragraph and update page info with TalkBack, closes #2276 (#3179) --- .../app/reader/components/FoliateViewer.tsx | 4 ++-- apps/readest-app/src/utils/a11y.ts | 21 ++++++++++++++++--- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/apps/readest-app/src/app/reader/components/FoliateViewer.tsx b/apps/readest-app/src/app/reader/components/FoliateViewer.tsx index 0030a6f7..6302b514 100644 --- a/apps/readest-app/src/app/reader/components/FoliateViewer.tsx +++ b/apps/readest-app/src/app/reader/components/FoliateViewer.tsx @@ -56,7 +56,7 @@ import { useBookCoverAutoSave } from '../hooks/useAutoSaveBookCover'; import { useDiscordPresence } from '@/hooks/useDiscordPresence'; import { manageSyntaxHighlighting } from '@/utils/highlightjs'; import { getViewInsets } from '@/utils/insets'; -import { removeTabIndex } from '@/utils/a11y'; +import { handleAccessibilityEvents } from '@/utils/a11y'; import { isCJKLang } from '@/utils/lang'; import { getLocale } from '@/utils/misc'; import Spinner from '@/components/Spinner'; @@ -214,7 +214,7 @@ const FoliateViewer: React.FC<{ applyThemeModeClass(detail.doc, isDarkMode); applyScrollModeClass(detail.doc, viewSettings.scrolled || false); keepTextAlignment(detail.doc); - removeTabIndex(detail.doc); + handleAccessibilityEvents(viewRef.current, detail.doc, detail.index); // Inline scripts in tauri platforms are not executed by default if (viewSettings.allowScript && isTauriAppPlatform()) { diff --git a/apps/readest-app/src/utils/a11y.ts b/apps/readest-app/src/utils/a11y.ts index d0001359..8e468136 100644 --- a/apps/readest-app/src/utils/a11y.ts +++ b/apps/readest-app/src/utils/a11y.ts @@ -1,5 +1,20 @@ -export const removeTabIndex = (document: Document) => { - document.querySelectorAll('a').forEach((a) => { - a.setAttribute('tabindex', '-1'); +import { FoliateView } from '@/types/view'; + +export const handleAccessibilityEvents = ( + view: FoliateView | null, + document: Document, + index: number, +) => { + if (!view) return; + document.querySelectorAll('a, p').forEach((el) => { + el.setAttribute('tabindex', '-1'); + el.addEventListener('focus', (e) => { + const range = document.createRange(); + range.selectNodeContents(e.target as Node); + const cfi = view.getCFI(index, range); + setTimeout(() => { + view.goTo(cfi); + }, 100); + }); }); };