diff --git a/package-lock.json b/package-lock.json index baef732..6ead025 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,7 @@ "expo-document-picker": "~13.0.0", "expo-file-system": "~18.0.0", "expo-font": "~13.0.4", + "expo-keep-awake": "~14.0.3", "expo-localization": "~16.0.1", "expo-status-bar": "~2.0.0", "expo-updates": "~0.27.5", @@ -6174,6 +6175,16 @@ "resolved": "https://registry.npmjs.org/expo-json-utils/-/expo-json-utils-0.14.0.tgz", "integrity": "sha512-xjGfK9dL0B1wLnOqNkX0jM9p48Y0I5xEPzHude28LY67UmamUyAACkqhZGaPClyPNfdzczk7Ej6WaRMT3HfXvw==" }, + "node_modules/expo-keep-awake": { + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-14.0.3.tgz", + "integrity": "sha512-6Jh94G6NvTZfuLnm2vwIpKe3GdOiVBuISl7FI8GqN0/9UOg9E0WXXp5cDcfAG8bn80RfgLJS8P7EPUGTZyOvhg==", + "license": "MIT", + "peerDependencies": { + "expo": "*", + "react": "*" + } + }, "node_modules/expo-localization": { "version": "16.0.1", "resolved": "https://registry.npmjs.org/expo-localization/-/expo-localization-16.0.1.tgz", @@ -6312,15 +6323,6 @@ "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.0.tgz", "integrity": "sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg==" }, - "node_modules/expo/node_modules/expo-keep-awake": { - "version": "14.0.3", - "resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-14.0.3.tgz", - "integrity": "sha512-6Jh94G6NvTZfuLnm2vwIpKe3GdOiVBuISl7FI8GqN0/9UOg9E0WXXp5cDcfAG8bn80RfgLJS8P7EPUGTZyOvhg==", - "peerDependencies": { - "expo": "*", - "react": "*" - } - }, "node_modules/exponential-backoff": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.3.tgz", diff --git a/package.json b/package.json index 64760c7..f481653 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "expo-document-picker": "~13.0.0", "expo-file-system": "~18.0.0", "expo-font": "~13.0.4", + "expo-keep-awake": "~14.0.3", "expo-localization": "~16.0.1", "expo-status-bar": "~2.0.0", "expo-updates": "~0.27.5", diff --git a/src/screens/ReaderScreen.tsx b/src/screens/ReaderScreen.tsx index 5717938..e99c841 100644 --- a/src/screens/ReaderScreen.tsx +++ b/src/screens/ReaderScreen.tsx @@ -19,6 +19,10 @@ import { TouchableWithoutFeedback, View, } from "react-native"; +import { + activateKeepAwakeAsync, + deactivateKeepAwake, +} from "expo-keep-awake"; import type { NativeStackScreenProps } from "@react-navigation/native-stack"; import type { RootStackParamList } from "../../App"; import { firstIndexOfPage, WordEntry } from "../utils/pdfParser"; @@ -35,6 +39,8 @@ const WebView = type Props = NativeStackScreenProps; +const READER_KEEP_AWAKE_TAG = "reader-screen"; + const CONTEXT_LINES = 5; const WORDS_PER_LINE_EST = 8; // rough estimate for advance threshold const CONTEXT_WINDOW = WORDS_PER_LINE_EST * CONTEXT_LINES; // ~40 words fills 5 lines @@ -188,6 +194,7 @@ export default function ReaderScreen({ route, navigation }: Props) { const [pageInput, setPageInput] = useState(""); const [flowReading, setFlowReading] = useState(true); + const [keepScreenAwake, setKeepScreenAwake] = useState(false); const indexRef = useRef(currentIndex); const wpmRef = useRef(wpm); @@ -205,6 +212,17 @@ export default function ReaderScreen({ route, navigation }: Props) { flowReadingRef.current = flowReading; }, [flowReading]); + useEffect(() => { + if (!keepScreenAwake) { + void deactivateKeepAwake(READER_KEEP_AWAKE_TAG); + return; + } + void activateKeepAwakeAsync(READER_KEEP_AWAKE_TAG); + return () => { + void deactivateKeepAwake(READER_KEEP_AWAKE_TAG); + }; + }, [keepScreenAwake]); + // Called by ContextDisplay when the highlighted word's onLayout reports it's past // the visible container. Advances the window so the current word is near the top. const WINDOW_OVERLAP = 3; @@ -569,6 +587,19 @@ export default function ReaderScreen({ route, navigation }: Props) { {font === "opendyslexic" ? "OpenDyslexic" : "Dyslexic"} + setKeepScreenAwake((v) => !v)} + > + + {keepScreenAwake ? t(lang, "keepAwakeOn") : t(lang, "keepAwakeOff")} + + @@ -850,6 +881,8 @@ function makeStyles(c: ThemeColors, SERIF: string = 'Georgia') { }, speedToggles: { flexDirection: "row", + flexWrap: "wrap", + justifyContent: "center", alignItems: "center", gap: 10, }, diff --git a/src/utils/i18n.ts b/src/utils/i18n.ts index cc7257b..2e6b9ac 100644 --- a/src/utils/i18n.ts +++ b/src/utils/i18n.ts @@ -50,6 +50,8 @@ const strings = { lookUpWord: "look up word", flowOn: "flow on", flowOff: "flow off", + keepAwakeOn: "Awake", + keepAwakeOff: "Stay awake", back: "\u2190 back", backBtn: "\u2190 Back", jumpToPage: "Jump to page", @@ -109,6 +111,8 @@ const strings = { lookUpWord: "buscar palabra", flowOn: "flujo activado", flowOff: "flujo desactivado", + keepAwakeOn: "Activa", + keepAwakeOff: "No apagar", back: "\u2190 atr\u00e1s", backBtn: "\u2190 Volver", jumpToPage: "Ir a p\u00e1gina",