App copy
This commit is contained in:
@@ -69,20 +69,31 @@ const ensureInstallConsistency = async (): Promise<boolean> => {
|
||||
const sqliteMarker = AppMetaDb.get('install_marker_v2');
|
||||
const secureMarker = await SecureStore.getItemAsync(SECURE_INSTALL_MARKER).catch(() => null);
|
||||
|
||||
if (sqliteMarker === '1' && secureMarker === '1') {
|
||||
return false; // Alles gut, keine Neuinstallation
|
||||
}
|
||||
|
||||
if (sqliteMarker === '1' || secureMarker === '1') {
|
||||
// Teilweise vorhanden -> heilen, nicht löschen
|
||||
AppMetaDb.set('install_marker_v2', '1');
|
||||
await SecureStore.setItemAsync(SECURE_INSTALL_MARKER, '1');
|
||||
// WICHTIG: Nur der SQLite-Marker taugt als Neuinstallations-Erkennung.
|
||||
// SecureStore liegt auf iOS im Keychain, und Keychain-Eintraege ueberleben
|
||||
// das Loeschen der App. Nach einer Neuinstallation gilt also immer
|
||||
// sqliteMarker === null && secureMarker === '1' - das ist der Normalfall,
|
||||
// nicht ein halb geschriebener Zustand.
|
||||
//
|
||||
// Vorher lief genau dieser Fall in den "heilen"-Zweig: die Session blieb
|
||||
// bestehen, der Nutzer war nach der Neuinstallation weiter eingeloggt und
|
||||
// hat das Onboarding nie wieder gesehen (Gate: !session && !hasCompletedOnboarding).
|
||||
if (sqliteMarker === '1') {
|
||||
// App-Daten vorhanden -> laufende Installation. Keychain-Marker nachziehen,
|
||||
// falls er fehlt (z. B. nach einem Keychain-Reset).
|
||||
if (secureMarker !== '1') {
|
||||
await SecureStore.setItemAsync(SECURE_INSTALL_MARKER, '1');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Fresh Install: Alles zurücksetzen
|
||||
// Fresh Install: Alles zurücksetzen. Der Nutzer landet danach auf dem
|
||||
// Welcome-Screen und durchläuft das Onboarding erneut - inklusive
|
||||
// A/B-Zuweisung, die ebenfalls im geloeschten App-Storage lag.
|
||||
await AuthService.logout();
|
||||
await AsyncStorage.removeItem('greenlens_show_tour');
|
||||
// Experiment-Zuweisungen gehoeren zur Installation, nicht zum Keychain.
|
||||
await AsyncStorage.removeItem('greenlens_experiment_welcome_headline_v1');
|
||||
AppMetaDb.set('install_marker_v2', '1');
|
||||
await SecureStore.setItemAsync(SECURE_INSTALL_MARKER, '1');
|
||||
return true;
|
||||
@@ -152,6 +163,7 @@ function RootLayoutInner() {
|
||||
<Stack.Screen name="onboarding" options={{ animation: 'none' }} />
|
||||
<Stack.Screen name="onboarding/slides" options={{ animation: 'slide_from_right' }} />
|
||||
<Stack.Screen name="onboarding/source" options={{ animation: 'slide_from_right' }} />
|
||||
<Stack.Screen name="onboarding/health-check" options={{ animation: 'slide_from_right' }} />
|
||||
<Stack.Screen name="onboarding/goal" options={{ animation: 'slide_from_right' }} />
|
||||
<Stack.Screen name="onboarding/experience" options={{ animation: 'slide_from_right' }} />
|
||||
<Stack.Screen name="onboarding/customize" options={{ animation: 'slide_from_right' }} />
|
||||
@@ -182,6 +194,7 @@ function RootLayoutInner() {
|
||||
<Stack.Screen name="onboarding" options={{ animation: 'none' }} />
|
||||
<Stack.Screen name="onboarding/slides" options={{ animation: 'slide_from_right' }} />
|
||||
<Stack.Screen name="onboarding/source" options={{ animation: 'slide_from_right' }} />
|
||||
<Stack.Screen name="onboarding/health-check" options={{ animation: 'slide_from_right' }} />
|
||||
<Stack.Screen name="onboarding/goal" options={{ animation: 'slide_from_right' }} />
|
||||
<Stack.Screen name="onboarding/experience" options={{ animation: 'slide_from_right' }} />
|
||||
<Stack.Screen name="onboarding/customize" options={{ animation: 'slide_from_right' }} />
|
||||
|
||||
Reference in New Issue
Block a user