mirror of
https://github.com/immich-app/immich.git
synced 2025-09-29 15:31:13 -04:00
fix: repeat timeline migration for first time user (#21794)
This commit is contained in:
parent
56e5236a39
commit
2d2673c114
@ -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,49 +44,13 @@ class _ChangeExperiencePageState extends ConsumerState<ChangeExperiencePage> {
|
||||
|
||||
Future<void> _handleMigration() async {
|
||||
try {
|
||||
if (widget.switchingToBeta) {
|
||||
final assetNotifier = ref.read(assetProvider.notifier);
|
||||
if (assetNotifier.mounted) {
|
||||
assetNotifier.dispose();
|
||||
}
|
||||
final albumNotifier = ref.read(albumProvider.notifier);
|
||||
if (albumNotifier.mounted) {
|
||||
albumNotifier.dispose();
|
||||
}
|
||||
|
||||
// Cancel uploads
|
||||
await Store.put(StoreKey.backgroundBackup, false);
|
||||
ref
|
||||
.read(backupProvider.notifier)
|
||||
.configureBackgroundBackup(enabled: false, onBatteryInfo: () {}, onError: (_) {});
|
||||
ref.read(backupProvider.notifier).setAutoBackup(false);
|
||||
ref.read(backupProvider.notifier).cancelBackup();
|
||||
ref.read(manualUploadProvider.notifier).cancelBackup();
|
||||
// Start listening to new websocket events
|
||||
ref.read(websocketProvider.notifier).stopListenToOldEvents();
|
||||
ref.read(websocketProvider.notifier).startListeningToBetaEvents();
|
||||
|
||||
final permission = await ref.read(galleryPermissionNotifier.notifier).requestGalleryPermission();
|
||||
|
||||
if (permission.isGranted) {
|
||||
await ref.read(backgroundSyncProvider).syncLocal(full: true);
|
||||
await migrateDeviceAssetToSqlite(ref.read(isarProvider), ref.read(driftProvider));
|
||||
await migrateBackupAlbumsToSqlite(ref.read(isarProvider), ref.read(driftProvider));
|
||||
await migrateStoreToSqlite(ref.read(isarProvider), ref.read(driftProvider));
|
||||
await ref.read(backgroundServiceProvider).disableService();
|
||||
}
|
||||
} else {
|
||||
await ref.read(backgroundSyncProvider).cancel();
|
||||
ref.read(websocketProvider.notifier).stopListeningToBetaEvents();
|
||||
ref.read(websocketProvider.notifier).startListeningToOldEvents();
|
||||
ref.read(readonlyModeProvider.notifier).setReadonlyMode(false);
|
||||
await migrateStoreToIsar(ref.read(isarProvider), ref.read(driftProvider));
|
||||
await ref.read(backgroundServiceProvider).resumeServiceIfEnabled();
|
||||
await ref.read(backgroundWorkerFgServiceProvider).disable();
|
||||
}
|
||||
|
||||
await IsarStoreRepository(ref.read(isarProvider)).upsert(StoreKey.betaTimeline, widget.switchingToBeta);
|
||||
await DriftStoreRepository(ref.read(driftProvider)).upsert(StoreKey.betaTimeline, widget.switchingToBeta);
|
||||
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(() {
|
||||
@ -102,6 +68,52 @@ class _ChangeExperiencePageState extends ConsumerState<ChangeExperiencePage> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _performMigrationLogic() async {
|
||||
if (widget.switchingToBeta) {
|
||||
final assetNotifier = ref.read(assetProvider.notifier);
|
||||
if (assetNotifier.mounted) {
|
||||
assetNotifier.dispose();
|
||||
}
|
||||
final albumNotifier = ref.read(albumProvider.notifier);
|
||||
if (albumNotifier.mounted) {
|
||||
albumNotifier.dispose();
|
||||
}
|
||||
|
||||
// Cancel uploads
|
||||
await Store.put(StoreKey.backgroundBackup, false);
|
||||
ref
|
||||
.read(backupProvider.notifier)
|
||||
.configureBackgroundBackup(enabled: false, onBatteryInfo: () {}, onError: (_) {});
|
||||
ref.read(backupProvider.notifier).setAutoBackup(false);
|
||||
ref.read(backupProvider.notifier).cancelBackup();
|
||||
ref.read(manualUploadProvider.notifier).cancelBackup();
|
||||
// Start listening to new websocket events
|
||||
ref.read(websocketProvider.notifier).stopListenToOldEvents();
|
||||
ref.read(websocketProvider.notifier).startListeningToBetaEvents();
|
||||
|
||||
final permission = await ref.read(galleryPermissionNotifier.notifier).requestGalleryPermission();
|
||||
|
||||
if (permission.isGranted) {
|
||||
await ref.read(backgroundSyncProvider).syncLocal(full: true);
|
||||
await migrateDeviceAssetToSqlite(ref.read(isarProvider), ref.read(driftProvider));
|
||||
await migrateBackupAlbumsToSqlite(ref.read(isarProvider), ref.read(driftProvider));
|
||||
await migrateStoreToSqlite(ref.read(isarProvider), ref.read(driftProvider));
|
||||
await ref.read(backgroundServiceProvider).disableService();
|
||||
}
|
||||
} else {
|
||||
await ref.read(backgroundSyncProvider).cancel();
|
||||
ref.read(websocketProvider.notifier).stopListeningToBetaEvents();
|
||||
ref.read(websocketProvider.notifier).startListeningToOldEvents();
|
||||
ref.read(readonlyModeProvider.notifier).setReadonlyMode(false);
|
||||
await migrateStoreToIsar(ref.read(isarProvider), ref.read(driftProvider));
|
||||
await ref.read(backgroundServiceProvider).resumeServiceIfEnabled();
|
||||
await ref.read(backgroundWorkerFgServiceProvider).disable();
|
||||
}
|
||||
|
||||
await IsarStoreRepository(ref.read(isarProvider)).upsert(StoreKey.betaTimeline, widget.switchingToBeta);
|
||||
await DriftStoreRepository(ref.read(driftProvider)).upsert(StoreKey.betaTimeline, widget.switchingToBeta);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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(
|
||||
|
Loading…
x
Reference in New Issue
Block a user