diff --git a/app.config.js b/app.config.js index e5b1170..8efab0c 100644 --- a/app.config.js +++ b/app.config.js @@ -22,7 +22,10 @@ export default { "foregroundImage": "./assets/images/adaptive-icon.png", "backgroundColor": "#ffffff" }, - "package": "com.torpenn.boxons" + "package": "com.torpenn.boxons", + "permissions": [ + "FOREGROUND_SERVICE" + ] }, "web": { "bundler": "metro", diff --git a/app/timer.tsx b/app/timer.tsx index 2edf87a..a69ba20 100644 --- a/app/timer.tsx +++ b/app/timer.tsx @@ -10,6 +10,7 @@ import { Audio } from 'expo-av'; import { Sound } from 'expo-av/build/Audio'; import { activateKeepAwakeAsync, deactivateKeepAwake } from 'expo-keep-awake'; import { loadUserSettings } from '@/components/shared/business/AsyncStorage'; +import BackgroundTimer from 'react-native-background-timer'; interface TimerProps { reps: number; @@ -57,36 +58,24 @@ export default function Timer() { }, [navigation]); useEffect(() => { - let timer: NodeJS.Timeout; + let timerId: number | null = null; if (isRunning && timeLeft > 0) { - timer = setTimeout(() => { - setTimeLeft(timeLeft - 1); - }, 1000); + // Utilisation de BackgroundTimer pour gérer le timer même en arrière-plan + timerId = BackgroundTimer.setInterval(() => { + setTimeLeft((prevTime) => prevTime - 1); + }, 1000); // Timer d'une seconde } else if (isRunning && timeLeft === 0) { - if (currentRep < reps) { - if (isWorkPhase) { - // If the work phase is over, move on to the rest phase - playSound() - setIsWorkPhase(false); - setTimeLeft(restTime); - } else { - // If the rest phase is complete, move on to the next work phase - playSound() - setIsWorkPhase(true); - setTimeLeft(workTime); - setCurrentRep(currentRep + 1); - } - } else { - // Done - playSound(); - setIsRunning(false); - setIsFinish(true); - } + nextRep(); // Passe à la répétition suivante } - return () => clearTimeout(timer); - }, [isRunning, timeLeft, currentRep, isWorkPhase, reps, workTime, restTime]); + return () => { + // Nettoyage du timer lorsqu'il est arrêté ou que le composant est démonté + if (timerId !== null) { + BackgroundTimer.clearInterval(timerId); + } + }; + }, [isRunning, timeLeft]); const handleStart = () => { setCurrentRep(1); @@ -126,14 +115,17 @@ export default function Timer() { const nextRep = () => { if (currentRep < reps) { if (isWorkPhase) { + playSound(); setIsWorkPhase(false); setTimeLeft(restTime); } else { + playSound(); setIsWorkPhase(true); setTimeLeft(workTime); setCurrentRep((prevRep) => prevRep + 1); } } else { + playSound(); setIsFinish(true); setIsRunning(false); } diff --git a/package-lock.json b/package-lock.json index 904494d..2eb1594 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ "@testing-library/react-native": "^12.7.2", "expo": "~51.0.37", "expo-av": "~14.0.7", + "expo-dev-client": "~4.0.28", "expo-font": "~12.0.9", "expo-keep-awake": "~13.0.2", "expo-linking": "~6.3.1", @@ -30,6 +31,7 @@ "react": "18.2.0", "react-dom": "18.2.0", "react-native": "0.74.5", + "react-native-background-timer": "^2.4.1", "react-native-dropdown-picker": "^5.4.6", "react-native-linear-gradient": "^2.8.3", "react-native-reanimated": "~3.10.1", @@ -42,6 +44,7 @@ "@babel/core": "^7.20.0", "@testing-library/jest-native": "^5.4.3", "@types/react": "~18.2.45", + "@types/react-native-background-timer": "^2.0.2", "@typescript-eslint/eslint-plugin": "^7.2.0", "@typescript-eslint/parser": "^7.2.0", "dotenv": "^16.4.5", @@ -7957,6 +7960,13 @@ "csstype": "^3.0.2" } }, + "node_modules/@types/react-native-background-timer": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@types/react-native-background-timer/-/react-native-background-timer-2.0.2.tgz", + "integrity": "sha512-cMAep0M5yqUHjiiRPvGiviqiJYdI45KSjbI5ufsIFSQGFwHwrHJC/8yawNhy0G3Gix6fufWLsEj6jC5niUNHiQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/semver": { "version": "7.5.8", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", @@ -12019,6 +12029,100 @@ "expo": "*" } }, + "node_modules/expo-dev-client": { + "version": "4.0.28", + "resolved": "https://registry.npmjs.org/expo-dev-client/-/expo-dev-client-4.0.28.tgz", + "integrity": "sha512-wz5G4vY3Gbk5GuQTyijdqY4Hwr/NDt5OUTErbOu1vd4XRIAsI+8IkK5hsBUhGmqrdkYnP5NxxOxC/soFzX/9+w==", + "license": "MIT", + "dependencies": { + "expo-dev-launcher": "4.0.28", + "expo-dev-menu": "5.0.22", + "expo-dev-menu-interface": "1.8.3", + "expo-manifests": "~0.14.0", + "expo-updates-interface": "~0.16.2" + }, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-dev-launcher": { + "version": "4.0.28", + "resolved": "https://registry.npmjs.org/expo-dev-launcher/-/expo-dev-launcher-4.0.28.tgz", + "integrity": "sha512-goE7jcaGVA2zu4gV3/hQ9RXqGhUZZAu339VYNLbwPdaNCzFaG6A8MZHg18gytCUnZ5QkRJsYi4q/8YcwUCASlQ==", + "license": "MIT", + "dependencies": { + "ajv": "8.11.0", + "expo-dev-menu": "5.0.22", + "expo-manifests": "~0.14.0", + "resolve-from": "^5.0.0", + "semver": "^7.6.0" + }, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-dev-launcher/node_modules/ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/expo-dev-launcher/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/expo-dev-menu": { + "version": "5.0.22", + "resolved": "https://registry.npmjs.org/expo-dev-menu/-/expo-dev-menu-5.0.22.tgz", + "integrity": "sha512-VzpdQReAtjbI1qIuwOf0sUzf91HsfGThojgJD9Ez0eca12qY5tTGYzHa1EM9V+zIcNuNZ7+A8bHJJdmZ4zvU6g==", + "license": "MIT", + "dependencies": { + "expo-dev-menu-interface": "1.8.3", + "semver": "^7.5.4" + }, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-dev-menu-interface": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/expo-dev-menu-interface/-/expo-dev-menu-interface-1.8.3.tgz", + "integrity": "sha512-QM0LRozeFT5Ek0N7XpV93M+HMdEKRLEOXn0aW5M3uoUlnqC1+PLtF3HMy3k3hMKTTE/kJ1y1Z7akH07T0lunCQ==", + "license": "MIT", + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-dev-menu/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/expo-eas-client": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/expo-eas-client/-/expo-eas-client-0.12.0.tgz", @@ -19878,6 +19982,15 @@ } } }, + "node_modules/react-native-background-timer": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/react-native-background-timer/-/react-native-background-timer-2.4.1.tgz", + "integrity": "sha512-TE4Kiy7jUyv+hugxDxitzu38sW1NqjCk4uE5IgU2WevLv7sZacaBc6PZKOShNRPGirLl1NWkaG3LDEkdb9Um5g==", + "license": "MIT", + "peerDependencies": { + "react-native": ">=0.47.0" + } + }, "node_modules/react-native-dropdown-picker": { "version": "5.4.6", "resolved": "https://registry.npmjs.org/react-native-dropdown-picker/-/react-native-dropdown-picker-5.4.6.tgz", @@ -22401,7 +22514,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" diff --git a/package.json b/package.json index 0f35bbd..846f418 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "@testing-library/react-native": "^12.7.2", "expo": "~51.0.37", "expo-av": "~14.0.7", + "expo-dev-client": "~4.0.28", "expo-font": "~12.0.9", "expo-keep-awake": "~13.0.2", "expo-linking": "~6.3.1", @@ -46,6 +47,7 @@ "react": "18.2.0", "react-dom": "18.2.0", "react-native": "0.74.5", + "react-native-background-timer": "^2.4.1", "react-native-dropdown-picker": "^5.4.6", "react-native-linear-gradient": "^2.8.3", "react-native-reanimated": "~3.10.1", @@ -58,6 +60,7 @@ "@babel/core": "^7.20.0", "@testing-library/jest-native": "^5.4.3", "@types/react": "~18.2.45", + "@types/react-native-background-timer": "^2.0.2", "@typescript-eslint/eslint-plugin": "^7.2.0", "@typescript-eslint/parser": "^7.2.0", "dotenv": "^16.4.5",