Merge pull request #275 from astubenbord/fix/allow-empty-document-titles

Fix/allow empty document titles
This commit is contained in:
Anton Stubenbord
2023-10-10 16:42:47 +02:00
committed by GitHub
29 changed files with 337 additions and 369 deletions

View File

@@ -5,6 +5,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:paperless_mobile/constants.dart'; import 'package:paperless_mobile/constants.dart';
import 'package:paperless_mobile/core/database/tables/local_user_account.dart'; import 'package:paperless_mobile/core/database/tables/local_user_account.dart';
import 'package:paperless_mobile/core/widgets/hint_card.dart';
import 'package:paperless_mobile/core/widgets/paperless_logo.dart'; import 'package:paperless_mobile/core/widgets/paperless_logo.dart';
import 'package:paperless_mobile/extensions/flutter_extensions.dart'; import 'package:paperless_mobile/extensions/flutter_extensions.dart';
import 'package:paperless_mobile/features/documents/cubit/documents_cubit.dart'; import 'package:paperless_mobile/features/documents/cubit/documents_cubit.dart';
@@ -12,6 +13,7 @@ import 'package:paperless_mobile/features/saved_view/cubit/saved_view_cubit.dart
import 'package:paperless_mobile/features/sharing/cubit/receive_share_cubit.dart'; import 'package:paperless_mobile/features/sharing/cubit/receive_share_cubit.dart';
import 'package:paperless_mobile/generated/l10n/app_localizations.dart'; import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
import 'package:paperless_mobile/routes/typed/branches/documents_route.dart'; import 'package:paperless_mobile/routes/typed/branches/documents_route.dart';
import 'package:paperless_mobile/routes/typed/branches/saved_views_route.dart';
import 'package:paperless_mobile/routes/typed/branches/upload_queue_route.dart'; import 'package:paperless_mobile/routes/typed/branches/upload_queue_route.dart';
import 'package:paperless_mobile/routes/typed/shells/authenticated_route.dart'; import 'package:paperless_mobile/routes/typed/shells/authenticated_route.dart';
import 'package:paperless_mobile/routes/typed/top_level/settings_route.dart'; import 'package:paperless_mobile/routes/typed/top_level/settings_route.dart';
@@ -198,7 +200,26 @@ class AppDrawer extends StatelessWidget {
.where((element) => element.showInSidebar) .where((element) => element.showInSidebar)
.toList(); .toList();
if (sidebarViews.isEmpty) { if (sidebarViews.isEmpty) {
return Text("Nothing to show here.").paddedOnly(left: 16); return Column(
children: [
Text(
S.of(context)!.youDidNotSaveAnyViewsYet,
style: Theme.of(context).textTheme.bodySmall,
).paddedOnly(
left: 16,
right: 16,
),
TextButton.icon(
onPressed: () {
Scaffold.of(context).closeDrawer();
const CreateSavedViewRoute(showInSidebar: true)
.push(context);
},
icon: Icon(Icons.add),
label: Text(S.of(context)!.newView),
),
],
);
} }
return Expanded( return Expanded(
child: ListView.builder( child: ListView.builder(

View File

@@ -214,7 +214,7 @@ class DocumentDetailsCubit extends Cubit<DocumentDetailsState> {
throw Exception("An error occurred while downloading the document."); throw Exception("An error occurred while downloading the document.");
} }
Printing.layoutPdf( Printing.layoutPdf(
name: state.document.title ?? 'Document', name: state.document.title,
onLayout: (format) => file.readAsBytesSync(), onLayout: (format) => file.readAsBytesSync(),
); );
} }

View File

@@ -26,6 +26,7 @@ import 'package:paperless_mobile/helpers/connectivity_aware_action_wrapper.dart'
import 'package:paperless_mobile/helpers/message_helpers.dart'; import 'package:paperless_mobile/helpers/message_helpers.dart';
import 'package:paperless_mobile/routes/typed/branches/documents_route.dart'; import 'package:paperless_mobile/routes/typed/branches/documents_route.dart';
import 'package:paperless_mobile/routes/typed/shells/authenticated_route.dart'; import 'package:paperless_mobile/routes/typed/shells/authenticated_route.dart';
import 'package:paperless_mobile/theme.dart';
class DocumentDetailsPage extends StatefulWidget { class DocumentDetailsPage extends StatefulWidget {
final bool isLabelClickable; final bool isLabelClickable;
@@ -57,136 +58,100 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
context.watch<LocalUserAccount>().hasMultiUserSupport; context.watch<LocalUserAccount>().hasMultiUserSupport;
final tabLength = 4 + (hasMultiUserSupport && false ? 1 : 0); final tabLength = 4 + (hasMultiUserSupport && false ? 1 : 0);
final title = context.watch<DocumentDetailsCubit>().state.document.title; final title = context.watch<DocumentDetailsCubit>().state.document.title;
return WillPopScope( return AnnotatedRegion(
onWillPop: () async { value: buildOverlayStyle(
Navigator.of(context) Theme.of(context),
.pop(context.read<DocumentDetailsCubit>().state.document); systemNavigationBarColor: Theme.of(context).bottomAppBarTheme.color,
return false; ),
}, child: WillPopScope(
child: DefaultTabController( onWillPop: () async {
length: tabLength, Navigator.of(context)
child: BlocListener<ConnectivityCubit, ConnectivityState>( .pop(context.read<DocumentDetailsCubit>().state.document);
listenWhen: (previous, current) => return false;
!previous.isConnected && current.isConnected, },
listener: (context, state) { child: DefaultTabController(
context.read<DocumentDetailsCubit>().loadMetaData(); length: tabLength,
}, child: BlocListener<ConnectivityCubit, ConnectivityState>(
child: Scaffold( listenWhen: (previous, current) =>
extendBodyBehindAppBar: false, !previous.isConnected && current.isConnected,
floatingActionButtonLocation: listener: (context, state) {
FloatingActionButtonLocation.endDocked, context.read<DocumentDetailsCubit>().loadMetaData();
floatingActionButton: _buildEditButton(), },
bottomNavigationBar: _buildBottomAppBar(), child: Scaffold(
body: NestedScrollView( extendBodyBehindAppBar: false,
headerSliverBuilder: (context, innerBoxIsScrolled) => [ floatingActionButtonLocation:
SliverOverlapAbsorber( FloatingActionButtonLocation.endDocked,
handle: floatingActionButton: _buildEditButton(),
NestedScrollView.sliverOverlapAbsorberHandleFor(context), bottomNavigationBar: _buildBottomAppBar(),
sliver: SliverAppBar( body: NestedScrollView(
title: title != null ? Text(title) : null, headerSliverBuilder: (context, innerBoxIsScrolled) => [
leading: const BackButton(), SliverOverlapAbsorber(
pinned: true, handle: NestedScrollView.sliverOverlapAbsorberHandleFor(
forceElevated: innerBoxIsScrolled, context),
collapsedHeight: kToolbarHeight, sliver: SliverAppBar(
expandedHeight: 250.0, title: Text(title),
flexibleSpace: FlexibleSpaceBar( leading: const BackButton(),
background: BlocBuilder<DocumentDetailsCubit, pinned: true,
DocumentDetailsState>( forceElevated: innerBoxIsScrolled,
builder: (context, state) { collapsedHeight: kToolbarHeight,
return Hero( expandedHeight: 250.0,
tag: "thumb_${state.document.id}", flexibleSpace: FlexibleSpaceBar(
child: GestureDetector( background: BlocBuilder<DocumentDetailsCubit,
onTap: () { DocumentDetailsState>(
DocumentPreviewRoute($extra: state.document) builder: (context, state) {
.push(context); return Hero(
}, tag: "thumb_${state.document.id}",
child: Stack( child: GestureDetector(
alignment: Alignment.topCenter, onTap: () {
children: [ DocumentPreviewRoute($extra: state.document)
Positioned.fill( .push(context);
child: DocumentPreview( },
enableHero: false, child: Stack(
document: state.document, alignment: Alignment.topCenter,
fit: BoxFit.cover, children: [
alignment: Alignment.topCenter, Positioned.fill(
child: DocumentPreview(
enableHero: false,
document: state.document,
fit: BoxFit.cover,
alignment: Alignment.topCenter,
),
), ),
), Positioned.fill(
Positioned.fill( child: DecoratedBox(
child: DecoratedBox( decoration: BoxDecoration(
decoration: BoxDecoration( gradient: LinearGradient(
gradient: LinearGradient( stops: [0.2, 0.4],
stops: [0.2, 0.4], colors: [
colors: [ Theme.of(context)
Theme.of(context) .colorScheme
.colorScheme .background
.background .withOpacity(0.6),
.withOpacity(0.6), Theme.of(context)
Theme.of(context) .colorScheme
.colorScheme .background
.background .withOpacity(0.3),
.withOpacity(0.3), ],
], begin: Alignment.topCenter,
begin: Alignment.topCenter, end: Alignment.bottomCenter,
end: Alignment.bottomCenter, ),
), ),
), ),
), ),
), ],
], ),
), ),
), );
); },
}, ),
), ),
), bottom: ColoredTabBar(
bottom: ColoredTabBar( tabBar: TabBar(
tabBar: TabBar( isScrollable: true,
isScrollable: true, tabs: [
tabs: [
Tab(
child: Text(
S.of(context)!.overview,
style: TextStyle(
color: Theme.of(context)
.colorScheme
.onPrimaryContainer,
),
),
),
Tab(
child: Text(
S.of(context)!.content,
style: TextStyle(
color: Theme.of(context)
.colorScheme
.onPrimaryContainer,
),
),
),
Tab(
child: Text(
S.of(context)!.metaData,
style: TextStyle(
color: Theme.of(context)
.colorScheme
.onPrimaryContainer,
),
),
),
Tab(
child: Text(
S.of(context)!.similarDocuments,
style: TextStyle(
color: Theme.of(context)
.colorScheme
.onPrimaryContainer,
),
),
),
if (hasMultiUserSupport && false)
Tab( Tab(
child: Text( child: Text(
"Permissions", S.of(context)!.overview,
style: TextStyle( style: TextStyle(
color: Theme.of(context) color: Theme.of(context)
.colorScheme .colorScheme
@@ -194,80 +159,111 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
), ),
), ),
), ),
], Tab(
child: Text(
S.of(context)!.content,
style: TextStyle(
color: Theme.of(context)
.colorScheme
.onPrimaryContainer,
),
),
),
Tab(
child: Text(
S.of(context)!.metaData,
style: TextStyle(
color: Theme.of(context)
.colorScheme
.onPrimaryContainer,
),
),
),
Tab(
child: Text(
S.of(context)!.similarDocuments,
style: TextStyle(
color: Theme.of(context)
.colorScheme
.onPrimaryContainer,
),
),
),
if (hasMultiUserSupport && false)
Tab(
child: Text(
"Permissions",
style: TextStyle(
color: Theme.of(context)
.colorScheme
.onPrimaryContainer,
),
),
),
],
),
), ),
), ),
), ),
), ],
], body: BlocBuilder<DocumentDetailsCubit, DocumentDetailsState>(
body: BlocBuilder<DocumentDetailsCubit, DocumentDetailsState>( builder: (context, state) {
builder: (context, state) { return BlocProvider(
return BlocProvider( create: (context) => SimilarDocumentsCubit(
create: (context) => SimilarDocumentsCubit( context.read(),
context.read(), context.read(),
context.read(), context.read(),
context.read(), context.read(),
context.read(), documentId: state.document.id,
documentId: state.document.id,
),
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 16,
horizontal: 16,
), ),
child: TabBarView( child: Padding(
children: [ padding: const EdgeInsets.symmetric(
CustomScrollView( vertical: 16,
slivers: [ horizontal: 16,
SliverOverlapInjector( ),
handle: NestedScrollView child: TabBarView(
.sliverOverlapAbsorberHandleFor(context), children: [
), CustomScrollView(
DocumentOverviewWidget( slivers: [
document: state.document, SliverOverlapInjector(
itemSpacing: _itemSpacing, handle: NestedScrollView
queryString: widget.titleAndContentQueryString, .sliverOverlapAbsorberHandleFor(context),
), ),
], DocumentOverviewWidget(
), document: state.document,
CustomScrollView( itemSpacing: _itemSpacing,
slivers: [ queryString:
SliverOverlapInjector( widget.titleAndContentQueryString,
handle: NestedScrollView ),
.sliverOverlapAbsorberHandleFor(context), ],
), ),
DocumentContentWidget( CustomScrollView(
isFullContentLoaded: state.isFullContentLoaded, slivers: [
document: state.document, SliverOverlapInjector(
queryString: widget.titleAndContentQueryString, handle: NestedScrollView
), .sliverOverlapAbsorberHandleFor(context),
], ),
), DocumentContentWidget(
CustomScrollView( isFullContentLoaded:
slivers: [ state.isFullContentLoaded,
SliverOverlapInjector( document: state.document,
handle: NestedScrollView queryString:
.sliverOverlapAbsorberHandleFor(context), widget.titleAndContentQueryString,
), ),
DocumentMetaDataWidget( ],
document: state.document, ),
itemSpacing: _itemSpacing, CustomScrollView(
), slivers: [
], SliverOverlapInjector(
), handle: NestedScrollView
CustomScrollView( .sliverOverlapAbsorberHandleFor(context),
controller: _pagingScrollController, ),
slivers: [ DocumentMetaDataWidget(
SliverOverlapInjector( document: state.document,
handle: NestedScrollView itemSpacing: _itemSpacing,
.sliverOverlapAbsorberHandleFor(context), ),
), ],
SimilarDocumentsView( ),
pagingScrollController: _pagingScrollController,
),
],
),
if (hasMultiUserSupport && false)
CustomScrollView( CustomScrollView(
controller: _pagingScrollController, controller: _pagingScrollController,
slivers: [ slivers: [
@@ -275,16 +271,32 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
handle: NestedScrollView handle: NestedScrollView
.sliverOverlapAbsorberHandleFor(context), .sliverOverlapAbsorberHandleFor(context),
), ),
DocumentPermissionsWidget( SimilarDocumentsView(
document: state.document, pagingScrollController:
_pagingScrollController,
), ),
], ],
), ),
], if (hasMultiUserSupport && false)
CustomScrollView(
controller: _pagingScrollController,
slivers: [
SliverOverlapInjector(
handle: NestedScrollView
.sliverOverlapAbsorberHandleFor(
context),
),
DocumentPermissionsWidget(
document: state.document,
),
],
),
],
),
), ),
), );
); },
}, ),
), ),
), ),
), ),

View File

@@ -29,11 +29,11 @@ class DocumentOverviewWidget extends StatelessWidget {
final availableLabels = context.watch<LabelRepository>().state; final availableLabels = context.watch<LabelRepository>().state;
return SliverList.list( return SliverList.list(
children: [ children: [
if (document.title != null) if (document.title.isNotEmpty)
DetailsItem( DetailsItem(
label: S.of(context)!.title, label: S.of(context)!.title,
content: HighlightedText( content: HighlightedText(
text: document.title!, text: document.title,
highlights: queryString?.split(" ") ?? [], highlights: queryString?.split(" ") ?? [],
style: Theme.of(context).textTheme.bodyLarge, style: Theme.of(context).textTheme.bodyLarge,
), ),

View File

@@ -2,6 +2,7 @@ import 'dart:async';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart'; import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:flutter_typeahead/flutter_typeahead.dart'; import 'package:flutter_typeahead/flutter_typeahead.dart';
@@ -9,7 +10,6 @@ import 'package:go_router/go_router.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:paperless_api/paperless_api.dart'; import 'package:paperless_api/paperless_api.dart';
import 'package:paperless_mobile/core/database/tables/local_user_account.dart'; import 'package:paperless_mobile/core/database/tables/local_user_account.dart';
import 'package:paperless_mobile/core/notifier/document_changed_notifier.dart';
import 'package:paperless_mobile/core/widgets/dialog_utils/dialog_cancel_button.dart'; import 'package:paperless_mobile/core/widgets/dialog_utils/dialog_cancel_button.dart';
import 'package:paperless_mobile/core/widgets/dialog_utils/pop_with_unsaved_changes.dart'; import 'package:paperless_mobile/core/widgets/dialog_utils/pop_with_unsaved_changes.dart';
import 'package:paperless_mobile/core/workarounds/colored_chip.dart'; import 'package:paperless_mobile/core/workarounds/colored_chip.dart';
@@ -21,6 +21,7 @@ import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
import 'package:paperless_mobile/helpers/message_helpers.dart'; import 'package:paperless_mobile/helpers/message_helpers.dart';
import 'package:paperless_mobile/routes/typed/branches/labels_route.dart'; import 'package:paperless_mobile/routes/typed/branches/labels_route.dart';
import 'package:paperless_mobile/routes/typed/shells/authenticated_route.dart'; import 'package:paperless_mobile/routes/typed/shells/authenticated_route.dart';
import 'package:paperless_mobile/theme.dart';
class DocumentEditPage extends StatefulWidget { class DocumentEditPage extends StatefulWidget {
const DocumentEditPage({ const DocumentEditPage({
@@ -42,12 +43,6 @@ class _DocumentEditPageState extends State<DocumentEditPage> {
final _formKey = GlobalKey<FormBuilderState>(); final _formKey = GlobalKey<FormBuilderState>();
@override
void didUpdateWidget(covariant DocumentEditPage oldWidget) {
super.didUpdateWidget(oldWidget);
print("WIDGET CONFIGURATION CHANGED?!?!?");
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final currentUser = context.watch<LocalUserAccount>().paperlessUser; final currentUser = context.watch<LocalUserAccount>().paperlessUser;
@@ -404,12 +399,6 @@ class _DocumentEditPageState extends State<DocumentEditPage> {
Widget _buildTitleFormField(String? initialTitle) { Widget _buildTitleFormField(String? initialTitle) {
return FormBuilderTextField( return FormBuilderTextField(
name: fkTitle, name: fkTitle,
validator: (value) {
if (value?.trim().isEmpty ?? true) {
return S.of(context)!.thisFieldIsRequired;
}
return null;
},
decoration: InputDecoration( decoration: InputDecoration(
label: Text(S.of(context)!.title), label: Text(S.of(context)!.title),
), ),
@@ -478,55 +467,3 @@ class _DocumentEditPageState extends State<DocumentEditPage> {
).padded(); ).padded();
} }
} }
// class SampleWidget extends StatefulWidget {
// const SampleWidget({super.key});
// @override
// State<SampleWidget> createState() => _SampleWidgetState();
// }
// class _SampleWidgetState extends State<SampleWidget> {
// @override
// Widget build(BuildContext context) {
// return BlocBuilder<OptionsBloc, OptionsState>(
// builder: (context, state) {
// return OptionsFormField(
// options: state.options,
// onAddOption: (option) {
// // This will call the repository and will cause a new state containing the new option to be emitted.
// context.read<OptionsBloc>().addOption(option);
// },
// );
// },
// );
// }
// }
// class OptionsFormField extends StatefulWidget {
// final List<Option> options;
// final void Function(Option option) onAddOption;
// const OptionsFormField({
// super.key,
// required this.options,
// required this.onAddOption,
// });
// @override
// State<OptionsFormField> createState() => _OptionsFormFieldState();
// }
// class _OptionsFormFieldState extends State<OptionsFormField> {
// final TextEditingController _controller;
// @override
// Widget build(BuildContext context) {
// return TextFormField(
// onTap: () async {
// // User creates new option...
// final Option option = await showOptionCreationForm();
// widget.onAddOption(option);
// },
// );
// }
// }

View File

@@ -20,7 +20,7 @@ class DeleteDocumentConfirmationDialog extends StatelessWidget {
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
Text( Text(
document.title ?? document.originalFileName ?? '-', document.title.isEmpty ? '(no title)' : document.title,
maxLines: 2, maxLines: 2,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: const TextStyle( style: const TextStyle(

View File

@@ -111,7 +111,7 @@ class DocumentDetailedItem extends DocumentItem {
], ],
).paddedLTRB(8, 8, 8, 4), ).paddedLTRB(8, 8, 8, 4),
Text( Text(
document.title ?? '-', document.title.isEmpty ? '-' : document.title,
style: Theme.of(context).textTheme.titleMedium, style: Theme.of(context).textTheme.titleMedium,
maxLines: 2, maxLines: 2,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,

View File

@@ -113,7 +113,7 @@ class DocumentGridItem extends DocumentItem {
Padding( Padding(
padding: const EdgeInsets.only(bottom: 8.0), padding: const EdgeInsets.only(bottom: 8.0),
child: Text( child: Text(
document.title ?? '-', document.title.isEmpty ? '-' : document.title,
maxLines: 3, maxLines: 3,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: Theme.of(context).textTheme.titleMedium, style: Theme.of(context).textTheme.titleMedium,

View File

@@ -58,7 +58,7 @@ class DocumentListItem extends DocumentItem {
], ],
), ),
Text( Text(
document.title ?? '-', document.title.isEmpty ? '-' : document.title,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
maxLines: 1, maxLines: 1,
), ),

View File

@@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
import 'package:paperless_api/paperless_api.dart'; import 'package:paperless_api/paperless_api.dart';
import 'package:paperless_mobile/extensions/flutter_extensions.dart'; import 'package:paperless_mobile/extensions/flutter_extensions.dart';
import 'package:paperless_mobile/routes/typed/branches/saved_views_route.dart'; import 'package:paperless_mobile/routes/typed/branches/saved_views_route.dart';
import 'package:paperless_mobile/routes/typed/shells/authenticated_route.dart';
class SavedViewChip extends StatefulWidget { class SavedViewChip extends StatefulWidget {
final SavedView view; final SavedView view;

View File

@@ -8,6 +8,7 @@ import 'package:paperless_mobile/features/saved_view/cubit/saved_view_cubit.dart
import 'package:paperless_mobile/generated/l10n/app_localizations.dart'; import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
import 'package:paperless_mobile/helpers/connectivity_aware_action_wrapper.dart'; import 'package:paperless_mobile/helpers/connectivity_aware_action_wrapper.dart';
import 'package:paperless_mobile/routes/typed/branches/saved_views_route.dart'; import 'package:paperless_mobile/routes/typed/branches/saved_views_route.dart';
import 'package:paperless_mobile/routes/typed/shells/authenticated_route.dart';
class SavedViewsWidget extends StatefulWidget { class SavedViewsWidget extends StatefulWidget {
final void Function(SavedView view) onViewSelected; final void Function(SavedView view) onViewSelected;
@@ -126,8 +127,10 @@ class _SavedViewsWidgetState extends State<SavedViewsWidget>
.maybeMap( .maybeMap(
loaded: (value) { loaded: (value) {
if (value.savedViews.isEmpty) { if (value.savedViews.isEmpty) {
return Text(S.of(context)!.youDidNotSaveAnyViewsYet) return Text(
.paddedOnly(left: 16); S.of(context)!.youDidNotSaveAnyViewsYet,
style: Theme.of(context).textTheme.bodySmall,
).paddedOnly(left: 16);
} }
return SizedBox( return SizedBox(
@@ -172,8 +175,9 @@ class _SavedViewsWidgetState extends State<SavedViewsWidget>
), ),
); );
}, },
error: (_) => Text(S.of(context)!.couldNotLoadSavedViews) error: (_) => Text(
.paddedOnly(left: 16), S.of(context)!.couldNotLoadSavedViews,
).paddedOnly(left: 16),
orElse: _buildLoadingState, orElse: _buildLoadingState,
) )
.paddedOnly(top: 16), .paddedOnly(top: 16),
@@ -184,7 +188,8 @@ class _SavedViewsWidgetState extends State<SavedViewsWidget>
child: ConnectivityAwareActionWrapper( child: ConnectivityAwareActionWrapper(
child: TextButton.icon( child: TextButton.icon(
onPressed: () { onPressed: () {
CreateSavedViewRoute(widget.filter).push(context); CreateSavedViewRoute($extra: widget.filter)
.push(context);
}, },
icon: const Icon(Icons.add), icon: const Icon(Icons.add),
label: Text(S.of(context)!.newView), label: Text(S.of(context)!.newView),

View File

@@ -44,7 +44,7 @@ class BulkDeleteConfirmationDialog extends StatelessWidget {
return ListTile( return ListTile(
dense: true, dense: true,
title: Text( title: Text(
doc.title ?? doc.originalFileName ?? '-', doc.title.isEmpty ? '-' : doc.title,
maxLines: 1, maxLines: 1,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: const TextStyle( style: const TextStyle(

View File

@@ -351,7 +351,7 @@ class _InboxItemState extends State<InboxItem> {
Text _buildTitle() { Text _buildTitle() {
return Text( return Text(
widget.document.title ?? '-', widget.document.title.isEmpty ? '-' : widget.document.title,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
maxLines: 2, maxLines: 2,
style: Theme.of(context).textTheme.titleSmall, style: Theme.of(context).textTheme.titleSmall,

View File

@@ -12,6 +12,7 @@ import 'package:paperless_mobile/features/saved_view_details/view/saved_view_pre
import 'package:paperless_mobile/generated/l10n/app_localizations.dart'; import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
import 'package:paperless_mobile/routes/typed/branches/documents_route.dart'; import 'package:paperless_mobile/routes/typed/branches/documents_route.dart';
import 'package:paperless_mobile/routes/typed/branches/inbox_route.dart'; import 'package:paperless_mobile/routes/typed/branches/inbox_route.dart';
import 'package:paperless_mobile/routes/typed/branches/saved_views_route.dart';
import 'package:paperless_mobile/routes/typed/shells/authenticated_route.dart'; import 'package:paperless_mobile/routes/typed/shells/authenticated_route.dart';
class LandingPage extends StatefulWidget { class LandingPage extends StatefulWidget {
@@ -84,10 +85,16 @@ class _LandingPageState extends State<LandingPage> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text(S.of(context)!.noSavedViewOnHomepageHint) Text(
.padded(), S.of(context)!.youDidNotSaveAnyViewsYet,
style: Theme.of(context).textTheme.bodySmall,
).padded(),
TextButton.icon( TextButton.icon(
onPressed: () {}, onPressed: () {
const CreateSavedViewRoute(
showOnDashboard: true,
).push(context);
},
icon: const Icon(Icons.add), icon: const Icon(Icons.add),
label: Text(S.of(context)!.newView), label: Text(S.of(context)!.newView),
) )

View File

@@ -3,6 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart'; import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:paperless_api/paperless_api.dart'; import 'package:paperless_api/paperless_api.dart';
import 'package:paperless_mobile/core/widgets/hint_card.dart';
import 'package:paperless_mobile/features/saved_view/cubit/saved_view_cubit.dart'; import 'package:paperless_mobile/features/saved_view/cubit/saved_view_cubit.dart';
import 'package:paperless_mobile/generated/l10n/app_localizations.dart'; import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
@@ -12,9 +13,13 @@ const _fkShowInSidebar = 'show_in_sidebar';
class AddSavedViewPage extends StatefulWidget { class AddSavedViewPage extends StatefulWidget {
final DocumentFilter? initialFilter; final DocumentFilter? initialFilter;
final bool? showOnDashboard;
final bool? showInSidebar;
const AddSavedViewPage({ const AddSavedViewPage({
super.key, super.key,
this.initialFilter, this.initialFilter,
this.showOnDashboard,
this.showInSidebar,
}); });
@override @override
@@ -59,7 +64,7 @@ class _AddSavedViewPageState extends State<AddSavedViewPage> {
), ),
FormBuilderField<bool>( FormBuilderField<bool>(
name: _fkShowOnDashboard, name: _fkShowOnDashboard,
initialValue: false, initialValue: widget.showOnDashboard ?? false,
builder: (field) { builder: (field) {
return CheckboxListTile( return CheckboxListTile(
value: field.value, value: field.value,
@@ -70,7 +75,7 @@ class _AddSavedViewPageState extends State<AddSavedViewPage> {
), ),
FormBuilderField<bool>( FormBuilderField<bool>(
name: _fkShowInSidebar, name: _fkShowInSidebar,
initialValue: false, initialValue: widget.showInSidebar ?? false,
builder: (field) { builder: (field) {
return CheckboxListTile( return CheckboxListTile(
value: field.value, value: field.value,
@@ -82,6 +87,14 @@ class _AddSavedViewPageState extends State<AddSavedViewPage> {
], ],
), ),
), ),
//TODO: INTL or remove
HintCard(
hintText:
"Saved views can currently only be edited by changing the "
"document filter. Therefore, go to the documents page, select "
"this view, add the filters you want this view to have and "
"save it by pressing 'Save changes' in the view menu.",
),
], ],
), ),
), ),

View File

@@ -873,7 +873,7 @@
"@donate": { "@donate": {
"description": "Label of the in-app donate button" "description": "Label of the in-app donate button"
}, },
"donationDialogContent": "Thank you for considering to support this app! Due to both Google's and Apple's Payment Policies, no links leading to donations may be displayed in-app. Not even linking to the project's repository page appears to be allowed in this context. Therefore, maybe have a look at the 'Donations' section in the project's README. Your support is much appreciated and keeps the development of this app alive. Thanks!", "donationDialogContent": "Gràcies per considerar donar suport a aquesta aplicació! A causa de les polítiques de pagament de Google i d'Apple, no es pot mostrar cap enllaç a les donacions a l'aplicació. Ni tan sols l'enllaç a la pàgina del repositori del projecte sembla que estigui permès en aquest context. Per tant, potser feu una ullada a la secció 'Donacions' del README del projecte. El vostre suport és molt apreciat i manté viu el desenvolupament d'aquesta aplicació. Gràcies!",
"@donationDialogContent": { "@donationDialogContent": {
"description": "Text displayed in the donation dialog" "description": "Text displayed in the donation dialog"
}, },
@@ -897,44 +897,44 @@
"@couldNotDeleteStoragePath": { "@couldNotDeleteStoragePath": {
"description": "Message shown when a storage path could not be deleted" "description": "Message shown when a storage path could not be deleted"
}, },
"couldNotUpdateCorrespondent": "Could not update correspondent, please try again.", "couldNotUpdateCorrespondent": "No es pot actualitzar corresponsal, prova de nou.",
"@couldNotUpdateCorrespondent": { "@couldNotUpdateCorrespondent": {
"description": "Message shown when a correspondent could not be updated" "description": "Message shown when a correspondent could not be updated"
}, },
"couldNotUpdateDocumentType": "Could not update document type, please try again.", "couldNotUpdateDocumentType": "No es pot actualitzar tipus de document, prova de nou.",
"@couldNotUpdateDocumentType": { "@couldNotUpdateDocumentType": {
"description": "Message shown when a document type could not be updated" "description": "Message shown when a document type could not be updated"
}, },
"couldNotUpdateTag": "Could not update tag, please try again.", "couldNotUpdateTag": "No es pot actualitzar etiqueta, prova de nou.",
"@couldNotUpdateTag": { "@couldNotUpdateTag": {
"description": "Message shown when a tag could not be updated" "description": "Message shown when a tag could not be updated"
}, },
"couldNotLoadServerInformation": "Could not load server information.", "couldNotLoadServerInformation": "No es pot carregar informació del servidor.",
"@couldNotLoadServerInformation": { "@couldNotLoadServerInformation": {
"description": "Message shown when the server information could not be loaded" "description": "Message shown when the server information could not be loaded"
}, },
"couldNotLoadStatistics": "Could not load server statistics.", "couldNotLoadStatistics": "No es poden carregar estastiques del servidor.",
"@couldNotLoadStatistics": { "@couldNotLoadStatistics": {
"description": "Message shown when the server statistics could not be loaded" "description": "Message shown when the server statistics could not be loaded"
}, },
"couldNotLoadUISettings": "Could not load UI settings.", "couldNotLoadUISettings": "No es pot carregar l'interfície.",
"@couldNotLoadUISettings": { "@couldNotLoadUISettings": {
"description": "Message shown when the UI settings could not be loaded" "description": "Message shown when the UI settings could not be loaded"
}, },
"couldNotLoadTasks": "Could not load tasks.", "couldNotLoadTasks": "No es poden carregar les tasques.",
"@couldNotLoadTasks": { "@couldNotLoadTasks": {
"description": "Message shown when the tasks (e.g. document consumed) could not be loaded" "description": "Message shown when the tasks (e.g. document consumed) could not be loaded"
}, },
"userNotFound": "User could not be found.", "userNotFound": "Usuari no trobat.",
"@userNotFound": { "@userNotFound": {
"description": "Message shown when the specified user (e.g. by id) could not be found" "description": "Message shown when the specified user (e.g. by id) could not be found"
}, },
"couldNotUpdateSavedView": "Could not update saved view, please try again.", "couldNotUpdateSavedView": "No es poden acualitzar les vistes desades, prova de nou.",
"@couldNotUpdateSavedView": { "@couldNotUpdateSavedView": {
"description": "Message shown when a saved view could not be updated" "description": "Message shown when a saved view could not be updated"
}, },
"couldNotUpdateStoragePath": "Could not update storage path, please try again.", "couldNotUpdateStoragePath": "No es pot actualitzar la ruta emmagatzematge, prova de nou.",
"savedViewSuccessfullyUpdated": "Saved view successfully updated.", "savedViewSuccessfullyUpdated": "Vista desada actualitzada correctament.",
"@savedViewSuccessfullyUpdated": { "@savedViewSuccessfullyUpdated": {
"description": "Message shown when a saved view was successfully updated." "description": "Message shown when a saved view was successfully updated."
}, },
@@ -942,11 +942,11 @@
"@discardChanges": { "@discardChanges": {
"description": "Title of the alert dialog shown when a user tries to close a view with unsaved changes." "description": "Title of the alert dialog shown when a user tries to close a view with unsaved changes."
}, },
"savedViewChangedDialogContent": "The filter conditions of the active view have changed. By resetting the filter, these changes will be lost. Do you still wish to continue?", "savedViewChangedDialogContent": "Les condicions del filtre de la vista activa han canviat. En restablir el filtre, aquests canvis es perdran. Encara vols continuar?",
"@savedViewChangedDialogContent": { "@savedViewChangedDialogContent": {
"description": "Content of the alert dialog shown when all of the following applies:\r\n* User has saved view selected\r\n* User has performed changes to the current document filter\r\n* User now tries to reset this filter without having saved the changes to the view." "description": "Content of the alert dialog shown when all of the following applies:\r\n* User has saved view selected\r\n* User has performed changes to the current document filter\r\n* User now tries to reset this filter without having saved the changes to the view."
}, },
"createFromCurrentFilter": "Create from current filter", "createFromCurrentFilter": "Crear desde filtre actual",
"@createFromCurrentFilter": { "@createFromCurrentFilter": {
"description": "Tooltip of the \"New saved view\" button" "description": "Tooltip of the \"New saved view\" button"
}, },
@@ -958,10 +958,6 @@
"@welcomeUser": { "@welcomeUser": {
"description": "Top message shown on the home page" "description": "Top message shown on the home page"
}, },
"noSavedViewOnHomepageHint": "Configure a saved view to be displayed on your home page and it will show up here.",
"@noSavedViewOnHomepageHint": {
"description": "Message shown when there is no saved view to display on the home page."
},
"statistics": "Estadí­stiques", "statistics": "Estadí­stiques",
"documentsInInbox": "Document safata", "documentsInInbox": "Document safata",
"totalDocuments": "Total documents", "totalDocuments": "Total documents",
@@ -974,26 +970,26 @@
"@userAlreadyExists": { "@userAlreadyExists": {
"description": "Error message shown when the user tries to add an already existing account." "description": "Error message shown when the user tries to add an already existing account."
}, },
"youDidNotSaveAnyViewsYet": "You did not save any views yet, create one and it will be shown here.", "youDidNotSaveAnyViewsYet": "Encara no has desat cap visualització, crea'n una i es mostrarà aquí.",
"@youDidNotSaveAnyViewsYet": { "@youDidNotSaveAnyViewsYet": {
"description": "Message shown when there are no saved views yet." "description": "Message shown when there are no saved views yet."
}, },
"tryAgain": "Try again", "tryAgain": "Torna a provar",
"discardFile": "Discard file?", "discardFile": "Desestimar arxiu?",
"discard": "Discard", "discard": "Descarta",
"backToLogin": "Back to login", "backToLogin": "Torna a inici de sessió",
"skipEditingReceivedFiles": "Skip editing received files", "skipEditingReceivedFiles": "Salta l'edició de fitxers rebuts",
"uploadWithoutPromptingUploadForm": "Always upload without prompting the upload form when sharing files with the app.", "uploadWithoutPromptingUploadForm": "Pengeu sempre sense demanar el formulari de càrrega quan compartiu fitxers amb l'aplicació.",
"authenticatingDots": "Authenticating...", "authenticatingDots": "Autenticant…",
"@authenticatingDots": { "@authenticatingDots": {
"description": "Message shown when the app is authenticating the user" "description": "Message shown when the app is authenticating the user"
}, },
"persistingUserInformation": "Persisting user information...", "persistingUserInformation": "Informació de l'usuari persistent...",
"fetchingUserInformation": "Fetching user information...", "fetchingUserInformation": "Obtenint dades d'usuari...",
"@fetchingUserInformation": { "@fetchingUserInformation": {
"description": "Message shown when the app loads user data from the server" "description": "Message shown when the app loads user data from the server"
}, },
"restoringSession": "Restoring session...", "restoringSession": "Restaurant sessió...",
"@restoringSession": { "@restoringSession": {
"description": "Message shown when the user opens the app and the previous user is tried to be authenticated and logged in" "description": "Message shown when the user opens the app and the previous user is tried to be authenticated and logged in"
}, },
@@ -1001,7 +997,7 @@
"@documentsAssigned": { "@documentsAssigned": {
"description": "Text shown with a correspondent, document type etc. to indicate the number of documents this filter will maximally yield." "description": "Text shown with a correspondent, document type etc. to indicate the number of documents this filter will maximally yield."
}, },
"discardChangesWarning": "You have unsaved changes. By continuing, all changes will be lost. Do you want to discard these changes?", "discardChangesWarning": "Tens canvis sense desar. Si continues es perdran. Vols descartar els canvis?",
"@discardChangesWarning": { "@discardChangesWarning": {
"description": "Warning message shown when the user tries to close a route without saving the changes." "description": "Warning message shown when the user tries to close a route without saving the changes."
} }

View File

@@ -958,10 +958,6 @@
"@welcomeUser": { "@welcomeUser": {
"description": "Top message shown on the home page" "description": "Top message shown on the home page"
}, },
"noSavedViewOnHomepageHint": "Configure a saved view to be displayed on your home page and it will show up here.",
"@noSavedViewOnHomepageHint": {
"description": "Message shown when there is no saved view to display on the home page."
},
"statistics": "Statistics", "statistics": "Statistics",
"documentsInInbox": "Documents in inbox", "documentsInInbox": "Documents in inbox",
"totalDocuments": "Total documents", "totalDocuments": "Total documents",

View File

@@ -958,10 +958,6 @@
"@welcomeUser": { "@welcomeUser": {
"description": "Top message shown on the home page" "description": "Top message shown on the home page"
}, },
"noSavedViewOnHomepageHint": "Konfiguriere eine Ansicht so, dass sie auf deiner Startseite angezeigt wird und sie wird hier erscheinen.",
"@noSavedViewOnHomepageHint": {
"description": "Message shown when there is no saved view to display on the home page."
},
"statistics": "Statistiken", "statistics": "Statistiken",
"documentsInInbox": "Dokumente im Posteingang", "documentsInInbox": "Dokumente im Posteingang",
"totalDocuments": "Dokumente insgesamt", "totalDocuments": "Dokumente insgesamt",

View File

@@ -958,10 +958,6 @@
"@welcomeUser": { "@welcomeUser": {
"description": "Top message shown on the home page" "description": "Top message shown on the home page"
}, },
"noSavedViewOnHomepageHint": "Configure a saved view to be displayed on your home page and it will show up here.",
"@noSavedViewOnHomepageHint": {
"description": "Message shown when there is no saved view to display on the home page."
},
"statistics": "Statistics", "statistics": "Statistics",
"documentsInInbox": "Documents in inbox", "documentsInInbox": "Documents in inbox",
"totalDocuments": "Total documents", "totalDocuments": "Total documents",

View File

@@ -958,10 +958,6 @@
"@welcomeUser": { "@welcomeUser": {
"description": "Top message shown on the home page" "description": "Top message shown on the home page"
}, },
"noSavedViewOnHomepageHint": "Configure una vista guardada para que sea mostrada en su página de inicio y aparecerá aquí.",
"@noSavedViewOnHomepageHint": {
"description": "Message shown when there is no saved view to display on the home page."
},
"statistics": "Estadísticas", "statistics": "Estadísticas",
"documentsInInbox": "Documentos en el buzón", "documentsInInbox": "Documentos en el buzón",
"totalDocuments": "Total de documentos", "totalDocuments": "Total de documentos",

View File

@@ -958,10 +958,6 @@
"@welcomeUser": { "@welcomeUser": {
"description": "Top message shown on the home page" "description": "Top message shown on the home page"
}, },
"noSavedViewOnHomepageHint": "Configure a saved view to be displayed on your home page and it will show up here.",
"@noSavedViewOnHomepageHint": {
"description": "Message shown when there is no saved view to display on the home page."
},
"statistics": "Statistics", "statistics": "Statistics",
"documentsInInbox": "Documents in inbox", "documentsInInbox": "Documents in inbox",
"totalDocuments": "Total documents", "totalDocuments": "Total documents",

View File

@@ -958,10 +958,6 @@
"@welcomeUser": { "@welcomeUser": {
"description": "Top message shown on the home page" "description": "Top message shown on the home page"
}, },
"noSavedViewOnHomepageHint": "Configure a saved view to be displayed on your home page and it will show up here.",
"@noSavedViewOnHomepageHint": {
"description": "Message shown when there is no saved view to display on the home page."
},
"statistics": "Statistics", "statistics": "Statistics",
"documentsInInbox": "Documents in inbox", "documentsInInbox": "Documents in inbox",
"totalDocuments": "Total documents", "totalDocuments": "Total documents",

View File

@@ -958,10 +958,6 @@
"@welcomeUser": { "@welcomeUser": {
"description": "Top message shown on the home page" "description": "Top message shown on the home page"
}, },
"noSavedViewOnHomepageHint": "Настройте сохраненный вид для отображения на вашей домашней страница и он будет отображаться здесь.",
"@noSavedViewOnHomepageHint": {
"description": "Message shown when there is no saved view to display on the home page."
},
"statistics": "Статистика", "statistics": "Статистика",
"documentsInInbox": "Документы во входящих", "documentsInInbox": "Документы во входящих",
"totalDocuments": "Всего документов", "totalDocuments": "Всего документов",

View File

@@ -958,10 +958,6 @@
"@welcomeUser": { "@welcomeUser": {
"description": "Top message shown on the home page" "description": "Top message shown on the home page"
}, },
"noSavedViewOnHomepageHint": "Configure a saved view to be displayed on your home page and it will show up here.",
"@noSavedViewOnHomepageHint": {
"description": "Message shown when there is no saved view to display on the home page."
},
"statistics": "Statistics", "statistics": "Statistics",
"documentsInInbox": "Documents in inbox", "documentsInInbox": "Documents in inbox",
"totalDocuments": "Total documents", "totalDocuments": "Total documents",

View File

@@ -316,7 +316,7 @@ class _GoRouterShellState extends State<GoRouterShell> {
$loginRoute, $loginRoute,
$loggingOutRoute, $loggingOutRoute,
$addAccountRoute, $addAccountRoute,
$providerShellRoute, $authenticatedRoute,
], ],
), ),
], ],

View File

@@ -3,34 +3,28 @@ import 'package:go_router/go_router.dart';
import 'package:paperless_api/paperless_api.dart'; import 'package:paperless_api/paperless_api.dart';
import 'package:paperless_mobile/features/saved_view/view/add_saved_view_page.dart'; import 'package:paperless_mobile/features/saved_view/view/add_saved_view_page.dart';
import 'package:paperless_mobile/features/saved_view/view/edit_saved_view_page.dart'; import 'package:paperless_mobile/features/saved_view/view/edit_saved_view_page.dart';
import 'package:paperless_mobile/routes/routes.dart';
part 'saved_views_route.g.dart';
@TypedGoRoute<SavedViewsRoute>(
path: "/saved-views",
routes: [
TypedGoRoute<CreateSavedViewRoute>(
path: "create",
name: R.createSavedView,
),
TypedGoRoute<EditSavedViewRoute>(
path: "edit",
name: R.editSavedView,
),
],
)
class SavedViewsRoute extends GoRouteData { class SavedViewsRoute extends GoRouteData {
const SavedViewsRoute(); const SavedViewsRoute();
} }
class CreateSavedViewRoute extends GoRouteData { class CreateSavedViewRoute extends GoRouteData {
final DocumentFilter? $extra; final DocumentFilter? $extra;
const CreateSavedViewRoute(this.$extra); final bool? showOnDashboard;
final bool? showInSidebar;
const CreateSavedViewRoute({
this.$extra = const DocumentFilter(),
this.showOnDashboard,
this.showInSidebar,
});
@override @override
Widget build(BuildContext context, GoRouterState state) { Widget build(BuildContext context, GoRouterState state) {
return AddSavedViewPage(initialFilter: $extra); return AddSavedViewPage(
initialFilter: $extra,
showInSidebar: showInSidebar,
showOnDashboard: showOnDashboard,
);
} }
} }

View File

@@ -19,6 +19,7 @@ import 'package:paperless_mobile/routes/typed/branches/documents_route.dart';
import 'package:paperless_mobile/routes/typed/branches/inbox_route.dart'; import 'package:paperless_mobile/routes/typed/branches/inbox_route.dart';
import 'package:paperless_mobile/routes/typed/branches/labels_route.dart'; import 'package:paperless_mobile/routes/typed/branches/labels_route.dart';
import 'package:paperless_mobile/routes/typed/branches/landing_route.dart'; import 'package:paperless_mobile/routes/typed/branches/landing_route.dart';
import 'package:paperless_mobile/routes/typed/branches/saved_views_route.dart';
import 'package:paperless_mobile/routes/typed/branches/scanner_route.dart'; import 'package:paperless_mobile/routes/typed/branches/scanner_route.dart';
import 'package:paperless_mobile/routes/typed/branches/upload_queue_route.dart'; import 'package:paperless_mobile/routes/typed/branches/upload_queue_route.dart';
import 'package:paperless_mobile/routes/typed/shells/scaffold_shell_route.dart'; import 'package:paperless_mobile/routes/typed/shells/scaffold_shell_route.dart';
@@ -29,7 +30,7 @@ import 'package:provider/provider.dart';
part 'authenticated_route.g.dart'; part 'authenticated_route.g.dart';
@TypedShellRoute<ProviderShellRoute>( @TypedShellRoute<AuthenticatedRoute>(
routes: [ routes: [
TypedGoRoute<SettingsRoute>( TypedGoRoute<SettingsRoute>(
path: "/settings", path: "/settings",
@@ -39,6 +40,19 @@ part 'authenticated_route.g.dart';
path: "/upload-queue", path: "/upload-queue",
name: R.uploadQueue, name: R.uploadQueue,
), ),
TypedGoRoute<SavedViewsRoute>(
path: "/saved-views",
routes: [
TypedGoRoute<CreateSavedViewRoute>(
path: "create",
name: R.createSavedView,
),
TypedGoRoute<EditSavedViewRoute>(
path: "edit",
name: R.editSavedView,
),
],
),
TypedStatefulShellRoute<ScaffoldShellRoute>( TypedStatefulShellRoute<ScaffoldShellRoute>(
branches: [ branches: [
TypedStatefulShellBranch<LandingBranch>( TypedStatefulShellBranch<LandingBranch>(
@@ -122,10 +136,10 @@ part 'authenticated_route.g.dart';
), ),
], ],
) )
class ProviderShellRoute extends ShellRouteData { class AuthenticatedRoute extends ShellRouteData {
static final GlobalKey<NavigatorState> $navigatorKey = outerShellNavigatorKey; static final GlobalKey<NavigatorState> $navigatorKey = outerShellNavigatorKey;
const ProviderShellRoute(); const AuthenticatedRoute();
@override @override
Widget builder( Widget builder(

View File

@@ -185,7 +185,7 @@ class DocumentFilter extends Equatable {
added.matches(document.added) && added.matches(document.added) &&
modified.matches(document.modified) && modified.matches(document.modified) &&
query.matches( query.matches(
title: document.title ?? '', title: document.title,
content: document.content, content: document.content,
asn: document.archiveSerialNumber, asn: document.archiveSerialNumber,
); );

View File

@@ -26,7 +26,7 @@ class DocumentModel extends Equatable {
static const storagePathKey = 'storage_path'; static const storagePathKey = 'storage_path';
final int id; final int id;
final String? title; final String title;
final String? content; final String? content;
final Iterable<int> tags; final Iterable<int> tags;
final int? documentType; final int? documentType;