mirror of
https://gitlab.com/nkming2/nc-photos.git
synced 2025-02-25 02:48:54 +01:00
Fix no albums shown if any one of them erred
This commit is contained in:
parent
60339968de
commit
a124c99f33
4 changed files with 72 additions and 65 deletions
|
@ -6,6 +6,7 @@ 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/event/event.dart';
|
import 'package:nc_photos/event/event.dart';
|
||||||
import 'package:nc_photos/use_case/list_album.dart';
|
import 'package:nc_photos/use_case/list_album.dart';
|
||||||
|
import 'package:tuple/tuple.dart';
|
||||||
|
|
||||||
abstract class ListAlbumBlocEvent {
|
abstract class ListAlbumBlocEvent {
|
||||||
const ListAlbumBlocEvent();
|
const ListAlbumBlocEvent();
|
||||||
|
@ -124,30 +125,19 @@ class ListAlbumBloc extends Bloc<ListAlbumBlocEvent, ListAlbumBlocState> {
|
||||||
|
|
||||||
if (!hasContent) {
|
if (!hasContent) {
|
||||||
// show something instantly on first load
|
// show something instantly on first load
|
||||||
ListAlbumBlocState cacheState = ListAlbumBlocInit();
|
final cacheState = await _queryOffline(ev);
|
||||||
await for (final s in _queryOffline(ev, () => cacheState)) {
|
|
||||||
cacheState = s;
|
|
||||||
}
|
|
||||||
yield ListAlbumBlocLoading(ev.account, cacheState.albums);
|
yield ListAlbumBlocLoading(ev.account, cacheState.albums);
|
||||||
hasContent = cacheState.albums.isNotEmpty;
|
hasContent = cacheState.albums.isNotEmpty;
|
||||||
}
|
}
|
||||||
|
|
||||||
ListAlbumBlocState newState = ListAlbumBlocInit();
|
final newState = await _queryOnline(ev);
|
||||||
if (!hasContent) {
|
if (newState is ListAlbumBlocFailure) {
|
||||||
await for (final s in _queryOnline(ev, () => newState)) {
|
yield ListAlbumBlocFailure(
|
||||||
newState = s;
|
ev.account,
|
||||||
yield s;
|
newState.albums?.isNotEmpty == true ? newState.albums : state.albums,
|
||||||
}
|
newState.exception);
|
||||||
} else {
|
} else {
|
||||||
await for (final s in _queryOnline(ev, () => newState)) {
|
yield newState;
|
||||||
newState = s;
|
|
||||||
}
|
|
||||||
if (newState is ListAlbumBlocSuccess) {
|
|
||||||
yield newState;
|
|
||||||
} else if (newState is ListAlbumBlocFailure) {
|
|
||||||
yield ListAlbumBlocFailure(
|
|
||||||
ev.account, state.albums, newState.exception);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,29 +172,37 @@ class ListAlbumBloc extends Bloc<ListAlbumBlocEvent, ListAlbumBlocState> {
|
||||||
add(_ListAlbumBlocExternalEvent());
|
add(_ListAlbumBlocExternalEvent());
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream<ListAlbumBlocState> _queryOffline(
|
Future<ListAlbumBlocState> _queryOffline(ListAlbumBlocQuery ev) =>
|
||||||
ListAlbumBlocQuery ev, ListAlbumBlocState Function() getState) =>
|
|
||||||
_queryWithAlbumDataSource(
|
_queryWithAlbumDataSource(
|
||||||
ev, getState, FileAppDbDataSource(), AlbumAppDbDataSource());
|
ev, FileAppDbDataSource(), AlbumAppDbDataSource());
|
||||||
|
|
||||||
Stream<ListAlbumBlocState> _queryOnline(
|
Future<ListAlbumBlocState> _queryOnline(ListAlbumBlocQuery ev) =>
|
||||||
ListAlbumBlocQuery ev, ListAlbumBlocState Function() getState) =>
|
|
||||||
_queryWithAlbumDataSource(
|
_queryWithAlbumDataSource(
|
||||||
ev, getState, FileCachedDataSource(), AlbumCachedDataSource());
|
ev, FileCachedDataSource(), AlbumCachedDataSource());
|
||||||
|
|
||||||
Stream<ListAlbumBlocState> _queryWithAlbumDataSource(
|
Future<ListAlbumBlocState> _queryWithAlbumDataSource(ListAlbumBlocQuery ev,
|
||||||
ListAlbumBlocQuery ev,
|
FileDataSource fileDataSource, AlbumDataSource albumDataSrc) async {
|
||||||
ListAlbumBlocState Function() getState,
|
|
||||||
FileDataSource fileDataSource,
|
|
||||||
AlbumDataSource albumDataSrc) async* {
|
|
||||||
try {
|
try {
|
||||||
final results = await ListAlbum(
|
final albums = <Album>[];
|
||||||
FileRepo(fileDataSource), AlbumRepo(albumDataSrc))(ev.account);
|
final errors = <dynamic>[];
|
||||||
yield ListAlbumBlocSuccess(ev.account, results);
|
await for (final result in ListAlbum(
|
||||||
|
FileRepo(fileDataSource), AlbumRepo(albumDataSrc))(ev.account)) {
|
||||||
|
if (result is Tuple2) {
|
||||||
|
_log.severe("[_queryWithAlbumDataSource] Exception while ListAlbum",
|
||||||
|
result.item1, result.item2);
|
||||||
|
errors.add(result.item1);
|
||||||
|
} else if (result is Album) {
|
||||||
|
albums.add(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (errors.isEmpty) {
|
||||||
|
return ListAlbumBlocSuccess(ev.account, albums);
|
||||||
|
} else {
|
||||||
|
return ListAlbumBlocFailure(ev.account, albums, errors.first);
|
||||||
|
}
|
||||||
} catch (e, stacktrace) {
|
} catch (e, stacktrace) {
|
||||||
_log.severe(
|
_log.severe("[_queryWithAlbumDataSource] Exception", e, stacktrace);
|
||||||
"[_queryWithAlbumDataSource] Exception while request", e, stacktrace);
|
return ListAlbumBlocFailure(ev.account, [], e);
|
||||||
yield ListAlbumBlocFailure(ev.account, getState().albums, e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -102,7 +102,9 @@ class ListImportableAlbumBloc
|
||||||
try {
|
try {
|
||||||
final fileRepo = FileRepo(FileCachedDataSource());
|
final fileRepo = FileRepo(FileCachedDataSource());
|
||||||
final albumRepo = AlbumRepo(AlbumCachedDataSource());
|
final albumRepo = AlbumRepo(AlbumCachedDataSource());
|
||||||
final albums = await ListAlbum(fileRepo, albumRepo)(ev.account);
|
final albums = (await ListAlbum(fileRepo, albumRepo)(ev.account)
|
||||||
|
.where((event) => event is Album)
|
||||||
|
.toList()).cast<Album>();
|
||||||
final importedDirs = albums.map((a) {
|
final importedDirs = albums.map((a) {
|
||||||
if (a.provider is! AlbumDirProvider) {
|
if (a.provider is! AlbumDirProvider) {
|
||||||
return <File>[];
|
return <File>[];
|
||||||
|
|
|
@ -6,54 +6,59 @@ import 'package:nc_photos/exception.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/use_case/compat/v15.dart';
|
import 'package:nc_photos/use_case/compat/v15.dart';
|
||||||
import 'package:nc_photos/use_case/ls.dart';
|
import 'package:nc_photos/use_case/ls.dart';
|
||||||
|
import 'package:tuple/tuple.dart';
|
||||||
|
|
||||||
class ListAlbum {
|
class ListAlbum {
|
||||||
ListAlbum(this.fileRepo, this.albumRepo);
|
ListAlbum(this.fileRepo, this.albumRepo);
|
||||||
|
|
||||||
/// List all albums associated with [account]
|
/// List all albums associated with [account]
|
||||||
Future<List<Album>> call(Account account) async {
|
///
|
||||||
final results = await _call(account);
|
/// The returned stream would emit either Album data or a tuple of exception
|
||||||
if (results.isEmpty) {
|
/// and stacktrace
|
||||||
|
Stream<dynamic> call(Account account) async* {
|
||||||
|
bool hasAlbum = false;
|
||||||
|
await for (final result in _call(account)) {
|
||||||
|
hasAlbum = true;
|
||||||
|
yield result;
|
||||||
|
}
|
||||||
|
if (!hasAlbum) {
|
||||||
if (await CompatV15.migrateAlbumFiles(account, fileRepo)) {
|
if (await CompatV15.migrateAlbumFiles(account, fileRepo)) {
|
||||||
// migrated
|
// migrated, try again
|
||||||
return await _call(account);
|
yield* _call(account);
|
||||||
} else {
|
|
||||||
// no need to migrate
|
|
||||||
return [];
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
return results;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<Album>> _call(Account account) async {
|
Stream<dynamic> _call(Account account) async* {
|
||||||
|
List<File> ls;
|
||||||
try {
|
try {
|
||||||
final ls = await Ls(fileRepo)(
|
ls = await Ls(fileRepo)(
|
||||||
account,
|
account,
|
||||||
File(
|
File(
|
||||||
path: remote_storage_util.getRemoteAlbumsDir(account),
|
path: remote_storage_util.getRemoteAlbumsDir(account),
|
||||||
));
|
));
|
||||||
final albumFiles =
|
|
||||||
ls.where((element) => element.isCollection != true).toList();
|
|
||||||
final albums = <Album>[];
|
|
||||||
for (final f in albumFiles) {
|
|
||||||
final album = await albumRepo.get(account, f);
|
|
||||||
albums.add(album);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
albumRepo.cleanUp(account, albumFiles);
|
|
||||||
} catch (e, stacktrace) {
|
|
||||||
// not important, log and ignore
|
|
||||||
_log.shout("[_call] Failed while cleanUp", e, stacktrace);
|
|
||||||
}
|
|
||||||
return albums;
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e is ApiException && e.response.statusCode == 404) {
|
if (e is ApiException && e.response.statusCode == 404) {
|
||||||
// no albums
|
// no albums
|
||||||
return [];
|
return;
|
||||||
}
|
}
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
|
final albumFiles =
|
||||||
|
ls.where((element) => element.isCollection != true).toList();
|
||||||
|
for (final f in albumFiles) {
|
||||||
|
try {
|
||||||
|
yield await albumRepo.get(account, f);
|
||||||
|
} catch (e, stacktrace) {
|
||||||
|
yield Tuple2(e, stacktrace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
albumRepo.cleanUp(account, albumFiles);
|
||||||
|
} catch (e, stacktrace) {
|
||||||
|
// not important, log and ignore
|
||||||
|
_log.shout("[_call] Failed while cleanUp", e, stacktrace);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final FileRepo fileRepo;
|
final FileRepo fileRepo;
|
||||||
|
|
|
@ -24,7 +24,9 @@ class Remove {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _cleanUpAlbums(Account account, File file) async {
|
Future<void> _cleanUpAlbums(Account account, File file) async {
|
||||||
final albums = await ListAlbum(fileRepo, albumRepo)(account);
|
final albums = (await ListAlbum(fileRepo, albumRepo)(account)
|
||||||
|
.where((event) => event is Album)
|
||||||
|
.toList()).cast<Album>();
|
||||||
// clean up only make sense for static albums
|
// clean up only make sense for static albums
|
||||||
for (final a
|
for (final a
|
||||||
in albums.where((element) => element.provider is AlbumStaticProvider)) {
|
in albums.where((element) => element.provider is AlbumStaticProvider)) {
|
||||||
|
|
Loading…
Reference in a new issue