From f388f77d639dc4cc7b77e290e8c2254f2ce173e8 Mon Sep 17 00:00:00 2001 From: Anton Stubenbord Date: Thu, 11 May 2023 12:37:17 +0200 Subject: [PATCH] fix: Adapt to new provider strucutre --- lib/core/bloc/server_information_cubit.dart | 17 - lib/core/bloc/server_information_state.dart | 11 - .../database/tables/local_user_account.dart | 6 +- .../database/tables/local_user_app_state.dart | 7 + .../dio_http_error_interceptor.dart | 12 +- lib/core/navigation/push_routes.dart | 107 ++ .../error_code_localization_mapper.dart | 2 + lib/features/app_drawer/view/app_drawer.dart | 28 +- .../view/pages/document_details_page.dart | 78 +- .../widgets/document_meta_data_widget.dart | 6 +- .../widgets/document_permissions_widget.dart | 12 + .../view/document_edit_page.dart | 9 +- .../document_scan/view/scanner_page.dart | 2 - .../view/document_search_page.dart | 23 +- .../view/sliver_search_bar.dart | 11 +- .../documents/cubit/documents_cubit.dart | 12 +- .../documents/view/pages/document_view.dart | 49 +- .../documents/view/pages/documents_page.dart | 9 +- .../sort_field_selection_bottom_sheet.dart | 16 +- .../view/widgets/sort_documents_button.dart | 18 +- lib/features/home/view/home_page.dart | 9 +- lib/features/home/view/home_route.dart | 27 +- lib/features/home/view/model/api_version.dart | 8 + .../inbox/view/widgets/inbox_item.dart | 1 + .../view/linked_documents_page.dart | 1 + .../login/cubit/authentication_cubit.dart | 54 +- .../saved_view/cubit/saved_view_cubit.dart | 41 +- .../cubit/saved_view_cubit.freezed.dart | 993 ++---------------- .../saved_view/cubit/saved_view_state.dart | 30 +- .../saved_view/view/saved_view_list.dart | 50 +- .../view/saved_view_details_page.dart | 11 +- .../settings/view/manage_accounts_page.dart | 13 + lib/features/settings/view/settings_page.dart | 20 +- .../view/similar_documents_view.dart | 3 +- lib/main.dart | 9 +- lib/routes/document_details_route.dart | 38 - .../models/paperless_server_exception.dart | 3 +- .../paperless_server_information_model.dart | 24 +- .../permissions/inherited_permissions.dart | 4 +- .../lib/src/models/user_model.dart | 2 +- .../paperless_documents_api_impl.dart | 1 - .../paperless_server_stats_api_impl.dart | 15 +- .../user_api/paperless_user_api_v3_impl.dart | 2 +- 43 files changed, 540 insertions(+), 1254 deletions(-) delete mode 100644 lib/core/bloc/server_information_cubit.dart delete mode 100644 lib/core/bloc/server_information_state.dart create mode 100644 lib/core/navigation/push_routes.dart create mode 100644 lib/features/document_details/view/widgets/document_permissions_widget.dart create mode 100644 lib/features/home/view/model/api_version.dart diff --git a/lib/core/bloc/server_information_cubit.dart b/lib/core/bloc/server_information_cubit.dart deleted file mode 100644 index 942c2d3..0000000 --- a/lib/core/bloc/server_information_cubit.dart +++ /dev/null @@ -1,17 +0,0 @@ -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:paperless_api/paperless_api.dart'; -import 'package:paperless_mobile/core/bloc/server_information_state.dart'; - -class ServerInformationCubit extends Cubit { - final PaperlessServerStatsApi _api; - - ServerInformationCubit(this._api) : super(ServerInformationState()); - - Future updateInformation() async { - final information = await _api.getServerInformation(); - emit(ServerInformationState( - isLoaded: true, - information: information, - )); - } -} diff --git a/lib/core/bloc/server_information_state.dart b/lib/core/bloc/server_information_state.dart deleted file mode 100644 index 401ed3f..0000000 --- a/lib/core/bloc/server_information_state.dart +++ /dev/null @@ -1,11 +0,0 @@ -import 'package:paperless_api/paperless_api.dart'; - -class ServerInformationState { - final bool isLoaded; - final PaperlessServerInformationModel? information; - - ServerInformationState({ - this.isLoaded = false, - this.information, - }); -} diff --git a/lib/core/database/tables/local_user_account.dart b/lib/core/database/tables/local_user_account.dart index 256dd02..f5de026 100644 --- a/lib/core/database/tables/local_user_account.dart +++ b/lib/core/database/tables/local_user_account.dart @@ -1,5 +1,6 @@ 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_settings.dart'; import 'package:paperless_api/paperless_api.dart'; @@ -17,7 +18,7 @@ class LocalUserAccount extends HiveObject { final LocalUserSettings settings; @HiveField(7) - final UserModel paperlessUser; + UserModel paperlessUser; LocalUserAccount({ required this.id, @@ -25,4 +26,7 @@ class LocalUserAccount extends HiveObject { required this.settings, required this.paperlessUser, }); + + static LocalUserAccount get current => Hive.box(HiveBoxes.localUserAccount) + .get(Hive.box(HiveBoxes.globalSettings).getValue()!.currentLoggedInUser)!; } diff --git a/lib/core/database/tables/local_user_app_state.dart b/lib/core/database/tables/local_user_app_state.dart index 8dd9603..ffb5b43 100644 --- a/lib/core/database/tables/local_user_app_state.dart +++ b/lib/core/database/tables/local_user_app_state.dart @@ -1,6 +1,7 @@ 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/features/settings/model/view_type.dart'; part 'local_user_app_state.g.dart'; @@ -37,4 +38,10 @@ class LocalUserAppState extends HiveObject { this.documentSearchViewType = ViewType.list, this.savedViewsViewType = ViewType.list, }); + + static LocalUserAppState get current { + final currentLocalUserId = + Hive.box(HiveBoxes.globalSettings).getValue()!.currentLoggedInUser!; + return Hive.box(HiveBoxes.localUserAppState).get(currentLocalUserId)!; + } } diff --git a/lib/core/interceptor/dio_http_error_interceptor.dart b/lib/core/interceptor/dio_http_error_interceptor.dart index b5a0700..8cb0d38 100644 --- a/lib/core/interceptor/dio_http_error_interceptor.dart +++ b/lib/core/interceptor/dio_http_error_interceptor.dart @@ -15,6 +15,15 @@ class DioHttpErrorInterceptor extends Interceptor { } else if (data is String) { return _handlePlainError(data, handler, err); } + } else if (err.response?.statusCode == 403) { + handler.reject( + DioError( + requestOptions: err.requestOptions, + error: const PaperlessServerException(ErrorCode.notAuthorized), + response: err.response, + ), + ); + return; } else if (err.error is SocketException) { final ex = err.error as SocketException; if (ex.osError?.errorCode == _OsErrorCodes.serverUnreachable.code) { @@ -67,8 +76,7 @@ class DioHttpErrorInterceptor extends Interceptor { DioError( requestOptions: err.requestOptions, type: DioErrorType.badResponse, - error: const PaperlessServerException( - ErrorCode.missingClientCertificate), + error: const PaperlessServerException(ErrorCode.missingClientCertificate), ), ); } diff --git a/lib/core/navigation/push_routes.dart b/lib/core/navigation/push_routes.dart new file mode 100644 index 0000000..4a8615f --- /dev/null +++ b/lib/core/navigation/push_routes.dart @@ -0,0 +1,107 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_cache_manager/flutter_cache_manager.dart'; +import 'package:hive/hive.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_app_state.dart'; +import 'package:paperless_mobile/core/notifier/document_changed_notifier.dart'; +import 'package:paperless_mobile/core/repository/label_repository.dart'; +import 'package:paperless_mobile/core/repository/user_repository.dart'; +import 'package:paperless_mobile/features/document_search/cubit/document_search_cubit.dart'; +import 'package:paperless_mobile/features/document_search/view/document_search_page.dart'; +import 'package:paperless_mobile/features/home/view/model/api_version.dart'; +import 'package:paperless_mobile/features/notifications/services/local_notification_service.dart'; +import 'package:paperless_mobile/features/saved_view/cubit/saved_view_cubit.dart'; +import 'package:paperless_mobile/features/saved_view_details/cubit/saved_view_details_cubit.dart'; +import 'package:paperless_mobile/features/saved_view_details/view/saved_view_details_page.dart'; +import 'package:paperless_mobile/routes/document_details_route.dart'; +import 'package:provider/provider.dart'; + +Future pushDocumentSearchPage(BuildContext context) { + final currentUser = + Hive.box(HiveBoxes.globalSettings).getValue()!.currentLoggedInUser; + return Navigator.of(context).push( + MaterialPageRoute( + builder: (_) => MultiProvider( + providers: [ + Provider.value(value: context.read()), + Provider.value(value: context.read()), + Provider.value(value: context.read()), + Provider.value(value: context.read()), + ], + builder: (context, _) { + return BlocProvider( + create: (context) => DocumentSearchCubit( + context.read(), + context.read(), + context.read(), + Hive.box(HiveBoxes.localUserAppState).get(currentUser)!, + ), + child: const DocumentSearchPage(), + ); + }, + ), + ), + ); +} + +Future pushDocumentDetailsRoute( + BuildContext context, { + required DocumentModel document, + bool isLabelClickable = true, + bool allowEdit = true, + String? titleAndContentQueryString, +}) { + return Navigator.of(context).push( + MaterialPageRoute( + builder: (_) => MultiProvider( + providers: [ + Provider.value(value: context.read()), + Provider.value(value: context.read()), + Provider.value(value: context.read()), + Provider.value(value: context.read()), + Provider.value(value: context.read()), + Provider.value(value: context.read()), + if (context.read().hasMultiUserSupport) + Provider.value(value: context.read()), + ], + child: DocumentDetailsRoute( + document: document, + isLabelClickable: isLabelClickable, + ), + ), + ), + ); +} + +Future pushSavedViewDetailsRoute(BuildContext context, {required SavedView savedView}) { + return Navigator.of(context).push( + MaterialPageRoute( + builder: (_) => MultiProvider( + providers: [ + Provider.value(value: context.read()), + Provider.value(value: context.read()), + Provider.value(value: context.read()), + Provider.value(value: context.read()), + ], + child: SavedViewDetailsPage( + onDelete: context.read().remove, + ), + builder: (_, child) { + return BlocProvider( + create: (context) => SavedViewDetailsCubit( + context.read(), + context.read(), + context.read(), + LocalUserAppState.current, + savedView: savedView, + ), + child: SavedViewDetailsPage(onDelete: context.read().remove), + ); + }, + ), + ), + ); +} diff --git a/lib/core/translation/error_code_localization_mapper.dart b/lib/core/translation/error_code_localization_mapper.dart index 4b2be11..9143850 100644 --- a/lib/core/translation/error_code_localization_mapper.dart +++ b/lib/core/translation/error_code_localization_mapper.dart @@ -72,5 +72,7 @@ String translateError(BuildContext context, ErrorCode code) { return S.of(context)!.couldNotLoadSuggestions; case ErrorCode.acknowledgeTasksError: return S.of(context)!.couldNotAcknowledgeTasks; + case ErrorCode.notAuthorized: + return "You do not have the permission to perform this action."; //TODO: INTL } } diff --git a/lib/features/app_drawer/view/app_drawer.dart b/lib/features/app_drawer/view/app_drawer.dart index 1a778a5..08d1479 100644 --- a/lib/features/app_drawer/view/app_drawer.dart +++ b/lib/features/app_drawer/view/app_drawer.dart @@ -3,14 +3,13 @@ import 'package:flutter/material.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/bloc/server_information_cubit.dart'; import 'package:paperless_mobile/core/widgets/paperless_logo.dart'; import 'package:paperless_mobile/extensions/flutter_extensions.dart'; +import 'package:paperless_mobile/features/home/view/model/api_version.dart'; import 'package:paperless_mobile/features/settings/view/settings_page.dart'; import 'package:paperless_mobile/generated/l10n/app_localizations.dart'; +import 'package:provider/provider.dart'; -import 'package:url_launcher/link.dart'; -import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher_string.dart'; class AppDrawer extends StatelessWidget { @@ -42,7 +41,16 @@ class AppDrawer extends StatelessWidget { ListTile( dense: true, leading: const Icon(Icons.bug_report_outlined), - title: Text(S.of(context)!.reportABug), + title: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(S.of(context)!.reportABug), + const Icon( + Icons.open_in_new, + size: 16, + ) + ], + ), onTap: () { launchUrlString( 'https://github.com/astubenbord/paperless-mobile/issues/new', @@ -64,7 +72,7 @@ class AppDrawer extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(S.of(context)!.donateCoffee), - Icon( + const Icon( Icons.open_in_new, size: 16, ) @@ -85,8 +93,8 @@ class AppDrawer extends StatelessWidget { ), onTap: () => Navigator.of(context).push( MaterialPageRoute( - builder: (_) => BlocProvider.value( - value: context.read(), + builder: (_) => Provider.value( + value: context.read(), child: const SettingsPage(), ), ), @@ -148,19 +156,19 @@ class AppDrawer extends StatelessWidget { return RichText( text: TextSpan( children: [ - TextSpan( + const TextSpan( text: 'Onboarding images by ', ), TextSpan( text: 'pch.vector', - style: TextStyle(color: Colors.blue), + style: const TextStyle(color: Colors.blue), recognizer: TapGestureRecognizer() ..onTap = () { launchUrlString( 'https://www.freepik.com/free-vector/business-team-working-cogwheel-mechanism-together_8270974.htm#query=setting&position=4&from_view=author'); }, ), - TextSpan( + const TextSpan( text: ' on Freepik.', ), ], diff --git a/lib/features/document_details/view/pages/document_details_page.dart b/lib/features/document_details/view/pages/document_details_page.dart index 0a90b4e..aeced88 100644 --- a/lib/features/document_details/view/pages/document_details_page.dart +++ b/lib/features/document_details/view/pages/document_details_page.dart @@ -1,8 +1,13 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:hive_flutter/adapters.dart'; import 'package:open_filex/open_filex.dart'; import 'package:paperless_api/paperless_api.dart'; import 'package:paperless_mobile/core/bloc/connectivity_cubit.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/repository/user_repository.dart'; import 'package:paperless_mobile/core/translation/error_code_localization_mapper.dart'; import 'package:paperless_mobile/core/widgets/material/colored_tab_bar.dart'; import 'package:paperless_mobile/extensions/flutter_extensions.dart'; @@ -11,19 +16,20 @@ import 'package:paperless_mobile/features/document_details/view/widgets/document import 'package:paperless_mobile/features/document_details/view/widgets/document_download_button.dart'; import 'package:paperless_mobile/features/document_details/view/widgets/document_meta_data_widget.dart'; import 'package:paperless_mobile/features/document_details/view/widgets/document_overview_widget.dart'; +import 'package:paperless_mobile/features/document_details/view/widgets/document_permissions_widget.dart'; import 'package:paperless_mobile/features/document_details/view/widgets/document_share_button.dart'; import 'package:paperless_mobile/features/document_edit/cubit/document_edit_cubit.dart'; import 'package:paperless_mobile/features/document_edit/view/document_edit_page.dart'; import 'package:paperless_mobile/features/documents/view/pages/document_view.dart'; import 'package:paperless_mobile/features/documents/view/widgets/delete_document_confirmation_dialog.dart'; import 'package:paperless_mobile/features/documents/view/widgets/document_preview.dart'; +import 'package:paperless_mobile/features/home/view/model/api_version.dart'; import 'package:paperless_mobile/features/similar_documents/cubit/similar_documents_cubit.dart'; import 'package:paperless_mobile/features/similar_documents/view/similar_documents_view.dart'; import 'package:paperless_mobile/generated/l10n/app_localizations.dart'; import 'package:paperless_mobile/helpers/message_helpers.dart'; class DocumentDetailsPage extends StatefulWidget { - final bool allowEdit; final bool isLabelClickable; final String? titleAndContentQueryString; @@ -31,7 +37,6 @@ class DocumentDetailsPage extends StatefulWidget { Key? key, this.isLabelClickable = true, this.titleAndContentQueryString, - this.allowEdit = true, }) : super(key: key); @override @@ -50,13 +55,16 @@ class _DocumentDetailsPageState extends State { @override Widget build(BuildContext context) { + final apiVersion = context.watch(); + + final tabLength = 4 + (apiVersion.supportsPermissions ? 1 : 0); return WillPopScope( onWillPop: () async { Navigator.of(context).pop(context.read().state.document); return false; }, child: DefaultTabController( - length: 4, + length: tabLength, child: BlocListener( listenWhen: (previous, current) => !previous.isConnected && current.isConnected, listener: (context, state) { @@ -65,7 +73,7 @@ class _DocumentDetailsPageState extends State { child: Scaffold( extendBodyBehindAppBar: false, floatingActionButtonLocation: FloatingActionButtonLocation.endDocked, - floatingActionButton: widget.allowEdit ? _buildEditButton() : null, + floatingActionButton: _buildEditButton(), bottomNavigationBar: _buildBottomAppBar(), body: NestedScrollView( headerSliverBuilder: (context, innerBoxIsScrolled) => [ @@ -90,7 +98,7 @@ class _DocumentDetailsPageState extends State { ), ), ), - Positioned.fill( + Positioned.fill( top: 0, child: Container( height: 100, @@ -147,6 +155,15 @@ class _DocumentDetailsPageState extends State { ), ), ), + if (apiVersion.supportsPermissions) + Tab( + child: Text( + "Permissions", + style: TextStyle( + color: Theme.of(context).colorScheme.onPrimaryContainer, + ), + ), + ), ], ), ), @@ -220,6 +237,15 @@ class _DocumentDetailsPageState extends State { ), ], ), + CustomScrollView( + controller: _pagingScrollController, + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + ), + const DocumentPermissionsWidget(), + ], + ), ], ), ), @@ -234,25 +260,29 @@ class _DocumentDetailsPageState extends State { } Widget _buildEditButton() { + bool canEdit = context.watchInternetConnection; + final apiVersion = context.watch(); + + if (apiVersion.supportsPermissions) { + canEdit = + LocalUserAccount.current.paperlessUser.hasPermission(UserPermissions.changeDocument); + } + if (!canEdit) { + return const SizedBox.shrink(); + } return BlocBuilder( builder: (context, state) { // final _filteredSuggestions = // state.suggestions?.documentDifference(state.document); - return BlocBuilder( - builder: (context, connectivityState) { - if (!connectivityState.isConnected) { - return const SizedBox.shrink(); - } - return Tooltip( - message: S.of(context)!.editDocumentTooltip, - preferBelow: false, - verticalOffset: 40, - child: FloatingActionButton( - child: const Icon(Icons.edit), - onPressed: () => _onEdit(state.document), - ), - ); - }, + + return Tooltip( + message: S.of(context)!.editDocumentTooltip, + preferBelow: false, + verticalOffset: 40, + child: FloatingActionButton( + child: const Icon(Icons.edit), + onPressed: canEdit ? () => _onEdit(state.document) : null, + ), ); }, ); @@ -265,14 +295,16 @@ class _DocumentDetailsPageState extends State { child: BlocBuilder( builder: (context, connectivityState) { final isConnected = connectivityState.isConnected; + + final canDelete = LocalUserAccount.current.paperlessUser + .hasPermission(UserPermissions.deleteDocument); return Row( mainAxisAlignment: MainAxisAlignment.start, children: [ IconButton( tooltip: S.of(context)!.deleteDocumentTooltip, icon: const Icon(Icons.delete), - onPressed: - widget.allowEdit && isConnected ? () => _onDelete(state.document) : null, + onPressed: (isConnected && canDelete) ? () => _onDelete(state.document) : null, ).paddedSymmetrically(horizontal: 4), DocumentDownloadButton( document: state.document, @@ -374,7 +406,7 @@ class _DocumentDetailsPageState extends State { Future _onOpen(DocumentModel document) async { Navigator.of(context).push( MaterialPageRoute( - builder: (context) => DocumentView( + builder: (_) => DocumentView( documentBytes: context.read().getPreview(document.id), ), ), diff --git a/lib/features/document_details/view/widgets/document_meta_data_widget.dart b/lib/features/document_details/view/widgets/document_meta_data_widget.dart index 07e26dd..24806c6 100644 --- a/lib/features/document_details/view/widgets/document_meta_data_widget.dart +++ b/lib/features/document_details/view/widgets/document_meta_data_widget.dart @@ -29,7 +29,11 @@ class _DocumentMetaDataWidgetState extends State { builder: (context, state) { debugPrint("Building state..."); if (state.metaData == null) { - return const Center(child: CircularProgressIndicator()); + return SliverToBoxAdapter( + child: const Center( + child: CircularProgressIndicator(), + ), + ); } return SliverList( delegate: SliverChildListDelegate( diff --git a/lib/features/document_details/view/widgets/document_permissions_widget.dart b/lib/features/document_details/view/widgets/document_permissions_widget.dart new file mode 100644 index 0000000..655fbf6 --- /dev/null +++ b/lib/features/document_details/view/widgets/document_permissions_widget.dart @@ -0,0 +1,12 @@ +import 'package:flutter/material.dart'; + +class DocumentPermissionsWidget extends StatelessWidget { + const DocumentPermissionsWidget({super.key}); + + @override + Widget build(BuildContext context) { + return const SliverToBoxAdapter( + child: Placeholder(), + ); + } +} diff --git a/lib/features/document_edit/view/document_edit_page.dart b/lib/features/document_edit/view/document_edit_page.dart index f40ca2d..baf6127 100644 --- a/lib/features/document_edit/view/document_edit_page.dart +++ b/lib/features/document_edit/view/document_edit_page.dart @@ -264,9 +264,12 @@ class _DocumentEditPageState extends State { var mergedDocument = document.copyWith( title: values[fkTitle], created: values[fkCreatedDate], - documentType: () => (values[fkDocumentType] as SetIdQueryParameter).id, - correspondent: () => (values[fkCorrespondent] as SetIdQueryParameter).id, - storagePath: () => (values[fkStoragePath] as SetIdQueryParameter).id, + documentType: () => + (values[fkDocumentType] as IdQueryParameter).whenOrNull(fromId: (id) => id), + correspondent: () => + (values[fkCorrespondent] as IdQueryParameter).whenOrNull(fromId: (id) => id), + storagePath: () => + (values[fkStoragePath] as IdQueryParameter).whenOrNull(fromId: (id) => id), tags: (values[fkTags] as IdsTagsQuery).include, content: values[fkContent], ); diff --git a/lib/features/document_scan/view/scanner_page.dart b/lib/features/document_scan/view/scanner_page.dart index ae60b2e..d396903 100644 --- a/lib/features/document_scan/view/scanner_page.dart +++ b/lib/features/document_scan/view/scanner_page.dart @@ -11,7 +11,6 @@ import 'package:paperless_api/paperless_api.dart'; import 'package:paperless_mobile/core/bloc/connectivity_cubit.dart'; import 'package:paperless_mobile/core/delegate/customizable_sliver_persistent_header_delegate.dart'; import 'package:paperless_mobile/core/global/constants.dart'; -import 'package:paperless_mobile/core/repository/label_repository.dart'; import 'package:paperless_mobile/core/service/file_description.dart'; import 'package:paperless_mobile/core/service/file_service.dart'; import 'package:paperless_mobile/features/app_drawer/view/app_drawer.dart'; @@ -23,7 +22,6 @@ import 'package:paperless_mobile/features/document_upload/view/document_upload_p import 'package:paperless_mobile/features/documents/view/pages/document_view.dart'; import 'package:paperless_mobile/features/tasks/cubit/task_status_cubit.dart'; import 'package:paperless_mobile/generated/l10n/app_localizations.dart'; -import 'package:paperless_mobile/helpers/file_helpers.dart'; import 'package:paperless_mobile/helpers/message_helpers.dart'; import 'package:paperless_mobile/helpers/permission_helpers.dart'; import 'package:path/path.dart' as p; diff --git a/lib/features/document_search/view/document_search_page.dart b/lib/features/document_search/view/document_search_page.dart index f28a701..14803f3 100644 --- a/lib/features/document_search/view/document_search_page.dart +++ b/lib/features/document_search/view/document_search_page.dart @@ -3,10 +3,15 @@ import 'dart:async'; import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_cache_manager/flutter_cache_manager.dart'; import 'package:hive/hive.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_app_state.dart'; +import 'package:paperless_mobile/core/navigation/push_routes.dart'; +import 'package:paperless_mobile/core/notifier/document_changed_notifier.dart'; +import 'package:paperless_mobile/core/repository/label_repository.dart'; import 'package:paperless_mobile/extensions/flutter_extensions.dart'; import 'package:paperless_mobile/features/document_search/cubit/document_search_cubit.dart'; import 'package:paperless_mobile/features/document_search/view/remove_history_entry_dialog.dart'; @@ -17,23 +22,7 @@ import 'package:paperless_mobile/generated/l10n/app_localizations.dart'; import 'package:paperless_mobile/routes/document_details_route.dart'; import 'dart:math' as math; -Future showDocumentSearchPage(BuildContext context) { - final currentUser = - Hive.box(HiveBoxes.globalSettings).getValue()!.currentLoggedInUser; - return Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => BlocProvider( - create: (context) => DocumentSearchCubit( - context.read(), - context.read(), - context.read(), - Hive.box(HiveBoxes.localUserAppState).get(currentUser)!, - ), - child: const DocumentSearchPage(), - ), - ), - ); -} +import 'package:provider/provider.dart'; class DocumentSearchPage extends StatefulWidget { const DocumentSearchPage({super.key}); diff --git a/lib/features/document_search/view/sliver_search_bar.dart b/lib/features/document_search/view/sliver_search_bar.dart index 0f36ff7..ba1feba 100644 --- a/lib/features/document_search/view/sliver_search_bar.dart +++ b/lib/features/document_search/view/sliver_search_bar.dart @@ -1,16 +1,17 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:hive_flutter/adapters.dart'; -import 'package:paperless_mobile/core/bloc/server_information_cubit.dart'; import 'package:paperless_mobile/core/config/hive/hive_config.dart'; import 'package:paperless_mobile/core/database/tables/local_user_account.dart'; import 'package:paperless_mobile/core/delegate/customizable_sliver_persistent_header_delegate.dart'; +import 'package:paperless_mobile/core/navigation/push_routes.dart'; import 'package:paperless_mobile/core/widgets/material/search/m3_search_bar.dart' as s; -import 'package:paperless_mobile/features/document_search/view/document_search_page.dart'; +import 'package:paperless_mobile/features/home/view/model/api_version.dart'; import 'package:paperless_mobile/features/settings/view/manage_accounts_page.dart'; import 'package:paperless_mobile/features/settings/view/widgets/global_settings_builder.dart'; import 'package:paperless_mobile/features/settings/view/widgets/user_avatar.dart'; import 'package:paperless_mobile/generated/l10n/app_localizations.dart'; +import 'package:provider/provider.dart'; class SliverSearchBar extends StatelessWidget { final bool floating; @@ -34,7 +35,7 @@ class SliverSearchBar extends StatelessWidget { child: s.SearchBar( height: kToolbarHeight, supportingText: S.of(context)!.searchDocuments, - onTap: () => showDocumentSearchPage(context), + onTap: () => pushDocumentSearchPage(context), leadingIcon: IconButton( icon: const Icon(Icons.menu), onPressed: Scaffold.of(context).openDrawer, @@ -58,8 +59,8 @@ class SliverSearchBar extends StatelessWidget { onPressed: () { showDialog( context: context, - builder: (_) => BlocProvider.value( - value: context.read(), + builder: (_) => Provider.value( + value: context.read(), child: const ManageAccountsPage(), ), ); diff --git a/lib/features/documents/cubit/documents_cubit.dart b/lib/features/documents/cubit/documents_cubit.dart index 36297f5..78226a8 100644 --- a/lib/features/documents/cubit/documents_cubit.dart +++ b/lib/features/documents/cubit/documents_cubit.dart @@ -14,7 +14,7 @@ import 'package:paperless_mobile/features/settings/model/view_type.dart'; part 'documents_cubit.g.dart'; part 'documents_state.dart'; -class DocumentsCubit extends Cubit with DocumentPagingBlocMixin { +class DocumentsCubit extends HydratedCubit with DocumentPagingBlocMixin { @override final PaperlessDocumentsApi api; @@ -123,4 +123,14 @@ class DocumentsCubit extends Cubit with DocumentPagingBlocMixin _userState.currentDocumentFilter = filter; await _userState.save(); } + + @override + DocumentsState? fromJson(Map json) { + return DocumentsState.fromJson(json); + } + + @override + Map? toJson(DocumentsState state) { + return state.toJson(); + } } diff --git a/lib/features/documents/view/pages/document_view.dart b/lib/features/documents/view/pages/document_view.dart index 09131cf..e7fa0e8 100644 --- a/lib/features/documents/view/pages/document_view.dart +++ b/lib/features/documents/view/pages/document_view.dart @@ -2,8 +2,6 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:paperless_mobile/generated/l10n/app_localizations.dart'; -import 'package:pdfx/pdfx.dart'; - class DocumentView extends StatefulWidget { final Future documentBytes; @@ -17,36 +15,37 @@ class DocumentView extends StatefulWidget { } class _DocumentViewState extends State { - late PdfController _pdfController; + // late PdfController _pdfController; @override void initState() { super.initState(); - _pdfController = PdfController( - document: PdfDocument.openData( - widget.documentBytes, - ), - ); + // _pdfController = PdfController( + // document: PdfDocument.openData( + // widget.documentBytes, + // ), + // ); } @override Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Text(S.of(context)!.preview), - ), - body: PdfView( - builders: PdfViewBuilders( - options: const DefaultBuilderOptions( - loaderSwitchDuration: Duration(milliseconds: 500), - ), - pageLoaderBuilder: (context) => const Center( - child: CircularProgressIndicator(), - ), - ), - scrollDirection: Axis.vertical, - controller: _pdfController, - ), - ); + return Container(); + // return Scaffold( + // appBar: AppBar( + // title: Text(S.of(context)!.preview), + // ), + // body: PdfView( + // builders: PdfViewBuilders( + // options: const DefaultBuilderOptions( + // loaderSwitchDuration: Duration(milliseconds: 500), + // ), + // pageLoaderBuilder: (context) => const Center( + // child: CircularProgressIndicator(), + // ), + // ), + // scrollDirection: Axis.vertical, + // controller: _pdfController, + // ), + // ); } } diff --git a/lib/features/documents/view/pages/documents_page.dart b/lib/features/documents/view/pages/documents_page.dart index c76f86b..2d9d359 100644 --- a/lib/features/documents/view/pages/documents_page.dart +++ b/lib/features/documents/view/pages/documents_page.dart @@ -5,6 +5,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:paperless_api/paperless_api.dart'; import 'package:paperless_mobile/core/bloc/connectivity_cubit.dart'; import 'package:paperless_mobile/core/delegate/customizable_sliver_persistent_header_delegate.dart'; +import 'package:paperless_mobile/core/navigation/push_routes.dart'; import 'package:paperless_mobile/core/repository/label_repository.dart'; import 'package:paperless_mobile/core/widgets/material/colored_tab_bar.dart'; import 'package:paperless_mobile/extensions/flutter_extensions.dart'; @@ -375,10 +376,10 @@ class _DocumentsPageState extends State with SingleTickerProvider builder: (context, state) { return AddSavedViewPage( currentFilter: filter, - correspondents: state.correspondents, - documentTypes: state.documentTypes, - storagePaths: state.storagePaths, - tags: state.tags, + correspondents: context.read().state.correspondents, + documentTypes: context.read().state.documentTypes, + storagePaths: context.read().state.storagePaths, + tags: context.read().state.tags, ); }, ), diff --git a/lib/features/documents/view/widgets/search/sort_field_selection_bottom_sheet.dart b/lib/features/documents/view/widgets/search/sort_field_selection_bottom_sheet.dart index 51669bc..f74b619 100644 --- a/lib/features/documents/view/widgets/search/sort_field_selection_bottom_sheet.dart +++ b/lib/features/documents/view/widgets/search/sort_field_selection_bottom_sheet.dart @@ -1,10 +1,8 @@ import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:paperless_api/paperless_api.dart'; import 'package:paperless_mobile/core/translation/sort_field_localization_mapper.dart'; import 'package:paperless_mobile/extensions/flutter_extensions.dart'; -import 'package:paperless_mobile/features/labels/cubit/label_cubit.dart'; import 'package:paperless_mobile/generated/l10n/app_localizations.dart'; class SortFieldSelectionBottomSheet extends StatefulWidget { @@ -29,12 +27,10 @@ class SortFieldSelectionBottomSheet extends StatefulWidget { }); @override - State createState() => - _SortFieldSelectionBottomSheetState(); + State createState() => _SortFieldSelectionBottomSheetState(); } -class _SortFieldSelectionBottomSheetState - extends State { +class _SortFieldSelectionBottomSheetState extends State { late SortField? _currentSortField; late SortOrder _currentSortOrder; @@ -62,8 +58,8 @@ class _SortFieldSelectionBottomSheetState ), TextButton( child: Text(S.of(context)!.apply), - onPressed: () { - widget.onSubmit( + onPressed: () async { + await widget.onSubmit( _currentSortField, _currentSortOrder, ); @@ -131,7 +127,9 @@ class _SortFieldSelectionBottomSheetState contentPadding: const EdgeInsets.only(left: 32, right: 16), title: Text(translateSortField(context, field)), trailing: _currentSortField == field ? const Icon(Icons.done) : null, - onTap: () => setState(() => _currentSortField = field), + onTap: () { + setState(() => _currentSortField = field); + }, ); } } diff --git a/lib/features/documents/view/widgets/sort_documents_button.dart b/lib/features/documents/view/widgets/sort_documents_button.dart index 822c69c..95909ab 100644 --- a/lib/features/documents/view/widgets/sort_documents_button.dart +++ b/lib/features/documents/view/widgets/sort_documents_button.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:paperless_api/paperless_api.dart'; -import 'package:paperless_mobile/core/repository/label_repository.dart'; import 'package:paperless_mobile/core/translation/sort_field_localization_mapper.dart'; import 'package:paperless_mobile/features/documents/cubit/documents_cubit.dart'; import 'package:paperless_mobile/features/documents/view/widgets/search/sort_field_selection_bottom_sheet.dart'; @@ -21,6 +20,7 @@ class SortDocumentsButton extends StatelessWidget { if (state.filter.sortField == null) { return const SizedBox.shrink(); } + print(state.filter.sortField); return TextButton.icon( icon: Icon(state.filter.sortOrder == SortOrder.ascending ? Icons.arrow_upward @@ -49,14 +49,14 @@ class SortDocumentsButton extends StatelessWidget { child: SortFieldSelectionBottomSheet( initialSortField: state.filter.sortField, initialSortOrder: state.filter.sortOrder, - onSubmit: (field, order) => context - .read() - .updateCurrentFilter( - (filter) => filter.copyWith( - sortField: field, - sortOrder: order, - ), - ), + onSubmit: (field, order) { + return context.read().updateCurrentFilter( + (filter) => filter.copyWith( + sortField: field, + sortOrder: order, + ), + ); + }, correspondents: state.correspondents, documentTypes: state.documentTypes, storagePaths: state.storagePaths, diff --git a/lib/features/home/view/home_page.dart b/lib/features/home/view/home_page.dart index cf075fa..83b5f3b 100644 --- a/lib/features/home/view/home_page.dart +++ b/lib/features/home/view/home_page.dart @@ -9,13 +9,13 @@ import 'package:fluttertoast/fluttertoast.dart'; import 'package:hive/hive.dart'; import 'package:paperless_api/paperless_api.dart'; import 'package:paperless_mobile/core/bloc/connectivity_cubit.dart'; -import 'package:paperless_mobile/core/bloc/server_information_cubit.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_app_state.dart'; import 'package:paperless_mobile/core/global/constants.dart'; import 'package:paperless_mobile/core/repository/label_repository.dart'; import 'package:paperless_mobile/core/repository/saved_view_repository.dart'; +import 'package:paperless_mobile/core/repository/user_repository.dart'; import 'package:paperless_mobile/core/service/file_description.dart'; import 'package:paperless_mobile/core/translation/error_code_localization_mapper.dart'; import 'package:paperless_mobile/features/document_scan/cubit/document_scanner_cubit.dart'; @@ -44,7 +44,8 @@ import 'package:responsive_builder/responsive_builder.dart'; /// Wrapper around all functionality for a logged in user. /// Performs initialization logic. class HomePage extends StatefulWidget { - const HomePage({Key? key}) : super(key: key); + final int paperlessApiVersion; + const HomePage({Key? key, required this.paperlessApiVersion}) : super(key: key); @override _HomePageState createState() => _HomePageState(); @@ -186,8 +187,6 @@ class _HomePageState extends State with WidgetsBindingObserver { @override Widget build(BuildContext context) { - final userId = - Hive.box(HiveBoxes.globalSettings).getValue()!.currentLoggedInUser!; final destinations = [ RouteDescription( icon: const Icon(Icons.description_outlined), @@ -235,6 +234,7 @@ class _HomePageState extends State with WidgetsBindingObserver { ]; final routes = [ const DocumentsPage(), + if (LocalUserAccount.current.paperlessUser.hasPermission(UserPermissions.changeDocument)) const ScannerPage(), const LabelsPage(), const InboxPage(), @@ -303,7 +303,6 @@ class _HomePageState extends State with WidgetsBindingObserver { Future.wait([ context.read().initialize(), context.read().findAll(), - context.read().updateInformation(), ]).onError((error, stackTrace) { showErrorMessage(context, error, stackTrace); throw error; diff --git a/lib/features/home/view/home_route.dart b/lib/features/home/view/home_route.dart index eb08550..3d7928d 100644 --- a/lib/features/home/view/home_route.dart +++ b/lib/features/home/view/home_route.dart @@ -3,18 +3,19 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_cache_manager/flutter_cache_manager.dart'; import 'package:hive_flutter/adapters.dart'; import 'package:paperless_api/paperless_api.dart'; -import 'package:paperless_mobile/core/bloc/server_information_cubit.dart'; import 'package:paperless_mobile/core/config/hive/hive_config.dart'; import 'package:paperless_mobile/core/database/tables/local_user_app_state.dart'; import 'package:paperless_mobile/core/factory/paperless_api_factory.dart'; import 'package:paperless_mobile/core/notifier/document_changed_notifier.dart'; import 'package:paperless_mobile/core/repository/label_repository.dart'; import 'package:paperless_mobile/core/repository/saved_view_repository.dart'; +import 'package:paperless_mobile/core/repository/user_repository.dart'; import 'package:paperless_mobile/core/security/session_manager.dart'; import 'package:paperless_mobile/core/service/dio_file_service.dart'; import 'package:paperless_mobile/features/document_scan/cubit/document_scanner_cubit.dart'; import 'package:paperless_mobile/features/documents/cubit/documents_cubit.dart'; import 'package:paperless_mobile/features/home/view/home_page.dart'; +import 'package:paperless_mobile/features/home/view/model/api_version.dart'; import 'package:paperless_mobile/features/inbox/cubit/inbox_cubit.dart'; import 'package:paperless_mobile/features/labels/cubit/label_cubit.dart'; import 'package:paperless_mobile/features/saved_view/cubit/saved_view_cubit.dart'; @@ -46,6 +47,7 @@ class HomeRoute extends StatelessWidget { final currentLocalUserId = settings.currentLoggedInUser!; return MultiProvider( providers: [ + Provider.value(value: ApiVersion(paperlessApiVersion)), Provider( create: (context) => CacheManager( Config( @@ -85,6 +87,12 @@ class HomeRoute extends StatelessWidget { apiVersion: paperlessApiVersion, ), ), + if (paperlessApiVersion >= 3) + ProxyProvider( + update: (context, value, previous) => PaperlessUserApiV3Impl( + value.client, + ), + ), ], builder: (context, child) { return MultiProvider( @@ -97,7 +105,7 @@ class HomeRoute extends StatelessWidget { ), ], builder: (context, child) { - return MultiBlocProvider( + return MultiProvider( providers: [ ProxyProvider3( @@ -120,24 +128,23 @@ class HomeRoute extends StatelessWidget { notifier, )..initialize(), ), - ProxyProvider2( - update: (context, savedViewRepo, labelRepo, previous) => SavedViewCubit( + ProxyProvider( + update: (context, savedViewRepo, previous) => SavedViewCubit( savedViewRepo, - labelRepo, )..initialize(), ), - ProxyProvider( - update: (context, value, previous) => - ServerInformationCubit(value)..updateInformation(), - ), ProxyProvider( update: (context, value, previous) => LabelCubit(value), ), ProxyProvider( update: (context, value, previous) => TaskStatusCubit(value), ), + if (paperlessApiVersion >= 3) + ProxyProvider( + update: (context, value, previous) => UserRepository(value)..initialize(), + ), ], - child: const HomePage(), + child: HomePage(paperlessApiVersion: paperlessApiVersion), ); }, ); diff --git a/lib/features/home/view/model/api_version.dart b/lib/features/home/view/model/api_version.dart new file mode 100644 index 0000000..f44beaf --- /dev/null +++ b/lib/features/home/view/model/api_version.dart @@ -0,0 +1,8 @@ +class ApiVersion { + final int version; + + ApiVersion(this.version); + + bool get supportsPermissions => version >= 3; + bool get hasMultiUserSupport => version >= 3; +} diff --git a/lib/features/inbox/view/widgets/inbox_item.dart b/lib/features/inbox/view/widgets/inbox_item.dart index 235f9e1..910d487 100644 --- a/lib/features/inbox/view/widgets/inbox_item.dart +++ b/lib/features/inbox/view/widgets/inbox_item.dart @@ -2,6 +2,7 @@ import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:paperless_api/paperless_api.dart'; +import 'package:paperless_mobile/core/navigation/push_routes.dart'; import 'package:paperless_mobile/core/workarounds/colored_chip.dart'; import 'package:paperless_mobile/extensions/flutter_extensions.dart'; import 'package:paperless_mobile/features/documents/view/widgets/delete_document_confirmation_dialog.dart'; diff --git a/lib/features/linked_documents/view/linked_documents_page.dart b/lib/features/linked_documents/view/linked_documents_page.dart index e8a688b..eeaa148 100644 --- a/lib/features/linked_documents/view/linked_documents_page.dart +++ b/lib/features/linked_documents/view/linked_documents_page.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:paperless_mobile/core/bloc/connectivity_cubit.dart'; +import 'package:paperless_mobile/core/navigation/push_routes.dart'; import 'package:paperless_mobile/features/documents/view/widgets/adaptive_documents_view.dart'; import 'package:paperless_mobile/features/documents/view/widgets/selection/view_type_selection_widget.dart'; import 'package:paperless_mobile/features/linked_documents/cubit/linked_documents_cubit.dart'; diff --git a/lib/features/login/cubit/authentication_cubit.dart b/lib/features/login/cubit/authentication_cubit.dart index 042e093..0dc1d76 100644 --- a/lib/features/login/cubit/authentication_cubit.dart +++ b/lib/features/login/cubit/authentication_cubit.dart @@ -3,25 +3,24 @@ import 'dart:typed_data'; import 'package:dio/dio.dart'; import 'package:flutter/widgets.dart'; +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:hive_flutter/adapters.dart'; import 'package:hydrated_bloc/hydrated_bloc.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/database/tables/local_user_app_state.dart'; +import 'package:paperless_mobile/core/database/tables/local_user_settings.dart'; +import 'package:paperless_mobile/core/database/tables/user_credentials.dart'; import 'package:paperless_mobile/core/factory/paperless_api_factory.dart'; import 'package:paperless_mobile/core/security/session_manager.dart'; import 'package:paperless_mobile/features/login/model/client_certificate.dart'; import 'package:paperless_mobile/features/login/model/login_form_credentials.dart'; -import 'package:paperless_mobile/core/database/tables/local_user_account.dart'; -import 'package:paperless_mobile/core/database/tables/user_credentials.dart'; import 'package:paperless_mobile/features/login/services/authentication_service.dart'; -import 'package:paperless_mobile/core/database/tables/global_settings.dart'; -import 'package:paperless_mobile/core/database/tables/local_user_settings.dart'; -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; -part 'authentication_state.dart'; part 'authentication_cubit.freezed.dart'; +part 'authentication_state.dart'; class AuthenticationCubit extends Cubit { final LocalAuthenticationService _localAuthService; @@ -111,6 +110,12 @@ class AuthenticationCubit extends Cubit { final apiVersion = await _getApiVersion(_sessionManager.client); + await _updateRemoteUser( + _sessionManager, + Hive.box(HiveBoxes.localUserAccount).get(localUserId)!, + apiVersion, + ); + emit(AuthenticationState.authenticated( localUserId: localUserId, apiVersion: apiVersion, @@ -163,10 +168,10 @@ class AuthenticationCubit extends Cubit { // If there is nothing to restore, we can quit here. return; } + final localUserAccountBox = Hive.box(HiveBoxes.localUserAccount); + final localUserAccount = localUserAccountBox.get(localUserId)!; - final userAccount = Hive.box(HiveBoxes.localUserAccount).get(localUserId)!; - - if (userAccount.settings.isBiometricAuthenticationEnabled) { + if (localUserAccount.settings.isBiometricAuthenticationEnabled) { final localAuthSuccess = await _localAuthService.authenticateLocalUser("Authenticate to log back in"); //TODO: INTL if (!localAuthSuccess) { @@ -176,18 +181,23 @@ class AuthenticationCubit extends Cubit { } final userCredentialsBox = await _getUserCredentialsBox(); final authentication = userCredentialsBox.get(globalSettings.currentLoggedInUser!); - await userCredentialsBox.close(); if (authentication == null) { - throw Exception("User should be authenticated but no authentication information was found."); + throw Exception( + "User should be authenticated but no authentication information was found."); //TODO: INTL } _sessionManager.updateSettings( clientCertificate: authentication.clientCertificate, authToken: authentication.token, - baseUrl: userAccount.serverUrl, + baseUrl: localUserAccount.serverUrl, ); final apiVersion = await _getApiVersion(_sessionManager.client); + await _updateRemoteUser( + _sessionManager, + localUserAccount, + apiVersion, + ); emit( AuthenticationState.authenticated( apiVersion: apiVersion, @@ -258,7 +268,7 @@ class AuthenticationCubit extends Cubit { clientCertificate: clientCert, authToken: token, ); - + final userAccountBox = Hive.box(HiveBoxes.localUserAccount); final userStateBox = Hive.box(HiveBoxes.localUserAppState); @@ -308,4 +318,20 @@ class AuthenticationCubit extends Cubit { final response = await dio.get("/api/"); return int.parse(response.headers.value('x-api-version') ?? "3"); } + + /// Fetches possibly updated (permissions, name, updated server version and thus new user model, ...) remote user data. + Future _updateRemoteUser( + SessionManager sessionManager, + LocalUserAccount localUserAccount, + int apiVersion, + ) async { + final updatedPaperlessUser = await _apiFactory + .createUserApi( + sessionManager.client, + apiVersion: apiVersion, + ) + .findCurrentUser(); + localUserAccount.paperlessUser = updatedPaperlessUser; + await localUserAccount.save(); + } } diff --git a/lib/features/saved_view/cubit/saved_view_cubit.dart b/lib/features/saved_view/cubit/saved_view_cubit.dart index 76912e8..ca2bff6 100644 --- a/lib/features/saved_view/cubit/saved_view_cubit.dart +++ b/lib/features/saved_view/cubit/saved_view_cubit.dart @@ -11,38 +11,14 @@ part 'saved_view_cubit.freezed.dart'; class SavedViewCubit extends Cubit { final SavedViewRepository _savedViewRepository; - final LabelRepository _labelRepository; - - SavedViewCubit(this._savedViewRepository, this._labelRepository) - : super( - SavedViewState.initial( - correspondents: _labelRepository.state.correspondents, - documentTypes: _labelRepository.state.documentTypes, - storagePaths: _labelRepository.state.storagePaths, - tags: _labelRepository.state.tags, - ), - ) { - _labelRepository.addListener( - this, - onChanged: (labels) { - emit( - state.copyWith( - correspondents: labels.correspondents, - documentTypes: labels.documentTypes, - tags: labels.tags, - storagePaths: labels.storagePaths, - ), - ); - }, - ); + SavedViewCubit(this._savedViewRepository) : super(const SavedViewState.initial()) { _savedViewRepository.addListener( this, onChanged: (views) { emit( state.maybeWhen( - loaded: (savedViews, correspondents, documentTypes, tags, storagePaths) => - (state as _SavedViewLoadedState).copyWith( + loaded: (savedViews) => (state as _SavedViewLoadedState).copyWith( savedViews: views.savedViews, ), orElse: () => state, @@ -64,13 +40,11 @@ class SavedViewCubit extends Cubit { final views = await _savedViewRepository.findAll(); final values = {for (var element in views) element.id!: element}; if (!isClosed) { - emit(SavedViewState.loaded( - savedViews: values, - correspondents: state.correspondents, - documentTypes: state.documentTypes, - storagePaths: state.storagePaths, - tags: state.tags, - )); + emit( + SavedViewState.loaded( + savedViews: values, + ), + ); } } @@ -79,7 +53,6 @@ class SavedViewCubit extends Cubit { @override Future close() { _savedViewRepository.removeListener(this); - _labelRepository.removeListener(this); return super.close(); } } diff --git a/lib/features/saved_view/cubit/saved_view_cubit.freezed.dart b/lib/features/saved_view/cubit/saved_view_cubit.freezed.dart index 64fd200..ab53977 100644 --- a/lib/features/saved_view/cubit/saved_view_cubit.freezed.dart +++ b/lib/features/saved_view/cubit/saved_view_cubit.freezed.dart @@ -16,97 +16,28 @@ final _privateConstructorUsedError = UnsupportedError( /// @nodoc mixin _$SavedViewState { - Map get correspondents => - throw _privateConstructorUsedError; - Map get documentTypes => - throw _privateConstructorUsedError; - Map get tags => throw _privateConstructorUsedError; - Map get storagePaths => throw _privateConstructorUsedError; @optionalTypeArgs TResult when({ - required TResult Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths) - initial, - required TResult Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths) - loading, - required TResult Function( - Map savedViews, - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths) - loaded, - required TResult Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths) - error, + required TResult Function() initial, + required TResult Function() loading, + required TResult Function(Map savedViews) loaded, + required TResult Function() error, }) => throw _privateConstructorUsedError; @optionalTypeArgs TResult? whenOrNull({ - TResult? Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths)? - initial, - TResult? Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths)? - loading, - TResult? Function( - Map savedViews, - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths)? - loaded, - TResult? Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths)? - error, + TResult? Function()? initial, + TResult? Function()? loading, + TResult? Function(Map savedViews)? loaded, + TResult? Function()? error, }) => throw _privateConstructorUsedError; @optionalTypeArgs TResult maybeWhen({ - TResult Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths)? - initial, - TResult Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths)? - loading, - TResult Function( - Map savedViews, - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths)? - loaded, - TResult Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths)? - error, + TResult Function()? initial, + TResult Function()? loading, + TResult Function(Map savedViews)? loaded, + TResult Function()? error, required TResult orElse(), }) => throw _privateConstructorUsedError; @@ -135,10 +66,6 @@ mixin _$SavedViewState { required TResult orElse(), }) => throw _privateConstructorUsedError; - - @JsonKey(ignore: true) - $SavedViewStateCopyWith get copyWith => - throw _privateConstructorUsedError; } /// @nodoc @@ -146,12 +73,6 @@ abstract class $SavedViewStateCopyWith<$Res> { factory $SavedViewStateCopyWith( SavedViewState value, $Res Function(SavedViewState) then) = _$SavedViewStateCopyWithImpl<$Res, SavedViewState>; - @useResult - $Res call( - {Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths}); } /// @nodoc @@ -163,49 +84,13 @@ class _$SavedViewStateCopyWithImpl<$Res, $Val extends SavedViewState> final $Val _value; // ignore: unused_field final $Res Function($Val) _then; - - @pragma('vm:prefer-inline') - @override - $Res call({ - Object? correspondents = null, - Object? documentTypes = null, - Object? tags = null, - Object? storagePaths = null, - }) { - return _then(_value.copyWith( - correspondents: null == correspondents - ? _value.correspondents - : correspondents // ignore: cast_nullable_to_non_nullable - as Map, - documentTypes: null == documentTypes - ? _value.documentTypes - : documentTypes // ignore: cast_nullable_to_non_nullable - as Map, - tags: null == tags - ? _value.tags - : tags // ignore: cast_nullable_to_non_nullable - as Map, - storagePaths: null == storagePaths - ? _value.storagePaths - : storagePaths // ignore: cast_nullable_to_non_nullable - as Map, - ) as $Val); - } } /// @nodoc -abstract class _$$_SavedViewIntialStateCopyWith<$Res> - implements $SavedViewStateCopyWith<$Res> { +abstract class _$$_SavedViewIntialStateCopyWith<$Res> { factory _$$_SavedViewIntialStateCopyWith(_$_SavedViewIntialState value, $Res Function(_$_SavedViewIntialState) then) = __$$_SavedViewIntialStateCopyWithImpl<$Res>; - @override - @useResult - $Res call( - {Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths}); } /// @nodoc @@ -215,211 +100,60 @@ class __$$_SavedViewIntialStateCopyWithImpl<$Res> __$$_SavedViewIntialStateCopyWithImpl(_$_SavedViewIntialState _value, $Res Function(_$_SavedViewIntialState) _then) : super(_value, _then); - - @pragma('vm:prefer-inline') - @override - $Res call({ - Object? correspondents = null, - Object? documentTypes = null, - Object? tags = null, - Object? storagePaths = null, - }) { - return _then(_$_SavedViewIntialState( - correspondents: null == correspondents - ? _value._correspondents - : correspondents // ignore: cast_nullable_to_non_nullable - as Map, - documentTypes: null == documentTypes - ? _value._documentTypes - : documentTypes // ignore: cast_nullable_to_non_nullable - as Map, - tags: null == tags - ? _value._tags - : tags // ignore: cast_nullable_to_non_nullable - as Map, - storagePaths: null == storagePaths - ? _value._storagePaths - : storagePaths // ignore: cast_nullable_to_non_nullable - as Map, - )); - } } /// @nodoc class _$_SavedViewIntialState implements _SavedViewIntialState { - const _$_SavedViewIntialState( - {required final Map correspondents, - required final Map documentTypes, - required final Map tags, - required final Map storagePaths}) - : _correspondents = correspondents, - _documentTypes = documentTypes, - _tags = tags, - _storagePaths = storagePaths; - - final Map _correspondents; - @override - Map get correspondents { - if (_correspondents is EqualUnmodifiableMapView) return _correspondents; - // ignore: implicit_dynamic_type - return EqualUnmodifiableMapView(_correspondents); - } - - final Map _documentTypes; - @override - Map get documentTypes { - if (_documentTypes is EqualUnmodifiableMapView) return _documentTypes; - // ignore: implicit_dynamic_type - return EqualUnmodifiableMapView(_documentTypes); - } - - final Map _tags; - @override - Map get tags { - if (_tags is EqualUnmodifiableMapView) return _tags; - // ignore: implicit_dynamic_type - return EqualUnmodifiableMapView(_tags); - } - - final Map _storagePaths; - @override - Map get storagePaths { - if (_storagePaths is EqualUnmodifiableMapView) return _storagePaths; - // ignore: implicit_dynamic_type - return EqualUnmodifiableMapView(_storagePaths); - } + const _$_SavedViewIntialState(); @override String toString() { - return 'SavedViewState.initial(correspondents: $correspondents, documentTypes: $documentTypes, tags: $tags, storagePaths: $storagePaths)'; + return 'SavedViewState.initial()'; } @override bool operator ==(dynamic other) { return identical(this, other) || - (other.runtimeType == runtimeType && - other is _$_SavedViewIntialState && - const DeepCollectionEquality() - .equals(other._correspondents, _correspondents) && - const DeepCollectionEquality() - .equals(other._documentTypes, _documentTypes) && - const DeepCollectionEquality().equals(other._tags, _tags) && - const DeepCollectionEquality() - .equals(other._storagePaths, _storagePaths)); + (other.runtimeType == runtimeType && other is _$_SavedViewIntialState); } @override - int get hashCode => Object.hash( - runtimeType, - const DeepCollectionEquality().hash(_correspondents), - const DeepCollectionEquality().hash(_documentTypes), - const DeepCollectionEquality().hash(_tags), - const DeepCollectionEquality().hash(_storagePaths)); - - @JsonKey(ignore: true) - @override - @pragma('vm:prefer-inline') - _$$_SavedViewIntialStateCopyWith<_$_SavedViewIntialState> get copyWith => - __$$_SavedViewIntialStateCopyWithImpl<_$_SavedViewIntialState>( - this, _$identity); + int get hashCode => runtimeType.hashCode; @override @optionalTypeArgs TResult when({ - required TResult Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths) - initial, - required TResult Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths) - loading, - required TResult Function( - Map savedViews, - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths) - loaded, - required TResult Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths) - error, + required TResult Function() initial, + required TResult Function() loading, + required TResult Function(Map savedViews) loaded, + required TResult Function() error, }) { - return initial(correspondents, documentTypes, tags, storagePaths); + return initial(); } @override @optionalTypeArgs TResult? whenOrNull({ - TResult? Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths)? - initial, - TResult? Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths)? - loading, - TResult? Function( - Map savedViews, - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths)? - loaded, - TResult? Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths)? - error, + TResult? Function()? initial, + TResult? Function()? loading, + TResult? Function(Map savedViews)? loaded, + TResult? Function()? error, }) { - return initial?.call(correspondents, documentTypes, tags, storagePaths); + return initial?.call(); } @override @optionalTypeArgs TResult maybeWhen({ - TResult Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths)? - initial, - TResult Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths)? - loading, - TResult Function( - Map savedViews, - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths)? - loaded, - TResult Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths)? - error, + TResult Function()? initial, + TResult Function()? loading, + TResult Function(Map savedViews)? loaded, + TResult Function()? error, required TResult orElse(), }) { if (initial != null) { - return initial(correspondents, documentTypes, tags, storagePaths); + return initial(); } return orElse(); } @@ -463,40 +197,14 @@ class _$_SavedViewIntialState implements _SavedViewIntialState { } abstract class _SavedViewIntialState implements SavedViewState { - const factory _SavedViewIntialState( - {required final Map correspondents, - required final Map documentTypes, - required final Map tags, - required final Map storagePaths}) = - _$_SavedViewIntialState; - - @override - Map get correspondents; - @override - Map get documentTypes; - @override - Map get tags; - @override - Map get storagePaths; - @override - @JsonKey(ignore: true) - _$$_SavedViewIntialStateCopyWith<_$_SavedViewIntialState> get copyWith => - throw _privateConstructorUsedError; + const factory _SavedViewIntialState() = _$_SavedViewIntialState; } /// @nodoc -abstract class _$$_SavedViewLoadingStateCopyWith<$Res> - implements $SavedViewStateCopyWith<$Res> { +abstract class _$$_SavedViewLoadingStateCopyWith<$Res> { factory _$$_SavedViewLoadingStateCopyWith(_$_SavedViewLoadingState value, $Res Function(_$_SavedViewLoadingState) then) = __$$_SavedViewLoadingStateCopyWithImpl<$Res>; - @override - @useResult - $Res call( - {Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths}); } /// @nodoc @@ -506,211 +214,60 @@ class __$$_SavedViewLoadingStateCopyWithImpl<$Res> __$$_SavedViewLoadingStateCopyWithImpl(_$_SavedViewLoadingState _value, $Res Function(_$_SavedViewLoadingState) _then) : super(_value, _then); - - @pragma('vm:prefer-inline') - @override - $Res call({ - Object? correspondents = null, - Object? documentTypes = null, - Object? tags = null, - Object? storagePaths = null, - }) { - return _then(_$_SavedViewLoadingState( - correspondents: null == correspondents - ? _value._correspondents - : correspondents // ignore: cast_nullable_to_non_nullable - as Map, - documentTypes: null == documentTypes - ? _value._documentTypes - : documentTypes // ignore: cast_nullable_to_non_nullable - as Map, - tags: null == tags - ? _value._tags - : tags // ignore: cast_nullable_to_non_nullable - as Map, - storagePaths: null == storagePaths - ? _value._storagePaths - : storagePaths // ignore: cast_nullable_to_non_nullable - as Map, - )); - } } /// @nodoc class _$_SavedViewLoadingState implements _SavedViewLoadingState { - const _$_SavedViewLoadingState( - {required final Map correspondents, - required final Map documentTypes, - required final Map tags, - required final Map storagePaths}) - : _correspondents = correspondents, - _documentTypes = documentTypes, - _tags = tags, - _storagePaths = storagePaths; - - final Map _correspondents; - @override - Map get correspondents { - if (_correspondents is EqualUnmodifiableMapView) return _correspondents; - // ignore: implicit_dynamic_type - return EqualUnmodifiableMapView(_correspondents); - } - - final Map _documentTypes; - @override - Map get documentTypes { - if (_documentTypes is EqualUnmodifiableMapView) return _documentTypes; - // ignore: implicit_dynamic_type - return EqualUnmodifiableMapView(_documentTypes); - } - - final Map _tags; - @override - Map get tags { - if (_tags is EqualUnmodifiableMapView) return _tags; - // ignore: implicit_dynamic_type - return EqualUnmodifiableMapView(_tags); - } - - final Map _storagePaths; - @override - Map get storagePaths { - if (_storagePaths is EqualUnmodifiableMapView) return _storagePaths; - // ignore: implicit_dynamic_type - return EqualUnmodifiableMapView(_storagePaths); - } + const _$_SavedViewLoadingState(); @override String toString() { - return 'SavedViewState.loading(correspondents: $correspondents, documentTypes: $documentTypes, tags: $tags, storagePaths: $storagePaths)'; + return 'SavedViewState.loading()'; } @override bool operator ==(dynamic other) { return identical(this, other) || - (other.runtimeType == runtimeType && - other is _$_SavedViewLoadingState && - const DeepCollectionEquality() - .equals(other._correspondents, _correspondents) && - const DeepCollectionEquality() - .equals(other._documentTypes, _documentTypes) && - const DeepCollectionEquality().equals(other._tags, _tags) && - const DeepCollectionEquality() - .equals(other._storagePaths, _storagePaths)); + (other.runtimeType == runtimeType && other is _$_SavedViewLoadingState); } @override - int get hashCode => Object.hash( - runtimeType, - const DeepCollectionEquality().hash(_correspondents), - const DeepCollectionEquality().hash(_documentTypes), - const DeepCollectionEquality().hash(_tags), - const DeepCollectionEquality().hash(_storagePaths)); - - @JsonKey(ignore: true) - @override - @pragma('vm:prefer-inline') - _$$_SavedViewLoadingStateCopyWith<_$_SavedViewLoadingState> get copyWith => - __$$_SavedViewLoadingStateCopyWithImpl<_$_SavedViewLoadingState>( - this, _$identity); + int get hashCode => runtimeType.hashCode; @override @optionalTypeArgs TResult when({ - required TResult Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths) - initial, - required TResult Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths) - loading, - required TResult Function( - Map savedViews, - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths) - loaded, - required TResult Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths) - error, + required TResult Function() initial, + required TResult Function() loading, + required TResult Function(Map savedViews) loaded, + required TResult Function() error, }) { - return loading(correspondents, documentTypes, tags, storagePaths); + return loading(); } @override @optionalTypeArgs TResult? whenOrNull({ - TResult? Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths)? - initial, - TResult? Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths)? - loading, - TResult? Function( - Map savedViews, - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths)? - loaded, - TResult? Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths)? - error, + TResult? Function()? initial, + TResult? Function()? loading, + TResult? Function(Map savedViews)? loaded, + TResult? Function()? error, }) { - return loading?.call(correspondents, documentTypes, tags, storagePaths); + return loading?.call(); } @override @optionalTypeArgs TResult maybeWhen({ - TResult Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths)? - initial, - TResult Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths)? - loading, - TResult Function( - Map savedViews, - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths)? - loaded, - TResult Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths)? - error, + TResult Function()? initial, + TResult Function()? loading, + TResult Function(Map savedViews)? loaded, + TResult Function()? error, required TResult orElse(), }) { if (loading != null) { - return loading(correspondents, documentTypes, tags, storagePaths); + return loading(); } return orElse(); } @@ -754,41 +311,16 @@ class _$_SavedViewLoadingState implements _SavedViewLoadingState { } abstract class _SavedViewLoadingState implements SavedViewState { - const factory _SavedViewLoadingState( - {required final Map correspondents, - required final Map documentTypes, - required final Map tags, - required final Map storagePaths}) = - _$_SavedViewLoadingState; - - @override - Map get correspondents; - @override - Map get documentTypes; - @override - Map get tags; - @override - Map get storagePaths; - @override - @JsonKey(ignore: true) - _$$_SavedViewLoadingStateCopyWith<_$_SavedViewLoadingState> get copyWith => - throw _privateConstructorUsedError; + const factory _SavedViewLoadingState() = _$_SavedViewLoadingState; } /// @nodoc -abstract class _$$_SavedViewLoadedStateCopyWith<$Res> - implements $SavedViewStateCopyWith<$Res> { +abstract class _$$_SavedViewLoadedStateCopyWith<$Res> { factory _$$_SavedViewLoadedStateCopyWith(_$_SavedViewLoadedState value, $Res Function(_$_SavedViewLoadedState) then) = __$$_SavedViewLoadedStateCopyWithImpl<$Res>; - @override @useResult - $Res call( - {Map savedViews, - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths}); + $Res call({Map savedViews}); } /// @nodoc @@ -803,32 +335,12 @@ class __$$_SavedViewLoadedStateCopyWithImpl<$Res> @override $Res call({ Object? savedViews = null, - Object? correspondents = null, - Object? documentTypes = null, - Object? tags = null, - Object? storagePaths = null, }) { return _then(_$_SavedViewLoadedState( savedViews: null == savedViews ? _value._savedViews : savedViews // ignore: cast_nullable_to_non_nullable as Map, - correspondents: null == correspondents - ? _value._correspondents - : correspondents // ignore: cast_nullable_to_non_nullable - as Map, - documentTypes: null == documentTypes - ? _value._documentTypes - : documentTypes // ignore: cast_nullable_to_non_nullable - as Map, - tags: null == tags - ? _value._tags - : tags // ignore: cast_nullable_to_non_nullable - as Map, - storagePaths: null == storagePaths - ? _value._storagePaths - : storagePaths // ignore: cast_nullable_to_non_nullable - as Map, )); } } @@ -836,17 +348,8 @@ class __$$_SavedViewLoadedStateCopyWithImpl<$Res> /// @nodoc class _$_SavedViewLoadedState implements _SavedViewLoadedState { - const _$_SavedViewLoadedState( - {required final Map savedViews, - required final Map correspondents, - required final Map documentTypes, - required final Map tags, - required final Map storagePaths}) - : _savedViews = savedViews, - _correspondents = correspondents, - _documentTypes = documentTypes, - _tags = tags, - _storagePaths = storagePaths; + const _$_SavedViewLoadedState({required final Map savedViews}) + : _savedViews = savedViews; final Map _savedViews; @override @@ -856,41 +359,9 @@ class _$_SavedViewLoadedState implements _SavedViewLoadedState { return EqualUnmodifiableMapView(_savedViews); } - final Map _correspondents; - @override - Map get correspondents { - if (_correspondents is EqualUnmodifiableMapView) return _correspondents; - // ignore: implicit_dynamic_type - return EqualUnmodifiableMapView(_correspondents); - } - - final Map _documentTypes; - @override - Map get documentTypes { - if (_documentTypes is EqualUnmodifiableMapView) return _documentTypes; - // ignore: implicit_dynamic_type - return EqualUnmodifiableMapView(_documentTypes); - } - - final Map _tags; - @override - Map get tags { - if (_tags is EqualUnmodifiableMapView) return _tags; - // ignore: implicit_dynamic_type - return EqualUnmodifiableMapView(_tags); - } - - final Map _storagePaths; - @override - Map get storagePaths { - if (_storagePaths is EqualUnmodifiableMapView) return _storagePaths; - // ignore: implicit_dynamic_type - return EqualUnmodifiableMapView(_storagePaths); - } - @override String toString() { - return 'SavedViewState.loaded(savedViews: $savedViews, correspondents: $correspondents, documentTypes: $documentTypes, tags: $tags, storagePaths: $storagePaths)'; + return 'SavedViewState.loaded(savedViews: $savedViews)'; } @override @@ -899,24 +370,12 @@ class _$_SavedViewLoadedState implements _SavedViewLoadedState { (other.runtimeType == runtimeType && other is _$_SavedViewLoadedState && const DeepCollectionEquality() - .equals(other._savedViews, _savedViews) && - const DeepCollectionEquality() - .equals(other._correspondents, _correspondents) && - const DeepCollectionEquality() - .equals(other._documentTypes, _documentTypes) && - const DeepCollectionEquality().equals(other._tags, _tags) && - const DeepCollectionEquality() - .equals(other._storagePaths, _storagePaths)); + .equals(other._savedViews, _savedViews)); } @override int get hashCode => Object.hash( - runtimeType, - const DeepCollectionEquality().hash(_savedViews), - const DeepCollectionEquality().hash(_correspondents), - const DeepCollectionEquality().hash(_documentTypes), - const DeepCollectionEquality().hash(_tags), - const DeepCollectionEquality().hash(_storagePaths)); + runtimeType, const DeepCollectionEquality().hash(_savedViews)); @JsonKey(ignore: true) @override @@ -928,102 +387,36 @@ class _$_SavedViewLoadedState implements _SavedViewLoadedState { @override @optionalTypeArgs TResult when({ - required TResult Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths) - initial, - required TResult Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths) - loading, - required TResult Function( - Map savedViews, - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths) - loaded, - required TResult Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths) - error, + required TResult Function() initial, + required TResult Function() loading, + required TResult Function(Map savedViews) loaded, + required TResult Function() error, }) { - return loaded( - savedViews, correspondents, documentTypes, tags, storagePaths); + return loaded(savedViews); } @override @optionalTypeArgs TResult? whenOrNull({ - TResult? Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths)? - initial, - TResult? Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths)? - loading, - TResult? Function( - Map savedViews, - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths)? - loaded, - TResult? Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths)? - error, + TResult? Function()? initial, + TResult? Function()? loading, + TResult? Function(Map savedViews)? loaded, + TResult? Function()? error, }) { - return loaded?.call( - savedViews, correspondents, documentTypes, tags, storagePaths); + return loaded?.call(savedViews); } @override @optionalTypeArgs TResult maybeWhen({ - TResult Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths)? - initial, - TResult Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths)? - loading, - TResult Function( - Map savedViews, - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths)? - loaded, - TResult Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths)? - error, + TResult Function()? initial, + TResult Function()? loading, + TResult Function(Map savedViews)? loaded, + TResult Function()? error, required TResult orElse(), }) { if (loaded != null) { - return loaded( - savedViews, correspondents, documentTypes, tags, storagePaths); + return loaded(savedViews); } return orElse(); } @@ -1068,41 +461,20 @@ class _$_SavedViewLoadedState implements _SavedViewLoadedState { abstract class _SavedViewLoadedState implements SavedViewState { const factory _SavedViewLoadedState( - {required final Map savedViews, - required final Map correspondents, - required final Map documentTypes, - required final Map tags, - required final Map storagePaths}) = + {required final Map savedViews}) = _$_SavedViewLoadedState; Map get savedViews; - @override - Map get correspondents; - @override - Map get documentTypes; - @override - Map get tags; - @override - Map get storagePaths; - @override @JsonKey(ignore: true) _$$_SavedViewLoadedStateCopyWith<_$_SavedViewLoadedState> get copyWith => throw _privateConstructorUsedError; } /// @nodoc -abstract class _$$_SavedViewErrorStateCopyWith<$Res> - implements $SavedViewStateCopyWith<$Res> { +abstract class _$$_SavedViewErrorStateCopyWith<$Res> { factory _$$_SavedViewErrorStateCopyWith(_$_SavedViewErrorState value, $Res Function(_$_SavedViewErrorState) then) = __$$_SavedViewErrorStateCopyWithImpl<$Res>; - @override - @useResult - $Res call( - {Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths}); } /// @nodoc @@ -1112,211 +484,60 @@ class __$$_SavedViewErrorStateCopyWithImpl<$Res> __$$_SavedViewErrorStateCopyWithImpl(_$_SavedViewErrorState _value, $Res Function(_$_SavedViewErrorState) _then) : super(_value, _then); - - @pragma('vm:prefer-inline') - @override - $Res call({ - Object? correspondents = null, - Object? documentTypes = null, - Object? tags = null, - Object? storagePaths = null, - }) { - return _then(_$_SavedViewErrorState( - correspondents: null == correspondents - ? _value._correspondents - : correspondents // ignore: cast_nullable_to_non_nullable - as Map, - documentTypes: null == documentTypes - ? _value._documentTypes - : documentTypes // ignore: cast_nullable_to_non_nullable - as Map, - tags: null == tags - ? _value._tags - : tags // ignore: cast_nullable_to_non_nullable - as Map, - storagePaths: null == storagePaths - ? _value._storagePaths - : storagePaths // ignore: cast_nullable_to_non_nullable - as Map, - )); - } } /// @nodoc class _$_SavedViewErrorState implements _SavedViewErrorState { - const _$_SavedViewErrorState( - {required final Map correspondents, - required final Map documentTypes, - required final Map tags, - required final Map storagePaths}) - : _correspondents = correspondents, - _documentTypes = documentTypes, - _tags = tags, - _storagePaths = storagePaths; - - final Map _correspondents; - @override - Map get correspondents { - if (_correspondents is EqualUnmodifiableMapView) return _correspondents; - // ignore: implicit_dynamic_type - return EqualUnmodifiableMapView(_correspondents); - } - - final Map _documentTypes; - @override - Map get documentTypes { - if (_documentTypes is EqualUnmodifiableMapView) return _documentTypes; - // ignore: implicit_dynamic_type - return EqualUnmodifiableMapView(_documentTypes); - } - - final Map _tags; - @override - Map get tags { - if (_tags is EqualUnmodifiableMapView) return _tags; - // ignore: implicit_dynamic_type - return EqualUnmodifiableMapView(_tags); - } - - final Map _storagePaths; - @override - Map get storagePaths { - if (_storagePaths is EqualUnmodifiableMapView) return _storagePaths; - // ignore: implicit_dynamic_type - return EqualUnmodifiableMapView(_storagePaths); - } + const _$_SavedViewErrorState(); @override String toString() { - return 'SavedViewState.error(correspondents: $correspondents, documentTypes: $documentTypes, tags: $tags, storagePaths: $storagePaths)'; + return 'SavedViewState.error()'; } @override bool operator ==(dynamic other) { return identical(this, other) || - (other.runtimeType == runtimeType && - other is _$_SavedViewErrorState && - const DeepCollectionEquality() - .equals(other._correspondents, _correspondents) && - const DeepCollectionEquality() - .equals(other._documentTypes, _documentTypes) && - const DeepCollectionEquality().equals(other._tags, _tags) && - const DeepCollectionEquality() - .equals(other._storagePaths, _storagePaths)); + (other.runtimeType == runtimeType && other is _$_SavedViewErrorState); } @override - int get hashCode => Object.hash( - runtimeType, - const DeepCollectionEquality().hash(_correspondents), - const DeepCollectionEquality().hash(_documentTypes), - const DeepCollectionEquality().hash(_tags), - const DeepCollectionEquality().hash(_storagePaths)); - - @JsonKey(ignore: true) - @override - @pragma('vm:prefer-inline') - _$$_SavedViewErrorStateCopyWith<_$_SavedViewErrorState> get copyWith => - __$$_SavedViewErrorStateCopyWithImpl<_$_SavedViewErrorState>( - this, _$identity); + int get hashCode => runtimeType.hashCode; @override @optionalTypeArgs TResult when({ - required TResult Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths) - initial, - required TResult Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths) - loading, - required TResult Function( - Map savedViews, - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths) - loaded, - required TResult Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths) - error, + required TResult Function() initial, + required TResult Function() loading, + required TResult Function(Map savedViews) loaded, + required TResult Function() error, }) { - return error(correspondents, documentTypes, tags, storagePaths); + return error(); } @override @optionalTypeArgs TResult? whenOrNull({ - TResult? Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths)? - initial, - TResult? Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths)? - loading, - TResult? Function( - Map savedViews, - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths)? - loaded, - TResult? Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths)? - error, + TResult? Function()? initial, + TResult? Function()? loading, + TResult? Function(Map savedViews)? loaded, + TResult? Function()? error, }) { - return error?.call(correspondents, documentTypes, tags, storagePaths); + return error?.call(); } @override @optionalTypeArgs TResult maybeWhen({ - TResult Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths)? - initial, - TResult Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths)? - loading, - TResult Function( - Map savedViews, - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths)? - loaded, - TResult Function( - Map correspondents, - Map documentTypes, - Map tags, - Map storagePaths)? - error, + TResult Function()? initial, + TResult Function()? loading, + TResult Function(Map savedViews)? loaded, + TResult Function()? error, required TResult orElse(), }) { if (error != null) { - return error(correspondents, documentTypes, tags, storagePaths); + return error(); } return orElse(); } @@ -1360,23 +581,5 @@ class _$_SavedViewErrorState implements _SavedViewErrorState { } abstract class _SavedViewErrorState implements SavedViewState { - const factory _SavedViewErrorState( - {required final Map correspondents, - required final Map documentTypes, - required final Map tags, - required final Map storagePaths}) = - _$_SavedViewErrorState; - - @override - Map get correspondents; - @override - Map get documentTypes; - @override - Map get tags; - @override - Map get storagePaths; - @override - @JsonKey(ignore: true) - _$$_SavedViewErrorStateCopyWith<_$_SavedViewErrorState> get copyWith => - throw _privateConstructorUsedError; + const factory _SavedViewErrorState() = _$_SavedViewErrorState; } diff --git a/lib/features/saved_view/cubit/saved_view_state.dart b/lib/features/saved_view/cubit/saved_view_state.dart index b886840..c73f123 100644 --- a/lib/features/saved_view/cubit/saved_view_state.dart +++ b/lib/features/saved_view/cubit/saved_view_state.dart @@ -2,32 +2,12 @@ part of 'saved_view_cubit.dart'; @freezed class SavedViewState with _$SavedViewState { - const factory SavedViewState.initial({ - required Map correspondents, - required Map documentTypes, - required Map tags, - required Map storagePaths, - }) = _SavedViewIntialState; + const factory SavedViewState.initial() = _SavedViewIntialState; - const factory SavedViewState.loading({ - required Map correspondents, - required Map documentTypes, - required Map tags, - required Map storagePaths, - }) = _SavedViewLoadingState; + const factory SavedViewState.loading() = _SavedViewLoadingState; - const factory SavedViewState.loaded({ - required Map savedViews, - required Map correspondents, - required Map documentTypes, - required Map tags, - required Map storagePaths, - }) = _SavedViewLoadedState; + const factory SavedViewState.loaded({required Map savedViews}) = + _SavedViewLoadedState; - const factory SavedViewState.error({ - required Map correspondents, - required Map documentTypes, - required Map tags, - required Map storagePaths, - }) = _SavedViewErrorState; + const factory SavedViewState.error() = _SavedViewErrorState; } diff --git a/lib/features/saved_view/view/saved_view_list.dart b/lib/features/saved_view/view/saved_view_list.dart index 29b263f..5f6ac15 100644 --- a/lib/features/saved_view/view/saved_view_list.dart +++ b/lib/features/saved_view/view/saved_view_list.dart @@ -5,6 +5,7 @@ import 'package:paperless_mobile/core/bloc/connectivity_cubit.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_app_state.dart'; +import 'package:paperless_mobile/core/navigation/push_routes.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_details/cubit/saved_view_details_cubit.dart'; @@ -21,17 +22,13 @@ class SavedViewList extends StatelessWidget { return BlocBuilder( builder: (context, state) { return state.when( - initial: (correspondents, documentTypes, tags, storagePaths) => Container(), - loading: (correspondents, documentTypes, tags, storagePaths) => Center( - child: Text("Saved views loading..."), //TODO: INTL + initial: () => SliverToBoxAdapter(child: Container()), + loading: () => SliverToBoxAdapter( + child: Center( + child: Text("Saved views loading..."), //TODO: INTL + ), ), - loaded: ( - savedViews, - correspondents, - documentTypes, - tags, - storagePaths, - ) { + loaded: (savedViews) { if (savedViews.isEmpty) { return SliverToBoxAdapter( child: HintCard( @@ -50,30 +47,7 @@ class SavedViewList extends StatelessWidget { S.of(context)!.nFiltersSet(view.filterRules.length), ), onTap: () { - Navigator.of(context).push( - MaterialPageRoute( - builder: (ctxt) => MultiBlocProvider( - providers: [ - BlocProvider( - create: (context) => SavedViewDetailsCubit( - ctxt.read(), - ctxt.read(), - context.read(), - Hive.box(HiveBoxes.localUserAppState).get( - Hive.box(HiveBoxes.globalSettings) - .getValue()! - .currentLoggedInUser!, - )!, - savedView: view, - ), - ), - ], - child: SavedViewDetailsPage( - onDelete: context.read().remove, - ), - ), - ), - ); + pushSavedViewDetailsRoute(context, savedView: view); }, ); }, @@ -81,13 +55,7 @@ class SavedViewList extends StatelessWidget { ), ); }, - error: ( - correspondents, - documentTypes, - tags, - storagePaths, - ) => - Center( + error: () => Center( child: Text( "An error occurred while trying to load the saved views.", ), diff --git a/lib/features/saved_view_details/view/saved_view_details_page.dart b/lib/features/saved_view_details/view/saved_view_details_page.dart index 7bc08d9..234d21f 100644 --- a/lib/features/saved_view_details/view/saved_view_details_page.dart +++ b/lib/features/saved_view_details/view/saved_view_details_page.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:paperless_api/paperless_api.dart'; import 'package:paperless_mobile/core/bloc/connectivity_cubit.dart'; +import 'package:paperless_mobile/core/navigation/push_routes.dart'; import 'package:paperless_mobile/features/documents/view/widgets/adaptive_documents_view.dart'; import 'package:paperless_mobile/features/documents/view/widgets/documents_empty_state.dart'; import 'package:paperless_mobile/features/documents/view/widgets/selection/confirm_delete_saved_view_dialog.dart'; @@ -76,14 +77,10 @@ class _SavedViewDetailsPageState extends State isLoading: state.isLoading, hasLoaded: state.hasLoaded, onTap: (document) { - Navigator.push( + pushDocumentDetailsRoute( context, - MaterialPageRoute( - builder: (context) => DocumentDetailsRoute( - document: document, - isLabelClickable: false, - ), - ), + document: document, + isLabelClickable: false, ); }, viewType: state.viewType, diff --git a/lib/features/settings/view/manage_accounts_page.dart b/lib/features/settings/view/manage_accounts_page.dart index 55b8a95..edec819 100644 --- a/lib/features/settings/view/manage_accounts_page.dart +++ b/lib/features/settings/view/manage_accounts_page.dart @@ -5,6 +5,7 @@ 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/features/home/view/model/api_version.dart'; import 'package:paperless_mobile/features/login/cubit/authentication_cubit.dart'; import 'package:paperless_mobile/features/login/model/login_form_credentials.dart'; import 'package:paperless_mobile/features/login/view/login_page.dart'; @@ -13,6 +14,7 @@ import 'package:paperless_mobile/features/settings/view/pages/switching_accounts import 'package:paperless_mobile/features/settings/view/widgets/global_settings_builder.dart'; import 'package:paperless_mobile/features/settings/view/widgets/user_avatar.dart'; import 'package:paperless_mobile/generated/l10n/app_localizations.dart'; +import 'package:provider/provider.dart'; class ManageAccountsPage extends StatelessWidget { const ManageAccountsPage({super.key}); @@ -67,6 +69,17 @@ class ManageAccountsPage extends StatelessWidget { _onAddAccount(context, globalSettings.currentLoggedInUser!); }, ), + Consumer( + builder: (context, value, child) { + if (value.version >= 3) { + return const ListTile( + leading: Icon(Icons.admin_panel_settings), + title: Text("Manage permissions"), //TODO : INTL + ); + } + return const SizedBox.shrink(); + }, + ) ], ); }, diff --git a/lib/features/settings/view/settings_page.dart b/lib/features/settings/view/settings_page.dart index d3614fd..a7d9f9b 100644 --- a/lib/features/settings/view/settings_page.dart +++ b/lib/features/settings/view/settings_page.dart @@ -1,7 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:paperless_mobile/core/bloc/server_information_cubit.dart'; -import 'package:paperless_mobile/core/bloc/server_information_state.dart'; +import 'package:paperless_api/paperless_api.dart'; import 'package:paperless_mobile/features/settings/view/pages/application_settings_page.dart'; import 'package:paperless_mobile/features/settings/view/pages/security_settings_page.dart'; import 'package:paperless_mobile/features/settings/view/widgets/user_settings_builder.dart'; @@ -26,13 +24,21 @@ class SettingsPage extends StatelessWidget { style: Theme.of(context).textTheme.labelSmall, textAlign: TextAlign.center, ), - subtitle: BlocBuilder( - builder: (context, state) { + subtitle: FutureBuilder( + builder: (context, snapshot) { + if (!snapshot.hasData) { + return Text( + "Loading server information...", + style: Theme.of(context).textTheme.labelSmall, + textAlign: TextAlign.center, + ); + } + final serverData = snapshot.data!; return Text( S.of(context)!.paperlessServerVersion + ' ' + - state.information!.version.toString() + - ' (API v${state.information!.apiVersion})', + serverData.version.toString() + + ' (API v${serverData.apiVersion})', style: Theme.of(context).textTheme.labelSmall, textAlign: TextAlign.center, ); diff --git a/lib/features/similar_documents/view/similar_documents_view.dart b/lib/features/similar_documents/view/similar_documents_view.dart index 3b9352f..a12a466 100644 --- a/lib/features/similar_documents/view/similar_documents_view.dart +++ b/lib/features/similar_documents/view/similar_documents_view.dart @@ -2,14 +2,13 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:paperless_api/paperless_api.dart'; import 'package:paperless_mobile/core/bloc/connectivity_cubit.dart'; +import 'package:paperless_mobile/core/navigation/push_routes.dart'; import 'package:paperless_mobile/core/widgets/offline_widget.dart'; import 'package:paperless_mobile/features/documents/view/widgets/adaptive_documents_view.dart'; -import 'package:paperless_mobile/features/documents/view/widgets/documents_empty_state.dart'; import 'package:paperless_mobile/features/paged_document_view/view/document_paging_view_mixin.dart'; import 'package:paperless_mobile/features/similar_documents/cubit/similar_documents_cubit.dart'; import 'package:paperless_mobile/generated/l10n/app_localizations.dart'; import 'package:paperless_mobile/helpers/message_helpers.dart'; -import 'package:paperless_mobile/routes/document_details_route.dart'; class SimilarDocumentsView extends StatefulWidget { final ScrollController pagingScrollController; diff --git a/lib/main.dart b/lib/main.dart index 792b4b1..eea1556 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -41,7 +41,6 @@ import 'package:paperless_mobile/features/settings/view/widgets/global_settings_ import 'package:paperless_mobile/features/sharing/share_intent_queue.dart'; import 'package:paperless_mobile/generated/l10n/app_localizations.dart'; import 'package:paperless_mobile/helpers/message_helpers.dart'; -import 'package:paperless_mobile/routes/document_details_route.dart'; import 'package:paperless_mobile/theme.dart'; import 'package:path_provider/path_provider.dart'; import 'package:provider/provider.dart'; @@ -122,7 +121,6 @@ void main() async { }); final apiFactory = PaperlessApiFactoryImpl(sessionManager); - runApp( MultiProvider( providers: [ @@ -220,10 +218,9 @@ class _AuthenticationWrapperState extends State { @override void didChangeDependencies() { super.didChangeDependencies(); - context - .read() - .restoreSessionState() - .then((value) => FlutterNativeSplash.remove()); + context.read().restoreSessionState().then((value) { + FlutterNativeSplash.remove(); + }); } @override diff --git a/lib/routes/document_details_route.dart b/lib/routes/document_details_route.dart index c2e1afa..a90001e 100644 --- a/lib/routes/document_details_route.dart +++ b/lib/routes/document_details_route.dart @@ -1,26 +1,19 @@ import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_cache_manager/flutter_cache_manager.dart'; import 'package:paperless_api/paperless_api.dart'; -import 'package:paperless_mobile/core/notifier/document_changed_notifier.dart'; -import 'package:paperless_mobile/core/repository/label_repository.dart'; import 'package:paperless_mobile/features/document_details/cubit/document_details_cubit.dart'; import 'package:paperless_mobile/features/document_details/view/pages/document_details_page.dart'; -import 'package:paperless_mobile/features/notifications/services/local_notification_service.dart'; -import 'package:provider/provider.dart'; class DocumentDetailsRoute extends StatelessWidget { final DocumentModel document; final bool isLabelClickable; - final bool allowEdit; final String? titleAndContentQueryString; const DocumentDetailsRoute({ super.key, required this.document, this.isLabelClickable = true, - this.allowEdit = true, this.titleAndContentQueryString, }); @@ -36,7 +29,6 @@ class DocumentDetailsRoute extends StatelessWidget { ), lazy: false, child: DocumentDetailsPage( - allowEdit: allowEdit, isLabelClickable: isLabelClickable, titleAndContentQueryString: titleAndContentQueryString, ), @@ -57,33 +49,3 @@ class DocumentDetailsRouteArguments { this.titleAndContentQueryString, }); } - -Future pushDocumentDetailsRoute( - BuildContext context, { - required DocumentModel document, - bool isLabelClickable = true, - bool allowEdit = true, - String? titleAndContentQueryString, -}) { - final LabelRepository labelRepository = context.read(); - final DocumentChangedNotifier changeNotifier = context.read(); - final PaperlessDocumentsApi documentsApi = context.read(); - final LocalNotificationService notificationservice = context.read(); - final CacheManager cacheManager = context.read(); - return Navigator.of(context).push(MaterialPageRoute( - builder: (_) => MultiProvider( - providers: [ - Provider.value(value: documentsApi), - Provider.value(value: labelRepository), - Provider.value(value: changeNotifier), - Provider.value(value: notificationservice), - Provider.value(value: cacheManager), - ], - child: DocumentDetailsRoute( - document: document, - allowEdit: allowEdit, - isLabelClickable: isLabelClickable, - ), - ), - )); -} diff --git a/packages/paperless_api/lib/src/models/paperless_server_exception.dart b/packages/paperless_api/lib/src/models/paperless_server_exception.dart index 10ada4d..3d180de 100644 --- a/packages/paperless_api/lib/src/models/paperless_server_exception.dart +++ b/packages/paperless_api/lib/src/models/paperless_server_exception.dart @@ -53,5 +53,6 @@ enum ErrorCode { requestTimedOut, unsupportedFileFormat, missingClientCertificate, - acknowledgeTasksError; + acknowledgeTasksError, + notAuthorized; } diff --git a/packages/paperless_api/lib/src/models/paperless_server_information_model.dart b/packages/paperless_api/lib/src/models/paperless_server_information_model.dart index 16eb623..73bb983 100644 --- a/packages/paperless_api/lib/src/models/paperless_server_information_model.dart +++ b/packages/paperless_api/lib/src/models/paperless_server_information_model.dart @@ -3,25 +3,17 @@ import 'package:paperless_api/src/request_utils.dart'; class PaperlessServerInformationModel { static const String versionHeader = 'x-version'; static const String apiVersionHeader = 'x-api-version'; - static const String hostHeader = 'x-served-by'; - final String? version; - final int? apiVersion; - final String? username; - final String? host; - - String? get userInitials { - return username?.substring(0, 1).toUpperCase(); - } + final String version; + final int apiVersion; + final bool isUpdateAvailable; PaperlessServerInformationModel({ - this.host, - this.username, - this.version = 'unknown', - this.apiVersion = 1, + required this.version, + required this.apiVersion, + required this.isUpdateAvailable, }); - int compareToOtherVersion(String? other) { - return getExtendedVersionNumber(version ?? '0.0.0') - .compareTo(getExtendedVersionNumber(other ?? '0.0.0')); + int compareToOtherVersion(String other) { + return getExtendedVersionNumber(version).compareTo(getExtendedVersionNumber(other)); } } diff --git a/packages/paperless_api/lib/src/models/permissions/inherited_permissions.dart b/packages/paperless_api/lib/src/models/permissions/inherited_permissions.dart index 9336562..dc8a272 100644 --- a/packages/paperless_api/lib/src/models/permissions/inherited_permissions.dart +++ b/packages/paperless_api/lib/src/models/permissions/inherited_permissions.dart @@ -130,7 +130,9 @@ enum InheritedPermissions { @HiveField(60) documentsChangeSavedviewfilterrule("documents.change_savedviewfilterrule"), @HiveField(61) - documentsChangeStoragepathdocuments("documents.change_storagepathdocuments.change_tag"), + documentsChangeStoragepath("documents.change_storagepath"), + @HiveField(111) + documentsChangeTag("documents.change_tag"), @HiveField(62) documentsChangeUisettings("documents.change_uisettings"), @HiveField(63) diff --git a/packages/paperless_api/lib/src/models/user_model.dart b/packages/paperless_api/lib/src/models/user_model.dart index 53d9038..acfba27 100644 --- a/packages/paperless_api/lib/src/models/user_model.dart +++ b/packages/paperless_api/lib/src/models/user_model.dart @@ -64,7 +64,7 @@ class UserModel with _$UserModel { return value.userPermissions.contains(permission); }, v2: (value) { - // In previous versions, all users have access to all + // In previous versions, all users have all permissions. return true; }, ); diff --git a/packages/paperless_api/lib/src/modules/documents_api/paperless_documents_api_impl.dart b/packages/paperless_api/lib/src/modules/documents_api/paperless_documents_api_impl.dart index e2845c7..1b1fe42 100644 --- a/packages/paperless_api/lib/src/modules/documents_api/paperless_documents_api_impl.dart +++ b/packages/paperless_api/lib/src/modules/documents_api/paperless_documents_api_impl.dart @@ -78,7 +78,6 @@ class PaperlessDocumentsApiImpl implements PaperlessDocumentsApi { throw const PaperlessServerException(ErrorCode.documentUpdateFailed); } } on DioError catch (err) { - //TODO: Handle 403 permission errors for 1.14.0 throw err.error!; } } diff --git a/packages/paperless_api/lib/src/modules/server_stats_api/paperless_server_stats_api_impl.dart b/packages/paperless_api/lib/src/modules/server_stats_api/paperless_server_stats_api_impl.dart index 92e033b..e9c4ff5 100644 --- a/packages/paperless_api/lib/src/modules/server_stats_api/paperless_server_stats_api_impl.dart +++ b/packages/paperless_api/lib/src/modules/server_stats_api/paperless_server_stats_api_impl.dart @@ -22,16 +22,13 @@ class PaperlessServerStatsApiImpl implements PaperlessServerStatsApi { if (response.statusCode == 200) { final version = response.data["version"] as String; final updateAvailable = response.data["update_available"] as bool; + return PaperlessServerInformationModel( + apiVersion: int.parse(response.headers.value('x-api-version')!), + version: version, + isUpdateAvailable: updateAvailable, + ); } - throw PaperlessServerException.unknown(); - final version = - response.headers[PaperlessServerInformationModel.versionHeader]?.first ?? 'unknown'; - final apiVersion = int.tryParse( - response.headers[PaperlessServerInformationModel.apiVersionHeader]?.first ?? '1'); - return PaperlessServerInformationModel( - version: version, - apiVersion: apiVersion, - ); + throw const PaperlessServerException.unknown(); } @override diff --git a/packages/paperless_api/lib/src/modules/user_api/paperless_user_api_v3_impl.dart b/packages/paperless_api/lib/src/modules/user_api/paperless_user_api_v3_impl.dart index 8e217c9..e0d2246 100644 --- a/packages/paperless_api/lib/src/modules/user_api/paperless_user_api_v3_impl.dart +++ b/packages/paperless_api/lib/src/modules/user_api/paperless_user_api_v3_impl.dart @@ -52,7 +52,7 @@ class PaperlessUserApiV3Impl implements PaperlessUserApi, PaperlessUserApiV3 { if (response.statusCode == 200) { return PagedSearchResult.fromJson( response.data, - UserModelV3.fromJson as UserModelV3 Function(Object?), + (json) => UserModelV3.fromJson(json as dynamic), ).results; } throw const PaperlessServerException.unknown();