import 'package:bloc/bloc.dart'; import 'package:flutter/foundation.dart'; import 'package:kiwi/kiwi.dart'; import 'package:logging/logging.dart'; import 'package:nc_photos/di_container.dart'; import 'package:nc_photos/entity/local_file.dart'; import 'package:nc_photos/event/event.dart'; import 'package:nc_photos/iterable_extension.dart'; import 'package:nc_photos/use_case/scan_local_dir.dart'; import 'package:np_codegen/np_codegen.dart'; import 'package:to_string/to_string.dart'; part 'scan_local_dir.g.dart'; abstract class ScanLocalDirBlocEvent { const ScanLocalDirBlocEvent(); } @toString class ScanLocalDirBlocQuery extends ScanLocalDirBlocEvent { const ScanLocalDirBlocQuery(this.relativePaths); @override String toString() => _$toString(); @Format(r"${$?.toReadableString()}") final List relativePaths; } @toString class _ScanLocalDirBlocFileDeleted extends ScanLocalDirBlocEvent { const _ScanLocalDirBlocFileDeleted(this.files); @override String toString() => _$toString(); @Format(r"${$?.map((f) => f.logTag).toReadableString()}") final List files; } @toString abstract class ScanLocalDirBlocState { const ScanLocalDirBlocState(this.files); @override String toString() => _$toString(); final List files; } class ScanLocalDirBlocInit extends ScanLocalDirBlocState { const ScanLocalDirBlocInit() : super(const []); } class ScanLocalDirBlocLoading extends ScanLocalDirBlocState { const ScanLocalDirBlocLoading(List files) : super(files); } class ScanLocalDirBlocSuccess extends ScanLocalDirBlocState { const ScanLocalDirBlocSuccess(List files) : super(files); } @toString class ScanLocalDirBlocFailure extends ScanLocalDirBlocState { const ScanLocalDirBlocFailure(List files, this.exception) : super(files); @override String toString() => _$toString(); final dynamic exception; } @npLog class ScanLocalDirBloc extends Bloc { ScanLocalDirBloc() : super(const ScanLocalDirBlocInit()) { on(_onScanLocalDirBlocQuery); on<_ScanLocalDirBlocFileDeleted>(_onScanLocalDirBlocFileDeleted); _fileDeletedEventListener.begin(); } @override close() { _fileDeletedEventListener.end(); return super.close(); } Future _onScanLocalDirBlocQuery( ScanLocalDirBlocQuery event, Emitter emit) async { final shouldEmitIntermediate = state.files.isEmpty; try { emit(ScanLocalDirBlocLoading(state.files)); final c = KiwiContainer().resolve(); final products = []; for (final p in event.relativePaths) { if (shouldEmitIntermediate) { emit(ScanLocalDirBlocLoading(products.toList())); } final files = await ScanLocalDir(c)(p); products.addAll(files); } emit(ScanLocalDirBlocSuccess(products)); } catch (e, stackTrace) { _log.severe( "[_onScanLocalDirBlocQuery] Exception while request", e, stackTrace); emit(ScanLocalDirBlocFailure(state.files, e)); } } Future _onScanLocalDirBlocFileDeleted( _ScanLocalDirBlocFileDeleted event, Emitter emit) async { final newFiles = state.files .where((f) => !event.files.any((d) => d.compareIdentity(f))) .toList(); if (newFiles.length != state.files.length) { emit(ScanLocalDirBlocSuccess(newFiles)); } } void _onFileDeletedEvent(LocalFileDeletedEvent ev) { if (state is ScanLocalDirBlocInit) { return; } add(_ScanLocalDirBlocFileDeleted(ev.files)); } late final _fileDeletedEventListener = AppEventListener(_onFileDeletedEvent); }