mirror of
https://gitlab.com/nkming2/nc-photos.git
synced 2025-03-14 11:18:54 +01:00
Overhaul how dependencies are injected to clients
This commit is contained in:
parent
9cf061ad8e
commit
2d8738146e
29 changed files with 272 additions and 186 deletions
|
@ -1,7 +1,8 @@
|
||||||
import 'package:bloc/bloc.dart';
|
import 'package:bloc/bloc.dart';
|
||||||
|
import 'package:kiwi/kiwi.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:nc_photos/account.dart';
|
import 'package:nc_photos/account.dart';
|
||||||
import 'package:nc_photos/app_db.dart';
|
import 'package:nc_photos/di_container.dart';
|
||||||
import 'package:nc_photos/entity/album.dart';
|
import 'package:nc_photos/entity/album.dart';
|
||||||
import 'package:nc_photos/entity/file.dart';
|
import 'package:nc_photos/entity/file.dart';
|
||||||
import 'package:nc_photos/entity/file/data_source.dart';
|
import 'package:nc_photos/entity/file/data_source.dart';
|
||||||
|
@ -10,6 +11,7 @@ import 'package:nc_photos/entity/share.dart';
|
||||||
import 'package:nc_photos/event/event.dart';
|
import 'package:nc_photos/event/event.dart';
|
||||||
import 'package:nc_photos/exception.dart';
|
import 'package:nc_photos/exception.dart';
|
||||||
import 'package:nc_photos/exception_event.dart';
|
import 'package:nc_photos/exception_event.dart';
|
||||||
|
import 'package:nc_photos/or_null.dart';
|
||||||
import 'package:nc_photos/remote_storage_util.dart' as remote_storage_util;
|
import 'package:nc_photos/remote_storage_util.dart' as remote_storage_util;
|
||||||
import 'package:nc_photos/throttler.dart';
|
import 'package:nc_photos/throttler.dart';
|
||||||
import 'package:nc_photos/use_case/list_album.dart';
|
import 'package:nc_photos/use_case/list_album.dart';
|
||||||
|
@ -102,7 +104,19 @@ class ListAlbumBlocInconsistent extends ListAlbumBlocState {
|
||||||
}
|
}
|
||||||
|
|
||||||
class ListAlbumBloc extends Bloc<ListAlbumBlocEvent, ListAlbumBlocState> {
|
class ListAlbumBloc extends Bloc<ListAlbumBlocEvent, ListAlbumBlocState> {
|
||||||
ListAlbumBloc() : super(const ListAlbumBlocInit()) {
|
/// Constructor
|
||||||
|
///
|
||||||
|
/// If [offlineC] is not null, this [DiContainer] will be used when requesting
|
||||||
|
/// offline contents, otherwise [_c] will be used
|
||||||
|
ListAlbumBloc(
|
||||||
|
this._c, [
|
||||||
|
DiContainer? offlineC,
|
||||||
|
]) : _offlineC = offlineC ?? _c,
|
||||||
|
assert(require(_c)),
|
||||||
|
assert(offlineC == null || require(offlineC)),
|
||||||
|
assert(ListAlbum.require(_c)),
|
||||||
|
assert(offlineC == null || ListAlbum.require(offlineC)),
|
||||||
|
super(const ListAlbumBlocInit()) {
|
||||||
_albumUpdatedListener =
|
_albumUpdatedListener =
|
||||||
AppEventListener<AlbumUpdatedEvent>(_onAlbumUpdatedEvent);
|
AppEventListener<AlbumUpdatedEvent>(_onAlbumUpdatedEvent);
|
||||||
_fileRemovedListener =
|
_fileRemovedListener =
|
||||||
|
@ -124,6 +138,28 @@ class ListAlbumBloc extends Bloc<ListAlbumBlocEvent, ListAlbumBlocState> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool require(DiContainer c) => true;
|
||||||
|
|
||||||
|
static ListAlbumBloc of(Account account) {
|
||||||
|
final id = "${account.scheme}://${account.username}@${account.address}";
|
||||||
|
try {
|
||||||
|
_log.fine("[of] Resolving bloc for '$id'");
|
||||||
|
return KiwiContainer().resolve<ListAlbumBloc>("ListAlbumBloc($id)");
|
||||||
|
} catch (_) {
|
||||||
|
// no created instance for this account, make a new one
|
||||||
|
_log.info("[of] New bloc instance for account: $account");
|
||||||
|
final c = KiwiContainer().resolve<DiContainer>();
|
||||||
|
final offlineC = c.copyWith(
|
||||||
|
fileRepo: OrNull(FileRepo(FileAppDbDataSource(c.appDb))),
|
||||||
|
albumRepo: OrNull(AlbumRepo(AlbumAppDbDataSource(c.appDb))),
|
||||||
|
);
|
||||||
|
final bloc = ListAlbumBloc(c, offlineC);
|
||||||
|
KiwiContainer()
|
||||||
|
.registerInstance<ListAlbumBloc>(bloc, name: "ListAlbumBloc($id)");
|
||||||
|
return bloc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
mapEventToState(ListAlbumBlocEvent event) async* {
|
mapEventToState(ListAlbumBlocEvent event) async* {
|
||||||
_log.info("[mapEventToState] $event");
|
_log.info("[mapEventToState] $event");
|
||||||
|
@ -249,20 +285,17 @@ class ListAlbumBloc extends Bloc<ListAlbumBlocEvent, ListAlbumBlocState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<ListAlbumBlocState> _queryOffline(ListAlbumBlocQuery ev) =>
|
Future<ListAlbumBlocState> _queryOffline(ListAlbumBlocQuery ev) =>
|
||||||
_queryWithAlbumDataSource(
|
_queryWithAlbumDataSource(_offlineC, ev);
|
||||||
ev, FileAppDbDataSource(AppDb()), AlbumAppDbDataSource(AppDb()));
|
|
||||||
|
|
||||||
Future<ListAlbumBlocState> _queryOnline(ListAlbumBlocQuery ev) =>
|
Future<ListAlbumBlocState> _queryOnline(ListAlbumBlocQuery ev) =>
|
||||||
_queryWithAlbumDataSource(
|
_queryWithAlbumDataSource(_c, ev);
|
||||||
ev, FileCachedDataSource(AppDb()), AlbumCachedDataSource(AppDb()));
|
|
||||||
|
|
||||||
Future<ListAlbumBlocState> _queryWithAlbumDataSource(ListAlbumBlocQuery ev,
|
Future<ListAlbumBlocState> _queryWithAlbumDataSource(
|
||||||
FileDataSource fileDataSource, AlbumDataSource albumDataSrc) async {
|
DiContainer c, ListAlbumBlocQuery ev) async {
|
||||||
try {
|
try {
|
||||||
final albums = <Album>[];
|
final albums = <Album>[];
|
||||||
final errors = <dynamic>[];
|
final errors = <dynamic>[];
|
||||||
await for (final result in ListAlbum(
|
await for (final result in ListAlbum(c)(ev.account)) {
|
||||||
FileRepo(fileDataSource), AlbumRepo(albumDataSrc))(ev.account)) {
|
|
||||||
if (result is ExceptionEvent) {
|
if (result is ExceptionEvent) {
|
||||||
if (result.error is CacheNotFoundException) {
|
if (result.error is CacheNotFoundException) {
|
||||||
_log.info(
|
_log.info(
|
||||||
|
@ -292,6 +325,9 @@ class ListAlbumBloc extends Bloc<ListAlbumBlocEvent, ListAlbumBlocState> {
|
||||||
bool _isAccountOfInterest(Account account) =>
|
bool _isAccountOfInterest(Account account) =>
|
||||||
state.account == null || state.account!.compareServerIdentity(account);
|
state.account == null || state.account!.compareServerIdentity(account);
|
||||||
|
|
||||||
|
final DiContainer _c;
|
||||||
|
final DiContainer _offlineC;
|
||||||
|
|
||||||
late AppEventListener<AlbumUpdatedEvent> _albumUpdatedListener;
|
late AppEventListener<AlbumUpdatedEvent> _albumUpdatedListener;
|
||||||
late AppEventListener<FileRemovedEvent> _fileRemovedListener;
|
late AppEventListener<FileRemovedEvent> _fileRemovedListener;
|
||||||
late AppEventListener<AlbumCreatedEvent> _albumCreatedListener;
|
late AppEventListener<AlbumCreatedEvent> _albumCreatedListener;
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
import 'package:bloc/bloc.dart';
|
import 'package:bloc/bloc.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:nc_photos/account.dart';
|
import 'package:nc_photos/account.dart';
|
||||||
import 'package:nc_photos/app_db.dart';
|
|
||||||
import 'package:nc_photos/debug_util.dart';
|
import 'package:nc_photos/debug_util.dart';
|
||||||
|
import 'package:nc_photos/di_container.dart';
|
||||||
import 'package:nc_photos/entity/album.dart';
|
import 'package:nc_photos/entity/album.dart';
|
||||||
import 'package:nc_photos/entity/album/provider.dart';
|
import 'package:nc_photos/entity/album/provider.dart';
|
||||||
import 'package:nc_photos/entity/file.dart';
|
import 'package:nc_photos/entity/file.dart';
|
||||||
import 'package:nc_photos/entity/file/data_source.dart';
|
|
||||||
import 'package:nc_photos/entity/file_util.dart' as file_util;
|
import 'package:nc_photos/entity/file_util.dart' as file_util;
|
||||||
import 'package:nc_photos/iterable_extension.dart';
|
import 'package:nc_photos/iterable_extension.dart';
|
||||||
import 'package:nc_photos/use_case/list_album.dart';
|
import 'package:nc_photos/use_case/list_album.dart';
|
||||||
|
@ -87,7 +86,12 @@ class ListImportableAlbumBlocFailure extends ListImportableAlbumBlocState {
|
||||||
/// Return all directories that potentially could be a new album
|
/// Return all directories that potentially could be a new album
|
||||||
class ListImportableAlbumBloc
|
class ListImportableAlbumBloc
|
||||||
extends Bloc<ListImportableAlbumBlocEvent, ListImportableAlbumBlocState> {
|
extends Bloc<ListImportableAlbumBlocEvent, ListImportableAlbumBlocState> {
|
||||||
ListImportableAlbumBloc() : super(ListImportableAlbumBlocInit());
|
ListImportableAlbumBloc(this._c)
|
||||||
|
: assert(require(_c)),
|
||||||
|
assert(ListAlbum.require(_c)),
|
||||||
|
super(ListImportableAlbumBlocInit());
|
||||||
|
|
||||||
|
static bool require(DiContainer c) => DiContainer.has(c, DiType.fileRepo);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
mapEventToState(ListImportableAlbumBlocEvent event) async* {
|
mapEventToState(ListImportableAlbumBlocEvent event) async* {
|
||||||
|
@ -101,9 +105,7 @@ class ListImportableAlbumBloc
|
||||||
ListImportableAlbumBlocQuery ev) async* {
|
ListImportableAlbumBlocQuery ev) async* {
|
||||||
yield const ListImportableAlbumBlocLoading([]);
|
yield const ListImportableAlbumBlocLoading([]);
|
||||||
try {
|
try {
|
||||||
final fileRepo = FileRepo(FileCachedDataSource(AppDb()));
|
final albums = (await ListAlbum(_c)(ev.account)
|
||||||
final albumRepo = AlbumRepo(AlbumCachedDataSource(AppDb()));
|
|
||||||
final albums = (await ListAlbum(fileRepo, albumRepo)(ev.account)
|
|
||||||
.where((event) => event is Album)
|
.where((event) => event is Album)
|
||||||
.toList())
|
.toList())
|
||||||
.cast<Album>();
|
.cast<Album>();
|
||||||
|
@ -119,8 +121,7 @@ class ListImportableAlbumBloc
|
||||||
final products = <ListImportableAlbumBlocItem>[];
|
final products = <ListImportableAlbumBlocItem>[];
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (final r in ev.roots) {
|
for (final r in ev.roots) {
|
||||||
await for (final ev
|
await for (final ev in _queryDir(ev.account, importedDirs, r)) {
|
||||||
in _queryDir(fileRepo, ev.account, importedDirs, r)) {
|
|
||||||
if (ev is Exception || ev is Error) {
|
if (ev is Exception || ev is Error) {
|
||||||
throw ev;
|
throw ev;
|
||||||
} else if (ev is ListImportableAlbumBlocItem) {
|
} else if (ev is ListImportableAlbumBlocItem) {
|
||||||
|
@ -142,13 +143,13 @@ class ListImportableAlbumBloc
|
||||||
/// Query [dir] and emit all conforming dirs recursively (including [dir])
|
/// Query [dir] and emit all conforming dirs recursively (including [dir])
|
||||||
///
|
///
|
||||||
/// Emit ListImportableAlbumBlocItem or Exception
|
/// Emit ListImportableAlbumBlocItem or Exception
|
||||||
Stream<dynamic> _queryDir(FileRepo fileRepo, Account account,
|
Stream<dynamic> _queryDir(
|
||||||
List<File> importedDirs, File dir) async* {
|
Account account, List<File> importedDirs, File dir) async* {
|
||||||
try {
|
try {
|
||||||
if (importedDirs.containsIf(dir, (a, b) => a.path == b.path)) {
|
if (importedDirs.containsIf(dir, (a, b) => a.path == b.path)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final files = await Ls(fileRepo)(account, dir);
|
final files = await Ls(_c.fileRepo)(account, dir);
|
||||||
// check number of supported files in this directory
|
// check number of supported files in this directory
|
||||||
final count = files.where((f) => file_util.isSupportedFormat(f)).length;
|
final count = files.where((f) => file_util.isSupportedFormat(f)).length;
|
||||||
// arbitrary number
|
// arbitrary number
|
||||||
|
@ -156,7 +157,7 @@ class ListImportableAlbumBloc
|
||||||
yield ListImportableAlbumBlocItem(dir, count);
|
yield ListImportableAlbumBlocItem(dir, count);
|
||||||
}
|
}
|
||||||
for (final d in files.where((f) => f.isCollection == true)) {
|
for (final d in files.where((f) => f.isCollection == true)) {
|
||||||
yield* _queryDir(fileRepo, account, importedDirs, d);
|
yield* _queryDir(account, importedDirs, d);
|
||||||
}
|
}
|
||||||
} catch (e, stacktrace) {
|
} catch (e, stacktrace) {
|
||||||
_log.shout(
|
_log.shout(
|
||||||
|
@ -167,6 +168,8 @@ class ListImportableAlbumBloc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final DiContainer _c;
|
||||||
|
|
||||||
static final _log =
|
static final _log =
|
||||||
Logger("bloc.list_importable_album.ListImportableAlbumBloc");
|
Logger("bloc.list_importable_album.ListImportableAlbumBloc");
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,13 +2,11 @@ import 'package:bloc/bloc.dart';
|
||||||
import 'package:kiwi/kiwi.dart';
|
import 'package:kiwi/kiwi.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:nc_photos/account.dart';
|
import 'package:nc_photos/account.dart';
|
||||||
import 'package:nc_photos/app_db.dart';
|
import 'package:nc_photos/di_container.dart';
|
||||||
import 'package:nc_photos/entity/album.dart';
|
import 'package:nc_photos/entity/album.dart';
|
||||||
import 'package:nc_photos/entity/file.dart';
|
import 'package:nc_photos/entity/file.dart';
|
||||||
import 'package:nc_photos/entity/file/data_source.dart';
|
|
||||||
import 'package:nc_photos/entity/file_util.dart' as file_util;
|
import 'package:nc_photos/entity/file_util.dart' as file_util;
|
||||||
import 'package:nc_photos/entity/share.dart';
|
import 'package:nc_photos/entity/share.dart';
|
||||||
import 'package:nc_photos/entity/share/data_source.dart';
|
|
||||||
import 'package:nc_photos/event/event.dart';
|
import 'package:nc_photos/event/event.dart';
|
||||||
import 'package:nc_photos/iterable_extension.dart';
|
import 'package:nc_photos/iterable_extension.dart';
|
||||||
import 'package:nc_photos/remote_storage_util.dart' as remote_storage_util;
|
import 'package:nc_photos/remote_storage_util.dart' as remote_storage_util;
|
||||||
|
@ -152,7 +150,12 @@ class ListSharingBlocFailure extends ListSharingBlocState {
|
||||||
|
|
||||||
/// List shares to be shown in [SharingBrowser]
|
/// List shares to be shown in [SharingBrowser]
|
||||||
class ListSharingBloc extends Bloc<ListSharingBlocEvent, ListSharingBlocState> {
|
class ListSharingBloc extends Bloc<ListSharingBlocEvent, ListSharingBlocState> {
|
||||||
ListSharingBloc() : super(ListSharingBlocInit()) {
|
ListSharingBloc(this._c)
|
||||||
|
: assert(require(_c)),
|
||||||
|
assert(FindFile.require(_c)),
|
||||||
|
assert(ListShareWithMe.require(_c)),
|
||||||
|
assert(LsSingleFile.require(_c)),
|
||||||
|
super(ListSharingBlocInit()) {
|
||||||
_shareRemovedListener.begin();
|
_shareRemovedListener.begin();
|
||||||
_fileMovedEventListener.begin();
|
_fileMovedEventListener.begin();
|
||||||
|
|
||||||
|
@ -164,6 +167,11 @@ class ListSharingBloc extends Bloc<ListSharingBlocEvent, ListSharingBlocState> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool require(DiContainer c) =>
|
||||||
|
DiContainer.has(c, DiType.albumRepo) &&
|
||||||
|
DiContainer.has(c, DiType.fileRepo) &&
|
||||||
|
DiContainer.has(c, DiType.shareRepo);
|
||||||
|
|
||||||
static ListSharingBloc of(Account account) {
|
static ListSharingBloc of(Account account) {
|
||||||
final id =
|
final id =
|
||||||
"${account.scheme}://${account.username}@${account.address}?${account.roots.join('&')}";
|
"${account.scheme}://${account.username}@${account.address}?${account.roots.join('&')}";
|
||||||
|
@ -173,7 +181,7 @@ class ListSharingBloc extends Bloc<ListSharingBlocEvent, ListSharingBlocState> {
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
// no created instance for this account, make a new one
|
// no created instance for this account, make a new one
|
||||||
_log.info("[of] New bloc instance for account: $account");
|
_log.info("[of] New bloc instance for account: $account");
|
||||||
final bloc = ListSharingBloc();
|
final bloc = ListSharingBloc(KiwiContainer().resolve<DiContainer>());
|
||||||
KiwiContainer().registerInstance<ListSharingBloc>(bloc,
|
KiwiContainer().registerInstance<ListSharingBloc>(bloc,
|
||||||
name: "ListSharingBloc($id)");
|
name: "ListSharingBloc($id)");
|
||||||
return bloc;
|
return bloc;
|
||||||
|
@ -234,14 +242,10 @@ class ListSharingBloc extends Bloc<ListSharingBlocEvent, ListSharingBlocState> {
|
||||||
final items = List.of(state.items);
|
final items = List.of(state.items);
|
||||||
items.removeWhere(
|
items.removeWhere(
|
||||||
(i) => i is ListSharingAlbum && i.share.path == ev.file.strippedPath);
|
(i) => i is ListSharingAlbum && i.share.path == ev.file.strippedPath);
|
||||||
final fileRepo = FileRepo(FileCachedDataSource(AppDb()));
|
final newShares =
|
||||||
final albumRepo = AlbumRepo(AlbumCachedDataSource(AppDb()));
|
await ListShareWithMe(_c)(ev.account, File(path: ev.destination));
|
||||||
final shareRepo = ShareRepo(ShareRemoteDataSource());
|
final newAlbumFile = await LsSingleFile(_c)(ev.account, ev.destination);
|
||||||
final newShares = await ListShareWithMe(shareRepo)(
|
final newAlbum = await _c.albumRepo.get(ev.account, newAlbumFile);
|
||||||
ev.account, File(path: ev.destination));
|
|
||||||
final newAlbumFile =
|
|
||||||
await LsSingleFile(fileRepo)(ev.account, ev.destination);
|
|
||||||
final newAlbum = await albumRepo.get(ev.account, newAlbumFile);
|
|
||||||
for (final s in newShares) {
|
for (final s in newShares) {
|
||||||
items.add(ListSharingAlbum(s, newAlbum));
|
items.add(ListSharingAlbum(s, newAlbum));
|
||||||
}
|
}
|
||||||
|
@ -282,8 +286,7 @@ class ListSharingBloc extends Bloc<ListSharingBlocEvent, ListSharingBlocState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<ListSharingItem>> _query(ListSharingBlocQuery ev) async {
|
Future<List<ListSharingItem>> _query(ListSharingBlocQuery ev) async {
|
||||||
final fileRepo = FileRepo(FileCachedDataSource(AppDb()));
|
final sharedAlbumFiles = await Ls(_c.fileRepo)(
|
||||||
final sharedAlbumFiles = await Ls(fileRepo)(
|
|
||||||
ev.account,
|
ev.account,
|
||||||
File(
|
File(
|
||||||
path: remote_storage_util.getRemoteAlbumsDir(ev.account),
|
path: remote_storage_util.getRemoteAlbumsDir(ev.account),
|
||||||
|
@ -297,8 +300,7 @@ class ListSharingBloc extends Bloc<ListSharingBlocEvent, ListSharingBlocState> {
|
||||||
|
|
||||||
Future<List<ListSharingItem>> _querySharesByMe(
|
Future<List<ListSharingItem>> _querySharesByMe(
|
||||||
ListSharingBlocQuery ev, List<File> sharedAlbumFiles) async {
|
ListSharingBlocQuery ev, List<File> sharedAlbumFiles) async {
|
||||||
final shareRepo = ShareRepo(ShareRemoteDataSource());
|
final shares = await _c.shareRepo.listAll(ev.account);
|
||||||
final shares = await shareRepo.listAll(ev.account);
|
|
||||||
final futures = shares.map((s) async {
|
final futures = shares.map((s) async {
|
||||||
final webdavPath = file_util.unstripPath(ev.account, s.path);
|
final webdavPath = file_util.unstripPath(ev.account, s.path);
|
||||||
// include link share dirs
|
// include link share dirs
|
||||||
|
@ -344,7 +346,7 @@ class ListSharingBloc extends Bloc<ListSharingBlocEvent, ListSharingBlocState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final file = await FindFile(AppDb())(ev.account, s.itemSource);
|
final file = await FindFile(_c)(ev.account, s.itemSource);
|
||||||
return ListSharingFile(s, file);
|
return ListSharingFile(s, file);
|
||||||
} catch (e, stackTrace) {
|
} catch (e, stackTrace) {
|
||||||
_log.severe("[_querySharesByMe] File not found: ${s.itemSource}", e,
|
_log.severe("[_querySharesByMe] File not found: ${s.itemSource}", e,
|
||||||
|
@ -357,15 +359,13 @@ class ListSharingBloc extends Bloc<ListSharingBlocEvent, ListSharingBlocState> {
|
||||||
|
|
||||||
Future<List<ListSharingItem>> _querySharesWithMe(
|
Future<List<ListSharingItem>> _querySharesWithMe(
|
||||||
ListSharingBlocQuery ev, List<File> sharedAlbumFiles) async {
|
ListSharingBlocQuery ev, List<File> sharedAlbumFiles) async {
|
||||||
final fileRepo = FileRepo(FileCachedDataSource(AppDb()));
|
final pendingSharedAlbumFiles = await Ls(_c.fileRepo)(
|
||||||
final pendingSharedAlbumFiles = await Ls(fileRepo)(
|
|
||||||
ev.account,
|
ev.account,
|
||||||
File(
|
File(
|
||||||
path: remote_storage_util.getRemotePendingSharedAlbumsDir(ev.account),
|
path: remote_storage_util.getRemotePendingSharedAlbumsDir(ev.account),
|
||||||
));
|
));
|
||||||
|
|
||||||
final shareRepo = ShareRepo(ShareRemoteDataSource());
|
final shares = await _c.shareRepo.reverseListAll(ev.account);
|
||||||
final shares = await shareRepo.reverseListAll(ev.account);
|
|
||||||
final futures = shares.map((s) async {
|
final futures = shares.map((s) async {
|
||||||
final webdavPath = file_util.unstripPath(ev.account, s.path);
|
final webdavPath = file_util.unstripPath(ev.account, s.path);
|
||||||
// include pending shared albums
|
// include pending shared albums
|
||||||
|
@ -405,8 +405,7 @@ class ListSharingBloc extends Bloc<ListSharingBlocEvent, ListSharingBlocState> {
|
||||||
Future<ListSharingItem?> _querySharedAlbum(
|
Future<ListSharingItem?> _querySharedAlbum(
|
||||||
ListSharingBlocQuery ev, Share share, File albumFile) async {
|
ListSharingBlocQuery ev, Share share, File albumFile) async {
|
||||||
try {
|
try {
|
||||||
final albumRepo = AlbumRepo(AlbumCachedDataSource(AppDb()));
|
final album = await _c.albumRepo.get(ev.account, albumFile);
|
||||||
final album = await albumRepo.get(ev.account, albumFile);
|
|
||||||
return ListSharingAlbum(share, album);
|
return ListSharingAlbum(share, album);
|
||||||
} catch (e, stackTrace) {
|
} catch (e, stackTrace) {
|
||||||
_log.shout(
|
_log.shout(
|
||||||
|
@ -418,6 +417,8 @@ class ListSharingBloc extends Bloc<ListSharingBlocEvent, ListSharingBlocState> {
|
||||||
bool _isAccountOfInterest(Account account) =>
|
bool _isAccountOfInterest(Account account) =>
|
||||||
state.account == null || state.account!.compareServerIdentity(account);
|
state.account == null || state.account!.compareServerIdentity(account);
|
||||||
|
|
||||||
|
final DiContainer _c;
|
||||||
|
|
||||||
late final _shareRemovedListener =
|
late final _shareRemovedListener =
|
||||||
AppEventListener<ShareRemovedEvent>(_onShareRemovedEvent);
|
AppEventListener<ShareRemovedEvent>(_onShareRemovedEvent);
|
||||||
late final _fileMovedEventListener =
|
late final _fileMovedEventListener =
|
||||||
|
|
|
@ -5,6 +5,7 @@ import 'package:nc_photos/entity/file.dart';
|
||||||
import 'package:nc_photos/entity/person.dart';
|
import 'package:nc_photos/entity/person.dart';
|
||||||
import 'package:nc_photos/entity/share.dart';
|
import 'package:nc_photos/entity/share.dart';
|
||||||
import 'package:nc_photos/entity/sharee.dart';
|
import 'package:nc_photos/entity/sharee.dart';
|
||||||
|
import 'package:nc_photos/or_null.dart';
|
||||||
import 'package:nc_photos/pref.dart';
|
import 'package:nc_photos/pref.dart';
|
||||||
|
|
||||||
enum DiType {
|
enum DiType {
|
||||||
|
@ -58,6 +59,28 @@ class DiContainer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DiContainer copyWith({
|
||||||
|
OrNull<AlbumRepo>? albumRepo,
|
||||||
|
OrNull<FaceRepo>? faceRepo,
|
||||||
|
OrNull<FileRepo>? fileRepo,
|
||||||
|
OrNull<PersonRepo>? personRepo,
|
||||||
|
OrNull<ShareRepo>? shareRepo,
|
||||||
|
OrNull<ShareeRepo>? shareeRepo,
|
||||||
|
OrNull<AppDb>? appDb,
|
||||||
|
OrNull<Pref>? pref,
|
||||||
|
}) {
|
||||||
|
return DiContainer(
|
||||||
|
albumRepo: albumRepo == null ? this.albumRepo : albumRepo.obj,
|
||||||
|
faceRepo: faceRepo == null ? this.faceRepo : faceRepo.obj,
|
||||||
|
fileRepo: fileRepo == null ? this.fileRepo : fileRepo.obj,
|
||||||
|
personRepo: personRepo == null ? this.personRepo : personRepo.obj,
|
||||||
|
shareRepo: shareRepo == null ? this.shareRepo : shareRepo.obj,
|
||||||
|
shareeRepo: shareeRepo == null ? this.shareeRepo : shareeRepo.obj,
|
||||||
|
appDb: appDb == null ? this.appDb : appDb.obj,
|
||||||
|
pref: pref == null ? this.pref : pref.obj,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
AlbumRepo get albumRepo => _albumRepo!;
|
AlbumRepo get albumRepo => _albumRepo!;
|
||||||
FaceRepo get faceRepo => _faceRepo!;
|
FaceRepo get faceRepo => _faceRepo!;
|
||||||
FileRepo get fileRepo => _fileRepo!;
|
FileRepo get fileRepo => _fileRepo!;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:nc_photos/account.dart';
|
import 'package:nc_photos/account.dart';
|
||||||
|
import 'package:nc_photos/di_container.dart';
|
||||||
import 'package:nc_photos/entity/file.dart';
|
import 'package:nc_photos/entity/file.dart';
|
||||||
import 'package:nc_photos/use_case/move.dart';
|
import 'package:nc_photos/use_case/move.dart';
|
||||||
import 'package:path/path.dart' as path;
|
import 'package:path/path.dart' as path;
|
||||||
|
@ -12,12 +13,16 @@ class CompatV25 {
|
||||||
|
|
||||||
/// Migrate an album file to the new naming scheme
|
/// Migrate an album file to the new naming scheme
|
||||||
static Future<File> migrateAlbumFile(
|
static Future<File> migrateAlbumFile(
|
||||||
FileRepo fileRepo, Account account, File albumFile) =>
|
DiContainer c, Account account, File albumFile) =>
|
||||||
_MigrateAlbumFile(fileRepo)(account, albumFile);
|
_MigrateAlbumFile(c)(account, albumFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
class _MigrateAlbumFile {
|
class _MigrateAlbumFile {
|
||||||
_MigrateAlbumFile(this.fileRepo);
|
_MigrateAlbumFile(this._c)
|
||||||
|
: assert(require(_c)),
|
||||||
|
assert(Move.require(_c));
|
||||||
|
|
||||||
|
static bool require(DiContainer c) => true;
|
||||||
|
|
||||||
Future<File> call(Account account, File albumFile) async {
|
Future<File> call(Account account, File albumFile) async {
|
||||||
assert(CompatV25.isAlbumFileNeedMigration(albumFile));
|
assert(CompatV25.isAlbumFileNeedMigration(albumFile));
|
||||||
|
@ -25,12 +30,13 @@ class _MigrateAlbumFile {
|
||||||
"/" +
|
"/" +
|
||||||
path.basenameWithoutExtension(albumFile.path) +
|
path.basenameWithoutExtension(albumFile.path) +
|
||||||
".nc_album.json";
|
".nc_album.json";
|
||||||
_log.info("[call] Migrate album file from '${albumFile.path}' to '$newPath'");
|
_log.info(
|
||||||
await Move(fileRepo)(account, albumFile, newPath);
|
"[call] Migrate album file from '${albumFile.path}' to '$newPath'");
|
||||||
|
await Move(_c)(account, albumFile, newPath);
|
||||||
return albumFile.copyWith(path: newPath);
|
return albumFile.copyWith(path: newPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
final FileRepo fileRepo;
|
final DiContainer _c;
|
||||||
|
|
||||||
static final _log = Logger("use_case.compat.v25._MigrateAlbumFile");
|
static final _log = Logger("use_case.compat.v25._MigrateAlbumFile");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,18 @@
|
||||||
import 'package:idb_shim/idb_client.dart';
|
import 'package:idb_shim/idb_client.dart';
|
||||||
import 'package:nc_photos/account.dart';
|
import 'package:nc_photos/account.dart';
|
||||||
import 'package:nc_photos/app_db.dart';
|
import 'package:nc_photos/app_db.dart';
|
||||||
|
import 'package:nc_photos/di_container.dart';
|
||||||
import 'package:nc_photos/entity/file.dart';
|
import 'package:nc_photos/entity/file.dart';
|
||||||
import 'package:nc_photos/entity/file_util.dart' as file_util;
|
import 'package:nc_photos/entity/file_util.dart' as file_util;
|
||||||
|
|
||||||
class FindFile {
|
class FindFile {
|
||||||
const FindFile(this.appDb);
|
FindFile(this._c) : assert(require(_c));
|
||||||
|
|
||||||
|
static bool require(DiContainer c) => DiContainer.has(c, DiType.appDb);
|
||||||
|
|
||||||
/// Find the [File] in the DB by [fileId]
|
/// Find the [File] in the DB by [fileId]
|
||||||
Future<File> call(Account account, int fileId) async {
|
Future<File> call(Account account, int fileId) async {
|
||||||
return await appDb.use((db) async {
|
return await _c.appDb.use((db) async {
|
||||||
final transaction =
|
final transaction =
|
||||||
db.transaction(AppDb.fileDbStoreName, idbModeReadOnly);
|
db.transaction(AppDb.fileDbStoreName, idbModeReadOnly);
|
||||||
final store = transaction.objectStore(AppDb.fileDbStoreName);
|
final store = transaction.objectStore(AppDb.fileDbStoreName);
|
||||||
|
@ -27,5 +30,5 @@ class FindFile {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
final AppDb appDb;
|
final DiContainer _c;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import 'package:nc_photos/account.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/album.dart';
|
||||||
import 'package:nc_photos/entity/file.dart';
|
import 'package:nc_photos/entity/file.dart';
|
||||||
import 'package:nc_photos/remote_storage_util.dart' as remote_storage_util;
|
import 'package:nc_photos/remote_storage_util.dart' as remote_storage_util;
|
||||||
|
@ -7,22 +8,26 @@ import 'package:nc_photos/use_case/move.dart';
|
||||||
|
|
||||||
/// Import a shared album from the pending dir to the library
|
/// Import a shared album from the pending dir to the library
|
||||||
class ImportPendingSharedAlbum {
|
class ImportPendingSharedAlbum {
|
||||||
const ImportPendingSharedAlbum(this.fileRepo, this.albumRepo);
|
ImportPendingSharedAlbum(this._c)
|
||||||
|
: assert(require(_c)),
|
||||||
|
assert(LsSingleFile.require(_c)),
|
||||||
|
assert(Move.require(_c));
|
||||||
|
|
||||||
|
static bool require(DiContainer c) => DiContainer.has(c, DiType.albumRepo);
|
||||||
|
|
||||||
Future<Album> call(Account account, Album album) async {
|
Future<Album> call(Account account, Album album) async {
|
||||||
final destination =
|
final destination =
|
||||||
"${remote_storage_util.getRemoteAlbumsDir(account)}/${album.albumFile!.filename}";
|
"${remote_storage_util.getRemoteAlbumsDir(account)}/${album.albumFile!.filename}";
|
||||||
await Move(fileRepo)(
|
await Move(_c)(
|
||||||
account,
|
account,
|
||||||
album.albumFile!,
|
album.albumFile!,
|
||||||
destination,
|
destination,
|
||||||
shouldCreateMissingDir: true,
|
shouldCreateMissingDir: true,
|
||||||
);
|
);
|
||||||
final newAlbumFile = await LsSingleFile(fileRepo)(account, destination);
|
final newAlbumFile = await LsSingleFile(_c)(account, destination);
|
||||||
final newAlbum = await albumRepo.get(account, newAlbumFile);
|
final newAlbum = await _c.albumRepo.get(account, newAlbumFile);
|
||||||
return newAlbum;
|
return newAlbum;
|
||||||
}
|
}
|
||||||
|
|
||||||
final FileRepo fileRepo;
|
final DiContainer _c;
|
||||||
final AlbumRepo albumRepo;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:nc_photos/account.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/album.dart';
|
||||||
import 'package:nc_photos/entity/file.dart';
|
import 'package:nc_photos/entity/file.dart';
|
||||||
import 'package:nc_photos/pref.dart';
|
import 'package:nc_photos/pref.dart';
|
||||||
|
@ -9,20 +10,26 @@ import 'package:nc_photos/use_case/move.dart';
|
||||||
|
|
||||||
/// Import new shared albums to the pending dir
|
/// Import new shared albums to the pending dir
|
||||||
class ImportPotentialSharedAlbum {
|
class ImportPotentialSharedAlbum {
|
||||||
ImportPotentialSharedAlbum(this.fileRepo, this.albumRepo);
|
ImportPotentialSharedAlbum(this._c)
|
||||||
|
: assert(require(_c)),
|
||||||
|
assert(Move.require(_c));
|
||||||
|
|
||||||
|
static bool require(DiContainer c) =>
|
||||||
|
DiContainer.has(c, DiType.albumRepo) &&
|
||||||
|
DiContainer.has(c, DiType.fileRepo);
|
||||||
|
|
||||||
Future<List<Album>> call(Account account, AccountPref accountPref) async {
|
Future<List<Album>> call(Account account, AccountPref accountPref) async {
|
||||||
_log.info("[call] $account");
|
_log.info("[call] $account");
|
||||||
final products = <Album>[];
|
final products = <Album>[];
|
||||||
final files =
|
final files =
|
||||||
await ListPotentialSharedAlbum(fileRepo)(account, accountPref);
|
await ListPotentialSharedAlbum(_c.fileRepo)(account, accountPref);
|
||||||
for (final f in files) {
|
for (final f in files) {
|
||||||
// check if the file is actually an album
|
// check if the file is actually an album
|
||||||
try {
|
try {
|
||||||
final album = await albumRepo.get(account, f);
|
final album = await _c.albumRepo.get(account, f);
|
||||||
_log.info("[call] New shared album: ${album.name}, file: ${f.path}");
|
_log.info("[call] New shared album: ${album.name}, file: ${f.path}");
|
||||||
// move this file to the pending dir
|
// move this file to the pending dir
|
||||||
await Move(fileRepo)(
|
await Move(_c)(
|
||||||
account,
|
account,
|
||||||
f,
|
f,
|
||||||
"${remote_storage_util.getRemotePendingSharedAlbumsDir(account)}/${f.filename}",
|
"${remote_storage_util.getRemotePendingSharedAlbumsDir(account)}/${f.filename}",
|
||||||
|
@ -36,8 +43,7 @@ class ImportPotentialSharedAlbum {
|
||||||
return products;
|
return products;
|
||||||
}
|
}
|
||||||
|
|
||||||
final FileRepo fileRepo;
|
final DiContainer _c;
|
||||||
final AlbumRepo albumRepo;
|
|
||||||
|
|
||||||
static final _log = Logger(
|
static final _log = Logger(
|
||||||
"user_case.import_potential_shared_album.ImportPotentialSharedAlbum");
|
"user_case.import_potential_shared_album.ImportPotentialSharedAlbum");
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:nc_photos/account.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/album.dart';
|
||||||
import 'package:nc_photos/entity/file.dart';
|
import 'package:nc_photos/entity/file.dart';
|
||||||
import 'package:nc_photos/exception.dart';
|
import 'package:nc_photos/exception.dart';
|
||||||
|
@ -10,7 +11,11 @@ import 'package:nc_photos/use_case/compat/v25.dart';
|
||||||
import 'package:nc_photos/use_case/ls.dart';
|
import 'package:nc_photos/use_case/ls.dart';
|
||||||
|
|
||||||
class ListAlbum {
|
class ListAlbum {
|
||||||
ListAlbum(this.fileRepo, this.albumRepo);
|
ListAlbum(this._c) : assert(require(_c));
|
||||||
|
|
||||||
|
static bool require(DiContainer c) =>
|
||||||
|
DiContainer.has(c, DiType.albumRepo) &&
|
||||||
|
DiContainer.has(c, DiType.fileRepo);
|
||||||
|
|
||||||
/// List all albums associated with [account]
|
/// List all albums associated with [account]
|
||||||
///
|
///
|
||||||
|
@ -22,7 +27,7 @@ class ListAlbum {
|
||||||
yield result;
|
yield result;
|
||||||
}
|
}
|
||||||
if (!hasAlbum) {
|
if (!hasAlbum) {
|
||||||
if (await CompatV15.migrateAlbumFiles(account, fileRepo)) {
|
if (await CompatV15.migrateAlbumFiles(account, _c.fileRepo)) {
|
||||||
// migrated, try again
|
// migrated, try again
|
||||||
yield* _call(account);
|
yield* _call(account);
|
||||||
}
|
}
|
||||||
|
@ -32,7 +37,7 @@ class ListAlbum {
|
||||||
Stream<dynamic> _call(Account account) async* {
|
Stream<dynamic> _call(Account account) async* {
|
||||||
List<File> ls;
|
List<File> ls;
|
||||||
try {
|
try {
|
||||||
ls = await Ls(fileRepo)(
|
ls = await Ls(_c.fileRepo)(
|
||||||
account,
|
account,
|
||||||
File(
|
File(
|
||||||
path: remote_storage_util.getRemoteAlbumsDir(account),
|
path: remote_storage_util.getRemoteAlbumsDir(account),
|
||||||
|
@ -51,16 +56,16 @@ class ListAlbum {
|
||||||
var f = albumFiles[i];
|
var f = albumFiles[i];
|
||||||
try {
|
try {
|
||||||
if (CompatV25.isAlbumFileNeedMigration(f)) {
|
if (CompatV25.isAlbumFileNeedMigration(f)) {
|
||||||
f = await CompatV25.migrateAlbumFile(fileRepo, account, f);
|
f = await CompatV25.migrateAlbumFile(_c, account, f);
|
||||||
}
|
}
|
||||||
albumFiles[i] = f;
|
albumFiles[i] = f;
|
||||||
yield await albumRepo.get(account, f);
|
yield await _c.albumRepo.get(account, f);
|
||||||
} catch (e, stackTrace) {
|
} catch (e, stackTrace) {
|
||||||
yield ExceptionEvent(e, stackTrace);
|
yield ExceptionEvent(e, stackTrace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
albumRepo.cleanUp(
|
_c.albumRepo.cleanUp(
|
||||||
account, remote_storage_util.getRemoteAlbumsDir(account), albumFiles);
|
account, remote_storage_util.getRemoteAlbumsDir(account), albumFiles);
|
||||||
} catch (e, stacktrace) {
|
} catch (e, stacktrace) {
|
||||||
// not important, log and ignore
|
// not important, log and ignore
|
||||||
|
@ -68,8 +73,7 @@ class ListAlbum {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final FileRepo fileRepo;
|
final DiContainer _c;
|
||||||
final AlbumRepo albumRepo;
|
|
||||||
|
|
||||||
static final _log = Logger("use_case.list_album.ListAlbum");
|
static final _log = Logger("use_case.list_album.ListAlbum");
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,10 +9,11 @@ import 'package:nc_photos/use_case/find_file.dart';
|
||||||
|
|
||||||
/// List all shares from a given file
|
/// List all shares from a given file
|
||||||
class ListShare {
|
class ListShare {
|
||||||
ListShare(this._c) : assert(require(_c));
|
ListShare(this._c)
|
||||||
|
: assert(require(_c)),
|
||||||
|
assert(FindFile.require(_c));
|
||||||
|
|
||||||
static bool require(DiContainer c) =>
|
static bool require(DiContainer c) => DiContainer.has(c, DiType.shareRepo);
|
||||||
DiContainer.has(c, DiType.shareRepo) && DiContainer.has(c, DiType.appDb);
|
|
||||||
|
|
||||||
Future<List<Share>> call(
|
Future<List<Share>> call(
|
||||||
Account account,
|
Account account,
|
||||||
|
@ -21,7 +22,7 @@ class ListShare {
|
||||||
}) async {
|
}) async {
|
||||||
try {
|
try {
|
||||||
if (file_util.getUserDirName(file) != account.username) {
|
if (file_util.getUserDirName(file) != account.username) {
|
||||||
file = await FindFile(_c.appDb)(account, file.fileId!);
|
file = await FindFile(_c)(account, file.fileId!);
|
||||||
}
|
}
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
// file not found
|
// file not found
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
import 'package:nc_photos/account.dart';
|
import 'package:nc_photos/account.dart';
|
||||||
|
import 'package:nc_photos/di_container.dart';
|
||||||
import 'package:nc_photos/entity/file.dart';
|
import 'package:nc_photos/entity/file.dart';
|
||||||
import 'package:nc_photos/entity/share.dart';
|
import 'package:nc_photos/entity/share.dart';
|
||||||
|
|
||||||
/// List all shares by other users from a given file
|
/// List all shares by other users from a given file
|
||||||
class ListShareWithMe {
|
class ListShareWithMe {
|
||||||
ListShareWithMe(this.shareRepo);
|
ListShareWithMe(this._c) : assert(require(_c));
|
||||||
|
|
||||||
|
static bool require(DiContainer c) => DiContainer.has(c, DiType.shareRepo);
|
||||||
|
|
||||||
Future<List<Share>> call(Account account, File file) =>
|
Future<List<Share>> call(Account account, File file) =>
|
||||||
shareRepo.reverseList(account, file);
|
_c.shareRepo.reverseList(account, file);
|
||||||
|
|
||||||
final ShareRepo shareRepo;
|
final DiContainer _c;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
import 'package:nc_photos/account.dart';
|
import 'package:nc_photos/account.dart';
|
||||||
|
import 'package:nc_photos/di_container.dart';
|
||||||
import 'package:nc_photos/entity/file.dart';
|
import 'package:nc_photos/entity/file.dart';
|
||||||
|
|
||||||
class LsSingleFile {
|
class LsSingleFile {
|
||||||
LsSingleFile(this.fileRepo);
|
LsSingleFile(this._c) : assert(require(_c));
|
||||||
|
|
||||||
|
static bool require(DiContainer c) => DiContainer.has(c, DiType.fileRepo);
|
||||||
|
|
||||||
Future<File> call(Account account, String path) =>
|
Future<File> call(Account account, String path) =>
|
||||||
fileRepo.listSingle(account, File(path: path));
|
_c.fileRepo.listSingle(account, File(path: path));
|
||||||
|
|
||||||
final FileRepo fileRepo;
|
final DiContainer _c;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ import 'package:event_bus/event_bus.dart';
|
||||||
import 'package:kiwi/kiwi.dart';
|
import 'package:kiwi/kiwi.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:nc_photos/account.dart';
|
import 'package:nc_photos/account.dart';
|
||||||
|
import 'package:nc_photos/di_container.dart';
|
||||||
import 'package:nc_photos/entity/file.dart';
|
import 'package:nc_photos/entity/file.dart';
|
||||||
import 'package:nc_photos/entity/file_util.dart' as file_util;
|
import 'package:nc_photos/entity/file_util.dart' as file_util;
|
||||||
import 'package:nc_photos/event/event.dart';
|
import 'package:nc_photos/event/event.dart';
|
||||||
|
@ -10,7 +11,9 @@ import 'package:nc_photos/use_case/create_dir.dart';
|
||||||
import 'package:path/path.dart' as path;
|
import 'package:path/path.dart' as path;
|
||||||
|
|
||||||
class Move {
|
class Move {
|
||||||
Move(this.fileRepo);
|
Move(this._c) : assert(require(_c));
|
||||||
|
|
||||||
|
static bool require(DiContainer c) => DiContainer.has(c, DiType.fileRepo);
|
||||||
|
|
||||||
/// Move a file from its original location to [destination]
|
/// Move a file from its original location to [destination]
|
||||||
Future<void> call(
|
Future<void> call(
|
||||||
|
@ -44,15 +47,16 @@ class Move {
|
||||||
_log.info("[call] Retry with: '$to'");
|
_log.info("[call] Retry with: '$to'");
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
await fileRepo.move(account, file, to, shouldOverwrite: shouldOverwrite);
|
await _c.fileRepo
|
||||||
|
.move(account, file, to, shouldOverwrite: shouldOverwrite);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e is ApiException) {
|
if (e is ApiException) {
|
||||||
if (e.response.statusCode == 409 && shouldCreateMissingDir) {
|
if (e.response.statusCode == 409 && shouldCreateMissingDir) {
|
||||||
// no dir
|
// no dir
|
||||||
_log.info("[call] Auto creating parent dirs");
|
_log.info("[call] Auto creating parent dirs");
|
||||||
await CreateDir(fileRepo)(account, path.dirname(to));
|
await CreateDir(_c.fileRepo)(account, path.dirname(to));
|
||||||
await fileRepo.move(account, file, to,
|
await _c.fileRepo
|
||||||
shouldOverwrite: shouldOverwrite);
|
.move(account, file, to, shouldOverwrite: shouldOverwrite);
|
||||||
} else if (e.response.statusCode == 412 && shouldRenameOnOverwrite) {
|
} else if (e.response.statusCode == 412 && shouldRenameOnOverwrite) {
|
||||||
return _doWork(
|
return _doWork(
|
||||||
account,
|
account,
|
||||||
|
@ -84,7 +88,7 @@ class Move {
|
||||||
return "${path.dirname(destination)}/$newName";
|
return "${path.dirname(destination)}/$newName";
|
||||||
}
|
}
|
||||||
|
|
||||||
final FileRepo fileRepo;
|
final DiContainer _c;
|
||||||
|
|
||||||
static final _log = Logger("use_case.move.Move");
|
static final _log = Logger("use_case.move.Move");
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,14 +19,13 @@ import 'package:nc_photos/use_case/remove_share.dart';
|
||||||
class Remove {
|
class Remove {
|
||||||
Remove(this._c)
|
Remove(this._c)
|
||||||
: assert(require(_c)),
|
: assert(require(_c)),
|
||||||
|
assert(ListAlbum.require(_c)),
|
||||||
assert(ListShare.require(_c)),
|
assert(ListShare.require(_c)),
|
||||||
assert(RemoveFromAlbum.require(_c));
|
assert(RemoveFromAlbum.require(_c));
|
||||||
|
|
||||||
static bool require(DiContainer c) =>
|
static bool require(DiContainer c) =>
|
||||||
DiContainer.has(c, DiType.albumRepo) &&
|
|
||||||
DiContainer.has(c, DiType.fileRepo) &&
|
DiContainer.has(c, DiType.fileRepo) &&
|
||||||
DiContainer.has(c, DiType.shareRepo) &&
|
DiContainer.has(c, DiType.shareRepo);
|
||||||
DiContainer.has(c, DiType.appDb);
|
|
||||||
|
|
||||||
/// Remove files
|
/// Remove files
|
||||||
Future<void> call(
|
Future<void> call(
|
||||||
|
@ -55,7 +54,7 @@ class Remove {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _cleanUpAlbums(Account account, List<File> removes) async {
|
Future<void> _cleanUpAlbums(Account account, List<File> removes) async {
|
||||||
final albums = await ListAlbum(_c.fileRepo, _c.albumRepo)(account)
|
final albums = await ListAlbum(_c)(account)
|
||||||
.where((event) => event is Album)
|
.where((event) => event is Album)
|
||||||
.cast<Album>()
|
.cast<Album>()
|
||||||
.toList();
|
.toList();
|
||||||
|
|
|
@ -1,15 +1,20 @@
|
||||||
import 'package:event_bus/event_bus.dart';
|
import 'package:event_bus/event_bus.dart';
|
||||||
import 'package:kiwi/kiwi.dart';
|
import 'package:kiwi/kiwi.dart';
|
||||||
import 'package:nc_photos/account.dart';
|
import 'package:nc_photos/account.dart';
|
||||||
|
import 'package:nc_photos/di_container.dart';
|
||||||
import 'package:nc_photos/entity/file.dart';
|
import 'package:nc_photos/entity/file.dart';
|
||||||
import 'package:nc_photos/event/event.dart';
|
import 'package:nc_photos/event/event.dart';
|
||||||
import 'package:nc_photos/use_case/move.dart';
|
import 'package:nc_photos/use_case/move.dart';
|
||||||
|
|
||||||
class RestoreTrashbin {
|
class RestoreTrashbin {
|
||||||
RestoreTrashbin(this.fileRepo);
|
RestoreTrashbin(this._c)
|
||||||
|
: assert(require(_c)),
|
||||||
|
assert(Move.require(_c));
|
||||||
|
|
||||||
|
static bool require(DiContainer c) => true;
|
||||||
|
|
||||||
Future<void> call(Account account, File file) async {
|
Future<void> call(Account account, File file) async {
|
||||||
await Move(fileRepo)(
|
await Move(_c)(
|
||||||
account,
|
account,
|
||||||
file,
|
file,
|
||||||
"remote.php/dav/trashbin/${account.username}/restore/${file.filename}",
|
"remote.php/dav/trashbin/${account.username}/restore/${file.filename}",
|
||||||
|
@ -20,5 +25,5 @@ class RestoreTrashbin {
|
||||||
.fire(FileTrashbinRestoredEvent(account, file));
|
.fire(FileTrashbinRestoredEvent(account, file));
|
||||||
}
|
}
|
||||||
|
|
||||||
final FileRepo fileRepo;
|
final DiContainer _c;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import 'package:nc_photos/account.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/album.dart';
|
||||||
import 'package:nc_photos/entity/file.dart';
|
import 'package:nc_photos/entity/file.dart';
|
||||||
import 'package:nc_photos/remote_storage_util.dart' as remote_storage_util;
|
import 'package:nc_photos/remote_storage_util.dart' as remote_storage_util;
|
||||||
|
@ -6,12 +7,16 @@ import 'package:nc_photos/use_case/move.dart';
|
||||||
|
|
||||||
/// Unimport a shared album from the library
|
/// Unimport a shared album from the library
|
||||||
class UnimportSharedAlbum {
|
class UnimportSharedAlbum {
|
||||||
const UnimportSharedAlbum(this.fileRepo);
|
UnimportSharedAlbum(this._c)
|
||||||
|
: assert(require(_c)),
|
||||||
|
assert(Move.require(_c));
|
||||||
|
|
||||||
|
static bool require(DiContainer c) => true;
|
||||||
|
|
||||||
Future<void> call(Account account, Album album) async {
|
Future<void> call(Account account, Album album) async {
|
||||||
final destination =
|
final destination =
|
||||||
"${remote_storage_util.getRemotePendingSharedAlbumsDir(account)}/${album.albumFile!.filename}";
|
"${remote_storage_util.getRemotePendingSharedAlbumsDir(account)}/${album.albumFile!.filename}";
|
||||||
await Move(fileRepo)(
|
await Move(_c)(
|
||||||
account,
|
account,
|
||||||
album.albumFile!,
|
album.albumFile!,
|
||||||
destination,
|
destination,
|
||||||
|
@ -19,5 +24,5 @@ class UnimportSharedAlbum {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final FileRepo fileRepo;
|
final DiContainer _c;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,12 +15,10 @@ import 'package:nc_photos/use_case/remove_share.dart';
|
||||||
class UnshareFileFromAlbum {
|
class UnshareFileFromAlbum {
|
||||||
UnshareFileFromAlbum(this._c)
|
UnshareFileFromAlbum(this._c)
|
||||||
: assert(require(_c)),
|
: assert(require(_c)),
|
||||||
|
assert(ListAlbum.require(_c)),
|
||||||
assert(ListShare.require(_c));
|
assert(ListShare.require(_c));
|
||||||
|
|
||||||
static bool require(DiContainer c) =>
|
static bool require(DiContainer c) => DiContainer.has(c, DiType.shareRepo);
|
||||||
DiContainer.has(c, DiType.albumRepo) &&
|
|
||||||
DiContainer.has(c, DiType.fileRepo) &&
|
|
||||||
DiContainer.has(c, DiType.shareRepo);
|
|
||||||
|
|
||||||
/// Remove file shares created for an album
|
/// Remove file shares created for an album
|
||||||
///
|
///
|
||||||
|
@ -36,7 +34,7 @@ class UnshareFileFromAlbum {
|
||||||
_log.info(
|
_log.info(
|
||||||
"[call] Unshare ${files.length} files from album '${album.name}' with ${unshareWith.length} users");
|
"[call] Unshare ${files.length} files from album '${album.name}' with ${unshareWith.length} users");
|
||||||
// list albums with shares identical to any element in [unshareWith]
|
// list albums with shares identical to any element in [unshareWith]
|
||||||
final otherAlbums = await ListAlbum(_c.fileRepo, _c.albumRepo)(account)
|
final otherAlbums = await ListAlbum(_c)(account)
|
||||||
.where((event) => event is Album)
|
.where((event) => event is Album)
|
||||||
.cast<Album>()
|
.cast<Album>()
|
||||||
.where((a) =>
|
.where((a) =>
|
||||||
|
|
|
@ -15,7 +15,6 @@ import 'package:nc_photos/entity/album/item.dart';
|
||||||
import 'package:nc_photos/entity/album/provider.dart';
|
import 'package:nc_photos/entity/album/provider.dart';
|
||||||
import 'package:nc_photos/entity/album/sort_provider.dart';
|
import 'package:nc_photos/entity/album/sort_provider.dart';
|
||||||
import 'package:nc_photos/entity/file.dart';
|
import 'package:nc_photos/entity/file.dart';
|
||||||
import 'package:nc_photos/entity/file/data_source.dart';
|
|
||||||
import 'package:nc_photos/entity/file_util.dart' as file_util;
|
import 'package:nc_photos/entity/file_util.dart' as file_util;
|
||||||
import 'package:nc_photos/event/event.dart';
|
import 'package:nc_photos/event/event.dart';
|
||||||
import 'package:nc_photos/exception_util.dart' as exception_util;
|
import 'package:nc_photos/exception_util.dart' as exception_util;
|
||||||
|
@ -185,9 +184,8 @@ class _AlbumBrowserState extends State<AlbumBrowser>
|
||||||
var album = await albumRepo.get(widget.account, widget.album.albumFile!);
|
var album = await albumRepo.get(widget.account, widget.album.albumFile!);
|
||||||
if (widget.album.shares?.isNotEmpty == true) {
|
if (widget.album.shares?.isNotEmpty == true) {
|
||||||
try {
|
try {
|
||||||
final fileRepo = FileRepo(FileCachedDataSource(AppDb()));
|
final file = await LsSingleFile(KiwiContainer().resolve<DiContainer>())(
|
||||||
final file =
|
widget.account, album.albumFile!.path);
|
||||||
await LsSingleFile(fileRepo)(widget.account, album.albumFile!.path);
|
|
||||||
if (file.etag != album.albumFile!.etag) {
|
if (file.etag != album.albumFile!.etag) {
|
||||||
_log.info("[_initAlbum] Album modified in remote, forcing download");
|
_log.info("[_initAlbum] Album modified in remote, forcing download");
|
||||||
album = await albumRepo.get(widget.account, File(path: file.path));
|
album = await albumRepo.get(widget.account, File(path: file.path));
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
|
import 'package:kiwi/kiwi.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:nc_photos/account.dart';
|
import 'package:nc_photos/account.dart';
|
||||||
import 'package:nc_photos/api/api_util.dart' as api_util;
|
import 'package:nc_photos/api/api_util.dart' as api_util;
|
||||||
import 'package:nc_photos/app_db.dart';
|
import 'package:nc_photos/app_db.dart';
|
||||||
import 'package:nc_photos/app_localizations.dart';
|
import 'package:nc_photos/app_localizations.dart';
|
||||||
import 'package:nc_photos/debug_util.dart';
|
import 'package:nc_photos/debug_util.dart';
|
||||||
|
import 'package:nc_photos/di_container.dart';
|
||||||
import 'package:nc_photos/entity/album.dart';
|
import 'package:nc_photos/entity/album.dart';
|
||||||
import 'package:nc_photos/entity/album/cover_provider.dart';
|
import 'package:nc_photos/entity/album/cover_provider.dart';
|
||||||
import 'package:nc_photos/entity/file.dart';
|
|
||||||
import 'package:nc_photos/entity/file/data_source.dart';
|
|
||||||
import 'package:nc_photos/k.dart' as k;
|
import 'package:nc_photos/k.dart' as k;
|
||||||
import 'package:nc_photos/notified_action.dart';
|
import 'package:nc_photos/notified_action.dart';
|
||||||
import 'package:nc_photos/pref.dart';
|
import 'package:nc_photos/pref.dart';
|
||||||
|
@ -236,10 +236,8 @@ mixin AlbumBrowserMixin<T extends StatefulWidget>
|
||||||
try {
|
try {
|
||||||
await NotifiedAction(
|
await NotifiedAction(
|
||||||
() async {
|
() async {
|
||||||
final fileRepo = FileRepo(FileCachedDataSource(AppDb()));
|
newAlbum = await ImportPendingSharedAlbum(
|
||||||
final albumRepo = AlbumRepo(AlbumCachedDataSource(AppDb()));
|
KiwiContainer().resolve<DiContainer>())(account, album);
|
||||||
newAlbum = await ImportPendingSharedAlbum(fileRepo, albumRepo)(
|
|
||||||
account, album);
|
|
||||||
},
|
},
|
||||||
L10n.global().addToCollectionProcessingNotification(album.name),
|
L10n.global().addToCollectionProcessingNotification(album.name),
|
||||||
L10n.global().addToCollectionSuccessNotification(album.name),
|
L10n.global().addToCollectionSuccessNotification(album.name),
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:kiwi/kiwi.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:nc_photos/account.dart';
|
import 'package:nc_photos/account.dart';
|
||||||
import 'package:nc_photos/app_db.dart';
|
import 'package:nc_photos/app_db.dart';
|
||||||
import 'package:nc_photos/app_localizations.dart';
|
import 'package:nc_photos/app_localizations.dart';
|
||||||
import 'package:nc_photos/bloc/list_importable_album.dart';
|
import 'package:nc_photos/bloc/list_importable_album.dart';
|
||||||
|
import 'package:nc_photos/di_container.dart';
|
||||||
import 'package:nc_photos/entity/album.dart';
|
import 'package:nc_photos/entity/album.dart';
|
||||||
import 'package:nc_photos/entity/album/cover_provider.dart';
|
import 'package:nc_photos/entity/album/cover_provider.dart';
|
||||||
import 'package:nc_photos/entity/album/provider.dart';
|
import 'package:nc_photos/entity/album/provider.dart';
|
||||||
|
@ -79,7 +81,7 @@ class _AlbumImporterState extends State<AlbumImporter> {
|
||||||
|
|
||||||
void _initBloc() {
|
void _initBloc() {
|
||||||
_log.info("[_initBloc] Initialize bloc");
|
_log.info("[_initBloc] Initialize bloc");
|
||||||
_bloc = ListImportableAlbumBloc();
|
_bloc = ListImportableAlbumBloc(KiwiContainer().resolve<DiContainer>());
|
||||||
_bloc.add(ListImportableAlbumBlocQuery(
|
_bloc.add(ListImportableAlbumBlocQuery(
|
||||||
widget.account,
|
widget.account,
|
||||||
widget.account.roots
|
widget.account.roots
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:kiwi/kiwi.dart';
|
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:nc_photos/account.dart';
|
import 'package:nc_photos/account.dart';
|
||||||
import 'package:nc_photos/app_localizations.dart';
|
import 'package:nc_photos/app_localizations.dart';
|
||||||
|
@ -48,21 +47,6 @@ class _AlbumPickerDialogState extends State<AlbumPickerDialog> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void _initBloc() {
|
void _initBloc() {
|
||||||
ListAlbumBloc bloc;
|
|
||||||
final blocId =
|
|
||||||
"${widget.account.scheme}://${widget.account.username}@${widget.account.address}";
|
|
||||||
try {
|
|
||||||
_log.fine("[_initBloc] Resolving bloc for '$blocId'");
|
|
||||||
bloc = KiwiContainer().resolve<ListAlbumBloc>("ListAlbumBloc($blocId)");
|
|
||||||
} catch (_) {
|
|
||||||
// no created instance for this account, make a new one
|
|
||||||
_log.info("[_initBloc] New bloc instance for account: ${widget.account}");
|
|
||||||
bloc = ListAlbumBloc();
|
|
||||||
KiwiContainer().registerInstance<ListAlbumBloc>(bloc,
|
|
||||||
name: "ListAlbumBloc($blocId)");
|
|
||||||
}
|
|
||||||
|
|
||||||
_bloc = bloc;
|
|
||||||
if (_bloc.state is ListAlbumBlocInit) {
|
if (_bloc.state is ListAlbumBlocInit) {
|
||||||
_log.info("[_initBloc] Initialize bloc");
|
_log.info("[_initBloc] Initialize bloc");
|
||||||
_reqQuery();
|
_reqQuery();
|
||||||
|
@ -171,7 +155,7 @@ class _AlbumPickerDialogState extends State<AlbumPickerDialog> {
|
||||||
_bloc.add(ListAlbumBlocQuery(widget.account));
|
_bloc.add(ListAlbumBlocQuery(widget.account));
|
||||||
}
|
}
|
||||||
|
|
||||||
late ListAlbumBloc _bloc;
|
late final _bloc = ListAlbumBloc.of(widget.account);
|
||||||
|
|
||||||
final _items = <Album>[];
|
final _items = <Album>[];
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
|
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
|
||||||
|
import 'package:kiwi/kiwi.dart';
|
||||||
import 'package:nc_photos/account.dart';
|
import 'package:nc_photos/account.dart';
|
||||||
import 'package:nc_photos/app_db.dart';
|
|
||||||
import 'package:nc_photos/app_localizations.dart';
|
import 'package:nc_photos/app_localizations.dart';
|
||||||
import 'package:nc_photos/bloc/album_search.dart';
|
import 'package:nc_photos/bloc/album_search.dart';
|
||||||
import 'package:nc_photos/bloc/search_suggestion.dart';
|
import 'package:nc_photos/bloc/search_suggestion.dart';
|
||||||
import 'package:nc_photos/ci_string.dart';
|
import 'package:nc_photos/ci_string.dart';
|
||||||
|
import 'package:nc_photos/di_container.dart';
|
||||||
import 'package:nc_photos/entity/album.dart';
|
import 'package:nc_photos/entity/album.dart';
|
||||||
import 'package:nc_photos/entity/file.dart';
|
|
||||||
import 'package:nc_photos/entity/file/data_source.dart';
|
|
||||||
import 'package:nc_photos/theme.dart';
|
import 'package:nc_photos/theme.dart';
|
||||||
import 'package:nc_photos/use_case/list_album.dart';
|
import 'package:nc_photos/use_case/list_album.dart';
|
||||||
import 'package:nc_photos/widget/builder/album_grid_item_builder.dart';
|
import 'package:nc_photos/widget/builder/album_grid_item_builder.dart';
|
||||||
|
@ -22,9 +21,9 @@ class AlbumSearchDelegate extends SearchDelegate {
|
||||||
: super(
|
: super(
|
||||||
searchFieldLabel: L10n.global().albumSearchTextFieldHint,
|
searchFieldLabel: L10n.global().albumSearchTextFieldHint,
|
||||||
) {
|
) {
|
||||||
final fileRepo = FileRepo(FileCachedDataSource(AppDb()));
|
ListAlbum(KiwiContainer().resolve<DiContainer>())(account)
|
||||||
final albumRepo = AlbumRepo(AlbumCachedDataSource(AppDb()));
|
.toList()
|
||||||
ListAlbum(fileRepo, albumRepo)(account).toList().then((value) {
|
.then((value) {
|
||||||
final albums = value.whereType<Album>().toList();
|
final albums = value.whereType<Album>().toList();
|
||||||
_searchBloc.add(AlbumSearchBlocUpdateItemsEvent(albums));
|
_searchBloc.add(AlbumSearchBlocUpdateItemsEvent(albums));
|
||||||
_suggestionBloc.add(SearchSuggestionBlocUpdateItemsEvent<Album>(albums));
|
_suggestionBloc.add(SearchSuggestionBlocUpdateItemsEvent<Album>(albums));
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
|
import 'package:kiwi/kiwi.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:nc_photos/account.dart';
|
import 'package:nc_photos/account.dart';
|
||||||
import 'package:nc_photos/app_localizations.dart';
|
import 'package:nc_photos/app_localizations.dart';
|
||||||
|
import 'package:nc_photos/di_container.dart';
|
||||||
import 'package:nc_photos/entity/album.dart';
|
import 'package:nc_photos/entity/album.dart';
|
||||||
import 'package:nc_photos/entity/file.dart';
|
import 'package:nc_photos/entity/file.dart';
|
||||||
import 'package:nc_photos/entity/file/data_source.dart';
|
import 'package:nc_photos/entity/file/data_source.dart';
|
||||||
import 'package:nc_photos/k.dart' as k;
|
import 'package:nc_photos/k.dart' as k;
|
||||||
|
import 'package:nc_photos/or_null.dart';
|
||||||
import 'package:nc_photos/pref.dart';
|
import 'package:nc_photos/pref.dart';
|
||||||
import 'package:nc_photos/theme.dart';
|
import 'package:nc_photos/theme.dart';
|
||||||
import 'package:nc_photos/use_case/import_potential_shared_album.dart';
|
import 'package:nc_photos/use_case/import_potential_shared_album.dart';
|
||||||
|
@ -126,11 +129,13 @@ class _HomeState extends State<Home> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<Album>> _importPotentialSharedAlbum() async {
|
Future<List<Album>> _importPotentialSharedAlbum() async {
|
||||||
const fileRepo = FileRepo(FileWebdavDataSource());
|
final c = KiwiContainer().resolve<DiContainer>().copyWith(
|
||||||
// don't want the potential albums to be cached at this moment
|
// don't want the potential albums to be cached at this moment
|
||||||
final albumRepo = AlbumRepo(AlbumRemoteDataSource());
|
fileRepo: OrNull(const FileRepo(FileWebdavDataSource())),
|
||||||
|
albumRepo: OrNull(AlbumRepo(AlbumRemoteDataSource())),
|
||||||
|
);
|
||||||
try {
|
try {
|
||||||
return await ImportPotentialSharedAlbum(fileRepo, albumRepo)(
|
return await ImportPotentialSharedAlbum(c)(
|
||||||
widget.account, AccountPref.of(widget.account));
|
widget.account, AccountPref.of(widget.account));
|
||||||
} catch (e, stacktrace) {
|
} catch (e, stacktrace) {
|
||||||
_log.shout(
|
_log.shout(
|
||||||
|
|
|
@ -6,14 +6,12 @@ import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
|
||||||
import 'package:kiwi/kiwi.dart';
|
import 'package:kiwi/kiwi.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:nc_photos/account.dart';
|
import 'package:nc_photos/account.dart';
|
||||||
import 'package:nc_photos/app_db.dart';
|
|
||||||
import 'package:nc_photos/app_localizations.dart';
|
import 'package:nc_photos/app_localizations.dart';
|
||||||
import 'package:nc_photos/bloc/list_album.dart';
|
import 'package:nc_photos/bloc/list_album.dart';
|
||||||
import 'package:nc_photos/di_container.dart';
|
import 'package:nc_photos/di_container.dart';
|
||||||
import 'package:nc_photos/entity/album.dart';
|
import 'package:nc_photos/entity/album.dart';
|
||||||
import 'package:nc_photos/entity/album/provider.dart';
|
import 'package:nc_photos/entity/album/provider.dart';
|
||||||
import 'package:nc_photos/entity/file.dart';
|
import 'package:nc_photos/entity/file.dart';
|
||||||
import 'package:nc_photos/entity/file/data_source.dart';
|
|
||||||
import 'package:nc_photos/event/event.dart';
|
import 'package:nc_photos/event/event.dart';
|
||||||
import 'package:nc_photos/exception_util.dart' as exception_util;
|
import 'package:nc_photos/exception_util.dart' as exception_util;
|
||||||
import 'package:nc_photos/iterable_extension.dart';
|
import 'package:nc_photos/iterable_extension.dart';
|
||||||
|
@ -83,21 +81,6 @@ class _HomeAlbumsState extends State<HomeAlbums>
|
||||||
}
|
}
|
||||||
|
|
||||||
void _initBloc() {
|
void _initBloc() {
|
||||||
ListAlbumBloc bloc;
|
|
||||||
final blocId =
|
|
||||||
"${widget.account.scheme}://${widget.account.username}@${widget.account.address}";
|
|
||||||
try {
|
|
||||||
_log.fine("[_initBloc] Resolving bloc for '$blocId'");
|
|
||||||
bloc = KiwiContainer().resolve<ListAlbumBloc>("ListAlbumBloc($blocId)");
|
|
||||||
} catch (e) {
|
|
||||||
// no created instance for this account, make a new one
|
|
||||||
_log.info("[_initBloc] New bloc instance for account: ${widget.account}");
|
|
||||||
bloc = ListAlbumBloc();
|
|
||||||
KiwiContainer().registerInstance<ListAlbumBloc>(bloc,
|
|
||||||
name: "ListAlbumBloc($blocId)");
|
|
||||||
}
|
|
||||||
|
|
||||||
_bloc = bloc;
|
|
||||||
if (_bloc.state is ListAlbumBlocInit) {
|
if (_bloc.state is ListAlbumBlocInit) {
|
||||||
_log.info("[_initBloc] Initialize bloc");
|
_log.info("[_initBloc] Initialize bloc");
|
||||||
_reqQuery();
|
_reqQuery();
|
||||||
|
@ -406,7 +389,6 @@ class _HomeAlbumsState extends State<HomeAlbums>
|
||||||
setState(() {
|
setState(() {
|
||||||
clearSelectedItems();
|
clearSelectedItems();
|
||||||
});
|
});
|
||||||
final fileRepo = FileRepo(FileCachedDataSource(AppDb()));
|
|
||||||
final failures = <Album>[];
|
final failures = <Album>[];
|
||||||
for (final a in selected) {
|
for (final a in selected) {
|
||||||
try {
|
try {
|
||||||
|
@ -416,7 +398,8 @@ class _HomeAlbumsState extends State<HomeAlbums>
|
||||||
widget.account, a);
|
widget.account, a);
|
||||||
} else {
|
} else {
|
||||||
// remove shared albums from collection
|
// remove shared albums from collection
|
||||||
await UnimportSharedAlbum(fileRepo)(widget.account, a);
|
await UnimportSharedAlbum(KiwiContainer().resolve<DiContainer>())(
|
||||||
|
widget.account, a);
|
||||||
}
|
}
|
||||||
} catch (e, stackTrace) {
|
} catch (e, stackTrace) {
|
||||||
_log.shout(
|
_log.shout(
|
||||||
|
@ -512,7 +495,7 @@ class _HomeAlbumsState extends State<HomeAlbums>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
late ListAlbumBloc _bloc;
|
late final _bloc = ListAlbumBloc.of(widget.account);
|
||||||
late final _accountPrefUpdatedEventListener =
|
late final _accountPrefUpdatedEventListener =
|
||||||
AppEventListener<AccountPrefUpdatedEvent>(_onAccountPrefUpdatedEvent);
|
AppEventListener<AccountPrefUpdatedEvent>(_onAccountPrefUpdatedEvent);
|
||||||
|
|
||||||
|
|
|
@ -2,13 +2,13 @@ import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/scheduler.dart';
|
import 'package:flutter/scheduler.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
|
import 'package:kiwi/kiwi.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:nc_photos/account.dart';
|
import 'package:nc_photos/account.dart';
|
||||||
import 'package:nc_photos/api/api_util.dart' as api_util;
|
import 'package:nc_photos/api/api_util.dart' as api_util;
|
||||||
import 'package:nc_photos/app_db.dart';
|
|
||||||
import 'package:nc_photos/app_localizations.dart';
|
import 'package:nc_photos/app_localizations.dart';
|
||||||
|
import 'package:nc_photos/di_container.dart';
|
||||||
import 'package:nc_photos/entity/file.dart';
|
import 'package:nc_photos/entity/file.dart';
|
||||||
import 'package:nc_photos/entity/file/data_source.dart';
|
|
||||||
import 'package:nc_photos/entity/file_util.dart' as file_util;
|
import 'package:nc_photos/entity/file_util.dart' as file_util;
|
||||||
import 'package:nc_photos/exception_util.dart' as exception_util;
|
import 'package:nc_photos/exception_util.dart' as exception_util;
|
||||||
import 'package:nc_photos/k.dart' as k;
|
import 'package:nc_photos/k.dart' as k;
|
||||||
|
@ -58,12 +58,11 @@ class _RootPickerState extends State<RootPicker> {
|
||||||
|
|
||||||
void _initAccount() async {
|
void _initAccount() async {
|
||||||
try {
|
try {
|
||||||
final fileRepo = FileRepo(FileCachedDataSource(AppDb()));
|
|
||||||
final files = <File>[];
|
final files = <File>[];
|
||||||
for (final r in widget.account.roots) {
|
for (final r in widget.account.roots) {
|
||||||
if (r.isNotEmpty) {
|
if (r.isNotEmpty) {
|
||||||
_ensureInitDialog();
|
_ensureInitDialog();
|
||||||
files.add(await LsSingleFile(fileRepo)(
|
files.add(await LsSingleFile(KiwiContainer().resolve<DiContainer>())(
|
||||||
widget.account, file_util.unstripPath(widget.account, r)));
|
widget.account, file_util.unstripPath(widget.account, r)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:kiwi/kiwi.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:nc_photos/account.dart';
|
import 'package:nc_photos/account.dart';
|
||||||
import 'package:nc_photos/api/api.dart';
|
import 'package:nc_photos/api/api.dart';
|
||||||
|
@ -10,6 +11,7 @@ import 'package:nc_photos/api/api_util.dart' as api_util;
|
||||||
import 'package:nc_photos/app_localizations.dart';
|
import 'package:nc_photos/app_localizations.dart';
|
||||||
import 'package:nc_photos/bloc/list_sharing.dart';
|
import 'package:nc_photos/bloc/list_sharing.dart';
|
||||||
import 'package:nc_photos/cache_manager_util.dart';
|
import 'package:nc_photos/cache_manager_util.dart';
|
||||||
|
import 'package:nc_photos/di_container.dart';
|
||||||
import 'package:nc_photos/entity/album.dart';
|
import 'package:nc_photos/entity/album.dart';
|
||||||
import 'package:nc_photos/entity/file.dart';
|
import 'package:nc_photos/entity/file.dart';
|
||||||
import 'package:nc_photos/entity/file/data_source.dart';
|
import 'package:nc_photos/entity/file/data_source.dart';
|
||||||
|
@ -18,6 +20,7 @@ import 'package:nc_photos/exception_util.dart' as exception_util;
|
||||||
import 'package:nc_photos/iterable_extension.dart';
|
import 'package:nc_photos/iterable_extension.dart';
|
||||||
import 'package:nc_photos/k.dart' as k;
|
import 'package:nc_photos/k.dart' as k;
|
||||||
import 'package:nc_photos/object_extension.dart';
|
import 'package:nc_photos/object_extension.dart';
|
||||||
|
import 'package:nc_photos/or_null.dart';
|
||||||
import 'package:nc_photos/pref.dart';
|
import 'package:nc_photos/pref.dart';
|
||||||
import 'package:nc_photos/snack_bar_manager.dart';
|
import 'package:nc_photos/snack_bar_manager.dart';
|
||||||
import 'package:nc_photos/theme.dart';
|
import 'package:nc_photos/theme.dart';
|
||||||
|
@ -325,11 +328,13 @@ class _SharingBrowserState extends State<SharingBrowser> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<Album>> _importPotentialSharedAlbum() async {
|
Future<List<Album>> _importPotentialSharedAlbum() async {
|
||||||
const fileRepo = FileRepo(FileWebdavDataSource());
|
final c = KiwiContainer().resolve<DiContainer>().copyWith(
|
||||||
// don't want the potential albums to be cached at this moment
|
// don't want the potential albums to be cached at this moment
|
||||||
final albumRepo = AlbumRepo(AlbumRemoteDataSource());
|
fileRepo: OrNull(const FileRepo(FileWebdavDataSource())),
|
||||||
|
albumRepo: OrNull(AlbumRepo(AlbumRemoteDataSource())),
|
||||||
|
);
|
||||||
try {
|
try {
|
||||||
return await ImportPotentialSharedAlbum(fileRepo, albumRepo)(
|
return await ImportPotentialSharedAlbum(c)(
|
||||||
widget.account, AccountPref.of(widget.account));
|
widget.account, AccountPref.of(widget.account));
|
||||||
} catch (e, stackTrace) {
|
} catch (e, stackTrace) {
|
||||||
_log.shout(
|
_log.shout(
|
||||||
|
|
|
@ -3,14 +3,15 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
|
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
|
||||||
|
import 'package:kiwi/kiwi.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:nc_photos/account.dart';
|
import 'package:nc_photos/account.dart';
|
||||||
import 'package:nc_photos/api/api_util.dart' as api_util;
|
import 'package:nc_photos/api/api_util.dart' as api_util;
|
||||||
import 'package:nc_photos/app_localizations.dart';
|
import 'package:nc_photos/app_localizations.dart';
|
||||||
import 'package:nc_photos/bloc/ls_trashbin.dart';
|
import 'package:nc_photos/bloc/ls_trashbin.dart';
|
||||||
import 'package:nc_photos/debug_util.dart';
|
import 'package:nc_photos/debug_util.dart';
|
||||||
|
import 'package:nc_photos/di_container.dart';
|
||||||
import 'package:nc_photos/entity/file.dart';
|
import 'package:nc_photos/entity/file.dart';
|
||||||
import 'package:nc_photos/entity/file/data_source.dart';
|
|
||||||
import 'package:nc_photos/entity/file_util.dart' as file_util;
|
import 'package:nc_photos/entity/file_util.dart' as file_util;
|
||||||
import 'package:nc_photos/exception_util.dart' as exception_util;
|
import 'package:nc_photos/exception_util.dart' as exception_util;
|
||||||
import 'package:nc_photos/iterable_extension.dart';
|
import 'package:nc_photos/iterable_extension.dart';
|
||||||
|
@ -291,11 +292,11 @@ class _TrashbinBrowserState extends State<TrashbinBrowser>
|
||||||
setState(() {
|
setState(() {
|
||||||
clearSelectedItems();
|
clearSelectedItems();
|
||||||
});
|
});
|
||||||
const fileRepo = FileRepo(FileWebdavDataSource());
|
|
||||||
final failures = <File>[];
|
final failures = <File>[];
|
||||||
for (final f in selectedFiles) {
|
for (final f in selectedFiles) {
|
||||||
try {
|
try {
|
||||||
await RestoreTrashbin(fileRepo)(widget.account, f);
|
await RestoreTrashbin(KiwiContainer().resolve<DiContainer>())(
|
||||||
|
widget.account, f);
|
||||||
} catch (e, stacktrace) {
|
} catch (e, stacktrace) {
|
||||||
_log.shout(
|
_log.shout(
|
||||||
"[_onSelectionAppBarRestorePressed] Failed while restoring file: ${logFilename(f.path)}",
|
"[_onSelectionAppBarRestorePressed] Failed while restoring file: ${logFilename(f.path)}",
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
|
import 'package:kiwi/kiwi.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:nc_photos/account.dart';
|
import 'package:nc_photos/account.dart';
|
||||||
import 'package:nc_photos/app_db.dart';
|
|
||||||
import 'package:nc_photos/app_localizations.dart';
|
import 'package:nc_photos/app_localizations.dart';
|
||||||
import 'package:nc_photos/debug_util.dart';
|
import 'package:nc_photos/debug_util.dart';
|
||||||
|
import 'package:nc_photos/di_container.dart';
|
||||||
import 'package:nc_photos/entity/file.dart';
|
import 'package:nc_photos/entity/file.dart';
|
||||||
import 'package:nc_photos/entity/file/data_source.dart';
|
|
||||||
import 'package:nc_photos/entity/file_util.dart' as file_util;
|
import 'package:nc_photos/entity/file_util.dart' as file_util;
|
||||||
import 'package:nc_photos/exception_util.dart' as exception_util;
|
import 'package:nc_photos/exception_util.dart' as exception_util;
|
||||||
import 'package:nc_photos/k.dart' as k;
|
import 'package:nc_photos/k.dart' as k;
|
||||||
|
@ -166,9 +166,9 @@ class _TrashbinViewerState extends State<TrashbinViewer> {
|
||||||
controller?.closed.whenComplete(() {
|
controller?.closed.whenComplete(() {
|
||||||
controller = null;
|
controller = null;
|
||||||
});
|
});
|
||||||
final fileRepo = FileRepo(FileCachedDataSource(AppDb()));
|
|
||||||
try {
|
try {
|
||||||
await RestoreTrashbin(fileRepo)(widget.account, file);
|
await RestoreTrashbin(KiwiContainer().resolve<DiContainer>())(
|
||||||
|
widget.account, file);
|
||||||
controller?.close();
|
controller?.close();
|
||||||
SnackBarManager().showSnackBar(SnackBar(
|
SnackBarManager().showSnackBar(SnackBar(
|
||||||
content: Text(L10n.global().restoreSuccessNotification),
|
content: Text(L10n.global().restoreSuccessNotification),
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import 'package:nc_photos/di_container.dart';
|
||||||
|
import 'package:nc_photos/object_extension.dart';
|
||||||
import 'package:nc_photos/use_case/find_file.dart';
|
import 'package:nc_photos/use_case/find_file.dart';
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
@ -5,7 +7,6 @@ import '../mock_type.dart';
|
||||||
import '../test_util.dart' as util;
|
import '../test_util.dart' as util;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
util.initLog();
|
|
||||||
group("FindFile", () {
|
group("FindFile", () {
|
||||||
test("file", _findFile);
|
test("file", _findFile);
|
||||||
test("missing file", _findMissingFile);
|
test("missing file", _findMissingFile);
|
||||||
|
@ -21,10 +22,13 @@ Future<void> _findFile() async {
|
||||||
..addJpeg("admin/test1.jpg")
|
..addJpeg("admin/test1.jpg")
|
||||||
..addJpeg("admin/test2.jpg"))
|
..addJpeg("admin/test2.jpg"))
|
||||||
.build();
|
.build();
|
||||||
final appDb = MockAppDb();
|
final c = DiContainer(
|
||||||
await util.fillAppDb(appDb, account, files);
|
appDb: await MockAppDb().applyFuture((obj) async {
|
||||||
|
await util.fillAppDb(obj, account, files);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
expect(await FindFile(appDb)(account, 1), files[1]);
|
expect(await FindFile(c)(account, 1), files[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find a file not existing in app db
|
/// Find a file not existing in app db
|
||||||
|
@ -33,8 +37,11 @@ Future<void> _findFile() async {
|
||||||
Future<void> _findMissingFile() async {
|
Future<void> _findMissingFile() async {
|
||||||
final account = util.buildAccount();
|
final account = util.buildAccount();
|
||||||
final files = (util.FilesBuilder()..addJpeg("admin/test1.jpg")).build();
|
final files = (util.FilesBuilder()..addJpeg("admin/test1.jpg")).build();
|
||||||
final appDb = MockAppDb();
|
final c = DiContainer(
|
||||||
await util.fillAppDb(appDb, account, files);
|
appDb: await MockAppDb().applyFuture((obj) async {
|
||||||
|
await util.fillAppDb(obj, account, files);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
expect(() => FindFile(appDb)(account, 1), throwsStateError);
|
expect(() => FindFile(c)(account, 1), throwsStateError);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue