login without distant server local only mode
This commit is contained in:
@@ -27,9 +27,11 @@ function AuthGate() {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Stack>
|
<Stack>
|
||||||
|
<Stack.Screen name="index" options={{ title: i18n.t('files') }} />
|
||||||
|
<Stack.Screen name="folder/[id]" options={{ title: i18n.t('folder') }} />
|
||||||
<Stack.Screen name="login" options={{ title: i18n.t('login_title') }} />
|
<Stack.Screen name="login" options={{ title: i18n.t('login_title') }} />
|
||||||
</Stack>
|
</Stack>
|
||||||
{/* 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' ? <Redirect href="/login" /> : null}
|
{status === 'signedOut' ? <Redirect href="/login" /> : null}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
+20
-1
@@ -7,7 +7,7 @@ import i18n from '../i18n';
|
|||||||
|
|
||||||
export default function Login() {
|
export default function Login() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { signIn, user } = useAuth();
|
const { signIn, user, continueWithoutAccount } = useAuth();
|
||||||
const [username, setUsername] = useState('');
|
const [username, setUsername] = useState('');
|
||||||
const [password, setPassword] = useState('');
|
const [password, setPassword] = useState('');
|
||||||
const [submitting, setSubmitting] = useState(false);
|
const [submitting, setSubmitting] = useState(false);
|
||||||
@@ -73,6 +73,15 @@ export default function Login() {
|
|||||||
{submitting ? i18n.t('login_submitting') : i18n.t('login_submit')}
|
{submitting ? i18n.t('login_submitting') : i18n.t('login_submit')}
|
||||||
</Text>
|
</Text>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
|
<Pressable
|
||||||
|
style={styles.skipButton}
|
||||||
|
onPress={() => {
|
||||||
|
continueWithoutAccount();
|
||||||
|
router.replace('/');
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text style={styles.skipButtonText}>{i18n.t('login_skip')}</Text>
|
||||||
|
</Pressable>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -118,4 +127,14 @@ const styles = StyleSheet.create({
|
|||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: '600',
|
fontWeight: '600',
|
||||||
},
|
},
|
||||||
|
skipButton: {
|
||||||
|
alignItems: 'center',
|
||||||
|
paddingVertical: 10,
|
||||||
|
marginTop: 4,
|
||||||
|
},
|
||||||
|
skipButtonText: {
|
||||||
|
color: '#1a73e8',
|
||||||
|
fontSize: 15,
|
||||||
|
fontWeight: '500',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
@@ -87,9 +87,13 @@ export function AuthProvider({ children }: { children: ReactNode }) {
|
|||||||
setStatus('signedIn');
|
setStatus('signedIn');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const continueWithoutAccount = () => {
|
||||||
|
setStatus('local');
|
||||||
|
};
|
||||||
|
|
||||||
const value = useMemo(
|
const value = useMemo(
|
||||||
() => ({ user, deviceUserId, status, signIn, signOut }),
|
() => ({ user, deviceUserId, status, signIn, signOut, continueWithoutAccount }),
|
||||||
[user, deviceUserId, status, signIn, signOut],
|
[user, deviceUserId, status, signIn, signOut, continueWithoutAccount],
|
||||||
);
|
);
|
||||||
|
|
||||||
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
|
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import type { User } from '../api/types';
|
|||||||
|
|
||||||
export type { User };
|
export type { User };
|
||||||
|
|
||||||
export type AuthStatus = 'loading' | 'signedOut' | 'signedIn';
|
export type AuthStatus = 'loading' | 'signedOut' | 'local' | 'signedIn';
|
||||||
|
|
||||||
export type AuthContextValue = {
|
export type AuthContextValue = {
|
||||||
user: User | null;
|
user: User | null;
|
||||||
@@ -10,4 +10,5 @@ export type AuthContextValue = {
|
|||||||
status: AuthStatus;
|
status: AuthStatus;
|
||||||
signIn: (username: string, password: string) => Promise<void>;
|
signIn: (username: string, password: string) => Promise<void>;
|
||||||
signOut: () => Promise<void>;
|
signOut: () => Promise<void>;
|
||||||
|
continueWithoutAccount: () => void;
|
||||||
};
|
};
|
||||||
+3
-1
@@ -20,5 +20,7 @@
|
|||||||
"login_switch_title": "Account already signed in",
|
"login_switch_title": "Account already signed in",
|
||||||
"login_switch_message": "This sign-in will replace the active account on this device. Continue?",
|
"login_switch_message": "This sign-in will replace the active account on this device. Continue?",
|
||||||
"login_switch_confirm": "Replace",
|
"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."
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-1
@@ -20,5 +20,7 @@
|
|||||||
"login_switch_title": "Compte déjà connecté",
|
"login_switch_title": "Compte déjà connecté",
|
||||||
"login_switch_message": "Cette connexion remplacera le compte actif sur cet appareil. Continuer ?",
|
"login_switch_message": "Cette connexion remplacera le compte actif sur cet appareil. Continuer ?",
|
||||||
"login_switch_confirm": "Remplacer",
|
"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."
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user