feat: playbacks

This commit is contained in:
2025-12-08 14:27:27 +01:00
parent b0cf4a20ab
commit c97fb0a856
3 changed files with 129 additions and 47 deletions
+69 -3
View File
@@ -8,7 +8,13 @@ import React, {
useRef,
useState,
} from "react";
import { BackHandler, Text, TouchableOpacity, View } from "react-native";
import {
AppState,
BackHandler,
Text,
TouchableOpacity,
View,
} from "react-native";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import Svg, { Circle } from "react-native-svg";
import alert from "../../components/Alert";
@@ -56,6 +62,7 @@ const RecordPlayback = ({ route }) => {
const isPausedRef = useRef(false);
const stopRequestedRef = useRef(false);
const restartRequestedRef = useRef(false);
const interruptedRef = useRef(false); // New ref to track interruptions
const manualRestartInFlightRef = useRef(false);
const stopRequestedAtRef = useRef(0);
const activeRecordingPromiseRef = useRef(null);
@@ -107,6 +114,43 @@ const RecordPlayback = ({ route }) => {
isPausedRef.current = isPaused;
}, [isPaused]);
// Monitor AppState to detect backgrounding/interruptions
useEffect(() => {
const subscription = AppState.addEventListener("change", (nextAppState) => {
if (
nextAppState.match(/inactive|background/) &&
(isRecording || isPreparing)
) {
log("App backgrounded/interrupted during recording session");
interruptedRef.current = true;
// If we are merely preparing (countdown), we can just stop the timer
if (isPreparing) {
if (countdownTimerRef.current) {
clearInterval(countdownTimerRef.current);
countdownTimerRef.current = null;
}
setIsPreparing(false);
setCountdown(0);
}
// If recording, request stop immediately.
// The recording promise will resolve, and we will check interruptedRef there.
if (isRecording) {
stopRequestedRef.current = true;
stopRequestedAtRef.current = Date.now();
try {
cameraRef.current?.stopRecording?.();
} catch (_) {}
}
}
});
return () => {
subscription.remove();
};
}, [isRecording, isPreparing]);
const musicIndex = useMemo(() => {
const i = Number(songIndex);
return Number.isFinite(i) && i >= 0 ? i : 0;
@@ -451,6 +495,9 @@ const RecordPlayback = ({ route }) => {
try {
stopRequestedRef.current = false;
stopRequestedAtRef.current = 0;
stopRequestedRef.current = false;
stopRequestedAtRef.current = 0;
interruptedRef.current = false; // Reset interruption flag
listenedMsRef.current = 0;
incrementDoneRef.current = false;
@@ -470,7 +517,9 @@ const RecordPlayback = ({ route }) => {
});
if (activeRecordingPromiseRef.current) {
log("Waiting for previous recording to finish before starting a new one");
log(
"Waiting for previous recording to finish before starting a new one"
);
try {
await activeRecordingPromiseRef.current;
} catch (error) {
@@ -586,7 +635,8 @@ const RecordPlayback = ({ route }) => {
if (!player) return;
if (isPausedRef.current) return;
if (stopRequestedRef.current) {
const sinceLastRequest = Date.now() - (stopRequestedAtRef.current || 0);
const sinceLastRequest =
Date.now() - (stopRequestedAtRef.current || 0);
if (sinceLastRequest >= 1200) {
stopRequestedAtRef.current = Date.now();
try {
@@ -657,6 +707,22 @@ const RecordPlayback = ({ route }) => {
progressLogRef.current = { bucket: -1, lastPos: -1, lastDur: -1 };
const exitRequested = exitRequestedRef.current;
const shouldRestart = restartRequestedRef.current;
const wasInterrupted = interruptedRef.current;
if (wasInterrupted) {
log(
"Recording was interrupted (background/inactive), discarding and exiting"
);
exitRequestedRef.current = false;
restartRequestedRef.current = false;
manualRestartInFlightRef.current = false;
interruptedRef.current = false;
await discardRecordingFile(video?.uri, "interrupted");
try {
goBack();
} catch (_) {}
return;
}
if (exitRequested) {
exitRequestedRef.current = false;