mirror of
https://gitlab.com/nkming2/nc-photos.git
synced 2025-01-22 16:56:19 +01:00
206 lines
6.1 KiB
Dart
206 lines
6.1 KiB
Dart
import 'dart:async';
|
|
|
|
import 'package:collection/collection.dart';
|
|
import 'package:logging/logging.dart';
|
|
import 'package:nc_photos/account.dart';
|
|
import 'package:nc_photos/di_container.dart';
|
|
import 'package:nc_photos/entity/album.dart';
|
|
import 'package:nc_photos/entity/file.dart';
|
|
import 'package:nc_photos/entity/file_util.dart' as file_util;
|
|
import 'package:nc_photos/entity/share.dart';
|
|
import 'package:nc_photos/remote_storage_util.dart' as remote_storage_util;
|
|
import 'package:nc_photos/use_case/find_file.dart';
|
|
import 'package:nc_photos/use_case/ls.dart';
|
|
import 'package:np_codegen/np_codegen.dart';
|
|
import 'package:path/path.dart' as path_lib;
|
|
|
|
part 'list_sharing.g.dart';
|
|
|
|
abstract class ListSharingData {}
|
|
|
|
class ListSharingFileData implements ListSharingData {
|
|
const ListSharingFileData(this.share, this.file);
|
|
|
|
final Share share;
|
|
final File file;
|
|
}
|
|
|
|
class ListSharingAlbumData implements ListSharingData {
|
|
const ListSharingAlbumData(this.share, this.album);
|
|
|
|
final Share share;
|
|
final Album album;
|
|
}
|
|
|
|
@npLog
|
|
class ListSharing {
|
|
ListSharing(this._c);
|
|
|
|
Stream<List<ListSharingData>> call(Account account) async* {
|
|
final sharedAlbumFiles = await Ls(_c.fileRepo)(
|
|
account,
|
|
File(
|
|
path: remote_storage_util.getRemoteAlbumsDir(account),
|
|
),
|
|
);
|
|
|
|
final controller = StreamController<List<ListSharingData>>();
|
|
var byMe = <ListSharingData>[];
|
|
var isByMeDone = false;
|
|
var withMe = <ListSharingData>[];
|
|
var isWithMeDone = false;
|
|
|
|
void notify() {
|
|
controller.add([
|
|
...byMe,
|
|
...withMe,
|
|
]);
|
|
}
|
|
|
|
void onDone() {
|
|
if (isByMeDone && isWithMeDone) {
|
|
controller.close();
|
|
}
|
|
}
|
|
|
|
unawaited(_querySharesByMe(account, sharedAlbumFiles).then((value) {
|
|
byMe = value;
|
|
notify();
|
|
}).catchError((e, stackTrace) {
|
|
controller.addError(e, stackTrace);
|
|
}).whenComplete(() {
|
|
isByMeDone = true;
|
|
onDone();
|
|
}));
|
|
unawaited(_querySharesWithMe(account, sharedAlbumFiles).then((value) {
|
|
withMe = value;
|
|
notify();
|
|
}).catchError((e, stackTrace) {
|
|
controller.addError(e, stackTrace);
|
|
}).whenComplete(() {
|
|
isWithMeDone = true;
|
|
onDone();
|
|
}));
|
|
yield* controller.stream;
|
|
}
|
|
|
|
Future<List<ListSharingData>> _querySharesByMe(
|
|
Account account, List<File> sharedAlbumFiles) async {
|
|
final shares = await _c.shareRepo.listAll(account);
|
|
final futures = shares.map((s) async {
|
|
final webdavPath = file_util.unstripPath(account, s.path);
|
|
// include link share dirs
|
|
if (s.itemType == ShareItemType.folder) {
|
|
if (webdavPath
|
|
.startsWith(remote_storage_util.getRemoteLinkSharesDir(account))) {
|
|
return ListSharingFileData(
|
|
s,
|
|
File(
|
|
path: webdavPath,
|
|
fileId: s.itemSource,
|
|
isCollection: true,
|
|
),
|
|
);
|
|
}
|
|
}
|
|
// include shared albums
|
|
if (path_lib.dirname(webdavPath) ==
|
|
remote_storage_util.getRemoteAlbumsDir(account)) {
|
|
try {
|
|
final file = sharedAlbumFiles
|
|
.firstWhere((element) => element.fileId == s.itemSource);
|
|
return await _querySharedAlbum(account, s, file);
|
|
} catch (e, stackTrace) {
|
|
_log.severe(
|
|
"[_querySharesWithMe] Shared album not found: ${s.itemSource}",
|
|
e,
|
|
stackTrace);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
if (!file_util.isSupportedMime(s.mimeType)) {
|
|
return null;
|
|
}
|
|
// show only link shares
|
|
if (s.url == null) {
|
|
return null;
|
|
}
|
|
if (account.roots
|
|
.every((r) => r.isNotEmpty && !s.path.startsWith("$r/"))) {
|
|
// ignore files not under root dirs
|
|
return null;
|
|
}
|
|
|
|
try {
|
|
final file = (await FindFile(_c)(account, [s.itemSource])).first;
|
|
return ListSharingFileData(s, file);
|
|
} catch (e, stackTrace) {
|
|
_log.severe("[_querySharesByMe] File not found: ${s.itemSource}", e,
|
|
stackTrace);
|
|
return null;
|
|
}
|
|
});
|
|
return (await Future.wait(futures)).whereNotNull().toList();
|
|
}
|
|
|
|
Future<List<ListSharingData>> _querySharesWithMe(
|
|
Account account, List<File> sharedAlbumFiles) async {
|
|
final pendingSharedAlbumFiles = await Ls(_c.fileRepo)(
|
|
account,
|
|
File(
|
|
path: remote_storage_util.getRemotePendingSharedAlbumsDir(account),
|
|
),
|
|
);
|
|
|
|
final shares = await _c.shareRepo.reverseListAll(account);
|
|
final futures = shares.map((s) async {
|
|
final webdavPath = file_util.unstripPath(account, s.path);
|
|
// include pending shared albums
|
|
if (path_lib.dirname(webdavPath) ==
|
|
remote_storage_util.getRemotePendingSharedAlbumsDir(account)) {
|
|
try {
|
|
final file = pendingSharedAlbumFiles
|
|
.firstWhere((element) => element.fileId == s.itemSource);
|
|
return await _querySharedAlbum(account, s, file);
|
|
} catch (e, stackTrace) {
|
|
_log.severe(
|
|
"[_querySharesWithMe] Pending shared album not found: ${s.itemSource}",
|
|
e,
|
|
stackTrace);
|
|
return null;
|
|
}
|
|
}
|
|
// include shared albums
|
|
if (path_lib.dirname(webdavPath) ==
|
|
remote_storage_util.getRemoteAlbumsDir(account)) {
|
|
try {
|
|
final file = sharedAlbumFiles
|
|
.firstWhere((element) => element.fileId == s.itemSource);
|
|
return await _querySharedAlbum(account, s, file);
|
|
} catch (e, stackTrace) {
|
|
_log.severe(
|
|
"[_querySharesWithMe] Shared album not found: ${s.itemSource}",
|
|
e,
|
|
stackTrace);
|
|
return null;
|
|
}
|
|
}
|
|
});
|
|
return (await Future.wait(futures)).whereNotNull().toList();
|
|
}
|
|
|
|
Future<ListSharingData?> _querySharedAlbum(
|
|
Account account, Share share, File albumFile) async {
|
|
try {
|
|
final album = await _c.albumRepo.get(account, albumFile);
|
|
return ListSharingAlbumData(share, album);
|
|
} catch (e, stackTrace) {
|
|
_log.shout(
|
|
"[_querySharedAlbum] Failed while getting album", e, stackTrace);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
final DiContainer _c;
|
|
}
|