authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-09-17 02:37:55-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-09-17 02:37:55-07:00
logdd9528a974ba534faa8d1588f3f137fa2a281860
tree92ff2f9d00265158ae0324397e86086aeff7c67b
parent0150c6a53b409ba3bcb45645709b649cf8708354
signature Signed by PGP key B5690EEEBB952194

fix(mobile): keep screen awake during dictation (#12227)


4 files changed, 28 insertions(+), 8 deletions(-)

apps/mobile/package.json+1
......@@ -93,6 +93,7 @@
9393 "expo-image": "~57.0.3",
9494 "expo-image-manipulator": "~57.0.17",
9595 "expo-image-picker": "~57.0.14",
96 "expo-keep-awake": "~57.0.2",
9697 "expo-linking": "~57.0.8",
9798 "expo-network": "~57.0.1",
9899 "expo-notifications": "~57.0.15",
apps/mobile/src/features/voice-input/useVoiceInputController.ts+16-1
......@@ -7,8 +7,9 @@ import {
77 type RecordingStatus,
88} from "expo-audio";
99import { File } from "expo-file-system";
10import { activateKeepAwakeAsync, deactivateKeepAwake } from "expo-keep-awake";
1011import { useFocusEffect } from "@react-navigation/native";
11import { useCallback, useEffect, useRef, useState } from "react";
12import { useCallback, useEffect, useId, useRef, useState } from "react";
1213import { AppState } from "react-native";
1314import { useSharedValue } from "react-native-reanimated";
1415
......@@ -71,6 +72,8 @@ export function useVoiceInputController(input: {
7172}) {
7273 const [state, setState] = useState<VoiceInputState>(INITIAL_STATE);
7374 const [elapsedSeconds, setElapsedSeconds] = useState(0);
75 const keepAwakeId = useId();
76 const keepAwakeSessionRef = useRef(0);
7477 const elapsedSecondsRef = useRef(0);
7578 const audioLevelsRef = useRef(Array<number>(VOICE_WAVEFORM_SAMPLE_COUNT).fill(0));
7679 const audioLevels = useSharedValue(audioLevelsRef.current);
......@@ -156,6 +159,18 @@ export function useVoiceInputController(input: {
156159
157160 useEffect(() => () => controller.dispose(), [controller]);
158161
162 useEffect(() => {
163 if (state.phase !== "recording") return;
164
165 const tag = `voice-input:${keepAwakeId}:${++keepAwakeSessionRef.current}`;
166 const activation = activateKeepAwakeAsync(tag);
167 void activation.catch(() => {});
168 return () => {
169 // Release after activation settles, even if the recording ends immediately.
170 void activation.then(() => deactivateKeepAwake(tag)).catch(() => {});
171 };
172 }, [keepAwakeId, state.phase]);
173
159174 useEffect(() => {
160175 if (state.phase !== "preparing" && state.phase !== "recording") return;
161176
docs/user/composer.md+2-1
......@@ -131,7 +131,8 @@ recording started, ready for you to review and edit before sending.
131131The first use may download Apple's speech model and needs a network connection.
132132Later transcription works offline for that language. Recordings can be up to five
133133minutes long. Canceling, leaving the screen, or an audio interruption discards the
134recording and preserves your existing draft.
134recording and preserves your existing draft. While recording, the screen stays
135awake; it can sleep normally once recording stops.
135136
136137Transcription runs on your device. T3 Code deletes the temporary audio after
137138transcription or cancellation; only the message text is sent when you submit.
pnpm-lock.yaml+9-6
......@@ -373,6 +373,9 @@ importers:
373373 expo-image-picker:
374374 specifier: ~57.0.14
375375 version: 57.0.14(expo@57.0.18)
376 expo-keep-awake:
377 specifier: ~57.0.2
378 version: 57.0.2(expo@57.0.18)(react@19.2.3)
376379 expo-linking:
377380 specifier: ~57.0.8
378381 version: 57.0.8(expo@57.0.18)(react-native@0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3)
......@@ -7568,8 +7571,8 @@ packages:
75687571 expo-json-utils@57.0.1:
75697572 resolution: {integrity: sha512-cgTe1NqzQdYs/WN+3nIY5IZg8s0pb0xaTUbhYvxQDn137GbwRfHoGM2se3m3Vsl4Qu+B9G4RPEK5WJDEU2Do7g==}
75707573
7571 expo-keep-awake@57.0.1:
7572 resolution: {integrity: sha512-28lkFImeXTS+bhAjuCFV7w7tW5bXg27BJVrxv+nC/nyYa86qEa0oFeHwqol6ha5k4pdVDQgBF09GM4A1k76Ssg==}
7574 expo-keep-awake@57.0.2:
7575 resolution: {integrity: sha512-GqgH746wtJImmsbyHmCQoi7cOslKuWQBbJHXr53S35Bpf5UvxCAztvnitUEd7D0QvFN2rvkOhylbZpgZZfBLlQ==}
75737576 peerDependencies:
75747577 expo: '*'
75757578 react: '*'
......@@ -18157,12 +18160,12 @@ snapshots:
1815718160
1815818161 expo-json-utils@57.0.1: {}
1815918162
18160 expo-keep-awake@57.0.1(expo@57.0.18)(react@19.2.3):
18163 expo-keep-awake@57.0.2(expo@57.0.18)(react@19.2.3):
1816118164 dependencies:
1816218165 expo: 57.0.18(41fd11498a34454c91128cdad32f22f8)
1816318166 react: 19.2.3
1816418167
18165 expo-keep-awake@57.0.1(expo@57.0.18)(react@19.2.6):
18168 expo-keep-awake@57.0.2(expo@57.0.18)(react@19.2.6):
1816618169 dependencies:
1816718170 expo: 57.0.18(0bf40d5ad6281d8f1e92517b24812edb)
1816818171 react: 19.2.6
......@@ -18384,7 +18387,7 @@ snapshots:
1838418387 expo-constants: 57.0.16(expo@57.0.18)(react-native@0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.6)(utf-8-validate@6.0.6))
1838518388 expo-file-system: 57.0.6(expo@57.0.18)(react-native@0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.6)(utf-8-validate@6.0.6))
1838618389 expo-font: 57.0.2(expo@57.0.18)(react-native@0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.6)(utf-8-validate@6.0.6))(react@19.2.6)
18387 expo-keep-awake: 57.0.1(expo@57.0.18)(react@19.2.6)
18390 expo-keep-awake: 57.0.2(expo@57.0.18)(react@19.2.6)
1838818391 expo-modules-autolinking: 57.0.12(typescript@7.0.2)
1838918392 expo-modules-core: 57.0.14(react-native-worklets@0.10.1(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(react-native@0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.6)(utf-8-validate@6.0.6))(react@19.2.6))(react-native@0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.6)(utf-8-validate@6.0.6))(react@19.2.6)
1839018393 pretty-format: 29.7.0
......@@ -18427,7 +18430,7 @@ snapshots:
1842718430 expo-constants: 57.0.16(expo@57.0.18)(react-native@0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))
1842818431 expo-file-system: 57.0.6(expo@57.0.18)(react-native@0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))
1842918432 expo-font: 57.0.2(expo@57.0.18)(react-native@0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3)
18430 expo-keep-awake: 57.0.1(expo@57.0.18)(react@19.2.3)
18433 expo-keep-awake: 57.0.2(expo@57.0.18)(react@19.2.3)
1843118434 expo-modules-autolinking: 57.0.12(typescript@7.0.2)
1843218435 expo-modules-core: 57.0.14(react-native-worklets@0.11.4(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(react-native@0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3))(react-native@0.86.3(@babel/core@7.29.7)(@react-native/metro-config@0.86.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3)
1843318436 pretty-format: 29.7.0