nc-photos/app/lib/use_case/cache_favorite.dart

116 lines
3.9 KiB
Dart
Raw Normal View History

2022-07-25 07:51:52 +02:00
import 'package:collection/collection.dart';
import 'package:drift/drift.dart' as sql;
2022-01-25 11:08:13 +01:00
import 'package:event_bus/event_bus.dart';
import 'package:kiwi/kiwi.dart';
import 'package:logging/logging.dart';
import 'package:nc_photos/account.dart';
import 'package:nc_photos/di_container.dart';
2023-02-20 15:21:35 +01:00
import 'package:nc_photos/entity/sqlite/database.dart' as sql;
import 'package:nc_photos/entity/sqlite/files_query_builder.dart' as sql;
2022-01-25 11:08:13 +01:00
import 'package:nc_photos/event/event.dart';
import 'package:nc_photos/iterable_extension.dart';
2022-01-25 11:08:13 +01:00
import 'package:nc_photos/list_util.dart' as list_util;
import 'package:nc_photos/object_extension.dart';
2022-12-16 16:01:04 +01:00
import 'package:np_codegen/np_codegen.dart';
2022-01-25 11:08:13 +01:00
2022-12-16 16:01:04 +01:00
part 'cache_favorite.g.dart';
@npLog
2022-01-25 11:08:13 +01:00
class CacheFavorite {
CacheFavorite(this._c) : assert(require(_c));
2022-01-25 11:08:13 +01:00
static bool require(DiContainer c) => DiContainer.has(c, DiType.sqliteDb);
2022-01-25 11:08:13 +01:00
/// Cache favorites using results from remote
///
/// Return number of files updated
Future<int> call(Account account, Iterable<int> remoteFileIds) async {
_log.info("[call] Cache favorites");
final remote = remoteFileIds.sorted(Comparable.compare);
final updateCount = await _c.sqliteDb.use((db) async {
final dbAccount = await db.accountOf(account);
final cache = await _getCacheFavorites(db, dbAccount);
final cacheMap =
Map.fromEntries(cache.map((e) => MapEntry(e.fileId, e.rowId)));
final diff =
list_util.diff(cacheMap.keys.sorted(Comparable.compare), remote);
2023-02-14 16:40:30 +01:00
final newFileIds = diff.onlyInB;
_log.info("[call] New favorites: ${newFileIds.toReadableString()}");
2023-02-14 16:40:30 +01:00
final removedFildIds = diff.onlyInA;
_log.info(
"[call] Removed favorites: ${removedFildIds.toReadableString()}");
var updateCount = 0;
if (newFileIds.isNotEmpty) {
final rowIds = await db.accountFileRowIdsByFileIds(newFileIds,
sqlAccount: dbAccount);
2022-08-06 19:00:38 +02:00
final counts =
await rowIds.map((id) => id.accountFileRowId).withPartition(
(sublist) async {
return [
await (db.update(db.accountFiles)
..where((t) => t.rowId.isIn(sublist)))
.write(const sql.AccountFilesCompanion(
isFavorite: sql.Value(true))),
];
},
sql.maxByFileIdsSize,
);
final count = counts.sum;
_log.info("[call] Updated $count row (new)");
updateCount += count;
}
if (removedFildIds.isNotEmpty) {
2022-08-06 19:00:38 +02:00
final counts =
await removedFildIds.map((id) => cacheMap[id]).withPartition(
(sublist) async {
return [
await (db.update(db.accountFiles)
..where((t) =>
t.account.equals(dbAccount.rowId) &
t.file.isIn(sublist)))
.write(const sql.AccountFilesCompanion(
isFavorite: sql.Value(false)))
];
},
sql.maxByFileIdsSize,
);
final count = counts.sum;
_log.info("[call] Updated $count row (remove)");
updateCount += count;
}
return updateCount;
});
2022-01-25 11:08:13 +01:00
if (updateCount > 0) {
KiwiContainer().resolve<EventBus>().fire(FavoriteResyncedEvent(account));
}
return updateCount;
}
Future<List<_FileRowIdWithFileId>> _getCacheFavorites(
sql.SqliteDb db, sql.Account dbAccount) async {
final query = db.queryFiles().run((q) {
q
..setQueryMode(sql.FilesQueryMode.expression,
expressions: [db.files.rowId, db.files.fileId])
..setSqlAccount(dbAccount)
..byFavorite(true);
return q.build();
});
return await query
.map((r) => _FileRowIdWithFileId(
r.read(db.files.rowId)!, r.read(db.files.fileId)!))
.get();
2022-01-25 11:08:13 +01:00
}
final DiContainer _c;
}
class _FileRowIdWithFileId {
const _FileRowIdWithFileId(this.rowId, this.fileId);
final int rowId;
final int fileId;
}