diff --git a/lib/features/documents/view/pages/documents_page.dart b/lib/features/documents/view/pages/documents_page.dart index 25fc0e7..0673ae6 100644 --- a/lib/features/documents/view/pages/documents_page.dart +++ b/lib/features/documents/view/pages/documents_page.dart @@ -33,7 +33,6 @@ class DocumentFilterIntent { }); } -//TODO: Refactor this class DocumentsPage extends StatefulWidget { const DocumentsPage({Key? key}) : super(key: key); diff --git a/lib/features/documents/view/widgets/adaptive_documents_view.dart b/lib/features/documents/view/widgets/adaptive_documents_view.dart index 47f9110..a619207 100644 --- a/lib/features/documents/view/widgets/adaptive_documents_view.dart +++ b/lib/features/documents/view/widgets/adaptive_documents_view.dart @@ -159,7 +159,7 @@ class SliverAdaptiveDocumentsView extends AdaptiveDocumentsView { crossAxisCount: 2, mainAxisSpacing: 4, crossAxisSpacing: 4, - childAspectRatio: 1 / 2, + mainAxisExtent: 350, ), itemCount: documents.length, itemBuilder: (context, index) { diff --git a/lib/features/documents/view/widgets/items/document_detailed_item.dart b/lib/features/documents/view/widgets/items/document_detailed_item.dart index 70c211c..3f214ae 100644 --- a/lib/features/documents/view/widgets/items/document_detailed_item.dart +++ b/lib/features/documents/view/widgets/items/document_detailed_item.dart @@ -141,10 +141,10 @@ class DocumentDetailedItem extends DocumentItem { ], ).paddedLTRB(8, 0, 8, 4), TagsWidget( - isMultiLine: false, tags: document.tags .map((e) => context.watch().state.tags[e]!) .toList(), + onTagSelected: onTagSelected, ).padded(), if (highlights != null) Html( diff --git a/lib/features/documents/view/widgets/items/document_grid_item.dart b/lib/features/documents/view/widgets/items/document_grid_item.dart index 4f5c549..73284cd 100644 --- a/lib/features/documents/view/widgets/items/document_grid_item.dart +++ b/lib/features/documents/view/widgets/items/document_grid_item.dart @@ -1,11 +1,11 @@ import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; import 'package:paperless_mobile/core/repository/label_repository.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/correspondent/view/widgets/correspondent_widget.dart'; import 'package:paperless_mobile/features/labels/document_type/view/widgets/document_type_widget.dart'; import 'package:paperless_mobile/features/labels/tags/view/widgets/tags_widget.dart'; -import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; class DocumentGridItem extends DocumentItem { @@ -42,10 +42,46 @@ class DocumentGridItem extends DocumentItem { children: [ AspectRatio( aspectRatio: 1, - child: DocumentPreview( - document: document, - borderRadius: 12.0, - enableHero: enableHeroAnimation, + child: Stack( + children: [ + Positioned.fill( + child: DocumentPreview( + document: document, + borderRadius: 12.0, + enableHero: enableHeroAnimation, + ), + ), + Align( + alignment: Alignment.bottomLeft, + child: SizedBox( + height: 48, + child: NotificationListener( + // Prevents ancestor notification listeners to be notified when this widget scrolls + onNotification: (notification) => true, + child: CustomScrollView( + scrollDirection: Axis.horizontal, + slivers: [ + const SliverToBoxAdapter( + child: SizedBox(width: 8), + ), + TagsWidget.sliver( + tags: document.tags + .map((e) => context + .watch() + .state + .tags[e]!) + .toList(), + onTagSelected: onTagSelected, + ), + const SliverToBoxAdapter( + child: SizedBox(width: 8), + ), + ], + ), + ), + ), + ), + ], ), ), Expanded( @@ -59,29 +95,25 @@ class DocumentGridItem extends DocumentItem { .watch() .state .correspondents[document.correspondent], + onSelected: onCorrespondentSelected, ), DocumentTypeWidget( documentType: context .watch() .state .documentTypes[document.documentType], + onSelected: onDocumentTypeSelected, ), - Text( - document.title, - maxLines: document.tags.isEmpty ? 3 : 2, - overflow: TextOverflow.ellipsis, - style: Theme.of(context).textTheme.titleMedium, + Padding( + padding: const EdgeInsets.only(bottom: 8.0), + child: Text( + document.title, + maxLines: document.tags.isEmpty ? 3 : 2, + overflow: TextOverflow.ellipsis, + style: Theme.of(context).textTheme.titleMedium, + ), ), - const Spacer(), - TagsWidget( - tags: document.tags - .map((e) => - context.watch().state.tags[e]!) - .toList(), - isMultiLine: false, - onTagSelected: onTagSelected, - ), - const Spacer(), + Spacer(), Text( DateFormat.yMMMd().format(document.created), style: Theme.of(context).textTheme.bodySmall, diff --git a/lib/features/documents/view/widgets/items/document_list_item.dart b/lib/features/documents/view/widgets/items/document_list_item.dart index e187b14..1736eaf 100644 --- a/lib/features/documents/view/widgets/items/document_list_item.dart +++ b/lib/features/documents/view/widgets/items/document_list_item.dart @@ -68,7 +68,6 @@ class DocumentListItem extends DocumentItem { .where((e) => labels.tags.containsKey(e)) .map((e) => labels.tags[e]!) .toList(), - isMultiLine: false, onTagSelected: (id) => onTagSelected?.call(id), ), ), diff --git a/lib/features/inbox/view/widgets/inbox_item.dart b/lib/features/inbox/view/widgets/inbox_item.dart index e4faac2..a538b41 100644 --- a/lib/features/inbox/view/widgets/inbox_item.dart +++ b/lib/features/inbox/view/widgets/inbox_item.dart @@ -213,13 +213,11 @@ class _InboxItemState extends State { TagsWidget( tags: widget.document.tags .map((e) => state.labels.tags[e]) - .whereNot((element) => element == null) + .whereNot((e) => e == null) .toList() .cast(), - isMultiLine: false, isClickable: false, showShortNames: true, - dense: true, ).paddedOnly(left: 8, bottom: 8), ], ), diff --git a/lib/features/labels/tags/view/widgets/tags_widget.dart b/lib/features/labels/tags/view/widgets/tags_widget.dart index 609b59b..1711b64 100644 --- a/lib/features/labels/tags/view/widgets/tags_widget.dart +++ b/lib/features/labels/tags/view/widgets/tags_widget.dart @@ -4,51 +4,95 @@ import 'package:paperless_mobile/features/labels/tags/view/widgets/tag_widget.da class TagsWidget extends StatelessWidget { final List tags; - final bool isMultiLine; final void Function(int tagId)? onTagSelected; final bool isClickable; final bool showShortNames; final bool dense; const TagsWidget({ - Key? key, + super.key, required this.tags, - this.isMultiLine = true, - this.isClickable = true, this.onTagSelected, + this.isClickable = true, this.showShortNames = false, this.dense = true, - }) : super(key: key); + }); + + List get _children { + return [ + for (var tag in tags) + TagWidget( + tag: tag, + isClickable: isClickable, + onSelected: () => onTagSelected?.call(tag.id!), + showShortName: showShortNames, + dense: dense, + ) + ]; + } + + const factory TagsWidget.multiLine({ + Key? key, + required List tags, + required void Function(int tagId)? onTagSelected, + required bool isClickable, + required bool showShortNames, + required bool dense, + }) = _MultiLineTagsWidget; + + const factory TagsWidget.sliver({ + Key? key, + required List tags, + void Function(int tagId)? onTagSelected, + bool isClickable, + bool showShortNames, + bool dense, + }) = _SliverTagsWidget; @override Widget build(BuildContext context) { - return Builder( - builder: (context) { - final children = tags - .map( - (tag) => TagWidget( - tag: tag, - isClickable: isClickable, - onSelected: () => onTagSelected?.call(tag.id!), - showShortName: showShortNames, - dense: dense, - ), - ) - .toList(); - if (isMultiLine) { - return Wrap( - runAlignment: WrapAlignment.start, - children: children, - runSpacing: 4, - spacing: 4, - ); - } else { - return SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: Row(children: children), - ); - } - }, + return SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row(children: _children), + ); + } +} + +class _MultiLineTagsWidget extends TagsWidget { + const _MultiLineTagsWidget({ + super.key, + required super.tags, + super.onTagSelected, + super.isClickable, + super.showShortNames, + super.dense, + }); + + @override + Widget build(BuildContext context) { + return Wrap( + runAlignment: WrapAlignment.start, + children: _children, + runSpacing: 4, + spacing: 4, + ); + } +} + +class _SliverTagsWidget extends TagsWidget { + const _SliverTagsWidget({ + super.key, + required super.tags, + super.isClickable, + super.showShortNames, + super.dense, + super.onTagSelected, + }); + + @override + Widget build(BuildContext context) { + return SliverList.list( + children: _children, ); } } diff --git a/lib/main.dart b/lib/main.dart index 81e395d..a9b131f 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -26,7 +26,6 @@ import 'package:paperless_mobile/core/database/tables/local_user_app_state.dart' import 'package:paperless_mobile/core/exception/server_message_exception.dart'; import 'package:paperless_mobile/core/factory/paperless_api_factory.dart'; import 'package:paperless_mobile/core/factory/paperless_api_factory_impl.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/notifier/document_changed_notifier.dart'; import 'package:paperless_mobile/core/security/session_manager.dart'; diff --git a/packages/paperless_api/lib/src/models/query_parameters/date_range_queries/date_range_query.dart b/packages/paperless_api/lib/src/models/query_parameters/date_range_queries/date_range_query.dart index 0982267..17c470b 100644 --- a/packages/paperless_api/lib/src/models/query_parameters/date_range_queries/date_range_query.dart +++ b/packages/paperless_api/lib/src/models/query_parameters/date_range_queries/date_range_query.dart @@ -164,7 +164,7 @@ class UnsetDateRangeQueryAdapter extends TypeAdapter { @override UnsetDateRangeQuery read(BinaryReader reader) { - // reader.readByte(); + reader.readByte(); return const UnsetDateRangeQuery(); }