mirror of
https://gitlab.com/nkming2/nc-photos.git
synced 2025-02-08 18:28:53 +01:00
Fix item count in HomeCollections does not consider the runtime count from item controller
This commit is contained in:
parent
e77059225b
commit
0521e2b5c3
7 changed files with 89 additions and 16 deletions
|
@ -51,6 +51,13 @@ class CollectionItemsController {
|
||||||
required this.collection,
|
required this.collection,
|
||||||
required this.onCollectionUpdated,
|
required this.onCollectionUpdated,
|
||||||
}) {
|
}) {
|
||||||
|
_countStreamController = BehaviorSubject.seeded(collection.count);
|
||||||
|
_subscriptions.add(_dataStreamController.stream.listen((event) {
|
||||||
|
if (!event.hasNext) {
|
||||||
|
_countStreamController.add(event.items.length);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
_subscriptions.add(filesController.stream.listen(_onFilesEvent));
|
_subscriptions.add(filesController.stream.listen(_onFilesEvent));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,6 +89,8 @@ class CollectionItemsController {
|
||||||
/// Peek the stream and return the current value
|
/// Peek the stream and return the current value
|
||||||
CollectionItemStreamData peekStream() => _dataStreamController.stream.value;
|
CollectionItemStreamData peekStream() => _dataStreamController.stream.value;
|
||||||
|
|
||||||
|
ValueStream<int?> get countStream => _countStreamController.stream;
|
||||||
|
|
||||||
/// Add list of [files] to [collection]
|
/// Add list of [files] to [collection]
|
||||||
Future<void> addFiles(List<FileDescriptor> files) async {
|
Future<void> addFiles(List<FileDescriptor> files) async {
|
||||||
final isInited = _isDataStreamInited;
|
final isInited = _isDataStreamInited;
|
||||||
|
@ -346,6 +355,7 @@ class CollectionItemsController {
|
||||||
hasNext: true,
|
hasNext: true,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
late final BehaviorSubject<int?> _countStreamController;
|
||||||
|
|
||||||
final _mutex = Mutex();
|
final _mutex = Mutex();
|
||||||
final _subscriptions = <StreamSubscription>[];
|
final _subscriptions = <StreamSubscription>[];
|
||||||
|
|
|
@ -191,9 +191,14 @@ class _WrappedHomeCollectionsState extends State<_WrappedHomeCollections>
|
||||||
items: state.transformedItems,
|
items: state.transformedItems,
|
||||||
itemBuilder: (_, __, metadata) {
|
itemBuilder: (_, __, metadata) {
|
||||||
final item = metadata as _Item;
|
final item = metadata as _Item;
|
||||||
return _ItemView(
|
return _BlocSelector<int?>(
|
||||||
account: _bloc.account,
|
selector: (state) =>
|
||||||
item: item,
|
state.itemCounts[item.collection.id],
|
||||||
|
builder: (context, itemCount) => _ItemView(
|
||||||
|
account: _bloc.account,
|
||||||
|
item: item,
|
||||||
|
collectionItemCountOverride: itemCount,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
staggeredTileBuilder: (_, __) =>
|
staggeredTileBuilder: (_, __) =>
|
||||||
|
@ -267,7 +272,8 @@ class _WrappedHomeCollectionsState extends State<_WrappedHomeCollections>
|
||||||
|
|
||||||
typedef _BlocBuilder = BlocBuilder<_Bloc, _State>;
|
typedef _BlocBuilder = BlocBuilder<_Bloc, _State>;
|
||||||
typedef _BlocListener = BlocListener<_Bloc, _State>;
|
typedef _BlocListener = BlocListener<_Bloc, _State>;
|
||||||
// typedef _BlocSelector<T> = BlocSelector<_Bloc, _State, T>;
|
// typedef _BlocListenerT<T> = BlocListenerT<_Bloc, _State, T>;
|
||||||
|
typedef _BlocSelector<T> = BlocSelector<_Bloc, _State, T>;
|
||||||
|
|
||||||
extension on BuildContext {
|
extension on BuildContext {
|
||||||
_Bloc get bloc => read<_Bloc>();
|
_Bloc get bloc => read<_Bloc>();
|
||||||
|
|
|
@ -19,6 +19,7 @@ abstract class $_StateCopyWithWorker {
|
||||||
bool? isLoading,
|
bool? isLoading,
|
||||||
List<_Item>? transformedItems,
|
List<_Item>? transformedItems,
|
||||||
Set<_Item>? selectedItems,
|
Set<_Item>? selectedItems,
|
||||||
|
Map<String, int>? itemCounts,
|
||||||
ExceptionEvent? error,
|
ExceptionEvent? error,
|
||||||
ExceptionEvent? removeError});
|
ExceptionEvent? removeError});
|
||||||
}
|
}
|
||||||
|
@ -33,6 +34,7 @@ class _$_StateCopyWithWorkerImpl implements $_StateCopyWithWorker {
|
||||||
dynamic isLoading,
|
dynamic isLoading,
|
||||||
dynamic transformedItems,
|
dynamic transformedItems,
|
||||||
dynamic selectedItems,
|
dynamic selectedItems,
|
||||||
|
dynamic itemCounts,
|
||||||
dynamic error = copyWithNull,
|
dynamic error = copyWithNull,
|
||||||
dynamic removeError = copyWithNull}) {
|
dynamic removeError = copyWithNull}) {
|
||||||
return _State(
|
return _State(
|
||||||
|
@ -42,6 +44,7 @@ class _$_StateCopyWithWorkerImpl implements $_StateCopyWithWorker {
|
||||||
transformedItems:
|
transformedItems:
|
||||||
transformedItems as List<_Item>? ?? that.transformedItems,
|
transformedItems as List<_Item>? ?? that.transformedItems,
|
||||||
selectedItems: selectedItems as Set<_Item>? ?? that.selectedItems,
|
selectedItems: selectedItems as Set<_Item>? ?? that.selectedItems,
|
||||||
|
itemCounts: itemCounts as Map<String, int>? ?? that.itemCounts,
|
||||||
error: error == copyWithNull ? that.error : error as ExceptionEvent?,
|
error: error == copyWithNull ? that.error : error as ExceptionEvent?,
|
||||||
removeError: removeError == copyWithNull
|
removeError: removeError == copyWithNull
|
||||||
? that.removeError
|
? that.removeError
|
||||||
|
@ -96,7 +99,7 @@ extension _$_ItemNpLog on _Item {
|
||||||
extension _$_StateToString on _State {
|
extension _$_StateToString on _State {
|
||||||
String _$toString() {
|
String _$toString() {
|
||||||
// ignore: unnecessary_string_interpolations
|
// ignore: unnecessary_string_interpolations
|
||||||
return "_State {collections: [length: ${collections.length}], sort: ${sort.name}, isLoading: $isLoading, transformedItems: [length: ${transformedItems.length}], selectedItems: {length: ${selectedItems.length}}, error: $error, removeError: $removeError}";
|
return "_State {collections: [length: ${collections.length}], sort: ${sort.name}, isLoading: $isLoading, transformedItems: [length: ${transformedItems.length}], selectedItems: {length: ${selectedItems.length}}, itemCounts: $itemCounts, error: $error, removeError: $removeError}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,6 +152,13 @@ extension _$_SetCollectionSortToString on _SetCollectionSort {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension _$_SetItemCountToString on _SetItemCount {
|
||||||
|
String _$toString() {
|
||||||
|
// ignore: unnecessary_string_interpolations
|
||||||
|
return "_SetItemCount {collection: $collection, value: $value}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extension _$_SetErrorToString on _SetError {
|
extension _$_SetErrorToString on _SetError {
|
||||||
String _$toString() {
|
String _$toString() {
|
||||||
// ignore: unnecessary_string_interpolations
|
// ignore: unnecessary_string_interpolations
|
||||||
|
|
|
@ -16,18 +16,36 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
|
||||||
|
|
||||||
on<_UpdateCollectionSort>(_onUpdateCollectionSort);
|
on<_UpdateCollectionSort>(_onUpdateCollectionSort);
|
||||||
on<_SetCollectionSort>(_onSetCollectionSort);
|
on<_SetCollectionSort>(_onSetCollectionSort);
|
||||||
|
on<_SetItemCount>(_onSetItemCount);
|
||||||
|
|
||||||
on<_SetError>(_onSetError);
|
on<_SetError>(_onSetError);
|
||||||
|
|
||||||
_homeAlbumsSortSubscription =
|
_subscriptions.add(prefController.homeAlbumsSort.distinct().listen((event) {
|
||||||
prefController.homeAlbumsSort.distinct().listen((event) {
|
|
||||||
add(_UpdateCollectionSort(collection_util.CollectionSort.values[event]));
|
add(_UpdateCollectionSort(collection_util.CollectionSort.values[event]));
|
||||||
});
|
}));
|
||||||
|
_subscriptions.add(controller.stream.listen((event) {
|
||||||
|
for (final s in _itemSubscriptions) {
|
||||||
|
s.cancel();
|
||||||
|
}
|
||||||
|
_itemSubscriptions.clear();
|
||||||
|
for (final d in event.data) {
|
||||||
|
_itemSubscriptions.add(d.controller.countStream.listen((event) {
|
||||||
|
if (event != null) {
|
||||||
|
add(_SetItemCount(d.collection, event));
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> close() {
|
Future<void> close() {
|
||||||
_homeAlbumsSortSubscription?.cancel();
|
for (final s in _itemSubscriptions) {
|
||||||
|
s.cancel();
|
||||||
|
}
|
||||||
|
for (final s in _subscriptions) {
|
||||||
|
s.cancel();
|
||||||
|
}
|
||||||
return super.close();
|
return super.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,6 +123,13 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
|
||||||
prefController.setHomeAlbumsSort(ev.sort.index);
|
prefController.setHomeAlbumsSort(ev.sort.index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _onSetItemCount(_SetItemCount ev, Emitter<_State> emit) {
|
||||||
|
_log.info(ev);
|
||||||
|
final next = Map.of(state.itemCounts);
|
||||||
|
next[ev.collection.id] = ev.value;
|
||||||
|
emit(state.copyWith(itemCounts: next));
|
||||||
|
}
|
||||||
|
|
||||||
void _onSetError(_SetError ev, Emitter<_State> emit) {
|
void _onSetError(_SetError ev, Emitter<_State> emit) {
|
||||||
_log.info(ev);
|
_log.info(ev);
|
||||||
emit(state.copyWith(error: ExceptionEvent(ev.error, ev.stackTrace)));
|
emit(state.copyWith(error: ExceptionEvent(ev.error, ev.stackTrace)));
|
||||||
|
@ -122,6 +147,7 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
|
||||||
final CollectionsController controller;
|
final CollectionsController controller;
|
||||||
final PrefController prefController;
|
final PrefController prefController;
|
||||||
|
|
||||||
StreamSubscription<int>? _homeAlbumsSortSubscription;
|
final _subscriptions = <StreamSubscription>[];
|
||||||
|
final _itemSubscriptions = <StreamSubscription>[];
|
||||||
var _isHandlingError = false;
|
var _isHandlingError = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ class _State {
|
||||||
required this.isLoading,
|
required this.isLoading,
|
||||||
required this.transformedItems,
|
required this.transformedItems,
|
||||||
required this.selectedItems,
|
required this.selectedItems,
|
||||||
|
required this.itemCounts,
|
||||||
this.error,
|
this.error,
|
||||||
required this.removeError,
|
required this.removeError,
|
||||||
});
|
});
|
||||||
|
@ -20,6 +21,7 @@ class _State {
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
transformedItems: [],
|
transformedItems: [],
|
||||||
selectedItems: {},
|
selectedItems: {},
|
||||||
|
itemCounts: {},
|
||||||
removeError: null,
|
removeError: null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -32,6 +34,7 @@ class _State {
|
||||||
final bool isLoading;
|
final bool isLoading;
|
||||||
final List<_Item> transformedItems;
|
final List<_Item> transformedItems;
|
||||||
final Set<_Item> selectedItems;
|
final Set<_Item> selectedItems;
|
||||||
|
final Map<String, int> itemCounts;
|
||||||
|
|
||||||
final ExceptionEvent? error;
|
final ExceptionEvent? error;
|
||||||
final ExceptionEvent? removeError;
|
final ExceptionEvent? removeError;
|
||||||
|
@ -112,6 +115,17 @@ class _SetCollectionSort implements _Event {
|
||||||
final collection_util.CollectionSort sort;
|
final collection_util.CollectionSort sort;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@toString
|
||||||
|
class _SetItemCount implements _Event {
|
||||||
|
const _SetItemCount(this.collection, this.value);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => _$toString();
|
||||||
|
|
||||||
|
final Collection collection;
|
||||||
|
final int value;
|
||||||
|
}
|
||||||
|
|
||||||
@toString
|
@toString
|
||||||
class _SetError implements _Event {
|
class _SetError implements _Event {
|
||||||
const _SetError(this.error, [this.stackTrace]);
|
const _SetError(this.error, [this.stackTrace]);
|
||||||
|
|
|
@ -11,9 +11,6 @@ enum _ItemType {
|
||||||
class _Item implements SelectableItemMetadata {
|
class _Item implements SelectableItemMetadata {
|
||||||
_Item(this.collection)
|
_Item(this.collection)
|
||||||
: isShared = collection.shares.isNotEmpty || !collection.isOwned {
|
: isShared = collection.shares.isNotEmpty || !collection.isOwned {
|
||||||
if (collection.count != null) {
|
|
||||||
_subtitle = L10n.global().albumSize(collection.count!);
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
_coverUrl = collection.getCoverUrl(k.coverSize, k.coverSize);
|
_coverUrl = collection.getCoverUrl(k.coverSize, k.coverSize);
|
||||||
} catch (e, stackTrace) {
|
} catch (e, stackTrace) {
|
||||||
|
@ -35,7 +32,15 @@ class _Item implements SelectableItemMetadata {
|
||||||
|
|
||||||
String get name => collection.name;
|
String get name => collection.name;
|
||||||
|
|
||||||
String? get subtitle => _subtitle;
|
String? getSubtitle({
|
||||||
|
int? itemCountOverride,
|
||||||
|
}) {
|
||||||
|
if (collection.count != null) {
|
||||||
|
return L10n.global().albumSize(itemCountOverride ?? collection.count!);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String? get coverUrl => _coverUrl;
|
String? get coverUrl => _coverUrl;
|
||||||
|
|
||||||
|
@ -64,7 +69,6 @@ class _Item implements SelectableItemMetadata {
|
||||||
final Collection collection;
|
final Collection collection;
|
||||||
final bool isShared;
|
final bool isShared;
|
||||||
|
|
||||||
String? _subtitle;
|
|
||||||
String? _coverUrl;
|
String? _coverUrl;
|
||||||
late _ItemType _itemType;
|
late _ItemType _itemType;
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,6 +129,7 @@ class _ItemView extends StatelessWidget {
|
||||||
const _ItemView({
|
const _ItemView({
|
||||||
required this.account,
|
required this.account,
|
||||||
required this.item,
|
required this.item,
|
||||||
|
this.collectionItemCountOverride,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -152,7 +153,8 @@ class _ItemView extends StatelessWidget {
|
||||||
if (item.isShared) {
|
if (item.isShared) {
|
||||||
subtitle = "${L10n.global().albumSharedLabel} | ";
|
subtitle = "${L10n.global().albumSharedLabel} | ";
|
||||||
}
|
}
|
||||||
subtitle += item.subtitle ?? "";
|
subtitle +=
|
||||||
|
item.getSubtitle(itemCountOverride: collectionItemCountOverride) ?? "";
|
||||||
return CollectionGridItem(
|
return CollectionGridItem(
|
||||||
cover: _CollectionCover(
|
cover: _CollectionCover(
|
||||||
account: account,
|
account: account,
|
||||||
|
@ -166,6 +168,7 @@ class _ItemView extends StatelessWidget {
|
||||||
|
|
||||||
final Account account;
|
final Account account;
|
||||||
final _Item item;
|
final _Item item;
|
||||||
|
final int? collectionItemCountOverride;
|
||||||
}
|
}
|
||||||
|
|
||||||
class _CollectionCover extends StatelessWidget {
|
class _CollectionCover extends StatelessWidget {
|
||||||
|
|
Loading…
Reference in a new issue