mirror of
https://github.com/Xevion/paperless-mobile.git
synced 2025-12-09 08:08:14 -06:00
feat: view type stored in view/cubit, itself, cleanup coe
This commit is contained in:
@@ -5,8 +5,9 @@ import 'package:flutter/foundation.dart';
|
||||
import 'package:hydrated_bloc/hydrated_bloc.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/notifier/document_changed_notifier.dart';
|
||||
import 'package:paperless_mobile/features/documents/bloc/documents_state.dart';
|
||||
import 'package:paperless_mobile/features/documents/cubit/documents_state.dart';
|
||||
import 'package:paperless_mobile/features/paged_document_view/paged_documents_mixin.dart';
|
||||
import 'package:paperless_mobile/features/settings/model/view_type.dart';
|
||||
|
||||
class DocumentsCubit extends HydratedCubit<DocumentsState>
|
||||
with PagedDocumentsMixin {
|
||||
@@ -94,4 +95,8 @@ class DocumentsCubit extends HydratedCubit<DocumentsState>
|
||||
notifier.unsubscribe(this);
|
||||
return super.close();
|
||||
}
|
||||
|
||||
void setViewType(ViewType viewType) {
|
||||
emit(state.copyWith(viewType: viewType));
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,20 @@
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/features/paged_document_view/model/paged_documents_state.dart';
|
||||
import 'package:paperless_mobile/features/settings/model/view_type.dart';
|
||||
|
||||
part 'documents_state.g.dart';
|
||||
|
||||
@JsonSerializable()
|
||||
class DocumentsState extends PagedDocumentsState {
|
||||
@JsonKey(includeFromJson: true, includeToJson: false)
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
final List<DocumentModel> selection;
|
||||
|
||||
final ViewType viewType;
|
||||
|
||||
const DocumentsState({
|
||||
this.selection = const [],
|
||||
this.viewType = ViewType.list,
|
||||
super.value = const [],
|
||||
super.filter = const DocumentFilter(),
|
||||
super.hasLoaded = false,
|
||||
@@ -22,6 +29,7 @@ class DocumentsState extends PagedDocumentsState {
|
||||
List<PagedSearchResult<DocumentModel>>? value,
|
||||
DocumentFilter? filter,
|
||||
List<DocumentModel>? selection,
|
||||
ViewType? viewType,
|
||||
}) {
|
||||
return DocumentsState(
|
||||
hasLoaded: hasLoaded ?? this.hasLoaded,
|
||||
@@ -29,38 +37,22 @@ class DocumentsState extends PagedDocumentsState {
|
||||
value: value ?? this.value,
|
||||
filter: filter ?? this.filter,
|
||||
selection: selection ?? this.selection,
|
||||
viewType: viewType ?? this.viewType,
|
||||
);
|
||||
}
|
||||
|
||||
factory DocumentsState.fromJson(Map<String, dynamic> json) =>
|
||||
_$DocumentsStateFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$DocumentsStateToJson(this);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
selection,
|
||||
viewType,
|
||||
...super.props,
|
||||
];
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = {
|
||||
'hasLoaded': hasLoaded,
|
||||
'isLoading': isLoading,
|
||||
'filter': filter.toJson(),
|
||||
'value':
|
||||
value.map((e) => e.toJson(DocumentModelJsonConverter())).toList(),
|
||||
};
|
||||
return json;
|
||||
}
|
||||
|
||||
factory DocumentsState.fromJson(Map<String, dynamic> json) {
|
||||
return DocumentsState(
|
||||
hasLoaded: json['hasLoaded'],
|
||||
isLoading: json['isLoading'],
|
||||
value: (json['value'] as List<dynamic>)
|
||||
.map((e) =>
|
||||
PagedSearchResult.fromJsonT(e, DocumentModelJsonConverter()))
|
||||
.toList(),
|
||||
filter: DocumentFilter.fromJson(json['filter']),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
DocumentsState copyWithPaged({
|
||||
bool? hasLoaded,
|
||||
@@ -1,336 +0,0 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_form_builder/flutter_form_builder.dart';
|
||||
import 'package:flutter_typeahead/flutter_typeahead.dart';
|
||||
import 'package:form_builder_validators/form_builder_validators.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:paperless_api/paperless_api.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/storage_path_repository_state.dart';
|
||||
import 'package:paperless_mobile/core/workarounds/colored_chip.dart';
|
||||
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
||||
import 'package:paperless_mobile/features/edit_document/cubit/edit_document_cubit.dart';
|
||||
import 'package:paperless_mobile/features/edit_label/view/impl/add_correspondent_page.dart';
|
||||
import 'package:paperless_mobile/features/edit_label/view/impl/add_document_type_page.dart';
|
||||
import 'package:paperless_mobile/features/edit_label/view/impl/add_storage_path_page.dart';
|
||||
import 'package:paperless_mobile/features/labels/tags/view/widgets/tags_form_field.dart';
|
||||
import 'package:paperless_mobile/features/labels/view/widgets/label_form_field.dart';
|
||||
import 'package:paperless_mobile/generated/l10n.dart';
|
||||
import 'package:paperless_mobile/helpers/message_helpers.dart';
|
||||
import 'package:paperless_mobile/constants.dart';
|
||||
|
||||
class DocumentEditPage extends StatefulWidget {
|
||||
final FieldSuggestions suggestions;
|
||||
const DocumentEditPage({
|
||||
Key? key,
|
||||
required this.suggestions,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<DocumentEditPage> createState() => _DocumentEditPageState();
|
||||
}
|
||||
|
||||
class _DocumentEditPageState extends State<DocumentEditPage> {
|
||||
static const fkTitle = "title";
|
||||
static const fkCorrespondent = "correspondent";
|
||||
static const fkTags = "tags";
|
||||
static const fkDocumentType = "documentType";
|
||||
static const fkCreatedDate = "createdAtDate";
|
||||
static const fkStoragePath = 'storagePath';
|
||||
|
||||
final GlobalKey<FormBuilderState> _formKey = GlobalKey();
|
||||
bool _isSubmitLoading = false;
|
||||
|
||||
late final FieldSuggestions _filteredSuggestions;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_filteredSuggestions = widget.suggestions
|
||||
.documentDifference(context.read<EditDocumentCubit>().state.document);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<EditDocumentCubit, EditDocumentState>(
|
||||
builder: (context, state) {
|
||||
return Scaffold(
|
||||
resizeToAvoidBottomInset: false,
|
||||
floatingActionButton: FloatingActionButton.extended(
|
||||
onPressed: () => _onSubmit(state.document),
|
||||
icon: const Icon(Icons.save),
|
||||
label: Text(S.of(context).genericActionUpdateLabel),
|
||||
),
|
||||
appBar: AppBar(
|
||||
title: Text(S.of(context).documentEditPageTitle),
|
||||
bottom: _isSubmitLoading
|
||||
? const PreferredSize(
|
||||
preferredSize: Size.fromHeight(4),
|
||||
child: LinearProgressIndicator(),
|
||||
)
|
||||
: null,
|
||||
),
|
||||
extendBody: true,
|
||||
body: Padding(
|
||||
padding: EdgeInsets.only(
|
||||
bottom: MediaQuery.of(context).viewInsets.bottom,
|
||||
top: 8,
|
||||
left: 8,
|
||||
right: 8,
|
||||
),
|
||||
child: FormBuilder(
|
||||
key: _formKey,
|
||||
child: ListView(
|
||||
children: [
|
||||
_buildTitleFormField(state.document.title).padded(),
|
||||
_buildCreatedAtFormField(state.document.created).padded(),
|
||||
_buildDocumentTypeFormField(
|
||||
state.document.documentType,
|
||||
state.documentTypes,
|
||||
).padded(),
|
||||
_buildCorrespondentFormField(
|
||||
state.document.correspondent,
|
||||
state.correspondents,
|
||||
).padded(),
|
||||
_buildStoragePathFormField(
|
||||
state.document.storagePath,
|
||||
state.storagePaths,
|
||||
).padded(),
|
||||
TagFormField(
|
||||
initialValue:
|
||||
IdsTagsQuery.included(state.document.tags.toList()),
|
||||
notAssignedSelectable: false,
|
||||
anyAssignedSelectable: false,
|
||||
excludeAllowed: false,
|
||||
name: fkTags,
|
||||
selectableOptions: state.tags,
|
||||
suggestions: _filteredSuggestions.tags
|
||||
.toSet()
|
||||
.difference(state.document.tags.toSet())
|
||||
.isNotEmpty
|
||||
? _buildSuggestionsSkeleton<int>(
|
||||
suggestions: _filteredSuggestions.tags,
|
||||
itemBuilder: (context, itemData) {
|
||||
final tag = state.tags[itemData]!;
|
||||
return ActionChip(
|
||||
label: Text(
|
||||
tag.name,
|
||||
style: TextStyle(color: tag.textColor),
|
||||
),
|
||||
backgroundColor: tag.color,
|
||||
onPressed: () {
|
||||
final currentTags = _formKey.currentState
|
||||
?.fields[fkTags]?.value as TagsQuery;
|
||||
if (currentTags is IdsTagsQuery) {
|
||||
_formKey.currentState?.fields[fkTags]
|
||||
?.didChange((IdsTagsQuery.fromIds(
|
||||
{...currentTags.ids, itemData})));
|
||||
} else {
|
||||
_formKey.currentState?.fields[fkTags]
|
||||
?.didChange((IdsTagsQuery.fromIds(
|
||||
{itemData})));
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
)
|
||||
: null,
|
||||
).padded(),
|
||||
const SizedBox(
|
||||
height: 64), // Prevent tags from being hidden by fab
|
||||
],
|
||||
),
|
||||
),
|
||||
));
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildStoragePathFormField(
|
||||
int? initialId,
|
||||
Map<int, StoragePath> options,
|
||||
) {
|
||||
return Column(
|
||||
children: [
|
||||
LabelFormField<StoragePath>(
|
||||
notAssignedSelectable: false,
|
||||
formBuilderState: _formKey.currentState,
|
||||
labelCreationWidgetBuilder: (initialValue) => RepositoryProvider(
|
||||
create: (context) => context.read<LabelRepository<StoragePath>>(),
|
||||
child: AddStoragePathPage(initalValue: initialValue),
|
||||
),
|
||||
textFieldLabel: S.of(context).documentStoragePathPropertyLabel,
|
||||
labelOptions: options,
|
||||
initialValue: IdQueryParameter.fromId(initialId),
|
||||
name: fkStoragePath,
|
||||
prefixIcon: const Icon(Icons.folder_outlined),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildCorrespondentFormField(
|
||||
int? initialId, Map<int, Correspondent> options) {
|
||||
return Column(
|
||||
children: [
|
||||
LabelFormField<Correspondent>(
|
||||
notAssignedSelectable: false,
|
||||
formBuilderState: _formKey.currentState,
|
||||
labelCreationWidgetBuilder: (initialValue) => RepositoryProvider(
|
||||
create: (context) => context.read<LabelRepository<Correspondent>>(),
|
||||
child: AddCorrespondentPage(initialName: initialValue),
|
||||
),
|
||||
textFieldLabel: S.of(context).documentCorrespondentPropertyLabel,
|
||||
labelOptions: options,
|
||||
initialValue: IdQueryParameter.fromId(initialId),
|
||||
name: fkCorrespondent,
|
||||
prefixIcon: const Icon(Icons.person_outlined),
|
||||
),
|
||||
if (_filteredSuggestions.hasSuggestedCorrespondents)
|
||||
_buildSuggestionsSkeleton<int>(
|
||||
suggestions: _filteredSuggestions.correspondents,
|
||||
itemBuilder: (context, itemData) => ActionChip(
|
||||
label: Text(options[itemData]!.name),
|
||||
onPressed: () => _formKey.currentState?.fields[fkCorrespondent]
|
||||
?.didChange((IdQueryParameter.fromId(itemData))),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildDocumentTypeFormField(
|
||||
int? initialId,
|
||||
Map<int, DocumentType> options,
|
||||
) {
|
||||
return Column(
|
||||
children: [
|
||||
LabelFormField<DocumentType>(
|
||||
notAssignedSelectable: false,
|
||||
formBuilderState: _formKey.currentState,
|
||||
labelCreationWidgetBuilder: (currentInput) => RepositoryProvider(
|
||||
create: (context) => context.read<LabelRepository<DocumentType>>(),
|
||||
child: AddDocumentTypePage(
|
||||
initialName: currentInput,
|
||||
),
|
||||
),
|
||||
textFieldLabel: S.of(context).documentDocumentTypePropertyLabel,
|
||||
initialValue: IdQueryParameter.fromId(initialId),
|
||||
labelOptions: options,
|
||||
name: fkDocumentType,
|
||||
prefixIcon: const Icon(Icons.description_outlined),
|
||||
),
|
||||
if (_filteredSuggestions.hasSuggestedDocumentTypes)
|
||||
_buildSuggestionsSkeleton<int>(
|
||||
suggestions: _filteredSuggestions.documentTypes,
|
||||
itemBuilder: (context, itemData) => ActionChip(
|
||||
label: Text(options[itemData]!.name),
|
||||
onPressed: () => _formKey.currentState?.fields[fkDocumentType]
|
||||
?.didChange(IdQueryParameter.fromId(itemData)),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _onSubmit(DocumentModel document) async {
|
||||
if (_formKey.currentState?.saveAndValidate() ?? false) {
|
||||
final values = _formKey.currentState!.value;
|
||||
var mergedDocument = document.copyWith(
|
||||
title: values[fkTitle],
|
||||
created: values[fkCreatedDate],
|
||||
documentType: () => (values[fkDocumentType] as IdQueryParameter).id,
|
||||
correspondent: () => (values[fkCorrespondent] as IdQueryParameter).id,
|
||||
storagePath: () => (values[fkStoragePath] as IdQueryParameter).id,
|
||||
tags: (values[fkTags] as IdsTagsQuery).includedIds,
|
||||
);
|
||||
setState(() {
|
||||
_isSubmitLoading = true;
|
||||
});
|
||||
try {
|
||||
await context.read<EditDocumentCubit>().updateDocument(mergedDocument);
|
||||
showSnackBar(context, S.of(context).documentUpdateSuccessMessage);
|
||||
} on PaperlessServerException catch (error, stackTrace) {
|
||||
showErrorMessage(context, error, stackTrace);
|
||||
} finally {
|
||||
setState(() {
|
||||
_isSubmitLoading = false;
|
||||
});
|
||||
Navigator.pop(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildTitleFormField(String? initialTitle) {
|
||||
return FormBuilderTextField(
|
||||
name: fkTitle,
|
||||
validator: FormBuilderValidators.required(),
|
||||
decoration: InputDecoration(
|
||||
label: Text(S.of(context).documentTitlePropertyLabel),
|
||||
),
|
||||
initialValue: initialTitle,
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildCreatedAtFormField(DateTime? initialCreatedAtDate) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
FormBuilderDateTimePicker(
|
||||
inputType: InputType.date,
|
||||
name: fkCreatedDate,
|
||||
decoration: InputDecoration(
|
||||
prefixIcon: const Icon(Icons.calendar_month_outlined),
|
||||
label: Text(S.of(context).documentCreatedPropertyLabel),
|
||||
),
|
||||
initialValue: initialCreatedAtDate,
|
||||
format: DateFormat.yMMMMd(),
|
||||
initialEntryMode: DatePickerEntryMode.calendar,
|
||||
),
|
||||
if (_filteredSuggestions.hasSuggestedDates)
|
||||
_buildSuggestionsSkeleton<DateTime>(
|
||||
suggestions: _filteredSuggestions.dates,
|
||||
itemBuilder: (context, itemData) => ActionChip(
|
||||
label: Text(DateFormat.yMMMd().format(itemData)),
|
||||
onPressed: () => _formKey.currentState?.fields[fkCreatedDate]
|
||||
?.didChange(itemData),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
///
|
||||
/// Item builder is typically some sort of [Chip].
|
||||
///
|
||||
Widget _buildSuggestionsSkeleton<T>({
|
||||
required Iterable<T> suggestions,
|
||||
required ItemBuilder<T> itemBuilder,
|
||||
}) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
S.of(context).documentEditPageSuggestionsLabel,
|
||||
style: Theme.of(context).textTheme.bodySmall,
|
||||
),
|
||||
SizedBox(
|
||||
height: 48,
|
||||
child: ListView.separated(
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemCount: suggestions.length,
|
||||
itemBuilder: (context, index) => ColoredChipWrapper(
|
||||
child: itemBuilder(context, suggestions.elementAt(index)),
|
||||
),
|
||||
separatorBuilder: (BuildContext context, int index) =>
|
||||
const SizedBox(width: 4.0),
|
||||
),
|
||||
),
|
||||
],
|
||||
).padded();
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,4 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:badges/badges.dart' as b;
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
@@ -9,20 +6,19 @@ import 'package:paperless_mobile/core/bloc/connectivity_cubit.dart';
|
||||
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
||||
import 'package:paperless_mobile/features/app_drawer/view/app_drawer.dart';
|
||||
import 'package:paperless_mobile/features/document_search/view/document_search_page.dart';
|
||||
import 'package:paperless_mobile/features/documents/bloc/documents_cubit.dart';
|
||||
import 'package:paperless_mobile/features/documents/bloc/documents_state.dart';
|
||||
import 'package:paperless_mobile/features/documents/cubit/documents_cubit.dart';
|
||||
import 'package:paperless_mobile/features/documents/cubit/documents_state.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/view_type_selection_widget.dart';
|
||||
import 'package:paperless_mobile/features/documents/view/widgets/sort_documents_button.dart';
|
||||
import 'package:paperless_mobile/features/labels/bloc/providers/labels_bloc_provider.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';
|
||||
import 'package:paperless_mobile/features/search_app_bar/view/search_app_bar.dart';
|
||||
import 'package:paperless_mobile/features/settings/bloc/application_settings_cubit.dart';
|
||||
import 'package:paperless_mobile/features/settings/bloc/application_settings_state.dart';
|
||||
import 'package:paperless_mobile/features/settings/model/view_type.dart';
|
||||
import 'package:paperless_mobile/features/tasks/cubit/task_status_cubit.dart';
|
||||
import 'package:paperless_mobile/generated/l10n.dart';
|
||||
@@ -263,14 +259,6 @@ class _DocumentsPageState extends State<DocumentsPage>
|
||||
),
|
||||
_buildViewActions(),
|
||||
BlocBuilder<DocumentsCubit, DocumentsState>(
|
||||
// Not required anymore since saved views are now handled separately
|
||||
// buildWhen: (previous, current) =>
|
||||
// !const ListEquality().equals(
|
||||
// previous.documents,
|
||||
// current.documents,
|
||||
// ) ||
|
||||
// previous.selectedIds !=
|
||||
// current.selectedIds,
|
||||
builder: (context, state) {
|
||||
if (state.hasLoaded &&
|
||||
state.documents.isEmpty) {
|
||||
@@ -285,34 +273,27 @@ class _DocumentsPageState extends State<DocumentsPage>
|
||||
),
|
||||
);
|
||||
}
|
||||
return BlocBuilder<
|
||||
ApplicationSettingsCubit,
|
||||
ApplicationSettingsState>(
|
||||
builder: (context, settings) {
|
||||
return SliverAdaptiveDocumentsView(
|
||||
viewType:
|
||||
settings.preferredViewType,
|
||||
onTap: _openDetails,
|
||||
onSelected: context
|
||||
.read<DocumentsCubit>()
|
||||
.toggleDocumentSelection,
|
||||
hasInternetConnection:
|
||||
connectivityState.isConnected,
|
||||
onTagSelected: _addTagToFilter,
|
||||
onCorrespondentSelected:
|
||||
_addCorrespondentToFilter,
|
||||
onDocumentTypeSelected:
|
||||
_addDocumentTypeToFilter,
|
||||
onStoragePathSelected:
|
||||
_addStoragePathToFilter,
|
||||
documents: state.documents,
|
||||
hasLoaded: state.hasLoaded,
|
||||
isLabelClickable: true,
|
||||
isLoading: state.isLoading,
|
||||
selectedDocumentIds:
|
||||
state.selectedIds,
|
||||
);
|
||||
},
|
||||
|
||||
return SliverAdaptiveDocumentsView(
|
||||
viewType: state.viewType,
|
||||
onTap: _openDetails,
|
||||
onSelected: context
|
||||
.read<DocumentsCubit>()
|
||||
.toggleDocumentSelection,
|
||||
hasInternetConnection:
|
||||
connectivityState.isConnected,
|
||||
onTagSelected: _addTagToFilter,
|
||||
onCorrespondentSelected:
|
||||
_addCorrespondentToFilter,
|
||||
onDocumentTypeSelected:
|
||||
_addDocumentTypeToFilter,
|
||||
onStoragePathSelected:
|
||||
_addStoragePathToFilter,
|
||||
documents: state.documents,
|
||||
hasLoaded: state.hasLoaded,
|
||||
isLabelClickable: true,
|
||||
isLoading: state.isLoading,
|
||||
selectedDocumentIds: state.selectedIds,
|
||||
);
|
||||
},
|
||||
),
|
||||
@@ -360,18 +341,11 @@ class _DocumentsPageState extends State<DocumentsPage>
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const SortDocumentsButton(),
|
||||
BlocBuilder<ApplicationSettingsCubit, ApplicationSettingsState>(
|
||||
BlocBuilder<DocumentsCubit, DocumentsState>(
|
||||
builder: (context, state) {
|
||||
return IconButton(
|
||||
icon: Icon(
|
||||
state.preferredViewType == ViewType.list
|
||||
? Icons.grid_view_rounded
|
||||
: Icons.list,
|
||||
),
|
||||
onPressed: () =>
|
||||
context.read<ApplicationSettingsCubit>().setViewType(
|
||||
state.preferredViewType.toggle(),
|
||||
),
|
||||
return ViewTypeSelectionWidget(
|
||||
viewType: state.viewType,
|
||||
onChanged: context.read<DocumentsCubit>().setViewType,
|
||||
);
|
||||
},
|
||||
)
|
||||
|
||||
@@ -4,9 +4,9 @@ import 'package:intl/intl.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/features/documents/view/widgets/document_preview.dart';
|
||||
import 'package:paperless_mobile/features/documents/view/widgets/items/document_item.dart';
|
||||
import 'package:paperless_mobile/features/labels/bloc/label_cubit.dart';
|
||||
import 'package:paperless_mobile/features/labels/bloc/label_state.dart';
|
||||
import 'package:paperless_mobile/features/labels/bloc/providers/document_type_bloc_provider.dart';
|
||||
import 'package:paperless_mobile/features/labels/cubit/label_cubit.dart';
|
||||
import 'package:paperless_mobile/features/labels/cubit/label_state.dart';
|
||||
import 'package:paperless_mobile/features/labels/cubit/providers/document_type_bloc_provider.dart';
|
||||
import 'package:paperless_mobile/features/labels/correspondent/view/widgets/correspondent_widget.dart';
|
||||
import 'package:paperless_mobile/features/labels/tags/view/widgets/tags_widget.dart';
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@ import 'package:flutter_form_builder/flutter_form_builder.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/widgets/form_builder_fields/extended_date_range_form_field/form_builder_extended_date_range_picker.dart';
|
||||
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
||||
import 'package:paperless_mobile/features/labels/bloc/label_cubit.dart';
|
||||
import 'package:paperless_mobile/features/labels/bloc/label_state.dart';
|
||||
import 'package:paperless_mobile/features/labels/cubit/label_cubit.dart';
|
||||
import 'package:paperless_mobile/features/labels/cubit/label_state.dart';
|
||||
import 'package:paperless_mobile/features/labels/tags/view/widgets/tags_form_field.dart';
|
||||
import 'package:paperless_mobile/features/labels/view/widgets/label_form_field.dart';
|
||||
import 'package:paperless_mobile/generated/l10n.dart';
|
||||
|
||||
@@ -9,8 +9,8 @@ import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
||||
import 'package:paperless_mobile/features/documents/view/pages/documents_page.dart';
|
||||
import 'package:paperless_mobile/features/documents/view/widgets/search/document_filter_form.dart';
|
||||
import 'package:paperless_mobile/features/documents/view/widgets/search/text_query_form_field.dart';
|
||||
import 'package:paperless_mobile/features/labels/bloc/label_cubit.dart';
|
||||
import 'package:paperless_mobile/features/labels/bloc/label_state.dart';
|
||||
import 'package:paperless_mobile/features/labels/cubit/label_cubit.dart';
|
||||
import 'package:paperless_mobile/features/labels/cubit/label_state.dart';
|
||||
import 'package:paperless_mobile/features/labels/tags/view/widgets/tags_form_field.dart';
|
||||
import 'package:paperless_mobile/features/labels/view/widgets/label_form_field.dart';
|
||||
import 'package:paperless_mobile/generated/l10n.dart';
|
||||
|
||||
@@ -4,8 +4,8 @@ import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/translation/sort_field_localization_mapper.dart';
|
||||
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
||||
import 'package:paperless_mobile/features/labels/bloc/label_cubit.dart';
|
||||
import 'package:paperless_mobile/features/labels/bloc/label_state.dart';
|
||||
import 'package:paperless_mobile/features/labels/cubit/label_cubit.dart';
|
||||
import 'package:paperless_mobile/features/labels/cubit/label_state.dart';
|
||||
import 'package:paperless_mobile/generated/l10n.dart';
|
||||
|
||||
class SortFieldSelectionBottomSheet extends StatefulWidget {
|
||||
|
||||
@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_form_builder/flutter_form_builder.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/widgets/form_builder_fields/form_builder_type_ahead.dart';
|
||||
import 'package:paperless_mobile/features/documents/bloc/documents_cubit.dart';
|
||||
import 'package:paperless_mobile/features/documents/cubit/documents_cubit.dart';
|
||||
import 'package:paperless_mobile/generated/l10n.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/features/documents/bloc/documents_state.dart';
|
||||
import 'package:paperless_mobile/features/documents/cubit/documents_state.dart';
|
||||
import 'package:paperless_mobile/generated/l10n.dart';
|
||||
|
||||
class BulkDeleteConfirmationDialog extends StatelessWidget {
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:paperless_mobile/features/settings/model/view_type.dart';
|
||||
|
||||
/// Meant to be used with blocbuilder.
|
||||
class ViewTypeSelectionWidget extends StatelessWidget {
|
||||
final ViewType viewType;
|
||||
final void Function(ViewType type) onChanged;
|
||||
|
||||
const ViewTypeSelectionWidget({
|
||||
super.key,
|
||||
required this.viewType,
|
||||
required this.onChanged,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final next = viewType.toggle();
|
||||
final icon = next == ViewType.grid ? Icons.grid_view_rounded : Icons.list;
|
||||
return IconButton(
|
||||
icon: Icon(icon),
|
||||
onPressed: () {
|
||||
onChanged(next);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -5,10 +5,10 @@ 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/translation/sort_field_localization_mapper.dart';
|
||||
import 'package:paperless_mobile/features/documents/bloc/documents_cubit.dart';
|
||||
import 'package:paperless_mobile/features/documents/bloc/documents_state.dart';
|
||||
import 'package:paperless_mobile/features/documents/cubit/documents_cubit.dart';
|
||||
import 'package:paperless_mobile/features/documents/cubit/documents_state.dart';
|
||||
import 'package:paperless_mobile/features/documents/view/widgets/search/sort_field_selection_bottom_sheet.dart';
|
||||
import 'package:paperless_mobile/features/labels/bloc/label_cubit.dart';
|
||||
import 'package:paperless_mobile/features/labels/cubit/label_cubit.dart';
|
||||
|
||||
class SortDocumentsButton extends StatelessWidget {
|
||||
const SortDocumentsButton({
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:paperless_mobile/features/documents/view/widgets/sort_documents_button.dart';
|
||||
import 'package:paperless_mobile/features/settings/bloc/application_settings_cubit.dart';
|
||||
import 'package:paperless_mobile/features/settings/bloc/application_settings_state.dart';
|
||||
import 'package:paperless_mobile/features/settings/model/view_type.dart';
|
||||
|
||||
class ViewActions extends StatelessWidget {
|
||||
const ViewActions({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const SortDocumentsButton(),
|
||||
BlocBuilder<ApplicationSettingsCubit, ApplicationSettingsState>(
|
||||
builder: (context, settings) {
|
||||
final cubit = context.read<ApplicationSettingsCubit>();
|
||||
switch (settings.preferredViewType) {
|
||||
case ViewType.grid:
|
||||
return IconButton(
|
||||
icon: const Icon(Icons.list),
|
||||
onPressed: () =>
|
||||
cubit.setViewType(settings.preferredViewType.toggle()),
|
||||
);
|
||||
case ViewType.list:
|
||||
return IconButton(
|
||||
icon: const Icon(Icons.grid_view_rounded),
|
||||
onPressed: () =>
|
||||
cubit.setViewType(settings.preferredViewType.toggle()),
|
||||
);
|
||||
}
|
||||
},
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user