mirror of
https://github.com/Xevion/paperless-mobile.git
synced 2026-01-31 10:25:03 -06:00
Merge pull request #265 from astubenbord/bugfix/incorrect-locale-in-datepicker
Bugfix/incorrect locale in datepicker
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
* Beheben von inkorrekter Lokalisierung in der App
|
||||
* Hinzufügen der Unterscheidung zwischen US und GB Englisch
|
||||
@@ -0,0 +1,2 @@
|
||||
* Fixed incorrect localizations of dates and other texts
|
||||
* Add discrimination between US and GB English (useful for date input)
|
||||
+2
-2
@@ -146,7 +146,7 @@ class _ExtendedDateRangeDialogState extends State<ExtendedDateRangeDialog> {
|
||||
)
|
||||
: null,
|
||||
),
|
||||
format: DateFormat.yMd(),
|
||||
format: DateFormat.yMd(Localizations.localeOf(context).toString()),
|
||||
lastDate: _dateTimeMax(_before, DateTime.now()),
|
||||
inputType: InputType.date,
|
||||
onChanged: (after) {
|
||||
@@ -174,7 +174,7 @@ class _ExtendedDateRangeDialogState extends State<ExtendedDateRangeDialog> {
|
||||
)
|
||||
: null,
|
||||
),
|
||||
format: DateFormat.yMd(),
|
||||
format: DateFormat.yMd(Localizations.localeOf(context).toString()),
|
||||
firstDate: _after,
|
||||
lastDate: DateTime.now(),
|
||||
onChanged: (before) {
|
||||
|
||||
+1
-1
@@ -79,7 +79,7 @@ class _FormBuilderExtendedDateRangePickerState
|
||||
}
|
||||
|
||||
String _dateRangeQueryToString(DateRangeQuery query) {
|
||||
final df = DateFormat.yMd();
|
||||
final df = DateFormat.yMd(Localizations.localeOf(context).toString());
|
||||
if (query is UnsetDateRangeQuery) {
|
||||
return '';
|
||||
} else if (query is AbsoluteDateRangeQuery) {
|
||||
|
||||
@@ -4,6 +4,7 @@ import 'package:flutter_animate/flutter_animate.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:paperless_mobile/constants.dart';
|
||||
import 'package:paperless_mobile/core/database/tables/local_user_account.dart';
|
||||
import 'package:paperless_mobile/core/widgets/paperless_logo.dart';
|
||||
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
||||
import 'package:paperless_mobile/features/documents/cubit/documents_cubit.dart';
|
||||
@@ -12,6 +13,7 @@ import 'package:paperless_mobile/features/sharing/cubit/receive_share_cubit.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/upload_queue_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:provider/provider.dart';
|
||||
import 'package:url_launcher/url_launcher_string.dart';
|
||||
@@ -21,6 +23,10 @@ class AppDrawer extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final currentAccount = context.watch<LocalUserAccount>();
|
||||
final username = currentAccount.paperlessUser.username;
|
||||
final serverUrl =
|
||||
currentAccount.serverUrl.replaceAll(RegExp(r'https?://'), '');
|
||||
return SafeArea(
|
||||
child: Drawer(
|
||||
child: Column(
|
||||
@@ -28,13 +34,43 @@ class AppDrawer extends StatelessWidget {
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
const PaperlessLogo.green(),
|
||||
const PaperlessLogo.green(
|
||||
width: 32,
|
||||
height: 32,
|
||||
),
|
||||
Text(
|
||||
"Paperless Mobile",
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
],
|
||||
).padded(),
|
||||
).paddedLTRB(8, 8, 8, 16),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
S.of(context)!.loggedInAs(username),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: Theme.of(context).textTheme.labelMedium?.copyWith(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onBackground
|
||||
.withOpacity(0.5),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
serverUrl,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: Theme.of(context).textTheme.labelMedium?.copyWith(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onBackground
|
||||
.withOpacity(0.5),
|
||||
),
|
||||
),
|
||||
],
|
||||
).paddedSymmetrically(horizontal: 16),
|
||||
const Divider(),
|
||||
ListTile(
|
||||
dense: true,
|
||||
@@ -42,6 +78,31 @@ class AppDrawer extends StatelessWidget {
|
||||
leading: const Icon(Icons.info_outline),
|
||||
onTap: () => _showAboutDialog(context),
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
leading: const Icon(Icons.favorite_outline),
|
||||
title: Text(S.of(context)!.donate),
|
||||
onTap: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
icon: const Icon(Icons.favorite),
|
||||
title: Text(S.of(context)!.donate),
|
||||
content: Text(
|
||||
S.of(context)!.donationDialogContent,
|
||||
),
|
||||
actionsAlignment: MainAxisAlignment.spaceBetween,
|
||||
actions: [
|
||||
Text("~ Anton"),
|
||||
TextButton(
|
||||
onPressed: Navigator.of(context).pop,
|
||||
child: Text(S.of(context)!.gotIt),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
leading: const Icon(Icons.bug_report_outlined),
|
||||
@@ -62,26 +123,6 @@ class AppDrawer extends StatelessWidget {
|
||||
);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
leading: const Icon(Icons.favorite_outline),
|
||||
title: Text(S.of(context)!.donate),
|
||||
onTap: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
icon: const Icon(Icons.favorite),
|
||||
title: Text(S.of(context)!.donate),
|
||||
content: Text(
|
||||
S.of(context)!.donationDialogContent,
|
||||
),
|
||||
actions: const [
|
||||
Text("~ Anton"),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
leading: SvgPicture.asset(
|
||||
|
||||
@@ -218,7 +218,7 @@ class DocumentDetailsCubit extends Cubit<DocumentDetailsState> {
|
||||
throw Exception("An error occurred while downloading the document.");
|
||||
}
|
||||
Printing.layoutPdf(
|
||||
name: state.document.title,
|
||||
name: state.document.title ?? 'Document',
|
||||
onLayout: (format) => file.readAsBytesSync(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:intl/date_symbol_data_local.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:open_filex/open_filex.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/bloc/connectivity_cubit.dart';
|
||||
@@ -23,6 +25,7 @@ import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||
import 'package:paperless_mobile/helpers/connectivity_aware_action_wrapper.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/shells/authenticated_route.dart';
|
||||
|
||||
class DocumentDetailsPage extends StatefulWidget {
|
||||
final bool isLabelClickable;
|
||||
@@ -42,12 +45,18 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
|
||||
static const double _itemSpacing = 24;
|
||||
|
||||
final _pagingScrollController = ScrollController();
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
initializeDateFormatting(Localizations.localeOf(context).toString());
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final hasMultiUserSupport =
|
||||
context.watch<LocalUserAccount>().hasMultiUserSupport;
|
||||
final tabLength = 4 + (hasMultiUserSupport && false ? 1 : 0);
|
||||
final title = context.watch<DocumentDetailsCubit>().state.document.title;
|
||||
return WillPopScope(
|
||||
onWillPop: () async {
|
||||
Navigator.of(context)
|
||||
@@ -74,11 +83,7 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
|
||||
handle:
|
||||
NestedScrollView.sliverOverlapAbsorberHandleFor(context),
|
||||
sliver: SliverAppBar(
|
||||
title: Text(context
|
||||
.watch<DocumentDetailsCubit>()
|
||||
.state
|
||||
.document
|
||||
.title),
|
||||
title: title != null ? Text(title) : null,
|
||||
leading: const BackButton(),
|
||||
pinned: true,
|
||||
forceElevated: innerBoxIsScrolled,
|
||||
@@ -103,6 +108,7 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
|
||||
enableHero: false,
|
||||
document: state.document,
|
||||
fit: BoxFit.cover,
|
||||
alignment: Alignment.topCenter,
|
||||
),
|
||||
),
|
||||
Positioned.fill(
|
||||
@@ -221,10 +227,6 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
|
||||
document: state.document,
|
||||
itemSpacing: _itemSpacing,
|
||||
queryString: widget.titleAndContentQueryString,
|
||||
availableCorrespondents: state.correspondents,
|
||||
availableDocumentTypes: state.documentTypes,
|
||||
availableTags: state.tags,
|
||||
availableStoragePaths: state.storagePaths,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -44,12 +44,14 @@ class _DocumentMetaDataWidgetState extends State<DocumentMetaDataWidget> {
|
||||
document: widget.document,
|
||||
).paddedOnly(bottom: widget.itemSpacing),
|
||||
DetailsItem.text(
|
||||
DateFormat().format(widget.document.modified),
|
||||
DateFormat.yMMMMd(Localizations.localeOf(context).toString())
|
||||
.format(widget.document.modified),
|
||||
context: context,
|
||||
label: S.of(context)!.modifiedAt,
|
||||
).paddedOnly(bottom: widget.itemSpacing),
|
||||
DetailsItem.text(
|
||||
DateFormat().format(widget.document.added),
|
||||
DateFormat.yMMMMd(Localizations.localeOf(context).toString())
|
||||
.format(widget.document.added),
|
||||
context: context,
|
||||
label: S.of(context)!.addedAt,
|
||||
).paddedOnly(bottom: widget.itemSpacing),
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/database/tables/local_user_account.dart';
|
||||
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
||||
import 'package:paperless_mobile/core/widgets/highlighted_text.dart';
|
||||
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
||||
import 'package:paperless_mobile/features/document_details/view/widgets/details_item.dart';
|
||||
@@ -12,81 +13,69 @@ import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||
|
||||
class DocumentOverviewWidget extends StatelessWidget {
|
||||
final DocumentModel document;
|
||||
final Map<int, Correspondent> availableCorrespondents;
|
||||
final Map<int, DocumentType> availableDocumentTypes;
|
||||
final Map<int, Tag> availableTags;
|
||||
final Map<int, StoragePath> availableStoragePaths;
|
||||
final String? queryString;
|
||||
final double itemSpacing;
|
||||
|
||||
const DocumentOverviewWidget({
|
||||
super.key,
|
||||
required this.document,
|
||||
this.queryString,
|
||||
required this.itemSpacing,
|
||||
required this.availableCorrespondents,
|
||||
required this.availableDocumentTypes,
|
||||
required this.availableTags,
|
||||
required this.availableStoragePaths,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final user = context.watch<LocalUserAccount>().paperlessUser;
|
||||
final availableLabels = context.watch<LabelRepository>().state;
|
||||
return SliverList.list(
|
||||
children: [
|
||||
DetailsItem(
|
||||
label: S.of(context)!.title,
|
||||
content: HighlightedText(
|
||||
text: document.title,
|
||||
highlights: queryString?.split(" ") ?? [],
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
),
|
||||
).paddedOnly(bottom: itemSpacing),
|
||||
if (document.title != null)
|
||||
DetailsItem(
|
||||
label: S.of(context)!.title,
|
||||
content: HighlightedText(
|
||||
text: document.title!,
|
||||
highlights: queryString?.split(" ") ?? [],
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
),
|
||||
).paddedOnly(bottom: itemSpacing),
|
||||
DetailsItem.text(
|
||||
DateFormat.yMMMMd().format(document.created),
|
||||
DateFormat.yMMMMd(Localizations.localeOf(context).toString())
|
||||
.format(document.created),
|
||||
context: context,
|
||||
label: S.of(context)!.createdAt,
|
||||
).paddedOnly(bottom: itemSpacing),
|
||||
if (document.documentType != null &&
|
||||
context
|
||||
.watch<LocalUserAccount>()
|
||||
.paperlessUser
|
||||
.canViewDocumentTypes)
|
||||
if (document.documentType != null && user.canViewDocumentTypes)
|
||||
DetailsItem(
|
||||
label: S.of(context)!.documentType,
|
||||
content: LabelText<DocumentType>(
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
label: availableDocumentTypes[document.documentType],
|
||||
label: availableLabels.documentTypes[document.documentType],
|
||||
),
|
||||
).paddedOnly(bottom: itemSpacing),
|
||||
if (document.correspondent != null &&
|
||||
context
|
||||
.watch<LocalUserAccount>()
|
||||
.paperlessUser
|
||||
.canViewCorrespondents)
|
||||
if (document.correspondent != null && user.canViewCorrespondents)
|
||||
DetailsItem(
|
||||
label: S.of(context)!.correspondent,
|
||||
content: LabelText<Correspondent>(
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
label: availableCorrespondents[document.correspondent],
|
||||
label: availableLabels.correspondents[document.correspondent],
|
||||
),
|
||||
).paddedOnly(bottom: itemSpacing),
|
||||
if (document.storagePath != null &&
|
||||
context.watch<LocalUserAccount>().paperlessUser.canViewStoragePaths)
|
||||
if (document.storagePath != null && user.canViewStoragePaths)
|
||||
DetailsItem(
|
||||
label: S.of(context)!.storagePath,
|
||||
content: LabelText<StoragePath>(
|
||||
label: availableStoragePaths[document.storagePath],
|
||||
label: availableLabels.storagePaths[document.storagePath],
|
||||
),
|
||||
).paddedOnly(bottom: itemSpacing),
|
||||
if (document.tags.isNotEmpty &&
|
||||
context.watch<LocalUserAccount>().paperlessUser.canViewTags)
|
||||
if (document.tags.isNotEmpty && user.canViewTags)
|
||||
DetailsItem(
|
||||
label: S.of(context)!.tags,
|
||||
content: Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: TagsWidget(
|
||||
isClickable: false,
|
||||
tags: document.tags.map((e) => availableTags[e]!).toList(),
|
||||
tags:
|
||||
document.tags.map((e) => availableLabels.tags[e]!).toList(),
|
||||
),
|
||||
),
|
||||
).paddedOnly(bottom: itemSpacing),
|
||||
|
||||
@@ -376,14 +376,16 @@ class _DocumentEditPageState extends State<DocumentEditPage> {
|
||||
label: Text(S.of(context)!.createdAt),
|
||||
),
|
||||
initialValue: initialCreatedAtDate,
|
||||
format: DateFormat.yMMMMd(),
|
||||
format: DateFormat.yMMMMd(Localizations.localeOf(context).toString()),
|
||||
initialEntryMode: DatePickerEntryMode.calendar,
|
||||
),
|
||||
if (filteredSuggestions?.hasSuggestedDates ?? false)
|
||||
_buildSuggestionsSkeleton<DateTime>(
|
||||
suggestions: filteredSuggestions!.dates,
|
||||
itemBuilder: (context, itemData) => ActionChip(
|
||||
label: Text(DateFormat.yMMMd().format(itemData)),
|
||||
label: Text(
|
||||
DateFormat.yMMMMd(Localizations.localeOf(context).toString())
|
||||
.format(itemData)),
|
||||
onPressed: () => _formKey.currentState?.fields[fkCreatedDate]
|
||||
?.didChange(itemData),
|
||||
),
|
||||
|
||||
@@ -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/permission_helpers.dart';
|
||||
import 'package:paperless_mobile/routes/typed/branches/scanner_route.dart';
|
||||
import 'package:paperless_mobile/routes/typed/shells/authenticated_route.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:pdf/pdf.dart';
|
||||
import 'package:pdf/widgets.dart' as pw;
|
||||
|
||||
@@ -11,6 +11,7 @@ import 'package:paperless_mobile/features/documents/view/widgets/adaptive_docume
|
||||
import 'package:paperless_mobile/features/documents/view/widgets/selection/view_type_selection_widget.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/shells/authenticated_route.dart';
|
||||
|
||||
class DocumentSearchPage extends StatefulWidget {
|
||||
const DocumentSearchPage({super.key});
|
||||
|
||||
@@ -10,12 +10,10 @@ import 'package:paperless_mobile/features/settings/view/widgets/user_avatar.dart
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class SliverSearchBar extends StatelessWidget {
|
||||
final bool floating;
|
||||
final bool pinned;
|
||||
final String titleText;
|
||||
const SliverSearchBar({
|
||||
super.key,
|
||||
this.floating = false,
|
||||
this.pinned = false,
|
||||
required this.titleText,
|
||||
});
|
||||
|
||||
@@ -68,7 +68,6 @@ class _DocumentUploadPreparationPageState
|
||||
void initState() {
|
||||
super.initState();
|
||||
_syncTitleAndFilename = widget.filename == null && widget.title == null;
|
||||
initializeDateFormatting();
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -219,7 +218,8 @@ class _DocumentUploadPreparationPageState
|
||||
// Created at
|
||||
FormBuilderDateTimePicker(
|
||||
autovalidateMode: AutovalidateMode.always,
|
||||
format: DateFormat.yMMMMd(),
|
||||
format: DateFormat.yMMMMd(
|
||||
Localizations.localeOf(context).toString()),
|
||||
inputType: InputType.date,
|
||||
name: DocumentModel.createdKey,
|
||||
initialValue: null,
|
||||
|
||||
@@ -25,6 +25,7 @@ import 'package:paperless_mobile/features/tasks/model/pending_tasks_notifier.dar
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.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/shells/authenticated_route.dart';
|
||||
import 'package:sliver_tools/sliver_tools.dart';
|
||||
|
||||
class DocumentFilterIntent {
|
||||
@@ -176,13 +177,9 @@ class _DocumentsPageState extends State<DocumentsPage> {
|
||||
child: _showExtendedFab
|
||||
? Row(
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.filter_alt_outlined,
|
||||
),
|
||||
const Icon(Icons.filter_alt_outlined),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
S.of(context)!.filterDocuments,
|
||||
),
|
||||
Text(S.of(context)!.filterDocuments),
|
||||
],
|
||||
)
|
||||
: const Icon(Icons.filter_alt_outlined),
|
||||
@@ -269,7 +266,6 @@ class _DocumentsPageState extends State<DocumentsPage> {
|
||||
builder: (context, state) {
|
||||
if (state.selection.isEmpty) {
|
||||
return SliverSearchBar(
|
||||
floating: true,
|
||||
titleText: S.of(context)!.documents,
|
||||
);
|
||||
} else {
|
||||
@@ -620,9 +616,9 @@ class _DocumentsPageState extends State<DocumentsPage> {
|
||||
final cubit = context.read<DocumentsCubit>();
|
||||
|
||||
try {
|
||||
switch (cubit.state.filter.storagePath){
|
||||
case SetIdQueryParameter(id: var id):
|
||||
if (id == pathId) {
|
||||
switch (cubit.state.filter.storagePath) {
|
||||
case SetIdQueryParameter(id: var id):
|
||||
if (id == pathId) {
|
||||
cubit.updateCurrentFilter(
|
||||
(filter) =>
|
||||
filter.copyWith(storagePath: const UnsetIdQueryParameter()),
|
||||
@@ -634,14 +630,13 @@ class _DocumentsPageState extends State<DocumentsPage> {
|
||||
);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
cubit.updateCurrentFilter(
|
||||
default:
|
||||
cubit.updateCurrentFilter(
|
||||
(filter) =>
|
||||
filter.copyWith(storagePath: SetIdQueryParameter(id: pathId)),
|
||||
filter.copyWith(storagePath: SetIdQueryParameter(id: pathId)),
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
} on PaperlessApiException catch (error, stackTrace) {
|
||||
showErrorMessage(context, error, stackTrace);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ class DeleteDocumentConfirmationDialog extends StatelessWidget {
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
document.title,
|
||||
document.title ?? document.originalFileName ?? '-',
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(
|
||||
|
||||
@@ -4,6 +4,7 @@ import 'package:flutter_cache_manager/flutter_cache_manager.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/helpers/connectivity_aware_action_wrapper.dart';
|
||||
import 'package:paperless_mobile/routes/typed/branches/documents_route.dart';
|
||||
import 'package:paperless_mobile/routes/typed/shells/authenticated_route.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:shimmer/shimmer.dart';
|
||||
|
||||
|
||||
@@ -89,7 +89,8 @@ class DocumentDetailedItem extends DocumentItem {
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
DateFormat.yMMMMd().format(document.created),
|
||||
DateFormat.yMMMMd(Localizations.localeOf(context).toString())
|
||||
.format(document.created),
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodySmall
|
||||
@@ -110,7 +111,7 @@ class DocumentDetailedItem extends DocumentItem {
|
||||
],
|
||||
).paddedLTRB(8, 8, 8, 4),
|
||||
Text(
|
||||
document.title,
|
||||
document.title ?? '-',
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
|
||||
@@ -113,7 +113,7 @@ class DocumentGridItem extends DocumentItem {
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8.0),
|
||||
child: Text(
|
||||
document.title,
|
||||
document.title ?? '-',
|
||||
maxLines: 3,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
@@ -121,7 +121,9 @@ class DocumentGridItem extends DocumentItem {
|
||||
),
|
||||
const Spacer(),
|
||||
Text(
|
||||
DateFormat.yMMMd().format(document.created),
|
||||
DateFormat.yMMMMd(
|
||||
Localizations.localeOf(context).toString())
|
||||
.format(document.created),
|
||||
style: Theme.of(context).textTheme.bodySmall,
|
||||
),
|
||||
],
|
||||
|
||||
@@ -58,7 +58,7 @@ class DocumentListItem extends DocumentItem {
|
||||
],
|
||||
),
|
||||
Text(
|
||||
document.title,
|
||||
document.title ?? '-',
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 1,
|
||||
),
|
||||
@@ -81,7 +81,8 @@ class DocumentListItem extends DocumentItem {
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
text: TextSpan(
|
||||
text: DateFormat.yMMMd().format(document.created),
|
||||
text: DateFormat.yMMMMd(Localizations.localeOf(context).toString())
|
||||
.format(document.created),
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.labelSmall
|
||||
|
||||
@@ -44,7 +44,7 @@ class BulkDeleteConfirmationDialog extends StatelessWidget {
|
||||
return ListTile(
|
||||
dense: true,
|
||||
title: Text(
|
||||
doc.title,
|
||||
doc.title ?? doc.originalFileName ?? '-',
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(
|
||||
|
||||
@@ -7,6 +7,7 @@ import 'package:paperless_mobile/features/documents/view/widgets/selection/bulk_
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.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/shells/authenticated_route.dart';
|
||||
|
||||
class DocumentSelectionSliverAppBar extends StatelessWidget {
|
||||
final DocumentsState state;
|
||||
|
||||
@@ -331,7 +331,8 @@ class _InboxPageState extends State<InboxPage>
|
||||
if (doc.added.isYesterday) {
|
||||
return S.of(context)!.yesterday;
|
||||
}
|
||||
return DateFormat.yMMMMd().format(doc.added);
|
||||
return DateFormat.yMMMMd(Localizations.localeOf(context).toString())
|
||||
.format(doc.added);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import 'package:paperless_mobile/features/labels/view/widgets/label_text.dart';
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||
import 'package:paperless_mobile/helpers/connectivity_aware_action_wrapper.dart';
|
||||
import 'package:paperless_mobile/routes/typed/branches/documents_route.dart';
|
||||
import 'package:paperless_mobile/routes/typed/shells/authenticated_route.dart';
|
||||
|
||||
class InboxItemPlaceholder extends StatelessWidget {
|
||||
const InboxItemPlaceholder({super.key});
|
||||
@@ -350,7 +351,7 @@ class _InboxItemState extends State<InboxItem> {
|
||||
|
||||
Text _buildTitle() {
|
||||
return Text(
|
||||
widget.document.title,
|
||||
widget.document.title ?? '-',
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 2,
|
||||
style: Theme.of(context).textTheme.titleSmall,
|
||||
|
||||
@@ -15,6 +15,7 @@ import 'package:paperless_mobile/features/labels/view/widgets/label_tab_view.dar
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||
import 'package:paperless_mobile/helpers/connectivity_aware_action_wrapper.dart';
|
||||
import 'package:paperless_mobile/routes/typed/branches/labels_route.dart';
|
||||
import 'package:paperless_mobile/routes/typed/shells/authenticated_route.dart';
|
||||
|
||||
class LabelsPage extends StatefulWidget {
|
||||
const LabelsPage({Key? key}) : super(key: key);
|
||||
|
||||
@@ -4,6 +4,7 @@ import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/database/tables/local_user_account.dart';
|
||||
import 'package:paperless_mobile/helpers/format_helpers.dart';
|
||||
import 'package:paperless_mobile/routes/typed/branches/labels_route.dart';
|
||||
import 'package:paperless_mobile/routes/typed/shells/authenticated_route.dart';
|
||||
|
||||
class LabelItem<T extends Label> extends StatelessWidget {
|
||||
final T label;
|
||||
|
||||
@@ -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/routes/typed/branches/documents_route.dart';
|
||||
import 'package:paperless_mobile/routes/typed/branches/inbox_route.dart';
|
||||
import 'package:paperless_mobile/routes/typed/shells/authenticated_route.dart';
|
||||
|
||||
class LandingPage extends StatefulWidget {
|
||||
const LandingPage({super.key});
|
||||
@@ -34,7 +35,6 @@ class _LandingPageState extends State<LandingPage> {
|
||||
SliverOverlapAbsorber(
|
||||
handle: _searchBarHandle,
|
||||
sliver: SliverSearchBar(
|
||||
floating: true,
|
||||
titleText: S.of(context)!.documents,
|
||||
),
|
||||
),
|
||||
|
||||
@@ -7,6 +7,7 @@ import 'package:paperless_mobile/features/linked_documents/cubit/linked_document
|
||||
import 'package:paperless_mobile/features/paged_document_view/view/document_paging_view_mixin.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/shells/authenticated_route.dart';
|
||||
|
||||
class LinkedDocumentsPage extends StatefulWidget {
|
||||
const LinkedDocumentsPage({super.key});
|
||||
|
||||
@@ -13,6 +13,7 @@ import 'package:paperless_mobile/features/login/model/login_form_credentials.dar
|
||||
import 'package:paperless_mobile/features/login/view/add_account_page.dart';
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||
import 'package:paperless_mobile/helpers/message_helpers.dart';
|
||||
import 'package:paperless_mobile/routes/typed/shells/authenticated_route.dart';
|
||||
import 'package:paperless_mobile/routes/typed/top_level/login_route.dart';
|
||||
|
||||
class LoginPage extends StatelessWidget {
|
||||
|
||||
@@ -5,6 +5,7 @@ import 'package:paperless_mobile/core/config/hive/hive_extensions.dart';
|
||||
import 'package:paperless_mobile/features/login/cubit/authentication_cubit.dart';
|
||||
import 'package:paperless_mobile/features/users/view/widgets/user_account_list_tile.dart';
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||
import 'package:paperless_mobile/routes/typed/shells/authenticated_route.dart';
|
||||
import 'package:paperless_mobile/routes/typed/top_level/login_route.dart';
|
||||
|
||||
class LoginToExistingAccountPage extends StatelessWidget {
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
||||
import 'package:paperless_mobile/features/login/cubit/authentication_cubit.dart';
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||
import 'package:paperless_mobile/routes/typed/shells/authenticated_route.dart';
|
||||
import 'package:paperless_mobile/routes/typed/top_level/login_route.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import 'package:paperless_mobile/features/landing/view/widgets/expansion_card.da
|
||||
import 'package:paperless_mobile/features/saved_view_details/cubit/saved_view_preview_cubit.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/shells/authenticated_route.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class SavedViewPreview extends StatelessWidget {
|
||||
|
||||
@@ -7,6 +7,7 @@ import 'package:paperless_mobile/features/settings/view/dialogs/switch_account_d
|
||||
import 'package:paperless_mobile/features/settings/view/widgets/global_settings_builder.dart';
|
||||
import 'package:paperless_mobile/features/users/view/widgets/user_account_list_tile.dart';
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||
import 'package:paperless_mobile/routes/typed/shells/authenticated_route.dart';
|
||||
import 'package:paperless_mobile/routes/typed/top_level/add_account_route.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
@@ -146,35 +147,7 @@ class ManageAccountsPage extends StatelessWidget {
|
||||
|
||||
Future<void> _onAddAccount(BuildContext context, String currentUser) async {
|
||||
Navigator.of(context).pop();
|
||||
AddAccountRoute().push<String>(context);
|
||||
// final userId = await Navigator.push(
|
||||
// context,
|
||||
// MaterialPageRoute(
|
||||
// builder: (context) => AddAccountPage(
|
||||
// titleText: S.of(context)!.addAccount,
|
||||
// onSubmit: (context, username, password, serverUrl,
|
||||
// clientCertificate) async {
|
||||
// try {
|
||||
// final userId =
|
||||
// await context.read<AuthenticationCubit>().addAccount(
|
||||
// credentials: LoginFormCredentials(
|
||||
// username: username,
|
||||
// password: password,
|
||||
// ),
|
||||
// clientCertificate: clientCertificate,
|
||||
// serverUrl: serverUrl,
|
||||
// //TODO: Ask user whether to enable biometric authentication
|
||||
// enableBiometricAuthentication: false,
|
||||
// );
|
||||
|
||||
// Navigator.of(context).pop<String?>(userId);
|
||||
// } on PaperlessFormValidationException catch (error) {}
|
||||
// },
|
||||
// submitText: S.of(context)!.addAccount,
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
|
||||
const AddAccountRoute().push<String>(context);
|
||||
}
|
||||
|
||||
void _onSwitchAccount(
|
||||
|
||||
@@ -13,7 +13,8 @@ class LanguageSelectionSetting extends StatefulWidget {
|
||||
|
||||
class _LanguageSelectionSettingState extends State<LanguageSelectionSetting> {
|
||||
static const _languageOptions = {
|
||||
'en': LanguageOption('English', true),
|
||||
'en': LanguageOption('English (US)', true),
|
||||
'en_GB': LanguageOption('English (GB)', true),
|
||||
'de': LanguageOption('Deutsch', true),
|
||||
'es': LanguageOption("Español", true),
|
||||
'fr': LanguageOption('Français', true),
|
||||
|
||||
@@ -40,31 +40,34 @@ class _RadioSettingsDialogState<T> extends State<RadioSettingsDialog<T>> {
|
||||
return AlertDialog(
|
||||
actions: [
|
||||
const DialogCancelButton(),
|
||||
widget.confirmButton ??
|
||||
DialogConfirmButton(
|
||||
returnValue: _groupValue,
|
||||
),
|
||||
widget.confirmButton ?? DialogConfirmButton(returnValue: _groupValue),
|
||||
],
|
||||
title: widget.titleText != null ? Text(widget.titleText!) : null,
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (widget.descriptionText != null)
|
||||
Text(widget.descriptionText!,
|
||||
style: Theme.of(context).textTheme.bodySmall),
|
||||
...widget.options.map(_buildOptionListTile),
|
||||
if (widget.footer != null) widget.footer!,
|
||||
],
|
||||
content: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (widget.descriptionText != null)
|
||||
Text(
|
||||
widget.descriptionText!,
|
||||
style: Theme.of(context).textTheme.bodySmall,
|
||||
),
|
||||
...widget.options.map(_buildOptionListTile).toList(),
|
||||
if (widget.footer != null) widget.footer!,
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildOptionListTile(RadioOption<T> option) => RadioListTile<T>(
|
||||
groupValue: _groupValue,
|
||||
onChanged: (value) => setState(() => _groupValue = value!),
|
||||
value: option.value,
|
||||
title: Text(option.label),
|
||||
);
|
||||
Widget _buildOptionListTile(RadioOption<T> option) {
|
||||
return RadioListTile<T>(
|
||||
groupValue: _groupValue,
|
||||
onChanged: (value) => setState(() => _groupValue = value!),
|
||||
value: option.value,
|
||||
title: Text(option.label),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class RadioOption<T> {
|
||||
|
||||
@@ -15,16 +15,26 @@ class UserAvatar extends StatelessWidget {
|
||||
Colors.primaries[account.id.hashCode % Colors.primaries.length];
|
||||
final foregroundColor =
|
||||
backgroundColor.computeLuminance() > 0.5 ? Colors.black : Colors.white;
|
||||
return CircleAvatar(
|
||||
child: Text(
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(
|
||||
color: backgroundColor.shade900.withOpacity(0.4),
|
||||
width: 2,
|
||||
),
|
||||
),
|
||||
child: CircleAvatar(
|
||||
child: Text(
|
||||
(account.paperlessUser.fullName ?? account.paperlessUser.username)
|
||||
.split(" ")
|
||||
.take(2)
|
||||
.map((e) => e.substring(0, 1))
|
||||
.map((e) => e.toUpperCase())
|
||||
.join("")),
|
||||
backgroundColor: backgroundColor,
|
||||
foregroundColor: foregroundColor,
|
||||
.join(""),
|
||||
),
|
||||
backgroundColor: backgroundColor,
|
||||
foregroundColor: foregroundColor,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import 'package:paperless_mobile/features/tasks/model/pending_tasks_notifier.dar
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||
import 'package:paperless_mobile/helpers/message_helpers.dart';
|
||||
import 'package:paperless_mobile/routes/typed/branches/scanner_route.dart';
|
||||
import 'package:paperless_mobile/routes/typed/shells/authenticated_route.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:receive_sharing_intent/receive_sharing_intent.dart';
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import 'package:paperless_mobile/features/similar_documents/cubit/similar_docume
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.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/shells/authenticated_route.dart';
|
||||
|
||||
class SimilarDocumentsView extends StatefulWidget {
|
||||
final ScrollController pagingScrollController;
|
||||
|
||||
+110
-110
@@ -36,31 +36,27 @@ import 'package:paperless_mobile/features/notifications/services/local_notificat
|
||||
import 'package:paperless_mobile/features/settings/view/widgets/global_settings_builder.dart';
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||
import 'package:paperless_mobile/routes/navigation_keys.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/labels_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/upload_queue_route.dart';
|
||||
import 'package:paperless_mobile/routes/typed/shells/provider_shell_route.dart';
|
||||
import 'package:paperless_mobile/routes/typed/shells/scaffold_shell_route.dart';
|
||||
import 'package:paperless_mobile/routes/typed/shells/authenticated_route.dart';
|
||||
import 'package:paperless_mobile/routes/typed/top_level/add_account_route.dart';
|
||||
import 'package:paperless_mobile/routes/typed/top_level/logging_out_route.dart';
|
||||
import 'package:paperless_mobile/routes/typed/top_level/login_route.dart';
|
||||
import 'package:paperless_mobile/routes/typed/top_level/settings_route.dart';
|
||||
import 'package:paperless_mobile/theme.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
String get defaultPreferredLocaleSubtag {
|
||||
String preferredLocale = Platform.localeName.split("_").first;
|
||||
if (!S.supportedLocales
|
||||
.any((locale) => locale.languageCode == preferredLocale)) {
|
||||
preferredLocale = 'en';
|
||||
Locale get defaultPreferredLocale {
|
||||
final deviceLocale = _stringToLocale(Platform.localeName);
|
||||
if (S.supportedLocales.contains(deviceLocale)) {
|
||||
return deviceLocale;
|
||||
} else if (S.supportedLocales
|
||||
.map((e) => e.languageCode)
|
||||
.contains(deviceLocale.languageCode)) {
|
||||
return Locale(deviceLocale.languageCode);
|
||||
} else {
|
||||
return const Locale('en');
|
||||
}
|
||||
return preferredLocale;
|
||||
}
|
||||
|
||||
Map<String, Future<void> Function()> _migrations = {
|
||||
@@ -106,7 +102,7 @@ Future<void> _initHive() async {
|
||||
|
||||
if (!globalSettingsBox.hasValue) {
|
||||
await globalSettingsBox.setValue(
|
||||
GlobalSettings(preferredLocaleSubtag: defaultPreferredLocaleSubtag),
|
||||
GlobalSettings(preferredLocaleSubtag: defaultPreferredLocale.toString()),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -197,12 +193,14 @@ void main() async {
|
||||
value: localNotificationService),
|
||||
Provider.value(value: DocumentChangedNotifier()),
|
||||
],
|
||||
child: MultiBlocProvider(
|
||||
child: MultiProvider(
|
||||
providers: [
|
||||
BlocProvider<ConnectivityCubit>.value(value: connectivityCubit),
|
||||
BlocProvider.value(value: authenticationCubit),
|
||||
Provider<ConnectivityCubit>.value(value: connectivityCubit),
|
||||
Provider.value(value: authenticationCubit),
|
||||
],
|
||||
child: GoRouterShell(apiFactory: apiFactory),
|
||||
child: GoRouterShell(
|
||||
apiFactory: apiFactory,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -221,10 +219,7 @@ void main() async {
|
||||
|
||||
class GoRouterShell extends StatefulWidget {
|
||||
final PaperlessApiFactory apiFactory;
|
||||
const GoRouterShell({
|
||||
super.key,
|
||||
required this.apiFactory,
|
||||
});
|
||||
const GoRouterShell({super.key, required this.apiFactory});
|
||||
|
||||
@override
|
||||
State<GoRouterShell> createState() => _GoRouterShellState();
|
||||
@@ -267,50 +262,53 @@ class _GoRouterShellState extends State<GoRouterShell> {
|
||||
routes: [
|
||||
ShellRoute(
|
||||
builder: (context, state, child) {
|
||||
return BlocListener<AuthenticationCubit, AuthenticationState>(
|
||||
listener: (context, state) {
|
||||
switch (state) {
|
||||
case UnauthenticatedState(
|
||||
redirectToAccountSelection: var shouldRedirect
|
||||
):
|
||||
if (shouldRedirect) {
|
||||
const LoginToExistingAccountRoute().go(context);
|
||||
} else {
|
||||
const LoginRoute().go(context);
|
||||
}
|
||||
break;
|
||||
case RestoringSessionState():
|
||||
const RestoringSessionRoute().go(context);
|
||||
break;
|
||||
case VerifyIdentityState(userId: var userId):
|
||||
VerifyIdentityRoute(userId: userId).go(context);
|
||||
break;
|
||||
case SwitchingAccountsState():
|
||||
const SwitchingAccountsRoute().push(context);
|
||||
break;
|
||||
case AuthenticatedState():
|
||||
const LandingRoute().go(context);
|
||||
break;
|
||||
case AuthenticatingState state:
|
||||
AuthenticatingRoute(state.currentStage.name).push(context);
|
||||
break;
|
||||
case LoggingOutState():
|
||||
const LoggingOutRoute().go(context);
|
||||
break;
|
||||
case AuthenticationErrorState():
|
||||
if (context.canPop()) {
|
||||
context.pop();
|
||||
}
|
||||
// LoginRoute(
|
||||
// $extra: errorState.clientCertificate,
|
||||
// password: errorState.password,
|
||||
// serverUrl: errorState.serverUrl,
|
||||
// username: errorState.username,
|
||||
// ).go(context);
|
||||
break;
|
||||
}
|
||||
},
|
||||
child: child,
|
||||
return Provider.value(
|
||||
value: widget.apiFactory,
|
||||
child: BlocListener<AuthenticationCubit, AuthenticationState>(
|
||||
listener: (context, state) {
|
||||
switch (state) {
|
||||
case UnauthenticatedState(
|
||||
redirectToAccountSelection: var shouldRedirect
|
||||
):
|
||||
if (shouldRedirect) {
|
||||
const LoginToExistingAccountRoute().go(context);
|
||||
} else {
|
||||
const LoginRoute().go(context);
|
||||
}
|
||||
break;
|
||||
case RestoringSessionState():
|
||||
const RestoringSessionRoute().go(context);
|
||||
break;
|
||||
case VerifyIdentityState(userId: var userId):
|
||||
VerifyIdentityRoute(userId: userId).go(context);
|
||||
break;
|
||||
case SwitchingAccountsState():
|
||||
const SwitchingAccountsRoute().push(context);
|
||||
break;
|
||||
case AuthenticatedState():
|
||||
const LandingRoute().go(context);
|
||||
break;
|
||||
case AuthenticatingState state:
|
||||
AuthenticatingRoute(state.currentStage.name).push(context);
|
||||
break;
|
||||
case LoggingOutState():
|
||||
const LoggingOutRoute().go(context);
|
||||
break;
|
||||
case AuthenticationErrorState():
|
||||
if (context.canPop()) {
|
||||
context.pop();
|
||||
}
|
||||
// LoginRoute(
|
||||
// $extra: errorState.clientCertificate,
|
||||
// password: errorState.password,
|
||||
// serverUrl: errorState.serverUrl,
|
||||
// username: errorState.username,
|
||||
// ).go(context);
|
||||
break;
|
||||
}
|
||||
},
|
||||
child: child,
|
||||
),
|
||||
);
|
||||
},
|
||||
navigatorKey: rootNavigatorKey,
|
||||
@@ -318,44 +316,7 @@ class _GoRouterShellState extends State<GoRouterShell> {
|
||||
$loginRoute,
|
||||
$loggingOutRoute,
|
||||
$addAccountRoute,
|
||||
ShellRoute(
|
||||
navigatorKey: outerShellNavigatorKey,
|
||||
builder: ProviderShellRoute(widget.apiFactory).build,
|
||||
routes: [
|
||||
$settingsRoute,
|
||||
$savedViewsRoute,
|
||||
$uploadQueueRoute,
|
||||
StatefulShellRoute(
|
||||
navigatorContainerBuilder:
|
||||
(context, navigationShell, children) {
|
||||
return children[navigationShell.currentIndex];
|
||||
},
|
||||
builder: const ScaffoldShellRoute().builder,
|
||||
branches: [
|
||||
StatefulShellBranch(
|
||||
navigatorKey: landingNavigatorKey,
|
||||
routes: [$landingRoute],
|
||||
),
|
||||
StatefulShellBranch(
|
||||
navigatorKey: documentsNavigatorKey,
|
||||
routes: [$documentsRoute],
|
||||
),
|
||||
StatefulShellBranch(
|
||||
navigatorKey: scannerNavigatorKey,
|
||||
routes: [$scannerRoute],
|
||||
),
|
||||
StatefulShellBranch(
|
||||
navigatorKey: labelsNavigatorKey,
|
||||
routes: [$labelsRoute],
|
||||
),
|
||||
StatefulShellBranch(
|
||||
navigatorKey: inboxNavigatorKey,
|
||||
routes: [$inboxRoute],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
$providerShellRoute,
|
||||
],
|
||||
),
|
||||
],
|
||||
@@ -365,6 +326,7 @@ class _GoRouterShellState extends State<GoRouterShell> {
|
||||
Widget build(BuildContext context) {
|
||||
return GlobalSettingsBuilder(
|
||||
builder: (context, settings) {
|
||||
final locale = _stringToLocale(settings.preferredLocaleSubtag);
|
||||
return DynamicColorBuilder(
|
||||
builder: (lightDynamic, darkDynamic) {
|
||||
return MaterialApp.router(
|
||||
@@ -382,10 +344,41 @@ class _GoRouterShellState extends State<GoRouterShell> {
|
||||
preferredColorScheme: settings.preferredColorSchemeOption,
|
||||
),
|
||||
themeMode: settings.preferredThemeMode,
|
||||
supportedLocales: S.supportedLocales,
|
||||
locale: Locale.fromSubtags(
|
||||
languageCode: settings.preferredLocaleSubtag,
|
||||
),
|
||||
supportedLocales: const [
|
||||
Locale('en'),
|
||||
Locale('de'),
|
||||
Locale('en', 'GB'),
|
||||
Locale('ca'),
|
||||
Locale('cs'),
|
||||
Locale('es'),
|
||||
Locale('fr'),
|
||||
Locale('pl'),
|
||||
Locale('ru'),
|
||||
Locale('tr'),
|
||||
],
|
||||
localeResolutionCallback: (locale, supportedLocales) {
|
||||
if (locale == null) {
|
||||
return supportedLocales.first;
|
||||
}
|
||||
|
||||
final exactMatch = supportedLocales
|
||||
.where((element) =>
|
||||
element.languageCode == locale.languageCode &&
|
||||
element.countryCode == locale.countryCode)
|
||||
.toList();
|
||||
if (exactMatch.isNotEmpty) {
|
||||
return exactMatch.first;
|
||||
}
|
||||
final superLanguageMatch = supportedLocales
|
||||
.where((element) =>
|
||||
element.languageCode == locale.languageCode)
|
||||
.toList();
|
||||
if (superLanguageMatch.isNotEmpty) {
|
||||
return superLanguageMatch.first;
|
||||
}
|
||||
return supportedLocales.first;
|
||||
},
|
||||
locale: locale,
|
||||
localizationsDelegates: S.localizationsDelegates,
|
||||
);
|
||||
},
|
||||
@@ -394,3 +387,10 @@ class _GoRouterShellState extends State<GoRouterShell> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Locale _stringToLocale(String code) {
|
||||
final codes = code.split("_");
|
||||
final languageCode = codes[0];
|
||||
final countryCode = codes.length > 1 ? codes[1] : null;
|
||||
return Locale(languageCode, countryCode);
|
||||
}
|
||||
|
||||
@@ -17,35 +17,11 @@ import 'package:paperless_mobile/routes/navigation_keys.dart';
|
||||
import 'package:paperless_mobile/routes/routes.dart';
|
||||
import 'package:paperless_mobile/theme.dart';
|
||||
|
||||
part 'documents_route.g.dart';
|
||||
|
||||
class DocumentsBranch extends StatefulShellBranchData {
|
||||
static final GlobalKey<NavigatorState> $navigatorKey = documentsNavigatorKey;
|
||||
const DocumentsBranch();
|
||||
}
|
||||
|
||||
@TypedGoRoute<DocumentsRoute>(
|
||||
path: "/documents",
|
||||
name: R.documents,
|
||||
routes: [
|
||||
TypedGoRoute<EditDocumentRoute>(
|
||||
path: "edit",
|
||||
name: R.editDocument,
|
||||
),
|
||||
TypedGoRoute<DocumentDetailsRoute>(
|
||||
path: "details",
|
||||
name: R.documentDetails,
|
||||
),
|
||||
TypedGoRoute<DocumentPreviewRoute>(
|
||||
path: "preview",
|
||||
name: R.documentPreview,
|
||||
),
|
||||
TypedGoRoute<BulkEditDocumentsRoute>(
|
||||
path: "bulk-edit",
|
||||
name: R.bulkEditDocuments,
|
||||
),
|
||||
],
|
||||
)
|
||||
class DocumentsRoute extends GoRouteData {
|
||||
@override
|
||||
Widget build(BuildContext context, GoRouterState state) {
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import 'package:flutter/src/widgets/framework.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:paperless_mobile/features/inbox/view/pages/inbox_page.dart';
|
||||
import 'package:paperless_mobile/routes/routes.dart';
|
||||
import 'package:paperless_mobile/routes/navigation_keys.dart';
|
||||
|
||||
part 'inbox_route.g.dart';
|
||||
class InboxBranch extends StatefulShellBranchData {
|
||||
static final GlobalKey<NavigatorState> $navigatorKey = inboxNavigatorKey;
|
||||
|
||||
const InboxBranch();
|
||||
}
|
||||
|
||||
@TypedGoRoute<InboxRoute>(
|
||||
path: "/inbox",
|
||||
name: R.inbox,
|
||||
)
|
||||
class InboxRoute extends GoRouteData {
|
||||
@override
|
||||
Widget build(BuildContext context, GoRouterState state) {
|
||||
|
||||
@@ -14,33 +14,12 @@ import 'package:paperless_mobile/features/labels/view/pages/labels_page.dart';
|
||||
import 'package:paperless_mobile/features/linked_documents/cubit/linked_documents_cubit.dart';
|
||||
import 'package:paperless_mobile/features/linked_documents/view/linked_documents_page.dart';
|
||||
import 'package:paperless_mobile/routes/navigation_keys.dart';
|
||||
import 'package:paperless_mobile/routes/routes.dart';
|
||||
|
||||
part 'labels_route.g.dart';
|
||||
|
||||
class LabelsBranch extends StatefulShellBranchData {
|
||||
static final GlobalKey<NavigatorState> $navigatorKey = labelsNavigatorKey;
|
||||
const LabelsBranch();
|
||||
}
|
||||
|
||||
@TypedGoRoute<LabelsRoute>(
|
||||
path: "/labels",
|
||||
name: R.labels,
|
||||
routes: [
|
||||
TypedGoRoute<EditLabelRoute>(
|
||||
path: "edit",
|
||||
name: R.editLabel,
|
||||
),
|
||||
TypedGoRoute<CreateLabelRoute>(
|
||||
path: "create",
|
||||
name: R.createLabel,
|
||||
),
|
||||
TypedGoRoute<LinkedDocumentsRoute>(
|
||||
path: "linked-documents",
|
||||
name: R.linkedDocuments,
|
||||
),
|
||||
],
|
||||
)
|
||||
class LabelsRoute extends GoRouteData {
|
||||
@override
|
||||
Widget build(BuildContext context, GoRouterState state) {
|
||||
|
||||
@@ -4,18 +4,12 @@ import 'package:paperless_mobile/features/landing/view/landing_page.dart';
|
||||
import 'package:paperless_mobile/routes/navigation_keys.dart';
|
||||
import 'package:paperless_mobile/routes/routes.dart';
|
||||
|
||||
part 'landing_route.g.dart';
|
||||
|
||||
class LandingBranch extends StatefulShellBranchData {
|
||||
static final GlobalKey<NavigatorState> $navigatorKey = landingNavigatorKey;
|
||||
|
||||
const LandingBranch();
|
||||
}
|
||||
|
||||
@TypedGoRoute<LandingRoute>(
|
||||
path: "/landing",
|
||||
name: R.landing,
|
||||
)
|
||||
class LandingRoute extends GoRouteData {
|
||||
const LandingRoute();
|
||||
@override
|
||||
|
||||
@@ -10,38 +10,12 @@ import 'package:paperless_mobile/features/document_upload/view/document_upload_p
|
||||
import 'package:paperless_mobile/routes/navigation_keys.dart';
|
||||
import 'package:paperless_mobile/routes/routes.dart';
|
||||
|
||||
part 'scanner_route.g.dart';
|
||||
|
||||
// @TypedStatefulShellBranch<ScannerBranch>(
|
||||
// routes: [
|
||||
// TypedGoRoute<ScannerRoute>(
|
||||
// path: "/scanner",
|
||||
// name: R.scanner,
|
||||
// routes: [
|
||||
// TypedGoRoute<DocumentUploadRoute>(
|
||||
// path: "upload",
|
||||
// name: R.uploadDocument,
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ],
|
||||
// )
|
||||
class ScannerBranch extends StatefulShellBranchData {
|
||||
static final GlobalKey<NavigatorState> $navigatorKey = scannerNavigatorKey;
|
||||
|
||||
const ScannerBranch();
|
||||
}
|
||||
|
||||
@TypedGoRoute<ScannerRoute>(
|
||||
path: "/scanner",
|
||||
name: R.scanner,
|
||||
routes: [
|
||||
TypedGoRoute<DocumentUploadRoute>(
|
||||
path: "upload",
|
||||
name: R.uploadDocument,
|
||||
),
|
||||
],
|
||||
)
|
||||
class ScannerRoute extends GoRouteData {
|
||||
const ScannerRoute();
|
||||
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
import 'dart:async';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:hive_flutter/adapters.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/config/hive/hive_config.dart';
|
||||
import 'package:paperless_mobile/core/database/tables/global_settings.dart';
|
||||
import 'package:paperless_mobile/core/database/tables/local_user_account.dart';
|
||||
import 'package:paperless_mobile/core/factory/paperless_api_factory.dart';
|
||||
import 'package:paperless_mobile/features/home/view/home_shell_widget.dart';
|
||||
import 'package:paperless_mobile/features/home/view/scaffold_with_navigation_bar.dart';
|
||||
import 'package:paperless_mobile/features/sharing/cubit/receive_share_cubit.dart';
|
||||
import 'package:paperless_mobile/features/sharing/view/widgets/event_listener_shell.dart';
|
||||
import 'package:paperless_mobile/routes/navigation_keys.dart';
|
||||
import 'package:paperless_mobile/routes/routes.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/labels_route.dart';
|
||||
import 'package:paperless_mobile/routes/typed/branches/landing_route.dart';
|
||||
import 'package:paperless_mobile/routes/typed/branches/scanner_route.dart';
|
||||
import 'package:paperless_mobile/routes/typed/shells/scaffold_shell_route.dart';
|
||||
import 'package:paperless_mobile/routes/typed/top_level/settings_route.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
/// Key used to access
|
||||
|
||||
part 'authenticated_route.g.dart';
|
||||
|
||||
@TypedShellRoute<ProviderShellRoute>(
|
||||
routes: [
|
||||
TypedGoRoute<SettingsRoute>(
|
||||
path: "/settings",
|
||||
name: R.settings,
|
||||
),
|
||||
TypedStatefulShellRoute<ScaffoldShellRoute>(
|
||||
branches: [
|
||||
TypedStatefulShellBranch<LandingBranch>(
|
||||
routes: [
|
||||
TypedGoRoute<LandingRoute>(
|
||||
path: "/landing",
|
||||
name: R.landing,
|
||||
)
|
||||
],
|
||||
),
|
||||
TypedStatefulShellBranch<DocumentsBranch>(
|
||||
routes: [
|
||||
TypedGoRoute<DocumentsRoute>(
|
||||
path: "/documents",
|
||||
routes: [
|
||||
TypedGoRoute<DocumentDetailsRoute>(
|
||||
path: "details",
|
||||
name: R.documentDetails,
|
||||
),
|
||||
TypedGoRoute<EditDocumentRoute>(
|
||||
path: "edit",
|
||||
name: R.editDocument,
|
||||
),
|
||||
TypedGoRoute<BulkEditDocumentsRoute>(
|
||||
path: "bulk-edit",
|
||||
name: R.bulkEditDocuments,
|
||||
),
|
||||
TypedGoRoute<DocumentPreviewRoute>(
|
||||
path: 'preview',
|
||||
name: R.documentPreview,
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
TypedStatefulShellBranch<ScannerBranch>(
|
||||
routes: [
|
||||
TypedGoRoute<ScannerRoute>(
|
||||
path: "/scanner",
|
||||
name: R.scanner,
|
||||
routes: [
|
||||
TypedGoRoute<DocumentUploadRoute>(
|
||||
path: "upload",
|
||||
name: R.uploadDocument,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
TypedStatefulShellBranch<LabelsBranch>(
|
||||
routes: [
|
||||
TypedGoRoute<LabelsRoute>(
|
||||
path: "/labels",
|
||||
name: R.labels,
|
||||
routes: [
|
||||
TypedGoRoute<EditLabelRoute>(
|
||||
path: "edit",
|
||||
name: R.editLabel,
|
||||
),
|
||||
TypedGoRoute<CreateLabelRoute>(
|
||||
path: "create",
|
||||
name: R.createLabel,
|
||||
),
|
||||
TypedGoRoute<LinkedDocumentsRoute>(
|
||||
path: "linked-documents",
|
||||
name: R.linkedDocuments,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
TypedStatefulShellBranch<InboxBranch>(
|
||||
routes: [
|
||||
TypedGoRoute<InboxRoute>(
|
||||
path: "/inbox",
|
||||
name: R.inbox,
|
||||
)
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
class ProviderShellRoute extends ShellRouteData {
|
||||
static final GlobalKey<NavigatorState> $navigatorKey = outerShellNavigatorKey;
|
||||
|
||||
const ProviderShellRoute();
|
||||
|
||||
@override
|
||||
Widget builder(
|
||||
BuildContext context,
|
||||
GoRouterState state,
|
||||
Widget navigator,
|
||||
) {
|
||||
final currentUserId = Hive.box<GlobalSettings>(HiveBoxes.globalSettings)
|
||||
.getValue()!
|
||||
.loggedInUserId;
|
||||
if (currentUserId == null) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
final authenticatedUser =
|
||||
Hive.box<LocalUserAccount>(HiveBoxes.localUserAccount).get(
|
||||
currentUserId,
|
||||
)!;
|
||||
final apiFactory = context.read<PaperlessApiFactory>();
|
||||
return HomeShellWidget(
|
||||
localUserId: authenticatedUser.id,
|
||||
paperlessApiVersion: authenticatedUser.apiVersion,
|
||||
paperlessProviderFactory: apiFactory,
|
||||
child: ChangeNotifierProvider(
|
||||
create: (context) => ConsumptionChangeNotifier()
|
||||
..loadFromConsumptionDirectory(userId: currentUserId),
|
||||
child: EventListenerShell(
|
||||
child: navigator,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:hive_flutter/adapters.dart';
|
||||
import 'package:paperless_mobile/core/config/hive/hive_config.dart';
|
||||
import 'package:paperless_mobile/core/database/tables/global_settings.dart';
|
||||
import 'package:paperless_mobile/core/database/tables/local_user_account.dart';
|
||||
import 'package:paperless_mobile/core/factory/paperless_api_factory.dart';
|
||||
import 'package:paperless_mobile/features/home/view/home_shell_widget.dart';
|
||||
import 'package:paperless_mobile/features/sharing/cubit/receive_share_cubit.dart';
|
||||
import 'package:paperless_mobile/features/sharing/view/widgets/event_listener_shell.dart';
|
||||
import 'package:paperless_mobile/routes/navigation_keys.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
/// Key used to access
|
||||
|
||||
//part 'provider_shell_route.g.dart';
|
||||
//TODO: Wait for https://github.com/flutter/flutter/issues/127371 to be merged
|
||||
// @TypedShellRoute<ProviderShellRoute>(
|
||||
// routes: [
|
||||
// TypedStatefulShellRoute(
|
||||
// branches: [
|
||||
// TypedStatefulShellBranch<LandingBranch>(
|
||||
// routes: [
|
||||
// TypedGoRoute<LandingRoute>(
|
||||
// path: "/landing",
|
||||
// // name: R.landing,
|
||||
// )
|
||||
// ],
|
||||
// ),
|
||||
// TypedStatefulShellBranch<DocumentsBranch>(
|
||||
// routes: [
|
||||
// TypedGoRoute<DocumentsRoute>(
|
||||
// path: "/documents",
|
||||
// routes: [
|
||||
// TypedGoRoute<DocumentDetailsRoute>(
|
||||
// path: "details",
|
||||
// // name: R.documentDetails,
|
||||
// ),
|
||||
// TypedGoRoute<DocumentEditRoute>(
|
||||
// path: "edit",
|
||||
// // name: R.editDocument,
|
||||
// ),
|
||||
// ],
|
||||
// )
|
||||
// ],
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ],
|
||||
// )
|
||||
class ProviderShellRoute extends ShellRouteData {
|
||||
final PaperlessApiFactory apiFactory;
|
||||
static final GlobalKey<NavigatorState> $navigatorKey = outerShellNavigatorKey;
|
||||
|
||||
const ProviderShellRoute(this.apiFactory);
|
||||
|
||||
Widget build(
|
||||
BuildContext context,
|
||||
GoRouterState state,
|
||||
Widget navigator,
|
||||
) {
|
||||
final currentUserId = Hive.box<GlobalSettings>(HiveBoxes.globalSettings)
|
||||
.getValue()!
|
||||
.loggedInUserId;
|
||||
if (currentUserId == null) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
final authenticatedUser =
|
||||
Hive.box<LocalUserAccount>(HiveBoxes.localUserAccount).get(
|
||||
currentUserId,
|
||||
)!;
|
||||
|
||||
return HomeShellWidget(
|
||||
localUserId: authenticatedUser.id,
|
||||
paperlessApiVersion: authenticatedUser.apiVersion,
|
||||
paperlessProviderFactory: apiFactory,
|
||||
child: ChangeNotifierProvider(
|
||||
create: (context) => ConsumptionChangeNotifier()
|
||||
..loadFromConsumptionDirectory(userId: currentUserId),
|
||||
child: EventListenerShell(child: navigator),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,12 @@ import 'package:paperless_mobile/features/home/view/scaffold_with_navigation_bar
|
||||
|
||||
class ScaffoldShellRoute extends StatefulShellRouteData {
|
||||
const ScaffoldShellRoute();
|
||||
|
||||
static Widget $navigatorContainerBuilder(BuildContext context,
|
||||
StatefulNavigationShell navigationShell, List<Widget> children) {
|
||||
return children[navigationShell.currentIndex];
|
||||
}
|
||||
|
||||
@override
|
||||
Widget builder(
|
||||
BuildContext context,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/model/info_message_exception.dart';
|
||||
import 'package:paperless_mobile/features/login/cubit/authentication_cubit.dart';
|
||||
@@ -23,58 +23,61 @@ class AddAccountRoute extends GoRouteData {
|
||||
const AddAccountRoute();
|
||||
|
||||
static final $parentNavigatorKey = rootNavigatorKey;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, GoRouterState state) {
|
||||
return AddAccountPage(
|
||||
titleText: S.of(context)!.addAccount,
|
||||
onSubmit:
|
||||
(context, username, password, serverUrl, clientCertificate) async {
|
||||
try {
|
||||
final userId = await context.read<AuthenticationCubit>().addAccount(
|
||||
credentials: LoginFormCredentials(
|
||||
username: username,
|
||||
password: password,
|
||||
),
|
||||
clientCertificate: clientCertificate,
|
||||
serverUrl: serverUrl,
|
||||
enableBiometricAuthentication: false,
|
||||
locale: Localizations.localeOf(context).languageCode,
|
||||
);
|
||||
final shoudSwitch = await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (context) => const SwitchAccountDialog(),
|
||||
) ??
|
||||
false;
|
||||
if (shoudSwitch) {
|
||||
await context.read<AuthenticationCubit>().switchAccount(userId);
|
||||
} else {
|
||||
while (context.canPop()) {
|
||||
context.pop();
|
||||
Page<void> buildPage(BuildContext context, GoRouterState state) {
|
||||
return NoTransitionPage(
|
||||
child: AddAccountPage(
|
||||
titleText: S.of(context)!.addAccount,
|
||||
onSubmit:
|
||||
(context, username, password, serverUrl, clientCertificate) async {
|
||||
try {
|
||||
final userId = await context.read<AuthenticationCubit>().addAccount(
|
||||
credentials: LoginFormCredentials(
|
||||
username: username,
|
||||
password: password,
|
||||
),
|
||||
clientCertificate: clientCertificate,
|
||||
serverUrl: serverUrl,
|
||||
enableBiometricAuthentication: false,
|
||||
locale: Intl.getCurrentLocale(),
|
||||
);
|
||||
final shoudSwitch = await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (context) => const SwitchAccountDialog(),
|
||||
) ??
|
||||
false;
|
||||
if (shoudSwitch) {
|
||||
await context.read<AuthenticationCubit>().switchAccount(userId);
|
||||
} else {
|
||||
while (context.canPop()) {
|
||||
context.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
} on PaperlessApiException catch (error, stackTrace) {
|
||||
showErrorMessage(context, error, stackTrace);
|
||||
// context.pop();
|
||||
} on PaperlessFormValidationException catch (exception, stackTrace) {
|
||||
if (exception.hasUnspecificErrorMessage()) {
|
||||
showLocalizedError(context, exception.unspecificErrorMessage()!);
|
||||
} on PaperlessApiException catch (error, stackTrace) {
|
||||
showErrorMessage(context, error, stackTrace);
|
||||
// context.pop();
|
||||
} on PaperlessFormValidationException catch (exception, stackTrace) {
|
||||
if (exception.hasUnspecificErrorMessage()) {
|
||||
showLocalizedError(context, exception.unspecificErrorMessage()!);
|
||||
// context.pop();
|
||||
} else {
|
||||
showGenericError(
|
||||
context,
|
||||
exception.validationMessages.values.first,
|
||||
stackTrace,
|
||||
); //TODO: Check if we can show error message directly on field here.
|
||||
}
|
||||
} on InfoMessageException catch (error) {
|
||||
showInfoMessage(context, error);
|
||||
// context.pop();
|
||||
} catch (unknownError, stackTrace) {
|
||||
showGenericError(context, unknownError.toString(), stackTrace);
|
||||
// context.pop();
|
||||
} else {
|
||||
showGenericError(
|
||||
context,
|
||||
exception.validationMessages.values.first,
|
||||
stackTrace,
|
||||
); //TODO: Check if we can show error message directly on field here.
|
||||
}
|
||||
} on InfoMessageException catch (error) {
|
||||
showInfoMessage(context, error);
|
||||
// context.pop();
|
||||
} catch (unknownError, stackTrace) {
|
||||
showGenericError(context, unknownError.toString(), stackTrace);
|
||||
// context.pop();
|
||||
}
|
||||
},
|
||||
submitText: S.of(context)!.addAccount,
|
||||
},
|
||||
submitText: S.of(context)!.addAccount,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:paperless_mobile/routes/navigation_keys.dart';
|
||||
import 'package:paperless_mobile/routes/routes.dart';
|
||||
|
||||
part 'logging_out_route.g.dart';
|
||||
@@ -11,12 +10,16 @@ part 'logging_out_route.g.dart';
|
||||
name: R.loggingOut,
|
||||
)
|
||||
class LoggingOutRoute extends GoRouteData {
|
||||
static final $parentNavigatorKey = rootNavigatorKey;
|
||||
const LoggingOutRoute();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, GoRouterState state) {
|
||||
return Scaffold(
|
||||
body: Center(
|
||||
child: Text("Logging out..."),
|
||||
Page<void> buildPage(BuildContext context, GoRouterState state) {
|
||||
return const NoTransitionPage(
|
||||
child: Scaffold(
|
||||
body: Center(
|
||||
child: Text("Logging out..."), //TODO: INTL
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ import 'package:paperless_mobile/features/login/view/widgets/login_transition_pa
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||
import 'package:paperless_mobile/routes/navigation_keys.dart';
|
||||
import 'package:paperless_mobile/routes/routes.dart';
|
||||
|
||||
part 'login_route.g.dart';
|
||||
|
||||
@TypedGoRoute<LoginRoute>(
|
||||
@@ -80,10 +79,13 @@ class SwitchingAccountsRoute extends GoRouteData {
|
||||
static final $parentNavigatorKey = rootNavigatorKey;
|
||||
|
||||
const SwitchingAccountsRoute();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, GoRouterState state) {
|
||||
return LoginTransitionPage(
|
||||
text: S.of(context)!.switchingAccountsPleaseWait,
|
||||
Page<void> buildPage(BuildContext context, GoRouterState state) {
|
||||
return NoTransitionPage(
|
||||
child: LoginTransitionPage(
|
||||
text: S.of(context)!.switchingAccountsPleaseWait,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -93,8 +95,9 @@ class AuthenticatingRoute extends GoRouteData {
|
||||
|
||||
final String checkLoginStageName;
|
||||
const AuthenticatingRoute(this.checkLoginStageName);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, GoRouterState state) {
|
||||
Page<void> buildPage(BuildContext context, GoRouterState state) {
|
||||
final stage = AuthenticatingStage.values.byName(checkLoginStageName);
|
||||
final text = switch (stage) {
|
||||
AuthenticatingStage.authenticating => S.of(context)!.authenticatingDots,
|
||||
@@ -103,8 +106,11 @@ class AuthenticatingRoute extends GoRouteData {
|
||||
AuthenticatingStage.fetchingUserInformation =>
|
||||
S.of(context)!.fetchingUserInformation,
|
||||
};
|
||||
|
||||
return LoginTransitionPage(text: text);
|
||||
return NoTransitionPage(
|
||||
child: LoginTransitionPage(
|
||||
text: text,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,8 +121,10 @@ class VerifyIdentityRoute extends GoRouteData {
|
||||
const VerifyIdentityRoute({required this.userId});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, GoRouterState state) {
|
||||
return VerifyIdentityPage(userId: userId);
|
||||
Page<void> buildPage(BuildContext context, GoRouterState state) {
|
||||
return NoTransitionPage(
|
||||
child: VerifyIdentityPage(userId: userId),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,8 +142,10 @@ class LoginToExistingAccountRoute extends GoRouteData {
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, GoRouterState state) {
|
||||
return const LoginToExistingAccountPage();
|
||||
Page<void> buildPage(BuildContext context, GoRouterState state) {
|
||||
return const NoTransitionPage(
|
||||
child: LoginToExistingAccountPage(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,7 +155,11 @@ class RestoringSessionRoute extends GoRouteData {
|
||||
const RestoringSessionRoute();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, GoRouterState state) {
|
||||
return LoginTransitionPage(text: S.of(context)!.restoringSession);
|
||||
Page<void> buildPage(BuildContext context, GoRouterState state) {
|
||||
return NoTransitionPage(
|
||||
child: LoginTransitionPage(
|
||||
text: S.of(context)!.restoringSession,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,14 +6,9 @@ import 'package:paperless_mobile/routes/navigation_keys.dart';
|
||||
import 'package:paperless_mobile/routes/routes.dart';
|
||||
import 'package:paperless_mobile/theme.dart';
|
||||
|
||||
part 'settings_route.g.dart';
|
||||
|
||||
@TypedGoRoute<SettingsRoute>(
|
||||
path: "/settings",
|
||||
name: R.settings,
|
||||
)
|
||||
class SettingsRoute extends GoRouteData {
|
||||
static final GlobalKey<NavigatorState> $parentNavigatorKey = outerShellNavigatorKey;
|
||||
static final GlobalKey<NavigatorState> $parentNavigatorKey =
|
||||
outerShellNavigatorKey;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, GoRouterState state) {
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations_en.dart';
|
||||
|
||||
class SEnGb extends SEn {
|
||||
SEnGb() : super('en_GB');
|
||||
}
|
||||
|
||||
class SEnUs extends SEn {
|
||||
SEnUs() : super('en_US');
|
||||
}
|
||||
@@ -185,7 +185,7 @@ class DocumentFilter extends Equatable {
|
||||
added.matches(document.added) &&
|
||||
modified.matches(document.modified) &&
|
||||
query.matches(
|
||||
title: document.title,
|
||||
title: document.title ?? '',
|
||||
content: document.content,
|
||||
asn: document.archiveSerialNumber,
|
||||
);
|
||||
|
||||
@@ -26,7 +26,7 @@ class DocumentModel extends Equatable {
|
||||
static const storagePathKey = 'storage_path';
|
||||
|
||||
final int id;
|
||||
final String title;
|
||||
final String? title;
|
||||
final String? content;
|
||||
final Iterable<int> tags;
|
||||
final int? documentType;
|
||||
@@ -71,7 +71,8 @@ class DocumentModel extends Equatable {
|
||||
this.permissions,
|
||||
});
|
||||
|
||||
factory DocumentModel.fromJson(Map<String, dynamic> json) => _$DocumentModelFromJson(json);
|
||||
factory DocumentModel.fromJson(Map<String, dynamic> json) =>
|
||||
_$DocumentModelFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$DocumentModelToJson(this);
|
||||
|
||||
@@ -94,15 +95,17 @@ class DocumentModel extends Equatable {
|
||||
title: title ?? this.title,
|
||||
content: content ?? this.content,
|
||||
documentType: documentType != null ? documentType() : this.documentType,
|
||||
correspondent: correspondent != null ? correspondent() : this.correspondent,
|
||||
correspondent:
|
||||
correspondent != null ? correspondent() : this.correspondent,
|
||||
storagePath: storagePath != null ? storagePath() : this.storagePath,
|
||||
tags: tags ?? this.tags,
|
||||
created: created ?? this.created,
|
||||
modified: modified ?? this.modified,
|
||||
added: added ?? this.added,
|
||||
originalFileName: originalFileName ?? this.originalFileName,
|
||||
archiveSerialNumber:
|
||||
archiveSerialNumber != null ? archiveSerialNumber() : this.archiveSerialNumber,
|
||||
archiveSerialNumber: archiveSerialNumber != null
|
||||
? archiveSerialNumber()
|
||||
: this.archiveSerialNumber,
|
||||
archivedFileName: archivedFileName ?? this.archivedFileName,
|
||||
);
|
||||
}
|
||||
|
||||
+2
-2
@@ -748,10 +748,10 @@ packages:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: go_router_builder
|
||||
sha256: "89585f7cf2ddd35a3f05908c5bb54339d3f891fc5aac4f30e2864469d7ddc92b"
|
||||
sha256: b004ed761578fd1326054ff9c97daaf7b94f109b24cad843ca8bd349a810f947
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.1"
|
||||
version: "2.3.3"
|
||||
graphs:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
+2
-3
@@ -15,7 +15,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
|
||||
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
||||
# Read more about iOS versioning at
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
version: 3.0.2+49
|
||||
version: 3.0.3+50
|
||||
|
||||
environment:
|
||||
sdk: ">=3.0.0 <4.0.0"
|
||||
@@ -118,8 +118,7 @@ dev_dependencies:
|
||||
hive_generator: ^2.0.1
|
||||
mock_server:
|
||||
path: packages/mock_server
|
||||
go_router_builder: ^2.2.4
|
||||
|
||||
go_router_builder: ^2.3.3
|
||||
# For information on the generic Dart part of this file, see the
|
||||
# following page: https://dart.dev/tools/pub/pubspec
|
||||
# The following section is specific to Flutter.
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
echo "Updating source language..."
|
||||
crowdin download sources --identity=../crowdin_credentials.yml --config ../crowdin.yml --no-preserve-hierarchy
|
||||
echo "Updating translations..."
|
||||
crowdin download --identity=../crowdin_credentials.yml --config ../crowdin.yml
|
||||
Reference in New Issue
Block a user