feat: Add query highlight fragments to detailed view, fix build

This commit is contained in:
Anton Stubenbord
2023-02-24 14:29:19 +01:00
parent 6cf88b6fdc
commit ce39190723
9 changed files with 153 additions and 93 deletions

View File

@@ -5,6 +5,7 @@ import 'package:paperless_mobile/core/notifier/document_changed_notifier.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';
import 'package:paperless_mobile/features/settings/model/view_type.dart';
part 'document_search_state.dart'; part 'document_search_state.dart';
@@ -33,7 +34,7 @@ class DocumentSearchCubit extends HydratedCubit<DocumentSearchState>
view: SearchView.results, view: SearchView.results,
)); ));
final searchFilter = DocumentFilter( final searchFilter = DocumentFilter(
query: TextQuery.titleAndContent(query), query: TextQuery.extended(query),
); );
await updateFilter(filter: searchFilter); await updateFilter(filter: searchFilter);
@@ -48,6 +49,10 @@ class DocumentSearchCubit extends HydratedCubit<DocumentSearchState>
); );
} }
void updateViewType(ViewType viewType) {
emit(state.copyWith(viewType: viewType));
}
void removeHistoryEntry(String entry) { void removeHistoryEntry(String entry) {
emit( emit(
state.copyWith( state.copyWith(

View File

@@ -11,10 +11,13 @@ class DocumentSearchState extends DocumentPagingState {
final List<String> searchHistory; final List<String> searchHistory;
final SearchView view; final SearchView view;
final List<String> suggestions; final List<String> suggestions;
@JsonKey()
final ViewType viewType;
const DocumentSearchState({ const DocumentSearchState({
this.view = SearchView.suggestions, this.view = SearchView.suggestions,
this.searchHistory = const [], this.searchHistory = const [],
this.suggestions = const [], this.suggestions = const [],
this.viewType = ViewType.detailed,
super.filter, super.filter,
super.hasLoaded, super.hasLoaded,
super.isLoading, super.isLoading,
@@ -27,6 +30,7 @@ class DocumentSearchState extends DocumentPagingState {
searchHistory, searchHistory,
suggestions, suggestions,
view, view,
viewType,
]; ];
@override @override
@@ -52,6 +56,7 @@ class DocumentSearchState extends DocumentPagingState {
DocumentFilter? filter, DocumentFilter? filter,
List<String>? suggestions, List<String>? suggestions,
SearchView? view, SearchView? view,
ViewType? viewType,
}) { }) {
return DocumentSearchState( return DocumentSearchState(
value: value ?? this.value, value: value ?? this.value,
@@ -61,6 +66,7 @@ class DocumentSearchState extends DocumentPagingState {
searchHistory: searchHistory ?? this.searchHistory, searchHistory: searchHistory ?? this.searchHistory,
view: view ?? this.view, view: view ?? this.view,
suggestions: suggestions ?? this.suggestions, suggestions: suggestions ?? this.suggestions,
viewType: viewType ?? this.viewType,
); );
} }

View File

@@ -7,6 +7,8 @@ import 'package:paperless_mobile/extensions/flutter_extensions.dart';
import 'package:paperless_mobile/features/document_search/cubit/document_search_cubit.dart'; import 'package:paperless_mobile/features/document_search/cubit/document_search_cubit.dart';
import 'package:paperless_mobile/features/document_search/view/remove_history_entry_dialog.dart'; import 'package:paperless_mobile/features/document_search/view/remove_history_entry_dialog.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/selection/view_type_selection_widget.dart';
import 'package:paperless_mobile/features/settings/model/view_type.dart';
import 'package:paperless_mobile/generated/l10n/app_localizations.dart'; import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
import 'package:paperless_mobile/routes/document_details_route.dart'; import 'package:paperless_mobile/routes/document_details_route.dart';
@@ -168,7 +170,7 @@ class _DocumentSearchPageState extends State<DocumentSearchPage> {
alignment: Alignment.center, alignment: Alignment.center,
transform: Matrix4.rotationY(math.pi), transform: Matrix4.rotationY(math.pi),
child: IconButton( child: IconButton(
icon: Icon(Icons.arrow_outward), icon: const Icon(Icons.arrow_outward),
onPressed: () { onPressed: () {
_queryController.text = '$suggestion '; _queryController.text = '$suggestion ';
_queryController.selection = TextSelection.fromPosition( _queryController.selection = TextSelection.fromPosition(
@@ -181,9 +183,23 @@ class _DocumentSearchPageState extends State<DocumentSearchPage> {
} }
Widget _buildResultsView(DocumentSearchState state) { Widget _buildResultsView(DocumentSearchState state) {
final header = Text( final header = Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
S.of(context)!.results, S.of(context)!.results,
style: Theme.of(context).textTheme.labelSmall, style: Theme.of(context).textTheme.bodySmall,
),
BlocBuilder<DocumentSearchCubit, DocumentSearchState>(
builder: (context, state) {
return ViewTypeSelectionWidget(
viewType: state.viewType,
onChanged: (type) =>
context.read<DocumentSearchCubit>().updateViewType(type),
);
},
)
],
).padded(); ).padded();
return CustomScrollView( return CustomScrollView(
slivers: [ slivers: [
@@ -196,6 +212,7 @@ class _DocumentSearchPageState extends State<DocumentSearchPage> {
) )
else else
SliverAdaptiveDocumentsView( SliverAdaptiveDocumentsView(
viewType: state.viewType,
documents: state.documents, documents: state.documents,
hasInternetConnection: true, hasInternetConnection: true,
isLabelClickable: false, isLabelClickable: false,

View File

@@ -146,6 +146,7 @@ class SliverAdaptiveDocumentsView extends AdaptiveDocumentsView {
onDocumentTypeSelected: onDocumentTypeSelected, onDocumentTypeSelected: onDocumentTypeSelected,
onStoragePathSelected: onStoragePathSelected, onStoragePathSelected: onStoragePathSelected,
enableHeroAnimation: enableHeroAnimation, enableHeroAnimation: enableHeroAnimation,
highlights: document.searchHit?.highlights,
), ),
); );
}, },

View File

@@ -8,10 +8,13 @@ import 'package:paperless_mobile/features/documents/view/widgets/items/document_
import 'package:paperless_mobile/features/labels/correspondent/view/widgets/correspondent_widget.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/document_type/view/widgets/document_type_widget.dart';
import 'package:paperless_mobile/features/labels/tags/view/widgets/tags_widget.dart'; import 'package:paperless_mobile/features/labels/tags/view/widgets/tags_widget.dart';
import 'package:flutter_html/flutter_html.dart';
class DocumentDetailedItem extends DocumentItem { class DocumentDetailedItem extends DocumentItem {
final String? highlights;
const DocumentDetailedItem({ const DocumentDetailedItem({
super.key, super.key,
this.highlights,
required super.document, required super.document,
required super.isSelected, required super.isSelected,
required super.isSelectionActive, required super.isSelectionActive,
@@ -37,7 +40,9 @@ class DocumentDetailedItem extends DocumentItem {
padding.bottom - padding.bottom -
kBottomNavigationBarHeight - kBottomNavigationBarHeight -
kToolbarHeight; kToolbarHeight;
final maxHeight = min(500.0, availableHeight); final maxHeight = highlights != null
? min(600.0, availableHeight)
: min(500.0, availableHeight);
return Card( return Card(
child: InkWell( child: InkWell(
enableFeedback: true, enableFeedback: true,
@@ -52,9 +57,7 @@ class DocumentDetailedItem extends DocumentItem {
onLongPress: () { onLongPress: () {
onSelected?.call(document); onSelected?.call(document);
}, },
child: Stack( child: Column(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
ConstrainedBox( ConstrainedBox(
@@ -107,8 +110,7 @@ class DocumentDetailedItem extends DocumentItem {
CorrespondentWidget( CorrespondentWidget(
onSelected: onCorrespondentSelected, onSelected: onCorrespondentSelected,
textStyle: Theme.of(context).textTheme.titleSmall?.apply( textStyle: Theme.of(context).textTheme.titleSmall?.apply(
color: color: Theme.of(context).colorScheme.onSurfaceVariant,
Theme.of(context).colorScheme.onSurfaceVariant,
), ),
correspondentId: document.correspondent, correspondentId: document.correspondent,
), ),
@@ -123,8 +125,7 @@ class DocumentDetailedItem extends DocumentItem {
DocumentTypeWidget( DocumentTypeWidget(
onSelected: onDocumentTypeSelected, onSelected: onDocumentTypeSelected,
textStyle: Theme.of(context).textTheme.titleSmall?.apply( textStyle: Theme.of(context).textTheme.titleSmall?.apply(
color: color: Theme.of(context).colorScheme.onSurfaceVariant,
Theme.of(context).colorScheme.onSurfaceVariant,
), ),
documentTypeId: document.documentType, documentTypeId: document.documentType,
), ),
@@ -134,8 +135,20 @@ class DocumentDetailedItem extends DocumentItem {
isMultiLine: false, isMultiLine: false,
tagIds: document.tags, tagIds: document.tags,
).padded(), ).padded(),
], if (highlights != null)
Html(
data: '<p>${highlights!}</p>',
style: {
"span": Style(
backgroundColor: Colors.yellow,
color: Colors.black,
), ),
"p": Style(
maxLines: 3,
textOverflow: TextOverflow.ellipsis,
),
},
).padded(),
], ],
), ),
), ),

View File

@@ -27,7 +27,9 @@ class ViewTypeSelectionWidget extends StatelessWidget {
icon = Icons.article_outlined; icon = Icons.article_outlined;
break; break;
} }
return PopupMenuButton<ViewType>( return PopupMenuButton<ViewType>(
position: PopupMenuPosition.under,
initialValue: viewType, initialValue: viewType,
icon: Icon(icon), icon: Icon(icon),
itemBuilder: (context) => [ itemBuilder: (context) => [

View File

@@ -564,6 +564,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "7.7.0" version: "7.7.0"
flutter_html:
dependency: "direct main"
description:
name: flutter_html
sha256: "342c7908f0a67bcec62b6e0f7cf23e23bafe7f64693665dd35be98d5e783bdfd"
url: "https://pub.dev"
source: hosted
version: "3.0.0-alpha.6"
flutter_keyboard_visibility: flutter_keyboard_visibility:
dependency: transitive dependency: transitive
description: description:
@@ -1005,6 +1013,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.1" version: "2.0.1"
numerus:
dependency: transitive
description:
name: numerus
sha256: "436759d84f233b40107d0cc31cfa92d24e0960afeb2e506be70926d4cddffd9e"
url: "https://pub.dev"
source: hosted
version: "2.0.0"
octo_image: octo_image:
dependency: transitive dependency: transitive
description: description:

View File

@@ -1,5 +1,6 @@
name: paperless_mobile name: paperless_mobile
description: Application to conveniently scan and share documents with a paperless-ng description:
Application to conveniently scan and share documents with a paperless-ng
server. server.
# The following line prevents the package from being accidentally published to # The following line prevents the package from being accidentally published to
@@ -19,7 +20,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
version: 2.0.7+24 version: 2.0.7+24
environment: environment:
sdk: '>=2.19.0 <4.0.0' sdk: ">=2.19.0 <4.0.0"
# Dependencies specify other packages that your package needs in order to work. # Dependencies specify other packages that your package needs in order to work.
# To automatically upgrade your package dependencies to the latest versions # To automatically upgrade your package dependencies to the latest versions
@@ -88,7 +89,7 @@ dependencies:
open_filex: ^4.3.2 open_filex: ^4.3.2
flutter_displaymode: ^0.5.0 flutter_displaymode: ^0.5.0
dynamic_color: ^1.5.4 dynamic_color: ^1.5.4
flutter_html: ^3.0.0-alpha.6
dev_dependencies: dev_dependencies:
integration_test: integration_test:
@@ -147,7 +148,6 @@ flutter:
# For details regarding fonts from package dependencies, # For details regarding fonts from package dependencies,
# see https://flutter.dev/custom-fonts/#from-packages # see https://flutter.dev/custom-fonts/#from-packages
flutter_native_splash: flutter_native_splash:
image: assets/logos/paperless_logo_green.png image: assets/logos/paperless_logo_green.png
color: "#f9f9f9" color: "#f9f9f9"

View File

@@ -4,6 +4,6 @@ pushd packages/paperless_api
flutter pub get flutter pub get
flutter pub run build_runner build --delete-conflicting-outputs flutter pub run build_runner build --delete-conflicting-outputs
popd popd
flutter pub get flutter packages pub get
flutter gen-l10n flutter gen-l10n
flutter pub run build_runner build --delete-conflicting-outputs flutter pub run build_runner build --delete-conflicting-outputs