diff --git a/mobile/App.js b/mobile/App.js index cf70493..8202d2c 100644 --- a/mobile/App.js +++ b/mobile/App.js @@ -2,7 +2,7 @@ // browser behind it keeps its tabs of WebViews, address bar, and the shared // suggestion engine from core/. import { useCallback, useEffect, useMemo, useRef, useState } from "react"; -import { ActivityIndicator, BackHandler, Keyboard, PanResponder, Platform, Pressable, Text, TextInput, View, useWindowDimensions } from "react-native"; +import { AccessibilityInfo, ActivityIndicator, BackHandler, Keyboard, PanResponder, Platform, Pressable, Text, TextInput, View, useWindowDimensions } from "react-native"; import { StatusBar } from "expo-status-bar"; import { SafeAreaProvider, SafeAreaView } from "react-native-safe-area-context"; @@ -17,6 +17,7 @@ import TabsSheet from "./src/components/TabsSheet"; import AddressSuggestions from "./src/components/AddressSuggestions"; import AskSheet from "./src/components/AskSheet"; import TrailHome from "./src/components/TrailHome"; +import FullTextSheet from "./src/components/FullTextSheet"; import { captureRef } from "react-native-view-shot"; import { Directory, File, Paths } from "expo-file-system"; import SettingsSheet from "./src/components/SettingsSheet"; @@ -155,6 +156,12 @@ function Browser({ services }) { } catch { return; } + if (msg.type === "capinfo" && String(msg.id).startsWith("ft:")) { + // M19: the page's DOI or PMID, found on the phone; nothing is sent. + const ids = Capture.findIds(msg); + updateTab(tabId, { doi: ids.doi || "", pmid: ids.pmid || "" }); + return; + } if (msg.type === "capinfo") { const p = pending.current.get(msg.id); if (!p) return; @@ -206,6 +213,7 @@ function Browser({ services }) { // new load, so onLoadEnd does not run: start the new page's media here. if (before && !nav.loading && before.url && nav.url !== before.url) { if (lastSelection.current.tabId === tabId) lastSelection.current = { tabId: null, url: "", text: "" }; + updateTab(tabId, { doi: "", pmid: "" }); services.history.record(nav.url, nav.title); const tab = withRule({ ...before, url: nav.url }); refs.current.get(tabId)?.injectJavaScript(autoplayCall(tab.rule.autoplay)); @@ -217,6 +225,7 @@ function Browser({ services }) { // recorded as a capture card. No screen change; a note with Undo shows. const showToast = (t) => { clearTimeout(toastTimer.current); + AccessibilityInfo.announceForAccessibility?.(t.text); // VoiceOver reads the note; TalkBack uses the live region setToast(t); toastTimer.current = setTimeout(() => setToast(null), 6000); }; @@ -278,6 +287,7 @@ function Browser({ services }) { playback.navigated(tabId); // media of the previous page will not resume view.injectJavaScript(autoplayCall(tab.rule.autoplay)); if (tab.rule.center !== false) view.injectJavaScript(CENTER_ON_TAP); + view.injectJavaScript(Capture.captureInfoCall(`ft:${tabId}`)); // DOI for the Full text button if (tabId !== activeRef.current) { if (!soundAllRef.current) view.injectJavaScript(MUTE_ALL); // only the active tab plays sound return; @@ -397,8 +407,8 @@ function Browser({ services }) { {/* Address bar, with suggestions from history and Wikipedia while typing */} -