mirror of
https://github.com/Xevion/paperless-mobile.git
synced 2025-12-13 20:12:16 -06:00
Merge pull request #275 from astubenbord/fix/allow-empty-document-titles
Fix/allow empty document titles
This commit is contained in:
@@ -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(
|
||||||
|
|||||||
@@ -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(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
);
|
},
|
||||||
},
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -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,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -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);
|
|
||||||
// },
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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),
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -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.",
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -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 estadístiques 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."
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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": "Всего документов",
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -316,7 +316,7 @@ class _GoRouterShellState extends State<GoRouterShell> {
|
|||||||
$loginRoute,
|
$loginRoute,
|
||||||
$loggingOutRoute,
|
$loggingOutRoute,
|
||||||
$addAccountRoute,
|
$addAccountRoute,
|
||||||
$providerShellRoute,
|
$authenticatedRoute,
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -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,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user