Modify folder structure

This commit is contained in:
Sebastien Riviere
2026-02-18 00:45:38 +01:00
parent 2dfddd86e6
commit 4d8dcd241c
56 changed files with 27 additions and 27 deletions

View File

@@ -0,0 +1,27 @@
// React
import { useCallback } from "react";
// Services
import { emitSendPosition, emitCapture } from "../services/socketEmitter";
export const useGame = () => {
const sendCurrentPosition = useCallback(() => {
emitSendPosition();
}, []);
const capture = useCallback((captureCode) => {
return new Promise((resolve, reject) => {
const timeout = setTimeout(() => {
console.warn("Server timeout: capture", captureCode);
reject(new Error("Timeout"));
}, 3000);
emitCapture(captureCode, (response) => {
clearTimeout(timeout);
resolve(response);
});
});
}, []);
return { sendCurrentPosition, capture };
};

View File

@@ -0,0 +1,43 @@
// React
import { useEffect, useState, useCallback } from "react";
import AsyncStorage from '@react-native-async-storage/async-storage';
export const useLocalStorage = (key, initialValue) => {
const [storedValue, setStoredValue] = useState(initialValue);
useEffect(() => {
let isMounted = true;
const fetchData = async () => {
try {
const item = await AsyncStorage.getItem(key);
if (isMounted && item !== null) {
setStoredValue(JSON.parse(item));
}
} catch (error) {
console.error(`Error loading key "${key}":`, error);
}
};
fetchData();
return () => { isMounted = false; };
}, [key]);
const setValue = useCallback(async (value) => {
try {
setStoredValue((prevValue) => {
const valueToStore = value instanceof Function ? value(prevValue) : value;
AsyncStorage.setItem(key, JSON.stringify(valueToStore)).catch(err =>
console.error(`Error saving key "${key}":`, err)
);
return valueToStore;
});
} catch (error) {
console.error(error);
}
}, [key]);
return [storedValue, setValue];
};

View File

@@ -0,0 +1,33 @@
// React
import { useState, useEffect } from 'react';
// Expo
import * as Location from 'expo-location';
// Constants
import { LOCATION_PARAMETERS } from '../constants';
export const useLocation = () => {
const [location, setLocation] = useState(null);
useEffect(() => {
let subscription;
const startWatching = async () => {
const { status } = await Location.requestForegroundPermissionsAsync();
if (status !== 'granted') return;
subscription = await Location.watchPositionAsync(
LOCATION_PARAMETERS,
(location) => setLocation(location.coords)
);
};
startWatching();
return () => {
if (subscription) subscription.remove();
};
}, []);
return { location };
};

View File

@@ -0,0 +1,39 @@
// React
import { useState, useCallback } from 'react';
import { Alert } from 'react-native';
// Expo
import { launchImageLibraryAsync, requestMediaLibraryPermissionsAsync } from 'expo-image-picker';
export const usePickImage = () => {
const [image, setImage] = useState(null);
const pickImage = useCallback(async () => {
try {
const permissionResult = await requestMediaLibraryPermissionsAsync();
if (permissionResult.granted === false) {
Alert.alert("Permission refusée", "Activez l'accès au stockage ou à la gallerie dans les paramètres.");
return;
}
let result = await launchImageLibraryAsync({
mediaTypes: ['images'],
allowsMultipleSelection: false,
allowsEditing: true,
aspect: [4, 3],
quality: 1,
});
if (!result.canceled && result) {
setImage(result.assets[0]);
}
else {
console.log('Image picker cancelled.');
}
} catch (error) {
console.error('Error picking image;', error);
Alert.alert('Erreur', "Une erreur est survenue lors de la sélection d'une image.");
}
}, []);
return {image, pickImage};
};

View File

@@ -0,0 +1,46 @@
// React
import { useEffect, useRef } from 'react';
import DeviceInfo from 'react-native-device-info';
// Context
import { useTeamConnexion } from "../context/teamConnexionContext";
// Services
import { emitBattery, emitDeviceInfo } from "../services/socketEmitter";
export const useSendDeviceInfo = () => {
const { loggedIn } = useTeamConnexion();
const isMounted = useRef(true);
useEffect(() => {
isMounted.current = true;
if (!loggedIn) return;
const sendInfo = async () => {
const [brand, model, name] = await Promise.all([
DeviceInfo.getBrand(),
DeviceInfo.getModel(),
DeviceInfo.getDeviceName()
]);
if (!isMounted) return;
emitDeviceInfo({model: brand + " " + model, name: name});
};
const sendBattery = async () => {
const level = await DeviceInfo.getBatteryLevel();
if (!isMounted) return;
emitBattery(Math.round(level * 100));
};
sendInfo();
sendBattery();
const batteryCheckInterval = setInterval(() => sendBattery(), 5*60*1000); // 5 minutes
return () => {
isMounted.current = false;
clearInterval(batteryCheckInterval);
};
}, [loggedIn]);
return null;
};

View File

@@ -0,0 +1,60 @@
// React
import { useState, useEffect, useCallback, useRef } from 'react';
// Hook
import { useLocalStorage } from './useLocalStorage';
// Services
import { emitLogin, emitLogout } from "../services/socketEmitter";
export const useSocketAuth = () => {
const [loggedIn, setLoggedIn] = useState(false);
const [savedPassword, setSavedPassword] = useLocalStorage("team_password", null);
const isMounted = useRef(true);
useEffect(() => {
isMounted.current = true;
return () => {
isMounted.current = false;
};
}, []);
const login = useCallback((password) => {
return new Promise((resolve, reject) => {
const timeout = setTimeout(() => {
if (!isMounted.current) return;
console.warn("Server did not respond to login emit.");
reject();
}, 2000);
emitLogin(password, (response) => {
clearTimeout(timeout);
if (!isMounted.current) return;
if (response.isLoggedIn) {
console.log("Log in accepted.");
setLoggedIn(true);
setSavedPassword(password);
resolve(response);
} else {
console.log("Log in refused.");
setLoggedIn(false);
reject();
}
});
});
}, [setSavedPassword]);
useEffect(() => {
if (!loggedIn && savedPassword) {
login(savedPassword);
}
}, [loggedIn, login, savedPassword]);
const logout = useCallback(() => {
setLoggedIn(false);
setSavedPassword(null);
emitLogout();
}, [setSavedPassword]);
return {login, logout, password: savedPassword, loggedIn};
};

View File

@@ -0,0 +1,22 @@
// React
import { useEffect, useState } from "react";
export const useTimeDifference = (refTime, timeout) => {
// If refTime is in the past, time will be positive
// If refTime is in the future, time will be negative
// The time is updated every timeout milliseconds
const [time, setTime] = useState(0);
useEffect(() => {
const updateTime = () => {
setTime(Math.floor((Date.now() - refTime) / 1000));
};
updateTime();
const interval = setInterval(updateTime, timeout);
return () => clearInterval(interval);
}, [refTime, timeout]);
return [time];
};