feat: enhance configuration management, add update checks, and improve UI components
This commit is contained in:
@@ -14,6 +14,14 @@ const api = axios.create({
|
||||
timeout: 10000, // 10 seconds timeout
|
||||
});
|
||||
|
||||
// Export function to update base URL
|
||||
export const setApiBaseUrl = (url: string) => {
|
||||
if (url) {
|
||||
api.defaults.baseURL = url;
|
||||
console.log(`[API] Base URL updated to: ${url}`);
|
||||
}
|
||||
};
|
||||
|
||||
// Interceptor: Adds the token to EVERY request if it exists
|
||||
api.interceptors.request.use(
|
||||
async (config) => {
|
||||
|
||||
@@ -62,7 +62,7 @@ export function AuthProvider({ children }: PropsWithChildren) {
|
||||
const savedToken = await SecureStore.getItemAsync(KEY_TOKEN);
|
||||
|
||||
if (savedToken) {
|
||||
console.log("Token trovato: ", savedToken);
|
||||
console.log("Token trovato:", savedToken);
|
||||
|
||||
// Call backend to verify token and fetch user data
|
||||
// Note: api.ts already adds the Authorization header thanks to the interceptor (if configured to read from SecureStore)
|
||||
|
||||
87
utils/configProvider.tsx
Normal file
87
utils/configProvider.tsx
Normal file
@@ -0,0 +1,87 @@
|
||||
import React, { createContext, useState, useEffect, ReactNode } from 'react';
|
||||
import { Linking, Platform } from 'react-native';
|
||||
import Constants from 'expo-constants';
|
||||
import axios from 'axios';
|
||||
import LoadingScreen from '@/components/LoadingScreen';
|
||||
import UpdateScreen from '@/components/UpdateScreen';
|
||||
import { isUpdateAvailable } from '@/utils/version';
|
||||
import { setApiBaseUrl } from './api';
|
||||
|
||||
interface ConfigContextProps {
|
||||
children: ReactNode
|
||||
};
|
||||
|
||||
// Context (useful if you want to trigger manual checks from inside the app in the future)
|
||||
export const ConfigContext = createContext({});
|
||||
|
||||
const GW_API = process.env.EXPO_PUBLIC_GW_API_URL;
|
||||
const GW_UUID = process.env.EXPO_PUBLIC_GW_UUID;
|
||||
const GW_TOKEN = process.env.EXPO_PUBLIC_GW_API_TOKEN;
|
||||
|
||||
export const ConfigProvider = ({ children }: ConfigContextProps) => {
|
||||
const [isChecking, setIsChecking] = useState(true);
|
||||
const [needsUpdate, setNeedsUpdate] = useState(false);
|
||||
const [updateUrl, setUpdateUrl] = useState('');
|
||||
|
||||
useEffect(() => {
|
||||
const checkAppVersion = async () => {
|
||||
try {
|
||||
|
||||
const apiUrl = `${GW_API}${GW_UUID}`;
|
||||
const response = await axios.get(apiUrl, {
|
||||
headers: { "x-access-tokens": GW_TOKEN }
|
||||
});
|
||||
|
||||
// Update API URL: prioritize environment variable (override) over gateway response
|
||||
setApiBaseUrl(process.env.EXPO_PUBLIC_API_URL || response.data.url);
|
||||
|
||||
const currentVersion = Constants.expoConfig?.version;
|
||||
console.log("Versione attuale dell'app:", currentVersion);
|
||||
|
||||
const latestVersion = response.data.version;
|
||||
console.log("Versione più recente disponibile:", latestVersion);
|
||||
|
||||
// Check if an update is needed
|
||||
if (isUpdateAvailable(currentVersion, latestVersion)) {
|
||||
setNeedsUpdate(true);
|
||||
setUpdateUrl(Platform.OS === 'ios' ? response.data.app_url_ios : response.data.app_url_android);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error("Errore durante il controllo della versione:", error);
|
||||
setNeedsUpdate(false);
|
||||
} finally {
|
||||
setIsChecking(false);
|
||||
}
|
||||
};
|
||||
|
||||
checkAppVersion();
|
||||
}, []);
|
||||
|
||||
const handleUpdate = async () => {
|
||||
if (updateUrl) {
|
||||
Linking.openURL(updateUrl);
|
||||
}
|
||||
};
|
||||
|
||||
// Loading state
|
||||
if (isChecking) {
|
||||
return (
|
||||
<LoadingScreen />
|
||||
);
|
||||
}
|
||||
|
||||
// Update state: blocks children rendering
|
||||
if (needsUpdate) {
|
||||
return (
|
||||
<UpdateScreen onUpdate={handleUpdate} />
|
||||
);
|
||||
}
|
||||
|
||||
// Version is up to date
|
||||
return (
|
||||
<ConfigContext.Provider value={{ isChecking, needsUpdate }}>
|
||||
{children}
|
||||
</ConfigContext.Provider>
|
||||
);
|
||||
};
|
||||
27
utils/version.ts
Normal file
27
utils/version.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Compare two version strings.
|
||||
* Returns true if 'latest' is greater than 'current' (an update is available).
|
||||
*/
|
||||
export const isUpdateAvailable = (currentVersion: string | undefined, latestVersion: string) => {
|
||||
if (!currentVersion || !latestVersion) return false;
|
||||
|
||||
// Split strings into an array of numbers: "1.2.10" -> [1, 2, 10]
|
||||
const currentParts = currentVersion.split('.').map(Number);
|
||||
const latestParts = latestVersion.split('.').map(Number);
|
||||
const maxLength = Math.max(currentParts.length, latestParts.length);
|
||||
|
||||
for (let i = 0; i < maxLength; i++) {
|
||||
// If a part is missing, we consider it as 0 (e.g. "1.0" -> [1, 0, 0])
|
||||
const current = currentParts[i] || 0;
|
||||
const latest = latestParts[i] || 0;
|
||||
|
||||
if (current < latest) {
|
||||
return true; // It needs an update
|
||||
}
|
||||
if (current > latest) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
Reference in New Issue
Block a user