chore(mobile): remove Drift* prefixes from classes and variables (#31038)
* chore(mobile): remove Drift* prefixes from classes and variables * Remove *Drift* from related mocks
This commit is contained in:
@@ -30,11 +30,11 @@ abstract class MemoryData with _$MemoryData {
|
||||
factory MemoryData.fromJson(String source) => MemoryData.fromMap(json.decode(source) as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
// Model for a memory stored in the server
|
||||
/// A specialized collection of assets with some novel display mechanism
|
||||
// TODO(agg23): DriftMemoryRepository currently mutates `assets`
|
||||
@Freezed(makeCollectionsUnmodifiable: false)
|
||||
abstract class DriftMemory with _$DriftMemory {
|
||||
const factory DriftMemory({
|
||||
abstract class Memory with _$Memory {
|
||||
const factory Memory({
|
||||
required String id,
|
||||
required DateTime createdAt,
|
||||
required DateTime updatedAt,
|
||||
@@ -48,5 +48,5 @@ abstract class DriftMemory with _$DriftMemory {
|
||||
DateTime? showAt,
|
||||
DateTime? hideAt,
|
||||
required List<RemoteAsset> assets,
|
||||
}) = _DriftMemory;
|
||||
}) = _Memory;
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ import 'package:immich_mobile/infrastructure/repositories/settings.repository.da
|
||||
import 'package:immich_mobile/platform/background_worker_api.g.dart';
|
||||
import 'package:immich_mobile/platform/background_worker_lock_api.g.dart';
|
||||
import 'package:immich_mobile/providers/api.provider.dart';
|
||||
import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
|
||||
import 'package:immich_mobile/providers/backup/backup.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/platform.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/sync.provider.dart';
|
||||
@@ -308,7 +308,7 @@ class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi {
|
||||
}
|
||||
|
||||
if (Platform.isIOS) {
|
||||
return _ref?.read(driftBackupProvider.notifier).startBackupWithURLSession(currentUser.id);
|
||||
return _ref?.read(backupProvider.notifier).startBackupWithURLSession(currentUser.id);
|
||||
}
|
||||
|
||||
return _ref
|
||||
|
||||
@@ -2,22 +2,23 @@ import 'package:immich_mobile/domain/models/memory.model.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/memory.repository.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
class DriftMemoryService {
|
||||
final log = Logger("DriftMemoryService");
|
||||
/// Accesses Memories; a specialized collection of assets with some novel display mechanism
|
||||
class MemoryService {
|
||||
final log = Logger("MemoryService");
|
||||
|
||||
final MemoryRepository _repository;
|
||||
|
||||
DriftMemoryService(this._repository);
|
||||
MemoryService(this._repository);
|
||||
|
||||
Future<List<DriftMemory>> getMemoryLane(String ownerId) {
|
||||
Future<List<Memory>> getMemoryLane(String ownerId) {
|
||||
return _repository.getAll(ownerId);
|
||||
}
|
||||
|
||||
Future<List<DriftMemory>> getAll(String ownerId, {bool onlyFavorites = false}) {
|
||||
Future<List<Memory>> getAll(String ownerId, {bool onlyFavorites = false}) {
|
||||
return _repository.getAll(ownerId, onlyToday: false, onlyFavorites: onlyFavorites);
|
||||
}
|
||||
|
||||
Future<DriftMemory?> get(String memoryId) {
|
||||
Future<Memory?> get(String memoryId) {
|
||||
return _repository.get(memoryId);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,11 +4,12 @@ import 'package:immich_mobile/data/db/main/dao/person.dart';
|
||||
import 'package:immich_mobile/data/server/person.dart';
|
||||
import 'package:immich_mobile/domain/models/person.model.dart';
|
||||
|
||||
class DriftPeopleService {
|
||||
/// Accesses People; entities mapped to assets for presence and face detection
|
||||
class PeopleService {
|
||||
final PeopleRepository _repository;
|
||||
final PersonApiRepository _personApiRepository;
|
||||
|
||||
const DriftPeopleService(this._repository, this._personApiRepository);
|
||||
const PeopleService(this._repository, this._personApiRepository);
|
||||
|
||||
Future<Person?> get(String personId) {
|
||||
return _repository.get(personId);
|
||||
|
||||
@@ -8,7 +8,7 @@ import 'package:immich_mobile/domain/models/user.model.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/remote_album.repository.dart';
|
||||
import 'package:immich_mobile/models/albums/album_search.model.dart';
|
||||
import 'package:immich_mobile/providers/album/album_sort_by_options.provider.dart';
|
||||
import 'package:immich_mobile/repositories/drift_album_api_repository.dart';
|
||||
import 'package:immich_mobile/repositories/album_api_repository.dart';
|
||||
import 'package:immich_mobile/services/foreground_upload.service.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
@@ -26,7 +26,7 @@ class RemoteAlbumService {
|
||||
static final _logger = Logger('RemoteAlbumService');
|
||||
|
||||
final RemoteAlbumRepository _repository;
|
||||
final DriftAlbumApiRepository _albumApiRepository;
|
||||
final AlbumApiRepository _albumApiRepository;
|
||||
final ForegroundUploadService _uploadService;
|
||||
|
||||
const RemoteAlbumService(this._repository, this._albumApiRepository, this._uploadService);
|
||||
|
||||
@@ -8,7 +8,7 @@ import 'package:immich_mobile/infrastructure/repositories/local_album.repository
|
||||
import 'package:immich_mobile/infrastructure/repositories/remote_album.repository.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/store.provider.dart';
|
||||
import 'package:immich_mobile/repositories/drift_album_api_repository.dart';
|
||||
import 'package:immich_mobile/repositories/album_api_repository.dart';
|
||||
import 'package:immich_mobile/utils/debug_print.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
@@ -17,7 +17,7 @@ final syncLinkedAlbumServiceProvider = Provider((ref) {
|
||||
return SyncLinkedAlbumService(
|
||||
db.localAlbumRepository,
|
||||
db.remoteAlbumRepository,
|
||||
ref.watch(driftAlbumApiRepositoryProvider),
|
||||
ref.watch(albumApiRepositoryProvider),
|
||||
ref.watch(storeServiceProvider),
|
||||
);
|
||||
});
|
||||
@@ -25,7 +25,7 @@ final syncLinkedAlbumServiceProvider = Provider((ref) {
|
||||
class SyncLinkedAlbumService {
|
||||
final LocalAlbumRepository _localAlbumRepository;
|
||||
final RemoteAlbumRepository _remoteAlbumRepository;
|
||||
final DriftAlbumApiRepository _albumApiRepository;
|
||||
final AlbumApiRepository _albumApiRepository;
|
||||
final StoreService _storeService;
|
||||
|
||||
SyncLinkedAlbumService(
|
||||
|
||||
@@ -12,7 +12,7 @@ class MemoryRepository extends DatabaseAccessor<Drift> with $MemoryRepositoryMix
|
||||
|
||||
Drift get _db => attachedDatabase;
|
||||
|
||||
Future<List<DriftMemory>> getAll(String ownerId, {bool onlyToday = true, bool onlyFavorites = false}) async {
|
||||
Future<List<Memory>> getAll(String ownerId, {bool onlyToday = true, bool onlyFavorites = false}) async {
|
||||
final query =
|
||||
_db.select(_db.memoryEntity).join([
|
||||
innerJoin(_db.memoryAssetEntity, _db.memoryAssetEntity.memoryId.equalsExp(_db.memoryEntity.id)),
|
||||
@@ -45,7 +45,7 @@ class MemoryRepository extends DatabaseAccessor<Drift> with $MemoryRepositoryMix
|
||||
return const [];
|
||||
}
|
||||
|
||||
final Map<String, DriftMemory> memoriesMap = {};
|
||||
final Map<String, Memory> memoriesMap = {};
|
||||
|
||||
for (final row in rows) {
|
||||
final memory = row.readTable(_db.memoryEntity);
|
||||
@@ -63,7 +63,7 @@ class MemoryRepository extends DatabaseAccessor<Drift> with $MemoryRepositoryMix
|
||||
return memoriesMap.values.toList(growable: false);
|
||||
}
|
||||
|
||||
Future<DriftMemory?> get(String memoryId) async {
|
||||
Future<Memory?> get(String memoryId) async {
|
||||
final query =
|
||||
_db.select(_db.memoryEntity).join([
|
||||
leftOuterJoin(_db.memoryAssetEntity, _db.memoryAssetEntity.memoryId.equalsExp(_db.memoryEntity.id)),
|
||||
@@ -101,8 +101,8 @@ class MemoryRepository extends DatabaseAccessor<Drift> with $MemoryRepositoryMix
|
||||
}
|
||||
|
||||
extension on MemoryEntityData {
|
||||
DriftMemory toDto() {
|
||||
return DriftMemory(
|
||||
Memory toDto() {
|
||||
return Memory(
|
||||
id: id,
|
||||
createdAt: createdAt,
|
||||
updatedAt: updatedAt,
|
||||
|
||||
+22
-22
@@ -12,8 +12,8 @@ import 'package:immich_mobile/extensions/theme_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/backup/backup_toggle_button.widget.dart';
|
||||
import 'package:immich_mobile/providers/background_sync.provider.dart';
|
||||
import 'package:immich_mobile/providers/backup/backup.provider.dart';
|
||||
import 'package:immich_mobile/providers/backup/backup_album.provider.dart';
|
||||
import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
|
||||
import 'package:immich_mobile/providers/permission.provider.dart';
|
||||
import 'package:immich_mobile/providers/sync_status.provider.dart';
|
||||
@@ -27,14 +27,14 @@ import 'package:url_launcher/url_launcher.dart';
|
||||
import 'package:wakelock_plus/wakelock_plus.dart';
|
||||
|
||||
@RoutePage()
|
||||
class DriftBackupPage extends ConsumerStatefulWidget {
|
||||
const DriftBackupPage({super.key});
|
||||
class BackupPage extends ConsumerStatefulWidget {
|
||||
const BackupPage({super.key});
|
||||
|
||||
@override
|
||||
ConsumerState<DriftBackupPage> createState() => _DriftBackupPageState();
|
||||
ConsumerState<BackupPage> createState() => _BackupPageState();
|
||||
}
|
||||
|
||||
class _DriftBackupPageState extends ConsumerState<DriftBackupPage> {
|
||||
class _BackupPageState extends ConsumerState<BackupPage> {
|
||||
bool? syncSuccess;
|
||||
|
||||
@override
|
||||
@@ -49,7 +49,7 @@ class _DriftBackupPageState extends ConsumerState<DriftBackupPage> {
|
||||
}
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||
final backupNotifier = ref.read(driftBackupProvider.notifier);
|
||||
final backupNotifier = ref.read(backupProvider.notifier);
|
||||
final syncManager = ref.read(backgroundSyncProvider);
|
||||
|
||||
await backupNotifier.getBackupStatus(currentUser.id);
|
||||
@@ -77,9 +77,9 @@ class _DriftBackupPageState extends ConsumerState<DriftBackupPage> {
|
||||
.where((album) => album.backupSelection == BackupSelection.selected)
|
||||
.toList();
|
||||
|
||||
final error = ref.watch(driftBackupProvider.select((p) => p.error));
|
||||
final error = ref.watch(backupProvider.select((p) => p.error));
|
||||
|
||||
final backupNotifier = ref.watch(driftBackupProvider.notifier);
|
||||
final backupNotifier = ref.watch(backupProvider.notifier);
|
||||
final backupSyncManager = ref.watch(backgroundSyncProvider);
|
||||
|
||||
Future<void> startBackup() async {
|
||||
@@ -97,7 +97,7 @@ class _DriftBackupPageState extends ConsumerState<DriftBackupPage> {
|
||||
await backupNotifier.getBackupStatus(currentUser.id);
|
||||
|
||||
if (syncSuccess == false) {
|
||||
Logger("DriftBackupPage").warning("Remote sync did not complete successfully, skipping backup");
|
||||
Logger("BackupPage").warning("Remote sync did not complete successfully, skipping backup");
|
||||
return;
|
||||
}
|
||||
await backupNotifier.startForegroundBackup(currentUser.id);
|
||||
@@ -117,7 +117,7 @@ class _DriftBackupPageState extends ConsumerState<DriftBackupPage> {
|
||||
actions: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
unawaited(context.pushRoute(const DriftBackupOptionsRoute()));
|
||||
unawaited(context.pushRoute(const BackupOptionsRoute()));
|
||||
},
|
||||
icon: const Icon(Icons.settings_outlined),
|
||||
tooltip: context.t.backup_options,
|
||||
@@ -303,7 +303,7 @@ class _BackupFooterState extends ConsumerState<_BackupFooter> with WidgetsBindin
|
||||
],
|
||||
TextButton.icon(
|
||||
icon: const Icon(Icons.info_outline_rounded),
|
||||
onPressed: () => context.pushRoute(const DriftUploadDetailRoute()),
|
||||
onPressed: () => context.pushRoute(const UploadDetailRoute()),
|
||||
label: Text(context.t.view_details),
|
||||
),
|
||||
],
|
||||
@@ -396,7 +396,7 @@ class _BackupAlbumSelectionCard extends ConsumerWidget {
|
||||
),
|
||||
trailing: ElevatedButton(
|
||||
onPressed: () async {
|
||||
await context.pushRoute(const DriftBackupAlbumSelectionRoute());
|
||||
await context.pushRoute(const BackupAlbumSelectionRoute());
|
||||
if (!context.mounted) {
|
||||
return;
|
||||
}
|
||||
@@ -405,7 +405,7 @@ class _BackupAlbumSelectionCard extends ConsumerWidget {
|
||||
if (currentUser == null) {
|
||||
return;
|
||||
}
|
||||
unawaited(ref.read(driftBackupProvider.notifier).getBackupStatus(currentUser.id));
|
||||
unawaited(ref.read(backupProvider.notifier).getBackupStatus(currentUser.id));
|
||||
},
|
||||
child: Text(context.t.select, style: const TextStyle(fontWeight: FontWeight.bold)),
|
||||
),
|
||||
@@ -419,7 +419,7 @@ class _TotalCard extends ConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final totalCount = ref.watch(driftBackupProvider.select((p) => p.totalCount));
|
||||
final totalCount = ref.watch(backupProvider.select((p) => p.totalCount));
|
||||
|
||||
return BackupInfoCard(
|
||||
title: context.t.total,
|
||||
@@ -434,7 +434,7 @@ class _BackupCard extends ConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final backupCount = ref.watch(driftBackupProvider.select((p) => p.backupCount));
|
||||
final backupCount = ref.watch(backupProvider.select((p) => p.backupCount));
|
||||
final syncStatus = ref.watch(syncStatusProvider);
|
||||
|
||||
return BackupInfoCard(
|
||||
@@ -451,7 +451,7 @@ class _RemainderCard extends ConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final remainderCount = ref.watch(driftBackupProvider.select((p) => p.remainderCount));
|
||||
final remainderCount = ref.watch(backupProvider.select((p) => p.remainderCount));
|
||||
final syncStatus = ref.watch(syncStatusProvider);
|
||||
|
||||
return Card(
|
||||
@@ -522,7 +522,7 @@ class _RemainderCard extends ConsumerWidget {
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.only(bottomLeft: Radius.circular(20), bottomRight: Radius.circular(20)),
|
||||
),
|
||||
onTap: () => context.pushRoute(const DriftBackupAssetDetailRoute()),
|
||||
onTap: () => context.pushRoute(const BackupAssetDetailRoute()),
|
||||
title: Text(
|
||||
context.t.view_details,
|
||||
style: context.textTheme.labelLarge?.copyWith(color: context.colorScheme.onSurface.withAlpha(200)),
|
||||
@@ -559,7 +559,7 @@ class _PreparingStatusState extends ConsumerState {
|
||||
_pollingTimer = Timer.periodic(const Duration(seconds: 3), (timer) async {
|
||||
final currentUser = ref.read(currentUserProvider);
|
||||
if (currentUser != null && mounted) {
|
||||
await ref.read(driftBackupProvider.notifier).getBackupStatus(currentUser.id);
|
||||
await ref.read(backupProvider.notifier).getBackupStatus(currentUser.id);
|
||||
if (!context.mounted) {
|
||||
timer.cancel();
|
||||
_pollingTimer = null;
|
||||
@@ -567,7 +567,7 @@ class _PreparingStatusState extends ConsumerState {
|
||||
}
|
||||
|
||||
// Stop polling if processing count reaches 0
|
||||
final updatedProcessingCount = ref.read(driftBackupProvider.select((p) => p.processingCount));
|
||||
final updatedProcessingCount = ref.read(backupProvider.select((p) => p.processingCount));
|
||||
if (updatedProcessingCount == 0) {
|
||||
timer.cancel();
|
||||
_pollingTimer = null;
|
||||
@@ -582,11 +582,11 @@ class _PreparingStatusState extends ConsumerState {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final syncStatus = ref.watch(syncStatusProvider);
|
||||
final remainderCount = ref.watch(driftBackupProvider.select((p) => p.remainderCount));
|
||||
final processingCount = ref.watch(driftBackupProvider.select((p) => p.processingCount));
|
||||
final remainderCount = ref.watch(backupProvider.select((p) => p.remainderCount));
|
||||
final processingCount = ref.watch(backupProvider.select((p) => p.processingCount));
|
||||
final readyForUploadCount = remainderCount - processingCount;
|
||||
|
||||
ref.listen<int>(driftBackupProvider.select((p) => p.processingCount), (previous, next) {
|
||||
ref.listen<int>(backupProvider.select((p) => p.processingCount), (previous, next) {
|
||||
if (next > 0 && _pollingTimer == null) {
|
||||
_startPollingIfNeeded();
|
||||
} else if (next == 0 && _pollingTimer != null) {
|
||||
+13
-13
@@ -9,12 +9,12 @@ import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/settings.repository.dart';
|
||||
import 'package:immich_mobile/providers/background_sync.provider.dart';
|
||||
import 'package:immich_mobile/providers/backup/backup.provider.dart';
|
||||
import 'package:immich_mobile/providers/backup/backup_album.provider.dart';
|
||||
import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/platform.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
|
||||
import 'package:immich_mobile/providers/user.provider.dart';
|
||||
import 'package:immich_mobile/widgets/backup/drift_album_info_list_tile.dart';
|
||||
import 'package:immich_mobile/widgets/backup/album_info_list_tile.dart';
|
||||
import 'package:immich_mobile/widgets/common/search_field.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
@@ -24,14 +24,14 @@ final backupAlbumCountProvider = FutureProvider.autoDispose<int>((ref) async {
|
||||
});
|
||||
|
||||
@RoutePage()
|
||||
class DriftBackupAlbumSelectionPage extends ConsumerStatefulWidget {
|
||||
const DriftBackupAlbumSelectionPage({super.key});
|
||||
class BackupAlbumSelectionPage extends ConsumerStatefulWidget {
|
||||
const BackupAlbumSelectionPage({super.key});
|
||||
|
||||
@override
|
||||
ConsumerState<DriftBackupAlbumSelectionPage> createState() => _DriftBackupAlbumSelectionPageState();
|
||||
ConsumerState<BackupAlbumSelectionPage> createState() => _BackupAlbumSelectionPageState();
|
||||
}
|
||||
|
||||
class _DriftBackupAlbumSelectionPageState extends ConsumerState<DriftBackupAlbumSelectionPage> {
|
||||
class _BackupAlbumSelectionPageState extends ConsumerState<BackupAlbumSelectionPage> {
|
||||
String _searchQuery = '';
|
||||
bool _isSearchMode = false;
|
||||
int _initialTotalAssetCount = 0;
|
||||
@@ -49,7 +49,7 @@ class _DriftBackupAlbumSelectionPageState extends ConsumerState<DriftBackupAlbum
|
||||
|
||||
_enableSyncUploadAlbum.value = ref.read(appConfigProvider).backup.syncAlbums;
|
||||
|
||||
_initialTotalAssetCount = ref.read(driftBackupProvider.select((p) => p.totalCount));
|
||||
_initialTotalAssetCount = ref.read(backupProvider.select((p) => p.totalCount));
|
||||
}
|
||||
|
||||
Future<void> _handlePagePopped() async {
|
||||
@@ -111,14 +111,14 @@ class _DriftBackupAlbumSelectionPageState extends ConsumerState<DriftBackupAlbum
|
||||
}
|
||||
|
||||
final isBackupEnabled = SettingsRepository.instance.appConfig.backup.enabled;
|
||||
await ref.read(driftBackupProvider.notifier).getBackupStatus(user.id);
|
||||
await ref.read(backupProvider.notifier).getBackupStatus(user.id);
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
final currentTotalAssetCount = ref.read(driftBackupProvider.select((p) => p.totalCount));
|
||||
final currentTotalAssetCount = ref.read(backupProvider.select((p) => p.totalCount));
|
||||
final totalChanged = currentTotalAssetCount != _initialTotalAssetCount;
|
||||
final backupNotifier = ref.read(driftBackupProvider.notifier);
|
||||
final backupNotifier = ref.read(backupProvider.notifier);
|
||||
final backgroundSync = ref.read(backgroundSyncProvider);
|
||||
final nativeSync = ref.read(nativeSyncApiProvider);
|
||||
if (totalChanged) {
|
||||
@@ -131,7 +131,7 @@ class _DriftBackupAlbumSelectionPageState extends ConsumerState<DriftBackupAlbum
|
||||
if (success) {
|
||||
return backupNotifier.startForegroundBackup(user.id);
|
||||
} else {
|
||||
Logger('DriftBackupAlbumSelectionPage').warning('Background sync failed, not starting backup');
|
||||
Logger('BackupAlbumSelectionPage').warning('Background sync failed, not starting backup');
|
||||
}
|
||||
}),
|
||||
);
|
||||
@@ -328,7 +328,7 @@ class _AlbumSelectionList extends StatelessWidget {
|
||||
padding: const EdgeInsets.symmetric(vertical: 12.0),
|
||||
sliver: SliverList(
|
||||
delegate: SliverChildBuilderDelegate((context, index) {
|
||||
return DriftAlbumInfoListTile(album: filteredAlbums[index]);
|
||||
return AlbumInfoListTile(album: filteredAlbums[index]);
|
||||
}, childCount: filteredAlbums.length),
|
||||
),
|
||||
);
|
||||
@@ -352,7 +352,7 @@ class _AlbumSelectionGrid extends StatelessWidget {
|
||||
),
|
||||
itemCount: filteredAlbums.length,
|
||||
itemBuilder: (context, index) {
|
||||
return DriftAlbumInfoListTile(album: filteredAlbums[index]);
|
||||
return AlbumInfoListTile(album: filteredAlbums[index]);
|
||||
},
|
||||
),
|
||||
);
|
||||
+5
-5
@@ -9,17 +9,17 @@ import 'package:immich_mobile/extensions/theme_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/pages/common/large_leading_tile.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/images/thumbnail.widget.dart';
|
||||
import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
|
||||
import 'package:immich_mobile/providers/backup/backup.provider.dart';
|
||||
import 'package:immich_mobile/repositories/asset_media.repository.dart';
|
||||
import 'package:immich_mobile/routing/router.dart';
|
||||
|
||||
@RoutePage()
|
||||
class DriftBackupAssetDetailPage extends ConsumerWidget {
|
||||
const DriftBackupAssetDetailPage({super.key});
|
||||
class BackupAssetDetailPage extends ConsumerWidget {
|
||||
const BackupAssetDetailPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final AsyncValue<List<LocalAsset>> result = ref.watch(driftBackupCandidateProvider);
|
||||
final AsyncValue<List<LocalAsset>> result = ref.watch(backupCandidateProvider);
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text(context.t.backup_controller_page_remainder)),
|
||||
body: result.when(
|
||||
@@ -30,7 +30,7 @@ class DriftBackupAssetDetailPage extends ConsumerWidget {
|
||||
itemCount: candidates.length,
|
||||
itemBuilder: (context, index) {
|
||||
final asset = candidates[index];
|
||||
final albumsAsyncValue = ref.watch(driftCandidateBackupAlbumInfoProvider(asset.id));
|
||||
final albumsAsyncValue = ref.watch(candidateBackupAlbumInfoProvider(asset.id));
|
||||
final assetMediaRepository = ref.watch(assetMediaRepositoryProvider);
|
||||
return FutureBuilder<String?>(
|
||||
future: assetMediaRepository.getOriginalFilename(asset.id),
|
||||
+8
-8
@@ -6,15 +6,15 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/settings.repository.dart';
|
||||
import 'package:immich_mobile/providers/background_sync.provider.dart';
|
||||
import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
|
||||
import 'package:immich_mobile/providers/backup/backup.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
|
||||
import 'package:immich_mobile/providers/user.provider.dart';
|
||||
import 'package:immich_mobile/widgets/settings/backup_settings/drift_backup_settings.dart';
|
||||
import 'package:immich_mobile/widgets/settings/backup_settings/backup_settings.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
@RoutePage()
|
||||
class DriftBackupOptionsPage extends ConsumerWidget {
|
||||
const DriftBackupOptionsPage({super.key});
|
||||
class BackupOptionsPage extends ConsumerWidget {
|
||||
const BackupOptionsPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
@@ -44,7 +44,7 @@ class DriftBackupOptionsPage extends ConsumerWidget {
|
||||
return;
|
||||
}
|
||||
|
||||
await ref.read(driftBackupProvider.notifier).getBackupStatus(currentUser.id);
|
||||
await ref.read(backupProvider.notifier).getBackupStatus(currentUser.id);
|
||||
final isBackupEnabled = SettingsRepository.instance.appConfig.backup.enabled;
|
||||
if (!isBackupEnabled || !context.mounted) {
|
||||
return;
|
||||
@@ -54,7 +54,7 @@ class DriftBackupOptionsPage extends ConsumerWidget {
|
||||
SnackBar(content: Text(context.t.network_requirements_updated), duration: const Duration(seconds: 4)),
|
||||
);
|
||||
|
||||
final backupNotifier = ref.read(driftBackupProvider.notifier);
|
||||
final backupNotifier = ref.read(backupProvider.notifier);
|
||||
final backgroundSync = ref.read(backgroundSyncProvider);
|
||||
backupNotifier.stopForegroundBackup(reason: "backup settings updated");
|
||||
unawaited(
|
||||
@@ -62,7 +62,7 @@ class DriftBackupOptionsPage extends ConsumerWidget {
|
||||
if (success) {
|
||||
return backupNotifier.startForegroundBackup(currentUser.id);
|
||||
} else {
|
||||
Logger('DriftBackupOptionsPage').warning('Background sync failed, not starting backup');
|
||||
Logger('BackupOptionsPage').warning('Background sync failed, not starting backup');
|
||||
}
|
||||
}),
|
||||
);
|
||||
@@ -70,7 +70,7 @@ class DriftBackupOptionsPage extends ConsumerWidget {
|
||||
},
|
||||
child: Scaffold(
|
||||
appBar: AppBar(title: Text(context.t.backup_options)),
|
||||
body: const DriftBackupSettings(),
|
||||
body: const BackupSettings(),
|
||||
),
|
||||
);
|
||||
}
|
||||
+15
-15
@@ -5,20 +5,20 @@ import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/images/thumbnail.widget.dart';
|
||||
import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
|
||||
import 'package:immich_mobile/providers/backup/backup.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
|
||||
import 'package:immich_mobile/utils/bytes_units.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
@RoutePage()
|
||||
class DriftUploadDetailPage extends ConsumerStatefulWidget {
|
||||
const DriftUploadDetailPage({super.key});
|
||||
class UploadDetailPage extends ConsumerStatefulWidget {
|
||||
const UploadDetailPage({super.key});
|
||||
|
||||
@override
|
||||
ConsumerState<DriftUploadDetailPage> createState() => _DriftUploadDetailPageState();
|
||||
ConsumerState<UploadDetailPage> createState() => _UploadDetailPageState();
|
||||
}
|
||||
|
||||
class _DriftUploadDetailPageState extends ConsumerState<DriftUploadDetailPage> {
|
||||
class _UploadDetailPageState extends ConsumerState<UploadDetailPage> {
|
||||
final Set<String> _seenTaskIds = {};
|
||||
final Set<String> _failedTaskIds = {};
|
||||
|
||||
@@ -26,8 +26,8 @@ class _DriftUploadDetailPageState extends ConsumerState<DriftUploadDetailPage> {
|
||||
static const int _maxSlots = 3;
|
||||
|
||||
/// Assigns uploading items to fixed slots to prevent jumping when items complete
|
||||
List<DriftUploadStatus?> _assignItemsToSlots(List<DriftUploadStatus> uploadingItems) {
|
||||
final slots = List<DriftUploadStatus?>.filled(_maxSlots, null);
|
||||
List<UploadStatus?> _assignItemsToSlots(List<UploadStatus> uploadingItems) {
|
||||
final slots = List<UploadStatus?>.filled(_maxSlots, null);
|
||||
final currentTaskIds = uploadingItems.map((e) => e.taskId).toSet();
|
||||
|
||||
_taskSlotAssignments.removeWhere((taskId, _) => !currentTaskIds.contains(taskId));
|
||||
@@ -58,8 +58,8 @@ class _DriftUploadDetailPageState extends ConsumerState<DriftUploadDetailPage> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final uploadItems = ref.watch(driftBackupProvider.select((state) => state.uploadItems));
|
||||
final iCloudProgress = ref.watch(driftBackupProvider.select((state) => state.iCloudDownloadProgress));
|
||||
final uploadItems = ref.watch(backupProvider.select((state) => state.uploadItems));
|
||||
final iCloudProgress = ref.watch(backupProvider.select((state) => state.iCloudDownloadProgress));
|
||||
|
||||
for (final item in uploadItems.values) {
|
||||
if (item.isFailed == true) {
|
||||
@@ -91,8 +91,8 @@ class _DriftUploadDetailPageState extends ConsumerState<DriftUploadDetailPage> {
|
||||
|
||||
Widget _buildTwoSectionLayout(
|
||||
BuildContext context,
|
||||
List<DriftUploadStatus> uploadingItems,
|
||||
List<DriftUploadStatus> failedItems,
|
||||
List<UploadStatus> uploadingItems,
|
||||
List<UploadStatus> failedItems,
|
||||
Map<String, double> iCloudProgress,
|
||||
) {
|
||||
return CustomScrollView(
|
||||
@@ -276,7 +276,7 @@ class _DriftUploadDetailPageState extends ConsumerState<DriftUploadDetailPage> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildCurrentUploadCard(BuildContext context, DriftUploadStatus item) {
|
||||
Widget _buildCurrentUploadCard(BuildContext context, UploadStatus item) {
|
||||
final double progressPercentage = (item.progress * 100).clamp(0, 100);
|
||||
final isFailed = item.isFailed == true;
|
||||
|
||||
@@ -365,7 +365,7 @@ class _DriftUploadDetailPageState extends ConsumerState<DriftUploadDetailPage> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildErrorCard(BuildContext context, DriftUploadStatus item) {
|
||||
Widget _buildErrorCard(BuildContext context, UploadStatus item) {
|
||||
return Card(
|
||||
elevation: 0,
|
||||
color: context.colorScheme.errorContainer,
|
||||
@@ -493,7 +493,7 @@ class _DriftUploadDetailPageState extends ConsumerState<DriftUploadDetailPage> {
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _showFileDetailDialog(BuildContext context, DriftUploadStatus item) {
|
||||
Future<void> _showFileDetailDialog(BuildContext context, UploadStatus item) {
|
||||
return showDialog(
|
||||
context: context,
|
||||
builder: (context) => FileDetailDialog(uploadStatus: item),
|
||||
@@ -538,7 +538,7 @@ class _CurrentUploadThumbnail extends ConsumerWidget {
|
||||
}
|
||||
|
||||
class FileDetailDialog extends ConsumerWidget {
|
||||
final DriftUploadStatus uploadStatus;
|
||||
final UploadStatus uploadStatus;
|
||||
const FileDetailDialog({super.key, required this.uploadStatus});
|
||||
|
||||
@override
|
||||
@@ -7,7 +7,7 @@ import 'package:immich_mobile/routing/router.dart';
|
||||
import 'package:immich_mobile/widgets/settings/advanced_settings.dart';
|
||||
import 'package:immich_mobile/widgets/settings/asset_list_settings/asset_list_settings.dart';
|
||||
import 'package:immich_mobile/widgets/settings/asset_viewer_settings/asset_viewer_settings.dart';
|
||||
import 'package:immich_mobile/widgets/settings/backup_settings/drift_backup_settings.dart';
|
||||
import 'package:immich_mobile/widgets/settings/backup_settings/backup_settings.dart';
|
||||
import 'package:immich_mobile/widgets/settings/beta_sync_settings/sync_status_and_actions.dart';
|
||||
import 'package:immich_mobile/widgets/settings/free_up_space_settings.dart';
|
||||
import 'package:immich_mobile/widgets/settings/language_settings.dart';
|
||||
@@ -59,7 +59,7 @@ enum SettingSection {
|
||||
Widget get widget => switch (this) {
|
||||
SettingSection.advanced => const AdvancedSettings(),
|
||||
SettingSection.assetViewer => const AssetViewerSettings(),
|
||||
SettingSection.backup => const DriftBackupSettings(),
|
||||
SettingSection.backup => const BackupSettings(),
|
||||
SettingSection.freeUpSpace => const FreeUpSpaceSettings(),
|
||||
SettingSection.languages => const LanguageSettings(),
|
||||
SettingSection.networking => const NetworkingSettings(),
|
||||
|
||||
@@ -15,7 +15,7 @@ import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/settings.repository.dart';
|
||||
import 'package:immich_mobile/providers/auth.provider.dart';
|
||||
import 'package:immich_mobile/providers/background_sync.provider.dart';
|
||||
import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
|
||||
import 'package:immich_mobile/providers/backup/backup.provider.dart';
|
||||
import 'package:immich_mobile/providers/server_info.provider.dart';
|
||||
import 'package:immich_mobile/providers/view_intent/view_intent_handler.provider.dart';
|
||||
import 'package:immich_mobile/providers/websocket.provider.dart';
|
||||
@@ -310,7 +310,7 @@ class SplashScreenPageState extends ConsumerState<SplashScreenPage> {
|
||||
final infoProvider = ref.read(serverInfoProvider.notifier);
|
||||
final wsProvider = ref.read(websocketProvider.notifier);
|
||||
final backgroundManager = ref.read(backgroundSyncProvider);
|
||||
final backupProvider = ref.read(driftBackupProvider.notifier);
|
||||
final backupNotifier = ref.read(backupProvider.notifier);
|
||||
final viewIntentHandler = ref.read(viewIntentHandlerProvider);
|
||||
|
||||
unawaited(
|
||||
@@ -334,9 +334,9 @@ class SplashScreenPageState extends ConsumerState<SplashScreenPage> {
|
||||
if (syncSuccess) {
|
||||
await Future.wait([
|
||||
backgroundManager.hashAssets().then((_) {
|
||||
unawaited(_resumeBackup(backupProvider));
|
||||
unawaited(_resumeBackup(backupNotifier));
|
||||
}),
|
||||
_resumeBackup(backupProvider),
|
||||
_resumeBackup(backupNotifier),
|
||||
// TODO: Bring back when the soft freeze issue is addressed
|
||||
// backgroundManager.syncCloudIds(),
|
||||
]);
|
||||
@@ -376,7 +376,7 @@ class SplashScreenPageState extends ConsumerState<SplashScreenPage> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _resumeBackup(DriftBackupNotifier notifier) async {
|
||||
Future<void> _resumeBackup(BackupNotifier notifier) async {
|
||||
final isEnableBackup = SettingsRepository.instance.appConfig.backup.enabled;
|
||||
|
||||
if (isEnableBackup) {
|
||||
|
||||
@@ -77,7 +77,7 @@ class _TabShellPageState extends ConsumerState<TabShellPage> {
|
||||
}
|
||||
|
||||
return AutoTabsRouter(
|
||||
routes: const [MainTimelineRoute(), DriftSearchRoute(), DriftAlbumsRoute(), DriftLibraryRoute()],
|
||||
routes: const [MainTimelineRoute(), SearchRoute(), AlbumsRoute(), LibraryRoute()],
|
||||
duration: const Duration(milliseconds: 600),
|
||||
transitionBuilder: (context, child, animation) => FadeTransition(opacity: animation, child: child),
|
||||
builder: (context, child) {
|
||||
@@ -111,7 +111,7 @@ void _onNavigationSelected(TabsRouter router, int index, WidgetRef ref) {
|
||||
}
|
||||
|
||||
if (index == kPhotoTabIndex) {
|
||||
ref.invalidate(driftMemoryLaneProvider);
|
||||
ref.invalidate(memoryLaneProvider);
|
||||
}
|
||||
|
||||
if (router.activeIndex != kSearchTabIndex && index == kSearchTabIndex) {
|
||||
|
||||
@@ -37,7 +37,7 @@ class PinAuthPage extends HookConsumerWidget {
|
||||
),
|
||||
);
|
||||
|
||||
unawaited(context.replaceRoute(const DriftLockedFolderRoute()));
|
||||
unawaited(context.replaceRoute(const LockedFolderRoute()));
|
||||
}
|
||||
|
||||
Future<void> enableBiometricAuth() {
|
||||
@@ -85,7 +85,7 @@ class PinAuthPage extends HookConsumerWidget {
|
||||
child: PinVerificationForm(
|
||||
autoFocus: true,
|
||||
onSuccess: (_) {
|
||||
unawaited(context.replaceRoute(const DriftLockedFolderRoute()));
|
||||
unawaited(context.replaceRoute(const LockedFolderRoute()));
|
||||
},
|
||||
),
|
||||
),
|
||||
|
||||
@@ -58,7 +58,7 @@ class EditAssetAction extends AssetActionBuilder {
|
||||
ref.read(editorStateProvider.notifier).init(edits, exif);
|
||||
unawaited(
|
||||
context.pushRoute(
|
||||
DriftEditImageRoute(
|
||||
EditImageRoute(
|
||||
image: Image(image: getFullImageProvider(asset, edited: false)),
|
||||
applyEdits: (newEdits) => applyEdits(ref, asset.id, newEdits),
|
||||
),
|
||||
|
||||
@@ -37,6 +37,6 @@ class SimilarPhotosAction extends ActionBuilder {
|
||||
),
|
||||
);
|
||||
|
||||
unawaited(context.navigateTo(const DriftSearchRoute()));
|
||||
unawaited(context.navigateTo(const SearchRoute()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ class SlideshowAction extends ActionBuilder {
|
||||
ActionItem create(BuildContext context, WidgetRef ref) => .new(
|
||||
icon: Icons.slideshow,
|
||||
label: context.t.slideshow,
|
||||
onAction: () async =>
|
||||
unawaited(context.pushRoute(DriftSlideshowRoute(timeline: ref.read(timelineServiceProvider)))),
|
||||
onAction: () async => unawaited(context.pushRoute(SlideshowRoute(timeline: ref.read(timelineServiceProvider)))),
|
||||
);
|
||||
}
|
||||
|
||||
+4
-4
@@ -8,18 +8,18 @@ import 'package:immich_mobile/domain/models/album/album.model.dart';
|
||||
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/action_buttons/like_activity_action_button.widget.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/album/drift_activity_text_field.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/album/activity_text_field.dart';
|
||||
import 'package:immich_mobile/providers/activity.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/current_album.provider.dart';
|
||||
import 'package:immich_mobile/widgets/activities/comment_bubble.dart';
|
||||
|
||||
@RoutePage()
|
||||
class DriftActivitiesPage extends HookConsumerWidget {
|
||||
class ActivitiesPage extends HookConsumerWidget {
|
||||
final RemoteAlbum album;
|
||||
final String? assetId;
|
||||
final String? assetName;
|
||||
|
||||
const DriftActivitiesPage({super.key, required this.album, this.assetId, this.assetName});
|
||||
const ActivitiesPage({super.key, required this.album, this.assetId, this.assetName});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
@@ -82,7 +82,7 @@ class DriftActivitiesPage extends HookConsumerWidget {
|
||||
color: context.scaffoldBackgroundColor,
|
||||
border: Border(top: BorderSide(color: context.colorScheme.secondaryContainer, width: 1)),
|
||||
),
|
||||
child: DriftActivityTextField(isEnabled: album.isActivityEnabled, onSubmit: onAddComment),
|
||||
child: ActivityTextField(isEnabled: album.isActivityEnabled, onSubmit: onAddComment),
|
||||
),
|
||||
),
|
||||
],
|
||||
+5
-5
@@ -10,14 +10,14 @@ import 'package:immich_mobile/routing/router.dart';
|
||||
import 'package:immich_mobile/widgets/common/immich_sliver_app_bar.dart';
|
||||
|
||||
@RoutePage()
|
||||
class DriftAlbumsPage extends ConsumerStatefulWidget {
|
||||
const DriftAlbumsPage({super.key});
|
||||
class AlbumsPage extends ConsumerStatefulWidget {
|
||||
const AlbumsPage({super.key});
|
||||
|
||||
@override
|
||||
ConsumerState<DriftAlbumsPage> createState() => _DriftAlbumsPageState();
|
||||
ConsumerState<AlbumsPage> createState() => _AlbumsPageState();
|
||||
}
|
||||
|
||||
class _DriftAlbumsPageState extends ConsumerState<DriftAlbumsPage> {
|
||||
class _AlbumsPageState extends ConsumerState<AlbumsPage> {
|
||||
final ScrollController _scrollController = ScrollController();
|
||||
|
||||
Future<void> onRefresh() async {
|
||||
@@ -45,7 +45,7 @@ class _DriftAlbumsPageState extends ConsumerState<DriftAlbumsPage> {
|
||||
pinned: true,
|
||||
actions: [
|
||||
IconButton(
|
||||
onPressed: () => context.pushRoute(const DriftCreateAlbumRoute()),
|
||||
onPressed: () => context.pushRoute(const CreateAlbumRoute()),
|
||||
icon: const Icon(Icons.add_rounded),
|
||||
),
|
||||
],
|
||||
+6
-6
@@ -11,7 +11,7 @@ import 'package:immich_mobile/domain/models/user.model.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/theme_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_user_selection.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/user_selection.page.dart';
|
||||
import 'package:immich_mobile/providers/auth.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/current_album.provider.dart';
|
||||
@@ -22,9 +22,9 @@ import 'package:immich_mobile/widgets/common/immich_toast.dart';
|
||||
import 'package:immich_mobile/widgets/common/user_circle_avatar.dart';
|
||||
|
||||
@RoutePage()
|
||||
class DriftAlbumOptionsPage extends HookConsumerWidget {
|
||||
class AlbumOptionsPage extends HookConsumerWidget {
|
||||
final RemoteAlbum album;
|
||||
const DriftAlbumOptionsPage({super.key, required this.album});
|
||||
const AlbumOptionsPage({super.key, required this.album});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
@@ -33,7 +33,7 @@ class DriftAlbumOptionsPage extends HookConsumerWidget {
|
||||
final activityEnabled = useState(album.isActivityEnabled);
|
||||
final isOwner = album.ownerId == userId;
|
||||
final owner = isOwner ? ref.watch(currentUserProvider) : null;
|
||||
final allUsers = isOwner ? null : ref.watch(driftUsersProvider);
|
||||
final allUsers = isOwner ? null : ref.watch(usersProvider);
|
||||
|
||||
void showErrorMessage() {
|
||||
ContextHelper(context).pop();
|
||||
@@ -52,7 +52,7 @@ class DriftAlbumOptionsPage extends HookConsumerWidget {
|
||||
return;
|
||||
}
|
||||
|
||||
unawaited(context.navigateTo(const DriftAlbumsRoute()));
|
||||
unawaited(context.navigateTo(const AlbumsRoute()));
|
||||
} catch (_) {
|
||||
showErrorMessage();
|
||||
}
|
||||
@@ -70,7 +70,7 @@ class DriftAlbumOptionsPage extends HookConsumerWidget {
|
||||
}
|
||||
|
||||
Future<void> addUsers() async {
|
||||
final newUsers = await context.pushRoute<List<String>>(DriftUserSelectionRoute(album: album));
|
||||
final newUsers = await context.pushRoute<List<String>>(UserSelectionRoute(album: album));
|
||||
|
||||
if (newUsers == null || newUsers.isEmpty) {
|
||||
return;
|
||||
+2
-2
@@ -9,8 +9,8 @@ import 'package:immich_mobile/providers/user.provider.dart';
|
||||
import 'package:immich_mobile/widgets/common/mesmerizing_sliver_app_bar.dart';
|
||||
|
||||
@RoutePage()
|
||||
class DriftArchivePage extends StatelessWidget {
|
||||
const DriftArchivePage({super.key});
|
||||
class ArchivePage extends StatelessWidget {
|
||||
const ArchivePage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
+2
-2
@@ -7,9 +7,9 @@ import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
|
||||
import 'package:immich_mobile/providers/timeline/multiselect.provider.dart';
|
||||
|
||||
@RoutePage()
|
||||
class DriftAssetSelectionTimelinePage extends StatelessWidget {
|
||||
class AssetSelectionTimelinePage extends StatelessWidget {
|
||||
final Set<BaseAsset> lockedSelectionAssets;
|
||||
const DriftAssetSelectionTimelinePage({super.key, this.lockedSelectionAssets = const {}});
|
||||
const AssetSelectionTimelinePage({super.key, this.lockedSelectionAssets = const {}});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
+5
-5
@@ -13,14 +13,14 @@ import 'package:immich_mobile/widgets/album/album_action_filled_button.dart';
|
||||
import 'package:immich_mobile/widgets/common/immich_toast.dart';
|
||||
|
||||
@RoutePage()
|
||||
class DriftCreateAlbumPage extends ConsumerStatefulWidget {
|
||||
const DriftCreateAlbumPage({super.key});
|
||||
class CreateAlbumPage extends ConsumerStatefulWidget {
|
||||
const CreateAlbumPage({super.key});
|
||||
|
||||
@override
|
||||
ConsumerState<DriftCreateAlbumPage> createState() => _DriftCreateAlbumPageState();
|
||||
ConsumerState<CreateAlbumPage> createState() => _CreateAlbumPageState();
|
||||
}
|
||||
|
||||
class _DriftCreateAlbumPageState extends ConsumerState<DriftCreateAlbumPage> {
|
||||
class _CreateAlbumPageState extends ConsumerState<CreateAlbumPage> {
|
||||
TextEditingController albumTitleController = TextEditingController();
|
||||
TextEditingController albumDescriptionController = TextEditingController();
|
||||
FocusNode albumTitleTextFieldFocusNode = FocusNode();
|
||||
@@ -153,7 +153,7 @@ class _DriftCreateAlbumPageState extends ConsumerState<DriftCreateAlbumPage> {
|
||||
|
||||
Future<void> onSelectPhotos() async {
|
||||
final assets = await context.pushRoute<Set<BaseAsset>>(
|
||||
DriftAssetSelectionTimelineRoute(lockedSelectionAssets: selectedAssets),
|
||||
AssetSelectionTimelineRoute(lockedSelectionAssets: selectedAssets),
|
||||
);
|
||||
|
||||
if (assets == null || assets.isEmpty) {
|
||||
@@ -39,9 +39,9 @@ class _MainTimelinePageState extends ConsumerState<MainTimelinePage> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final hasMemories = ref.watch(driftMemoryLaneProvider.select((state) => state.value?.isNotEmpty ?? false));
|
||||
final hasMemories = ref.watch(memoryLaneProvider.select((state) => state.value?.isNotEmpty ?? false));
|
||||
return Timeline(
|
||||
topSliverWidget: const SliverToBoxAdapter(child: DriftMemoryLane()),
|
||||
topSliverWidget: const SliverToBoxAdapter(child: MemoryLane()),
|
||||
topSliverWidgetHeight: hasMemories ? 200 : 0,
|
||||
showStorageIndicator: true,
|
||||
);
|
||||
|
||||
+4
-4
@@ -19,17 +19,17 @@ import 'package:immich_ui/immich_ui.dart';
|
||||
import 'package:openapi/api.dart' show MirrorAxis, MirrorParameters, RotateParameters;
|
||||
|
||||
@RoutePage()
|
||||
class DriftEditImagePage extends ConsumerStatefulWidget {
|
||||
class EditImagePage extends ConsumerStatefulWidget {
|
||||
final Image image;
|
||||
final Future<void> Function(List<AssetEdit> edits) applyEdits;
|
||||
|
||||
const DriftEditImagePage({super.key, required this.image, required this.applyEdits});
|
||||
const EditImagePage({super.key, required this.image, required this.applyEdits});
|
||||
|
||||
@override
|
||||
ConsumerState<DriftEditImagePage> createState() => _DriftEditImagePageState();
|
||||
ConsumerState<EditImagePage> createState() => _EditImagePageState();
|
||||
}
|
||||
|
||||
class _DriftEditImagePageState extends ConsumerState<DriftEditImagePage> with TickerProviderStateMixin {
|
||||
class _EditImagePageState extends ConsumerState<EditImagePage> with TickerProviderStateMixin {
|
||||
Future<void> _saveEditedImage() async {
|
||||
ref.read(editorStateProvider.notifier).setIsEditing(true);
|
||||
|
||||
+2
-2
@@ -9,8 +9,8 @@ import 'package:immich_mobile/providers/user.provider.dart';
|
||||
import 'package:immich_mobile/widgets/common/mesmerizing_sliver_app_bar.dart';
|
||||
|
||||
@RoutePage()
|
||||
class DriftFavoritePage extends StatelessWidget {
|
||||
const DriftFavoritePage({super.key});
|
||||
class FavoritePage extends StatelessWidget {
|
||||
const FavoritePage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
+12
-12
@@ -22,8 +22,8 @@ import 'package:immich_mobile/widgets/map/map_thumbnail.dart';
|
||||
import 'package:maplibre_gl/maplibre_gl.dart';
|
||||
|
||||
@RoutePage()
|
||||
class DriftLibraryPage extends StatelessWidget {
|
||||
const DriftLibraryPage({super.key});
|
||||
class LibraryPage extends StatelessWidget {
|
||||
const LibraryPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -56,13 +56,13 @@ class _ActionButtonGrid extends ConsumerWidget {
|
||||
children: [
|
||||
_ActionButton(
|
||||
icon: Icons.favorite_outline_rounded,
|
||||
onTap: () => context.pushRoute(const DriftFavoriteRoute()),
|
||||
onTap: () => context.pushRoute(const FavoriteRoute()),
|
||||
label: context.t.favorites,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
_ActionButton(
|
||||
icon: Icons.archive_outlined,
|
||||
onTap: () => context.pushRoute(const DriftArchiveRoute()),
|
||||
onTap: () => context.pushRoute(const ArchiveRoute()),
|
||||
label: context.t.archived,
|
||||
),
|
||||
],
|
||||
@@ -79,7 +79,7 @@ class _ActionButtonGrid extends ConsumerWidget {
|
||||
isTrashEnable
|
||||
? _ActionButton(
|
||||
icon: Icons.delete_outline_rounded,
|
||||
onTap: () => context.pushRoute(const DriftTrashRoute()),
|
||||
onTap: () => context.pushRoute(const TrashRoute()),
|
||||
label: context.t.trash,
|
||||
)
|
||||
: const SizedBox.shrink(),
|
||||
@@ -161,7 +161,7 @@ class _PeopleCollectionCard extends ConsumerWidget {
|
||||
final size = context.width * widthFactor - 20.0;
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () => context.pushRoute(const DriftPeopleCollectionRoute()),
|
||||
onTap: () => context.pushRoute(const PeopleCollectionRoute()),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@@ -226,7 +226,7 @@ class _PlacesCollectionCard extends StatelessWidget {
|
||||
final size = context.width * widthFactor - 20.0;
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () => context.pushRoute(DriftPlaceRoute(currentLocation: null)),
|
||||
onTap: () => context.pushRoute(PlaceRoute(currentLocation: null)),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@@ -280,7 +280,7 @@ class _LocalAlbumsCollectionCard extends ConsumerWidget {
|
||||
final size = context.width * widthFactor - 20.0;
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () => context.pushRoute(const DriftLocalAlbumsRoute()),
|
||||
onTap: () => context.pushRoute(const LocalAlbumsRoute()),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@@ -341,7 +341,7 @@ class _MemoriesCollectionCard extends ConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final memories = ref.watch(driftAllMemoriesProvider(false));
|
||||
final memories = ref.watch(allMemoriesProvider(false));
|
||||
|
||||
return LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
@@ -350,7 +350,7 @@ class _MemoriesCollectionCard extends ConsumerWidget {
|
||||
final size = context.width * widthFactor - 20.0;
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () => context.pushRoute(const DriftMemoryListRoute()),
|
||||
onTap: () => context.pushRoute(const MemoryListRoute()),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@@ -469,7 +469,7 @@ class _QuickAccessButtonList extends ConsumerWidget {
|
||||
context.t.locked_folder,
|
||||
style: context.textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w500),
|
||||
),
|
||||
onTap: () => context.pushRoute(const DriftLockedFolderRoute()),
|
||||
onTap: () => context.pushRoute(const LockedFolderRoute()),
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.group_outlined, size: 26),
|
||||
@@ -516,7 +516,7 @@ class _PartnerList extends StatelessWidget {
|
||||
context.t.partner_list_user_photos(user: partner.name),
|
||||
style: const TextStyle(fontWeight: FontWeight.w500),
|
||||
),
|
||||
onTap: () => context.pushRoute(DriftPartnerDetailRoute(partner: partner)),
|
||||
onTap: () => context.pushRoute(PartnerDetailRoute(partner: partner)),
|
||||
);
|
||||
},
|
||||
);
|
||||
+2
-2
@@ -11,8 +11,8 @@ import 'package:immich_mobile/routing/router.dart';
|
||||
import 'package:immich_mobile/widgets/common/local_album_sliver_app_bar.dart';
|
||||
|
||||
@RoutePage()
|
||||
class DriftLocalAlbumsPage extends StatelessWidget {
|
||||
const DriftLocalAlbumsPage({super.key});
|
||||
class LocalAlbumsPage extends StatelessWidget {
|
||||
const LocalAlbumsPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
+4
-4
@@ -13,14 +13,14 @@ import 'package:immich_mobile/routing/router.dart';
|
||||
import 'package:immich_mobile/widgets/common/mesmerizing_sliver_app_bar.dart';
|
||||
|
||||
@RoutePage()
|
||||
class DriftLockedFolderPage extends ConsumerStatefulWidget {
|
||||
const DriftLockedFolderPage({super.key});
|
||||
class LockedFolderPage extends ConsumerStatefulWidget {
|
||||
const LockedFolderPage({super.key});
|
||||
|
||||
@override
|
||||
ConsumerState<DriftLockedFolderPage> createState() => _DriftLockedFolderPageState();
|
||||
ConsumerState<LockedFolderPage> createState() => _LockedFolderPageState();
|
||||
}
|
||||
|
||||
class _DriftLockedFolderPageState extends ConsumerState<DriftLockedFolderPage> with WidgetsBindingObserver {
|
||||
class _LockedFolderPageState extends ConsumerState<LockedFolderPage> with WidgetsBindingObserver {
|
||||
bool _showOverlay = false;
|
||||
|
||||
@override
|
||||
+4
-4
@@ -8,10 +8,10 @@ import 'package:immich_mobile/presentation/widgets/map/map_settings_sheet.dart';
|
||||
import 'package:maplibre_gl/maplibre_gl.dart';
|
||||
|
||||
@RoutePage()
|
||||
class DriftMapPage extends StatelessWidget {
|
||||
class MapPage extends StatelessWidget {
|
||||
final LatLng? initialLocation;
|
||||
|
||||
const DriftMapPage({super.key, this.initialLocation});
|
||||
const MapPage({super.key, this.initialLocation});
|
||||
|
||||
Future<void> onSettingsPressed(BuildContext context) {
|
||||
return showModalBottomSheet(
|
||||
@@ -19,7 +19,7 @@ class DriftMapPage extends StatelessWidget {
|
||||
showDragHandle: true,
|
||||
isScrollControlled: true,
|
||||
context: context,
|
||||
builder: (_) => const DriftMapSettingsSheet(),
|
||||
builder: (_) => const MapSettingsSheet(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ class DriftMapPage extends StatelessWidget {
|
||||
extendBodyBehindAppBar: true,
|
||||
body: Stack(
|
||||
children: [
|
||||
DriftMap(initialLocation: initialLocation),
|
||||
MapView(initialLocation: initialLocation),
|
||||
Positioned(
|
||||
left: 20,
|
||||
top: 70,
|
||||
+7
-7
@@ -20,13 +20,13 @@ import 'package:immich_mobile/widgets/memories/memory_progress_indicator.dart';
|
||||
|
||||
/// Expects the current asset to be set via [assetViewerProvider] before navigating to this page
|
||||
@RoutePage()
|
||||
class DriftMemoryPage extends HookConsumerWidget {
|
||||
final List<DriftMemory> memories;
|
||||
class MemoryPage extends HookConsumerWidget {
|
||||
final List<Memory> memories;
|
||||
final int memoryIndex;
|
||||
|
||||
const DriftMemoryPage({required this.memories, required this.memoryIndex, super.key});
|
||||
const MemoryPage({required this.memories, required this.memoryIndex, super.key});
|
||||
|
||||
static void setMemory(WidgetRef ref, DriftMemory memory) {
|
||||
static void setMemory(WidgetRef ref, Memory memory) {
|
||||
if (memory.assets.isNotEmpty) {
|
||||
ref.read(assetViewerProvider.notifier).setAsset(memory.assets.first);
|
||||
}
|
||||
@@ -221,7 +221,7 @@ class DriftMemoryPage extends HookConsumerWidget {
|
||||
currentMemory.value = memories[pageNumber];
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
DriftMemoryPage.setMemory(ref, memories[pageNumber]);
|
||||
MemoryPage.setMemory(ref, memories[pageNumber]);
|
||||
});
|
||||
|
||||
// Update currentAsset to the first asset of the new memory
|
||||
@@ -285,7 +285,7 @@ class DriftMemoryPage extends HookConsumerWidget {
|
||||
children: [
|
||||
ColoredBox(
|
||||
color: Colors.black,
|
||||
child: DriftMemoryCard(
|
||||
child: MemoryCard(
|
||||
asset: asset,
|
||||
title: title,
|
||||
showTitle: index == 0,
|
||||
@@ -348,7 +348,7 @@ class DriftMemoryPage extends HookConsumerWidget {
|
||||
],
|
||||
),
|
||||
),
|
||||
DriftMemoryBottomInfo(memory: memories[mIndex], title: title),
|
||||
MemoryBottomInfo(memory: memories[mIndex], title: title),
|
||||
],
|
||||
);
|
||||
},
|
||||
+8
-8
@@ -6,25 +6,25 @@ import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_memory.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/memory.page.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/images/thumbnail.widget.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/memory.provider.dart';
|
||||
import 'package:immich_mobile/routing/router.dart';
|
||||
|
||||
@RoutePage()
|
||||
class DriftMemoryListPage extends ConsumerStatefulWidget {
|
||||
const DriftMemoryListPage({super.key});
|
||||
class MemoryListPage extends ConsumerStatefulWidget {
|
||||
const MemoryListPage({super.key});
|
||||
|
||||
@override
|
||||
ConsumerState<DriftMemoryListPage> createState() => _DriftMemoryListPageState();
|
||||
ConsumerState<MemoryListPage> createState() => _MemoryListPageState();
|
||||
}
|
||||
|
||||
class _DriftMemoryListPageState extends ConsumerState<DriftMemoryListPage> {
|
||||
class _MemoryListPageState extends ConsumerState<MemoryListPage> {
|
||||
bool _onlyFavorites = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final memories = ref.watch(driftAllMemoriesProvider(_onlyFavorites));
|
||||
final memories = ref.watch(allMemoriesProvider(_onlyFavorites));
|
||||
|
||||
return LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
@@ -54,8 +54,8 @@ class _DriftMemoryListPageState extends ConsumerState<DriftMemoryListPage> {
|
||||
itemCount: memories.length,
|
||||
itemBuilder: (context, index) => GestureDetector(
|
||||
onTap: () {
|
||||
DriftMemoryPage.setMemory(ref, memories[index]);
|
||||
unawaited(context.pushRoute(DriftMemoryRoute(memories: memories, memoryIndex: index)));
|
||||
MemoryPage.setMemory(ref, memories[index]);
|
||||
unawaited(context.pushRoute(MemoryRoute(memories: memories, memoryIndex: index)));
|
||||
},
|
||||
child: Stack(
|
||||
children: [
|
||||
+2
-2
@@ -13,10 +13,10 @@ import 'package:immich_mobile/widgets/common/immich_toast.dart';
|
||||
import 'package:immich_mobile/widgets/common/mesmerizing_sliver_app_bar.dart';
|
||||
|
||||
@RoutePage()
|
||||
class DriftPartnerDetailPage extends StatelessWidget {
|
||||
class PartnerDetailPage extends StatelessWidget {
|
||||
final Partner partner;
|
||||
|
||||
const DriftPartnerDetailPage({super.key, required this.partner});
|
||||
const PartnerDetailPage({super.key, required this.partner});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
+5
-5
@@ -15,14 +15,14 @@ import 'package:immich_mobile/utils/people.utils.dart';
|
||||
import 'package:immich_mobile/widgets/common/search_field.dart';
|
||||
|
||||
@RoutePage()
|
||||
class DriftPeopleCollectionPage extends ConsumerStatefulWidget {
|
||||
const DriftPeopleCollectionPage({super.key});
|
||||
class PeopleCollectionPage extends ConsumerStatefulWidget {
|
||||
const PeopleCollectionPage({super.key});
|
||||
|
||||
@override
|
||||
ConsumerState<DriftPeopleCollectionPage> createState() => _DriftPeopleCollectionPageState();
|
||||
ConsumerState<PeopleCollectionPage> createState() => _PeopleCollectionPageState();
|
||||
}
|
||||
|
||||
class _DriftPeopleCollectionPageState extends ConsumerState<DriftPeopleCollectionPage> {
|
||||
class _PeopleCollectionPageState extends ConsumerState<PeopleCollectionPage> {
|
||||
final FocusNode _formFocus = FocusNode();
|
||||
String? _search;
|
||||
|
||||
@@ -92,7 +92,7 @@ class _DriftPeopleCollectionPageState extends ConsumerState<DriftPeopleCollectio
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
unawaited(context.pushRoute(DriftPersonRoute(person: person)));
|
||||
unawaited(context.pushRoute(PersonRoute(person: person)));
|
||||
},
|
||||
child: Material(
|
||||
shape: const CircleBorder(side: BorderSide.none),
|
||||
+4
-4
@@ -13,16 +13,16 @@ import 'package:immich_mobile/utils/people.utils.dart';
|
||||
import 'package:immich_mobile/widgets/common/person_sliver_app_bar.dart';
|
||||
|
||||
@RoutePage()
|
||||
class DriftPersonPage extends ConsumerStatefulWidget {
|
||||
class PersonPage extends ConsumerStatefulWidget {
|
||||
final Person person;
|
||||
|
||||
const DriftPersonPage({super.key, required this.person});
|
||||
const PersonPage({super.key, required this.person});
|
||||
|
||||
@override
|
||||
ConsumerState<DriftPersonPage> createState() => _DriftPersonPageState();
|
||||
ConsumerState<PersonPage> createState() => _PersonPageState();
|
||||
}
|
||||
|
||||
class _DriftPersonPageState extends ConsumerState<DriftPersonPage> {
|
||||
class _PersonPageState extends ConsumerState<PersonPage> {
|
||||
late Person _person;
|
||||
|
||||
@override
|
||||
+4
-4
@@ -13,8 +13,8 @@ import 'package:immich_mobile/widgets/map/map_thumbnail.dart';
|
||||
import 'package:maplibre_gl/maplibre_gl.dart';
|
||||
|
||||
@RoutePage()
|
||||
class DriftPlacePage extends StatelessWidget {
|
||||
const DriftPlacePage({super.key, this.currentLocation});
|
||||
class PlacePage extends StatelessWidget {
|
||||
const PlacePage({super.key, this.currentLocation});
|
||||
|
||||
final LatLng? currentLocation;
|
||||
|
||||
@@ -94,7 +94,7 @@ class _Map extends StatelessWidget {
|
||||
height: 200,
|
||||
width: context.width,
|
||||
child: MapThumbnail(
|
||||
onTap: (_, _) => context.pushRoute(DriftMapRoute(initialLocation: currentLocation)),
|
||||
onTap: (_, _) => context.pushRoute(MapRoute(initialLocation: currentLocation)),
|
||||
zoom: 8,
|
||||
centre: currentLocation ?? const LatLng(21.44950, -157.91959),
|
||||
showAttribution: false,
|
||||
@@ -163,7 +163,7 @@ class _PlaceTile extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return LargeLeadingTile(
|
||||
onTap: () => context.pushRoute(DriftPlaceDetailRoute(place: place.$1)),
|
||||
onTap: () => context.pushRoute(PlaceDetailRoute(place: place.$1)),
|
||||
title: Text(place.$1, style: context.textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w500)),
|
||||
leading: ClipRRect(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(20)),
|
||||
+2
-2
@@ -6,10 +6,10 @@ import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
|
||||
import 'package:immich_mobile/widgets/common/mesmerizing_sliver_app_bar.dart';
|
||||
|
||||
@RoutePage()
|
||||
class DriftPlaceDetailPage extends StatelessWidget {
|
||||
class PlaceDetailPage extends StatelessWidget {
|
||||
final String place;
|
||||
|
||||
const DriftPlaceDetailPage({super.key, required this.place});
|
||||
const PlaceDetailPage({super.key, required this.place});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -11,7 +11,7 @@ import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/images/image_provider.dart';
|
||||
import 'package:immich_mobile/providers/auth.provider.dart';
|
||||
import 'package:immich_mobile/providers/backup/backup.provider.dart';
|
||||
import 'package:immich_mobile/providers/backup/backup_server.provider.dart';
|
||||
import 'package:immich_mobile/providers/upload_profile_image.provider.dart';
|
||||
import 'package:immich_mobile/providers/user.provider.dart';
|
||||
import 'package:immich_mobile/utils/image_converter.dart';
|
||||
@@ -89,7 +89,7 @@ class _ProfilePictureCropPageState extends ConsumerState<ProfilePictureCropPage>
|
||||
if (user != null) {
|
||||
unawaited(ref.read(currentUserProvider.notifier).refresh());
|
||||
}
|
||||
unawaited(ref.read(backupProvider.notifier).updateDiskInfo());
|
||||
unawaited(ref.read(backupServerProvider.notifier).updateDiskInfo());
|
||||
|
||||
ImmichToast.show(
|
||||
context: context,
|
||||
|
||||
+2
-2
@@ -8,8 +8,8 @@ import 'package:immich_mobile/providers/user.provider.dart';
|
||||
import 'package:immich_mobile/widgets/common/mesmerizing_sliver_app_bar.dart';
|
||||
|
||||
@RoutePage()
|
||||
class DriftRecentlyAddedPage extends StatelessWidget {
|
||||
const DriftRecentlyAddedPage({super.key});
|
||||
class RecentlyAddedPage extends StatelessWidget {
|
||||
const RecentlyAddedPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
+2
-2
@@ -8,8 +8,8 @@ import 'package:immich_mobile/providers/user.provider.dart';
|
||||
import 'package:immich_mobile/widgets/common/mesmerizing_sliver_app_bar.dart';
|
||||
|
||||
@RoutePage()
|
||||
class DriftRecentlyTakenPage extends StatelessWidget {
|
||||
const DriftRecentlyTakenPage({super.key});
|
||||
class RecentlyTakenPage extends StatelessWidget {
|
||||
const RecentlyTakenPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
+7
-7
@@ -10,7 +10,7 @@ import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/album/pending_uploads_banner.widget.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/bottom_sheet/remote_album_bottom_sheet.widget.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/remote_album/drift_album_option.widget.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/remote_album/album_option.widget.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/timeline/timeline.widget.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/current_album.provider.dart';
|
||||
@@ -47,7 +47,7 @@ class _RemoteAlbumPageState extends ConsumerState<RemoteAlbumPage> {
|
||||
}
|
||||
|
||||
final newAssets = await context.pushRoute<Set<BaseAsset>>(
|
||||
DriftAssetSelectionTimelineRoute(lockedSelectionAssets: albumAssets.toSet()),
|
||||
AssetSelectionTimelineRoute(lockedSelectionAssets: albumAssets.toSet()),
|
||||
);
|
||||
|
||||
if (newAssets == null || newAssets.isEmpty) {
|
||||
@@ -69,7 +69,7 @@ class _RemoteAlbumPageState extends ConsumerState<RemoteAlbumPage> {
|
||||
}
|
||||
|
||||
Future<void> addUsers(BuildContext context) async {
|
||||
final newUsers = await context.pushRoute<List<String>>(DriftUserSelectionRoute(album: _album));
|
||||
final newUsers = await context.pushRoute<List<String>>(UserSelectionRoute(album: _album));
|
||||
|
||||
if (newUsers == null || newUsers.isEmpty) {
|
||||
return;
|
||||
@@ -145,7 +145,7 @@ class _RemoteAlbumPageState extends ConsumerState<RemoteAlbumPage> {
|
||||
|
||||
ImmichToast.show(context: context, msg: context.t.album_deleted, toastType: ToastType.success);
|
||||
|
||||
unawaited(context.pushRoute(const DriftAlbumsRoute()));
|
||||
unawaited(context.pushRoute(const AlbumsRoute()));
|
||||
} catch (e) {
|
||||
if (!context.mounted) {
|
||||
return;
|
||||
@@ -180,7 +180,7 @@ class _RemoteAlbumPageState extends ConsumerState<RemoteAlbumPage> {
|
||||
}
|
||||
|
||||
Future<void> showActivity(BuildContext context) async {
|
||||
unawaited(context.pushRoute(DriftActivitiesRoute(album: _album)));
|
||||
unawaited(context.pushRoute(ActivitiesRoute(album: _album)));
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -209,7 +209,7 @@ class _RemoteAlbumPageState extends ConsumerState<RemoteAlbumPage> {
|
||||
onToggleAlbumOrder: () => toggleAlbumOrder(),
|
||||
onEditAlbum: () => showEditTitleAndDescription(context),
|
||||
onCreateSharedLink: () => unawaited(context.pushRoute(SharedLinkEditRoute(albumId: _album.id))),
|
||||
onShowOptions: () => context.pushRoute(DriftAlbumOptionsRoute(album: _album)),
|
||||
onShowOptions: () => context.pushRoute(AlbumOptionsRoute(album: _album)),
|
||||
),
|
||||
onEditTitle: isOwner ? () => showEditTitleAndDescription(context) : null,
|
||||
onActivity: () => showActivity(context),
|
||||
@@ -428,7 +428,7 @@ class _AlbumKebabMenu extends ConsumerWidget {
|
||||
builder: (context, snapshot) {
|
||||
final canAddPhotos = snapshot.data ?? false;
|
||||
|
||||
return DriftRemoteAlbumOption(
|
||||
return RemoteAlbumOption(
|
||||
iconColor: iconColor,
|
||||
iconShadows: iconShadows,
|
||||
onDeleteAlbum: isOwner ? onDeleteAlbum : null,
|
||||
+6
-6
@@ -37,8 +37,8 @@ import 'package:immich_mobile/widgets/search/search_filter/search_filter_utils.d
|
||||
import 'package:immich_mobile/widgets/search/search_filter/star_rating_picker.dart';
|
||||
|
||||
@RoutePage()
|
||||
class DriftSearchPage extends HookConsumerWidget {
|
||||
const DriftSearchPage({super.key});
|
||||
class SearchPage extends HookConsumerWidget {
|
||||
const SearchPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
@@ -892,23 +892,23 @@ class _QuickLinkList extends StatelessWidget {
|
||||
title: context.t.recently_taken,
|
||||
icon: Icons.schedule_outlined,
|
||||
isTop: true,
|
||||
onTap: () => context.pushRoute(const DriftRecentlyTakenRoute()),
|
||||
onTap: () => context.pushRoute(const RecentlyTakenRoute()),
|
||||
),
|
||||
_QuickLink(
|
||||
title: context.t.recently_added,
|
||||
icon: Icons.upload_outlined,
|
||||
onTap: () => context.pushRoute(const DriftRecentlyAddedRoute()),
|
||||
onTap: () => context.pushRoute(const RecentlyAddedRoute()),
|
||||
),
|
||||
_QuickLink(
|
||||
title: context.t.videos,
|
||||
icon: Icons.play_circle_outline_rounded,
|
||||
onTap: () => context.pushRoute(const DriftVideoRoute()),
|
||||
onTap: () => context.pushRoute(const VideoRoute()),
|
||||
),
|
||||
_QuickLink(
|
||||
title: context.t.favorites,
|
||||
icon: Icons.favorite_border_rounded,
|
||||
isBottom: true,
|
||||
onTap: () => context.pushRoute(const DriftFavoriteRoute()),
|
||||
onTap: () => context.pushRoute(const FavoriteRoute()),
|
||||
),
|
||||
],
|
||||
),
|
||||
+4
-4
@@ -26,16 +26,16 @@ import 'package:immich_mobile/widgets/photo_view/photo_view.dart';
|
||||
import 'package:wakelock_plus/wakelock_plus.dart';
|
||||
|
||||
@RoutePage()
|
||||
class DriftSlideshowPage extends ConsumerStatefulWidget {
|
||||
class SlideshowPage extends ConsumerStatefulWidget {
|
||||
final TimelineService timeline;
|
||||
|
||||
const DriftSlideshowPage({super.key, required this.timeline});
|
||||
const SlideshowPage({super.key, required this.timeline});
|
||||
|
||||
@override
|
||||
ConsumerState<DriftSlideshowPage> createState() => _DriftSlideshowPageState();
|
||||
ConsumerState<SlideshowPage> createState() => _SlideshowPageState();
|
||||
}
|
||||
|
||||
class _DriftSlideshowPageState extends ConsumerState<DriftSlideshowPage> with SingleTickerProviderStateMixin {
|
||||
class _SlideshowPageState extends ConsumerState<SlideshowPage> with SingleTickerProviderStateMixin {
|
||||
static const double _kenBurnsZoom = 0.1;
|
||||
|
||||
late SlideshowConfig _config;
|
||||
+2
-2
@@ -14,8 +14,8 @@ import 'package:immich_mobile/widgets/common/confirm_dialog.dart';
|
||||
import 'package:immich_mobile/widgets/common/immich_toast.dart';
|
||||
|
||||
@RoutePage()
|
||||
class DriftTrashPage extends StatelessWidget {
|
||||
const DriftTrashPage({super.key});
|
||||
class TrashPage extends StatelessWidget {
|
||||
const TrashPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
+4
-4
@@ -15,7 +15,7 @@ import 'package:immich_mobile/providers/user.provider.dart';
|
||||
import 'package:immich_mobile/widgets/common/user_circle_avatar.dart';
|
||||
|
||||
// TODO: Refactor this provider when we have user provider/service/repository pattern in place
|
||||
final driftUsersProvider = FutureProvider.autoDispose<List<UserDto>>((ref) async {
|
||||
final usersProvider = FutureProvider.autoDispose<List<UserDto>>((ref) async {
|
||||
final drift = ref.watch(driftProvider);
|
||||
final currentUser = ref.watch(currentUserProvider);
|
||||
|
||||
@@ -44,14 +44,14 @@ final driftUsersProvider = FutureProvider.autoDispose<List<UserDto>>((ref) async
|
||||
});
|
||||
|
||||
@RoutePage()
|
||||
class DriftUserSelectionPage extends HookConsumerWidget {
|
||||
class UserSelectionPage extends HookConsumerWidget {
|
||||
final RemoteAlbum album;
|
||||
|
||||
const DriftUserSelectionPage({super.key, required this.album});
|
||||
const UserSelectionPage({super.key, required this.album});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final AsyncValue<List<UserDto>> suggestedShareUsers = ref.watch(driftUsersProvider);
|
||||
final AsyncValue<List<UserDto>> suggestedShareUsers = ref.watch(usersProvider);
|
||||
final sharedUsers = ref.watch(remoteAlbumSharedUsersProvider(album.id));
|
||||
final sharedUsersList = useState<Set<UserDto>>({});
|
||||
|
||||
+2
-2
@@ -8,8 +8,8 @@ import 'package:immich_mobile/providers/user.provider.dart';
|
||||
import 'package:immich_mobile/widgets/common/mesmerizing_sliver_app_bar.dart';
|
||||
|
||||
@RoutePage()
|
||||
class DriftVideoPage extends StatelessWidget {
|
||||
const DriftVideoPage({super.key});
|
||||
class VideoPage extends StatelessWidget {
|
||||
const VideoPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
+4
-4
@@ -5,14 +5,14 @@ import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/providers/user.provider.dart';
|
||||
import 'package:immich_mobile/widgets/common/user_circle_avatar.dart';
|
||||
|
||||
class DriftActivityTextField extends ConsumerStatefulWidget {
|
||||
class ActivityTextField extends ConsumerStatefulWidget {
|
||||
final bool isEnabled;
|
||||
final bool isBottomSheet;
|
||||
final String? likeId;
|
||||
final Function(String) onSubmit;
|
||||
final Function()? onKeyboardFocus;
|
||||
|
||||
const DriftActivityTextField({
|
||||
const ActivityTextField({
|
||||
required this.onSubmit,
|
||||
this.isEnabled = true,
|
||||
this.likeId,
|
||||
@@ -22,10 +22,10 @@ class DriftActivityTextField extends ConsumerStatefulWidget {
|
||||
});
|
||||
|
||||
@override
|
||||
ConsumerState<DriftActivityTextField> createState() => _DriftActivityTextFieldState();
|
||||
ConsumerState<ActivityTextField> createState() => _ActivityTextFieldState();
|
||||
}
|
||||
|
||||
class _DriftActivityTextFieldState extends ConsumerState<DriftActivityTextField> {
|
||||
class _ActivityTextFieldState extends ConsumerState<ActivityTextField> {
|
||||
late FocusNode inputFocusNode;
|
||||
late TextEditingController inputController;
|
||||
bool sendEnabled = false;
|
||||
+5
-5
@@ -28,18 +28,18 @@ class PeopleDetails extends ConsumerWidget {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
final peopleFuture = ref.watch(driftPeopleAssetProvider(asset.id));
|
||||
final peopleFuture = ref.watch(peopleAssetProvider(asset.id));
|
||||
|
||||
Future<void> showNameEditModal(Person person) async {
|
||||
await showDialog(
|
||||
context: context,
|
||||
useRootNavigator: false,
|
||||
builder: (BuildContext context) {
|
||||
return DriftPersonNameEditForm(person: person);
|
||||
return PersonNameEditForm(person: person);
|
||||
},
|
||||
);
|
||||
|
||||
ref.invalidate(driftPeopleAssetProvider(asset.id));
|
||||
ref.invalidate(peopleAssetProvider(asset.id));
|
||||
}
|
||||
|
||||
return peopleFuture.when(
|
||||
@@ -71,12 +71,12 @@ class PeopleDetails extends ConsumerWidget {
|
||||
final previousRouteArgs = previousRouteData?.arguments;
|
||||
|
||||
// Prevent circular navigation
|
||||
if (previousRouteArgs is DriftPersonRouteArgs && previousRouteArgs.person.id == person.id) {
|
||||
if (previousRouteArgs is PersonRouteArgs && previousRouteArgs.person.id == person.id) {
|
||||
context.back();
|
||||
return;
|
||||
}
|
||||
ContextHelper(context).pop();
|
||||
unawaited(context.pushRoute(DriftPersonRoute(person: person)));
|
||||
unawaited(context.pushRoute(PersonRoute(person: person)));
|
||||
},
|
||||
onNameTap: () => showNameEditModal(person),
|
||||
),
|
||||
|
||||
@@ -55,11 +55,7 @@ class ViewerTopAppBar extends ConsumerWidget implements PreferredSizeWidget {
|
||||
onPressed: () {
|
||||
unawaited(
|
||||
context.router.push(
|
||||
DriftActivitiesRoute(
|
||||
album: album,
|
||||
assetId: asset is RemoteAsset ? asset.id : null,
|
||||
assetName: asset.name,
|
||||
),
|
||||
ActivitiesRoute(album: album, assetId: asset is RemoteAsset ? asset.id : null, assetName: asset.name),
|
||||
),
|
||||
);
|
||||
},
|
||||
|
||||
@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
|
||||
import 'package:immich_mobile/providers/backup/backup.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
|
||||
|
||||
class BackupToggleButton extends ConsumerStatefulWidget {
|
||||
@@ -55,13 +55,13 @@ class BackupToggleButtonState extends ConsumerState<BackupToggleButton> with Sin
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final uploadTasks = ref.watch(driftBackupProvider.select((state) => state.uploadItems));
|
||||
final uploadTasks = ref.watch(backupProvider.select((state) => state.uploadItems));
|
||||
|
||||
final isSyncing = ref.watch(driftBackupProvider.select((state) => state.isSyncing));
|
||||
final isSyncing = ref.watch(backupProvider.select((state) => state.isSyncing));
|
||||
|
||||
final iCloudProgress = ref.watch(driftBackupProvider.select((state) => state.iCloudDownloadProgress));
|
||||
final iCloudProgress = ref.watch(backupProvider.select((state) => state.iCloudDownloadProgress));
|
||||
|
||||
final errorCount = ref.watch(driftBackupProvider.select((state) => state.errorCount));
|
||||
final errorCount = ref.watch(backupProvider.select((state) => state.errorCount));
|
||||
|
||||
final isProcessing = uploadTasks.isNotEmpty || isSyncing || iCloudProgress.isNotEmpty;
|
||||
|
||||
|
||||
@@ -39,16 +39,16 @@ class CustomSourceProperties implements SourceProperties {
|
||||
}
|
||||
}
|
||||
|
||||
class DriftMap extends ConsumerStatefulWidget {
|
||||
class MapView extends ConsumerStatefulWidget {
|
||||
final LatLng? initialLocation;
|
||||
|
||||
const DriftMap({super.key, this.initialLocation});
|
||||
const MapView({super.key, this.initialLocation});
|
||||
|
||||
@override
|
||||
ConsumerState<DriftMap> createState() => _DriftMapState();
|
||||
ConsumerState<MapView> createState() => _MapViewState();
|
||||
}
|
||||
|
||||
class _DriftMapState extends ConsumerState<DriftMap> {
|
||||
class _MapViewState extends ConsumerState<MapView> {
|
||||
MapLibreMapController? mapController;
|
||||
final _reloadMutex = AsyncMutex();
|
||||
final _debouncer = Debouncer(interval: const Duration(milliseconds: 500), maxWaitTime: const Duration(seconds: 2));
|
||||
|
||||
@@ -8,14 +8,14 @@ import 'package:immich_mobile/widgets/map/map_settings/map_settings_list_tile.da
|
||||
import 'package:immich_mobile/widgets/map/map_settings/map_settings_time_dropdown.dart';
|
||||
import 'package:immich_mobile/widgets/map/map_settings/map_theme_picker.dart';
|
||||
|
||||
class DriftMapSettingsSheet extends ConsumerStatefulWidget {
|
||||
const DriftMapSettingsSheet({super.key});
|
||||
class MapSettingsSheet extends ConsumerStatefulWidget {
|
||||
const MapSettingsSheet({super.key});
|
||||
|
||||
@override
|
||||
ConsumerState<DriftMapSettingsSheet> createState() => _DriftMapSettingsSheetState();
|
||||
ConsumerState<MapSettingsSheet> createState() => _MapSettingsSheetState();
|
||||
}
|
||||
|
||||
class _DriftMapSettingsSheetState extends ConsumerState<DriftMapSettingsSheet> {
|
||||
class _MapSettingsSheetState extends ConsumerState<MapSettingsSheet> {
|
||||
late bool useCustomRange;
|
||||
|
||||
@override
|
||||
|
||||
@@ -7,10 +7,10 @@ import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/routing/router.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
class DriftMemoryBottomInfo extends StatelessWidget {
|
||||
final DriftMemory memory;
|
||||
class MemoryBottomInfo extends StatelessWidget {
|
||||
final Memory memory;
|
||||
final String title;
|
||||
const DriftMemoryBottomInfo({super.key, required this.memory, required this.title});
|
||||
const MemoryBottomInfo({super.key, required this.memory, required this.title});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
@@ -9,14 +9,14 @@ import 'package:immich_mobile/presentation/widgets/images/full_image.widget.dart
|
||||
import 'package:immich_mobile/presentation/widgets/images/image_provider.dart';
|
||||
import 'package:immich_mobile/utils/hooks/blurhash_hook.dart';
|
||||
|
||||
class DriftMemoryCard extends StatelessWidget {
|
||||
class MemoryCard extends StatelessWidget {
|
||||
final RemoteAsset asset;
|
||||
final String title;
|
||||
final bool showTitle;
|
||||
final bool isCurrent;
|
||||
final Function()? onVideoEnded;
|
||||
|
||||
const DriftMemoryCard({
|
||||
const MemoryCard({
|
||||
required this.asset,
|
||||
required this.title,
|
||||
required this.showTitle,
|
||||
|
||||
@@ -5,19 +5,19 @@ import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/domain/models/memory.model.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_memory.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/memory.page.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/images/thumbnail.widget.dart';
|
||||
import 'package:immich_mobile/providers/haptic_feedback.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/memory.provider.dart';
|
||||
import 'package:immich_mobile/routing/router.dart';
|
||||
|
||||
class DriftMemoryLane extends ConsumerWidget {
|
||||
const DriftMemoryLane({super.key});
|
||||
class MemoryLane extends ConsumerWidget {
|
||||
const MemoryLane({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final memoryLaneProvider = ref.watch(driftMemoryLaneProvider);
|
||||
final memories = memoryLaneProvider.value ?? const [];
|
||||
final memoryLane = ref.watch(memoryLaneProvider);
|
||||
final memories = memoryLane.value ?? const [];
|
||||
if (memories.isEmpty) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
@@ -33,22 +33,20 @@ class DriftMemoryLane extends ConsumerWidget {
|
||||
onTap: (index) {
|
||||
ref.read(hapticFeedbackProvider.notifier).heavyImpact();
|
||||
if (memories[index].assets.isNotEmpty) {
|
||||
DriftMemoryPage.setMemory(ref, memories[index]);
|
||||
MemoryPage.setMemory(ref, memories[index]);
|
||||
}
|
||||
unawaited(context.pushRoute(DriftMemoryRoute(memories: memories, memoryIndex: index)));
|
||||
unawaited(context.pushRoute(MemoryRoute(memories: memories, memoryIndex: index)));
|
||||
},
|
||||
children: memories
|
||||
.map((memory) => DriftMemoryCard(key: Key(memory.id), memory: memory))
|
||||
.toList(growable: false),
|
||||
children: memories.map((memory) => MemoryCard(key: Key(memory.id), memory: memory)).toList(growable: false),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class DriftMemoryCard extends StatelessWidget {
|
||||
const DriftMemoryCard({super.key, required this.memory});
|
||||
class MemoryCard extends StatelessWidget {
|
||||
const MemoryCard({super.key, required this.memory});
|
||||
|
||||
final DriftMemory memory;
|
||||
final Memory memory;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
@@ -10,16 +10,16 @@ import 'package:immich_mobile/utils/debug_print.dart';
|
||||
import 'package:immich_mobile/widgets/common/immich_toast.dart';
|
||||
import 'package:scroll_date_picker/scroll_date_picker.dart';
|
||||
|
||||
class DriftPersonBirthdayEditForm extends ConsumerStatefulWidget {
|
||||
class PersonBirthdayEditForm extends ConsumerStatefulWidget {
|
||||
final Person person;
|
||||
|
||||
const DriftPersonBirthdayEditForm({super.key, required this.person});
|
||||
const PersonBirthdayEditForm({super.key, required this.person});
|
||||
|
||||
@override
|
||||
ConsumerState<DriftPersonBirthdayEditForm> createState() => _DriftPersonNameEditFormState();
|
||||
ConsumerState<PersonBirthdayEditForm> createState() => _PersonNameEditFormState();
|
||||
}
|
||||
|
||||
class _DriftPersonNameEditFormState extends ConsumerState<DriftPersonBirthdayEditForm> {
|
||||
class _PersonNameEditFormState extends ConsumerState<PersonBirthdayEditForm> {
|
||||
late DateTime _selectedDate;
|
||||
|
||||
@override
|
||||
@@ -30,7 +30,7 @@ class _DriftPersonNameEditFormState extends ConsumerState<DriftPersonBirthdayEdi
|
||||
|
||||
Future<void> saveBirthday() async {
|
||||
try {
|
||||
final result = await ref.read(driftPeopleServiceProvider).updateBirthday(widget.person.id, _selectedDate);
|
||||
final result = await ref.read(peopleServiceProvider).updateBirthday(widget.person.id, _selectedDate);
|
||||
|
||||
if (result != 0 && mounted) {
|
||||
context.pop<DateTime>(_selectedDate);
|
||||
|
||||
@@ -8,16 +8,16 @@ import 'package:immich_mobile/providers/infrastructure/people.provider.dart';
|
||||
import 'package:immich_mobile/utils/debug_print.dart';
|
||||
import 'package:immich_mobile/widgets/common/immich_toast.dart';
|
||||
|
||||
class DriftPersonNameEditForm extends ConsumerStatefulWidget {
|
||||
class PersonNameEditForm extends ConsumerStatefulWidget {
|
||||
final Person person;
|
||||
|
||||
const DriftPersonNameEditForm({super.key, required this.person});
|
||||
const PersonNameEditForm({super.key, required this.person});
|
||||
|
||||
@override
|
||||
ConsumerState<DriftPersonNameEditForm> createState() => _DriftPersonNameEditFormState();
|
||||
ConsumerState<PersonNameEditForm> createState() => _PersonNameEditFormState();
|
||||
}
|
||||
|
||||
class _DriftPersonNameEditFormState extends ConsumerState<DriftPersonNameEditForm> {
|
||||
class _PersonNameEditFormState extends ConsumerState<PersonNameEditForm> {
|
||||
late TextEditingController _formController;
|
||||
|
||||
@override
|
||||
@@ -28,7 +28,7 @@ class _DriftPersonNameEditFormState extends ConsumerState<DriftPersonNameEditFor
|
||||
|
||||
Future<void> onEdit(String personId, String newName) async {
|
||||
try {
|
||||
final result = await ref.read(driftPeopleServiceProvider).updateName(personId, newName);
|
||||
final result = await ref.read(peopleServiceProvider).updateName(personId, newName);
|
||||
if (result != 0 && mounted) {
|
||||
context.pop<String>(newName);
|
||||
}
|
||||
|
||||
+2
-2
@@ -3,8 +3,8 @@ import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/action_buttons/base_action_button.widget.dart';
|
||||
|
||||
class DriftRemoteAlbumOption extends StatelessWidget {
|
||||
const DriftRemoteAlbumOption({
|
||||
class RemoteAlbumOption extends StatelessWidget {
|
||||
const RemoteAlbumOption({
|
||||
super.key,
|
||||
this.onAddPhotos,
|
||||
this.onAddUsers,
|
||||
@@ -7,7 +7,7 @@ import 'package:immich_mobile/entities/store.entity.dart';
|
||||
import 'package:immich_mobile/extensions/platform_extensions.dart';
|
||||
import 'package:immich_mobile/providers/auth.provider.dart';
|
||||
import 'package:immich_mobile/providers/background_sync.provider.dart';
|
||||
import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
|
||||
import 'package:immich_mobile/providers/backup/backup.provider.dart';
|
||||
import 'package:immich_mobile/providers/gallery_permission.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/memory.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/platform.provider.dart';
|
||||
@@ -128,7 +128,7 @@ class AppLifeCycleNotifier extends StateNotifier<AppLifeCycleEnum> {
|
||||
syncSuccess = await backgroundManager.syncRemote();
|
||||
}, "syncRemote"),
|
||||
]);
|
||||
_ref.invalidate(driftAllMemoriesProvider);
|
||||
_ref.invalidate(allMemoriesProvider);
|
||||
if (syncSuccess) {
|
||||
await Future.wait([
|
||||
_safeRun(backgroundManager.hashAssets, "hashAssets").then((_) {
|
||||
@@ -157,7 +157,7 @@ class AppLifeCycleNotifier extends StateNotifier<AppLifeCycleEnum> {
|
||||
final currentUser = Store.tryGet(StoreKey.currentUser);
|
||||
if (currentUser != null) {
|
||||
await _safeRun(
|
||||
() => _ref.read(driftBackupProvider.notifier).startForegroundBackup(currentUser.id),
|
||||
() => _ref.read(backupProvider.notifier).startForegroundBackup(currentUser.id),
|
||||
"handleBackupResume",
|
||||
);
|
||||
}
|
||||
@@ -207,7 +207,7 @@ class AppLifeCycleNotifier extends StateNotifier<AppLifeCycleEnum> {
|
||||
|
||||
Future<void> _performPause() {
|
||||
if (_ref.read(authProvider).isAuthenticated) {
|
||||
_ref.read(driftBackupProvider.notifier).stopForegroundBackup(reason: "the app being sent to the background");
|
||||
_ref.read(backupProvider.notifier).stopForegroundBackup(reason: "the app being sent to the background");
|
||||
|
||||
_ref.read(websocketProvider.notifier).disconnect();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/domain/utils/background_sync.dart';
|
||||
import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
|
||||
import 'package:immich_mobile/providers/backup/backup.provider.dart';
|
||||
import 'package:immich_mobile/providers/sync_status.provider.dart';
|
||||
|
||||
final backgroundSyncProvider = Provider<BackgroundSyncManager>((ref) {
|
||||
@@ -10,17 +10,17 @@ final backgroundSyncProvider = Provider<BackgroundSyncManager>((ref) {
|
||||
onRemoteSyncStart: () {
|
||||
syncStatusNotifier.startRemoteSync();
|
||||
// ignore: dispose-provided-instances
|
||||
final backupProvider = ref.read(driftBackupProvider.notifier);
|
||||
if (backupProvider.mounted) {
|
||||
backupProvider.updateError(BackupError.none);
|
||||
final backupNotifier = ref.read(backupProvider.notifier);
|
||||
if (backupNotifier.mounted) {
|
||||
backupNotifier.updateError(BackupError.none);
|
||||
}
|
||||
},
|
||||
onRemoteSyncComplete: (isSuccess) {
|
||||
syncStatusNotifier.completeRemoteSync();
|
||||
// ignore: dispose-provided-instances
|
||||
final backupProvider = ref.read(driftBackupProvider.notifier);
|
||||
if (backupProvider.mounted) {
|
||||
backupProvider.updateError(isSuccess == true ? BackupError.none : BackupError.syncFailed);
|
||||
final backupNotifier = ref.read(backupProvider.notifier);
|
||||
if (backupNotifier.mounted) {
|
||||
backupNotifier.updateError(isSuccess == true ? BackupError.none : BackupError.syncFailed);
|
||||
}
|
||||
},
|
||||
onRemoteSyncError: syncStatusNotifier.errorRemoteSync,
|
||||
|
||||
@@ -1,23 +1,297 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/models/server_info/server_disk_info.model.dart';
|
||||
import 'package:immich_mobile/services/server_info.service.dart';
|
||||
import 'package:immich_mobile/constants/constants.dart';
|
||||
import 'package:immich_mobile/domain/models/album/local_album.model.dart';
|
||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
|
||||
import 'package:immich_mobile/providers/user.provider.dart';
|
||||
import 'package:immich_mobile/services/background_upload.service.dart';
|
||||
import 'package:immich_mobile/services/foreground_upload.service.dart';
|
||||
import 'package:immich_mobile/utils/upload_speed_calculator.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
final backupProvider = StateNotifierProvider<BackupNotifier, ServerDiskInfo>((ref) {
|
||||
return BackupNotifier(ref.watch(serverInfoServiceProvider));
|
||||
part 'backup.provider.freezed.dart';
|
||||
|
||||
@freezed
|
||||
abstract class EnqueueStatus with _$EnqueueStatus {
|
||||
const factory EnqueueStatus({required int enqueueCount, required int totalCount}) = _EnqueueStatus;
|
||||
}
|
||||
|
||||
@freezed
|
||||
abstract class UploadStatus with _$UploadStatus {
|
||||
const factory UploadStatus({
|
||||
required String taskId,
|
||||
required String filename,
|
||||
required double progress,
|
||||
required int fileSize,
|
||||
required String networkSpeedAsString,
|
||||
bool? isFailed,
|
||||
String? error,
|
||||
}) = _UploadStatus;
|
||||
}
|
||||
|
||||
enum BackupError { none, syncFailed }
|
||||
|
||||
@freezed
|
||||
abstract class BackupState with _$BackupState {
|
||||
const BackupState._();
|
||||
|
||||
const factory BackupState({
|
||||
required int totalCount,
|
||||
required int backupCount,
|
||||
required int remainderCount,
|
||||
required int processingCount,
|
||||
required bool isSyncing,
|
||||
@Default(BackupError.none) BackupError error,
|
||||
required Map<String, UploadStatus> uploadItems,
|
||||
@Default({}) Map<String, double> iCloudDownloadProgress,
|
||||
}) = _BackupState;
|
||||
|
||||
int get errorCount => uploadItems.values.where((item) => item.isFailed == true).length;
|
||||
}
|
||||
|
||||
final backupProvider = StateNotifierProvider<BackupNotifier, BackupState>((ref) {
|
||||
return BackupNotifier(
|
||||
ref.watch(foregroundUploadServiceProvider),
|
||||
ref.watch(backgroundUploadServiceProvider),
|
||||
UploadSpeedManager(),
|
||||
);
|
||||
});
|
||||
|
||||
class BackupNotifier extends StateNotifier<ServerDiskInfo> {
|
||||
BackupNotifier(this._serverInfoService)
|
||||
: super(const ServerDiskInfo(diskAvailable: "0", diskSize: "0", diskUse: "0", diskUsagePercentage: 0));
|
||||
class BackupNotifier extends StateNotifier<BackupState> {
|
||||
BackupNotifier(this._foregroundUploadService, this._backgroundUploadService, this._uploadSpeedManager)
|
||||
: super(
|
||||
const BackupState(
|
||||
totalCount: 0,
|
||||
backupCount: 0,
|
||||
remainderCount: 0,
|
||||
processingCount: 0,
|
||||
isSyncing: false,
|
||||
uploadItems: {},
|
||||
error: BackupError.none,
|
||||
),
|
||||
);
|
||||
|
||||
final ServerInfoService _serverInfoService;
|
||||
final ForegroundUploadService _foregroundUploadService;
|
||||
final BackgroundUploadService _backgroundUploadService;
|
||||
final UploadSpeedManager _uploadSpeedManager;
|
||||
Completer<void>? _cancelToken;
|
||||
|
||||
Future<void> updateDiskInfo() async {
|
||||
final diskInfo = await _serverInfoService.getDiskInfo();
|
||||
if (diskInfo != null) {
|
||||
state = diskInfo;
|
||||
final _logger = Logger("BackupNotifier");
|
||||
|
||||
/// Remove upload item from state
|
||||
void _removeUploadItem(String taskId) {
|
||||
if (!mounted) {
|
||||
_logger.warning("Skip _removeUploadItem: notifier disposed");
|
||||
return;
|
||||
}
|
||||
if (state.uploadItems.containsKey(taskId)) {
|
||||
final updatedItems = Map<String, UploadStatus>.from(state.uploadItems);
|
||||
updatedItems.remove(taskId);
|
||||
state = state.copyWith(uploadItems: updatedItems);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> getBackupStatus(String userId) async {
|
||||
if (!mounted) {
|
||||
_logger.warning("Skip getBackupStatus (pre-call): notifier disposed");
|
||||
return;
|
||||
}
|
||||
final counts = await _foregroundUploadService.getBackupCounts(userId);
|
||||
if (!mounted) {
|
||||
_logger.warning("Skip getBackupStatus (post-call): notifier disposed");
|
||||
return;
|
||||
}
|
||||
|
||||
state = state.copyWith(
|
||||
totalCount: counts.total,
|
||||
backupCount: counts.total - counts.remainder,
|
||||
remainderCount: counts.remainder,
|
||||
processingCount: counts.processing,
|
||||
);
|
||||
}
|
||||
|
||||
void updateError(BackupError error) {
|
||||
if (!mounted) {
|
||||
_logger.warning("Skip updateError: notifier disposed");
|
||||
return;
|
||||
}
|
||||
state = state.copyWith(error: error);
|
||||
}
|
||||
|
||||
void updateSyncing(bool isSyncing) {
|
||||
state = state.copyWith(isSyncing: isSyncing);
|
||||
}
|
||||
|
||||
Future<void> startForegroundBackup(String userId) async {
|
||||
// Cancel any existing backup before starting a new one
|
||||
if (_cancelToken != null) {
|
||||
stopForegroundBackup(reason: "restarting the backup");
|
||||
}
|
||||
|
||||
state = state.copyWith(error: BackupError.none);
|
||||
|
||||
// A pause during the recount below nulls _cancelToken, so the run keeps its own reference.
|
||||
final cancelToken = Completer<void>();
|
||||
_cancelToken = cancelToken;
|
||||
|
||||
// Re-baseline the counters against the same DB read that feeds this run's candidate list,
|
||||
// otherwise a resume counts duplicate successes against the old baseline (#26215).
|
||||
await getBackupStatus(userId);
|
||||
|
||||
return _foregroundUploadService.uploadCandidates(
|
||||
userId,
|
||||
cancelToken,
|
||||
callbacks: UploadCallbacks(
|
||||
onProgress: _handleForegroundBackupProgress,
|
||||
onSuccess: _handleForegroundBackupSuccess,
|
||||
onError: _handleForegroundBackupError,
|
||||
onICloudProgress: _handleICloudProgress,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void stopForegroundBackup({required String reason}) {
|
||||
if (_cancelToken != null) {
|
||||
_logger.info("Foreground backup cancelled: $reason");
|
||||
}
|
||||
_cancelToken?.complete();
|
||||
_cancelToken = null;
|
||||
_uploadSpeedManager.clear();
|
||||
state = state.copyWith(uploadItems: {}, iCloudDownloadProgress: {});
|
||||
}
|
||||
|
||||
void _handleICloudProgress(String localAssetId, double progress) {
|
||||
state = state.copyWith(iCloudDownloadProgress: {...state.iCloudDownloadProgress, localAssetId: progress});
|
||||
|
||||
if (progress >= 1.0) {
|
||||
Future.delayed(const Duration(milliseconds: 250), () {
|
||||
final updatedProgress = Map<String, double>.from(state.iCloudDownloadProgress);
|
||||
updatedProgress.remove(localAssetId);
|
||||
state = state.copyWith(iCloudDownloadProgress: updatedProgress);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void _handleForegroundBackupProgress(String localAssetId, String filename, int bytes, int totalBytes) {
|
||||
if (_cancelToken == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final progress = totalBytes > 0 ? bytes / totalBytes : 0.0;
|
||||
final networkSpeedAsString = _uploadSpeedManager.updateProgress(localAssetId, bytes, totalBytes);
|
||||
final currentItem = state.uploadItems[localAssetId];
|
||||
if (currentItem != null) {
|
||||
state = state.copyWith(
|
||||
uploadItems: {
|
||||
...state.uploadItems,
|
||||
localAssetId: currentItem.copyWith(
|
||||
filename: filename,
|
||||
progress: progress,
|
||||
fileSize: totalBytes,
|
||||
networkSpeedAsString: networkSpeedAsString,
|
||||
),
|
||||
},
|
||||
);
|
||||
} else {
|
||||
state = state.copyWith(
|
||||
uploadItems: {
|
||||
...state.uploadItems,
|
||||
localAssetId: UploadStatus(
|
||||
taskId: localAssetId,
|
||||
filename: filename,
|
||||
progress: progress,
|
||||
fileSize: totalBytes,
|
||||
networkSpeedAsString: networkSpeedAsString,
|
||||
),
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void _handleForegroundBackupSuccess(String localAssetId, String remoteAssetId) {
|
||||
if (!mounted) {
|
||||
_logger.warning("Skip _handleForegroundBackupSuccess: notifier disposed");
|
||||
return;
|
||||
}
|
||||
state = state.copyWith(backupCount: state.backupCount + 1, remainderCount: state.remainderCount - 1);
|
||||
_uploadSpeedManager.removeTask(localAssetId);
|
||||
|
||||
Future.delayed(const Duration(milliseconds: 1000), () {
|
||||
_removeUploadItem(localAssetId);
|
||||
});
|
||||
}
|
||||
|
||||
void _handleForegroundBackupError(String localAssetId, String errorMessage) {
|
||||
_logger.severe("Upload failed for $localAssetId: $errorMessage");
|
||||
|
||||
final currentItem = state.uploadItems[localAssetId];
|
||||
if (currentItem != null) {
|
||||
state = state.copyWith(
|
||||
uploadItems: {
|
||||
...state.uploadItems,
|
||||
localAssetId: currentItem.copyWith(isFailed: true, error: errorMessage),
|
||||
},
|
||||
);
|
||||
} else {
|
||||
state = state.copyWith(
|
||||
uploadItems: {
|
||||
...state.uploadItems,
|
||||
localAssetId: UploadStatus(
|
||||
taskId: localAssetId,
|
||||
filename: 'Unknown',
|
||||
progress: 0,
|
||||
fileSize: 0,
|
||||
networkSpeedAsString: '',
|
||||
isFailed: true,
|
||||
error: errorMessage,
|
||||
),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
_uploadSpeedManager.removeTask(localAssetId);
|
||||
}
|
||||
|
||||
Future<void> startBackupWithURLSession(String userId) async {
|
||||
if (!mounted) {
|
||||
_logger.warning("Skip handleBackupResume (pre-call): notifier disposed");
|
||||
return;
|
||||
}
|
||||
_logger.info("Start background backup sequence");
|
||||
state = state.copyWith(error: BackupError.none);
|
||||
final tasks = await _backgroundUploadService.getActiveTasks(kBackupGroup);
|
||||
if (!mounted) {
|
||||
_logger.warning("Skip handleBackupResume (post-call): notifier disposed");
|
||||
return;
|
||||
}
|
||||
_logger.info("Found ${tasks.length} pending tasks");
|
||||
|
||||
if (tasks.isEmpty) {
|
||||
_logger.info("No pending tasks, starting new upload");
|
||||
return _backgroundUploadService.uploadBackupCandidates(userId);
|
||||
}
|
||||
|
||||
_logger.info("Resuming upload ${tasks.length} assets");
|
||||
return _backgroundUploadService.resume();
|
||||
}
|
||||
}
|
||||
|
||||
final backupCandidateProvider = FutureProvider.autoDispose<List<LocalAsset>>((ref) {
|
||||
final user = ref.watch(currentUserProvider);
|
||||
if (user == null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return ref.read(foregroundUploadServiceProvider).getBackupCandidates(user.id, onlyHashed: false);
|
||||
});
|
||||
|
||||
final candidateBackupAlbumInfoProvider = FutureProvider.autoDispose.family<List<LocalAlbum>, String>((ref, assetId) {
|
||||
return ref
|
||||
.read(driftProvider)
|
||||
.localAssetRepository
|
||||
.getSourceAlbums(assetId, backupSelection: BackupSelection.selected);
|
||||
});
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/models/server_info/server_disk_info.model.dart';
|
||||
import 'package:immich_mobile/services/server_info.service.dart';
|
||||
|
||||
final backupServerProvider = StateNotifierProvider<BackupServerNotifier, ServerDiskInfo>((ref) {
|
||||
return BackupServerNotifier(ref.watch(serverInfoServiceProvider));
|
||||
});
|
||||
|
||||
class BackupServerNotifier extends StateNotifier<ServerDiskInfo> {
|
||||
BackupServerNotifier(this._serverInfoService)
|
||||
: super(const ServerDiskInfo(diskAvailable: "0", diskSize: "0", diskUse: "0", diskUsagePercentage: 0));
|
||||
|
||||
final ServerInfoService _serverInfoService;
|
||||
|
||||
Future<void> updateDiskInfo() async {
|
||||
final diskInfo = await _serverInfoService.getDiskInfo();
|
||||
if (diskInfo != null) {
|
||||
state = diskInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,300 +0,0 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/constants/constants.dart';
|
||||
import 'package:immich_mobile/domain/models/album/local_album.model.dart';
|
||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
|
||||
import 'package:immich_mobile/providers/user.provider.dart';
|
||||
import 'package:immich_mobile/services/background_upload.service.dart';
|
||||
import 'package:immich_mobile/services/foreground_upload.service.dart';
|
||||
import 'package:immich_mobile/utils/upload_speed_calculator.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
part 'drift_backup.provider.freezed.dart';
|
||||
|
||||
@freezed
|
||||
abstract class EnqueueStatus with _$EnqueueStatus {
|
||||
const factory EnqueueStatus({required int enqueueCount, required int totalCount}) = _EnqueueStatus;
|
||||
}
|
||||
|
||||
@freezed
|
||||
abstract class DriftUploadStatus with _$DriftUploadStatus {
|
||||
const factory DriftUploadStatus({
|
||||
required String taskId,
|
||||
required String filename,
|
||||
required double progress,
|
||||
required int fileSize,
|
||||
required String networkSpeedAsString,
|
||||
bool? isFailed,
|
||||
String? error,
|
||||
}) = _DriftUploadStatus;
|
||||
}
|
||||
|
||||
enum BackupError { none, syncFailed }
|
||||
|
||||
@freezed
|
||||
abstract class DriftBackupState with _$DriftBackupState {
|
||||
const DriftBackupState._();
|
||||
|
||||
const factory DriftBackupState({
|
||||
required int totalCount,
|
||||
required int backupCount,
|
||||
required int remainderCount,
|
||||
required int processingCount,
|
||||
required bool isSyncing,
|
||||
@Default(BackupError.none) BackupError error,
|
||||
required Map<String, DriftUploadStatus> uploadItems,
|
||||
@Default({}) Map<String, double> iCloudDownloadProgress,
|
||||
}) = _DriftBackupState;
|
||||
|
||||
int get errorCount => uploadItems.values.where((item) => item.isFailed == true).length;
|
||||
}
|
||||
|
||||
final driftBackupProvider = StateNotifierProvider<DriftBackupNotifier, DriftBackupState>((ref) {
|
||||
return DriftBackupNotifier(
|
||||
ref.watch(foregroundUploadServiceProvider),
|
||||
ref.watch(backgroundUploadServiceProvider),
|
||||
UploadSpeedManager(),
|
||||
);
|
||||
});
|
||||
|
||||
class DriftBackupNotifier extends StateNotifier<DriftBackupState> {
|
||||
DriftBackupNotifier(this._foregroundUploadService, this._backgroundUploadService, this._uploadSpeedManager)
|
||||
: super(
|
||||
const DriftBackupState(
|
||||
totalCount: 0,
|
||||
backupCount: 0,
|
||||
remainderCount: 0,
|
||||
processingCount: 0,
|
||||
isSyncing: false,
|
||||
uploadItems: {},
|
||||
error: BackupError.none,
|
||||
),
|
||||
);
|
||||
|
||||
final ForegroundUploadService _foregroundUploadService;
|
||||
final BackgroundUploadService _backgroundUploadService;
|
||||
final UploadSpeedManager _uploadSpeedManager;
|
||||
Completer<void>? _cancelToken;
|
||||
|
||||
final _logger = Logger("DriftBackupNotifier");
|
||||
|
||||
/// Remove upload item from state
|
||||
void _removeUploadItem(String taskId) {
|
||||
if (!mounted) {
|
||||
_logger.warning("Skip _removeUploadItem: notifier disposed");
|
||||
return;
|
||||
}
|
||||
if (state.uploadItems.containsKey(taskId)) {
|
||||
final updatedItems = Map<String, DriftUploadStatus>.from(state.uploadItems);
|
||||
updatedItems.remove(taskId);
|
||||
state = state.copyWith(uploadItems: updatedItems);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> getBackupStatus(String userId) async {
|
||||
if (!mounted) {
|
||||
_logger.warning("Skip getBackupStatus (pre-call): notifier disposed");
|
||||
return;
|
||||
}
|
||||
final counts = await _foregroundUploadService.getBackupCounts(userId);
|
||||
if (!mounted) {
|
||||
_logger.warning("Skip getBackupStatus (post-call): notifier disposed");
|
||||
return;
|
||||
}
|
||||
|
||||
state = state.copyWith(
|
||||
totalCount: counts.total,
|
||||
backupCount: counts.total - counts.remainder,
|
||||
remainderCount: counts.remainder,
|
||||
processingCount: counts.processing,
|
||||
);
|
||||
}
|
||||
|
||||
void updateError(BackupError error) {
|
||||
if (!mounted) {
|
||||
_logger.warning("Skip updateError: notifier disposed");
|
||||
return;
|
||||
}
|
||||
state = state.copyWith(error: error);
|
||||
}
|
||||
|
||||
void updateSyncing(bool isSyncing) {
|
||||
state = state.copyWith(isSyncing: isSyncing);
|
||||
}
|
||||
|
||||
Future<void> startForegroundBackup(String userId) async {
|
||||
// Cancel any existing backup before starting a new one
|
||||
if (_cancelToken != null) {
|
||||
stopForegroundBackup(reason: "restarting the backup");
|
||||
}
|
||||
|
||||
state = state.copyWith(error: BackupError.none);
|
||||
|
||||
// A pause during the recount below nulls _cancelToken, so the run keeps its own reference.
|
||||
final cancelToken = Completer<void>();
|
||||
_cancelToken = cancelToken;
|
||||
|
||||
// Re-baseline the counters against the same DB read that feeds this run's candidate list,
|
||||
// otherwise a resume counts duplicate successes against the old baseline (#26215).
|
||||
await getBackupStatus(userId);
|
||||
|
||||
return _foregroundUploadService.uploadCandidates(
|
||||
userId,
|
||||
cancelToken,
|
||||
callbacks: UploadCallbacks(
|
||||
onProgress: _handleForegroundBackupProgress,
|
||||
onSuccess: _handleForegroundBackupSuccess,
|
||||
onError: _handleForegroundBackupError,
|
||||
onICloudProgress: _handleICloudProgress,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void stopForegroundBackup({required String reason}) {
|
||||
if (_cancelToken != null) {
|
||||
_logger.info("Foreground backup cancelled: $reason");
|
||||
}
|
||||
_cancelToken?.complete();
|
||||
_cancelToken = null;
|
||||
_uploadSpeedManager.clear();
|
||||
state = state.copyWith(uploadItems: {}, iCloudDownloadProgress: {});
|
||||
}
|
||||
|
||||
void _handleICloudProgress(String localAssetId, double progress) {
|
||||
state = state.copyWith(iCloudDownloadProgress: {...state.iCloudDownloadProgress, localAssetId: progress});
|
||||
|
||||
if (progress >= 1.0) {
|
||||
Future.delayed(const Duration(milliseconds: 250), () {
|
||||
final updatedProgress = Map<String, double>.from(state.iCloudDownloadProgress);
|
||||
updatedProgress.remove(localAssetId);
|
||||
state = state.copyWith(iCloudDownloadProgress: updatedProgress);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void _handleForegroundBackupProgress(String localAssetId, String filename, int bytes, int totalBytes) {
|
||||
if (_cancelToken == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final progress = totalBytes > 0 ? bytes / totalBytes : 0.0;
|
||||
final networkSpeedAsString = _uploadSpeedManager.updateProgress(localAssetId, bytes, totalBytes);
|
||||
final currentItem = state.uploadItems[localAssetId];
|
||||
if (currentItem != null) {
|
||||
state = state.copyWith(
|
||||
uploadItems: {
|
||||
...state.uploadItems,
|
||||
localAssetId: currentItem.copyWith(
|
||||
filename: filename,
|
||||
progress: progress,
|
||||
fileSize: totalBytes,
|
||||
networkSpeedAsString: networkSpeedAsString,
|
||||
),
|
||||
},
|
||||
);
|
||||
} else {
|
||||
state = state.copyWith(
|
||||
uploadItems: {
|
||||
...state.uploadItems,
|
||||
localAssetId: DriftUploadStatus(
|
||||
taskId: localAssetId,
|
||||
filename: filename,
|
||||
progress: progress,
|
||||
fileSize: totalBytes,
|
||||
networkSpeedAsString: networkSpeedAsString,
|
||||
),
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void _handleForegroundBackupSuccess(String localAssetId, String remoteAssetId) {
|
||||
if (!mounted) {
|
||||
_logger.warning("Skip _handleForegroundBackupSuccess: notifier disposed");
|
||||
return;
|
||||
}
|
||||
state = state.copyWith(backupCount: state.backupCount + 1, remainderCount: state.remainderCount - 1);
|
||||
_uploadSpeedManager.removeTask(localAssetId);
|
||||
|
||||
Future.delayed(const Duration(milliseconds: 1000), () {
|
||||
_removeUploadItem(localAssetId);
|
||||
});
|
||||
}
|
||||
|
||||
void _handleForegroundBackupError(String localAssetId, String errorMessage) {
|
||||
_logger.severe("Upload failed for $localAssetId: $errorMessage");
|
||||
|
||||
final currentItem = state.uploadItems[localAssetId];
|
||||
if (currentItem != null) {
|
||||
state = state.copyWith(
|
||||
uploadItems: {
|
||||
...state.uploadItems,
|
||||
localAssetId: currentItem.copyWith(isFailed: true, error: errorMessage),
|
||||
},
|
||||
);
|
||||
} else {
|
||||
state = state.copyWith(
|
||||
uploadItems: {
|
||||
...state.uploadItems,
|
||||
localAssetId: DriftUploadStatus(
|
||||
taskId: localAssetId,
|
||||
filename: 'Unknown',
|
||||
progress: 0,
|
||||
fileSize: 0,
|
||||
networkSpeedAsString: '',
|
||||
isFailed: true,
|
||||
error: errorMessage,
|
||||
),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
_uploadSpeedManager.removeTask(localAssetId);
|
||||
}
|
||||
|
||||
Future<void> startBackupWithURLSession(String userId) async {
|
||||
if (!mounted) {
|
||||
_logger.warning("Skip handleBackupResume (pre-call): notifier disposed");
|
||||
return;
|
||||
}
|
||||
_logger.info("Start background backup sequence");
|
||||
state = state.copyWith(error: BackupError.none);
|
||||
final tasks = await _backgroundUploadService.getActiveTasks(kBackupGroup);
|
||||
if (!mounted) {
|
||||
_logger.warning("Skip handleBackupResume (post-call): notifier disposed");
|
||||
return;
|
||||
}
|
||||
_logger.info("Found ${tasks.length} pending tasks");
|
||||
|
||||
if (tasks.isEmpty) {
|
||||
_logger.info("No pending tasks, starting new upload");
|
||||
return _backgroundUploadService.uploadBackupCandidates(userId);
|
||||
}
|
||||
|
||||
_logger.info("Resuming upload ${tasks.length} assets");
|
||||
return _backgroundUploadService.resume();
|
||||
}
|
||||
}
|
||||
|
||||
final driftBackupCandidateProvider = FutureProvider.autoDispose<List<LocalAsset>>((ref) {
|
||||
final user = ref.watch(currentUserProvider);
|
||||
if (user == null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return ref.read(foregroundUploadServiceProvider).getBackupCandidates(user.id, onlyHashed: false);
|
||||
});
|
||||
|
||||
final driftCandidateBackupAlbumInfoProvider = FutureProvider.autoDispose.family<List<LocalAlbum>, String>((
|
||||
ref,
|
||||
assetId,
|
||||
) {
|
||||
return ref
|
||||
.read(driftProvider)
|
||||
.localAssetRepository
|
||||
.getSourceAlbums(assetId, backupSelection: BackupSelection.selected);
|
||||
});
|
||||
@@ -7,7 +7,7 @@ import 'package:immich_mobile/domain/services/remote_album.service.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/local_album.repository.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/remote_album.provider.dart';
|
||||
import 'package:immich_mobile/repositories/drift_album_api_repository.dart';
|
||||
import 'package:immich_mobile/repositories/album_api_repository.dart';
|
||||
import 'package:immich_mobile/services/foreground_upload.service.dart';
|
||||
|
||||
final localAlbumProvider = FutureProvider<List<LocalAlbum>>(
|
||||
@@ -23,7 +23,7 @@ final localAlbumThumbnailProvider = FutureProvider.family<LocalAsset?, String>(
|
||||
final remoteAlbumServiceProvider = Provider<RemoteAlbumService>(
|
||||
(ref) => RemoteAlbumService(
|
||||
ref.watch(driftProvider).remoteAlbumRepository,
|
||||
ref.watch(driftAlbumApiRepositoryProvider),
|
||||
ref.watch(albumApiRepositoryProvider),
|
||||
ref.watch(foregroundUploadServiceProvider),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -6,7 +6,7 @@ import 'package:immich_mobile/domain/services/memory.service.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
|
||||
import 'package:immich_mobile/providers/user.provider.dart';
|
||||
|
||||
final driftMemoryLaneProvider = FutureProvider.autoDispose<List<DriftMemory>>((ref) {
|
||||
final memoryLaneProvider = FutureProvider.autoDispose<List<Memory>>((ref) {
|
||||
final (userId, enabled) = ref.watch(currentUserProvider.select((user) => (user?.id, user?.memoryEnabled ?? true)));
|
||||
if (userId == null || !enabled) {
|
||||
return const [];
|
||||
@@ -17,16 +17,16 @@ final driftMemoryLaneProvider = FutureProvider.autoDispose<List<DriftMemory>>((r
|
||||
final timer = Timer(nextMidnight.difference(now) + const Duration(seconds: 5), ref.invalidateSelf);
|
||||
ref.onDispose(timer.cancel);
|
||||
|
||||
final service = DriftMemoryService(ref.watch(driftProvider).memoryRepository);
|
||||
final service = MemoryService(ref.watch(driftProvider).memoryRepository);
|
||||
return service.getMemoryLane(userId);
|
||||
});
|
||||
|
||||
final driftAllMemoriesProvider = FutureProvider.autoDispose.family<List<DriftMemory>, bool>((ref, onlyFavorites) {
|
||||
final allMemoriesProvider = FutureProvider.autoDispose.family<List<Memory>, bool>((ref, onlyFavorites) {
|
||||
final (userId, enabled) = ref.watch(currentUserProvider.select((user) => (user?.id, user?.memoryEnabled ?? true)));
|
||||
if (userId == null || !enabled) {
|
||||
return const [];
|
||||
}
|
||||
|
||||
final service = DriftMemoryService(ref.watch(driftProvider).memoryRepository);
|
||||
final service = MemoryService(ref.watch(driftProvider).memoryRepository);
|
||||
return service.getAll(userId, onlyFavorites: onlyFavorites);
|
||||
});
|
||||
|
||||
@@ -5,17 +5,17 @@ import 'package:immich_mobile/domain/services/people.service.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/user_metadata.provider.dart';
|
||||
|
||||
final driftPeopleServiceProvider = Provider<DriftPeopleService>(
|
||||
(ref) => DriftPeopleService(ref.watch(driftProvider).peopleRepository, ref.watch(personApiRepositoryProvider)),
|
||||
final peopleServiceProvider = Provider<PeopleService>(
|
||||
(ref) => PeopleService(ref.watch(driftProvider).peopleRepository, ref.watch(personApiRepositoryProvider)),
|
||||
);
|
||||
|
||||
final driftPeopleAssetProvider = FutureProvider.family<List<Person>, String>((ref, assetId) async {
|
||||
final service = ref.watch(driftPeopleServiceProvider);
|
||||
final peopleAssetProvider = FutureProvider.family<List<Person>, String>((ref, assetId) async {
|
||||
final service = ref.watch(peopleServiceProvider);
|
||||
return service.getAssetPeople(assetId);
|
||||
});
|
||||
|
||||
final getAllPeopleProvider = StreamProvider<List<Person>>((ref) async* {
|
||||
final service = ref.watch(driftPeopleServiceProvider);
|
||||
final service = ref.watch(peopleServiceProvider);
|
||||
final prefs = await ref.watch(userMetadataPreferencesProvider.future);
|
||||
yield* service.watch(minFaces: prefs?.minimumFaces ?? 3);
|
||||
});
|
||||
|
||||
@@ -8,7 +8,7 @@ bool isRouteInStack(Ref ref, String routeName) {
|
||||
return router.stackData.any((route) => route.name == routeName);
|
||||
}
|
||||
|
||||
final inLockedViewProvider = Provider<bool>((ref) => isRouteInStack(ref, DriftLockedFolderRoute.name));
|
||||
final inLockedViewProvider = Provider<bool>((ref) => isRouteInStack(ref, LockedFolderRoute.name));
|
||||
final isAssetViewerOpenProvider = Provider<bool>((ref) => isRouteInStack(ref, AssetViewerRoute.name));
|
||||
|
||||
final currentRouteNameProvider = StateProvider<String?>((ref) => null);
|
||||
|
||||
+3
-5
@@ -6,14 +6,12 @@ import 'package:immich_mobile/repositories/api.repository.dart';
|
||||
// ignore: import_rule_openapi
|
||||
import 'package:openapi/api.dart' hide AlbumUserRole;
|
||||
|
||||
final driftAlbumApiRepositoryProvider = Provider(
|
||||
(ref) => DriftAlbumApiRepository(ref.watch(apiServiceProvider).albumsApi),
|
||||
);
|
||||
final albumApiRepositoryProvider = Provider((ref) => AlbumApiRepository(ref.watch(apiServiceProvider).albumsApi));
|
||||
|
||||
class DriftAlbumApiRepository extends ApiRepository {
|
||||
class AlbumApiRepository extends ApiRepository {
|
||||
final AlbumsApi _api;
|
||||
|
||||
DriftAlbumApiRepository(this._api);
|
||||
AlbumApiRepository(this._api);
|
||||
|
||||
Future<RemoteAlbum> createDriftAlbum(
|
||||
String name,
|
||||
@@ -14,11 +14,11 @@ import 'package:immich_mobile/domain/services/timeline.service.dart';
|
||||
import 'package:immich_mobile/models/folder/recursive_folder.model.dart';
|
||||
import 'package:immich_mobile/models/shared_link/shared_link.model.dart';
|
||||
import 'package:immich_mobile/models/upload/share_intent_attachment.model.dart';
|
||||
import 'package:immich_mobile/pages/backup/drift_backup.page.dart';
|
||||
import 'package:immich_mobile/pages/backup/drift_backup_album_selection.page.dart';
|
||||
import 'package:immich_mobile/pages/backup/drift_backup_asset_detail.page.dart';
|
||||
import 'package:immich_mobile/pages/backup/drift_backup_options.page.dart';
|
||||
import 'package:immich_mobile/pages/backup/drift_upload_detail.page.dart';
|
||||
import 'package:immich_mobile/pages/backup/backup.page.dart';
|
||||
import 'package:immich_mobile/pages/backup/backup_album_selection.page.dart';
|
||||
import 'package:immich_mobile/pages/backup/backup_asset_detail.page.dart';
|
||||
import 'package:immich_mobile/pages/backup/backup_options.page.dart';
|
||||
import 'package:immich_mobile/pages/backup/upload_detail.page.dart';
|
||||
import 'package:immich_mobile/pages/common/app_log.page.dart';
|
||||
import 'package:immich_mobile/pages/common/app_log_detail.page.dart';
|
||||
import 'package:immich_mobile/pages/common/headers_settings.page.dart';
|
||||
@@ -35,41 +35,41 @@ import 'package:immich_mobile/pages/login/login.page.dart';
|
||||
import 'package:immich_mobile/pages/search/map/map_location_picker.page.dart';
|
||||
import 'package:immich_mobile/pages/settings/sync_status.page.dart';
|
||||
import 'package:immich_mobile/pages/share_intent/share_intent.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/activities.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/album.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/album_options.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/archive.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/asset_selection_timeline.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/asset_troubleshoot.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/cleanup_preview.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/create_album.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/dev/main_timeline.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/dev/media_stat.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/download_info.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_activities.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_album.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_album_options.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_archive.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_asset_selection_timeline.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_asset_troubleshoot.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_create_album.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_favorite.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_library.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_local_album.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_locked_folder.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_map.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_memory.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_memory_list.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_partner_detail.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_people_collection.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_person.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_place.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_place_detail.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_recently_added.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_recently_taken.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_remote_album.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_slideshow.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_trash.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_user_selection.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/drift_video.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/edit/drift_edit.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/edit/edit.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/favorite.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/feature_message/whats_new.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/library.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/local_album.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/local_timeline.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/locked_folder.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/map.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/memory.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/memory_list.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/partner_detail.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/people_collection.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/person.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/place.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/place_detail.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/profile/profile_picture_crop.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/search/drift_search.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/recently_added.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/recently_taken.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/remote_album.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/search/search.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/slideshow.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/trash.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/user_selection.page.dart';
|
||||
import 'package:immich_mobile/presentation/pages/video.page.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_viewer.page.dart';
|
||||
import 'package:immich_mobile/providers/api.provider.dart';
|
||||
import 'package:immich_mobile/routing/auth_guard.dart';
|
||||
@@ -123,9 +123,9 @@ class AppRouter extends RootStackRouter {
|
||||
guards: [_authGuard, _duplicateGuard],
|
||||
children: [
|
||||
AutoRoute(page: MainTimelineRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: DriftSearchRoute.page, guards: [_authGuard, _duplicateGuard], maintainState: false),
|
||||
AutoRoute(page: DriftLibraryRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: DriftAlbumsRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: SearchRoute.page, guards: [_authGuard, _duplicateGuard], maintainState: false),
|
||||
AutoRoute(page: LibraryRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: AlbumsRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
],
|
||||
),
|
||||
AutoRoute(page: ProfilePictureCropRoute.page),
|
||||
@@ -143,8 +143,8 @@ class AppRouter extends RootStackRouter {
|
||||
AutoRoute(page: PinAuthRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: LocalMediaSummaryRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: RemoteMediaSummaryRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: DriftBackupRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: DriftBackupAlbumSelectionRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: BackupRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: BackupAlbumSelectionRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: LocalTimelineRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: MainTimelineRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: RemoteAlbumRoute.page, guards: [_authGuard]),
|
||||
@@ -161,38 +161,38 @@ class AppRouter extends RootStackRouter {
|
||||
),
|
||||
),
|
||||
),
|
||||
AutoRoute(page: DriftMemoryRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: DriftFavoriteRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: DriftTrashRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: DriftArchiveRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: DriftLockedFolderRoute.page, guards: [_authGuard, _lockedGuard, _duplicateGuard]),
|
||||
AutoRoute(page: DriftVideoRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: DriftLibraryRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: DriftAssetSelectionTimelineRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: DriftPartnerDetailRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: DriftRecentlyTakenRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: DriftRecentlyAddedRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: DriftLocalAlbumsRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: DriftCreateAlbumRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: DriftPlaceRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: DriftPlaceDetailRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: DriftUserSelectionRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: MemoryRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: FavoriteRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: TrashRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: ArchiveRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: LockedFolderRoute.page, guards: [_authGuard, _lockedGuard, _duplicateGuard]),
|
||||
AutoRoute(page: VideoRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: LibraryRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: AssetSelectionTimelineRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: PartnerDetailRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: RecentlyTakenRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: RecentlyAddedRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: LocalAlbumsRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: CreateAlbumRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: PlaceRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: PlaceDetailRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: UserSelectionRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: PartnerRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: DriftUploadDetailRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: UploadDetailRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: SyncStatusRoute.page, guards: [_duplicateGuard]),
|
||||
AutoRoute(page: DriftPeopleCollectionRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: DriftPersonRoute.page, guards: [_authGuard]),
|
||||
AutoRoute(page: DriftBackupOptionsRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: DriftAlbumOptionsRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: DriftMapRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: DriftEditImageRoute.page),
|
||||
AutoRoute(page: DriftActivitiesRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: DriftBackupAssetDetailRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: PeopleCollectionRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: PersonRoute.page, guards: [_authGuard]),
|
||||
AutoRoute(page: BackupOptionsRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: AlbumOptionsRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: MapRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: EditImageRoute.page),
|
||||
AutoRoute(page: ActivitiesRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: BackupAssetDetailRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: AssetTroubleshootRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: DownloadInfoRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: CleanupPreviewRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: DriftSlideshowRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: DriftMemoryListRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: SlideshowRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: MemoryListRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
// required to handle all deeplinks in deep_link.service.dart
|
||||
// auto_route_library#1722
|
||||
RedirectRoute(path: '*', redirectTo: '/'),
|
||||
|
||||
@@ -21,8 +21,8 @@ final deepLinkServiceProvider = Provider(
|
||||
ref.watch(timelineFactoryProvider),
|
||||
ref.watch(beta_asset_provider.assetServiceProvider),
|
||||
ref.watch(remoteAlbumServiceProvider),
|
||||
DriftMemoryService(ref.watch(driftProvider).memoryRepository),
|
||||
ref.watch(driftPeopleServiceProvider),
|
||||
MemoryService(ref.watch(driftProvider).memoryRepository),
|
||||
ref.watch(peopleServiceProvider),
|
||||
ref.watch(currentUserProvider),
|
||||
),
|
||||
);
|
||||
@@ -31,8 +31,8 @@ class DeepLinkService {
|
||||
final TimelineFactory _betaTimelineFactory;
|
||||
final beta_asset_service.AssetService _betaAssetService;
|
||||
final RemoteAlbumService _betaRemoteAlbumService;
|
||||
final DriftMemoryService _betaMemoryService;
|
||||
final DriftPeopleService _betaPeopleService;
|
||||
final MemoryService _betaMemoryService;
|
||||
final PeopleService _betaPeopleService;
|
||||
|
||||
final UserDto? _currentUser;
|
||||
|
||||
@@ -88,7 +88,7 @@ class DeepLinkService {
|
||||
}
|
||||
|
||||
Future<PageRouteInfo?> _buildMemoryDeepLink(String? memoryId) async {
|
||||
List<DriftMemory> memories = [];
|
||||
List<Memory> memories = [];
|
||||
|
||||
if (memoryId == null) {
|
||||
if (_currentUser == null) {
|
||||
@@ -107,7 +107,7 @@ class DeepLinkService {
|
||||
return null;
|
||||
}
|
||||
|
||||
return DriftMemoryRoute(memories: memories, memoryIndex: 0);
|
||||
return MemoryRoute(memories: memories, memoryIndex: 0);
|
||||
}
|
||||
|
||||
Future<PageRouteInfo?> _buildAssetDeepLink(String assetId, WidgetRef ref, {String? albumId}) async {
|
||||
@@ -143,7 +143,7 @@ class DeepLinkService {
|
||||
return null;
|
||||
}
|
||||
|
||||
return DriftActivitiesRoute(album: album);
|
||||
return ActivitiesRoute(album: album);
|
||||
}
|
||||
|
||||
Future<PageRouteInfo?> _buildPeopleDeepLink(String personId) async {
|
||||
@@ -153,6 +153,6 @@ class DeepLinkService {
|
||||
return null;
|
||||
}
|
||||
|
||||
return DriftPersonRoute(person: person);
|
||||
return PersonRoute(person: person);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ Future<String?> showNameEditModal(BuildContext context, Person person) {
|
||||
context: context,
|
||||
useRootNavigator: false,
|
||||
builder: (BuildContext context) {
|
||||
return DriftPersonNameEditForm(person: person);
|
||||
return PersonNameEditForm(person: person);
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -49,7 +49,7 @@ Future<DateTime?> showBirthdayEditModal(BuildContext context, Person person) {
|
||||
context: context,
|
||||
useRootNavigator: false,
|
||||
builder: (BuildContext context) {
|
||||
return DriftPersonBirthdayEditForm(person: person);
|
||||
return PersonBirthdayEditForm(person: person);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ import 'package:immich_mobile/data/server/person.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/search.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/user.provider.dart';
|
||||
import 'package:immich_mobile/repositories/activity_api.repository.dart';
|
||||
import 'package:immich_mobile/repositories/album_api_repository.dart';
|
||||
import 'package:immich_mobile/repositories/asset_api.repository.dart';
|
||||
import 'package:immich_mobile/repositories/drift_album_api_repository.dart';
|
||||
import 'package:immich_mobile/repositories/partner_api.repository.dart';
|
||||
|
||||
void invalidateAllApiRepositoryProviders(WidgetRef ref) {
|
||||
@@ -16,5 +16,5 @@ void invalidateAllApiRepositoryProviders(WidgetRef ref) {
|
||||
ref.invalidate(searchApiRepositoryProvider);
|
||||
|
||||
// Drift
|
||||
ref.invalidate(driftAlbumApiRepositoryProvider);
|
||||
ref.invalidate(albumApiRepositoryProvider);
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ class RemoteAlbumSharedUserIcons extends ConsumerWidget {
|
||||
}
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () => context.pushRoute(DriftAlbumOptionsRoute(album: currentAlbum)),
|
||||
onTap: () => context.pushRoute(AlbumOptionsRoute(album: currentAlbum)),
|
||||
child: SizedBox(
|
||||
height: 50,
|
||||
child: ListView.builder(
|
||||
|
||||
+2
-2
@@ -12,10 +12,10 @@ import 'package:immich_mobile/providers/haptic_feedback.provider.dart';
|
||||
import 'package:immich_mobile/routing/router.dart';
|
||||
import 'package:immich_mobile/widgets/common/immich_toast.dart';
|
||||
|
||||
class DriftAlbumInfoListTile extends HookConsumerWidget {
|
||||
class AlbumInfoListTile extends HookConsumerWidget {
|
||||
final LocalAlbum album;
|
||||
|
||||
const DriftAlbumInfoListTile({super.key, required this.album});
|
||||
const AlbumInfoListTile({super.key, required this.album});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
@@ -9,7 +9,7 @@ import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/models/server_info/server_disk_info.model.dart';
|
||||
import 'package:immich_mobile/pages/common/settings.page.dart';
|
||||
import 'package:immich_mobile/providers/auth.provider.dart';
|
||||
import 'package:immich_mobile/providers/backup/backup.provider.dart';
|
||||
import 'package:immich_mobile/providers/backup/backup_server.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/readonly_mode.provider.dart';
|
||||
import 'package:immich_mobile/providers/locale_provider.dart';
|
||||
import 'package:immich_mobile/providers/user.provider.dart';
|
||||
@@ -29,7 +29,7 @@ class ImmichAppBarDialog extends HookConsumerWidget {
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
ref.watch(localeProvider);
|
||||
final ServerDiskInfo backupState = ref.watch(backupProvider);
|
||||
final ServerDiskInfo backupState = ref.watch(backupServerProvider);
|
||||
final theme = context.themeData;
|
||||
final bool isHorizontal = !context.isMobile;
|
||||
final horizontalPadding = isHorizontal ? 100.0 : 20.0;
|
||||
@@ -38,7 +38,7 @@ class ImmichAppBarDialog extends HookConsumerWidget {
|
||||
final isReadonlyModeEnabled = ref.watch(readonlyModeProvider);
|
||||
|
||||
useEffect(() {
|
||||
unawaited(ref.read(backupProvider.notifier).updateDiskInfo());
|
||||
unawaited(ref.read(backupServerProvider.notifier).updateDiskInfo());
|
||||
unawaited(ref.read(currentUserProvider.notifier).refresh());
|
||||
return null;
|
||||
}, []);
|
||||
|
||||
@@ -7,7 +7,7 @@ import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/theme_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/providers/auth.provider.dart';
|
||||
import 'package:immich_mobile/providers/backup/backup.provider.dart';
|
||||
import 'package:immich_mobile/providers/backup/backup_server.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/readonly_mode.provider.dart';
|
||||
import 'package:immich_mobile/providers/upload_profile_image.provider.dart';
|
||||
import 'package:immich_mobile/providers/user.provider.dart';
|
||||
@@ -55,7 +55,7 @@ class AppBarProfileInfoBox extends HookConsumerWidget {
|
||||
unawaited(ref.read(currentUserProvider.notifier).refresh());
|
||||
}
|
||||
|
||||
unawaited(ref.read(backupProvider.notifier).updateDiskInfo());
|
||||
unawaited(ref.read(backupServerProvider.notifier).updateDiskInfo());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/models/server_info/server_info.model.dart';
|
||||
import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
|
||||
import 'package:immich_mobile/providers/backup/backup.provider.dart';
|
||||
import 'package:immich_mobile/providers/cast.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/readonly_mode.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
|
||||
@@ -178,8 +178,8 @@ class _BackupIndicator extends ConsumerWidget {
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final backupEnabled = ref.watch(appConfigProvider.select((c) => c.backup.enabled));
|
||||
final hasError = ref.watch(driftBackupProvider.select((state) => state.error != BackupError.none));
|
||||
final isUploading = ref.watch(driftBackupProvider.select((state) => state.uploadItems.isNotEmpty));
|
||||
final hasError = ref.watch(backupProvider.select((state) => state.error != BackupError.none));
|
||||
final isUploading = ref.watch(backupProvider.select((state) => state.uploadItems.isNotEmpty));
|
||||
final indicatorIcon = _getBackupBadgeIcon(
|
||||
context,
|
||||
backupEnabled: backupEnabled,
|
||||
@@ -188,7 +188,7 @@ class _BackupIndicator extends ConsumerWidget {
|
||||
);
|
||||
|
||||
return IconButton(
|
||||
onPressed: () => context.pushRoute(const DriftBackupRoute()),
|
||||
onPressed: () => context.pushRoute(const BackupRoute()),
|
||||
icon: Badge(
|
||||
label: indicatorIcon,
|
||||
backgroundColor: Colors.transparent,
|
||||
|
||||
@@ -90,7 +90,7 @@ class _MesmerizingSliverAppBarState extends ConsumerState<RemoteAlbumSliverAppBa
|
||||
),
|
||||
actions: [
|
||||
IconButton(
|
||||
onPressed: () => context.pushRoute(DriftSlideshowRoute(timeline: ref.read(timelineServiceProvider))),
|
||||
onPressed: () => context.pushRoute(SlideshowRoute(timeline: ref.read(timelineServiceProvider))),
|
||||
icon: Icon(Icons.slideshow_outlined, color: actionIconColor, shadows: actionIconShadows),
|
||||
),
|
||||
if (currentAlbum.isActivityEnabled && currentAlbum.isShared)
|
||||
|
||||
+2
-2
@@ -18,8 +18,8 @@ import 'package:immich_mobile/widgets/settings/setting_group_title.dart';
|
||||
import 'package:immich_mobile/widgets/settings/setting_list_tile.dart';
|
||||
import 'package:immich_mobile/widgets/settings/settings_sub_page_scaffold.dart';
|
||||
|
||||
class DriftBackupSettings extends StatelessWidget {
|
||||
const DriftBackupSettings({super.key});
|
||||
class BackupSettings extends StatelessWidget {
|
||||
const BackupSettings({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -223,7 +223,7 @@ class _SyncStatsCounts extends ConsumerWidget {
|
||||
final assetService = ref.watch(assetServiceProvider);
|
||||
final localAlbumService = LocalAlbumService(db.localAlbumRepository);
|
||||
final remoteAlbumService = ref.watch(remoteAlbumServiceProvider);
|
||||
final memoryService = DriftMemoryService(db.memoryRepository);
|
||||
final memoryService = MemoryService(db.memoryRepository);
|
||||
final appSettingsService = ref.watch(appSettingsServiceProvider);
|
||||
|
||||
Future<List<dynamic>> loadCounts() async {
|
||||
|
||||
@@ -3,7 +3,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/domain/services/sync_linked_album.service.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/store.provider.dart';
|
||||
import 'package:immich_mobile/repositories/drift_album_api_repository.dart';
|
||||
import 'package:immich_mobile/repositories/album_api_repository.dart';
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
|
||||
import '../../infrastructure/repository.mock.dart';
|
||||
@@ -20,7 +20,7 @@ void main() {
|
||||
final container = ProviderContainer(
|
||||
overrides: [
|
||||
driftProvider.overrideWithValue(drift),
|
||||
driftAlbumApiRepositoryProvider.overrideWithValue(MockDriftAlbumApiRepository()),
|
||||
albumApiRepositoryProvider.overrideWithValue(MockAlbumApiRepository()),
|
||||
storeServiceProvider.overrideWithValue(MockStoreService()),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -16,7 +16,7 @@ import 'package:immich_mobile/infrastructure/repositories/sync_stream.repository
|
||||
import 'package:immich_mobile/infrastructure/repositories/trashed_local_asset.repository.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/user.repository.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/user_api.repository.dart';
|
||||
import 'package:immich_mobile/repositories/drift_album_api_repository.dart';
|
||||
import 'package:immich_mobile/repositories/album_api_repository.dart';
|
||||
import 'package:immich_mobile/repositories/upload.repository.dart';
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
|
||||
@@ -59,4 +59,4 @@ class MockUserApiRepository extends Mock implements UserApiRepository {}
|
||||
|
||||
class MockSyncApiRepository extends Mock implements SyncApiRepository {}
|
||||
|
||||
class MockDriftAlbumApiRepository extends Mock implements DriftAlbumApiRepository {}
|
||||
class MockAlbumApiRepository extends Mock implements AlbumApiRepository {}
|
||||
|
||||
+48
-167
@@ -1,25 +1,19 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/remote_album/drift_album_option.widget.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/remote_album/album_option.widget.dart';
|
||||
|
||||
import '../../../widget_tester_extensions.dart';
|
||||
|
||||
void main() {
|
||||
group('DriftRemoteAlbumOption', () {
|
||||
testWidgets('shows kebab menu icon button', (tester) async {
|
||||
await tester.pumpConsumerWidget(
|
||||
const DriftRemoteAlbumOption(),
|
||||
);
|
||||
await tester.pumpConsumerWidget(const RemoteAlbumOption());
|
||||
|
||||
expect(find.byIcon(Icons.more_vert_rounded), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('opens menu when icon button is tapped', (tester) async {
|
||||
await tester.pumpConsumerWidget(
|
||||
DriftRemoteAlbumOption(
|
||||
onEditAlbum: () {},
|
||||
),
|
||||
);
|
||||
await tester.pumpConsumerWidget(RemoteAlbumOption(onEditAlbum: () {}));
|
||||
|
||||
await tester.tap(find.byIcon(Icons.more_vert_rounded));
|
||||
await tester.pumpAndSettle();
|
||||
@@ -27,15 +21,10 @@ void main() {
|
||||
expect(find.byIcon(Icons.edit), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('shows edit album option when onEditAlbum is provided',
|
||||
(tester) async {
|
||||
testWidgets('shows edit album option when onEditAlbum is provided', (tester) async {
|
||||
bool editCalled = false;
|
||||
|
||||
await tester.pumpConsumerWidget(
|
||||
DriftRemoteAlbumOption(
|
||||
onEditAlbum: () => editCalled = true,
|
||||
),
|
||||
);
|
||||
await tester.pumpConsumerWidget(RemoteAlbumOption(onEditAlbum: () => editCalled = true));
|
||||
|
||||
await tester.tap(find.byIcon(Icons.more_vert_rounded));
|
||||
await tester.pumpAndSettle();
|
||||
@@ -48,13 +37,8 @@ void main() {
|
||||
expect(editCalled, isTrue);
|
||||
});
|
||||
|
||||
testWidgets('hides edit album option when onEditAlbum is null',
|
||||
(tester) async {
|
||||
await tester.pumpConsumerWidget(
|
||||
DriftRemoteAlbumOption(
|
||||
onAddPhotos: () {},
|
||||
),
|
||||
);
|
||||
testWidgets('hides edit album option when onEditAlbum is null', (tester) async {
|
||||
await tester.pumpConsumerWidget(RemoteAlbumOption(onAddPhotos: () {}));
|
||||
|
||||
await tester.tap(find.byIcon(Icons.more_vert_rounded));
|
||||
await tester.pumpAndSettle();
|
||||
@@ -62,15 +46,10 @@ void main() {
|
||||
expect(find.byIcon(Icons.edit), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('shows add photos option when onAddPhotos is provided',
|
||||
(tester) async {
|
||||
testWidgets('shows add photos option when onAddPhotos is provided', (tester) async {
|
||||
bool addPhotosCalled = false;
|
||||
|
||||
await tester.pumpConsumerWidget(
|
||||
DriftRemoteAlbumOption(
|
||||
onAddPhotos: () => addPhotosCalled = true,
|
||||
),
|
||||
);
|
||||
await tester.pumpConsumerWidget(RemoteAlbumOption(onAddPhotos: () => addPhotosCalled = true));
|
||||
|
||||
await tester.tap(find.byIcon(Icons.more_vert_rounded));
|
||||
await tester.pumpAndSettle();
|
||||
@@ -83,13 +62,8 @@ void main() {
|
||||
expect(addPhotosCalled, isTrue);
|
||||
});
|
||||
|
||||
testWidgets('hides add photos option when onAddPhotos is null',
|
||||
(tester) async {
|
||||
await tester.pumpConsumerWidget(
|
||||
DriftRemoteAlbumOption(
|
||||
onEditAlbum: () {},
|
||||
),
|
||||
);
|
||||
testWidgets('hides add photos option when onAddPhotos is null', (tester) async {
|
||||
await tester.pumpConsumerWidget(RemoteAlbumOption(onEditAlbum: () {}));
|
||||
|
||||
await tester.tap(find.byIcon(Icons.more_vert_rounded));
|
||||
await tester.pumpAndSettle();
|
||||
@@ -97,15 +71,10 @@ void main() {
|
||||
expect(find.byIcon(Icons.add_a_photo), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('shows add users option when onAddUsers is provided',
|
||||
(tester) async {
|
||||
testWidgets('shows add users option when onAddUsers is provided', (tester) async {
|
||||
bool addUsersCalled = false;
|
||||
|
||||
await tester.pumpConsumerWidget(
|
||||
DriftRemoteAlbumOption(
|
||||
onAddUsers: () => addUsersCalled = true,
|
||||
),
|
||||
);
|
||||
await tester.pumpConsumerWidget(RemoteAlbumOption(onAddUsers: () => addUsersCalled = true));
|
||||
|
||||
await tester.tap(find.byIcon(Icons.more_vert_rounded));
|
||||
await tester.pumpAndSettle();
|
||||
@@ -118,13 +87,8 @@ void main() {
|
||||
expect(addUsersCalled, isTrue);
|
||||
});
|
||||
|
||||
testWidgets('hides add users option when onAddUsers is null',
|
||||
(tester) async {
|
||||
await tester.pumpConsumerWidget(
|
||||
DriftRemoteAlbumOption(
|
||||
onEditAlbum: () {},
|
||||
),
|
||||
);
|
||||
testWidgets('hides add users option when onAddUsers is null', (tester) async {
|
||||
await tester.pumpConsumerWidget(RemoteAlbumOption(onEditAlbum: () {}));
|
||||
|
||||
await tester.tap(find.byIcon(Icons.more_vert_rounded));
|
||||
await tester.pumpAndSettle();
|
||||
@@ -132,15 +96,10 @@ void main() {
|
||||
expect(find.byIcon(Icons.group_add), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('shows leave album option when onLeaveAlbum is provided',
|
||||
(tester) async {
|
||||
testWidgets('shows leave album option when onLeaveAlbum is provided', (tester) async {
|
||||
bool leaveAlbumCalled = false;
|
||||
|
||||
await tester.pumpConsumerWidget(
|
||||
DriftRemoteAlbumOption(
|
||||
onLeaveAlbum: () => leaveAlbumCalled = true,
|
||||
),
|
||||
);
|
||||
await tester.pumpConsumerWidget(RemoteAlbumOption(onLeaveAlbum: () => leaveAlbumCalled = true));
|
||||
|
||||
await tester.tap(find.byIcon(Icons.more_vert_rounded));
|
||||
await tester.pumpAndSettle();
|
||||
@@ -153,13 +112,8 @@ void main() {
|
||||
expect(leaveAlbumCalled, isTrue);
|
||||
});
|
||||
|
||||
testWidgets('hides leave album option when onLeaveAlbum is null',
|
||||
(tester) async {
|
||||
await tester.pumpConsumerWidget(
|
||||
DriftRemoteAlbumOption(
|
||||
onEditAlbum: () {},
|
||||
),
|
||||
);
|
||||
testWidgets('hides leave album option when onLeaveAlbum is null', (tester) async {
|
||||
await tester.pumpConsumerWidget(RemoteAlbumOption(onEditAlbum: () {}));
|
||||
|
||||
await tester.tap(find.byIcon(Icons.more_vert_rounded));
|
||||
await tester.pumpAndSettle();
|
||||
@@ -167,16 +121,10 @@ void main() {
|
||||
expect(find.byIcon(Icons.person_remove_rounded), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'shows toggle album order option when onToggleAlbumOrder is provided',
|
||||
(tester) async {
|
||||
testWidgets('shows toggle album order option when onToggleAlbumOrder is provided', (tester) async {
|
||||
bool toggleOrderCalled = false;
|
||||
|
||||
await tester.pumpConsumerWidget(
|
||||
DriftRemoteAlbumOption(
|
||||
onToggleAlbumOrder: () => toggleOrderCalled = true,
|
||||
),
|
||||
);
|
||||
await tester.pumpConsumerWidget(RemoteAlbumOption(onToggleAlbumOrder: () => toggleOrderCalled = true));
|
||||
|
||||
await tester.tap(find.byIcon(Icons.more_vert_rounded));
|
||||
await tester.pumpAndSettle();
|
||||
@@ -189,13 +137,8 @@ void main() {
|
||||
expect(toggleOrderCalled, isTrue);
|
||||
});
|
||||
|
||||
testWidgets('hides toggle album order option when onToggleAlbumOrder is null',
|
||||
(tester) async {
|
||||
await tester.pumpConsumerWidget(
|
||||
DriftRemoteAlbumOption(
|
||||
onEditAlbum: () {},
|
||||
),
|
||||
);
|
||||
testWidgets('hides toggle album order option when onToggleAlbumOrder is null', (tester) async {
|
||||
await tester.pumpConsumerWidget(RemoteAlbumOption(onEditAlbum: () {}));
|
||||
|
||||
await tester.tap(find.byIcon(Icons.more_vert_rounded));
|
||||
await tester.pumpAndSettle();
|
||||
@@ -203,16 +146,10 @@ void main() {
|
||||
expect(find.byIcon(Icons.swap_vert_rounded), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'shows create shared link option when onCreateSharedLink is provided',
|
||||
(tester) async {
|
||||
testWidgets('shows create shared link option when onCreateSharedLink is provided', (tester) async {
|
||||
bool createSharedLinkCalled = false;
|
||||
|
||||
await tester.pumpConsumerWidget(
|
||||
DriftRemoteAlbumOption(
|
||||
onCreateSharedLink: () => createSharedLinkCalled = true,
|
||||
),
|
||||
);
|
||||
await tester.pumpConsumerWidget(RemoteAlbumOption(onCreateSharedLink: () => createSharedLinkCalled = true));
|
||||
|
||||
await tester.tap(find.byIcon(Icons.more_vert_rounded));
|
||||
await tester.pumpAndSettle();
|
||||
@@ -225,13 +162,8 @@ void main() {
|
||||
expect(createSharedLinkCalled, isTrue);
|
||||
});
|
||||
|
||||
testWidgets('hides create shared link option when onCreateSharedLink is null',
|
||||
(tester) async {
|
||||
await tester.pumpConsumerWidget(
|
||||
DriftRemoteAlbumOption(
|
||||
onEditAlbum: () {},
|
||||
),
|
||||
);
|
||||
testWidgets('hides create shared link option when onCreateSharedLink is null', (tester) async {
|
||||
await tester.pumpConsumerWidget(RemoteAlbumOption(onEditAlbum: () {}));
|
||||
|
||||
await tester.tap(find.byIcon(Icons.more_vert_rounded));
|
||||
await tester.pumpAndSettle();
|
||||
@@ -239,15 +171,10 @@ void main() {
|
||||
expect(find.byIcon(Icons.link), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('shows options option when onShowOptions is provided',
|
||||
(tester) async {
|
||||
testWidgets('shows options option when onShowOptions is provided', (tester) async {
|
||||
bool showOptionsCalled = false;
|
||||
|
||||
await tester.pumpConsumerWidget(
|
||||
DriftRemoteAlbumOption(
|
||||
onShowOptions: () => showOptionsCalled = true,
|
||||
),
|
||||
);
|
||||
await tester.pumpConsumerWidget(RemoteAlbumOption(onShowOptions: () => showOptionsCalled = true));
|
||||
|
||||
await tester.tap(find.byIcon(Icons.more_vert_rounded));
|
||||
await tester.pumpAndSettle();
|
||||
@@ -260,13 +187,8 @@ void main() {
|
||||
expect(showOptionsCalled, isTrue);
|
||||
});
|
||||
|
||||
testWidgets('hides options option when onShowOptions is null',
|
||||
(tester) async {
|
||||
await tester.pumpConsumerWidget(
|
||||
DriftRemoteAlbumOption(
|
||||
onEditAlbum: () {},
|
||||
),
|
||||
);
|
||||
testWidgets('hides options option when onShowOptions is null', (tester) async {
|
||||
await tester.pumpConsumerWidget(RemoteAlbumOption(onEditAlbum: () {}));
|
||||
|
||||
await tester.tap(find.byIcon(Icons.more_vert_rounded));
|
||||
await tester.pumpAndSettle();
|
||||
@@ -274,15 +196,10 @@ void main() {
|
||||
expect(find.byIcon(Icons.settings), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('shows delete album option when onDeleteAlbum is provided',
|
||||
(tester) async {
|
||||
testWidgets('shows delete album option when onDeleteAlbum is provided', (tester) async {
|
||||
bool deleteAlbumCalled = false;
|
||||
|
||||
await tester.pumpConsumerWidget(
|
||||
DriftRemoteAlbumOption(
|
||||
onDeleteAlbum: () => deleteAlbumCalled = true,
|
||||
),
|
||||
);
|
||||
await tester.pumpConsumerWidget(RemoteAlbumOption(onDeleteAlbum: () => deleteAlbumCalled = true));
|
||||
|
||||
await tester.tap(find.byIcon(Icons.more_vert_rounded));
|
||||
await tester.pumpAndSettle();
|
||||
@@ -295,13 +212,8 @@ void main() {
|
||||
expect(deleteAlbumCalled, isTrue);
|
||||
});
|
||||
|
||||
testWidgets('hides delete album option when onDeleteAlbum is null',
|
||||
(tester) async {
|
||||
await tester.pumpConsumerWidget(
|
||||
DriftRemoteAlbumOption(
|
||||
onEditAlbum: () {},
|
||||
),
|
||||
);
|
||||
testWidgets('hides delete album option when onDeleteAlbum is null', (tester) async {
|
||||
await tester.pumpConsumerWidget(RemoteAlbumOption(onEditAlbum: () {}));
|
||||
|
||||
await tester.tap(find.byIcon(Icons.more_vert_rounded));
|
||||
await tester.pumpAndSettle();
|
||||
@@ -310,12 +222,7 @@ void main() {
|
||||
});
|
||||
|
||||
testWidgets('shows divider before delete album option', (tester) async {
|
||||
await tester.pumpConsumerWidget(
|
||||
DriftRemoteAlbumOption(
|
||||
onEditAlbum: () {},
|
||||
onDeleteAlbum: () {},
|
||||
),
|
||||
);
|
||||
await tester.pumpConsumerWidget(RemoteAlbumOption(onEditAlbum: () {}, onDeleteAlbum: () {}));
|
||||
|
||||
await tester.tap(find.byIcon(Icons.more_vert_rounded));
|
||||
await tester.pumpAndSettle();
|
||||
@@ -323,10 +230,9 @@ void main() {
|
||||
expect(find.byType(Divider), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('shows all options when all callbacks are provided',
|
||||
(tester) async {
|
||||
testWidgets('shows all options when all callbacks are provided', (tester) async {
|
||||
await tester.pumpConsumerWidget(
|
||||
DriftRemoteAlbumOption(
|
||||
RemoteAlbumOption(
|
||||
onEditAlbum: () {},
|
||||
onAddPhotos: () {},
|
||||
onAddUsers: () {},
|
||||
@@ -353,9 +259,7 @@ void main() {
|
||||
});
|
||||
|
||||
testWidgets('shows no options when all callbacks are null', (tester) async {
|
||||
await tester.pumpConsumerWidget(
|
||||
const DriftRemoteAlbumOption(),
|
||||
);
|
||||
await tester.pumpConsumerWidget(const RemoteAlbumOption());
|
||||
|
||||
await tester.tap(find.byIcon(Icons.more_vert_rounded));
|
||||
await tester.pumpAndSettle();
|
||||
@@ -373,11 +277,7 @@ void main() {
|
||||
testWidgets('uses custom icon color when provided', (tester) async {
|
||||
const customColor = Colors.red;
|
||||
|
||||
await tester.pumpConsumerWidget(
|
||||
const DriftRemoteAlbumOption(
|
||||
iconColor: customColor,
|
||||
),
|
||||
);
|
||||
await tester.pumpConsumerWidget(const RemoteAlbumOption(iconColor: customColor));
|
||||
|
||||
final iconButton = tester.widget<IconButton>(find.byType(IconButton));
|
||||
final icon = iconButton.icon as Icon;
|
||||
@@ -385,11 +285,8 @@ void main() {
|
||||
expect(icon.color, equals(customColor));
|
||||
});
|
||||
|
||||
testWidgets('uses default white color when iconColor is null',
|
||||
(tester) async {
|
||||
await tester.pumpConsumerWidget(
|
||||
const DriftRemoteAlbumOption(),
|
||||
);
|
||||
testWidgets('uses default white color when iconColor is null', (tester) async {
|
||||
await tester.pumpConsumerWidget(const RemoteAlbumOption());
|
||||
|
||||
final iconButton = tester.widget<IconButton>(find.byType(IconButton));
|
||||
final icon = iconButton.icon as Icon;
|
||||
@@ -398,15 +295,9 @@ void main() {
|
||||
});
|
||||
|
||||
testWidgets('applies icon shadows when provided', (tester) async {
|
||||
final shadows = [
|
||||
const Shadow(offset: Offset(0, 2), blurRadius: 5, color: Colors.black),
|
||||
];
|
||||
final shadows = [const Shadow(offset: Offset(0, 2), blurRadius: 5, color: Colors.black)];
|
||||
|
||||
await tester.pumpConsumerWidget(
|
||||
DriftRemoteAlbumOption(
|
||||
iconShadows: shadows,
|
||||
),
|
||||
);
|
||||
await tester.pumpConsumerWidget(RemoteAlbumOption(iconShadows: shadows));
|
||||
|
||||
final iconButton = tester.widget<IconButton>(find.byType(IconButton));
|
||||
final icon = iconButton.icon as Icon;
|
||||
@@ -418,7 +309,7 @@ void main() {
|
||||
testWidgets('owner sees all management options', (tester) async {
|
||||
// Simulating owner scenario - all callbacks provided
|
||||
await tester.pumpConsumerWidget(
|
||||
DriftRemoteAlbumOption(
|
||||
RemoteAlbumOption(
|
||||
onEditAlbum: () {},
|
||||
onAddPhotos: () {},
|
||||
onAddUsers: () {},
|
||||
@@ -443,15 +334,10 @@ void main() {
|
||||
expect(find.byIcon(Icons.person_remove_rounded), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('non-owner with editor role sees limited options',
|
||||
(tester) async {
|
||||
testWidgets('non-owner with editor role sees limited options', (tester) async {
|
||||
// Simulating non-owner with editor role - can add photos, show options, leave
|
||||
await tester.pumpConsumerWidget(
|
||||
DriftRemoteAlbumOption(
|
||||
onAddPhotos: () {},
|
||||
onShowOptions: () {},
|
||||
onLeaveAlbum: () {},
|
||||
),
|
||||
RemoteAlbumOption(onAddPhotos: () {}, onShowOptions: () {}, onLeaveAlbum: () {}),
|
||||
);
|
||||
|
||||
await tester.tap(find.byIcon(Icons.more_vert_rounded));
|
||||
@@ -473,12 +359,7 @@ void main() {
|
||||
|
||||
testWidgets('non-owner viewer sees minimal options', (tester) async {
|
||||
// Simulating viewer - can only show options and leave
|
||||
await tester.pumpConsumerWidget(
|
||||
DriftRemoteAlbumOption(
|
||||
onShowOptions: () {},
|
||||
onLeaveAlbum: () {},
|
||||
),
|
||||
);
|
||||
await tester.pumpConsumerWidget(RemoteAlbumOption(onShowOptions: () {}, onLeaveAlbum: () {}));
|
||||
|
||||
await tester.tap(find.byIcon(Icons.more_vert_rounded));
|
||||
await tester.pumpAndSettle();
|
||||
@@ -9,7 +9,7 @@ import 'package:immich_mobile/models/auth/auth_state.model.dart';
|
||||
import 'package:immich_mobile/models/server_info/server_version.model.dart';
|
||||
import 'package:immich_mobile/providers/app_life_cycle.provider.dart';
|
||||
import 'package:immich_mobile/providers/auth.provider.dart';
|
||||
import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
|
||||
import 'package:immich_mobile/providers/backup/backup.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/platform.provider.dart';
|
||||
import 'package:immich_mobile/providers/server_info.provider.dart';
|
||||
import 'package:immich_mobile/providers/websocket.provider.dart';
|
||||
@@ -66,7 +66,7 @@ class TestWebsocketNotifier extends WebsocketNotifier {
|
||||
void disconnect() => disconnectCount++;
|
||||
}
|
||||
|
||||
class TestDriftBackupNotifier extends DriftBackupNotifier {
|
||||
class TestDriftBackupNotifier extends BackupNotifier {
|
||||
TestDriftBackupNotifier() : super(MockForegroundUploadService(), MockBackgroundUploadService(), UploadSpeedManager());
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ void main() {
|
||||
websocketProvider.overrideWith((ref) {
|
||||
return websocket = TestWebsocketNotifier(ref);
|
||||
}),
|
||||
driftBackupProvider.overrideWith((_) => TestDriftBackupNotifier()),
|
||||
backupProvider.overrideWith((_) => TestDriftBackupNotifier()),
|
||||
backgroundWorkerLockServiceProvider.overrideWithValue(lockService),
|
||||
],
|
||||
);
|
||||
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
|
||||
import 'package:immich_mobile/providers/backup/backup.provider.dart';
|
||||
import 'package:immich_mobile/services/background_upload.service.dart';
|
||||
import 'package:immich_mobile/services/foreground_upload.service.dart';
|
||||
import 'package:immich_mobile/utils/upload_speed_calculator.dart';
|
||||
@@ -14,7 +14,7 @@ class MockBackgroundUploadService extends Mock implements BackgroundUploadServic
|
||||
void main() {
|
||||
late MockForegroundUploadService foregroundUploadService;
|
||||
late MockBackgroundUploadService backgroundUploadService;
|
||||
late DriftBackupNotifier notifier;
|
||||
late BackupNotifier notifier;
|
||||
|
||||
setUpAll(() {
|
||||
registerFallbackValue(Completer<void>());
|
||||
@@ -24,7 +24,7 @@ void main() {
|
||||
setUp(() {
|
||||
foregroundUploadService = MockForegroundUploadService();
|
||||
backgroundUploadService = MockBackgroundUploadService();
|
||||
notifier = DriftBackupNotifier(foregroundUploadService, backgroundUploadService, UploadSpeedManager());
|
||||
notifier = BackupNotifier(foregroundUploadService, backgroundUploadService, UploadSpeedManager());
|
||||
addTearDown(() {
|
||||
if (notifier.mounted) {
|
||||
notifier.dispose();
|
||||
@@ -52,11 +52,11 @@ void main() {
|
||||
when(() => userService.watchMyUser()).thenAnswer((_) => const Stream.empty());
|
||||
});
|
||||
|
||||
group('driftMemoryLaneProvider', () {
|
||||
group('memoryLaneProvider', () {
|
||||
test('re-queries after local midnight', () {
|
||||
fakeAsync((async) {
|
||||
final container = makeContainer();
|
||||
container.listen(driftMemoryLaneProvider, (_, _) {});
|
||||
container.listen(memoryLaneProvider, (_, _) {});
|
||||
async.flushMicrotasks();
|
||||
|
||||
verify(() => memoryRepository.getAll('user-1')).called(1);
|
||||
@@ -74,7 +74,7 @@ void main() {
|
||||
test('cancels the midnight timer when disposed', () {
|
||||
fakeAsync((async) {
|
||||
final container = makeContainer();
|
||||
final subscription = container.listen(driftMemoryLaneProvider, (_, _) {});
|
||||
final subscription = container.listen(memoryLaneProvider, (_, _) {});
|
||||
async.flushMicrotasks();
|
||||
verify(() => memoryRepository.getAll('user-1')).called(1);
|
||||
|
||||
@@ -91,7 +91,7 @@ void main() {
|
||||
|
||||
fakeAsync((async) {
|
||||
final container = makeContainer();
|
||||
container.listen(driftMemoryLaneProvider, (_, _) {});
|
||||
container.listen(memoryLaneProvider, (_, _) {});
|
||||
async.flushMicrotasks();
|
||||
|
||||
async.elapse(const Duration(hours: 25));
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:immich_mobile/repositories/drift_album_api_repository.dart';
|
||||
import 'package:immich_mobile/repositories/album_api_repository.dart';
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
import 'package:openapi/api.dart';
|
||||
|
||||
@@ -7,7 +7,7 @@ class _MockAlbumsApi extends Mock implements AlbumsApi {}
|
||||
|
||||
void main() {
|
||||
late _MockAlbumsApi api;
|
||||
late DriftAlbumApiRepository repo;
|
||||
late AlbumApiRepository repo;
|
||||
|
||||
setUpAll(() {
|
||||
registerFallbackValue(BulkIdsDto(ids: const []));
|
||||
@@ -15,7 +15,7 @@ void main() {
|
||||
|
||||
setUp(() {
|
||||
api = _MockAlbumsApi();
|
||||
repo = DriftAlbumApiRepository(api);
|
||||
repo = AlbumApiRepository(api);
|
||||
});
|
||||
|
||||
void stubResponse(List<BulkIdResponseDto> response) {
|
||||
@@ -22,9 +22,9 @@ class MockAssetService extends Mock implements AssetService {}
|
||||
|
||||
class MockRemoteAlbumService extends Mock implements RemoteAlbumService {}
|
||||
|
||||
class MockDriftMemoryService extends Mock implements DriftMemoryService {}
|
||||
class MockMemoryService extends Mock implements MemoryService {}
|
||||
|
||||
class MockDriftPeopleService extends Mock implements DriftPeopleService {}
|
||||
class MockPeopleService extends Mock implements PeopleService {}
|
||||
|
||||
class MockPlatformDeepLink extends Mock implements PlatformDeepLink {}
|
||||
|
||||
@@ -62,7 +62,7 @@ final _album = RemoteAlbum(
|
||||
ownerName: 'Owner',
|
||||
);
|
||||
|
||||
final _memory = DriftMemory(
|
||||
final _memory = Memory(
|
||||
id: _memoryId,
|
||||
createdAt: DateTime(2026, 6, 12),
|
||||
updatedAt: DateTime(2026, 6, 12),
|
||||
@@ -85,7 +85,7 @@ void main() {
|
||||
late MockTimelineFactory timelineFactory;
|
||||
late MockAssetService assetService;
|
||||
late MockRemoteAlbumService remoteAlbumService;
|
||||
late MockDriftMemoryService memoryService;
|
||||
late MockMemoryService memoryService;
|
||||
late MockWidgetRef ref;
|
||||
late List<TimelineService> createdTimelineServices;
|
||||
late DeepLinkService sut;
|
||||
@@ -94,7 +94,7 @@ void main() {
|
||||
timelineFactory = MockTimelineFactory();
|
||||
assetService = MockAssetService();
|
||||
remoteAlbumService = MockRemoteAlbumService();
|
||||
memoryService = MockDriftMemoryService();
|
||||
memoryService = MockMemoryService();
|
||||
ref = MockWidgetRef();
|
||||
createdTimelineServices = [];
|
||||
|
||||
@@ -116,7 +116,7 @@ void main() {
|
||||
assetService,
|
||||
remoteAlbumService,
|
||||
memoryService,
|
||||
MockDriftPeopleService(),
|
||||
MockPeopleService(),
|
||||
_user,
|
||||
);
|
||||
|
||||
@@ -170,8 +170,8 @@ void main() {
|
||||
|
||||
final route = await sut.handleScheme(deepLink, ref);
|
||||
|
||||
expect(route, isA<DriftMemoryRoute>());
|
||||
expect((route!.args! as DriftMemoryRouteArgs).memories, [_memory]);
|
||||
expect(route, isA<MemoryRoute>());
|
||||
expect((route!.args! as MemoryRouteArgs).memories, [_memory]);
|
||||
verify(() => memoryService.getMemoryLane(_userId)).called(1);
|
||||
verifyNever(() => memoryService.get(any()));
|
||||
});
|
||||
@@ -183,8 +183,8 @@ void main() {
|
||||
|
||||
final route = await sut.handleScheme(deepLink, ref);
|
||||
|
||||
expect(route, isA<DriftMemoryRoute>());
|
||||
expect((route!.args! as DriftMemoryRouteArgs).memories, [_memory]);
|
||||
expect(route, isA<MemoryRoute>());
|
||||
expect((route!.args! as MemoryRouteArgs).memories, [_memory]);
|
||||
verifyNever(() => memoryService.getMemoryLane(any()));
|
||||
verify(() => memoryService.get(_memoryId)).called(1);
|
||||
});
|
||||
|
||||
@@ -31,7 +31,7 @@ class RepositoryMocks {
|
||||
final remoteExif = RemoteExifRepositoryStub(MockRemoteExifRepository());
|
||||
final trashedAsset = MockTrashedLocalAssetRepository();
|
||||
final remoteAlbum = MockRemoteAlbumRepository();
|
||||
final albumApi = MockDriftAlbumApiRepository();
|
||||
final albumApi = MockAlbumApiRepository();
|
||||
final permission = PermissionRepositoryStub(MockPermissionRepository());
|
||||
|
||||
final nativeApi = NativeSyncApiStub(MockNativeSyncApi());
|
||||
|
||||
Reference in New Issue
Block a user