mirror of
https://github.com/Xevion/paperless-mobile.git
synced 2025-12-08 16:07:52 -06:00
feat: Add query highlight fragments to detailed view, fix build
This commit is contained in:
@@ -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(
|
||||||
|
|||||||
@@ -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,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -146,6 +146,7 @@ class SliverAdaptiveDocumentsView extends AdaptiveDocumentsView {
|
|||||||
onDocumentTypeSelected: onDocumentTypeSelected,
|
onDocumentTypeSelected: onDocumentTypeSelected,
|
||||||
onStoragePathSelected: onStoragePathSelected,
|
onStoragePathSelected: onStoragePathSelected,
|
||||||
enableHeroAnimation: enableHeroAnimation,
|
enableHeroAnimation: enableHeroAnimation,
|
||||||
|
highlights: document.searchHit?.highlights,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -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) => [
|
||||||
|
|||||||
16
pubspec.lock
16
pubspec.lock
@@ -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:
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user