diff --git a/mobile/app/_layout.tsx b/mobile/app/_layout.tsx
index a28d392..5c74ce4 100644
--- a/mobile/app/_layout.tsx
+++ b/mobile/app/_layout.tsx
@@ -27,9 +27,11 @@ function AuthGate() {
return (
<>
+
+
- {/* Toute route est protégée tant qu'aucun compte n'est connecté. */}
+ {/* Rediriger vers la connexion uniquement si l'utilisateur n'a pas de session ET n'est pas en mode local. */}
{status === 'signedOut' ? : null}
>
);
diff --git a/mobile/app/login.tsx b/mobile/app/login.tsx
index 679e99f..d3e358a 100644
--- a/mobile/app/login.tsx
+++ b/mobile/app/login.tsx
@@ -7,7 +7,7 @@ import i18n from '../i18n';
export default function Login() {
const router = useRouter();
- const { signIn, user } = useAuth();
+ const { signIn, user, continueWithoutAccount } = useAuth();
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const [submitting, setSubmitting] = useState(false);
@@ -73,6 +73,15 @@ export default function Login() {
{submitting ? i18n.t('login_submitting') : i18n.t('login_submit')}
+ {
+ continueWithoutAccount();
+ router.replace('/');
+ }}
+ >
+ {i18n.t('login_skip')}
+
);
}
@@ -118,4 +127,14 @@ const styles = StyleSheet.create({
fontSize: 16,
fontWeight: '600',
},
+ skipButton: {
+ alignItems: 'center',
+ paddingVertical: 10,
+ marginTop: 4,
+ },
+ skipButtonText: {
+ color: '#1a73e8',
+ fontSize: 15,
+ fontWeight: '500',
+ },
});
\ No newline at end of file
diff --git a/mobile/context/AuthContext.tsx b/mobile/context/AuthContext.tsx
index ea209d7..b9544dd 100644
--- a/mobile/context/AuthContext.tsx
+++ b/mobile/context/AuthContext.tsx
@@ -87,9 +87,13 @@ export function AuthProvider({ children }: { children: ReactNode }) {
setStatus('signedIn');
};
+ const continueWithoutAccount = () => {
+ setStatus('local');
+ };
+
const value = useMemo(
- () => ({ user, deviceUserId, status, signIn, signOut }),
- [user, deviceUserId, status, signIn, signOut],
+ () => ({ user, deviceUserId, status, signIn, signOut, continueWithoutAccount }),
+ [user, deviceUserId, status, signIn, signOut, continueWithoutAccount],
);
return {children};
diff --git a/mobile/context/AuthContext.types.ts b/mobile/context/AuthContext.types.ts
index cf2b2f1..e9fb868 100644
--- a/mobile/context/AuthContext.types.ts
+++ b/mobile/context/AuthContext.types.ts
@@ -2,7 +2,7 @@ import type { User } from '../api/types';
export type { User };
-export type AuthStatus = 'loading' | 'signedOut' | 'signedIn';
+export type AuthStatus = 'loading' | 'signedOut' | 'local' | 'signedIn';
export type AuthContextValue = {
user: User | null;
@@ -10,4 +10,5 @@ export type AuthContextValue = {
status: AuthStatus;
signIn: (username: string, password: string) => Promise;
signOut: () => Promise;
+ continueWithoutAccount: () => void;
};
\ No newline at end of file
diff --git a/mobile/i18n/en.json b/mobile/i18n/en.json
index 9daca6e..b55db50 100644
--- a/mobile/i18n/en.json
+++ b/mobile/i18n/en.json
@@ -20,5 +20,7 @@
"login_switch_title": "Account already signed in",
"login_switch_message": "This sign-in will replace the active account on this device. Continue?",
"login_switch_confirm": "Replace",
- "login_switch_cancel": "Cancel"
+ "login_switch_cancel": "Cancel",
+ "login_skip": "Continue without account",
+ "skip_message": "Local mode — your folders stay on this device and are not synced."
}
diff --git a/mobile/i18n/fr.json b/mobile/i18n/fr.json
index 0b25472..6185e8b 100644
--- a/mobile/i18n/fr.json
+++ b/mobile/i18n/fr.json
@@ -20,5 +20,7 @@
"login_switch_title": "Compte déjà connecté",
"login_switch_message": "Cette connexion remplacera le compte actif sur cet appareil. Continuer ?",
"login_switch_confirm": "Remplacer",
- "login_switch_cancel": "Annuler"
+ "login_switch_cancel": "Annuler",
+ "login_skip": "Continuer sans compte",
+ "skip_message": "Mode local — tes dossiers restent sur cet appareil et ne sont pas synchronisés."
}