diff --git a/app/home.tsx b/app/home.tsx index 0c73cdb..c09f39e 100644 --- a/app/home.tsx +++ b/app/home.tsx @@ -1,43 +1,219 @@ -import { useState } from 'react'; -import { Text, TextInput, View } from 'react-native'; +//npx expo install expo-location expo-camera -export default function Home() { - const users = [ - "alice", - "bob", - "charlie" - ] +import { + CameraView, + useCameraPermissions, +} from "expo-camera"; + +import React, { useRef, useState } from "react"; +import { + ActivityIndicator, + Alert, + Image, + Linking, + StyleSheet, + Text, + TouchableOpacity, + View, +} from "react-native"; - const variable = true; +export default function App() { + const cameraRef = useRef(null); - const [nom, setNom] = useState(''); + const [statusText, setStatusText] = useState("Permission non demandée"); + const [loading, setLoading] = useState(false); + const [cameraVisible, setCameraVisible] = useState(false); + const [photoUri, setPhotoUri] = useState(null); - return ( - - {variable && Test} - {variable ? Vrai : Faux} - {users.map(user => { - return {user} - })} + const [permission, requestPermission] = + useCameraPermissions(); - + const openSettings = () => { + Linking.openSettings(); + }; - - Saisie + bouton "Valider" - + const openCamera = async () => { + try { + setLoading(true); + setStatusText("Demande de permission caméra..."); - Valeur validée : {nom || '(vide)'} + const result = await requestPermission(); - + if (!result.granted) { + if (result.canAskAgain === false) { + Alert.alert( + "Permission bloquée", + "La caméra doit être activée dans les paramètres.", + [ + { text: "Annuler", style: "cancel" }, + { text: "Paramètres", onPress: openSettings }, + ] + ); + } else { + Alert.alert( + "Permission refusée", + "Impossible d'utiliser la caméra." + ); + } - + setStatusText("Permission caméra refusée"); + return; + } - ); + setPhotoUri(null); + setCameraVisible(true); + setStatusText("Caméra autorisée"); + } catch (e) { + setStatusText("Erreur lors de la demande caméra"); + } finally { + setLoading(false); + } + }; + + const takePhoto = async () => { + try { + if (!cameraRef.current) { + Alert.alert("Erreur", "La caméra n'est pas encore prête."); + return; + } + + setLoading(true); + setStatusText("Prise de photo..."); + + const photo = await cameraRef.current.takePictureAsync(); + + if (!photo || !photo.uri) { + Alert.alert("Erreur", "Aucune photo obtenue."); + return; + } + + setPhotoUri(photo.uri); + setCameraVisible(false); + setStatusText("Photo prise"); + } catch (e) { + setStatusText("Erreur lors de la prise de photo"); + } finally { + setLoading(false); + } + }; + + const closeCamera = () => { + setCameraVisible(false); + setStatusText("Caméra fermée"); + }; + + if (cameraVisible) { + return ( + + + + + + Fermer + + + + Prendre une photo + + + + ); + } + + return ( + + TP permissions Expo + + + Ouvrir la caméra + + + {loading ? : null} + + {statusText} + + {photoUri ? ( + + Photo prise : + + + ) : null} + + ); } + +const styles = StyleSheet.create({ + container: { + flex: 1, + justifyContent: "center", + padding: 20, + backgroundColor: "#fff", + }, + title: { + fontSize: 24, + fontWeight: "bold", + marginBottom: 20, + textAlign: "center", + }, + subtitle: { + fontWeight: "bold", + marginBottom: 10, + }, + button: { + backgroundColor: "#2563eb", + padding: 14, + borderRadius: 8, + marginBottom: 12, + }, + secondaryButton: { + backgroundColor: "#666", + padding: 14, + borderRadius: 8, + marginBottom: 12, + }, + buttonText: { + color: "#fff", + textAlign: "center", + fontWeight: "bold", + }, + status: { + textAlign: "center", + marginVertical: 20, + }, + box: { + padding: 16, + borderWidth: 1, + borderColor: "#ccc", + borderRadius: 8, + marginBottom: 20, + }, + photoBox: { + marginTop: 10, + alignItems: "center", + }, + photo: { + width: 250, + height: 250, + borderRadius: 8, + borderWidth: 1, + borderColor: "#ccc", + }, + cameraContainer: { + flex: 1, + backgroundColor: "#000", + }, + camera: { + flex: 1, + }, + cameraControls: { + position: "absolute", + bottom: 40, + left: 20, + right: 20, + }, +}); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index d0e66ff..b3dd863 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,15 +9,19 @@ "version": "1.0.0", "dependencies": { "@expo/vector-icons": "^15.0.3", + "@react-native-async-storage/async-storage": "2.2.0", "@react-navigation/bottom-tabs": "^7.4.0", "@react-navigation/elements": "^2.6.3", "@react-navigation/native": "^7.1.8", "expo": "~54.0.33", + "expo-camera": "~17.0.10", "expo-constants": "~18.0.13", "expo-font": "~14.0.11", "expo-haptics": "~15.0.8", "expo-image": "~3.0.11", + "expo-image-picker": "~17.0.10", "expo-linking": "~8.0.11", + "expo-location": "~19.0.8", "expo-router": "~6.0.23", "expo-splash-screen": "~31.0.13", "expo-status-bar": "~3.0.9", @@ -2756,6 +2760,18 @@ } } }, + "node_modules/@react-native-async-storage/async-storage": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@react-native-async-storage/async-storage/-/async-storage-2.2.0.tgz", + "integrity": "sha512-gvRvjR5JAaUZF8tv2Kcq/Gbt3JHwbKFYfmb445rhOj6NUMx3qPLixmDx5pZAyb9at1bYvJ4/eTUipU5aki45xw==", + "license": "MIT", + "dependencies": { + "merge-options": "^3.0.4" + }, + "peerDependencies": { + "react-native": "^0.0.0-0 || >=0.65 <1.0" + } + }, "node_modules/@react-native/assets-registry": { "version": "0.81.5", "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.81.5.tgz", @@ -6062,6 +6078,26 @@ "react-native": "*" } }, + "node_modules/expo-camera": { + "version": "17.0.10", + "resolved": "https://registry.npmjs.org/expo-camera/-/expo-camera-17.0.10.tgz", + "integrity": "sha512-w1RBw83mAGVk4BPPwNrCZyFop0VLiVSRE3c2V9onWbdFwonpRhzmB4drygG8YOUTl1H3wQvALJHyMPTbgsK1Jg==", + "license": "MIT", + "dependencies": { + "invariant": "^2.2.4" + }, + "peerDependencies": { + "expo": "*", + "react": "*", + "react-native": "*", + "react-native-web": "*" + }, + "peerDependenciesMeta": { + "react-native-web": { + "optional": true + } + } + }, "node_modules/expo-constants": { "version": "18.0.13", "resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-18.0.13.tgz", @@ -6126,6 +6162,27 @@ } } }, + "node_modules/expo-image-loader": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/expo-image-loader/-/expo-image-loader-6.0.0.tgz", + "integrity": "sha512-nKs/xnOGw6ACb4g26xceBD57FKLFkSwEUTDXEDF3Gtcu3MqF3ZIYd3YM+sSb1/z9AKV1dYT7rMSGVNgsveXLIQ==", + "license": "MIT", + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-image-picker": { + "version": "17.0.10", + "resolved": "https://registry.npmjs.org/expo-image-picker/-/expo-image-picker-17.0.10.tgz", + "integrity": "sha512-a2xrowp2trmvXyUWgX3O6Q2rZaa2C59AqivKI7+bm+wLvMfTEbZgldLX4rEJJhM8xtmEDTNU+lzjtObwzBRGaw==", + "license": "MIT", + "dependencies": { + "expo-image-loader": "~6.0.0" + }, + "peerDependencies": { + "expo": "*" + } + }, "node_modules/expo-keep-awake": { "version": "15.0.8", "resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-15.0.8.tgz", @@ -6150,6 +6207,15 @@ "react-native": "*" } }, + "node_modules/expo-location": { + "version": "19.0.8", + "resolved": "https://registry.npmjs.org/expo-location/-/expo-location-19.0.8.tgz", + "integrity": "sha512-H/FI75VuJ1coodJbbMu82pf+Zjess8X8Xkiv9Bv58ZgPKS/2ztjC1YO1/XMcGz7+s9DrbLuMIw22dFuP4HqneA==", + "license": "MIT", + "peerDependencies": { + "expo": "*" + } + }, "node_modules/expo-modules-autolinking": { "version": "3.0.24", "resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-3.0.24.tgz", @@ -7829,6 +7895,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/is-regex": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", @@ -8807,6 +8882,18 @@ "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==", "license": "MIT" }, + "node_modules/merge-options": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/merge-options/-/merge-options-3.0.4.tgz", + "integrity": "sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==", + "license": "MIT", + "dependencies": { + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", diff --git a/package.json b/package.json index 7d7170b..b07cf15 100644 --- a/package.json +++ b/package.json @@ -12,15 +12,19 @@ }, "dependencies": { "@expo/vector-icons": "^15.0.3", + "@react-native-async-storage/async-storage": "2.2.0", "@react-navigation/bottom-tabs": "^7.4.0", "@react-navigation/elements": "^2.6.3", "@react-navigation/native": "^7.1.8", "expo": "~54.0.33", + "expo-camera": "~17.0.10", "expo-constants": "~18.0.13", "expo-font": "~14.0.11", "expo-haptics": "~15.0.8", "expo-image": "~3.0.11", + "expo-image-picker": "~17.0.10", "expo-linking": "~8.0.11", + "expo-location": "~19.0.8", "expo-router": "~6.0.23", "expo-splash-screen": "~31.0.13", "expo-status-bar": "~3.0.9", @@ -31,11 +35,11 @@ "react-dom": "19.1.0", "react-native": "0.81.5", "react-native-gesture-handler": "~2.28.0", - "react-native-worklets": "0.5.1", "react-native-reanimated": "~4.1.1", "react-native-safe-area-context": "~5.6.0", "react-native-screens": "~4.16.0", - "react-native-web": "~0.21.0" + "react-native-web": "~0.21.0", + "react-native-worklets": "0.5.1" }, "devDependencies": { "@types/react": "~19.1.0", diff --git a/tsconfig.json b/tsconfig.json index 909e901..4acaa77 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,7 @@ { "extends": "expo/tsconfig.base", "compilerOptions": { - "strict": true, + "strict": false, "paths": { "@/*": [ "./*"