mirror of
https://github.com/Xevion/paperless-mobile.git
synced 2025-12-06 19:15:47 -06:00
feat: fix bug where tags were overwritten
This commit is contained in:
@@ -2,6 +2,7 @@ import 'dart:async';
|
|||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:paperless_api/paperless_api.dart';
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
|
import 'package:paperless_mobile/features/logging/data/logger.dart';
|
||||||
|
|
||||||
class LabelRepository extends ChangeNotifier {
|
class LabelRepository extends ChangeNotifier {
|
||||||
final PaperlessLabelsApi _api;
|
final PaperlessLabelsApi _api;
|
||||||
@@ -57,8 +58,29 @@ class LabelRepository extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<Iterable<Tag>> findAllTags([Iterable<int>? ids]) async {
|
Future<Iterable<Tag>> findAllTags([Iterable<int>? 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);
|
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();
|
notifyListeners();
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import 'package:freezed_annotation/freezed_annotation.dart';
|
|||||||
import 'package:paperless_api/paperless_api.dart';
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
import 'package:paperless_mobile/core/notifier/document_changed_notifier.dart';
|
import 'package:paperless_mobile/core/notifier/document_changed_notifier.dart';
|
||||||
import 'package:paperless_mobile/core/repository/label_repository.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_state.dart';
|
||||||
part 'document_edit_cubit.freezed.dart';
|
part 'document_edit_cubit.freezed.dart';
|
||||||
@@ -25,37 +26,91 @@ class DocumentEditCubit extends Cubit<DocumentEditState> {
|
|||||||
_notifier.addListener(
|
_notifier.addListener(
|
||||||
this,
|
this,
|
||||||
onUpdated: (doc) {
|
onUpdated: (doc) {
|
||||||
emit(state.copyWith(document: doc));
|
emit(state.copyWith(
|
||||||
|
document: doc,
|
||||||
|
suggestions: null,
|
||||||
|
));
|
||||||
|
loadFieldSuggestions();
|
||||||
},
|
},
|
||||||
ids: [document.id],
|
ids: [document.id],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> updateDocument(DocumentModel document) async {
|
Future<void> updateDocument(DocumentModel document) async {
|
||||||
|
logger.fi(
|
||||||
|
"Updating document ${document.id}...",
|
||||||
|
className: runtimeType.toString(),
|
||||||
|
methodName: "updateDocument",
|
||||||
|
);
|
||||||
final updated = await _docsApi.update(document);
|
final updated = await _docsApi.update(document);
|
||||||
|
logger.fi(
|
||||||
|
"Document ${document.id} successfully updated.",
|
||||||
|
className: runtimeType.toString(),
|
||||||
|
methodName: "updateDocument",
|
||||||
|
);
|
||||||
_notifier.notifyUpdated(updated);
|
_notifier.notifyUpdated(updated);
|
||||||
|
|
||||||
// Reload changed labels (documentCount property changes with removal/add)
|
// Reload changed labels (documentCount property changes with removal/add)
|
||||||
if (document.documentType != _initialDocument.documentType) {
|
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(
|
_labelRepository.findDocumentType(
|
||||||
(document.documentType ?? _initialDocument.documentType)!);
|
(document.documentType ?? _initialDocument.documentType)!,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (document.correspondent != _initialDocument.correspondent) {
|
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(
|
_labelRepository.findCorrespondent(
|
||||||
(document.correspondent ?? _initialDocument.correspondent)!);
|
(document.correspondent ?? _initialDocument.correspondent)!);
|
||||||
}
|
}
|
||||||
if (document.storagePath != _initialDocument.storagePath) {
|
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(
|
_labelRepository.findStoragePath(
|
||||||
(document.storagePath ?? _initialDocument.storagePath)!);
|
(document.storagePath ?? _initialDocument.storagePath)!);
|
||||||
}
|
}
|
||||||
if (!const DeepCollectionEquality.unordered()
|
if (!const DeepCollectionEquality.unordered()
|
||||||
.equals(document.tags, _initialDocument.tags)) {
|
.equals(document.tags.toList(), _initialDocument.tags.toList())) {
|
||||||
_labelRepository.findAllTags(document.tags);
|
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<void> loadFieldSuggestions() async {
|
Future<void> loadFieldSuggestions() async {
|
||||||
|
logger.fi(
|
||||||
|
"Loading suggestions for document ${state.document.id}...",
|
||||||
|
className: runtimeType.toString(),
|
||||||
|
methodName: "loadFieldSuggestions",
|
||||||
|
);
|
||||||
final suggestions = await _docsApi.findSuggestions(state.document);
|
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));
|
emit(state.copyWith(suggestions: suggestions));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -183,8 +183,12 @@ class _DocumentEditPageState extends State<DocumentEditPage>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Padding _buildEditForm(BuildContext context, DocumentEditState state,
|
Padding _buildEditForm(
|
||||||
FieldSuggestions? filteredSuggestions, UserModel currentUser) {
|
BuildContext context,
|
||||||
|
DocumentEditState state,
|
||||||
|
FieldSuggestions? filteredSuggestions,
|
||||||
|
UserModel currentUser,
|
||||||
|
) {
|
||||||
final labelRepository = context.watch<LabelRepository>();
|
final labelRepository = context.watch<LabelRepository>();
|
||||||
|
|
||||||
return Padding(
|
return Padding(
|
||||||
|
|||||||
@@ -105,14 +105,18 @@ class _DocumentViewState extends State<DocumentView> {
|
|||||||
body: PdfView(
|
body: PdfView(
|
||||||
controller: _controller,
|
controller: _controller,
|
||||||
onDocumentLoaded: (document) {
|
onDocumentLoaded: (document) {
|
||||||
setState(() {
|
if (mounted) {
|
||||||
_totalPages = document.pagesCount;
|
setState(() {
|
||||||
});
|
_totalPages = document.pagesCount;
|
||||||
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onPageChanged: (page) {
|
onPageChanged: (page) {
|
||||||
setState(() {
|
if (mounted) {
|
||||||
_currentPage = page;
|
setState(() {
|
||||||
});
|
_currentPage = page;
|
||||||
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -10,16 +10,16 @@ class LabelCubit extends Cubit<LabelState> {
|
|||||||
final LabelRepository labelRepository;
|
final LabelRepository labelRepository;
|
||||||
|
|
||||||
LabelCubit(this.labelRepository) : super(const LabelState()) {
|
LabelCubit(this.labelRepository) : super(const LabelState()) {
|
||||||
labelRepository.addListener(
|
labelRepository.addListener(_updateStateListener);
|
||||||
() {
|
}
|
||||||
emit(state.copyWith(
|
|
||||||
correspondents: labelRepository.correspondents,
|
void _updateStateListener() {
|
||||||
documentTypes: labelRepository.documentTypes,
|
emit(state.copyWith(
|
||||||
storagePaths: labelRepository.storagePaths,
|
correspondents: labelRepository.correspondents,
|
||||||
tags: labelRepository.tags,
|
documentTypes: labelRepository.documentTypes,
|
||||||
));
|
storagePaths: labelRepository.storagePaths,
|
||||||
},
|
tags: labelRepository.tags,
|
||||||
);
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> reload({
|
Future<void> reload({
|
||||||
@@ -130,6 +130,7 @@ class LabelCubit extends Cubit<LabelState> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> close() {
|
Future<void> close() {
|
||||||
|
labelRepository.removeListener(_updateStateListener);
|
||||||
return super.close();
|
return super.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,8 +117,12 @@ class TagsFormField extends StatelessWidget {
|
|||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
itemCount: displayedSuggestions.length,
|
itemCount: displayedSuggestions.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
|
print(options);
|
||||||
final suggestion =
|
final suggestion =
|
||||||
options[displayedSuggestions.elementAt(index)]!;
|
options[displayedSuggestions.elementAt(index)];
|
||||||
|
if (suggestion == null) {
|
||||||
|
return SizedBox.shrink();
|
||||||
|
}
|
||||||
return ColoredChipWrapper(
|
return ColoredChipWrapper(
|
||||||
child: ActionChip(
|
child: ActionChip(
|
||||||
label: Text(suggestion.name),
|
label: Text(suggestion.name),
|
||||||
|
|||||||
Reference in New Issue
Block a user