ente/lib/services/favorites_service.dart

185 lines
6.1 KiB
Dart
Raw Normal View History

// @dart=2.9
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_sodium/flutter_sodium.dart';
import 'package:photos/core/configuration.dart';
import 'package:photos/core/event_bus.dart';
2020-10-24 10:25:02 +00:00
import 'package:photos/db/files_db.dart';
import 'package:photos/events/collection_updated_event.dart';
import 'package:photos/events/files_updated_event.dart';
import 'package:photos/models/collection.dart';
2020-06-19 23:03:26 +00:00
import 'package:photos/models/file.dart';
import 'package:photos/services/collections_service.dart';
import 'package:photos/services/remote_sync_service.dart';
import 'package:photos/utils/crypto_util.dart';
2020-05-06 16:43:03 +00:00
2020-10-03 17:56:18 +00:00
class FavoritesService {
Configuration _config;
CollectionsService _collectionsService;
2020-10-24 10:25:02 +00:00
FilesDB _filesDB;
2020-10-30 20:17:06 +00:00
int _cachedFavoritesCollectionID;
final Set<int> _cachedFavUploadedIDs = {};
final Set<String> _cachedPendingLocalIDs = {};
StreamSubscription<CollectionUpdatedEvent> _collectionUpdatesSubscription;
FavoritesService._privateConstructor() {
_config = Configuration.instance;
_collectionsService = CollectionsService.instance;
2020-10-24 10:25:02 +00:00
_filesDB = FilesDB.instance;
_collectionUpdatesSubscription =
Bus.instance.on<CollectionUpdatedEvent>().listen((event) {
if (event.collectionID != null &&
_cachedFavoritesCollectionID != null &&
_cachedFavoritesCollectionID == event.collectionID) {
if (event.type == EventType.addedOrUpdated) {
_updateFavoriteFilesCache(event.updatedFiles, favFlag: true);
} else if (event.type == EventType.deletedFromEverywhere ||
event.type == EventType.deletedFromRemote) {
_updateFavoriteFilesCache(event.updatedFiles, favFlag: false);
}
}
});
}
Future<void> initFav() async {
await _warmUpCache();
}
void dispose() {
_collectionUpdatesSubscription.cancel();
}
Future<void> _warmUpCache() async {
final favCollection = await _getFavoritesCollection();
if (favCollection != null) {
final uploadedIDs =
await FilesDB.instance.getUploadedFileIDs(favCollection.id);
_cachedFavUploadedIDs.addAll(uploadedIDs);
}
}
static FavoritesService instance = FavoritesService._privateConstructor();
2020-05-06 16:43:03 +00:00
2021-03-17 21:11:31 +00:00
void clearCache() {
_cachedFavoritesCollectionID = null;
}
bool isFavoriteCache(File file, {bool checkOnlyAlbum = false}) {
if (file.collectionID != null &&
_cachedFavoritesCollectionID != null &&
file.collectionID == _cachedFavoritesCollectionID) {
return true;
}
if(checkOnlyAlbum) {
return false;
}
if (file.uploadedFileID != null) {
return _cachedFavUploadedIDs.contains(file.uploadedFileID);
} else if (file.localID != null) {
return _cachedPendingLocalIDs.contains(file.localID);
}
return false;
}
2020-10-30 20:17:06 +00:00
Future<bool> isFavorite(File file) async {
final collection = await _getFavoritesCollection();
if (collection == null) {
return false;
2020-10-24 10:25:02 +00:00
}
2020-10-30 20:17:06 +00:00
return _filesDB.doesFileExistInCollection(
2022-06-11 08:23:52 +00:00
file.uploadedFileID,
collection.id,
);
2020-05-06 16:43:03 +00:00
}
void _updateFavoriteFilesCache(List<File> files, {@required bool favFlag}) {
final Set<int> updatedIDs = {};
final Set<String> localIDs = {};
for (var file in files) {
if (file.uploadedFileID != null) {
updatedIDs.add(file.uploadedFileID);
} else if (file.localID != null || file.localID != "") {
/* Note: Favorite un-uploaded files
For such files, as we don't have uploaded IDs yet, we will cache
cache the local ID for showing the fav icon in the gallery
*/
localIDs.add(file.localID);
}
}
if (favFlag) {
_cachedFavUploadedIDs.addAll(updatedIDs);
} else {
_cachedFavUploadedIDs.removeAll(updatedIDs);
}
}
Future<void> addToFavorites(File file) async {
final collectionID = await _getOrCreateFavoriteCollectionID();
final List<File> files = [file];
if (file.uploadedFileID == null) {
file.collectionID = collectionID;
await _filesDB.insert(file);
Bus.instance.fire(CollectionUpdatedEvent(collectionID, files, "addTFav"));
} else {
await _collectionsService.addToCollection(collectionID, files);
}
_updateFavoriteFilesCache(files, favFlag: true);
RemoteSyncService.instance.sync(silently: true);
}
2020-10-23 16:18:38 +00:00
Future<void> removeFromFavorites(File file) async {
final collectionID = await _getOrCreateFavoriteCollectionID();
2022-08-29 14:43:31 +00:00
final fileID = file.uploadedFileID;
2020-10-23 16:18:38 +00:00
if (fileID == null) {
// Do nothing, ignore
} else {
2020-10-24 10:25:02 +00:00
await _collectionsService.removeFromCollection(collectionID, [file]);
2020-10-23 16:18:38 +00:00
}
_updateFavoriteFilesCache([file], favFlag: false);
2020-10-23 16:18:38 +00:00
}
2020-10-30 20:17:06 +00:00
Future<Collection> _getFavoritesCollection() async {
if (_cachedFavoritesCollectionID == null) {
final collections = _collectionsService.getActiveCollections();
for (final collection in collections) {
if (collection.owner.id == _config.getUserID() &&
collection.type == CollectionType.favorites) {
2020-10-30 20:17:06 +00:00
_cachedFavoritesCollectionID = collection.id;
return collection;
}
}
return null;
}
2020-10-30 20:17:06 +00:00
return _collectionsService.getCollectionByID(_cachedFavoritesCollectionID);
}
Future<int> _getOrCreateFavoriteCollectionID() async {
2020-10-30 20:17:06 +00:00
if (_cachedFavoritesCollectionID != null) {
return _cachedFavoritesCollectionID;
}
final key = CryptoUtil.generateKey();
final encryptedKeyData = CryptoUtil.encryptSync(key, _config.getKey());
final encryptedName = CryptoUtil.encryptSync(utf8.encode("Favorites"), key);
2022-06-11 08:23:52 +00:00
final collection = await _collectionsService.createAndCacheCollection(
Collection(
null,
null,
Sodium.bin2base64(encryptedKeyData.encryptedData),
Sodium.bin2base64(encryptedKeyData.nonce),
null,
Sodium.bin2base64(encryptedName.encryptedData),
Sodium.bin2base64(encryptedName.nonce),
CollectionType.favorites,
CollectionAttributes(),
null,
null,
null,
),
);
2020-10-30 20:17:06 +00:00
_cachedFavoritesCollectionID = collection.id;
return collection.id;
}
2020-05-06 16:43:03 +00:00
}