import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/constants/enums.dart'; import 'package:immich_mobile/extensions/platform_extensions.dart'; import 'package:immich_mobile/infrastructure/repositories/local_asset.repository.dart'; import 'package:immich_mobile/providers/infrastructure/asset.provider.dart'; import 'package:immich_mobile/repositories/asset_media.repository.dart'; final cleanupServiceProvider = Provider((ref) { return CleanupService(ref.watch(localAssetRepository), ref.watch(assetMediaRepositoryProvider)); }); class CleanupService { static final int _deleteBatchSize = CurrentPlatform.isAndroid ? 2000 : 10000; final DriftLocalAssetRepository _localAssetRepository; final AssetMediaRepository _assetMediaRepository; const CleanupService(this._localAssetRepository, this._assetMediaRepository); Future getRemovalCandidates( String userId, DateTime cutoffDate, { AssetKeepType keepMediaType = AssetKeepType.none, bool keepFavorites = true, Set keepAlbumIds = const {}, }) { return _localAssetRepository.getRemovalCandidates( userId, cutoffDate, keepMediaType: keepMediaType, keepFavorites: keepFavorites, keepAlbumIds: keepAlbumIds, ); } Future deleteLocalAssets(List localIds) async { if (localIds.isEmpty) { return 0; } int deletedCount = 0; for (int index = 0; index < localIds.length; index += _deleteBatchSize) { final end = index + _deleteBatchSize < localIds.length ? index + _deleteBatchSize : localIds.length; final batch = localIds.sublist(index, end); final deletedIds = await _assetMediaRepository.deleteAll(batch); if (deletedIds.isNotEmpty) { await _localAssetRepository.delete(deletedIds); deletedCount += deletedIds.length; } } return deletedCount; } /// Returns album IDs that should be kept by default (e.g., messaging app albums) Set getDefaultKeepAlbumIds(List<(String id, String name)> albums) { const messagingApps = ['whatsapp', 'telegram', 'signal', 'messenger', 'viber', 'wechat', 'line']; final toKeep = {}; for (final (id, name) in albums) { final albumName = name.toLowerCase(); if (messagingApps.any((app) => albumName.contains(app))) { toKeep.add(id); } } return toKeep; } }