From 0bec1d594a7542ac083e166473bce3c55694f40e Mon Sep 17 00:00:00 2001 From: Anton Stubenbord Date: Sat, 16 Dec 2023 14:10:09 +0100 Subject: [PATCH] feat: fix bug where tags were overwritten --- lib/core/repository/label_repository.dart | 24 ++++++- .../cubit/document_edit_cubit.dart | 63 +++++++++++++++++-- .../view/document_edit_page.dart | 8 ++- .../documents/view/pages/document_view.dart | 16 +++-- lib/features/labels/cubit/label_cubit.dart | 21 ++++--- .../tags/view/widgets/tags_form_field.dart | 6 +- 6 files changed, 114 insertions(+), 24 deletions(-) diff --git a/lib/core/repository/label_repository.dart b/lib/core/repository/label_repository.dart index 8456454..c9790b8 100644 --- a/lib/core/repository/label_repository.dart +++ b/lib/core/repository/label_repository.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:flutter/foundation.dart'; import 'package:paperless_api/paperless_api.dart'; +import 'package:paperless_mobile/features/logging/data/logger.dart'; class LabelRepository extends ChangeNotifier { final PaperlessLabelsApi _api; @@ -57,8 +58,29 @@ class LabelRepository extends ChangeNotifier { } Future> findAllTags([Iterable? ids]) async { + logger.fd( + "Loading ${ids?.isEmpty ?? true ? "all" : "a subset of"} tags" + "${ids?.isEmpty ?? true ? "" : " (${ids!.join(",")})"}...", + className: runtimeType.toString(), + methodName: "findAllTags", + ); final data = await _api.getTags(ids); - tags = {for (var tag in data) tag.id!: tag}; + if (ids?.isNotEmpty ?? false) { + logger.fd( + "Successfully updated subset of tags: ${ids!.join(",")}", + className: runtimeType.toString(), + methodName: "findAllTags", + ); + // Only update the tags that were requested, keep existing ones. + tags = {...tags, for (var tag in data) tag.id!: tag}; + } else { + logger.fd( + "Successfully updated all tags.", + className: runtimeType.toString(), + methodName: "findAllTags", + ); + tags = {for (var tag in data) tag.id!: tag}; + } notifyListeners(); return data; } diff --git a/lib/features/document_edit/cubit/document_edit_cubit.dart b/lib/features/document_edit/cubit/document_edit_cubit.dart index 839bf98..97376ea 100644 --- a/lib/features/document_edit/cubit/document_edit_cubit.dart +++ b/lib/features/document_edit/cubit/document_edit_cubit.dart @@ -5,6 +5,7 @@ import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:paperless_api/paperless_api.dart'; import 'package:paperless_mobile/core/notifier/document_changed_notifier.dart'; import 'package:paperless_mobile/core/repository/label_repository.dart'; +import 'package:paperless_mobile/features/logging/data/logger.dart'; part 'document_edit_state.dart'; part 'document_edit_cubit.freezed.dart'; @@ -25,37 +26,91 @@ class DocumentEditCubit extends Cubit { _notifier.addListener( this, onUpdated: (doc) { - emit(state.copyWith(document: doc)); + emit(state.copyWith( + document: doc, + suggestions: null, + )); + loadFieldSuggestions(); }, ids: [document.id], ); } Future updateDocument(DocumentModel document) async { + logger.fi( + "Updating document ${document.id}...", + className: runtimeType.toString(), + methodName: "updateDocument", + ); final updated = await _docsApi.update(document); + logger.fi( + "Document ${document.id} successfully updated.", + className: runtimeType.toString(), + methodName: "updateDocument", + ); _notifier.notifyUpdated(updated); // Reload changed labels (documentCount property changes with removal/add) if (document.documentType != _initialDocument.documentType) { + logger.fd( + "Document type assigned to document ${document.id} has changed " + "(${_initialDocument.documentType} -> ${document.documentType}). " + "Reloading document type ${document.documentType}...", + className: runtimeType.toString(), + methodName: "updateDocument", + ); _labelRepository.findDocumentType( - (document.documentType ?? _initialDocument.documentType)!); + (document.documentType ?? _initialDocument.documentType)!, + ); } if (document.correspondent != _initialDocument.correspondent) { + logger.fd( + "Correspondent assigned to document ${document.id} has changed " + "(${_initialDocument.correspondent} -> ${document.correspondent}). " + "Reloading correspondent ${document.correspondent}...", + className: runtimeType.toString(), + methodName: "updateDocument", + ); _labelRepository.findCorrespondent( (document.correspondent ?? _initialDocument.correspondent)!); } if (document.storagePath != _initialDocument.storagePath) { + logger.fd( + "Storage path assigned to document ${document.id} has changed " + "(${_initialDocument.storagePath} -> ${document.storagePath}). " + "Reloading storage path ${document.storagePath}...", + className: runtimeType.toString(), + methodName: "updateDocument", + ); _labelRepository.findStoragePath( (document.storagePath ?? _initialDocument.storagePath)!); } if (!const DeepCollectionEquality.unordered() - .equals(document.tags, _initialDocument.tags)) { - _labelRepository.findAllTags(document.tags); + .equals(document.tags.toList(), _initialDocument.tags.toList())) { + final tagsToReload = {...document.tags, ..._initialDocument.tags}; + logger.fd( + "Tags assigned to document ${document.id} have changed " + "(${_initialDocument.tags.join(",")} -> ${document.tags.join(",")}). " + "Reloading tags ${tagsToReload.join(",")}...", + className: runtimeType.toString(), + methodName: "updateDocument", + ); + _labelRepository.findAllTags(tagsToReload); } } Future loadFieldSuggestions() async { + logger.fi( + "Loading suggestions for document ${state.document.id}...", + className: runtimeType.toString(), + methodName: "loadFieldSuggestions", + ); final suggestions = await _docsApi.findSuggestions(state.document); + logger.fi( + "Found ${suggestions.suggestionsCount} suggestions for document ${state.document.id}.", + className: runtimeType.toString(), + methodName: "loadFieldSuggestions", + ); emit(state.copyWith(suggestions: suggestions)); } diff --git a/lib/features/document_edit/view/document_edit_page.dart b/lib/features/document_edit/view/document_edit_page.dart index 8930727..eaa16a9 100644 --- a/lib/features/document_edit/view/document_edit_page.dart +++ b/lib/features/document_edit/view/document_edit_page.dart @@ -183,8 +183,12 @@ class _DocumentEditPageState extends State ); } - Padding _buildEditForm(BuildContext context, DocumentEditState state, - FieldSuggestions? filteredSuggestions, UserModel currentUser) { + Padding _buildEditForm( + BuildContext context, + DocumentEditState state, + FieldSuggestions? filteredSuggestions, + UserModel currentUser, + ) { final labelRepository = context.watch(); return Padding( diff --git a/lib/features/documents/view/pages/document_view.dart b/lib/features/documents/view/pages/document_view.dart index 2432259..ececd57 100644 --- a/lib/features/documents/view/pages/document_view.dart +++ b/lib/features/documents/view/pages/document_view.dart @@ -105,14 +105,18 @@ class _DocumentViewState extends State { body: PdfView( controller: _controller, onDocumentLoaded: (document) { - setState(() { - _totalPages = document.pagesCount; - }); + if (mounted) { + setState(() { + _totalPages = document.pagesCount; + }); + } }, onPageChanged: (page) { - setState(() { - _currentPage = page; - }); + if (mounted) { + setState(() { + _currentPage = page; + }); + } }, ), ); diff --git a/lib/features/labels/cubit/label_cubit.dart b/lib/features/labels/cubit/label_cubit.dart index d9efbe4..e3ce900 100644 --- a/lib/features/labels/cubit/label_cubit.dart +++ b/lib/features/labels/cubit/label_cubit.dart @@ -10,16 +10,16 @@ class LabelCubit extends Cubit { final LabelRepository labelRepository; LabelCubit(this.labelRepository) : super(const LabelState()) { - labelRepository.addListener( - () { - emit(state.copyWith( - correspondents: labelRepository.correspondents, - documentTypes: labelRepository.documentTypes, - storagePaths: labelRepository.storagePaths, - tags: labelRepository.tags, - )); - }, - ); + labelRepository.addListener(_updateStateListener); + } + + void _updateStateListener() { + emit(state.copyWith( + correspondents: labelRepository.correspondents, + documentTypes: labelRepository.documentTypes, + storagePaths: labelRepository.storagePaths, + tags: labelRepository.tags, + )); } Future reload({ @@ -130,6 +130,7 @@ class LabelCubit extends Cubit { @override Future close() { + labelRepository.removeListener(_updateStateListener); return super.close(); } } diff --git a/lib/features/labels/tags/view/widgets/tags_form_field.dart b/lib/features/labels/tags/view/widgets/tags_form_field.dart index ba728e0..6b12b02 100644 --- a/lib/features/labels/tags/view/widgets/tags_form_field.dart +++ b/lib/features/labels/tags/view/widgets/tags_form_field.dart @@ -117,8 +117,12 @@ class TagsFormField extends StatelessWidget { scrollDirection: Axis.horizontal, itemCount: displayedSuggestions.length, itemBuilder: (context, index) { + print(options); final suggestion = - options[displayedSuggestions.elementAt(index)]!; + options[displayedSuggestions.elementAt(index)]; + if (suggestion == null) { + return SizedBox.shrink(); + } return ColoredChipWrapper( child: ActionChip( label: Text(suggestion.name),