diff --git a/android/fastlane/metadata/android/en-US/changelogs/39.txt b/android/fastlane/metadata/android/en-US/changelogs/39.txt new file mode 100644 index 0000000..eee1486 --- /dev/null +++ b/android/fastlane/metadata/android/en-US/changelogs/39.txt @@ -0,0 +1,3 @@ +* Fixed bug where document types and correspondents were not correctly synced and loaded +* Fixed bug where saved views were not correctly created and loaded +* \ No newline at end of file diff --git a/lib/core/config/hive/custom_adapters/theme_mode_adapter.dart b/lib/core/config/hive/custom_adapters/theme_mode_adapter.dart index 6b9548d..204ad18 100644 --- a/lib/core/config/hive/custom_adapters/theme_mode_adapter.dart +++ b/lib/core/config/hive/custom_adapters/theme_mode_adapter.dart @@ -41,5 +41,7 @@ class ThemeModeAdapter extends TypeAdapter { @override bool operator ==(Object other) => identical(this, other) || - other is ThemeModeAdapter && runtimeType == other.runtimeType && typeId == other.typeId; + other is ThemeModeAdapter && + runtimeType == other.runtimeType && + typeId == other.typeId; } diff --git a/lib/core/config/hive/hive_extensions.dart b/lib/core/config/hive/hive_extensions.dart index 09913ce..7a6c0e2 100644 --- a/lib/core/config/hive/hive_extensions.dart +++ b/lib/core/config/hive/hive_extensions.dart @@ -9,7 +9,8 @@ import 'package:hive_flutter/adapters.dart'; /// Opens an encrypted box, calls [callback] with the now opened box, awaits /// [callback] to return and returns the calculated value. Closes the box after. /// -Future withEncryptedBox(String name, FutureOr Function(Box box) callback) async { +Future withEncryptedBox( + String name, FutureOr Function(Box box) callback) async { final key = await _getEncryptedBoxKey(); final box = await Hive.openBox( name, diff --git a/lib/core/database/tables/local_user_account.dart b/lib/core/database/tables/local_user_account.dart index f5de026..64e6cc4 100644 --- a/lib/core/database/tables/local_user_account.dart +++ b/lib/core/database/tables/local_user_account.dart @@ -27,6 +27,9 @@ class LocalUserAccount extends HiveObject { required this.paperlessUser, }); - static LocalUserAccount get current => Hive.box(HiveBoxes.localUserAccount) - .get(Hive.box(HiveBoxes.globalSettings).getValue()!.currentLoggedInUser)!; + 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 ffb5b43..687eb3a 100644 --- a/lib/core/database/tables/local_user_app_state.dart +++ b/lib/core/database/tables/local_user_app_state.dart @@ -41,7 +41,10 @@ class LocalUserAppState extends HiveObject { static LocalUserAppState get current { final currentLocalUserId = - Hive.box(HiveBoxes.globalSettings).getValue()!.currentLoggedInUser!; - return Hive.box(HiveBoxes.localUserAppState).get(currentLocalUserId)!; + Hive.box(HiveBoxes.globalSettings) + .getValue()! + .currentLoggedInUser!; + return Hive.box(HiveBoxes.localUserAppState) + .get(currentLocalUserId)!; } } diff --git a/lib/core/factory/paperless_api_factory.dart b/lib/core/factory/paperless_api_factory.dart index 4295977..e239fff 100644 --- a/lib/core/factory/paperless_api_factory.dart +++ b/lib/core/factory/paperless_api_factory.dart @@ -3,9 +3,11 @@ import 'package:paperless_api/paperless_api.dart'; abstract class PaperlessApiFactory { PaperlessDocumentsApi createDocumentsApi(Dio dio, {required int apiVersion}); - PaperlessSavedViewsApi createSavedViewsApi(Dio dio, {required int apiVersion}); + PaperlessSavedViewsApi createSavedViewsApi(Dio dio, + {required int apiVersion}); PaperlessLabelsApi createLabelsApi(Dio dio, {required int apiVersion}); - PaperlessServerStatsApi createServerStatsApi(Dio dio, {required int apiVersion}); + PaperlessServerStatsApi createServerStatsApi(Dio dio, + {required int apiVersion}); PaperlessTasksApi createTasksApi(Dio dio, {required int apiVersion}); PaperlessAuthenticationApi createAuthenticationApi(Dio dio); PaperlessUserApi createUserApi(Dio dio, {required int apiVersion}); diff --git a/lib/core/factory/paperless_api_factory_impl.dart b/lib/core/factory/paperless_api_factory_impl.dart index fb66df5..e990c27 100644 --- a/lib/core/factory/paperless_api_factory_impl.dart +++ b/lib/core/factory/paperless_api_factory_impl.dart @@ -19,12 +19,14 @@ class PaperlessApiFactoryImpl implements PaperlessApiFactory { } @override - PaperlessSavedViewsApi createSavedViewsApi(Dio dio, {required int apiVersion}) { + PaperlessSavedViewsApi createSavedViewsApi(Dio dio, + {required int apiVersion}) { return PaperlessSavedViewsApiImpl(dio); } @override - PaperlessServerStatsApi createServerStatsApi(Dio dio, {required int apiVersion}) { + PaperlessServerStatsApi createServerStatsApi(Dio dio, + {required int apiVersion}) { return PaperlessServerStatsApiImpl(dio); } diff --git a/lib/core/interceptor/dio_http_error_interceptor.dart b/lib/core/interceptor/dio_http_error_interceptor.dart index 211aa45..cf65551 100644 --- a/lib/core/interceptor/dio_http_error_interceptor.dart +++ b/lib/core/interceptor/dio_http_error_interceptor.dart @@ -78,7 +78,8 @@ 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 index 07b5beb..05a65ee 100644 --- a/lib/core/navigation/push_routes.dart +++ b/lib/core/navigation/push_routes.dart @@ -1,5 +1,6 @@ import 'dart:typed_data'; +import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_cache_manager/flutter_cache_manager.dart'; @@ -35,8 +36,9 @@ import 'package:provider/provider.dart'; // 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 currentUser = Hive.box(HiveBoxes.globalSettings) + .getValue()! + .currentLoggedInUser; final userRepo = context.read(); return Navigator.of(context).push( MaterialPageRoute( @@ -53,7 +55,8 @@ Future pushDocumentSearchPage(BuildContext context) { create: (context) => DocumentSearchCubit( context.read(), context.read(), - Hive.box(HiveBoxes.localUserAppState).get(currentUser)!, + Hive.box(HiveBoxes.localUserAppState) + .get(currentUser)!, ), child: const DocumentSearchPage(), ); @@ -103,7 +106,8 @@ Future pushSavedViewDetailsRoute( builder: (_) => MultiProvider( providers: [ Provider.value(value: apiVersion), - if (apiVersion.hasMultiUserSupport) Provider.value(value: context.read()), + if (apiVersion.hasMultiUserSupport) + Provider.value(value: context.read()), Provider.value(value: context.read()), Provider.value(value: context.read()), Provider.value(value: context.read()), @@ -119,7 +123,8 @@ Future pushSavedViewDetailsRoute( LocalUserAppState.current, savedView: savedView, ), - child: SavedViewDetailsPage(onDelete: context.read().remove), + child: SavedViewDetailsPage( + onDelete: context.read().remove), ); }, ), @@ -127,7 +132,8 @@ Future pushSavedViewDetailsRoute( ); } -Future pushAddSavedViewRoute(BuildContext context, {required DocumentFilter filter}) { +Future pushAddSavedViewRoute(BuildContext context, + {required DocumentFilter filter}) { return Navigator.of(context).push( MaterialPageRoute( builder: (_) => AddSavedViewPage( @@ -141,7 +147,8 @@ Future pushAddSavedViewRoute(BuildContext context, {required Documen ); } -Future pushLinkedDocumentsView(BuildContext context, {required DocumentFilter filter}) { +Future pushLinkedDocumentsView(BuildContext context, + {required DocumentFilter filter}) { return Navigator.push( context, MaterialPageRoute( @@ -196,7 +203,9 @@ Future pushBulkEditCorrespondentRoute( labelMapper: (document) => document.correspondent, leadingIcon: const Icon(Icons.person_outline), hintText: S.of(context)!.startTyping, - onSubmit: context.read().bulkModifyCorrespondent, + onSubmit: context + .read() + .bulkModifyCorrespondent, assignMessageBuilder: (int count, String name) { return S.of(context)!.bulkEditCorrespondentAssignMessage( name, @@ -204,7 +213,9 @@ Future pushBulkEditCorrespondentRoute( ); }, removeMessageBuilder: (int count) { - return S.of(context)!.bulkEditCorrespondentRemoveMessage(count); + return S + .of(context)! + .bulkEditCorrespondentRemoveMessage(count); }, ); }, @@ -240,7 +251,9 @@ Future pushBulkEditStoragePathRoute( labelMapper: (document) => document.storagePath, leadingIcon: const Icon(Icons.folder_outlined), hintText: S.of(context)!.startTyping, - onSubmit: context.read().bulkModifyStoragePath, + onSubmit: context + .read() + .bulkModifyStoragePath, assignMessageBuilder: (int count, String name) { return S.of(context)!.bulkEditStoragePathAssignMessage( count, @@ -308,7 +321,9 @@ Future pushBulkEditDocumentTypeRoute(BuildContext context, labelMapper: (document) => document.documentType, leadingIcon: const Icon(Icons.description_outlined), hintText: S.of(context)!.startTyping, - onSubmit: context.read().bulkModifyDocumentType, + onSubmit: context + .read() + .bulkModifyDocumentType, assignMessageBuilder: (int count, String name) { return S.of(context)!.bulkEditDocumentTypeAssignMessage( count, @@ -316,7 +331,9 @@ Future pushBulkEditDocumentTypeRoute(BuildContext context, ); }, removeMessageBuilder: (int count) { - return S.of(context)!.bulkEditDocumentTypeRemoveMessage(count); + return S + .of(context)! + .bulkEditDocumentTypeRemoveMessage(count); }, ); }, @@ -336,17 +353,20 @@ Future pushDocumentUploadPreparationPage( }) { final labelRepo = context.read(); final docsApi = context.read(); + final connectivity = context.read(); return Navigator.of(context).push( MaterialPageRoute( builder: (_) => MultiProvider( providers: [ Provider.value(value: labelRepo), Provider.value(value: docsApi), + Provider.value(value: connectivity), ], builder: (_, child) => BlocProvider( create: (_) => DocumentUploadCubit( context.read(), context.read(), + context.read(), ), child: DocumentUploadPreparationPage( fileBytes: bytes, diff --git a/lib/core/repository/saved_view_repository.dart b/lib/core/repository/saved_view_repository.dart index 181d2fc..234ceb3 100644 --- a/lib/core/repository/saved_view_repository.dart +++ b/lib/core/repository/saved_view_repository.dart @@ -1,39 +1,55 @@ import 'dart:async'; +import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:paperless_api/paperless_api.dart'; import 'package:paperless_mobile/core/repository/persistent_repository.dart'; -import 'package:paperless_mobile/core/repository/saved_view_repository_state.dart'; -class SavedViewRepository extends PersistentRepository { +part 'saved_view_repository_state.dart'; +part 'saved_view_repository.g.dart'; +part 'saved_view_repository.freezed.dart'; + +class SavedViewRepository + extends PersistentRepository { final PaperlessSavedViewsApi _api; + final Completer _initialized = Completer(); - SavedViewRepository(this._api) : super(const SavedViewRepositoryState()) { - initialize(); - } + SavedViewRepository(this._api) + : super(const SavedViewRepositoryState.initial()); - Future initialize() { - return findAll(); + Future initialize() async { + try { + await findAll(); + _initialized.complete(); + } catch (e) { + _initialized.completeError(e); + emit(const SavedViewRepositoryState.error()); + } } Future create(SavedView object) async { + await _initialized.future; final created = await _api.save(object); - final updatedState = {...state.savedViews}..putIfAbsent(created.id!, () => created); - emit(state.copyWith(savedViews: updatedState)); + final updatedState = {...state.savedViews} + ..putIfAbsent(created.id!, () => created); + emit(SavedViewRepositoryState.loaded(savedViews: updatedState)); return created; } Future delete(SavedView view) async { + await _initialized.future; await _api.delete(view); final updatedState = {...state.savedViews}..remove(view.id); - emit(state.copyWith(savedViews: updatedState)); + emit(SavedViewRepositoryState.loaded(savedViews: updatedState)); return view.id!; } Future find(int id) async { + await _initialized.future; final found = await _api.find(id); if (found != null) { - final updatedState = {...state.savedViews}..update(id, (_) => found, ifAbsent: () => found); - emit(state.copyWith(savedViews: updatedState)); + final updatedState = {...state.savedViews} + ..update(id, (_) => found, ifAbsent: () => found); + emit(SavedViewRepositoryState.loaded(savedViews: updatedState)); } return found; } @@ -44,14 +60,15 @@ class SavedViewRepository extends PersistentRepository ...state.savedViews, ...{for (final view in found) view.id!: view}, }; - emit(state.copyWith(savedViews: updatedState)); + emit(SavedViewRepositoryState.loaded(savedViews: updatedState)); return found; } @override Future clear() async { + await _initialized.future; await super.clear(); - emit(const SavedViewRepositoryState()); + emit(const SavedViewRepositoryState.initial()); } @override diff --git a/lib/core/repository/saved_view_repository_state.dart b/lib/core/repository/saved_view_repository_state.dart index fb21b14..bf72058 100644 --- a/lib/core/repository/saved_view_repository_state.dart +++ b/lib/core/repository/saved_view_repository_state.dart @@ -1,14 +1,19 @@ -import 'package:freezed_annotation/freezed_annotation.dart'; -import 'package:paperless_api/paperless_api.dart'; - -part 'saved_view_repository_state.freezed.dart'; -part 'saved_view_repository_state.g.dart'; +part of 'saved_view_repository.dart'; @freezed class SavedViewRepositoryState with _$SavedViewRepositoryState { - const factory SavedViewRepositoryState({ + const factory SavedViewRepositoryState.initial({ @Default({}) Map savedViews, - }) = _SavedViewRepositoryState; + }) = _Initial; + const factory SavedViewRepositoryState.loading({ + @Default({}) Map savedViews, + }) = _Loading; + const factory SavedViewRepositoryState.loaded({ + @Default({}) Map savedViews, + }) = _Loaded; + const factory SavedViewRepositoryState.error({ + @Default({}) Map savedViews, + }) = _Error; factory SavedViewRepositoryState.fromJson(Map json) => _$SavedViewRepositoryStateFromJson(json); diff --git a/lib/core/security/session_manager.dart b/lib/core/security/session_manager.dart index 8bc7c9f..9ff8219 100644 --- a/lib/core/security/session_manager.dart +++ b/lib/core/security/session_manager.dart @@ -13,7 +13,8 @@ import 'package:pretty_dio_logger/pretty_dio_logger.dart'; class SessionManager extends ValueNotifier { Dio get client => value; - SessionManager([List interceptors = const []]) : super(_initDio(interceptors)); + SessionManager([List interceptors = const []]) + : super(_initDio(interceptors)); static Dio _initDio(List interceptors) { //en- and decoded by utf8 by default @@ -21,8 +22,8 @@ class SessionManager extends ValueNotifier { BaseOptions(contentType: Headers.jsonContentType), ); dio.options - ..receiveTimeout = const Duration(seconds: 15) - ..sendTimeout = const Duration(seconds: 10) + ..receiveTimeout = const Duration(seconds: 20) + ..sendTimeout = const Duration(seconds: 60) ..responseType = ResponseType.json; (dio.httpClientAdapter as IOHttpClientAdapter).onHttpClientCreate = (client) => client..badCertificateCallback = (cert, host, port) => true; @@ -62,7 +63,8 @@ class SessionManager extends ValueNotifier { ); final adapter = IOHttpClientAdapter() ..onHttpClientCreate = (client) => HttpClient(context: context) - ..badCertificateCallback = (X509Certificate cert, String host, int port) => true; + ..badCertificateCallback = + (X509Certificate cert, String host, int port) => true; client.httpClientAdapter = adapter; } diff --git a/lib/core/service/connectivity_status_service.dart b/lib/core/service/connectivity_status_service.dart index 83d309d..0dc1cf1 100644 --- a/lib/core/service/connectivity_status_service.dart +++ b/lib/core/service/connectivity_status_service.dart @@ -32,7 +32,8 @@ class ConnectivityStatusServiceImpl implements ConnectivityStatusService { @override Future isConnectedToInternet() async { - return _hasActiveInternetConnection(await (Connectivity().checkConnectivity())); + return _hasActiveInternetConnection( + await (Connectivity().checkConnectivity())); } @override @@ -71,10 +72,11 @@ class ConnectivityStatusServiceImpl implements ConnectivityStatusService { return ReachabilityStatus.unknown; } try { - SessionManager manager = SessionManager([ServerReachabilityErrorInterceptor()]) - ..updateSettings(clientCertificate: clientCertificate) - ..client.options.connectTimeout = const Duration(seconds: 5) - ..client.options.receiveTimeout = const Duration(seconds: 5); + SessionManager manager = + SessionManager([ServerReachabilityErrorInterceptor()]) + ..updateSettings(clientCertificate: clientCertificate) + ..client.options.connectTimeout = const Duration(seconds: 5) + ..client.options.receiveTimeout = const Duration(seconds: 5); final response = await manager.client.get('$serverAddress/api/'); if (response.statusCode == 200) { @@ -82,7 +84,8 @@ class ConnectivityStatusServiceImpl implements ConnectivityStatusService { } return ReachabilityStatus.notReachable; } on DioError catch (error) { - if (error.type == DioErrorType.unknown && error.error is ReachabilityStatus) { + if (error.type == DioErrorType.unknown && + error.error is ReachabilityStatus) { return error.error as ReachabilityStatus; } } on TlsException catch (error) { diff --git a/lib/core/service/github_issue_service.dart b/lib/core/service/github_issue_service.dart index 3d7e435..7244704 100644 --- a/lib/core/service/github_issue_service.dart +++ b/lib/core/service/github_issue_service.dart @@ -1,4 +1,3 @@ - import 'package:flutter/material.dart'; import 'package:paperless_mobile/core/model/github_error_report.model.dart'; import 'package:paperless_mobile/core/widgets/error_report_page.dart'; diff --git a/lib/core/type/types.dart b/lib/core/type/types.dart index ce6ae47..3ed65fa 100644 --- a/lib/core/type/types.dart +++ b/lib/core/type/types.dart @@ -1,4 +1,3 @@ - typedef JSON = Map; typedef PaperlessValidationErrors = Map; typedef PaperlessLocalizedErrorMessage = String; diff --git a/lib/core/widgets/form_builder_fields/form_builder_color_picker.dart b/lib/core/widgets/form_builder_fields/form_builder_color_picker.dart index 912d33d..21d0898 100644 --- a/lib/core/widgets/form_builder_fields/form_builder_color_picker.dart +++ b/lib/core/widgets/form_builder_fields/form_builder_color_picker.dart @@ -181,7 +181,8 @@ class FormBuilderColorPickerField extends FormBuilderField { ); @override - FormBuilderColorPickerFieldState createState() => FormBuilderColorPickerFieldState(); + FormBuilderColorPickerFieldState createState() => + FormBuilderColorPickerFieldState(); } class FormBuilderColorPickerFieldState diff --git a/lib/core/widgets/form_builder_fields/form_builder_type_ahead.dart b/lib/core/widgets/form_builder_fields/form_builder_type_ahead.dart index 18b9f50..bbd8480 100644 --- a/lib/core/widgets/form_builder_fields/form_builder_type_ahead.dart +++ b/lib/core/widgets/form_builder_fields/form_builder_type_ahead.dart @@ -334,7 +334,8 @@ class FormBuilderTypeAhead extends FormBuilderField { // TODO HACK to satisfy strictness suggestionsCallback: suggestionsCallback, itemBuilder: itemBuilder, - transitionBuilder: (context, suggestionsBox, controller) => suggestionsBox, + transitionBuilder: (context, suggestionsBox, controller) => + suggestionsBox, onSuggestionSelected: (T suggestion) { state.didChange(suggestion); onSuggestionSelected?.call(suggestion); @@ -356,7 +357,8 @@ class FormBuilderTypeAhead extends FormBuilderField { keepSuggestionsOnLoading: keepSuggestionsOnLoading, autoFlipDirection: autoFlipDirection, suggestionsBoxController: suggestionsBoxController, - keepSuggestionsOnSuggestionSelected: keepSuggestionsOnSuggestionSelected, + keepSuggestionsOnSuggestionSelected: + keepSuggestionsOnSuggestionSelected, hideKeyboard: hideKeyboard, scrollController: scrollController, ); @@ -367,14 +369,15 @@ class FormBuilderTypeAhead extends FormBuilderField { FormBuilderTypeAheadState createState() => FormBuilderTypeAheadState(); } -class FormBuilderTypeAheadState extends FormBuilderFieldState, T> { +class FormBuilderTypeAheadState + extends FormBuilderFieldState, T> { late TextEditingController _typeAheadController; @override void initState() { super.initState(); - _typeAheadController = - widget.controller ?? TextEditingController(text: _getTextString(initialValue)); + _typeAheadController = widget.controller ?? + TextEditingController(text: _getTextString(initialValue)); // _typeAheadController.addListener(_handleControllerChanged); } diff --git a/lib/core/widgets/material/chips_input.dart b/lib/core/widgets/material/chips_input.dart index d8f5ef6..7369a0c 100644 --- a/lib/core/widgets/material/chips_input.dart +++ b/lib/core/widgets/material/chips_input.dart @@ -27,7 +27,8 @@ import 'package:flutter/services.dart'; typedef ChipsInputSuggestions = Future> Function(String query); typedef ChipSelected = void Function(T data, bool selected); -typedef ChipsBuilder = Widget Function(BuildContext context, ChipsInputState state, T data); +typedef ChipsBuilder = Widget Function( + BuildContext context, ChipsInputState state, T data); class ChipsInput extends StatefulWidget { const ChipsInput({ @@ -70,7 +71,8 @@ class ChipsInputState extends State> { TextEditingValue get currentTextEditingValue => _value; - bool get _hasInputConnection => _connection != null && (_connection?.attached ?? false); + bool get _hasInputConnection => + _connection != null && (_connection?.attached ?? false); void requestKeyboard() { if (_focusNode.hasFocus) { @@ -189,7 +191,8 @@ class ChipsInputState extends State> { child: ListView.builder( itemCount: _suggestions.length, itemBuilder: (BuildContext context, int index) { - return widget.suggestionBuilder(context, this, _suggestions[index]); + return widget.suggestionBuilder( + context, this, _suggestions[index]); }, ), ), @@ -210,11 +213,14 @@ class ChipsInputState extends State> { } int _countReplacements(TextEditingValue value) { - return value.text.codeUnits.where((ch) => ch == kObjectReplacementChar).length; + return value.text.codeUnits + .where((ch) => ch == kObjectReplacementChar) + .length; } void _updateTextInputState() { - final text = String.fromCharCodes(_chips.map((_) => kObjectReplacementChar)); + final text = + String.fromCharCodes(_chips.map((_) => kObjectReplacementChar)); _value = TextEditingValue( text: text, selection: TextSelection.collapsed(offset: text.length), @@ -227,8 +233,9 @@ class ChipsInputState extends State> { final localId = ++_searchId; final results = await widget.findSuggestions(value); if (_searchId == localId && mounted) { - setState(() => _suggestions = - results.where((profile) => !_chips.contains(profile)).toList(growable: false)); + setState(() => _suggestions = results + .where((profile) => !_chips.contains(profile)) + .toList(growable: false)); } } } @@ -244,7 +251,8 @@ class _TextCaret extends StatefulWidget { _TextCursorState createState() => _TextCursorState(); } -class _TextCursorState extends State<_TextCaret> with SingleTickerProviderStateMixin { +class _TextCursorState extends State<_TextCaret> + with SingleTickerProviderStateMixin { bool _displayed = false; late Timer _timer; diff --git a/lib/features/app_drawer/view/app_drawer.dart b/lib/features/app_drawer/view/app_drawer.dart index 19778a7..48adf98 100644 --- a/lib/features/app_drawer/view/app_drawer.dart +++ b/lib/features/app_drawer/view/app_drawer.dart @@ -95,7 +95,8 @@ class AppDrawer extends StatelessWidget { MaterialPageRoute( builder: (_) => MultiProvider( providers: [ - Provider.value(value: context.read()), + Provider.value( + value: context.read()), Provider.value(value: context.read()), ], child: const SettingsPage(), @@ -128,7 +129,8 @@ class AppDrawer extends StatelessWidget { ), RichText( text: TextSpan( - style: theme.textTheme.bodyMedium?.copyWith(color: colorScheme.onSurface), + style: theme.textTheme.bodyMedium + ?.copyWith(color: colorScheme.onSurface), children: [ TextSpan( text: S.of(context)!.findTheSourceCodeOn, @@ -151,11 +153,13 @@ class AppDrawer extends StatelessWidget { const SizedBox(height: 16), Text( 'Credits', - style: theme.textTheme.titleMedium?.copyWith(color: colorScheme.onSurface), + style: theme.textTheme.titleMedium + ?.copyWith(color: colorScheme.onSurface), ), RichText( text: TextSpan( - style: theme.textTheme.bodyMedium?.copyWith(color: colorScheme.onSurface), + style: theme.textTheme.bodyMedium + ?.copyWith(color: colorScheme.onSurface), children: [ const TextSpan( text: 'Onboarding images by ', @@ -205,16 +209,16 @@ class AppDrawer extends StatelessWidget { } //Wrap( - // children: [ - // const Text('Onboarding images by '), - // GestureDetector( - // onTap: followLink, - // child: RichText( - - // 'pch.vector', - // style: TextStyle(color: Colors.blue), - // ), - // ), - // const Text(' on Freepik.') - // ], - // ) +// children: [ +// const Text('Onboarding images by '), +// GestureDetector( +// onTap: followLink, +// child: RichText( + +// 'pch.vector', +// style: TextStyle(color: Colors.blue), +// ), +// ), +// const Text(' on Freepik.') +// ], +// ) diff --git a/lib/features/app_intro/application_intro_slideshow.dart b/lib/features/app_intro/application_intro_slideshow.dart index 5168f25..de3b8eb 100644 --- a/lib/features/app_intro/application_intro_slideshow.dart +++ b/lib/features/app_intro/application_intro_slideshow.dart @@ -10,7 +10,8 @@ class ApplicationIntroSlideshow extends StatefulWidget { const ApplicationIntroSlideshow({super.key}); @override - State createState() => _ApplicationIntroSlideshowState(); + State createState() => + _ApplicationIntroSlideshowState(); } //TODO: INTL ALL diff --git a/lib/features/document_bulk_action/view/widgets/bulk_edit_label_bottom_sheet.dart b/lib/features/document_bulk_action/view/widgets/bulk_edit_label_bottom_sheet.dart index e99051e..9f740b8 100644 --- a/lib/features/document_bulk_action/view/widgets/bulk_edit_label_bottom_sheet.dart +++ b/lib/features/document_bulk_action/view/widgets/bulk_edit_label_bottom_sheet.dart @@ -8,7 +8,8 @@ import 'package:paperless_mobile/features/document_bulk_action/cubit/document_bu import 'package:paperless_mobile/features/labels/view/widgets/label_form_field.dart'; import 'package:paperless_mobile/generated/l10n/app_localizations.dart'; -typedef LabelOptionsSelector = Map Function(DocumentBulkActionState state); +typedef LabelOptionsSelector = Map Function( + DocumentBulkActionState state); class BulkEditLabelBottomSheet extends StatefulWidget { final String title; @@ -31,16 +32,19 @@ class BulkEditLabelBottomSheet extends StatefulWidget { }); @override - State> createState() => _BulkEditLabelBottomSheetState(); + State> createState() => + _BulkEditLabelBottomSheetState(); } -class _BulkEditLabelBottomSheetState extends State> { +class _BulkEditLabelBottomSheetState + extends State> { final _formKey = GlobalKey(); @override Widget build(BuildContext context) { return Padding( - padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), + padding: + EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), child: BlocBuilder( builder: (context, state) { return Padding( @@ -76,11 +80,13 @@ class _BulkEditLabelBottomSheetState extends State id, orElse: () => null)); + widget.onSubmit(value?.maybeWhen( + fromId: (id) => id, orElse: () => null)); } }, child: Text(S.of(context)!.apply), diff --git a/lib/features/document_details/cubit/document_details_cubit.dart b/lib/features/document_details/cubit/document_details_cubit.dart index 301a66b..20cec69 100644 --- a/lib/features/document_details/cubit/document_details_cubit.dart +++ b/lib/features/document_details/cubit/document_details_cubit.dart @@ -91,8 +91,8 @@ class DocumentDetailsCubit extends Cubit { _notifier.notifyUpdated(updatedDocument); } else { final int autoAsn = await _api.findNextAsn(); - final updatedDocument = - await _api.update(document.copyWith(archiveSerialNumber: () => autoAsn)); + final updatedDocument = await _api + .update(document.copyWith(archiveSerialNumber: () => autoAsn)); _notifier.notifyUpdated(updatedDocument); } } @@ -104,7 +104,8 @@ class DocumentDetailsCubit extends Cubit { if (state.metaData == null) { await loadMetaData(); } - final desc = FileDescription.fromPath(state.metaData!.mediaFilename.replaceAll("/", " ")); + final desc = FileDescription.fromPath( + state.metaData!.mediaFilename.replaceAll("/", " ")); final fileName = "${desc.filename}.pdf"; final file = File("${cacheDir.path}/$fileName"); @@ -138,7 +139,8 @@ class DocumentDetailsCubit extends Cubit { await FileService.downloadsDirectory, ); final desc = FileDescription.fromPath( - state.metaData!.mediaFilename.replaceAll("/", " "), // Flatten directory structure + state.metaData!.mediaFilename + .replaceAll("/", " "), // Flatten directory structure ); if (!File(filePath).existsSync()) { File(filePath).createSync(); @@ -205,7 +207,8 @@ class DocumentDetailsCubit extends Cubit { if (state.metaData == null) { await loadMetaData(); } - final filePath = _buildDownloadFilePath(false, await FileService.temporaryDirectory); + final filePath = + _buildDownloadFilePath(false, await FileService.temporaryDirectory); await _api.downloadToFile( state.document, filePath, @@ -223,7 +226,8 @@ class DocumentDetailsCubit extends Cubit { String _buildDownloadFilePath(bool original, Directory dir) { final description = FileDescription.fromPath( - state.metaData!.mediaFilename.replaceAll("/", " "), // Flatten directory structure + state.metaData!.mediaFilename + .replaceAll("/", " "), // Flatten directory structure ); final extension = original ? description.extension : 'pdf'; return "${dir.path}/${description.filename}.$extension"; diff --git a/lib/features/document_details/view/dialogs/select_file_type_dialog.dart b/lib/features/document_details/view/dialogs/select_file_type_dialog.dart index 1c9bccb..e9dc1f9 100644 --- a/lib/features/document_details/view/dialogs/select_file_type_dialog.dart +++ b/lib/features/document_details/view/dialogs/select_file_type_dialog.dart @@ -45,7 +45,8 @@ class _SelectFileTypeDialogState extends State { CheckboxListTile( controlAffinity: ListTileControlAffinity.leading, value: _rememberSelection, - onChanged: (value) => setState(() => _rememberSelection = value ?? false), + onChanged: (value) => + setState(() => _rememberSelection = value ?? false), title: Text( S.of(context)!.rememberDecision, style: Theme.of(context).textTheme.labelMedium, @@ -61,7 +62,8 @@ class _SelectFileTypeDialogState extends State { if (_rememberSelection) { widget.onRememberSelection(_downloadType); } - Navigator.of(context).pop(_downloadType == FileDownloadType.original); + Navigator.of(context) + .pop(_downloadType == FileDownloadType.original); }, ), ], 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 9e38841..2718dc4 100644 --- a/lib/features/document_details/view/pages/document_details_page.dart +++ b/lib/features/document_details/view/pages/document_details_page.dart @@ -51,27 +51,35 @@ class _DocumentDetailsPageState extends State { final tabLength = 4 + (apiVersion.hasMultiUserSupport ? 1 : 0); return WillPopScope( onWillPop: () async { - Navigator.of(context).pop(context.read().state.document); + Navigator.of(context) + .pop(context.read().state.document); return false; }, child: DefaultTabController( length: tabLength, child: BlocListener( - listenWhen: (previous, current) => !previous.isConnected && current.isConnected, + listenWhen: (previous, current) => + !previous.isConnected && current.isConnected, listener: (context, state) { context.read().loadMetaData(); }, child: Scaffold( extendBodyBehindAppBar: false, - floatingActionButtonLocation: FloatingActionButtonLocation.endDocked, + floatingActionButtonLocation: + FloatingActionButtonLocation.endDocked, floatingActionButton: _buildEditButton(), bottomNavigationBar: _buildBottomAppBar(), body: NestedScrollView( headerSliverBuilder: (context, innerBoxIsScrolled) => [ SliverOverlapAbsorber( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + handle: + NestedScrollView.sliverOverlapAbsorberHandleFor(context), sliver: SliverAppBar( - title: Text(context.watch().state.document.title), + title: Text(context + .watch() + .state + .document + .title), leading: const BackButton(), pinned: true, forceElevated: innerBoxIsScrolled, @@ -81,7 +89,8 @@ class _DocumentDetailsPageState extends State { background: Stack( alignment: Alignment.topCenter, children: [ - BlocBuilder( + BlocBuilder( builder: (context, state) { return Positioned.fill( child: DocumentPreview( @@ -97,8 +106,14 @@ class _DocumentDetailsPageState extends State { decoration: BoxDecoration( gradient: LinearGradient( colors: [ - Theme.of(context).colorScheme.background.withOpacity(0.8), - Theme.of(context).colorScheme.background.withOpacity(0.5), + Theme.of(context) + .colorScheme + .background + .withOpacity(0.8), + Theme.of(context) + .colorScheme + .background + .withOpacity(0.5), Colors.transparent, Colors.transparent, Colors.transparent, @@ -120,7 +135,9 @@ class _DocumentDetailsPageState extends State { child: Text( S.of(context)!.overview, style: TextStyle( - color: Theme.of(context).colorScheme.onPrimaryContainer, + color: Theme.of(context) + .colorScheme + .onPrimaryContainer, ), ), ), @@ -128,7 +145,9 @@ class _DocumentDetailsPageState extends State { child: Text( S.of(context)!.content, style: TextStyle( - color: Theme.of(context).colorScheme.onPrimaryContainer, + color: Theme.of(context) + .colorScheme + .onPrimaryContainer, ), ), ), @@ -136,7 +155,9 @@ class _DocumentDetailsPageState extends State { child: Text( S.of(context)!.metaData, style: TextStyle( - color: Theme.of(context).colorScheme.onPrimaryContainer, + color: Theme.of(context) + .colorScheme + .onPrimaryContainer, ), ), ), @@ -144,7 +165,9 @@ class _DocumentDetailsPageState extends State { child: Text( S.of(context)!.similarDocuments, style: TextStyle( - color: Theme.of(context).colorScheme.onPrimaryContainer, + color: Theme.of(context) + .colorScheme + .onPrimaryContainer, ), ), ), @@ -153,7 +176,9 @@ class _DocumentDetailsPageState extends State { child: Text( "Permissions", style: TextStyle( - color: Theme.of(context).colorScheme.onPrimaryContainer, + color: Theme.of(context) + .colorScheme + .onPrimaryContainer, ), ), ), @@ -182,7 +207,8 @@ class _DocumentDetailsPageState extends State { CustomScrollView( slivers: [ SliverOverlapInjector( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + handle: NestedScrollView + .sliverOverlapAbsorberHandleFor(context), ), DocumentOverviewWidget( document: state.document, @@ -198,7 +224,8 @@ class _DocumentDetailsPageState extends State { CustomScrollView( slivers: [ SliverOverlapInjector( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + handle: NestedScrollView + .sliverOverlapAbsorberHandleFor(context), ), DocumentContentWidget( isFullContentLoaded: state.isFullContentLoaded, @@ -211,7 +238,8 @@ class _DocumentDetailsPageState extends State { CustomScrollView( slivers: [ SliverOverlapInjector( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + handle: NestedScrollView + .sliverOverlapAbsorberHandleFor(context), ), DocumentMetaDataWidget( document: state.document, @@ -223,7 +251,8 @@ class _DocumentDetailsPageState extends State { controller: _pagingScrollController, slivers: [ SliverOverlapInjector( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + handle: NestedScrollView + .sliverOverlapAbsorberHandleFor(context), ), SimilarDocumentsView( pagingScrollController: _pagingScrollController, @@ -235,7 +264,8 @@ class _DocumentDetailsPageState extends State { controller: _pagingScrollController, slivers: [ SliverOverlapInjector( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + handle: NestedScrollView + .sliverOverlapAbsorberHandleFor(context), ), DocumentPermissionsWidget( document: state.document, @@ -289,15 +319,16 @@ class _DocumentDetailsPageState extends State { final isConnected = connectivityState.isConnected; final canDelete = isConnected && - LocalUserAccount.current.paperlessUser - .hasPermission(PermissionAction.delete, PermissionTarget.document); + LocalUserAccount.current.paperlessUser.hasPermission( + PermissionAction.delete, PermissionTarget.document); return Row( mainAxisAlignment: MainAxisAlignment.start, children: [ IconButton( tooltip: S.of(context)!.deleteDocumentTooltip, icon: const Icon(Icons.delete), - onPressed: canDelete ? () => _onDelete(state.document) : null, + onPressed: + canDelete ? () => _onDelete(state.document) : null, ).paddedSymmetrically(horizontal: 4), DocumentDownloadButton( document: state.document, @@ -307,7 +338,8 @@ class _DocumentDetailsPageState extends State { IconButton( tooltip: S.of(context)!.previewTooltip, icon: const Icon(Icons.visibility), - onPressed: (isConnected) ? () => _onOpen(state.document) : null, + onPressed: + (isConnected) ? () => _onOpen(state.document) : null, ).paddedOnly(right: 4.0), IconButton( tooltip: S.of(context)!.openInSystemViewer, @@ -317,7 +349,8 @@ class _DocumentDetailsPageState extends State { DocumentShareButton(document: state.document), IconButton( tooltip: S.of(context)!.print, //TODO: INTL - onPressed: () => context.read().printDocument(), + onPressed: () => + context.read().printDocument(), icon: const Icon(Icons.print), ), ], @@ -350,7 +383,8 @@ class _DocumentDetailsPageState extends State { ), ], child: BlocListener( - listenWhen: (previous, current) => previous.document != current.document, + listenWhen: (previous, current) => + previous.document != current.document, listener: (context, state) { cubit.replace(state.document); }, @@ -370,7 +404,8 @@ class _DocumentDetailsPageState extends State { } void _onOpenFileInSystemViewer() async { - final status = await context.read().openDocumentInSystemViewer(); + final status = + await context.read().openDocumentInSystemViewer(); if (status == ResultType.done) return; if (status == ResultType.noAppToOpen) { showGenericError(context, S.of(context)!.noAppToDisplayPDFFilesFound); @@ -379,14 +414,16 @@ class _DocumentDetailsPageState extends State { showGenericError(context, translateError(context, ErrorCode.unknown)); } if (status == ResultType.permissionDenied) { - showGenericError(context, S.of(context)!.couldNotOpenFilePermissionDenied); + showGenericError( + context, S.of(context)!.couldNotOpenFilePermissionDenied); } } void _onDelete(DocumentModel document) async { final delete = await showDialog( context: context, - builder: (context) => DeleteDocumentConfirmationDialog(document: document), + builder: (context) => + DeleteDocumentConfirmationDialog(document: document), ) ?? false; if (delete) { @@ -406,7 +443,8 @@ class _DocumentDetailsPageState extends State { Navigator.of(context).push( MaterialPageRoute( builder: (_) => DocumentView( - documentBytes: context.read().download(document), + documentBytes: + context.read().download(document), title: document.title, ), ), diff --git a/lib/features/document_details/view/widgets/archive_serial_number_field.dart b/lib/features/document_details/view/widgets/archive_serial_number_field.dart index f5c5f52..e7101fc 100644 --- a/lib/features/document_details/view/widgets/archive_serial_number_field.dart +++ b/lib/features/document_details/view/widgets/archive_serial_number_field.dart @@ -18,7 +18,8 @@ class ArchiveSerialNumberField extends StatefulWidget { }); @override - State createState() => _ArchiveSerialNumberFieldState(); + State createState() => + _ArchiveSerialNumberFieldState(); } class _ArchiveSerialNumberFieldState extends State { @@ -39,21 +40,25 @@ class _ArchiveSerialNumberFieldState extends State { void _clearButtonListener() { setState(() { _showClearButton = _asnEditingController.text.isNotEmpty; - _canUpdate = int.tryParse(_asnEditingController.text) != widget.document.archiveSerialNumber; + _canUpdate = int.tryParse(_asnEditingController.text) != + widget.document.archiveSerialNumber; }); } @override Widget build(BuildContext context) { - final userCanEditDocument = LocalUserAccount.current.paperlessUser.hasPermission( + final userCanEditDocument = + LocalUserAccount.current.paperlessUser.hasPermission( PermissionAction.change, PermissionTarget.document, ); return BlocListener( listenWhen: (previous, current) => - previous.document.archiveSerialNumber != current.document.archiveSerialNumber, + previous.document.archiveSerialNumber != + current.document.archiveSerialNumber, listener: (context, state) { - _asnEditingController.text = state.document.archiveSerialNumber?.toString() ?? ''; + _asnEditingController.text = + state.document.archiveSerialNumber?.toString() ?? ''; setState(() { _canUpdate = false; }); @@ -80,13 +85,17 @@ class _ArchiveSerialNumberFieldState extends State { IconButton( icon: const Icon(Icons.clear), color: Theme.of(context).colorScheme.primary, - onPressed: userCanEditDocument ? _asnEditingController.clear : null, + onPressed: userCanEditDocument + ? _asnEditingController.clear + : null, ), IconButton( icon: const Icon(Icons.plus_one_rounded), color: Theme.of(context).colorScheme.primary, onPressed: - context.watchInternetConnection && !_showClearButton ? _onAutoAssign : null, + context.watchInternetConnection && !_showClearButton + ? _onAutoAssign + : null, ).paddedOnly(right: 8), ], ), @@ -97,7 +106,9 @@ class _ArchiveSerialNumberFieldState extends State { ), TextButton.icon( icon: const Icon(Icons.done), - onPressed: context.watchInternetConnection && _canUpdate ? _onSubmitted : null, + onPressed: context.watchInternetConnection && _canUpdate + ? _onSubmitted + : null, label: Text(S.of(context)!.save), ).padded(), ], diff --git a/lib/features/document_details/view/widgets/details_item.dart b/lib/features/document_details/view/widgets/details_item.dart index 4003cd0..7916389 100644 --- a/lib/features/document_details/view/widgets/details_item.dart +++ b/lib/features/document_details/view/widgets/details_item.dart @@ -24,7 +24,8 @@ class DetailsItem extends StatelessWidget { } DetailsItem.text( - String text, {super.key, + String text, { + super.key, required this.label, required BuildContext context, }) : content = Text( diff --git a/lib/features/document_details/view/widgets/document_download_button.dart b/lib/features/document_details/view/widgets/document_download_button.dart index 657cf5e..ab1fe74 100644 --- a/lib/features/document_details/view/widgets/document_download_button.dart +++ b/lib/features/document_details/view/widgets/document_download_button.dart @@ -44,14 +44,16 @@ class _DocumentDownloadButtonState extends State { width: 16, ) : const Icon(Icons.download), - onPressed: - widget.document != null && widget.enabled ? () => _onDownload(widget.document!) : null, + onPressed: widget.document != null && widget.enabled + ? () => _onDownload(widget.document!) + : null, ).paddedOnly(right: 4); } Future _onDownload(DocumentModel document) async { try { - final globalSettings = Hive.box(HiveBoxes.globalSettings).getValue()!; + final globalSettings = + Hive.box(HiveBoxes.globalSettings).getValue()!; bool original; switch (globalSettings.defaultDownloadType) { diff --git a/lib/features/document_details/view/widgets/document_permissions_widget.dart b/lib/features/document_details/view/widgets/document_permissions_widget.dart index c2621c0..d66e913 100644 --- a/lib/features/document_details/view/widgets/document_permissions_widget.dart +++ b/lib/features/document_details/view/widgets/document_permissions_widget.dart @@ -6,7 +6,8 @@ class DocumentPermissionsWidget extends StatefulWidget { const DocumentPermissionsWidget({super.key, required this.document}); @override - State createState() => _DocumentPermissionsWidgetState(); + State createState() => + _DocumentPermissionsWidgetState(); } class _DocumentPermissionsWidgetState extends State { diff --git a/lib/features/document_details/view/widgets/document_share_button.dart b/lib/features/document_details/view/widgets/document_share_button.dart index d473f2d..ea6a052 100644 --- a/lib/features/document_details/view/widgets/document_share_button.dart +++ b/lib/features/document_details/view/widgets/document_share_button.dart @@ -43,14 +43,16 @@ class _DocumentShareButtonState extends State { child: CircularProgressIndicator(), ) : const Icon(Icons.share), - onPressed: - widget.document != null && widget.enabled ? () => _onShare(widget.document!) : null, + onPressed: widget.document != null && widget.enabled + ? () => _onShare(widget.document!) + : null, ).paddedOnly(right: 4); } Future _onShare(DocumentModel document) async { try { - final globalSettings = Hive.box(HiveBoxes.globalSettings).getValue()!; + final globalSettings = + Hive.box(HiveBoxes.globalSettings).getValue()!; bool original; switch (globalSettings.defaultShareType) { diff --git a/lib/features/document_edit/view/document_edit_page.dart b/lib/features/document_edit/view/document_edit_page.dart index 0d836e9..658d5e3 100644 --- a/lib/features/document_edit/view/document_edit_page.dart +++ b/lib/features/document_edit/view/document_edit_page.dart @@ -49,8 +49,8 @@ class _DocumentEditPageState extends State { @override void initState() { super.initState(); - _filteredSuggestions = - widget.suggestions?.documentDifference(context.read().state.document); + _filteredSuggestions = widget.suggestions + ?.documentDifference(context.read().state.document); } @override @@ -94,14 +94,16 @@ class _DocumentEditPageState extends State { ListView( children: [ _buildTitleFormField(state.document.title).padded(), - _buildCreatedAtFormField(state.document.created).padded(), + _buildCreatedAtFormField(state.document.created) + .padded(), // Correspondent form field Column( children: [ LabelFormField( showAnyAssignedOption: false, showNotAssignedOption: false, - addLabelPageBuilder: (initialValue) => RepositoryProvider.value( + addLabelPageBuilder: (initialValue) => + RepositoryProvider.value( value: context.read(), child: AddCorrespondentPage( initialName: initialValue, @@ -109,26 +111,39 @@ class _DocumentEditPageState extends State { ), addLabelText: S.of(context)!.addCorrespondent, labelText: S.of(context)!.correspondent, - options: context.watch().state.correspondents, - initialValue: state.document.correspondent != null - ? IdQueryParameter.fromId(state.document.correspondent!) - : const IdQueryParameter.unset(), + options: context + .watch() + .state + .correspondents, + initialValue: + state.document.correspondent != null + ? IdQueryParameter.fromId( + state.document.correspondent!) + : const IdQueryParameter.unset(), name: fkCorrespondent, prefixIcon: const Icon(Icons.person_outlined), allowSelectUnassigned: true, - canCreateNewLabel: - LocalUserAccount.current.paperlessUser.hasPermission( + canCreateNewLabel: LocalUserAccount + .current.paperlessUser + .hasPermission( PermissionAction.add, PermissionTarget.correspondent, ), ), - if (_filteredSuggestions?.hasSuggestedCorrespondents ?? false) + if (_filteredSuggestions + ?.hasSuggestedCorrespondents ?? + false) _buildSuggestionsSkeleton( - suggestions: _filteredSuggestions!.correspondents, - itemBuilder: (context, itemData) => ActionChip( - label: Text(state.correspondents[itemData]!.name), + suggestions: + _filteredSuggestions!.correspondents, + itemBuilder: (context, itemData) => + ActionChip( + label: Text( + state.correspondents[itemData]!.name), onPressed: () { - _formKey.currentState?.fields[fkCorrespondent]?.didChange( + _formKey + .currentState?.fields[fkCorrespondent] + ?.didChange( IdQueryParameter.fromId(itemData), ); }, @@ -142,34 +157,45 @@ class _DocumentEditPageState extends State { LabelFormField( showAnyAssignedOption: false, showNotAssignedOption: false, - addLabelPageBuilder: (currentInput) => RepositoryProvider.value( + addLabelPageBuilder: (currentInput) => + RepositoryProvider.value( value: context.read(), child: AddDocumentTypePage( initialName: currentInput, ), ), - canCreateNewLabel: - LocalUserAccount.current.paperlessUser.hasPermission( + canCreateNewLabel: LocalUserAccount + .current.paperlessUser + .hasPermission( PermissionAction.add, PermissionTarget.documentType, ), addLabelText: S.of(context)!.addDocumentType, labelText: S.of(context)!.documentType, - initialValue: state.document.documentType != null - ? IdQueryParameter.fromId(state.document.documentType!) - : const IdQueryParameter.unset(), + initialValue: + state.document.documentType != null + ? IdQueryParameter.fromId( + state.document.documentType!) + : const IdQueryParameter.unset(), options: state.documentTypes, name: _DocumentEditPageState.fkDocumentType, - prefixIcon: const Icon(Icons.description_outlined), + prefixIcon: + const Icon(Icons.description_outlined), allowSelectUnassigned: true, ), - if (_filteredSuggestions?.hasSuggestedDocumentTypes ?? false) + if (_filteredSuggestions + ?.hasSuggestedDocumentTypes ?? + false) _buildSuggestionsSkeleton( - suggestions: _filteredSuggestions!.documentTypes, - itemBuilder: (context, itemData) => ActionChip( - label: Text(state.documentTypes[itemData]!.name), - onPressed: () => - _formKey.currentState?.fields[fkDocumentType]?.didChange( + suggestions: + _filteredSuggestions!.documentTypes, + itemBuilder: (context, itemData) => + ActionChip( + label: Text( + state.documentTypes[itemData]!.name), + onPressed: () => _formKey + .currentState?.fields[fkDocumentType] + ?.didChange( IdQueryParameter.fromId(itemData), ), ), @@ -182,12 +208,15 @@ class _DocumentEditPageState extends State { LabelFormField( showAnyAssignedOption: false, showNotAssignedOption: false, - addLabelPageBuilder: (initialValue) => RepositoryProvider.value( + addLabelPageBuilder: (initialValue) => + RepositoryProvider.value( value: context.read(), - child: AddStoragePathPage(initalName: initialValue), + child: AddStoragePathPage( + initalName: initialValue), ), - canCreateNewLabel: - LocalUserAccount.current.paperlessUser.hasPermission( + canCreateNewLabel: LocalUserAccount + .current.paperlessUser + .hasPermission( PermissionAction.add, PermissionTarget.storagePath, ), @@ -195,7 +224,8 @@ class _DocumentEditPageState extends State { labelText: S.of(context)!.storagePath, options: state.storagePaths, initialValue: state.document.storagePath != null - ? IdQueryParameter.fromId(state.document.storagePath!) + ? IdQueryParameter.fromId( + state.document.storagePath!) : const IdQueryParameter.unset(), name: fkStoragePath, prefixIcon: const Icon(Icons.folder_outlined), @@ -220,7 +250,8 @@ class _DocumentEditPageState extends State { .isNotEmpty ?? false) _buildSuggestionsSkeleton( - suggestions: (_filteredSuggestions?.tags.toSet() ?? {}), + suggestions: + (_filteredSuggestions?.tags.toSet() ?? {}), itemBuilder: (context, itemData) { final tag = state.tags[itemData]!; return ActionChip( @@ -230,13 +261,17 @@ class _DocumentEditPageState extends State { ), backgroundColor: tag.color, onPressed: () { - final currentTags = - _formKey.currentState?.fields[fkTags]?.value as TagsQuery; - _formKey.currentState?.fields[fkTags]?.didChange( + final currentTags = _formKey.currentState + ?.fields[fkTags]?.value as TagsQuery; + _formKey.currentState?.fields[fkTags] + ?.didChange( currentTags.maybeWhen( - ids: (include, exclude) => TagsQuery.ids( - include: [...include, itemData], exclude: exclude), - orElse: () => TagsQuery.ids(include: [itemData]), + ids: (include, exclude) => + TagsQuery.ids( + include: [...include, itemData], + exclude: exclude), + orElse: () => + TagsQuery.ids(include: [itemData]), ), ); }, @@ -278,12 +313,12 @@ class _DocumentEditPageState extends State { var mergedDocument = document.copyWith( title: values[fkTitle], created: values[fkCreatedDate], - 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), + 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], ); @@ -340,7 +375,8 @@ class _DocumentEditPageState extends State { suggestions: _filteredSuggestions!.dates, itemBuilder: (context, itemData) => ActionChip( label: Text(DateFormat.yMMMd().format(itemData)), - onPressed: () => _formKey.currentState?.fields[fkCreatedDate]?.didChange(itemData), + onPressed: () => _formKey.currentState?.fields[fkCreatedDate] + ?.didChange(itemData), ), ), ], @@ -369,7 +405,8 @@ class _DocumentEditPageState extends State { itemBuilder: (context, index) => ColoredChipWrapper( child: itemBuilder(context, suggestions.elementAt(index)), ), - separatorBuilder: (BuildContext context, int index) => const SizedBox(width: 4.0), + separatorBuilder: (BuildContext context, int index) => + const SizedBox(width: 4.0), ), ), ], @@ -405,7 +442,6 @@ class _DocumentEditPageState extends State { // final List