import 'dart:typed_data'; 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/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/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_bulk_action/cubit/document_bulk_action_cubit.dart'; import 'package:paperless_mobile/features/document_bulk_action/view/widgets/fullscreen_bulk_edit_label_page.dart'; import 'package:paperless_mobile/features/document_bulk_action/view/widgets/fullscreen_bulk_edit_tags_widget.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/document_upload/cubit/document_upload_cubit.dart'; import 'package:paperless_mobile/features/document_upload/view/document_upload_preparation_page.dart'; import 'package:paperless_mobile/features/home/view/model/api_version.dart'; import 'package:paperless_mobile/features/linked_documents/cubit/linked_documents_cubit.dart'; import 'package:paperless_mobile/features/linked_documents/view/linked_documents_page.dart'; import 'package:paperless_mobile/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/view/add_saved_view_page.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/generated/l10n/app_localizations.dart'; import 'package:paperless_mobile/routes/document_details_route.dart'; import 'package:provider/provider.dart'; // These are convenience methods for nativating to views without having to pass providers around explicitly. // Providers unfortunately have to be passed to the routes since they are children of the Navigator, not ancestors. Future pushDocumentSearchPage(BuildContext context) { final currentUser = Hive.box(HiveBoxes.globalSettings).getValue()!.currentLoggedInUser; final userRepo = context.read(); 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: userRepo), ], 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()), 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, }) { final apiVersion = context.read(); return Navigator.of(context).push( MaterialPageRoute( builder: (_) => MultiProvider( providers: [ Provider.value(value: apiVersion), if (apiVersion.hasMultiUserSupport) 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()), ], builder: (_, child) { return BlocProvider( create: (context) => SavedViewDetailsCubit( context.read(), context.read(), context.read(), LocalUserAppState.current, savedView: savedView, ), child: SavedViewDetailsPage(onDelete: context.read().remove), ); }, ), ), ); } Future pushAddSavedViewRoute(BuildContext context, {required DocumentFilter filter}) { return Navigator.of(context).push( MaterialPageRoute( builder: (_) => AddSavedViewPage( currentFilter: filter, correspondents: context.read().state.correspondents, documentTypes: context.read().state.documentTypes, storagePaths: context.read().state.storagePaths, tags: context.read().state.tags, ), ), ); } Future pushLinkedDocumentsView(BuildContext context, {required DocumentFilter filter}) { return Navigator.push( context, 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()), Provider.value(value: context.read()), if (context.read().hasMultiUserSupport) Provider.value(value: context.read()), ], builder: (context, _) => BlocProvider( create: (context) => LinkedDocumentsCubit( filter, context.read(), context.read(), context.read(), ), child: const LinkedDocumentsPage(), ), ), ), ); } Future pushBulkEditCorrespondentRoute( BuildContext context, { required List selection, }) { return Navigator.of(context).push( MaterialPageRoute( builder: (_) => MultiProvider( providers: [ ..._getRequiredBulkEditProviders(context), ], builder: (_, __) => BlocProvider( create: (_) => DocumentBulkActionCubit( context.read(), context.read(), context.read(), selection: selection, ), child: BlocBuilder( builder: (context, state) { return FullscreenBulkEditLabelPage( options: state.correspondents, selection: state.selection, labelMapper: (document) => document.correspondent, leadingIcon: const Icon(Icons.person_outline), hintText: S.of(context)!.startTyping, onSubmit: context.read().bulkModifyCorrespondent, assignMessageBuilder: (int count, String name) { return S.of(context)!.bulkEditCorrespondentAssignMessage( name, count, ); }, removeMessageBuilder: (int count) { return S.of(context)!.bulkEditCorrespondentRemoveMessage(count); }, ); }, ), ), ), ), ); } Future pushBulkEditStoragePathRoute( BuildContext context, { required List selection, }) { return Navigator.of(context).push( MaterialPageRoute( builder: (_) => MultiProvider( providers: [ ..._getRequiredBulkEditProviders(context), ], builder: (_, __) => BlocProvider( create: (_) => DocumentBulkActionCubit( context.read(), context.read(), context.read(), selection: selection, ), child: BlocBuilder( builder: (context, state) { return FullscreenBulkEditLabelPage( options: state.storagePaths, selection: state.selection, labelMapper: (document) => document.storagePath, leadingIcon: const Icon(Icons.folder_outlined), hintText: S.of(context)!.startTyping, onSubmit: context.read().bulkModifyStoragePath, assignMessageBuilder: (int count, String name) { return S.of(context)!.bulkEditStoragePathAssignMessage( count, name, ); }, removeMessageBuilder: (int count) { return S.of(context)!.bulkEditStoragePathRemoveMessage(count); }, ); }, ), ), ), ), ); } Future pushBulkEditTagsRoute( BuildContext context, { required List selection, }) { return Navigator.of(context).push( MaterialPageRoute( builder: (_) => MultiProvider( providers: [ ..._getRequiredBulkEditProviders(context), ], builder: (_, __) => BlocProvider( create: (_) => DocumentBulkActionCubit( context.read(), context.read(), context.read(), selection: selection, ), child: Builder(builder: (context) { return const FullscreenBulkEditTagsWidget(); }), ), ), ), ); } Future pushBulkEditDocumentTypeRoute(BuildContext context, {required List selection}) { return Navigator.of(context).push( MaterialPageRoute( builder: (_) => MultiProvider( providers: [ ..._getRequiredBulkEditProviders(context), ], builder: (_, __) => BlocProvider( create: (_) => DocumentBulkActionCubit( context.read(), context.read(), context.read(), selection: selection, ), child: BlocBuilder( builder: (context, state) { return FullscreenBulkEditLabelPage( options: state.documentTypes, selection: state.selection, labelMapper: (document) => document.documentType, leadingIcon: const Icon(Icons.description_outlined), hintText: S.of(context)!.startTyping, onSubmit: context.read().bulkModifyDocumentType, assignMessageBuilder: (int count, String name) { return S.of(context)!.bulkEditDocumentTypeAssignMessage( count, name, ); }, removeMessageBuilder: (int count) { return S.of(context)!.bulkEditDocumentTypeRemoveMessage(count); }, ); }, ), ), ), ), ); } Future pushDocumentUploadPreparationPage( BuildContext context, { required Uint8List bytes, String? filename, String? fileExtension, String? title, }) { final labelRepo = context.read(); final docsApi = context.read(); return Navigator.of(context).push( MaterialPageRoute( builder: (_) => MultiProvider( providers: [ Provider.value(value: labelRepo), Provider.value(value: docsApi), ], builder: (_, child) => BlocProvider( create: (_) => DocumentUploadCubit( context.read(), context.read(), ), child: DocumentUploadPreparationPage( fileBytes: bytes, fileExtension: fileExtension, filename: filename, title: title, ), ), ), ), ); } List _getRequiredBulkEditProviders(BuildContext context) { return [ Provider.value(value: context.read()), Provider.value(value: context.read()), Provider.value(value: context.read()), ]; }