fix: repeat timeline migration for first time user (#21794)

This commit is contained in:
Alex 2025-09-10 16:27:00 -05:00 committed by GitHub
parent 56e5236a39
commit 2d2673c114
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 63 additions and 52 deletions

View File

@ -1,3 +1,5 @@
import 'dart:async';
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
@ -42,6 +44,31 @@ class _ChangeExperiencePageState extends ConsumerState<ChangeExperiencePage> {
Future<void> _handleMigration() async {
try {
await _performMigrationLogic().timeout(
const Duration(minutes: 3),
onTimeout: () async {
await IsarStoreRepository(ref.read(isarProvider)).upsert(StoreKey.betaTimeline, widget.switchingToBeta);
await DriftStoreRepository(ref.read(driftProvider)).upsert(StoreKey.betaTimeline, widget.switchingToBeta);
},
);
if (mounted) {
setState(() {
HapticFeedback.heavyImpact();
hasMigrated = const AsyncValue.data(true);
});
}
} catch (e, s) {
Logger("ChangeExperiencePage").severe("Error during migration", e, s);
if (mounted) {
setState(() {
hasMigrated = AsyncValue.error(e, s);
});
}
}
}
Future<void> _performMigrationLogic() async {
if (widget.switchingToBeta) {
final assetNotifier = ref.read(assetProvider.notifier);
if (assetNotifier.mounted) {
@ -85,21 +112,6 @@ class _ChangeExperiencePageState extends ConsumerState<ChangeExperiencePage> {
await IsarStoreRepository(ref.read(isarProvider)).upsert(StoreKey.betaTimeline, widget.switchingToBeta);
await DriftStoreRepository(ref.read(driftProvider)).upsert(StoreKey.betaTimeline, widget.switchingToBeta);
if (mounted) {
setState(() {
HapticFeedback.heavyImpact();
hasMigrated = const AsyncValue.data(true);
});
}
} catch (e, s) {
Logger("ChangeExperiencePage").severe("Error during migration", e, s);
if (mounted) {
setState(() {
hasMigrated = AsyncValue.error(e, s);
});
}
}
}
@override

View File

@ -167,13 +167,6 @@ class AppLifeCycleNotifier extends StateNotifier<AppLifeCycleEnum> {
}
} catch (e, stackTrace) {
_log.severe("Error during background sync", e, stackTrace);
} finally {
// Ensure lock is released even if operations fail
try {
_log.info("Lock released after background sync operations");
} catch (lockError) {
_log.warning("Failed to release lock after error: $lockError");
}
}
}

View File

@ -63,7 +63,10 @@ Future<void> migrateDatabaseIfNeeded(Isar db, Drift drift) async {
// Handle migration only for this version
// TODO: remove when old timeline is removed
if (version == 15) {
final needBetaMigration = Store.tryGet(StoreKey.needBetaMigration);
if (version == 15 && needBetaMigration == null) {
// Check both databases directly instead of relying on cache
final isBeta = Store.tryGet(StoreKey.betaTimeline);
final isNewInstallation = await _isNewInstallation(db, drift);
@ -71,6 +74,7 @@ Future<void> migrateDatabaseIfNeeded(Isar db, Drift drift) async {
// For existing installations, only migrate if beta timeline is not enabled (null or false)
if (isNewInstallation || isBeta == true) {
await Store.put(StoreKey.needBetaMigration, false);
await Store.put(StoreKey.betaTimeline, true);
} else {
await resetDriftDatabase(drift);
await Store.put(StoreKey.needBetaMigration, true);

View File

@ -104,7 +104,6 @@ class SyncStatusAndActions extends HookConsumerWidget {
padding: const EdgeInsets.only(top: 16, bottom: 32),
child: ListView(
children: [
_SectionHeaderText(text: "assets".t(context: context)),
const _SyncStatsCounts(),
const Divider(height: 1, indent: 16, endIndent: 16),
const SizedBox(height: 24),
@ -270,7 +269,10 @@ class _SyncStatsCounts extends ConsumerWidget {
final localHashedCount = snapshot.data![4]! as int;
return Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_SectionHeaderText(text: "assets".t(context: context)),
Padding(
padding: const EdgeInsets.fromLTRB(16, 8, 16, 16),
child: Flex(