Add mobile app login flow abort when manually skipped flow (#520)

This commit is contained in:
Leendert de Borst
2025-10-26 15:15:59 +01:00
parent 9843142419
commit dc114c6bfa
2 changed files with 58 additions and 1 deletions

View File

@@ -24,6 +24,7 @@ export default function Initialize() : React.ReactNode {
const skipButtonTimeoutRef = useRef<NodeJS.Timeout | null>(null);
const lastStatusRef = useRef<string>('');
const canShowSkipButtonRef = useRef(false); // Only allow skip button after vault unlock
const abortControllerRef = useRef<AbortController | null>(null);
const { t } = useTranslation();
const app = useApp();
const { syncVault } = useVaultSync();
@@ -68,6 +69,13 @@ export default function Initialize() : React.ReactNode {
* Handle offline scenario - show alert with options to open local vault or retry sync.
*/
const handleOfflineFlow = useCallback((): void => {
// Don't show the alert if we're already in offline mode
if (app.isOffline) {
console.debug('Already in offline mode, skipping offline flow alert');
router.replace('/(tabs)/credentials');
return;
}
Alert.alert(
t('app.alerts.syncIssue'),
t('app.alerts.syncIssueMessage'),
@@ -136,6 +144,12 @@ export default function Initialize() : React.ReactNode {
updateStatus(t('app.status.retryingConnection'));
setShowSkipButton(false);
// Abort any pending sync operation
if (abortControllerRef.current) {
abortControllerRef.current.abort();
abortControllerRef.current = null;
}
// Clear any existing timeout
if (skipButtonTimeoutRef.current) {
clearTimeout(skipButtonTimeoutRef.current);
@@ -241,9 +255,13 @@ export default function Initialize() : React.ReactNode {
canShowSkipButtonRef.current = true;
}
// Create abort controller for sync operations
abortControllerRef.current = new AbortController();
// Now perform vault sync (network operations - these are skippable)
await syncVault({
initialSync: true,
abortSignal: abortControllerRef.current.signal,
/**
* Handle the status update.
*/
@@ -301,6 +319,13 @@ export default function Initialize() : React.ReactNode {
* Handle skip button press by calling the offline handler.
*/
const handleSkipPress = (): void => {
// Abort any pending sync operation
if (abortControllerRef.current) {
console.debug('Aborting pending sync operation');
abortControllerRef.current.abort();
abortControllerRef.current = null;
}
// Clear any existing timeout
if (skipButtonTimeoutRef.current) {
clearTimeout(skipButtonTimeoutRef.current);

View File

@@ -44,6 +44,7 @@ type VaultSyncOptions = {
onStatus?: (message: string) => void;
onOffline?: () => void;
onUpgradeRequired?: () => void;
abortSignal?: AbortSignal;
}
/**
@@ -58,12 +59,18 @@ export const useVaultSync = () : {
const dbContext = useDb();
const syncVault = useCallback(async (options: VaultSyncOptions = {}) => {
const { initialSync = false, onSuccess, onError, onStatus, onOffline, onUpgradeRequired } = options;
const { initialSync = false, onSuccess, onError, onStatus, onOffline, onUpgradeRequired, abortSignal } = options;
// For the initial sync, we add an artifical delay to various steps which makes it feel more fluid.
const enableDelay = initialSync;
try {
// Check if operation was aborted
if (abortSignal?.aborted) {
console.debug('VaultSync: Operation aborted before starting');
return false;
}
const { isLoggedIn } = await app.initializeAuth();
if (!isLoggedIn) {
@@ -71,6 +78,12 @@ export const useVaultSync = () : {
return false;
}
// Check if operation was aborted
if (abortSignal?.aborted) {
console.debug('VaultSync: Operation aborted after auth check');
return false;
}
// Update status
onStatus?.(t('vault.checkingVaultUpdates'));
@@ -79,6 +92,12 @@ export const useVaultSync = () : {
await new Promise(resolve => setTimeout(resolve, 300));
}
// Check if operation was aborted
if (abortSignal?.aborted) {
console.debug('VaultSync: Operation aborted after status update');
return false;
}
// Step 1: Check if a new vault version is available
// This calls Auth/status endpoint and compares vault revisions
let hasNewVault = false;
@@ -86,11 +105,24 @@ export const useVaultSync = () : {
try {
const versionCheckResult = await NativeVaultManager.isNewVaultVersionAvailable();
// Check if operation was aborted after version check
if (abortSignal?.aborted) {
console.debug('VaultSync: Operation aborted after version check');
return false;
}
hasNewVault = versionCheckResult.isNewVersionAvailable;
newRevision = versionCheckResult.newRevision;
// Step 2: If a new version is available, download it
if (hasNewVault && newRevision != null) {
// Check if operation was aborted before download
if (abortSignal?.aborted) {
console.debug('VaultSync: Operation aborted before download');
return false;
}
onStatus?.(t('vault.syncingUpdatedVault'));
// Run downloadVault with a min delay for UX purposes