mirror of
https://github.com/Xevion/paperless-mobile.git
synced 2025-12-14 22:12:18 -06:00
fix: Refactor labels structure
This commit is contained in:
@@ -23,8 +23,8 @@ class DocumentChangedNotifier {
|
|||||||
_deleted.add(deleted);
|
_deleted.add(deleted);
|
||||||
}
|
}
|
||||||
|
|
||||||
void subscribe(
|
void addListener(
|
||||||
dynamic subscriber, {
|
Object subscriber, {
|
||||||
DocumentChangedCallback? onUpdated,
|
DocumentChangedCallback? onUpdated,
|
||||||
DocumentChangedCallback? onDeleted,
|
DocumentChangedCallback? onDeleted,
|
||||||
}) {
|
}) {
|
||||||
@@ -41,7 +41,7 @@ class DocumentChangedNotifier {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void unsubscribe(dynamic subscriber) {
|
void removeListener(Object subscriber) {
|
||||||
_subscribers[subscriber]?.forEach((element) {
|
_subscribers[subscriber]?.forEach((element) {
|
||||||
element.cancel();
|
element.cancel();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ class LabelRepository extends HydratedCubit<LabelRepositoryState> {
|
|||||||
final PaperlessLabelsApi _api;
|
final PaperlessLabelsApi _api;
|
||||||
final Map<Object, StreamSubscription> _subscribers = {};
|
final Map<Object, StreamSubscription> _subscribers = {};
|
||||||
|
|
||||||
void subscribe(
|
LabelRepository(this._api) : super(const LabelRepositoryState());
|
||||||
|
|
||||||
|
void addListener(
|
||||||
Object source, {
|
Object source, {
|
||||||
required void Function(LabelRepositoryState) onChanged,
|
required void Function(LabelRepositoryState) onChanged,
|
||||||
}) {
|
}) {
|
||||||
@@ -18,12 +20,19 @@ class LabelRepository extends HydratedCubit<LabelRepositoryState> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void unsubscribe(Object source) async {
|
void removeListener(Object source) async {
|
||||||
await _subscribers[source]?.cancel();
|
await _subscribers[source]?.cancel();
|
||||||
_subscribers.remove(source);
|
_subscribers.remove(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
LabelRepository(this._api) : super(const LabelRepositoryState());
|
Future<void> initialize() {
|
||||||
|
return Future.wait([
|
||||||
|
findAllCorrespondents(),
|
||||||
|
findAllDocumentTypes(),
|
||||||
|
findAllStoragePaths(),
|
||||||
|
findAllTags(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
Future<Tag> createTag(Tag object) async {
|
Future<Tag> createTag(Tag object) async {
|
||||||
final created = await _api.saveTag(object);
|
final created = await _api.saveTag(object);
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ class DocumentBulkActionCubit extends Cubit<DocumentBulkActionState> {
|
|||||||
tags: _labelRepository.state.tags,
|
tags: _labelRepository.state.tags,
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
_notifier.subscribe(
|
_notifier.addListener(
|
||||||
this,
|
this,
|
||||||
onDeleted: (document) {
|
onDeleted: (document) {
|
||||||
// Remove items from internal selection after the document was deleted.
|
// Remove items from internal selection after the document was deleted.
|
||||||
@@ -43,7 +43,7 @@ class DocumentBulkActionCubit extends Cubit<DocumentBulkActionState> {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
_labelRepository.subscribe(
|
_labelRepository.addListener(
|
||||||
this,
|
this,
|
||||||
onChanged: (labels) {
|
onChanged: (labels) {
|
||||||
emit(
|
emit(
|
||||||
@@ -142,8 +142,8 @@ class DocumentBulkActionCubit extends Cubit<DocumentBulkActionState> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> close() {
|
Future<void> close() {
|
||||||
_notifier.unsubscribe(this);
|
_notifier.removeListener(this);
|
||||||
_labelRepository.unsubscribe(this);
|
_labelRepository.removeListener(this);
|
||||||
return super.close();
|
return super.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ class DocumentDetailsCubit extends Cubit<DocumentDetailsState> {
|
|||||||
}) : super(DocumentDetailsState(
|
}) : super(DocumentDetailsState(
|
||||||
document: initialDocument,
|
document: initialDocument,
|
||||||
)) {
|
)) {
|
||||||
_notifier.subscribe(this, onUpdated: replace);
|
_notifier.addListener(this, onUpdated: replace);
|
||||||
_labelRepository.subscribe(
|
_labelRepository.addListener(
|
||||||
this,
|
this,
|
||||||
onChanged: (labels) => emit(
|
onChanged: (labels) => emit(
|
||||||
state.copyWith(
|
state.copyWith(
|
||||||
@@ -210,7 +210,7 @@ class DocumentDetailsCubit extends Cubit<DocumentDetailsState> {
|
|||||||
for (final element in _subscriptions) {
|
for (final element in _subscriptions) {
|
||||||
await element.cancel();
|
await element.cancel();
|
||||||
}
|
}
|
||||||
_notifier.unsubscribe(this);
|
_notifier.removeListener(this);
|
||||||
await super.close();
|
await super.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -176,6 +176,7 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
|
|||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) => SimilarDocumentsCubit(
|
create: (context) => SimilarDocumentsCubit(
|
||||||
|
context.read(),
|
||||||
context.read(),
|
context.read(),
|
||||||
context.read(),
|
context.read(),
|
||||||
documentId: state.document.id,
|
documentId: state.document.id,
|
||||||
@@ -186,7 +187,10 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
|
|||||||
document: state.document,
|
document: state.document,
|
||||||
itemSpacing: _itemSpacing,
|
itemSpacing: _itemSpacing,
|
||||||
queryString: widget.titleAndContentQueryString,
|
queryString: widget.titleAndContentQueryString,
|
||||||
|
availableCorrespondents: state.correspondents,
|
||||||
|
availableDocumentTypes: state.documentTypes,
|
||||||
|
availableTags: state.tags,
|
||||||
|
availableStoragePaths: state.storagePaths,
|
||||||
),
|
),
|
||||||
DocumentContentWidget(
|
DocumentContentWidget(
|
||||||
isFullContentLoaded: state.isFullContentLoaded,
|
isFullContentLoaded: state.isFullContentLoaded,
|
||||||
@@ -215,7 +219,7 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
|
|||||||
return BlocBuilder<DocumentDetailsCubit, DocumentDetailsState>(
|
return BlocBuilder<DocumentDetailsCubit, DocumentDetailsState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
final _filteredSuggestions =
|
final _filteredSuggestions =
|
||||||
state.suggestions.documentDifference(state.document);
|
state.suggestions?.documentDifference(state.document);
|
||||||
return BlocBuilder<ConnectivityCubit, ConnectivityState>(
|
return BlocBuilder<ConnectivityCubit, ConnectivityState>(
|
||||||
builder: (context, connectivityState) {
|
builder: (context, connectivityState) {
|
||||||
if (!connectivityState.isConnected) {
|
if (!connectivityState.isConnected) {
|
||||||
@@ -223,7 +227,7 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
|
|||||||
}
|
}
|
||||||
return b.Badge(
|
return b.Badge(
|
||||||
position: b.BadgePosition.topEnd(top: -12, end: -6),
|
position: b.BadgePosition.topEnd(top: -12, end: -6),
|
||||||
showBadge: _filteredSuggestions.hasSuggestions,
|
showBadge: _filteredSuggestions?.hasSuggestions ?? false,
|
||||||
child: Tooltip(
|
child: Tooltip(
|
||||||
message: S.of(context)!.editDocumentTooltip,
|
message: S.of(context)!.editDocumentTooltip,
|
||||||
preferBelow: false,
|
preferBelow: false,
|
||||||
@@ -234,7 +238,7 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
badgeContent: Text(
|
badgeContent: Text(
|
||||||
'${_filteredSuggestions.suggestionsCount}',
|
'${_filteredSuggestions?.suggestionsCount ?? 0}',
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
),
|
),
|
||||||
@@ -300,13 +304,10 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
|
|||||||
providers: [
|
providers: [
|
||||||
BlocProvider.value(
|
BlocProvider.value(
|
||||||
value: DocumentEditCubit(
|
value: DocumentEditCubit(
|
||||||
document,
|
context.read(),
|
||||||
documentsApi: context.read(),
|
context.read(),
|
||||||
correspondentRepository: context.read(),
|
context.read(),
|
||||||
documentTypeRepository: context.read(),
|
document: document,
|
||||||
storagePathRepository: context.read(),
|
|
||||||
tagRepository: context.read(),
|
|
||||||
notifier: context.read(),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
BlocProvider<DocumentDetailsCubit>.value(
|
BlocProvider<DocumentDetailsCubit>.value(
|
||||||
|
|||||||
@@ -32,10 +32,10 @@ class DocumentEditCubit extends Cubit<DocumentEditState> {
|
|||||||
tags: _labelRepository.state.tags,
|
tags: _labelRepository.state.tags,
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
_notifier.subscribe(this, onUpdated: replace);
|
_notifier.addListener(this, onUpdated: replace);
|
||||||
_labelRepository.subscribe(
|
_labelRepository.addListener(
|
||||||
this,
|
this,
|
||||||
onStateChanged: (labels) => emit(state.copyWith()),
|
onChanged: (labels) => emit(state.copyWith()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,7 +71,7 @@ class DocumentEditCubit extends Cubit<DocumentEditState> {
|
|||||||
for (final sub in _subscriptions) {
|
for (final sub in _subscriptions) {
|
||||||
sub.cancel();
|
sub.cancel();
|
||||||
}
|
}
|
||||||
_notifier.unsubscribe(this);
|
_notifier.removeListener(this);
|
||||||
return super.close();
|
return super.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
|||||||
import 'package:paperless_mobile/helpers/message_helpers.dart';
|
import 'package:paperless_mobile/helpers/message_helpers.dart';
|
||||||
|
|
||||||
class DocumentEditPage extends StatefulWidget {
|
class DocumentEditPage extends StatefulWidget {
|
||||||
final FieldSuggestions suggestions;
|
final FieldSuggestions? suggestions;
|
||||||
const DocumentEditPage({
|
const DocumentEditPage({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.suggestions,
|
required this.suggestions,
|
||||||
@@ -43,13 +43,13 @@ class _DocumentEditPageState extends State<DocumentEditPage> {
|
|||||||
final GlobalKey<FormBuilderState> _formKey = GlobalKey();
|
final GlobalKey<FormBuilderState> _formKey = GlobalKey();
|
||||||
bool _isSubmitLoading = false;
|
bool _isSubmitLoading = false;
|
||||||
|
|
||||||
late final FieldSuggestions _filteredSuggestions;
|
late final FieldSuggestions? _filteredSuggestions;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_filteredSuggestions = widget.suggestions
|
_filteredSuggestions = widget.suggestions
|
||||||
.documentDifference(context.read<DocumentEditCubit>().state.document);
|
?.documentDifference(context.read<DocumentEditCubit>().state.document);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -115,12 +115,14 @@ class _DocumentEditPageState extends State<DocumentEditPage> {
|
|||||||
excludeAllowed: false,
|
excludeAllowed: false,
|
||||||
name: fkTags,
|
name: fkTags,
|
||||||
selectableOptions: state.tags,
|
selectableOptions: state.tags,
|
||||||
suggestions: _filteredSuggestions.tags
|
suggestions: (_filteredSuggestions?.tags.toSet() ??
|
||||||
.toSet()
|
{})
|
||||||
.difference(state.document.tags.toSet())
|
.difference(state.document.tags.toSet())
|
||||||
.isNotEmpty
|
.isNotEmpty
|
||||||
? _buildSuggestionsSkeleton<int>(
|
? _buildSuggestionsSkeleton<int>(
|
||||||
suggestions: _filteredSuggestions.tags,
|
suggestions:
|
||||||
|
(_filteredSuggestions?.tags.toSet() ??
|
||||||
|
{}),
|
||||||
itemBuilder: (context, itemData) {
|
itemBuilder: (context, itemData) {
|
||||||
final tag = state.tags[itemData]!;
|
final tag = state.tags[itemData]!;
|
||||||
return ActionChip(
|
return ActionChip(
|
||||||
@@ -216,8 +218,9 @@ class _DocumentEditPageState extends State<DocumentEditPage> {
|
|||||||
LabelFormField<Correspondent>(
|
LabelFormField<Correspondent>(
|
||||||
notAssignedSelectable: false,
|
notAssignedSelectable: false,
|
||||||
formBuilderState: _formKey.currentState,
|
formBuilderState: _formKey.currentState,
|
||||||
labelCreationWidgetBuilder: (initialValue) => RepositoryProvider(
|
labelCreationWidgetBuilder: (initialValue) =>
|
||||||
create: (context) => context.read<LabelRepository<Correspondent>>(),
|
RepositoryProvider.value(
|
||||||
|
value: context.read<LabelRepository>(),
|
||||||
child: AddCorrespondentPage(initialName: initialValue),
|
child: AddCorrespondentPage(initialName: initialValue),
|
||||||
),
|
),
|
||||||
textFieldLabel: S.of(context)!.correspondent,
|
textFieldLabel: S.of(context)!.correspondent,
|
||||||
@@ -226,9 +229,9 @@ class _DocumentEditPageState extends State<DocumentEditPage> {
|
|||||||
name: fkCorrespondent,
|
name: fkCorrespondent,
|
||||||
prefixIcon: const Icon(Icons.person_outlined),
|
prefixIcon: const Icon(Icons.person_outlined),
|
||||||
),
|
),
|
||||||
if (_filteredSuggestions.hasSuggestedCorrespondents)
|
if (_filteredSuggestions?.hasSuggestedCorrespondents ?? false)
|
||||||
_buildSuggestionsSkeleton<int>(
|
_buildSuggestionsSkeleton<int>(
|
||||||
suggestions: _filteredSuggestions.correspondents,
|
suggestions: _filteredSuggestions!.correspondents,
|
||||||
itemBuilder: (context, itemData) => ActionChip(
|
itemBuilder: (context, itemData) => ActionChip(
|
||||||
label: Text(options[itemData]!.name),
|
label: Text(options[itemData]!.name),
|
||||||
onPressed: () => _formKey.currentState?.fields[fkCorrespondent]
|
onPressed: () => _formKey.currentState?.fields[fkCorrespondent]
|
||||||
@@ -248,8 +251,9 @@ class _DocumentEditPageState extends State<DocumentEditPage> {
|
|||||||
LabelFormField<DocumentType>(
|
LabelFormField<DocumentType>(
|
||||||
notAssignedSelectable: false,
|
notAssignedSelectable: false,
|
||||||
formBuilderState: _formKey.currentState,
|
formBuilderState: _formKey.currentState,
|
||||||
labelCreationWidgetBuilder: (currentInput) => RepositoryProvider(
|
labelCreationWidgetBuilder: (currentInput) =>
|
||||||
create: (context) => context.read<LabelRepository<DocumentType>>(),
|
RepositoryProvider.value(
|
||||||
|
value: context.read<LabelRepository>(),
|
||||||
child: AddDocumentTypePage(
|
child: AddDocumentTypePage(
|
||||||
initialName: currentInput,
|
initialName: currentInput,
|
||||||
),
|
),
|
||||||
@@ -260,9 +264,9 @@ class _DocumentEditPageState extends State<DocumentEditPage> {
|
|||||||
name: fkDocumentType,
|
name: fkDocumentType,
|
||||||
prefixIcon: const Icon(Icons.description_outlined),
|
prefixIcon: const Icon(Icons.description_outlined),
|
||||||
),
|
),
|
||||||
if (_filteredSuggestions.hasSuggestedDocumentTypes)
|
if (_filteredSuggestions?.hasSuggestedDocumentTypes ?? false)
|
||||||
_buildSuggestionsSkeleton<int>(
|
_buildSuggestionsSkeleton<int>(
|
||||||
suggestions: _filteredSuggestions.documentTypes,
|
suggestions: _filteredSuggestions!.documentTypes,
|
||||||
itemBuilder: (context, itemData) => ActionChip(
|
itemBuilder: (context, itemData) => ActionChip(
|
||||||
label: Text(options[itemData]!.name),
|
label: Text(options[itemData]!.name),
|
||||||
onPressed: () => _formKey.currentState?.fields[fkDocumentType]
|
onPressed: () => _formKey.currentState?.fields[fkDocumentType]
|
||||||
@@ -327,9 +331,9 @@ class _DocumentEditPageState extends State<DocumentEditPage> {
|
|||||||
format: DateFormat.yMMMMd(),
|
format: DateFormat.yMMMMd(),
|
||||||
initialEntryMode: DatePickerEntryMode.calendar,
|
initialEntryMode: DatePickerEntryMode.calendar,
|
||||||
),
|
),
|
||||||
if (_filteredSuggestions.hasSuggestedDates)
|
if (_filteredSuggestions?.hasSuggestedDates ?? false)
|
||||||
_buildSuggestionsSkeleton<DateTime>(
|
_buildSuggestionsSkeleton<DateTime>(
|
||||||
suggestions: _filteredSuggestions.dates,
|
suggestions: _filteredSuggestions!.dates,
|
||||||
itemBuilder: (context, itemData) => ActionChip(
|
itemBuilder: (context, itemData) => ActionChip(
|
||||||
label: Text(DateFormat.yMMMd().format(itemData)),
|
label: Text(DateFormat.yMMMd().format(itemData)),
|
||||||
onPressed: () => _formKey.currentState?.fields[fkCreatedDate]
|
onPressed: () => _formKey.currentState?.fields[fkCreatedDate]
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import 'package:paperless_mobile/core/bloc/connectivity_cubit.dart';
|
|||||||
import 'package:paperless_mobile/core/delegate/customizable_sliver_persistent_header_delegate.dart';
|
import 'package:paperless_mobile/core/delegate/customizable_sliver_persistent_header_delegate.dart';
|
||||||
import 'package:paperless_mobile/core/global/constants.dart';
|
import 'package:paperless_mobile/core/global/constants.dart';
|
||||||
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
||||||
import 'package:paperless_mobile/core/repository/provider/label_repositories_provider.dart';
|
|
||||||
import 'package:paperless_mobile/core/service/file_description.dart';
|
import 'package:paperless_mobile/core/service/file_description.dart';
|
||||||
import 'package:paperless_mobile/core/service/file_service.dart';
|
import 'package:paperless_mobile/core/service/file_service.dart';
|
||||||
import 'package:paperless_mobile/features/app_drawer/view/app_drawer.dart';
|
import 'package:paperless_mobile/features/app_drawer/view/app_drawer.dart';
|
||||||
@@ -198,20 +197,14 @@ class _ScannerPageState extends State<ScannerPage>
|
|||||||
);
|
);
|
||||||
final uploadResult = await Navigator.of(context).push<DocumentUploadResult>(
|
final uploadResult = await Navigator.of(context).push<DocumentUploadResult>(
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (_) => LabelRepositoriesProvider(
|
builder: (_) => BlocProvider(
|
||||||
child: BlocProvider(
|
create: (context) => DocumentUploadCubit(
|
||||||
create: (context) => DocumentUploadCubit(
|
context.read(),
|
||||||
documentApi: context.read<PaperlessDocumentsApi>(),
|
context.read(),
|
||||||
correspondentRepository:
|
),
|
||||||
context.read<LabelRepository<Correspondent>>(),
|
child: DocumentUploadPreparationPage(
|
||||||
documentTypeRepository:
|
fileBytes: file.bytes,
|
||||||
context.read<LabelRepository<DocumentType>>(),
|
fileExtension: file.extension,
|
||||||
tagRepository: context.read<LabelRepository<Tag>>(),
|
|
||||||
),
|
|
||||||
child: DocumentUploadPreparationPage(
|
|
||||||
fileBytes: file.bytes,
|
|
||||||
fileExtension: file.extension,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -316,22 +309,16 @@ class _ScannerPageState extends State<ScannerPage>
|
|||||||
}
|
}
|
||||||
Navigator.of(context).push(
|
Navigator.of(context).push(
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (_) => LabelRepositoriesProvider(
|
builder: (_) => BlocProvider(
|
||||||
child: BlocProvider(
|
create: (context) => DocumentUploadCubit(
|
||||||
create: (context) => DocumentUploadCubit(
|
context.read(),
|
||||||
documentApi: context.read<PaperlessDocumentsApi>(),
|
context.read(),
|
||||||
correspondentRepository:
|
),
|
||||||
context.read<LabelRepository<Correspondent>>(),
|
child: DocumentUploadPreparationPage(
|
||||||
documentTypeRepository:
|
fileBytes: file.readAsBytesSync(),
|
||||||
context.read<LabelRepository<DocumentType>>(),
|
filename: fileDescription.filename,
|
||||||
tagRepository: context.read<LabelRepository<Tag>>(),
|
title: fileDescription.filename,
|
||||||
),
|
fileExtension: fileDescription.extension,
|
||||||
child: DocumentUploadPreparationPage(
|
|
||||||
fileBytes: file.readAsBytesSync(),
|
|
||||||
filename: fileDescription.filename,
|
|
||||||
title: fileDescription.filename,
|
|
||||||
fileExtension: fileDescription.extension,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import 'package:collection/collection.dart';
|
|||||||
import 'package:hydrated_bloc/hydrated_bloc.dart';
|
import 'package:hydrated_bloc/hydrated_bloc.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/features/paged_document_view/cubit/document_paging_bloc_mixin.dart';
|
import 'package:paperless_mobile/features/paged_document_view/cubit/document_paging_bloc_mixin.dart';
|
||||||
import 'package:json_annotation/json_annotation.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/paged_document_view/cubit/paged_documents_state.dart';
|
||||||
@@ -15,12 +16,22 @@ class DocumentSearchCubit extends HydratedCubit<DocumentSearchState>
|
|||||||
with DocumentPagingBlocMixin {
|
with DocumentPagingBlocMixin {
|
||||||
@override
|
@override
|
||||||
final PaperlessDocumentsApi api;
|
final PaperlessDocumentsApi api;
|
||||||
|
|
||||||
|
final LabelRepository _labelRepository;
|
||||||
@override
|
@override
|
||||||
final DocumentChangedNotifier notifier;
|
final DocumentChangedNotifier notifier;
|
||||||
|
|
||||||
DocumentSearchCubit(this.api, this.notifier)
|
DocumentSearchCubit(this.api, this.notifier, this._labelRepository)
|
||||||
: super(const DocumentSearchState()) {
|
: super(const DocumentSearchState()) {
|
||||||
notifier.subscribe(
|
_labelRepository.addListener(this, onChanged: (labels) {
|
||||||
|
emit(state.copyWith(
|
||||||
|
correspondents: labels.correspondents,
|
||||||
|
documentTypes: labels.documentTypes,
|
||||||
|
tags: labels.tags,
|
||||||
|
storagePaths: labels.storagePaths,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
notifier.addListener(
|
||||||
this,
|
this,
|
||||||
onDeleted: remove,
|
onDeleted: remove,
|
||||||
onUpdated: replace,
|
onUpdated: replace,
|
||||||
@@ -89,7 +100,7 @@ class DocumentSearchCubit extends HydratedCubit<DocumentSearchState>
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> close() {
|
Future<void> close() {
|
||||||
notifier.unsubscribe(this);
|
notifier.removeListener(this);
|
||||||
return super.close();
|
return super.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,12 @@ class DocumentSearchState extends DocumentPagingState {
|
|||||||
final List<String> suggestions;
|
final List<String> suggestions;
|
||||||
@JsonKey()
|
@JsonKey()
|
||||||
final ViewType viewType;
|
final ViewType viewType;
|
||||||
|
|
||||||
|
final Map<int, Correspondent> correspondents;
|
||||||
|
final Map<int, DocumentType> documentTypes;
|
||||||
|
final Map<int, Tag> tags;
|
||||||
|
final Map<int, StoragePath> storagePaths;
|
||||||
|
|
||||||
const DocumentSearchState({
|
const DocumentSearchState({
|
||||||
this.view = SearchView.suggestions,
|
this.view = SearchView.suggestions,
|
||||||
this.searchHistory = const [],
|
this.searchHistory = const [],
|
||||||
@@ -22,6 +28,10 @@ class DocumentSearchState extends DocumentPagingState {
|
|||||||
super.hasLoaded,
|
super.hasLoaded,
|
||||||
super.isLoading,
|
super.isLoading,
|
||||||
super.value,
|
super.value,
|
||||||
|
this.correspondents = const {},
|
||||||
|
this.documentTypes = const {},
|
||||||
|
this.tags = const {},
|
||||||
|
this.storagePaths = const {},
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -31,6 +41,10 @@ class DocumentSearchState extends DocumentPagingState {
|
|||||||
suggestions,
|
suggestions,
|
||||||
view,
|
view,
|
||||||
viewType,
|
viewType,
|
||||||
|
correspondents,
|
||||||
|
documentTypes,
|
||||||
|
tags,
|
||||||
|
storagePaths,
|
||||||
];
|
];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -57,6 +71,10 @@ class DocumentSearchState extends DocumentPagingState {
|
|||||||
List<String>? suggestions,
|
List<String>? suggestions,
|
||||||
SearchView? view,
|
SearchView? view,
|
||||||
ViewType? viewType,
|
ViewType? viewType,
|
||||||
|
Map<int, Correspondent>? correspondents,
|
||||||
|
Map<int, DocumentType>? documentTypes,
|
||||||
|
Map<int, Tag>? tags,
|
||||||
|
Map<int, StoragePath>? storagePaths,
|
||||||
}) {
|
}) {
|
||||||
return DocumentSearchState(
|
return DocumentSearchState(
|
||||||
value: value ?? this.value,
|
value: value ?? this.value,
|
||||||
@@ -67,6 +85,10 @@ class DocumentSearchState extends DocumentPagingState {
|
|||||||
view: view ?? this.view,
|
view: view ?? this.view,
|
||||||
suggestions: suggestions ?? this.suggestions,
|
suggestions: suggestions ?? this.suggestions,
|
||||||
viewType: viewType ?? this.viewType,
|
viewType: viewType ?? this.viewType,
|
||||||
|
correspondents: correspondents ?? this.correspondents,
|
||||||
|
documentTypes: documentTypes ?? this.documentTypes,
|
||||||
|
tags: tags ?? this.tags,
|
||||||
|
storagePaths: storagePaths ?? this.storagePaths,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ Future<void> showDocumentSearchPage(BuildContext context) {
|
|||||||
create: (context) => DocumentSearchCubit(
|
create: (context) => DocumentSearchCubit(
|
||||||
context.read(),
|
context.read(),
|
||||||
context.read(),
|
context.read(),
|
||||||
|
context.read(),
|
||||||
),
|
),
|
||||||
child: const DocumentSearchPage(),
|
child: const DocumentSearchPage(),
|
||||||
),
|
),
|
||||||
@@ -229,6 +230,10 @@ class _DocumentSearchPageState extends State<DocumentSearchPage> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
correspondents: state.correspondents,
|
||||||
|
documentTypes: state.documentTypes,
|
||||||
|
tags: state.tags,
|
||||||
|
storagePaths: state.storagePaths,
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -5,42 +5,26 @@ import 'package:equatable/equatable.dart';
|
|||||||
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/core/repository/label_repository.dart';
|
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
||||||
import 'package:paperless_mobile/core/repository/state/impl/correspondent_repository_state.dart';
|
|
||||||
import 'package:paperless_mobile/core/repository/state/impl/document_type_repository_state.dart';
|
|
||||||
import 'package:paperless_mobile/core/repository/state/impl/tag_repository_state.dart';
|
|
||||||
|
|
||||||
part 'document_upload_state.dart';
|
part 'document_upload_state.dart';
|
||||||
|
|
||||||
class DocumentUploadCubit extends Cubit<DocumentUploadState> {
|
class DocumentUploadCubit extends Cubit<DocumentUploadState> {
|
||||||
final PaperlessDocumentsApi _documentApi;
|
final PaperlessDocumentsApi _documentApi;
|
||||||
|
|
||||||
final LabelRepository<Tag> _tagRepository;
|
final LabelRepository _labelRepository;
|
||||||
final LabelRepository<Correspondent> _correspondentRepository;
|
|
||||||
final LabelRepository<DocumentType> _documentTypeRepository;
|
|
||||||
|
|
||||||
final List<StreamSubscription> _subs = [];
|
DocumentUploadCubit(this._labelRepository, this._documentApi)
|
||||||
|
: super(const DocumentUploadState()) {
|
||||||
DocumentUploadCubit({
|
_labelRepository.addListener(
|
||||||
required PaperlessDocumentsApi documentApi,
|
this,
|
||||||
required LabelRepository<Tag> tagRepository,
|
onChanged: (labels) {
|
||||||
required LabelRepository<Correspondent> correspondentRepository,
|
emit(state.copyWith(
|
||||||
required LabelRepository<DocumentType> documentTypeRepository,
|
correspondents: labels.correspondents,
|
||||||
}) : _documentApi = documentApi,
|
documentTypes: labels.documentTypes,
|
||||||
_tagRepository = tagRepository,
|
tags: labels.tags,
|
||||||
_correspondentRepository = correspondentRepository,
|
));
|
||||||
_documentTypeRepository = documentTypeRepository,
|
},
|
||||||
super(const DocumentUploadState()) {
|
);
|
||||||
_subs.add(_tagRepository.values.listen(
|
|
||||||
(tags) => emit(state.copyWith(tags: tags?.values)),
|
|
||||||
));
|
|
||||||
_subs.add(_correspondentRepository.values.listen(
|
|
||||||
(correspondents) =>
|
|
||||||
emit(state.copyWith(correspondents: correspondents?.values)),
|
|
||||||
));
|
|
||||||
_subs.add(_documentTypeRepository.values.listen(
|
|
||||||
(documentTypes) =>
|
|
||||||
emit(state.copyWith(documentTypes: documentTypes?.values)),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String?> upload(
|
Future<String?> upload(
|
||||||
@@ -65,9 +49,7 @@ class DocumentUploadCubit extends Cubit<DocumentUploadState> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> close() async {
|
Future<void> close() async {
|
||||||
for (final sub in _subs) {
|
_labelRepository.removeListener(this);
|
||||||
await sub.cancel();
|
|
||||||
}
|
|
||||||
return super.close();
|
return super.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -192,9 +192,8 @@ class _DocumentUploadPreparationPageState
|
|||||||
notAssignedSelectable: false,
|
notAssignedSelectable: false,
|
||||||
formBuilderState: _formKey.currentState,
|
formBuilderState: _formKey.currentState,
|
||||||
labelCreationWidgetBuilder: (initialName) =>
|
labelCreationWidgetBuilder: (initialName) =>
|
||||||
RepositoryProvider(
|
RepositoryProvider.value(
|
||||||
create: (context) =>
|
value: context.read<LabelRepository>(),
|
||||||
context.read<LabelRepository<Correspondent>>(),
|
|
||||||
child: AddCorrespondentPage(initialName: initialName),
|
child: AddCorrespondentPage(initialName: initialName),
|
||||||
),
|
),
|
||||||
textFieldLabel: S.of(context)!.correspondent + " *",
|
textFieldLabel: S.of(context)!.correspondent + " *",
|
||||||
@@ -207,9 +206,8 @@ class _DocumentUploadPreparationPageState
|
|||||||
notAssignedSelectable: false,
|
notAssignedSelectable: false,
|
||||||
formBuilderState: _formKey.currentState,
|
formBuilderState: _formKey.currentState,
|
||||||
labelCreationWidgetBuilder: (initialName) =>
|
labelCreationWidgetBuilder: (initialName) =>
|
||||||
RepositoryProvider(
|
RepositoryProvider.value(
|
||||||
create: (context) =>
|
value: context.read<LabelRepository>(),
|
||||||
context.read<LabelRepository<DocumentType>>(),
|
|
||||||
child: AddDocumentTypePage(initialName: initialName),
|
child: AddDocumentTypePage(initialName: initialName),
|
||||||
),
|
),
|
||||||
textFieldLabel: S.of(context)!.documentType + " *",
|
textFieldLabel: S.of(context)!.documentType + " *",
|
||||||
@@ -229,7 +227,7 @@ class _DocumentUploadPreparationPageState
|
|||||||
"* " + S.of(context)!.uploadInferValuesHint,
|
"* " + S.of(context)!.uploadInferValuesHint,
|
||||||
style: Theme.of(context).textTheme.bodySmall,
|
style: Theme.of(context).textTheme.bodySmall,
|
||||||
),
|
),
|
||||||
SizedBox(height: 300),
|
const SizedBox(height: 300),
|
||||||
].padded(),
|
].padded(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,19 +1,17 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:developer';
|
|
||||||
|
|
||||||
import 'package:collection/collection.dart';
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:hydrated_bloc/hydrated_bloc.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_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/paged_document_view/cubit/document_paging_bloc_mixin.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/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_cubit.g.dart';
|
||||||
|
part 'documents_state.dart';
|
||||||
|
|
||||||
class DocumentsCubit extends HydratedCubit<DocumentsState>
|
class DocumentsCubit extends HydratedCubit<DocumentsState>
|
||||||
with DocumentPagingBlocMixin {
|
with DocumentPagingBlocMixin {
|
||||||
@@ -32,7 +30,7 @@ class DocumentsCubit extends HydratedCubit<DocumentsState>
|
|||||||
storagePaths: _labelRepository.state.storagePaths,
|
storagePaths: _labelRepository.state.storagePaths,
|
||||||
tags: _labelRepository.state.tags,
|
tags: _labelRepository.state.tags,
|
||||||
)) {
|
)) {
|
||||||
notifier.subscribe(
|
notifier.addListener(
|
||||||
this,
|
this,
|
||||||
onUpdated: (document) {
|
onUpdated: (document) {
|
||||||
replace(document);
|
replace(document);
|
||||||
@@ -54,9 +52,9 @@ class DocumentsCubit extends HydratedCubit<DocumentsState>
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
_labelRepository.subscribe(
|
_labelRepository.addListener(
|
||||||
this,
|
this,
|
||||||
onStateChanged: (labels) => emit(
|
onChanged: (labels) => emit(
|
||||||
state.copyWith(
|
state.copyWith(
|
||||||
correspondents: labels.correspondents,
|
correspondents: labels.correspondents,
|
||||||
documentTypes: labels.documentTypes,
|
documentTypes: labels.documentTypes,
|
||||||
@@ -120,8 +118,8 @@ class DocumentsCubit extends HydratedCubit<DocumentsState>
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> close() {
|
Future<void> close() {
|
||||||
notifier.unsubscribe(this);
|
notifier.removeListener(this);
|
||||||
_labelRepository.unsubscribe(this);
|
_labelRepository.removeListener(this);
|
||||||
return super.close();
|
return super.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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/adaptive_documents_view.dart';
|
||||||
import 'package:paperless_mobile/features/documents/view/widgets/documents_empty_state.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/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/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/selection/view_type_selection_widget.dart';
|
||||||
import 'package:paperless_mobile/features/documents/view/widgets/sort_documents_button.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/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/add_saved_view_page.dart';
|
||||||
import 'package:paperless_mobile/features/saved_view/view/saved_view_list.dart';
|
import 'package:paperless_mobile/features/saved_view/view/saved_view_list.dart';
|
||||||
@@ -358,6 +356,10 @@ class _DocumentsPageState extends State<DocumentsPage>
|
|||||||
isLabelClickable: true,
|
isLabelClickable: true,
|
||||||
isLoading: state.isLoading,
|
isLoading: state.isLoading,
|
||||||
selectedDocumentIds: state.selectedIds,
|
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 {
|
void _onCreateSavedView(DocumentFilter filter) async {
|
||||||
final newView = await Navigator.of(context).push<SavedView?>(
|
final newView = await Navigator.of(context).push<SavedView?>(
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => LabelsBlocProvider(
|
builder: (context) => BlocBuilder<SavedViewCubit, SavedViewState>(
|
||||||
child: AddSavedViewPage(
|
builder: (context, state) {
|
||||||
currentFilter: filter,
|
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],
|
snapSizes: const [0.9, 1],
|
||||||
initialChildSize: .9,
|
initialChildSize: .9,
|
||||||
maxChildSize: 1,
|
maxChildSize: 1,
|
||||||
builder: (context, controller) => LabelsBlocProvider(
|
builder: (context, controller) =>
|
||||||
child: DocumentFilterPanel(
|
BlocBuilder<DocumentsCubit, DocumentsState>(
|
||||||
initialFilter: context.read<DocumentsCubit>().state.filter,
|
builder: (context, state) {
|
||||||
scrollController: controller,
|
return DocumentFilterPanel(
|
||||||
draggableSheetController: draggableSheetController,
|
initialFilter: context.read<DocumentsCubit>().state.filter,
|
||||||
),
|
scrollController: controller,
|
||||||
|
draggableSheetController: draggableSheetController,
|
||||||
|
correspondents: state.correspondents,
|
||||||
|
documentTypes: state.documentTypes,
|
||||||
|
storagePaths: state.storagePaths,
|
||||||
|
tags: state.tags,
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ class DocumentDetailedItem extends DocumentItem {
|
|||||||
textStyle: Theme.of(context).textTheme.titleSmall?.apply(
|
textStyle: Theme.of(context).textTheme.titleSmall?.apply(
|
||||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||||
),
|
),
|
||||||
correspondent: context.read<DocumentsCubit>().correspondent,
|
correspondent: correspondents[document.correspondent],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
).paddedLTRB(8, 0, 8, 4),
|
).paddedLTRB(8, 0, 8, 4),
|
||||||
@@ -134,13 +134,13 @@ class DocumentDetailedItem extends DocumentItem {
|
|||||||
textStyle: Theme.of(context).textTheme.titleSmall?.apply(
|
textStyle: Theme.of(context).textTheme.titleSmall?.apply(
|
||||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||||
),
|
),
|
||||||
documentTypeId: document.documentType,
|
documentType: documentTypes[document.documentType],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
).paddedLTRB(8, 0, 8, 4),
|
).paddedLTRB(8, 0, 8, 4),
|
||||||
TagsWidget(
|
TagsWidget(
|
||||||
isMultiLine: false,
|
isMultiLine: false,
|
||||||
tagIds: document.tags,
|
tags: document.tags.map((e) => tags[e]!).toList(),
|
||||||
).padded(),
|
).padded(),
|
||||||
if (highlights != null)
|
if (highlights != null)
|
||||||
Html(
|
Html(
|
||||||
|
|||||||
@@ -49,6 +49,11 @@ class DocumentFilterForm extends StatefulWidget {
|
|||||||
final DocumentFilter initialFilter;
|
final DocumentFilter initialFilter;
|
||||||
final ScrollController? scrollController;
|
final ScrollController? scrollController;
|
||||||
final EdgeInsets padding;
|
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({
|
const DocumentFilterForm({
|
||||||
super.key,
|
super.key,
|
||||||
this.header,
|
this.header,
|
||||||
@@ -56,6 +61,10 @@ class DocumentFilterForm extends StatefulWidget {
|
|||||||
required this.initialFilter,
|
required this.initialFilter,
|
||||||
this.scrollController,
|
this.scrollController,
|
||||||
this.padding = const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
|
this.padding = const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
|
||||||
|
required this.correspondents,
|
||||||
|
required this.documentTypes,
|
||||||
|
required this.tags,
|
||||||
|
required this.storagePaths,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -145,47 +154,35 @@ class _DocumentFilterFormState extends State<DocumentFilterForm> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildDocumentTypeFormField() {
|
Widget _buildDocumentTypeFormField() {
|
||||||
return BlocBuilder<LabelCubit<DocumentType>, LabelState<DocumentType>>(
|
return LabelFormField<DocumentType>(
|
||||||
builder: (context, state) {
|
formBuilderState: widget.formKey.currentState,
|
||||||
return LabelFormField<DocumentType>(
|
name: DocumentFilterForm.fkDocumentType,
|
||||||
formBuilderState: widget.formKey.currentState,
|
labelOptions: widget.documentTypes,
|
||||||
name: DocumentFilterForm.fkDocumentType,
|
textFieldLabel: S.of(context)!.documentType,
|
||||||
labelOptions: state.labels,
|
initialValue: widget.initialFilter.documentType,
|
||||||
textFieldLabel: S.of(context)!.documentType,
|
prefixIcon: const Icon(Icons.description_outlined),
|
||||||
initialValue: widget.initialFilter.documentType,
|
|
||||||
prefixIcon: const Icon(Icons.description_outlined),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildCorrespondentFormField() {
|
Widget _buildCorrespondentFormField() {
|
||||||
return BlocBuilder<LabelCubit<Correspondent>, LabelState<Correspondent>>(
|
return LabelFormField<Correspondent>(
|
||||||
builder: (context, state) {
|
formBuilderState: widget.formKey.currentState,
|
||||||
return LabelFormField<Correspondent>(
|
name: DocumentFilterForm.fkCorrespondent,
|
||||||
formBuilderState: widget.formKey.currentState,
|
labelOptions: widget.correspondents,
|
||||||
name: DocumentFilterForm.fkCorrespondent,
|
textFieldLabel: S.of(context)!.correspondent,
|
||||||
labelOptions: state.labels,
|
initialValue: widget.initialFilter.correspondent,
|
||||||
textFieldLabel: S.of(context)!.correspondent,
|
prefixIcon: const Icon(Icons.person_outline),
|
||||||
initialValue: widget.initialFilter.correspondent,
|
|
||||||
prefixIcon: const Icon(Icons.person_outline),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildStoragePathFormField() {
|
Widget _buildStoragePathFormField() {
|
||||||
return BlocBuilder<LabelCubit<StoragePath>, LabelState<StoragePath>>(
|
return LabelFormField<StoragePath>(
|
||||||
builder: (context, state) {
|
formBuilderState: widget.formKey.currentState,
|
||||||
return LabelFormField<StoragePath>(
|
name: DocumentFilterForm.fkStoragePath,
|
||||||
formBuilderState: widget.formKey.currentState,
|
labelOptions: widget.storagePaths,
|
||||||
name: DocumentFilterForm.fkStoragePath,
|
textFieldLabel: S.of(context)!.storagePath,
|
||||||
labelOptions: state.labels,
|
initialValue: widget.initialFilter.storagePath,
|
||||||
textFieldLabel: S.of(context)!.storagePath,
|
prefixIcon: const Icon(Icons.folder_outlined),
|
||||||
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() {
|
Widget _buildTagsFormField() {
|
||||||
return BlocBuilder<LabelCubit<Tag>, LabelState<Tag>>(
|
return TagFormField(
|
||||||
builder: (context, state) {
|
name: DocumentModel.tagsKey,
|
||||||
return TagFormField(
|
initialValue: widget.initialFilter.tags,
|
||||||
name: DocumentModel.tagsKey,
|
allowCreation: false,
|
||||||
initialValue: widget.initialFilter.tags,
|
selectableOptions: widget.tags,
|
||||||
allowCreation: false,
|
|
||||||
selectableOptions: state.labels,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,11 +13,20 @@ class DocumentFilterPanel extends StatefulWidget {
|
|||||||
final DocumentFilter initialFilter;
|
final DocumentFilter initialFilter;
|
||||||
final ScrollController scrollController;
|
final ScrollController scrollController;
|
||||||
final DraggableScrollableController draggableSheetController;
|
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({
|
const DocumentFilterPanel({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.initialFilter,
|
required this.initialFilter,
|
||||||
required this.scrollController,
|
required this.scrollController,
|
||||||
required this.draggableSheetController,
|
required this.draggableSheetController,
|
||||||
|
required this.correspondents,
|
||||||
|
required this.documentTypes,
|
||||||
|
required this.tags,
|
||||||
|
required this.storagePaths,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -38,10 +47,8 @@ class _DocumentFilterPanelState extends State<DocumentFilterPanel> {
|
|||||||
|
|
||||||
void animateTitleByDrag() {
|
void animateTitleByDrag() {
|
||||||
setState(
|
setState(
|
||||||
() {
|
() => _heightAnimationValue =
|
||||||
_heightAnimationValue = dp(
|
dp(((max(0.9, widget.draggableSheetController.size) - 0.9) / 0.1), 5),
|
||||||
((max(0.9, widget.draggableSheetController.size) - 0.9) / 0.1), 5);
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,6 +103,10 @@ class _DocumentFilterPanelState extends State<DocumentFilterPanel> {
|
|||||||
scrollController: widget.scrollController,
|
scrollController: widget.scrollController,
|
||||||
initialFilter: widget.initialFilter,
|
initialFilter: widget.initialFilter,
|
||||||
header: _buildPanelHeader(),
|
header: _buildPanelHeader(),
|
||||||
|
correspondents: widget.correspondents,
|
||||||
|
documentTypes: widget.documentTypes,
|
||||||
|
storagePaths: widget.storagePaths,
|
||||||
|
tags: widget.tags,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -10,6 +10,10 @@ import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
|||||||
class SortFieldSelectionBottomSheet extends StatefulWidget {
|
class SortFieldSelectionBottomSheet extends StatefulWidget {
|
||||||
final SortOrder initialSortOrder;
|
final SortOrder initialSortOrder;
|
||||||
final SortField? initialSortField;
|
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;
|
final Future Function(SortField? field, SortOrder order) onSubmit;
|
||||||
|
|
||||||
@@ -18,6 +22,10 @@ class SortFieldSelectionBottomSheet extends StatefulWidget {
|
|||||||
required this.initialSortOrder,
|
required this.initialSortOrder,
|
||||||
required this.initialSortField,
|
required this.initialSortField,
|
||||||
required this.onSubmit,
|
required this.onSubmit,
|
||||||
|
required this.correspondents,
|
||||||
|
required this.documentTypes,
|
||||||
|
required this.tags,
|
||||||
|
required this.storagePaths,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -67,31 +75,20 @@ class _SortFieldSelectionBottomSheetState
|
|||||||
Column(
|
Column(
|
||||||
children: [
|
children: [
|
||||||
_buildSortOption(SortField.archiveSerialNumber),
|
_buildSortOption(SortField.archiveSerialNumber),
|
||||||
BlocBuilder<LabelCubit<Correspondent>,
|
_buildSortOption(
|
||||||
LabelState<Correspondent>>(
|
SortField.correspondentName,
|
||||||
builder: (context, state) {
|
enabled: widget.correspondents.values.fold<bool>(
|
||||||
return _buildSortOption(
|
false,
|
||||||
SortField.correspondentName,
|
(previousValue, element) =>
|
||||||
enabled: state.labels.values.fold<bool>(
|
previousValue || (element.documentCount ?? 0) > 0),
|
||||||
false,
|
|
||||||
(previousValue, element) =>
|
|
||||||
previousValue ||
|
|
||||||
(element.documentCount ?? 0) > 0),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
_buildSortOption(SortField.title),
|
_buildSortOption(SortField.title),
|
||||||
BlocBuilder<LabelCubit<DocumentType>, LabelState<DocumentType>>(
|
_buildSortOption(
|
||||||
builder: (context, state) {
|
SortField.documentType,
|
||||||
return _buildSortOption(
|
enabled: widget.documentTypes.values.fold<bool>(
|
||||||
SortField.documentType,
|
false,
|
||||||
enabled: state.labels.values.fold<bool>(
|
(previousValue, element) =>
|
||||||
false,
|
previousValue || (element.documentCount ?? 0) > 0),
|
||||||
(previousValue, element) =>
|
|
||||||
previousValue ||
|
|
||||||
(element.documentCount ?? 0) > 0),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
_buildSortOption(SortField.created),
|
_buildSortOption(SortField.created),
|
||||||
_buildSortOption(SortField.added),
|
_buildSortOption(SortField.added),
|
||||||
|
|||||||
@@ -57,6 +57,10 @@ class SortDocumentsButton extends StatelessWidget {
|
|||||||
sortOrder: order,
|
sortOrder: order,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
correspondents: state.correspondents,
|
||||||
|
documentTypes: state.documentTypes,
|
||||||
|
storagePaths: state.storagePaths,
|
||||||
|
tags: state.tags,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class EditLabelCubit extends Cubit<EditLabelState> with LabelCubitMixin {
|
|||||||
final LabelRepository labelRepository;
|
final LabelRepository labelRepository;
|
||||||
|
|
||||||
EditLabelCubit(this.labelRepository) : super(const EditLabelState()) {
|
EditLabelCubit(this.labelRepository) : super(const EditLabelState()) {
|
||||||
labelRepository.subscribe(
|
labelRepository.addListener(
|
||||||
this,
|
this,
|
||||||
onChanged: (labels) => state.copyWith(
|
onChanged: (labels) => state.copyWith(
|
||||||
correspondents: labels.correspondents,
|
correspondents: labels.correspondents,
|
||||||
@@ -26,7 +26,7 @@ class EditLabelCubit extends Cubit<EditLabelState> with LabelCubitMixin {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> close() {
|
Future<void> close() {
|
||||||
labelRepository.unsubscribe(this);
|
labelRepository.removeListener(this);
|
||||||
return super.close();
|
return super.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -157,10 +157,8 @@ class _HomePageState extends State<HomePage> with WidgetsBindingObserver {
|
|||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => BlocProvider.value(
|
builder: (context) => BlocProvider.value(
|
||||||
value: DocumentUploadCubit(
|
value: DocumentUploadCubit(
|
||||||
documentApi: context.read(),
|
context.read(),
|
||||||
tagRepository: context.read(),
|
context.read(),
|
||||||
correspondentRepository: context.read(),
|
|
||||||
documentTypeRepository: context.read(),
|
|
||||||
),
|
),
|
||||||
child: DocumentUploadPreparationPage(
|
child: DocumentUploadPreparationPage(
|
||||||
fileBytes: bytes,
|
fileBytes: bytes,
|
||||||
@@ -239,11 +237,13 @@ class _HomePageState extends State<HomePage> with WidgetsBindingObserver {
|
|||||||
create: (context) => DocumentsCubit(
|
create: (context) => DocumentsCubit(
|
||||||
context.read(),
|
context.read(),
|
||||||
context.read(),
|
context.read(),
|
||||||
|
context.read(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
create: (context) => SavedViewCubit(
|
create: (context) => SavedViewCubit(
|
||||||
context.read(),
|
context.read(),
|
||||||
|
context.read(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ class InboxCubit extends HydratedCubit<InboxState>
|
|||||||
this._labelRepository,
|
this._labelRepository,
|
||||||
this.notifier,
|
this.notifier,
|
||||||
) : super(InboxState(labels: _labelRepository.state)) {
|
) : super(InboxState(labels: _labelRepository.state)) {
|
||||||
notifier.subscribe(
|
notifier.addListener(
|
||||||
this,
|
this,
|
||||||
onDeleted: remove,
|
onDeleted: remove,
|
||||||
onUpdated: (document) {
|
onUpdated: (document) {
|
||||||
@@ -47,7 +47,7 @@ class InboxCubit extends HydratedCubit<InboxState>
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
_labelRepository.subscribe(
|
_labelRepository.addListener(
|
||||||
this,
|
this,
|
||||||
onChanged: (labels) {
|
onChanged: (labels) {
|
||||||
emit(state.copyWith(labels: labels));
|
emit(state.copyWith(labels: labels));
|
||||||
@@ -209,7 +209,7 @@ class InboxCubit extends HydratedCubit<InboxState>
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> close() {
|
Future<void> close() {
|
||||||
_labelRepository.unsubscribe(this);
|
_labelRepository.removeListener(this);
|
||||||
return super.close();
|
return super.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ class LabelCubit extends Cubit<LabelState> with LabelCubitMixin<LabelState> {
|
|||||||
final LabelRepository labelRepository;
|
final LabelRepository labelRepository;
|
||||||
|
|
||||||
LabelCubit(this.labelRepository) : super(const LabelState()) {
|
LabelCubit(this.labelRepository) : super(const LabelState()) {
|
||||||
labelRepository.subscribe(
|
labelRepository.addListener(
|
||||||
this,
|
this,
|
||||||
onChanged: (labels) {
|
onChanged: (labels) {
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
@@ -27,7 +27,7 @@ class LabelCubit extends Cubit<LabelState> with LabelCubitMixin<LabelState> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> close() {
|
Future<void> close() {
|
||||||
labelRepository.unsubscribe(this);
|
labelRepository.removeListener(this);
|
||||||
return super.close();
|
return super.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ class LinkedDocumentsCubit extends HydratedCubit<LinkedDocumentsState>
|
|||||||
this._labelRepository,
|
this._labelRepository,
|
||||||
) : super(const LinkedDocumentsState()) {
|
) : super(const LinkedDocumentsState()) {
|
||||||
updateFilter(filter: filter);
|
updateFilter(filter: filter);
|
||||||
_labelRepository.subscribe(
|
_labelRepository.addListener(
|
||||||
this,
|
this,
|
||||||
onChanged: (labels) {
|
onChanged: (labels) {
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
@@ -38,7 +38,7 @@ class LinkedDocumentsCubit extends HydratedCubit<LinkedDocumentsState>
|
|||||||
));
|
));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
notifier.subscribe(
|
notifier.addListener(
|
||||||
this,
|
this,
|
||||||
onUpdated: replace,
|
onUpdated: replace,
|
||||||
onDeleted: remove,
|
onDeleted: remove,
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ mixin DocumentPagingBlocMixin<State extends DocumentPagingState>
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> close() {
|
Future<void> close() {
|
||||||
notifier.unsubscribe(this);
|
notifier.removeListener(this);
|
||||||
return super.close();
|
return super.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class SavedViewCubit extends Cubit<SavedViewState> {
|
|||||||
storagePaths: _labelRepository.state.storagePaths,
|
storagePaths: _labelRepository.state.storagePaths,
|
||||||
tags: _labelRepository.state.tags,
|
tags: _labelRepository.state.tags,
|
||||||
)) {
|
)) {
|
||||||
_labelRepository.subscribe(
|
_labelRepository.addListener(
|
||||||
this,
|
this,
|
||||||
onChanged: (labels) {
|
onChanged: (labels) {
|
||||||
emit(
|
emit(
|
||||||
@@ -76,7 +76,7 @@ class SavedViewCubit extends Cubit<SavedViewState> {
|
|||||||
@override
|
@override
|
||||||
Future<void> close() {
|
Future<void> close() {
|
||||||
_savedViewRepository.unsubscribe(this);
|
_savedViewRepository.unsubscribe(this);
|
||||||
_labelRepository.unsubscribe(this);
|
_labelRepository.removeListener(this);
|
||||||
return super.close();
|
return super.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,18 @@ import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
|||||||
|
|
||||||
class AddSavedViewPage extends StatefulWidget {
|
class AddSavedViewPage extends StatefulWidget {
|
||||||
final DocumentFilter currentFilter;
|
final DocumentFilter currentFilter;
|
||||||
const AddSavedViewPage({super.key, required this.currentFilter});
|
final Map<int, Correspondent> correspondents;
|
||||||
|
final Map<int, DocumentType> documentTypes;
|
||||||
|
final Map<int, Tag> tags;
|
||||||
|
final Map<int, StoragePath> storagePaths;
|
||||||
|
const AddSavedViewPage({
|
||||||
|
super.key,
|
||||||
|
required this.currentFilter,
|
||||||
|
required this.correspondents,
|
||||||
|
required this.documentTypes,
|
||||||
|
required this.tags,
|
||||||
|
required this.storagePaths,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<AddSavedViewPage> createState() => _AddSavedViewPageState();
|
State<AddSavedViewPage> createState() => _AddSavedViewPageState();
|
||||||
@@ -72,6 +83,10 @@ class _AddSavedViewPageState extends State<AddSavedViewPage> {
|
|||||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||||
formKey: _filterFormKey,
|
formKey: _filterFormKey,
|
||||||
initialFilter: widget.currentFilter,
|
initialFilter: widget.currentFilter,
|
||||||
|
correspondents: widget.correspondents,
|
||||||
|
documentTypes: widget.documentTypes,
|
||||||
|
storagePaths: widget.storagePaths,
|
||||||
|
tags: widget.tags,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ class SavedViewDetailsCubit extends HydratedCubit<SavedViewDetailsState>
|
|||||||
this.notifier, {
|
this.notifier, {
|
||||||
required this.savedView,
|
required this.savedView,
|
||||||
}) : super(const SavedViewDetailsState()) {
|
}) : super(const SavedViewDetailsState()) {
|
||||||
notifier.subscribe(
|
notifier.addListener(
|
||||||
this,
|
this,
|
||||||
onDeleted: remove,
|
onDeleted: remove,
|
||||||
onUpdated: replace,
|
onUpdated: replace,
|
||||||
|
|||||||
@@ -5,17 +5,30 @@ class SavedViewDetailsState extends DocumentPagingState {
|
|||||||
@JsonKey()
|
@JsonKey()
|
||||||
final ViewType viewType;
|
final ViewType viewType;
|
||||||
|
|
||||||
|
final Map<int, Correspondent> correspondents;
|
||||||
|
final Map<int, DocumentType> documentTypes;
|
||||||
|
final Map<int, Tag> tags;
|
||||||
|
final Map<int, StoragePath> storagePaths;
|
||||||
|
|
||||||
const SavedViewDetailsState({
|
const SavedViewDetailsState({
|
||||||
this.viewType = ViewType.list,
|
this.viewType = ViewType.list,
|
||||||
super.filter,
|
super.filter,
|
||||||
super.hasLoaded,
|
super.hasLoaded,
|
||||||
super.isLoading,
|
super.isLoading,
|
||||||
super.value,
|
super.value,
|
||||||
|
this.correspondents = const {},
|
||||||
|
this.documentTypes = const {},
|
||||||
|
this.tags = const {},
|
||||||
|
this.storagePaths = const {},
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object?> get props => [
|
List<Object?> get props => [
|
||||||
viewType,
|
viewType,
|
||||||
|
correspondents,
|
||||||
|
documentTypes,
|
||||||
|
tags,
|
||||||
|
storagePaths,
|
||||||
...super.props,
|
...super.props,
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -40,6 +53,10 @@ class SavedViewDetailsState extends DocumentPagingState {
|
|||||||
List<PagedSearchResult<DocumentModel>>? value,
|
List<PagedSearchResult<DocumentModel>>? value,
|
||||||
DocumentFilter? filter,
|
DocumentFilter? filter,
|
||||||
ViewType? viewType,
|
ViewType? viewType,
|
||||||
|
Map<int, Correspondent>? correspondents,
|
||||||
|
Map<int, DocumentType>? documentTypes,
|
||||||
|
Map<int, Tag>? tags,
|
||||||
|
Map<int, StoragePath>? storagePaths,
|
||||||
}) {
|
}) {
|
||||||
return SavedViewDetailsState(
|
return SavedViewDetailsState(
|
||||||
hasLoaded: hasLoaded ?? this.hasLoaded,
|
hasLoaded: hasLoaded ?? this.hasLoaded,
|
||||||
@@ -47,6 +64,10 @@ class SavedViewDetailsState extends DocumentPagingState {
|
|||||||
value: value ?? this.value,
|
value: value ?? this.value,
|
||||||
filter: filter ?? this.filter,
|
filter: filter ?? this.filter,
|
||||||
viewType: viewType ?? this.viewType,
|
viewType: viewType ?? this.viewType,
|
||||||
|
correspondents: correspondents ?? this.correspondents,
|
||||||
|
documentTypes: documentTypes ?? this.documentTypes,
|
||||||
|
tags: tags ?? this.tags,
|
||||||
|
storagePaths: storagePaths ?? this.storagePaths,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -86,6 +86,10 @@ class _SavedViewDetailsPageState extends State<SavedViewDetailsPage>
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
viewType: state.viewType,
|
viewType: state.viewType,
|
||||||
|
correspondents: state.correspondents,
|
||||||
|
documentTypes: state.documentTypes,
|
||||||
|
tags: state.tags,
|
||||||
|
storagePaths: state.storagePaths,
|
||||||
),
|
),
|
||||||
if (state.hasLoaded && state.isLoading)
|
if (state.hasLoaded && state.isLoading)
|
||||||
const SliverToBoxAdapter(
|
const SliverToBoxAdapter(
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'package:bloc/bloc.dart';
|
import 'package:bloc/bloc.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/features/paged_document_view/cubit/document_paging_bloc_mixin.dart';
|
import 'package:paperless_mobile/features/paged_document_view/cubit/document_paging_bloc_mixin.dart';
|
||||||
import 'package:paperless_mobile/features/paged_document_view/cubit/paged_documents_state.dart';
|
import 'package:paperless_mobile/features/paged_document_view/cubit/paged_documents_state.dart';
|
||||||
|
|
||||||
@@ -13,19 +14,33 @@ class SimilarDocumentsCubit extends Cubit<SimilarDocumentsState>
|
|||||||
@override
|
@override
|
||||||
final PaperlessDocumentsApi api;
|
final PaperlessDocumentsApi api;
|
||||||
|
|
||||||
|
final LabelRepository _labelRepository;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
final DocumentChangedNotifier notifier;
|
final DocumentChangedNotifier notifier;
|
||||||
|
|
||||||
SimilarDocumentsCubit(
|
SimilarDocumentsCubit(
|
||||||
this.api,
|
this.api,
|
||||||
this.notifier, {
|
this.notifier,
|
||||||
|
this._labelRepository, {
|
||||||
required this.documentId,
|
required this.documentId,
|
||||||
}) : super(const SimilarDocumentsState()) {
|
}) : super(const SimilarDocumentsState()) {
|
||||||
notifier.subscribe(
|
notifier.addListener(
|
||||||
this,
|
this,
|
||||||
onDeleted: remove,
|
onDeleted: remove,
|
||||||
onUpdated: replace,
|
onUpdated: replace,
|
||||||
);
|
);
|
||||||
|
_labelRepository.addListener(
|
||||||
|
this,
|
||||||
|
onChanged: (labels) {
|
||||||
|
emit(state.copyWith(
|
||||||
|
correspondents: labels.correspondents,
|
||||||
|
documentTypes: labels.documentTypes,
|
||||||
|
tags: labels.tags,
|
||||||
|
storagePaths: labels.storagePaths,
|
||||||
|
));
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> initialize() async {
|
Future<void> initialize() async {
|
||||||
@@ -38,4 +53,11 @@ class SimilarDocumentsCubit extends Cubit<SimilarDocumentsState>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> close() {
|
||||||
|
notifier.removeListener(this);
|
||||||
|
_labelRepository.removeListener(this);
|
||||||
|
return super.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,20 @@
|
|||||||
part of 'similar_documents_cubit.dart';
|
part of 'similar_documents_cubit.dart';
|
||||||
|
|
||||||
class SimilarDocumentsState extends DocumentPagingState {
|
class SimilarDocumentsState extends DocumentPagingState {
|
||||||
|
final Map<int, Correspondent> correspondents;
|
||||||
|
final Map<int, DocumentType> documentTypes;
|
||||||
|
final Map<int, Tag> tags;
|
||||||
|
final Map<int, StoragePath> storagePaths;
|
||||||
|
|
||||||
const SimilarDocumentsState({
|
const SimilarDocumentsState({
|
||||||
super.filter,
|
super.filter,
|
||||||
super.hasLoaded,
|
super.hasLoaded,
|
||||||
super.isLoading,
|
super.isLoading,
|
||||||
super.value,
|
super.value,
|
||||||
|
this.correspondents = const {},
|
||||||
|
this.documentTypes = const {},
|
||||||
|
this.tags = const {},
|
||||||
|
this.storagePaths = const {},
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -14,6 +23,10 @@ class SimilarDocumentsState extends DocumentPagingState {
|
|||||||
hasLoaded,
|
hasLoaded,
|
||||||
isLoading,
|
isLoading,
|
||||||
value,
|
value,
|
||||||
|
correspondents,
|
||||||
|
documentTypes,
|
||||||
|
tags,
|
||||||
|
storagePaths,
|
||||||
];
|
];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -36,12 +49,20 @@ class SimilarDocumentsState extends DocumentPagingState {
|
|||||||
bool? isLoading,
|
bool? isLoading,
|
||||||
List<PagedSearchResult<DocumentModel>>? value,
|
List<PagedSearchResult<DocumentModel>>? value,
|
||||||
DocumentFilter? filter,
|
DocumentFilter? filter,
|
||||||
|
Map<int, Correspondent>? correspondents,
|
||||||
|
Map<int, DocumentType>? documentTypes,
|
||||||
|
Map<int, Tag>? tags,
|
||||||
|
Map<int, StoragePath>? storagePaths,
|
||||||
}) {
|
}) {
|
||||||
return SimilarDocumentsState(
|
return SimilarDocumentsState(
|
||||||
hasLoaded: hasLoaded ?? this.hasLoaded,
|
hasLoaded: hasLoaded ?? this.hasLoaded,
|
||||||
isLoading: isLoading ?? this.isLoading,
|
isLoading: isLoading ?? this.isLoading,
|
||||||
value: value ?? this.value,
|
value: value ?? this.value,
|
||||||
filter: filter ?? this.filter,
|
filter: filter ?? this.filter,
|
||||||
|
correspondents: correspondents ?? this.correspondents,
|
||||||
|
documentTypes: documentTypes ?? this.documentTypes,
|
||||||
|
tags: tags ?? this.tags,
|
||||||
|
storagePaths: storagePaths ?? this.storagePaths,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,6 +78,10 @@ class _SimilarDocumentsViewState extends State<SimilarDocumentsView>
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
correspondents: state.correspondents,
|
||||||
|
documentTypes: state.documentTypes,
|
||||||
|
tags: state.tags,
|
||||||
|
storagePaths: state.storagePaths,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import 'package:paperless_mobile/core/bloc/paperless_server_information_cubit.da
|
|||||||
import 'package:paperless_mobile/core/interceptor/dio_http_error_interceptor.dart';
|
import 'package:paperless_mobile/core/interceptor/dio_http_error_interceptor.dart';
|
||||||
import 'package:paperless_mobile/core/interceptor/language_header.interceptor.dart';
|
import 'package:paperless_mobile/core/interceptor/language_header.interceptor.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/impl/saved_view_repository_impl.dart';
|
|
||||||
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
||||||
import 'package:paperless_mobile/core/repository/saved_view_repository.dart';
|
import 'package:paperless_mobile/core/repository/saved_view_repository.dart';
|
||||||
import 'package:paperless_mobile/core/security/session_manager.dart';
|
import 'package:paperless_mobile/core/security/session_manager.dart';
|
||||||
@@ -101,7 +100,7 @@ void main() async {
|
|||||||
|
|
||||||
// Create repositories
|
// Create repositories
|
||||||
final labelRepository = LabelRepository(labelsApi);
|
final labelRepository = LabelRepository(labelsApi);
|
||||||
final savedViewRepository = SavedViewRepositoryImpl(savedViewsApi);
|
final savedViewRepository = SavedViewRepository(savedViewsApi);
|
||||||
|
|
||||||
//Create cubits/blocs
|
//Create cubits/blocs
|
||||||
final authCubit = AuthenticationCubit(
|
final authCubit = AuthenticationCubit(
|
||||||
|
|||||||
Reference in New Issue
Block a user