2021-04-10 06:28:12 +02:00
|
|
|
import 'package:bloc/bloc.dart';
|
|
|
|
import 'package:logging/logging.dart';
|
|
|
|
import 'package:nc_photos/account.dart';
|
|
|
|
import 'package:nc_photos/entity/album.dart';
|
|
|
|
import 'package:nc_photos/entity/file.dart';
|
2021-05-24 09:09:25 +02:00
|
|
|
import 'package:nc_photos/entity/file/data_source.dart';
|
2021-04-10 06:28:12 +02:00
|
|
|
import 'package:nc_photos/event/event.dart';
|
|
|
|
import 'package:nc_photos/use_case/list_album.dart';
|
|
|
|
|
|
|
|
abstract class ListAlbumBlocEvent {
|
|
|
|
const ListAlbumBlocEvent();
|
|
|
|
}
|
|
|
|
|
|
|
|
class ListAlbumBlocQuery extends ListAlbumBlocEvent {
|
|
|
|
const ListAlbumBlocQuery(this.account);
|
|
|
|
|
|
|
|
@override
|
|
|
|
toString() {
|
|
|
|
return "$runtimeType {"
|
|
|
|
"account: $account, "
|
|
|
|
"}";
|
|
|
|
}
|
|
|
|
|
|
|
|
final Account account;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// An external event has happened and may affect the state of this bloc
|
|
|
|
class _ListAlbumBlocExternalEvent extends ListAlbumBlocEvent {
|
|
|
|
const _ListAlbumBlocExternalEvent();
|
|
|
|
|
|
|
|
@override
|
|
|
|
toString() {
|
|
|
|
return "$runtimeType {"
|
|
|
|
"}";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
abstract class ListAlbumBlocState {
|
|
|
|
const ListAlbumBlocState(this.account, this.albums);
|
|
|
|
|
|
|
|
@override
|
|
|
|
toString() {
|
|
|
|
return "$runtimeType {"
|
|
|
|
"account: $account, "
|
|
|
|
"albums: List {length: ${albums.length}}, "
|
|
|
|
"}";
|
|
|
|
}
|
|
|
|
|
|
|
|
final Account account;
|
|
|
|
final List<Album> albums;
|
|
|
|
}
|
|
|
|
|
|
|
|
class ListAlbumBlocInit extends ListAlbumBlocState {
|
|
|
|
const ListAlbumBlocInit() : super(null, const []);
|
|
|
|
}
|
|
|
|
|
|
|
|
class ListAlbumBlocLoading extends ListAlbumBlocState {
|
|
|
|
const ListAlbumBlocLoading(Account account, List<Album> albums)
|
|
|
|
: super(account, albums);
|
|
|
|
}
|
|
|
|
|
|
|
|
class ListAlbumBlocSuccess extends ListAlbumBlocState {
|
|
|
|
const ListAlbumBlocSuccess(Account account, List<Album> albums)
|
|
|
|
: super(account, albums);
|
|
|
|
}
|
|
|
|
|
|
|
|
class ListAlbumBlocFailure extends ListAlbumBlocState {
|
|
|
|
const ListAlbumBlocFailure(
|
|
|
|
Account account, List<Album> albums, this.exception)
|
|
|
|
: super(account, albums);
|
|
|
|
|
|
|
|
@override
|
|
|
|
toString() {
|
|
|
|
return "$runtimeType {"
|
|
|
|
"super: ${super.toString()}, "
|
|
|
|
"exception: $exception, "
|
|
|
|
"}";
|
|
|
|
}
|
|
|
|
|
|
|
|
final dynamic exception;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// The state of this bloc is inconsistent. This typically means that the data
|
|
|
|
/// may have been changed externally
|
|
|
|
class ListAlbumBlocInconsistent extends ListAlbumBlocState {
|
|
|
|
const ListAlbumBlocInconsistent(Account account, List<Album> albums)
|
|
|
|
: super(account, albums);
|
|
|
|
}
|
|
|
|
|
|
|
|
class ListAlbumBloc extends Bloc<ListAlbumBlocEvent, ListAlbumBlocState> {
|
|
|
|
ListAlbumBloc() : super(ListAlbumBlocInit()) {
|
2021-05-28 19:15:09 +02:00
|
|
|
_filePropertyUpdatedListener =
|
|
|
|
AppEventListener<FilePropertyUpdatedEvent>(_onFilePropertyUpdatedEvent);
|
2021-04-10 06:28:12 +02:00
|
|
|
_albumUpdatedListener =
|
|
|
|
AppEventListener<AlbumUpdatedEvent>(_onAlbumUpdatedEvent);
|
|
|
|
_fileRemovedListener =
|
|
|
|
AppEventListener<FileRemovedEvent>(_onFileRemovedEvent);
|
|
|
|
_albumCreatedListener =
|
|
|
|
AppEventListener<AlbumCreatedEvent>(_onAlbumCreatedEvent);
|
2021-05-28 19:15:09 +02:00
|
|
|
_filePropertyUpdatedListener.begin();
|
2021-04-10 06:28:12 +02:00
|
|
|
_albumUpdatedListener.begin();
|
|
|
|
_fileRemovedListener.begin();
|
|
|
|
_albumCreatedListener.begin();
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
mapEventToState(ListAlbumBlocEvent event) async* {
|
|
|
|
_log.info("[mapEventToState] $event");
|
|
|
|
if (event is ListAlbumBlocQuery) {
|
|
|
|
yield* _onEventQuery(event);
|
|
|
|
} else if (event is _ListAlbumBlocExternalEvent) {
|
|
|
|
yield* _onExternalEvent(event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
close() {
|
2021-05-28 19:15:09 +02:00
|
|
|
_filePropertyUpdatedListener.end();
|
2021-04-10 06:28:12 +02:00
|
|
|
_albumUpdatedListener.end();
|
|
|
|
_fileRemovedListener.end();
|
|
|
|
_albumCreatedListener.end();
|
|
|
|
return super.close();
|
|
|
|
}
|
|
|
|
|
|
|
|
Stream<ListAlbumBlocState> _onEventQuery(ListAlbumBlocQuery ev) async* {
|
|
|
|
yield ListAlbumBlocLoading(ev.account, state.albums);
|
2021-04-26 18:14:44 +02:00
|
|
|
bool hasContent = state.albums.isNotEmpty;
|
2021-04-10 06:28:12 +02:00
|
|
|
|
2021-04-26 18:14:44 +02:00
|
|
|
if (!hasContent) {
|
|
|
|
// show something instantly on first load
|
|
|
|
ListAlbumBlocState cacheState = ListAlbumBlocInit();
|
|
|
|
await for (final s in _queryOffline(ev, () => cacheState)) {
|
|
|
|
cacheState = s;
|
|
|
|
}
|
|
|
|
yield ListAlbumBlocLoading(ev.account, cacheState.albums);
|
|
|
|
hasContent = cacheState.albums.isNotEmpty;
|
2021-04-10 06:28:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ListAlbumBlocState newState = ListAlbumBlocInit();
|
2021-04-26 18:14:44 +02:00
|
|
|
if (!hasContent) {
|
2021-04-10 06:28:12 +02:00
|
|
|
await for (final s in _queryOnline(ev, () => newState)) {
|
|
|
|
newState = s;
|
|
|
|
yield s;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
await for (final s in _queryOnline(ev, () => newState)) {
|
|
|
|
newState = s;
|
|
|
|
}
|
|
|
|
if (newState is ListAlbumBlocSuccess) {
|
|
|
|
yield newState;
|
|
|
|
} else if (newState is ListAlbumBlocFailure) {
|
|
|
|
yield ListAlbumBlocFailure(
|
2021-04-26 18:14:44 +02:00
|
|
|
ev.account, state.albums, newState.exception);
|
2021-04-10 06:28:12 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Stream<ListAlbumBlocState> _onExternalEvent(
|
|
|
|
_ListAlbumBlocExternalEvent ev) async* {
|
|
|
|
yield ListAlbumBlocInconsistent(state.account, state.albums);
|
|
|
|
}
|
|
|
|
|
2021-05-28 19:15:09 +02:00
|
|
|
void _onFilePropertyUpdatedEvent(FilePropertyUpdatedEvent ev) {
|
|
|
|
if (!ev.hasAnyProperties([FilePropertyUpdatedEvent.propMetadata])) {
|
|
|
|
// not interested
|
|
|
|
return;
|
|
|
|
}
|
2021-04-10 06:28:12 +02:00
|
|
|
if (state is ListAlbumBlocInit) {
|
|
|
|
// no data in this bloc, ignore
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
add(_ListAlbumBlocExternalEvent());
|
|
|
|
}
|
|
|
|
|
|
|
|
void _onAlbumUpdatedEvent(AlbumUpdatedEvent ev) {
|
|
|
|
if (state is ListAlbumBlocInit) {
|
|
|
|
// no data in this bloc, ignore
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
add(_ListAlbumBlocExternalEvent());
|
|
|
|
}
|
|
|
|
|
|
|
|
void _onFileRemovedEvent(FileRemovedEvent ev) {
|
|
|
|
if (state is ListAlbumBlocInit) {
|
|
|
|
// no data in this bloc, ignore
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (isAlbumFile(ev.file)) {
|
|
|
|
add(_ListAlbumBlocExternalEvent());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void _onAlbumCreatedEvent(AlbumCreatedEvent ev) {
|
|
|
|
if (state is ListAlbumBlocInit) {
|
|
|
|
// no data in this bloc, ignore
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
add(_ListAlbumBlocExternalEvent());
|
|
|
|
}
|
|
|
|
|
|
|
|
Stream<ListAlbumBlocState> _queryOffline(
|
|
|
|
ListAlbumBlocQuery ev, ListAlbumBlocState Function() getState) =>
|
|
|
|
_queryWithAlbumDataSource(
|
|
|
|
ev, getState, FileAppDbDataSource(), AlbumAppDbDataSource());
|
|
|
|
|
|
|
|
Stream<ListAlbumBlocState> _queryOnline(
|
|
|
|
ListAlbumBlocQuery ev, ListAlbumBlocState Function() getState) =>
|
|
|
|
_queryWithAlbumDataSource(
|
|
|
|
ev, getState, FileCachedDataSource(), AlbumCachedDataSource());
|
|
|
|
|
|
|
|
Stream<ListAlbumBlocState> _queryWithAlbumDataSource(
|
|
|
|
ListAlbumBlocQuery ev,
|
|
|
|
ListAlbumBlocState Function() getState,
|
|
|
|
FileDataSource fileDataSource,
|
|
|
|
AlbumDataSource albumDataSrc) async* {
|
|
|
|
try {
|
|
|
|
final results = await ListAlbum(
|
|
|
|
FileRepo(fileDataSource), AlbumRepo(albumDataSrc))(ev.account);
|
|
|
|
yield ListAlbumBlocSuccess(ev.account, results);
|
2021-04-26 18:15:37 +02:00
|
|
|
} catch (e, stacktrace) {
|
|
|
|
_log.severe(
|
|
|
|
"[_queryWithAlbumDataSource] Exception while request", e, stacktrace);
|
2021-04-10 06:28:12 +02:00
|
|
|
yield ListAlbumBlocFailure(ev.account, getState().albums, e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-28 19:15:09 +02:00
|
|
|
AppEventListener<FilePropertyUpdatedEvent> _filePropertyUpdatedListener;
|
2021-04-10 06:28:12 +02:00
|
|
|
AppEventListener<AlbumUpdatedEvent> _albumUpdatedListener;
|
|
|
|
AppEventListener<FileRemovedEvent> _fileRemovedListener;
|
|
|
|
AppEventListener<AlbumCreatedEvent> _albumCreatedListener;
|
|
|
|
|
|
|
|
static final _log = Logger("bloc.list_album.ListAlbumBloc");
|
|
|
|
}
|