Skip to content

Commit

Permalink
Merge pull request #125 from astubenbord/feature/highlighted-search-f…
Browse files Browse the repository at this point in the history
…ragments

Feature/highlighted search fragments
  • Loading branch information
astubenbord authored Feb 24, 2023
2 parents 2647d9b + df792d6 commit 3b30f20
Show file tree
Hide file tree
Showing 10 changed files with 151 additions and 91 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,15 +100,15 @@ If you want to manually install dependencies and build generated files, you can
#### Inside the project's root folder
4. Install the dependencies for the app
```sh
flutter pub get
flutter packages pub get
```
5. Build generated files for the app
```sh
flutter packages pub run build_runner build --delete-conflicting-outputs
```
6. Generate the localization files for the app
```sh
flutter pub run intl_utils:generate
flutter gen-l10n
```

### Build release version
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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:json_annotation/json_annotation.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';

Expand Down Expand Up @@ -33,7 +34,7 @@ class DocumentSearchCubit extends HydratedCubit<DocumentSearchState>
view: SearchView.results,
));
final searchFilter = DocumentFilter(
query: TextQuery.titleAndContent(query),
query: TextQuery.extended(query),
);

await updateFilter(filter: searchFilter);
Expand All @@ -48,6 +49,10 @@ class DocumentSearchCubit extends HydratedCubit<DocumentSearchState>
);
}

void updateViewType(ViewType viewType) {
emit(state.copyWith(viewType: viewType));
}

void removeHistoryEntry(String entry) {
emit(
state.copyWith(
Expand Down
6 changes: 6 additions & 0 deletions lib/features/document_search/cubit/document_search_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,13 @@ class DocumentSearchState extends DocumentPagingState {
final List<String> searchHistory;
final SearchView view;
final List<String> suggestions;
@JsonKey()
final ViewType viewType;
const DocumentSearchState({
this.view = SearchView.suggestions,
this.searchHistory = const [],
this.suggestions = const [],
this.viewType = ViewType.detailed,
super.filter,
super.hasLoaded,
super.isLoading,
Expand All @@ -27,6 +30,7 @@ class DocumentSearchState extends DocumentPagingState {
searchHistory,
suggestions,
view,
viewType,
];

@override
Expand All @@ -52,6 +56,7 @@ class DocumentSearchState extends DocumentPagingState {
DocumentFilter? filter,
List<String>? suggestions,
SearchView? view,
ViewType? viewType,
}) {
return DocumentSearchState(
value: value ?? this.value,
Expand All @@ -61,6 +66,7 @@ class DocumentSearchState extends DocumentPagingState {
searchHistory: searchHistory ?? this.searchHistory,
view: view ?? this.view,
suggestions: suggestions ?? this.suggestions,
viewType: viewType ?? this.viewType,
);
}

Expand Down
25 changes: 21 additions & 4 deletions lib/features/document_search/view/document_search_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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/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/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/routes/document_details_route.dart';
Expand Down Expand Up @@ -168,7 +170,7 @@ class _DocumentSearchPageState extends State<DocumentSearchPage> {
alignment: Alignment.center,
transform: Matrix4.rotationY(math.pi),
child: IconButton(
icon: Icon(Icons.arrow_outward),
icon: const Icon(Icons.arrow_outward),
onPressed: () {
_queryController.text = '$suggestion ';
_queryController.selection = TextSelection.fromPosition(
Expand All @@ -181,9 +183,23 @@ class _DocumentSearchPageState extends State<DocumentSearchPage> {
}

Widget _buildResultsView(DocumentSearchState state) {
final header = Text(
S.of(context)!.results,
style: Theme.of(context).textTheme.labelSmall,
final header = Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
S.of(context)!.results,
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();
return CustomScrollView(
slivers: [
Expand All @@ -196,6 +212,7 @@ class _DocumentSearchPageState extends State<DocumentSearchPage> {
)
else
SliverAdaptiveDocumentsView(
viewType: state.viewType,
documents: state.documents,
hasInternetConnection: true,
isLabelClickable: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ class SliverAdaptiveDocumentsView extends AdaptiveDocumentsView {
onDocumentTypeSelected: onDocumentTypeSelected,
onStoragePathSelected: onStoragePathSelected,
enableHeroAnimation: enableHeroAnimation,
highlights: document.searchHit?.highlights,
),
);
},
Expand Down
171 changes: 92 additions & 79 deletions lib/features/documents/view/widgets/items/document_detailed_item.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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/document_type/view/widgets/document_type_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 {
final String? highlights;
const DocumentDetailedItem({
super.key,
this.highlights,
required super.document,
required super.isSelected,
required super.isSelectionActive,
Expand All @@ -37,7 +40,9 @@ class DocumentDetailedItem extends DocumentItem {
padding.bottom -
kBottomNavigationBarHeight -
kToolbarHeight;
final maxHeight = min(500.0, availableHeight);
final maxHeight = highlights != null
? min(600.0, availableHeight)
: min(500.0, availableHeight);
return Card(
child: InkWell(
enableFeedback: true,
Expand All @@ -52,90 +57,98 @@ class DocumentDetailedItem extends DocumentItem {
onLongPress: () {
onSelected?.call(document);
},
child: Stack(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
ConstrainedBox(
constraints: BoxConstraints.tightFor(
width: double.infinity,
height: maxHeight / 2,
),
child: DocumentPreview(
document: document,
fit: BoxFit.cover,
alignment: Alignment.topCenter,
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
ConstrainedBox(
constraints: BoxConstraints.tightFor(
width: double.infinity,
height: maxHeight / 2,
),
child: DocumentPreview(
document: document,
fit: BoxFit.cover,
alignment: Alignment.topCenter,
Text(
DateFormat.yMMMMd().format(document.created),
style: Theme.of(context)
.textTheme
.bodySmall
?.apply(color: Theme.of(context).hintColor),
),
if (document.archiveSerialNumber != null)
Row(
children: [
Text(
'#${document.archiveSerialNumber}',
style: Theme.of(context)
.textTheme
.bodySmall
?.apply(color: Theme.of(context).hintColor),
),
],
),
],
).paddedLTRB(8, 8, 8, 4),
Text(
document.title,
style: Theme.of(context).textTheme.titleMedium,
maxLines: 2,
overflow: TextOverflow.ellipsis,
).paddedLTRB(8, 0, 8, 4),
Row(
children: [
const Icon(
Icons.person_outline,
size: 16,
).paddedOnly(right: 4.0),
CorrespondentWidget(
onSelected: onCorrespondentSelected,
textStyle: Theme.of(context).textTheme.titleSmall?.apply(
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
correspondentId: document.correspondent,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
DateFormat.yMMMMd().format(document.created),
style: Theme.of(context)
.textTheme
.bodySmall
?.apply(color: Theme.of(context).hintColor),
),
if (document.archiveSerialNumber != null)
Row(
children: [
Text(
'#${document.archiveSerialNumber}',
style: Theme.of(context)
.textTheme
.bodySmall
?.apply(color: Theme.of(context).hintColor),
),
],
],
).paddedLTRB(8, 0, 8, 4),
Row(
children: [
const Icon(
Icons.description_outlined,
size: 16,
).paddedOnly(right: 4.0),
DocumentTypeWidget(
onSelected: onDocumentTypeSelected,
textStyle: Theme.of(context).textTheme.titleSmall?.apply(
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
],
).paddedLTRB(8, 8, 8, 4),
Text(
document.title,
style: Theme.of(context).textTheme.titleMedium,
maxLines: 2,
overflow: TextOverflow.ellipsis,
).paddedLTRB(8, 0, 8, 4),
Row(
children: [
const Icon(
Icons.person_outline,
size: 16,
).paddedOnly(right: 4.0),
CorrespondentWidget(
onSelected: onCorrespondentSelected,
textStyle: Theme.of(context).textTheme.titleSmall?.apply(
color:
Theme.of(context).colorScheme.onSurfaceVariant,
),
correspondentId: document.correspondent,
),
],
).paddedLTRB(8, 0, 8, 4),
Row(
children: [
const Icon(
Icons.description_outlined,
size: 16,
).paddedOnly(right: 4.0),
DocumentTypeWidget(
onSelected: onDocumentTypeSelected,
textStyle: Theme.of(context).textTheme.titleSmall?.apply(
color:
Theme.of(context).colorScheme.onSurfaceVariant,
),
documentTypeId: document.documentType,
),
],
).paddedLTRB(8, 0, 8, 4),
TagsWidget(
isMultiLine: false,
tagIds: document.tags,
).padded(),
documentTypeId: document.documentType,
),
],
),
).paddedLTRB(8, 0, 8, 4),
TagsWidget(
isMultiLine: false,
tagIds: document.tags,
).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(),
],
),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ class ViewTypeSelectionWidget extends StatelessWidget {
icon = Icons.article_outlined;
break;
}

return PopupMenuButton<ViewType>(
position: PopupMenuPosition.under,
initialValue: viewType,
icon: Icon(icon),
itemBuilder: (context) => [
Expand Down
16 changes: 16 additions & 0 deletions pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,14 @@ packages:
url: "https://pub.dev"
source: hosted
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:
dependency: transitive
description:
Expand Down Expand Up @@ -1005,6 +1013,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.1"
numerus:
dependency: transitive
description:
name: numerus
sha256: "436759d84f233b40107d0cc31cfa92d24e0960afeb2e506be70926d4cddffd9e"
url: "https://pub.dev"
source: hosted
version: "2.0.0"
octo_image:
dependency: transitive
description:
Expand Down
Loading

0 comments on commit 3b30f20

Please sign in to comment.