trashed_asset.provider.dart 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. import 'package:hooks_riverpod/hooks_riverpod.dart';
  2. import 'package:immich_mobile/modules/home/ui/asset_grid/asset_grid_data_structure.dart';
  3. import 'package:immich_mobile/modules/trash/services/trash.service.dart';
  4. import 'package:immich_mobile/shared/models/asset.dart';
  5. import 'package:immich_mobile/shared/providers/db.provider.dart';
  6. import 'package:immich_mobile/shared/providers/user.provider.dart';
  7. import 'package:immich_mobile/shared/services/sync.service.dart';
  8. import 'package:isar/isar.dart';
  9. import 'package:logging/logging.dart';
  10. class TrashNotifier extends StateNotifier<bool> {
  11. final Isar _db;
  12. final Ref _ref;
  13. final TrashService _trashService;
  14. final _log = Logger('TrashNotifier');
  15. TrashNotifier(
  16. this._trashService,
  17. this._db,
  18. this._ref,
  19. ) : super(false);
  20. Future<void> emptyTrash() async {
  21. try {
  22. final user = _ref.read(currentUserProvider);
  23. if (user == null) {
  24. return;
  25. }
  26. await _trashService.emptyTrash();
  27. final idsToRemove = await _db.assets
  28. .where()
  29. .remoteIdIsNotNull()
  30. .filter()
  31. .ownerIdEqualTo(user.isarId)
  32. .isTrashedEqualTo(true)
  33. .remoteIdProperty()
  34. .findAll();
  35. // TODO: handle local asset removal on emptyTrash
  36. _ref
  37. .read(syncServiceProvider)
  38. .handleRemoteAssetRemoval(idsToRemove.cast<String>().toList());
  39. } catch (error, stack) {
  40. _log.severe("Cannot empty trash ${error.toString()}", error, stack);
  41. }
  42. }
  43. Future<bool> restoreAssets(Iterable<Asset> assetList) async {
  44. try {
  45. final result = await _trashService.restoreAssets(assetList);
  46. if (result) {
  47. final remoteAssets = assetList.where((a) => a.isRemote).toList();
  48. final updatedAssets = remoteAssets.map((e) {
  49. e.isTrashed = false;
  50. return e;
  51. }).toList();
  52. await _db.writeTxn(() async {
  53. await _db.assets.putAll(updatedAssets);
  54. });
  55. return true;
  56. }
  57. } catch (error, stack) {
  58. _log.severe("Cannot restore trash ${error.toString()}", error, stack);
  59. }
  60. return false;
  61. }
  62. Future<void> restoreTrash() async {
  63. try {
  64. final user = _ref.read(currentUserProvider);
  65. if (user == null) {
  66. return;
  67. }
  68. await _trashService.restoreTrash();
  69. final assets = await _db.assets
  70. .where()
  71. .remoteIdIsNotNull()
  72. .filter()
  73. .ownerIdEqualTo(user.isarId)
  74. .isTrashedEqualTo(true)
  75. .findAll();
  76. final updatedAssets = assets.map((e) {
  77. e.isTrashed = false;
  78. return e;
  79. }).toList();
  80. await _db.writeTxn(() async {
  81. await _db.assets.putAll(updatedAssets);
  82. });
  83. } catch (error, stack) {
  84. _log.severe("Cannot restore trash ${error.toString()}", error, stack);
  85. }
  86. }
  87. }
  88. final trashProvider = StateNotifierProvider<TrashNotifier, bool>((ref) {
  89. return TrashNotifier(
  90. ref.watch(trashServiceProvider),
  91. ref.watch(dbProvider),
  92. ref,
  93. );
  94. });
  95. final trashedAssetsProvider = StreamProvider<RenderList>((ref) async* {
  96. final user = ref.read(currentUserProvider);
  97. if (user == null) return;
  98. final query = ref
  99. .watch(dbProvider)
  100. .assets
  101. .filter()
  102. .ownerIdEqualTo(user.isarId)
  103. .isTrashedEqualTo(true)
  104. .sortByFileCreatedAt();
  105. const groupBy = GroupAssetsBy.none;
  106. yield await RenderList.fromQuery(query, groupBy);
  107. await for (final _ in query.watchLazy()) {
  108. yield await RenderList.fromQuery(query, groupBy);
  109. }
  110. });