fix: Refactor labels structure

This commit is contained in:
Anton Stubenbord
2023-04-05 19:44:58 +02:00
parent a2388b014b
commit 79ccdd0946
35 changed files with 357 additions and 234 deletions

View File

@@ -1,19 +1,17 @@
import 'dart:async';
import 'dart:developer';
import 'package:collection/collection.dart';
import 'package:flutter/foundation.dart';
import 'package:hydrated_bloc/hydrated_bloc.dart';
import 'package:json_annotation/json_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/paged_document_view/cubit/document_paging_bloc_mixin.dart';
import 'package:paperless_mobile/features/settings/model/view_type.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:paperless_mobile/features/paged_document_view/cubit/paged_documents_state.dart';
import 'package:paperless_mobile/features/settings/model/view_type.dart';
part 'documents_state.dart';
part 'documents_cubit.g.dart';
part 'documents_state.dart';
class DocumentsCubit extends HydratedCubit<DocumentsState>
with DocumentPagingBlocMixin {
@@ -32,7 +30,7 @@ class DocumentsCubit extends HydratedCubit<DocumentsState>
storagePaths: _labelRepository.state.storagePaths,
tags: _labelRepository.state.tags,
)) {
notifier.subscribe(
notifier.addListener(
this,
onUpdated: (document) {
replace(document);
@@ -54,9 +52,9 @@ class DocumentsCubit extends HydratedCubit<DocumentsState>
);
},
);
_labelRepository.subscribe(
_labelRepository.addListener(
this,
onStateChanged: (labels) => emit(
onChanged: (labels) => emit(
state.copyWith(
correspondents: labels.correspondents,
documentTypes: labels.documentTypes,
@@ -120,8 +118,8 @@ class DocumentsCubit extends HydratedCubit<DocumentsState>
@override
Future<void> close() {
notifier.unsubscribe(this);
_labelRepository.unsubscribe(this);
notifier.removeListener(this);
_labelRepository.removeListener(this);
return super.close();
}

View File

@@ -12,11 +12,9 @@ import 'package:paperless_mobile/features/documents/cubit/documents_cubit.dart';
import 'package:paperless_mobile/features/documents/view/widgets/adaptive_documents_view.dart';
import 'package:paperless_mobile/features/documents/view/widgets/documents_empty_state.dart';
import 'package:paperless_mobile/features/documents/view/widgets/search/document_filter_panel.dart';
import 'package:paperless_mobile/features/documents/view/widgets/selection/bulk_delete_confirmation_dialog.dart';
import 'package:paperless_mobile/features/documents/view/widgets/selection/document_selection_sliver_app_bar.dart';
import 'package:paperless_mobile/features/documents/view/widgets/selection/view_type_selection_widget.dart';
import 'package:paperless_mobile/features/documents/view/widgets/sort_documents_button.dart';
import 'package:paperless_mobile/features/labels/cubit/providers/labels_bloc_provider.dart';
import 'package:paperless_mobile/features/saved_view/cubit/saved_view_cubit.dart';
import 'package:paperless_mobile/features/saved_view/view/add_saved_view_page.dart';
import 'package:paperless_mobile/features/saved_view/view/saved_view_list.dart';
@@ -358,6 +356,10 @@ class _DocumentsPageState extends State<DocumentsPage>
isLabelClickable: true,
isLoading: state.isLoading,
selectedDocumentIds: state.selectedIds,
correspondents: state.correspondents,
documentTypes: state.documentTypes,
tags: state.tags,
storagePaths: state.storagePaths,
);
},
),
@@ -391,10 +393,16 @@ class _DocumentsPageState extends State<DocumentsPage>
void _onCreateSavedView(DocumentFilter filter) async {
final newView = await Navigator.of(context).push<SavedView?>(
MaterialPageRoute(
builder: (context) => LabelsBlocProvider(
child: AddSavedViewPage(
currentFilter: filter,
),
builder: (context) => BlocBuilder<SavedViewCubit, SavedViewState>(
builder: (context, state) {
return AddSavedViewPage(
currentFilter: filter,
correspondents: state.correspondents,
documentTypes: state.documentTypes,
storagePaths: state.storagePaths,
tags: state.tags,
);
},
),
),
);
@@ -428,12 +436,19 @@ class _DocumentsPageState extends State<DocumentsPage>
snapSizes: const [0.9, 1],
initialChildSize: .9,
maxChildSize: 1,
builder: (context, controller) => LabelsBlocProvider(
child: DocumentFilterPanel(
initialFilter: context.read<DocumentsCubit>().state.filter,
scrollController: controller,
draggableSheetController: draggableSheetController,
),
builder: (context, controller) =>
BlocBuilder<DocumentsCubit, DocumentsState>(
builder: (context, state) {
return DocumentFilterPanel(
initialFilter: context.read<DocumentsCubit>().state.filter,
scrollController: controller,
draggableSheetController: draggableSheetController,
correspondents: state.correspondents,
documentTypes: state.documentTypes,
storagePaths: state.storagePaths,
tags: state.tags,
);
},
),
),
),

View File

@@ -119,7 +119,7 @@ class DocumentDetailedItem extends DocumentItem {
textStyle: Theme.of(context).textTheme.titleSmall?.apply(
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
correspondent: context.read<DocumentsCubit>().correspondent,
correspondent: correspondents[document.correspondent],
),
],
).paddedLTRB(8, 0, 8, 4),
@@ -134,13 +134,13 @@ class DocumentDetailedItem extends DocumentItem {
textStyle: Theme.of(context).textTheme.titleSmall?.apply(
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
documentTypeId: document.documentType,
documentType: documentTypes[document.documentType],
),
],
).paddedLTRB(8, 0, 8, 4),
TagsWidget(
isMultiLine: false,
tagIds: document.tags,
tags: document.tags.map((e) => tags[e]!).toList(),
).padded(),
if (highlights != null)
Html(

View File

@@ -49,6 +49,11 @@ class DocumentFilterForm extends StatefulWidget {
final DocumentFilter initialFilter;
final ScrollController? scrollController;
final EdgeInsets padding;
final Map<int, Correspondent> correspondents;
final Map<int, DocumentType> documentTypes;
final Map<int, Tag> tags;
final Map<int, StoragePath> storagePaths;
const DocumentFilterForm({
super.key,
this.header,
@@ -56,6 +61,10 @@ class DocumentFilterForm extends StatefulWidget {
required this.initialFilter,
this.scrollController,
this.padding = const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
required this.correspondents,
required this.documentTypes,
required this.tags,
required this.storagePaths,
});
@override
@@ -145,47 +154,35 @@ class _DocumentFilterFormState extends State<DocumentFilterForm> {
}
Widget _buildDocumentTypeFormField() {
return BlocBuilder<LabelCubit<DocumentType>, LabelState<DocumentType>>(
builder: (context, state) {
return LabelFormField<DocumentType>(
formBuilderState: widget.formKey.currentState,
name: DocumentFilterForm.fkDocumentType,
labelOptions: state.labels,
textFieldLabel: S.of(context)!.documentType,
initialValue: widget.initialFilter.documentType,
prefixIcon: const Icon(Icons.description_outlined),
);
},
return LabelFormField<DocumentType>(
formBuilderState: widget.formKey.currentState,
name: DocumentFilterForm.fkDocumentType,
labelOptions: widget.documentTypes,
textFieldLabel: S.of(context)!.documentType,
initialValue: widget.initialFilter.documentType,
prefixIcon: const Icon(Icons.description_outlined),
);
}
Widget _buildCorrespondentFormField() {
return BlocBuilder<LabelCubit<Correspondent>, LabelState<Correspondent>>(
builder: (context, state) {
return LabelFormField<Correspondent>(
formBuilderState: widget.formKey.currentState,
name: DocumentFilterForm.fkCorrespondent,
labelOptions: state.labels,
textFieldLabel: S.of(context)!.correspondent,
initialValue: widget.initialFilter.correspondent,
prefixIcon: const Icon(Icons.person_outline),
);
},
return LabelFormField<Correspondent>(
formBuilderState: widget.formKey.currentState,
name: DocumentFilterForm.fkCorrespondent,
labelOptions: widget.correspondents,
textFieldLabel: S.of(context)!.correspondent,
initialValue: widget.initialFilter.correspondent,
prefixIcon: const Icon(Icons.person_outline),
);
}
Widget _buildStoragePathFormField() {
return BlocBuilder<LabelCubit<StoragePath>, LabelState<StoragePath>>(
builder: (context, state) {
return LabelFormField<StoragePath>(
formBuilderState: widget.formKey.currentState,
name: DocumentFilterForm.fkStoragePath,
labelOptions: state.labels,
textFieldLabel: S.of(context)!.storagePath,
initialValue: widget.initialFilter.storagePath,
prefixIcon: const Icon(Icons.folder_outlined),
);
},
return LabelFormField<StoragePath>(
formBuilderState: widget.formKey.currentState,
name: DocumentFilterForm.fkStoragePath,
labelOptions: widget.storagePaths,
textFieldLabel: S.of(context)!.storagePath,
initialValue: widget.initialFilter.storagePath,
prefixIcon: const Icon(Icons.folder_outlined),
);
}
@@ -197,16 +194,12 @@ class _DocumentFilterFormState extends State<DocumentFilterForm> {
);
}
BlocBuilder<LabelCubit<Tag>, LabelState<Tag>> _buildTagsFormField() {
return BlocBuilder<LabelCubit<Tag>, LabelState<Tag>>(
builder: (context, state) {
return TagFormField(
name: DocumentModel.tagsKey,
initialValue: widget.initialFilter.tags,
allowCreation: false,
selectableOptions: state.labels,
);
},
Widget _buildTagsFormField() {
return TagFormField(
name: DocumentModel.tagsKey,
initialValue: widget.initialFilter.tags,
allowCreation: false,
selectableOptions: widget.tags,
);
}
}

View File

@@ -13,11 +13,20 @@ class DocumentFilterPanel extends StatefulWidget {
final DocumentFilter initialFilter;
final ScrollController scrollController;
final DraggableScrollableController draggableSheetController;
final Map<int, Correspondent> correspondents;
final Map<int, DocumentType> documentTypes;
final Map<int, Tag> tags;
final Map<int, StoragePath> storagePaths;
const DocumentFilterPanel({
Key? key,
required this.initialFilter,
required this.scrollController,
required this.draggableSheetController,
required this.correspondents,
required this.documentTypes,
required this.tags,
required this.storagePaths,
}) : super(key: key);
@override
@@ -38,10 +47,8 @@ class _DocumentFilterPanelState extends State<DocumentFilterPanel> {
void animateTitleByDrag() {
setState(
() {
_heightAnimationValue = dp(
((max(0.9, widget.draggableSheetController.size) - 0.9) / 0.1), 5);
},
() => _heightAnimationValue =
dp(((max(0.9, widget.draggableSheetController.size) - 0.9) / 0.1), 5),
);
}
@@ -96,6 +103,10 @@ class _DocumentFilterPanelState extends State<DocumentFilterPanel> {
scrollController: widget.scrollController,
initialFilter: widget.initialFilter,
header: _buildPanelHeader(),
correspondents: widget.correspondents,
documentTypes: widget.documentTypes,
storagePaths: widget.storagePaths,
tags: widget.tags,
),
),
);

View File

@@ -10,6 +10,10 @@ import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
class SortFieldSelectionBottomSheet extends StatefulWidget {
final SortOrder initialSortOrder;
final SortField? initialSortField;
final Map<int, Correspondent> correspondents;
final Map<int, DocumentType> documentTypes;
final Map<int, Tag> tags;
final Map<int, StoragePath> storagePaths;
final Future Function(SortField? field, SortOrder order) onSubmit;
@@ -18,6 +22,10 @@ class SortFieldSelectionBottomSheet extends StatefulWidget {
required this.initialSortOrder,
required this.initialSortField,
required this.onSubmit,
required this.correspondents,
required this.documentTypes,
required this.tags,
required this.storagePaths,
});
@override
@@ -67,31 +75,20 @@ class _SortFieldSelectionBottomSheetState
Column(
children: [
_buildSortOption(SortField.archiveSerialNumber),
BlocBuilder<LabelCubit<Correspondent>,
LabelState<Correspondent>>(
builder: (context, state) {
return _buildSortOption(
SortField.correspondentName,
enabled: state.labels.values.fold<bool>(
false,
(previousValue, element) =>
previousValue ||
(element.documentCount ?? 0) > 0),
);
},
_buildSortOption(
SortField.correspondentName,
enabled: widget.correspondents.values.fold<bool>(
false,
(previousValue, element) =>
previousValue || (element.documentCount ?? 0) > 0),
),
_buildSortOption(SortField.title),
BlocBuilder<LabelCubit<DocumentType>, LabelState<DocumentType>>(
builder: (context, state) {
return _buildSortOption(
SortField.documentType,
enabled: state.labels.values.fold<bool>(
false,
(previousValue, element) =>
previousValue ||
(element.documentCount ?? 0) > 0),
);
},
_buildSortOption(
SortField.documentType,
enabled: widget.documentTypes.values.fold<bool>(
false,
(previousValue, element) =>
previousValue || (element.documentCount ?? 0) > 0),
),
_buildSortOption(SortField.created),
_buildSortOption(SortField.added),

View File

@@ -57,6 +57,10 @@ class SortDocumentsButton extends StatelessWidget {
sortOrder: order,
),
),
correspondents: state.correspondents,
documentTypes: state.documentTypes,
storagePaths: state.storagePaths,
tags: state.tags,
),
),
),