2021-09-25 18:22:19 +02:00
|
|
|
import 'package:logging/logging.dart';
|
2021-09-08 10:17:51 +02:00
|
|
|
import 'package:nc_photos/account.dart';
|
2021-11-01 10:50:13 +01:00
|
|
|
import 'package:nc_photos/app_db.dart';
|
2021-10-23 06:47:32 +02:00
|
|
|
import 'package:nc_photos/debug_util.dart';
|
2021-09-08 10:17:51 +02:00
|
|
|
import 'package:nc_photos/entity/album.dart';
|
|
|
|
import 'package:nc_photos/entity/album/item.dart';
|
|
|
|
import 'package:nc_photos/entity/album/provider.dart';
|
2021-10-23 06:47:32 +02:00
|
|
|
import 'package:nc_photos/entity/file.dart';
|
|
|
|
import 'package:nc_photos/entity/share.dart';
|
2021-11-17 20:39:22 +01:00
|
|
|
import 'package:nc_photos/override_comparator.dart';
|
2021-10-29 19:37:11 +02:00
|
|
|
import 'package:nc_photos/pref.dart';
|
2021-10-23 06:47:32 +02:00
|
|
|
import 'package:nc_photos/use_case/create_share.dart';
|
|
|
|
import 'package:nc_photos/use_case/list_share.dart';
|
2021-09-29 13:00:00 +02:00
|
|
|
import 'package:nc_photos/use_case/preprocess_album.dart';
|
2021-09-08 10:17:51 +02:00
|
|
|
import 'package:nc_photos/use_case/update_album.dart';
|
2021-09-25 18:22:19 +02:00
|
|
|
import 'package:nc_photos/use_case/update_album_with_actual_items.dart';
|
2021-09-08 10:17:51 +02:00
|
|
|
|
|
|
|
class AddToAlbum {
|
2021-11-01 15:43:02 +01:00
|
|
|
const AddToAlbum(this.albumRepo, this.shareRepo, this.appDb, this.pref);
|
2021-09-08 10:17:51 +02:00
|
|
|
|
|
|
|
/// Add a list of AlbumItems to [album]
|
2021-09-25 18:22:19 +02:00
|
|
|
Future<Album> call(
|
|
|
|
Account account, Album album, List<AlbumItem> items) async {
|
|
|
|
_log.info("[call] Add ${items.length} items to album '${album.name}'");
|
|
|
|
assert(album.provider is AlbumStaticProvider);
|
|
|
|
// resync is needed to work out album cover and latest item
|
2021-11-01 10:50:13 +01:00
|
|
|
final oldItems = await PreProcessAlbum(appDb)(account, album);
|
2021-11-17 20:39:22 +01:00
|
|
|
final itemSet = oldItems
|
|
|
|
.map((e) => OverrideComparator<AlbumItem>(
|
|
|
|
e, _isItemFileEqual, _getItemHashCode))
|
|
|
|
.toSet();
|
|
|
|
// find the items that are not having the same file as any existing ones
|
|
|
|
final addItems = items
|
|
|
|
.where((i) => itemSet.add(OverrideComparator<AlbumItem>(
|
|
|
|
i, _isItemFileEqual, _getItemHashCode)))
|
|
|
|
.toList();
|
|
|
|
if (addItems.isEmpty) {
|
|
|
|
return album;
|
|
|
|
}
|
|
|
|
final newItems = <AlbumItem>[...addItems, ...oldItems];
|
2021-09-25 18:22:19 +02:00
|
|
|
var newAlbum = album.copyWith(
|
|
|
|
provider: AlbumStaticProvider.of(album).copyWith(
|
|
|
|
items: newItems,
|
|
|
|
),
|
|
|
|
);
|
|
|
|
// UpdateAlbumWithActualItems only persists when there are changes to
|
|
|
|
// several properties, so we can't rely on it
|
|
|
|
newAlbum = await UpdateAlbumWithActualItems(null)(
|
|
|
|
account,
|
|
|
|
newAlbum,
|
|
|
|
newItems,
|
|
|
|
);
|
|
|
|
await UpdateAlbum(albumRepo)(account, newAlbum);
|
2021-10-23 06:47:32 +02:00
|
|
|
|
2021-11-01 15:43:02 +01:00
|
|
|
if (pref.isLabEnableSharedAlbumOr(false)) {
|
2021-10-29 19:37:11 +02:00
|
|
|
final newFiles =
|
|
|
|
items.whereType<AlbumFileItem>().map((e) => e.file).toList();
|
|
|
|
if (newFiles.isNotEmpty) {
|
|
|
|
await _shareFiles(account, newAlbum, newFiles);
|
|
|
|
}
|
2021-10-23 06:47:32 +02:00
|
|
|
}
|
|
|
|
|
2021-09-25 18:22:19 +02:00
|
|
|
return newAlbum;
|
|
|
|
}
|
2021-09-08 10:17:51 +02:00
|
|
|
|
2021-10-23 06:47:32 +02:00
|
|
|
Future<void> _shareFiles(
|
|
|
|
Account account, Album album, List<File> files) async {
|
2021-11-11 18:03:36 +01:00
|
|
|
if (album.shares?.isNotEmpty != true) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
final albumShares = (album.shares!.map((e) => e.userId).toList()
|
|
|
|
..add(album.albumFile!.ownerId ?? account.username))
|
2021-11-12 22:13:02 +01:00
|
|
|
.where((element) => element != account.username)
|
2021-11-11 18:03:36 +01:00
|
|
|
.toSet();
|
|
|
|
if (albumShares.isEmpty) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (final f in files) {
|
|
|
|
try {
|
|
|
|
final fileShares = (await ListShare(shareRepo)(account, f))
|
|
|
|
.where((element) => element.shareType == ShareType.user)
|
|
|
|
.map((e) => e.shareWith!)
|
|
|
|
.toSet();
|
|
|
|
final diffShares = albumShares.difference(fileShares);
|
|
|
|
for (final s in diffShares) {
|
2021-11-19 18:03:53 +01:00
|
|
|
if (s == f.ownerId) {
|
|
|
|
// skip files already owned by the target user
|
|
|
|
continue;
|
|
|
|
}
|
2021-11-11 18:03:36 +01:00
|
|
|
try {
|
2021-11-12 22:13:02 +01:00
|
|
|
await CreateUserShare(shareRepo)(account, f, s.raw);
|
2021-11-11 18:03:36 +01:00
|
|
|
} catch (e, stackTrace) {
|
|
|
|
_log.shout(
|
|
|
|
"[_shareFiles] Failed while CreateUserShare: ${logFilename(f.path)}",
|
|
|
|
e,
|
|
|
|
stackTrace);
|
2021-10-23 06:47:32 +02:00
|
|
|
}
|
|
|
|
}
|
2021-11-11 18:03:36 +01:00
|
|
|
} catch (e, stackTrace) {
|
|
|
|
_log.shout(
|
|
|
|
"[_shareFiles] Failed while listing shares: ${logFilename(f.path)}",
|
|
|
|
e,
|
|
|
|
stackTrace);
|
2021-10-23 06:47:32 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-08 10:17:51 +02:00
|
|
|
final AlbumRepo albumRepo;
|
2021-10-23 06:47:32 +02:00
|
|
|
final ShareRepo shareRepo;
|
2021-11-01 10:50:13 +01:00
|
|
|
final AppDb appDb;
|
2021-11-01 15:43:02 +01:00
|
|
|
final Pref pref;
|
2021-09-25 18:22:19 +02:00
|
|
|
|
|
|
|
static final _log = Logger("use_case.add_to_album.AddToAlbum");
|
2021-09-08 10:17:51 +02:00
|
|
|
}
|
2021-11-17 20:39:22 +01:00
|
|
|
|
|
|
|
bool _isItemFileEqual(AlbumItem a, AlbumItem b) {
|
|
|
|
if (a is! AlbumFileItem || b is! AlbumFileItem) {
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
return a.file.compareServerIdentity(b.file);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int _getItemHashCode(AlbumItem a) {
|
|
|
|
if (a is AlbumFileItem) {
|
|
|
|
return a.file.path.hashCode;
|
|
|
|
} else {
|
|
|
|
return a.hashCode;
|
|
|
|
}
|
|
|
|
}
|