mirror of
https://github.com/Xevion/paperless-mobile.git
synced 2025-12-06 11:15:48 -06:00
chore+fix+feat: Apply dart fixes after upgrade to flutter 3.10, add permission checks, make most api calls work again
This commit is contained in:
5
lib/core/exception/server_message_exception.dart
Normal file
5
lib/core/exception/server_message_exception.dart
Normal file
@@ -0,0 +1,5 @@
|
||||
class ServerMessageException implements Exception {
|
||||
final String message;
|
||||
|
||||
ServerMessageException(this.message);
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import 'dart:io';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/exception/server_message_exception.dart';
|
||||
import 'package:paperless_mobile/core/type/types.dart';
|
||||
|
||||
class DioHttpErrorInterceptor extends Interceptor {
|
||||
@@ -16,14 +17,15 @@ class DioHttpErrorInterceptor extends Interceptor {
|
||||
return _handlePlainError(data, handler, err);
|
||||
}
|
||||
} else if (err.response?.statusCode == 403) {
|
||||
handler.reject(
|
||||
DioError(
|
||||
var data = err.response!.data;
|
||||
if (data is Map && data.containsKey("detail")) {
|
||||
handler.reject(DioError(
|
||||
requestOptions: err.requestOptions,
|
||||
error: const PaperlessServerException(ErrorCode.notAuthorized),
|
||||
error: ServerMessageException(data['detail']),
|
||||
response: err.response,
|
||||
),
|
||||
);
|
||||
return;
|
||||
));
|
||||
return;
|
||||
}
|
||||
} else if (err.error is SocketException) {
|
||||
final ex = err.error as SocketException;
|
||||
if (ex.osError?.errorCode == _OsErrorCodes.serverUnreachable.code) {
|
||||
@@ -84,8 +86,7 @@ class DioHttpErrorInterceptor extends Interceptor {
|
||||
}
|
||||
|
||||
enum _OsErrorCodes {
|
||||
serverUnreachable(101),
|
||||
hostNotFound(7);
|
||||
serverUnreachable(101);
|
||||
|
||||
const _OsErrorCodes(this.code);
|
||||
final int code;
|
||||
|
||||
@@ -3,6 +3,7 @@ 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';
|
||||
@@ -12,13 +13,19 @@ 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/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/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<void> pushDocumentSearchPage(BuildContext context) {
|
||||
final currentUser =
|
||||
Hive.box<GlobalSettings>(HiveBoxes.globalSettings).getValue()!.currentLoggedInUser;
|
||||
@@ -64,6 +71,7 @@ Future<void> pushDocumentDetailsRoute(
|
||||
Provider.value(value: context.read<PaperlessDocumentsApi>()),
|
||||
Provider.value(value: context.read<LocalNotificationService>()),
|
||||
Provider.value(value: context.read<CacheManager>()),
|
||||
Provider.value(value: context.read<ConnectivityCubit>()),
|
||||
if (context.read<ApiVersion>().hasMultiUserSupport)
|
||||
Provider.value(value: context.read<UserRepository>()),
|
||||
],
|
||||
@@ -76,19 +84,23 @@ Future<void> pushDocumentDetailsRoute(
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> pushSavedViewDetailsRoute(BuildContext context, {required SavedView savedView}) {
|
||||
Future<void> pushSavedViewDetailsRoute(
|
||||
BuildContext context, {
|
||||
required SavedView savedView,
|
||||
}) {
|
||||
final apiVersion = context.read<ApiVersion>();
|
||||
return Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (_) => MultiProvider(
|
||||
providers: [
|
||||
Provider.value(value: apiVersion),
|
||||
if (apiVersion.hasMultiUserSupport) Provider.value(value: context.read<UserRepository>()),
|
||||
Provider.value(value: context.read<LabelRepository>()),
|
||||
Provider.value(value: context.read<DocumentChangedNotifier>()),
|
||||
Provider.value(value: context.read<PaperlessDocumentsApi>()),
|
||||
Provider.value(value: context.read<CacheManager>()),
|
||||
Provider.value(value: context.read<ConnectivityCubit>()),
|
||||
],
|
||||
child: SavedViewDetailsPage(
|
||||
onDelete: context.read<SavedViewCubit>().remove,
|
||||
),
|
||||
builder: (_, child) {
|
||||
return BlocProvider(
|
||||
create: (context) => SavedViewDetailsCubit(
|
||||
@@ -105,3 +117,47 @@ Future<void> pushSavedViewDetailsRoute(BuildContext context, {required SavedView
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<SavedView?> pushAddSavedViewRoute(BuildContext context, {required DocumentFilter filter}) {
|
||||
return Navigator.of(context).push<SavedView?>(
|
||||
MaterialPageRoute(
|
||||
builder: (_) => AddSavedViewPage(
|
||||
currentFilter: filter,
|
||||
correspondents: context.read<LabelRepository>().state.correspondents,
|
||||
documentTypes: context.read<LabelRepository>().state.documentTypes,
|
||||
storagePaths: context.read<LabelRepository>().state.storagePaths,
|
||||
tags: context.read<LabelRepository>().state.tags,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> pushLinkedDocumentsView(BuildContext context, {required DocumentFilter filter}) {
|
||||
return Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => MultiProvider(
|
||||
providers: [
|
||||
Provider.value(value: context.read<ApiVersion>()),
|
||||
Provider.value(value: context.read<LabelRepository>()),
|
||||
Provider.value(value: context.read<DocumentChangedNotifier>()),
|
||||
Provider.value(value: context.read<PaperlessDocumentsApi>()),
|
||||
Provider.value(value: context.read<LocalNotificationService>()),
|
||||
Provider.value(value: context.read<CacheManager>()),
|
||||
Provider.value(value: context.read<ConnectivityCubit>()),
|
||||
if (context.read<ApiVersion>().hasMultiUserSupport)
|
||||
Provider.value(value: context.read<UserRepository>()),
|
||||
],
|
||||
builder: (context, _) => BlocProvider(
|
||||
create: (context) => LinkedDocumentsCubit(
|
||||
filter,
|
||||
context.read(),
|
||||
context.read(),
|
||||
context.read(),
|
||||
),
|
||||
child: const LinkedDocumentsPage(),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import 'dart:async';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:hydrated_bloc/hydrated_bloc.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/repository/label_repository_state.dart';
|
||||
import 'package:paperless_mobile/core/repository/persistent_repository.dart';
|
||||
@@ -9,7 +8,9 @@ import 'package:paperless_mobile/core/repository/persistent_repository.dart';
|
||||
class LabelRepository extends PersistentRepository<LabelRepositoryState> {
|
||||
final PaperlessLabelsApi _api;
|
||||
|
||||
LabelRepository(this._api) : super(const LabelRepositoryState());
|
||||
LabelRepository(this._api) : super(const LabelRepositoryState()) {
|
||||
initialize();
|
||||
}
|
||||
|
||||
Future<void> initialize() {
|
||||
debugPrint("Initializing labels...");
|
||||
|
||||
@@ -7,7 +7,9 @@ import 'package:paperless_mobile/core/repository/saved_view_repository_state.dar
|
||||
class SavedViewRepository extends PersistentRepository<SavedViewRepositoryState> {
|
||||
final PaperlessSavedViewsApi _api;
|
||||
|
||||
SavedViewRepository(this._api) : super(const SavedViewRepositoryState());
|
||||
SavedViewRepository(this._api) : super(const SavedViewRepositoryState()) {
|
||||
initialize();
|
||||
}
|
||||
|
||||
Future<void> initialize() {
|
||||
return findAll();
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:paperless_mobile/core/model/github_error_report.model.dart';
|
||||
|
||||
@@ -1,16 +1,8 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:http/http.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/bloc/document_status_cubit.dart';
|
||||
import 'package:paperless_mobile/core/model/document_processing_status.dart';
|
||||
import 'package:paperless_mobile/features/login/model/authentication_information.dart';
|
||||
import 'package:paperless_mobile/constants.dart';
|
||||
import 'package:paperless_mobile/core/database/tables/user_credentials.dart';
|
||||
import 'package:web_socket_channel/io.dart';
|
||||
// import 'package:web_socket_channel/io.dart';
|
||||
|
||||
abstract class StatusService {
|
||||
Future<void> startListeningBeforeDocumentUpload(
|
||||
@@ -19,7 +11,7 @@ abstract class StatusService {
|
||||
|
||||
class WebSocketStatusService implements StatusService {
|
||||
late WebSocket? socket;
|
||||
late IOWebSocketChannel? _channel;
|
||||
// late IOWebSocketChannel? _channel;
|
||||
|
||||
WebSocketStatusService();
|
||||
|
||||
|
||||
@@ -72,7 +72,5 @@ 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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:rxdart/subjects.dart';
|
||||
|
||||
typedef JSON = Map<String, dynamic>;
|
||||
typedef PaperlessValidationErrors = Map<String, String>;
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/src/widgets/framework.dart';
|
||||
import 'package:flutter/src/widgets/placeholder.dart';
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||
|
||||
class DialogCancelButton extends StatelessWidget {
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/src/widgets/framework.dart';
|
||||
import 'package:flutter/src/widgets/placeholder.dart';
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||
|
||||
enum DialogConfirmButtonStyle {
|
||||
|
||||
@@ -181,8 +181,7 @@ class FormBuilderColorPickerField extends FormBuilderField<Color> {
|
||||
);
|
||||
|
||||
@override
|
||||
FormBuilderColorPickerFieldState createState() =>
|
||||
FormBuilderColorPickerFieldState();
|
||||
FormBuilderColorPickerFieldState createState() => FormBuilderColorPickerFieldState();
|
||||
}
|
||||
|
||||
class FormBuilderColorPickerFieldState
|
||||
@@ -217,8 +216,6 @@ class FormBuilderColorPickerFieldState
|
||||
final selected = await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
final materialLocalizations = S.of(context)!;
|
||||
|
||||
return AlertDialog(
|
||||
// title: null, //const Text('Pick a color!'),
|
||||
content: _buildColorPicker(),
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||
|
||||
|
||||
@@ -27,8 +27,7 @@ import 'package:flutter/services.dart';
|
||||
|
||||
typedef ChipsInputSuggestions<T> = Future<List<T>> Function(String query);
|
||||
typedef ChipSelected<T> = void Function(T data, bool selected);
|
||||
typedef ChipsBuilder<T> = Widget Function(
|
||||
BuildContext context, ChipsInputState<T> state, T data);
|
||||
typedef ChipsBuilder<T> = Widget Function(BuildContext context, ChipsInputState<T> state, T data);
|
||||
|
||||
class ChipsInput<T> extends StatefulWidget {
|
||||
const ChipsInput({
|
||||
@@ -71,8 +70,7 @@ class ChipsInputState<T> extends State<ChipsInput<T>> {
|
||||
|
||||
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) {
|
||||
@@ -191,8 +189,7 @@ class ChipsInputState<T> extends State<ChipsInput<T>> {
|
||||
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]);
|
||||
},
|
||||
),
|
||||
),
|
||||
@@ -213,14 +210,11 @@ class ChipsInputState<T> extends State<ChipsInput<T>> {
|
||||
}
|
||||
|
||||
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),
|
||||
@@ -233,35 +227,30 @@ class ChipsInputState<T> extends State<ChipsInput<T>> {
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class _TextCaret extends StatefulWidget {
|
||||
const _TextCaret({
|
||||
this.duration = const Duration(milliseconds: 500),
|
||||
this.resumed = false,
|
||||
});
|
||||
|
||||
final Duration duration;
|
||||
final bool resumed;
|
||||
|
||||
@override
|
||||
_TextCursorState createState() => _TextCursorState();
|
||||
}
|
||||
|
||||
class _TextCursorState extends State<_TextCaret>
|
||||
with SingleTickerProviderStateMixin {
|
||||
class _TextCursorState extends State<_TextCaret> with SingleTickerProviderStateMixin {
|
||||
bool _displayed = false;
|
||||
late Timer _timer;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_timer = Timer.periodic(widget.duration, _onTimer);
|
||||
}
|
||||
|
||||
void _onTimer(Timer timer) {
|
||||
|
||||
@@ -251,7 +251,6 @@ abstract class SearchDelegate<T> {
|
||||
///
|
||||
/// Setting the query string programmatically moves the cursor to the end of the text field.
|
||||
set query(String value) {
|
||||
assert(query != null);
|
||||
_queryTextController.text = value;
|
||||
if (_queryTextController.text.isNotEmpty) {
|
||||
_queryTextController.selection = TextSelection.fromPosition(
|
||||
|
||||
@@ -7,7 +7,6 @@ import 'dart:ui';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
const int _kOpenViewMilliseconds = 600;
|
||||
const Duration _kOpenViewDuration =
|
||||
@@ -1649,7 +1648,6 @@ class SearchBarTheme extends InheritedWidget {
|
||||
final SearchBarTheme? searchBarTheme =
|
||||
context.dependOnInheritedWidgetOfExactType<SearchBarTheme>();
|
||||
return searchBarTheme?.data ?? const SearchBarThemeData();
|
||||
;
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'package:flutter/gestures.dart';
|
||||
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/widgets/paperless_logo.dart';
|
||||
|
||||
@@ -50,7 +50,7 @@ class _ApplicationIntroSlideshowState extends State<ApplicationIntroSlideshow> {
|
||||
image: AssetImages.organizeDocuments.image,
|
||||
),
|
||||
),
|
||||
bodyWidget: Column(
|
||||
bodyWidget: const Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
@@ -70,7 +70,7 @@ class _ApplicationIntroSlideshowState extends State<ApplicationIntroSlideshow> {
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Image(image: AssetImages.secureDocuments.image),
|
||||
),
|
||||
bodyWidget: Column(
|
||||
bodyWidget: const Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
@@ -90,8 +90,8 @@ class _ApplicationIntroSlideshowState extends State<ApplicationIntroSlideshow> {
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Image(image: AssetImages.success.image),
|
||||
),
|
||||
bodyWidget: Column(
|
||||
children: const [
|
||||
bodyWidget: const Column(
|
||||
children: [
|
||||
BiometricAuthenticationSetting(),
|
||||
LanguageSelectionSetting(),
|
||||
ThemeModeSetting(),
|
||||
|
||||
@@ -2,7 +2,6 @@ import 'dart:async';
|
||||
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:equatable/equatable.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';
|
||||
|
||||
@@ -17,6 +17,7 @@ class BulkEditLabelBottomSheet<T extends Label> extends StatefulWidget {
|
||||
final LabelOptionsSelector<T> availableOptionsSelector;
|
||||
final void Function(int? selectedId) onSubmit;
|
||||
final int? initialValue;
|
||||
final bool canCreateNewLabel;
|
||||
|
||||
const BulkEditLabelBottomSheet({
|
||||
super.key,
|
||||
@@ -26,6 +27,7 @@ class BulkEditLabelBottomSheet<T extends Label> extends StatefulWidget {
|
||||
required this.availableOptionsSelector,
|
||||
required this.onSubmit,
|
||||
this.initialValue,
|
||||
required this.canCreateNewLabel,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -58,6 +60,7 @@ class _BulkEditLabelBottomSheetState<T extends Label> extends State<BulkEditLabe
|
||||
initialValue: widget.initialValue != null
|
||||
? IdQueryParameter.fromId(widget.initialValue!)
|
||||
: const IdQueryParameter.unset(),
|
||||
canCreateNewLabel: widget.canCreateNewLabel,
|
||||
name: "labelFormField",
|
||||
options: widget.availableOptionsSelector(state),
|
||||
labelText: widget.formFieldLabel,
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/src/widgets/framework.dart';
|
||||
import 'package:flutter/src/widgets/placeholder.dart';
|
||||
import 'package:paperless_mobile/core/widgets/dialog_utils/dialog_cancel_button.dart';
|
||||
import 'package:paperless_mobile/core/widgets/dialog_utils/dialog_confirm_button.dart';
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||
|
||||
@@ -26,8 +26,8 @@ class _FullscreenBulkEditTagsWidgetState
|
||||
/// Tags not assigned to at least one document in the selection
|
||||
late final List<int> _nonSharedTags;
|
||||
|
||||
List<int> _addTags = [];
|
||||
List<int> _removeTags = [];
|
||||
final List<int> _addTags = [];
|
||||
final List<int> _removeTags = [];
|
||||
late List<int> _filteredTags;
|
||||
|
||||
@override
|
||||
|
||||
@@ -41,7 +41,7 @@ class _SelectFileTypeDialogState extends State<SelectFileTypeDialog> {
|
||||
},
|
||||
title: Text(S.of(context)!.archivedPdf),
|
||||
),
|
||||
Divider(),
|
||||
const Divider(),
|
||||
CheckboxListTile(
|
||||
controlAffinity: ListTileControlAffinity.leading,
|
||||
value: _rememberSelection,
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
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';
|
||||
@@ -57,7 +53,7 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
|
||||
Widget build(BuildContext context) {
|
||||
final apiVersion = context.watch<ApiVersion>();
|
||||
|
||||
final tabLength = 4 + (apiVersion.supportsPermissions ? 1 : 0);
|
||||
final tabLength = 4 + (apiVersion.hasMultiUserSupport ? 1 : 0);
|
||||
return WillPopScope(
|
||||
onWillPop: () async {
|
||||
Navigator.of(context).pop(context.read<DocumentDetailsCubit>().state.document);
|
||||
@@ -155,7 +151,7 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
|
||||
),
|
||||
),
|
||||
),
|
||||
if (apiVersion.supportsPermissions)
|
||||
if (apiVersion.hasMultiUserSupport)
|
||||
Tab(
|
||||
child: Text(
|
||||
"Permissions",
|
||||
@@ -260,13 +256,9 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
|
||||
}
|
||||
|
||||
Widget _buildEditButton() {
|
||||
bool canEdit = context.watchInternetConnection;
|
||||
final apiVersion = context.watch<ApiVersion>();
|
||||
|
||||
if (apiVersion.supportsPermissions) {
|
||||
canEdit =
|
||||
LocalUserAccount.current.paperlessUser.hasPermission(UserPermissions.changeDocument);
|
||||
}
|
||||
bool canEdit = context.watchInternetConnection &&
|
||||
LocalUserAccount.current.paperlessUser
|
||||
.hasPermission(PermissionAction.change, PermissionTarget.document);
|
||||
if (!canEdit) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
@@ -281,7 +273,7 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
|
||||
verticalOffset: 40,
|
||||
child: FloatingActionButton(
|
||||
child: const Icon(Icons.edit),
|
||||
onPressed: canEdit ? () => _onEdit(state.document) : null,
|
||||
onPressed: () => _onEdit(state.document),
|
||||
),
|
||||
);
|
||||
},
|
||||
@@ -296,15 +288,16 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
|
||||
builder: (context, connectivityState) {
|
||||
final isConnected = connectivityState.isConnected;
|
||||
|
||||
final canDelete = LocalUserAccount.current.paperlessUser
|
||||
.hasPermission(UserPermissions.deleteDocument);
|
||||
final canDelete = isConnected &&
|
||||
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: (isConnected && canDelete) ? () => _onDelete(state.document) : null,
|
||||
onPressed: canDelete ? () => _onDelete(state.document) : null,
|
||||
).paddedSymmetrically(horizontal: 4),
|
||||
DocumentDownloadButton(
|
||||
document: state.document,
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'package:flutter/services.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/database/tables/local_user_account.dart';
|
||||
import 'package:paperless_mobile/core/type/types.dart';
|
||||
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
||||
import 'package:paperless_mobile/features/document_details/cubit/document_details_cubit.dart';
|
||||
@@ -17,8 +18,7 @@ class ArchiveSerialNumberField extends StatefulWidget {
|
||||
});
|
||||
|
||||
@override
|
||||
State<ArchiveSerialNumberField> createState() =>
|
||||
_ArchiveSerialNumberFieldState();
|
||||
State<ArchiveSerialNumberField> createState() => _ArchiveSerialNumberFieldState();
|
||||
}
|
||||
|
||||
class _ArchiveSerialNumberFieldState extends State<ArchiveSerialNumberField> {
|
||||
@@ -39,20 +39,21 @@ class _ArchiveSerialNumberFieldState extends State<ArchiveSerialNumberField> {
|
||||
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(
|
||||
PermissionAction.change,
|
||||
PermissionTarget.document,
|
||||
);
|
||||
return BlocListener<DocumentDetailsCubit, DocumentDetailsState>(
|
||||
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;
|
||||
});
|
||||
@@ -61,6 +62,7 @@ class _ArchiveSerialNumberFieldState extends State<ArchiveSerialNumberField> {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
TextFormField(
|
||||
enabled: userCanEditDocument,
|
||||
controller: _asnEditingController,
|
||||
keyboardType: TextInputType.number,
|
||||
onChanged: (value) {
|
||||
@@ -78,15 +80,13 @@ class _ArchiveSerialNumberFieldState extends State<ArchiveSerialNumberField> {
|
||||
IconButton(
|
||||
icon: const Icon(Icons.clear),
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
onPressed: _asnEditingController.clear,
|
||||
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,9 +97,7 @@ class _ArchiveSerialNumberFieldState extends State<ArchiveSerialNumberField> {
|
||||
),
|
||||
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(),
|
||||
],
|
||||
|
||||
@@ -24,7 +24,7 @@ class DetailsItem extends StatelessWidget {
|
||||
}
|
||||
|
||||
DetailsItem.text(
|
||||
String text, {
|
||||
String text, {super.key,
|
||||
required this.label,
|
||||
required BuildContext context,
|
||||
}) : content = Text(
|
||||
|
||||
@@ -29,8 +29,8 @@ class _DocumentMetaDataWidgetState extends State<DocumentMetaDataWidget> {
|
||||
builder: (context, state) {
|
||||
debugPrint("Building state...");
|
||||
if (state.metaData == null) {
|
||||
return SliverToBoxAdapter(
|
||||
child: const Center(
|
||||
return const SliverToBoxAdapter(
|
||||
child: Center(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -4,7 +4,6 @@ import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/widgets/highlighted_text.dart';
|
||||
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
||||
import 'package:paperless_mobile/features/document_details/view/widgets/details_item.dart';
|
||||
import 'package:paperless_mobile/features/labels/storage_path/view/widgets/storage_path_widget.dart';
|
||||
import 'package:paperless_mobile/features/labels/tags/view/widgets/tags_widget.dart';
|
||||
import 'package:paperless_mobile/features/labels/view/widgets/label_text.dart';
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import 'dart:async';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@@ -8,6 +7,7 @@ import 'package:flutter_typeahead/flutter_typeahead.dart';
|
||||
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/database/tables/local_user_account.dart';
|
||||
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
||||
import 'package:paperless_mobile/core/workarounds/colored_chip.dart';
|
||||
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
||||
@@ -16,7 +16,6 @@ import 'package:paperless_mobile/features/edit_label/view/impl/add_correspondent
|
||||
import 'package:paperless_mobile/features/edit_label/view/impl/add_document_type_page.dart';
|
||||
import 'package:paperless_mobile/features/edit_label/view/impl/add_storage_path_page.dart';
|
||||
import 'package:paperless_mobile/features/labels/tags/view/widgets/tags_form_field.dart';
|
||||
import 'package:paperless_mobile/features/labels/tags/view/widgets/tags_form_field.dart';
|
||||
import 'package:paperless_mobile/features/labels/view/widgets/label_form_field.dart';
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||
|
||||
@@ -117,6 +116,11 @@ class _DocumentEditPageState extends State<DocumentEditPage> {
|
||||
name: fkCorrespondent,
|
||||
prefixIcon: const Icon(Icons.person_outlined),
|
||||
allowSelectUnassigned: true,
|
||||
canCreateNewLabel:
|
||||
LocalUserAccount.current.paperlessUser.hasPermission(
|
||||
PermissionAction.add,
|
||||
PermissionTarget.correspondent,
|
||||
),
|
||||
),
|
||||
if (_filteredSuggestions?.hasSuggestedCorrespondents ?? false)
|
||||
_buildSuggestionsSkeleton<int>(
|
||||
@@ -144,6 +148,11 @@ class _DocumentEditPageState extends State<DocumentEditPage> {
|
||||
initialName: currentInput,
|
||||
),
|
||||
),
|
||||
canCreateNewLabel:
|
||||
LocalUserAccount.current.paperlessUser.hasPermission(
|
||||
PermissionAction.add,
|
||||
PermissionTarget.documentType,
|
||||
),
|
||||
addLabelText: S.of(context)!.addDocumentType,
|
||||
labelText: S.of(context)!.documentType,
|
||||
initialValue: state.document.documentType != null
|
||||
@@ -177,6 +186,11 @@ class _DocumentEditPageState extends State<DocumentEditPage> {
|
||||
value: context.read<LabelRepository>(),
|
||||
child: AddStoragePathPage(initalName: initialValue),
|
||||
),
|
||||
canCreateNewLabel:
|
||||
LocalUserAccount.current.paperlessUser.hasPermission(
|
||||
PermissionAction.add,
|
||||
PermissionTarget.storagePath,
|
||||
),
|
||||
addLabelText: S.of(context)!.addStoragePath,
|
||||
labelText: S.of(context)!.storagePath,
|
||||
options: state.storagePaths,
|
||||
|
||||
@@ -98,7 +98,7 @@ class _ScannedImageItemState extends State<ScannedImageItem> {
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: TextButton(
|
||||
onPressed: widget.onDelete,
|
||||
child: Text("Remove"),
|
||||
child: const Text("Remove"),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -3,15 +3,7 @@ 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';
|
||||
@@ -19,10 +11,8 @@ import 'package:paperless_mobile/features/documents/view/widgets/adaptive_docume
|
||||
import 'package:paperless_mobile/features/documents/view/widgets/selection/view_type_selection_widget.dart';
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||
|
||||
import 'package:paperless_mobile/routes/document_details_route.dart';
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class DocumentSearchPage extends StatefulWidget {
|
||||
const DocumentSearchPage({super.key});
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:hive_flutter/adapters.dart';
|
||||
import 'package:paperless_mobile/core/config/hive/hive_config.dart';
|
||||
import 'package:paperless_mobile/core/database/tables/local_user_account.dart';
|
||||
|
||||
@@ -35,6 +35,7 @@ class DocumentUploadCubit extends Cubit<DocumentUploadState> {
|
||||
int? correspondent,
|
||||
Iterable<int> tags = const [],
|
||||
DateTime? createdAt,
|
||||
int? asn,
|
||||
}) async {
|
||||
return await _documentApi.create(
|
||||
bytes,
|
||||
@@ -44,6 +45,7 @@ class DocumentUploadCubit extends Cubit<DocumentUploadState> {
|
||||
documentType: documentType,
|
||||
tags: tags,
|
||||
createdAt: createdAt,
|
||||
asn: asn,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import 'package:flutter_form_builder/flutter_form_builder.dart';
|
||||
import 'package:intl/date_symbol_data_local.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/database/tables/local_user_account.dart';
|
||||
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
||||
import 'package:paperless_mobile/core/type/types.dart';
|
||||
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
||||
@@ -32,7 +33,6 @@ class DocumentUploadPreparationPage extends StatefulWidget {
|
||||
final String? filename;
|
||||
final String? fileExtension;
|
||||
|
||||
|
||||
const DocumentUploadPreparationPage({
|
||||
Key? key,
|
||||
required this.fileBytes,
|
||||
@@ -193,6 +193,10 @@ class _DocumentUploadPreparationPageState extends State<DocumentUploadPreparatio
|
||||
options: state.correspondents,
|
||||
prefixIcon: const Icon(Icons.person_outline),
|
||||
allowSelectUnassigned: true,
|
||||
canCreateNewLabel: LocalUserAccount.current.paperlessUser.hasPermission(
|
||||
PermissionAction.add,
|
||||
PermissionTarget.correspondent,
|
||||
),
|
||||
),
|
||||
// Document type
|
||||
LabelFormField<DocumentType>(
|
||||
@@ -208,6 +212,10 @@ class _DocumentUploadPreparationPageState extends State<DocumentUploadPreparatio
|
||||
options: state.documentTypes,
|
||||
prefixIcon: const Icon(Icons.description_outlined),
|
||||
allowSelectUnassigned: true,
|
||||
canCreateNewLabel: LocalUserAccount.current.paperlessUser.hasPermission(
|
||||
PermissionAction.add,
|
||||
PermissionTarget.documentType,
|
||||
),
|
||||
),
|
||||
TagsFormField(
|
||||
name: DocumentModel.tagsKey,
|
||||
@@ -239,10 +247,14 @@ class _DocumentUploadPreparationPageState extends State<DocumentUploadPreparatio
|
||||
|
||||
final createdAt = fv[DocumentModel.createdKey] as DateTime?;
|
||||
final title = fv[DocumentModel.titleKey] as String;
|
||||
final docType = fv[DocumentModel.documentTypeKey] as SetIdQueryParameter;
|
||||
final tags = fv[DocumentModel.tagsKey] as IdsTagsQuery;
|
||||
final correspondent = fv[DocumentModel.correspondentKey] as SetIdQueryParameter;
|
||||
|
||||
final docType = (fv[DocumentModel.documentTypeKey] as IdQueryParameter?)
|
||||
?.whenOrNull(fromId: (id) => id);
|
||||
final tags = (fv[DocumentModel.tagsKey] as TagsQuery?)
|
||||
?.whenOrNull(ids: (include, exclude) => include) ??
|
||||
[];
|
||||
final correspondent = (fv[DocumentModel.correspondentKey] as IdQueryParameter?)
|
||||
?.whenOrNull(fromId: (id) => id);
|
||||
final asn = fv[DocumentModel.asnKey] as int?;
|
||||
final taskId = await cubit.upload(
|
||||
widget.fileBytes,
|
||||
filename: _padWithExtension(
|
||||
@@ -250,10 +262,11 @@ class _DocumentUploadPreparationPageState extends State<DocumentUploadPreparatio
|
||||
widget.fileExtension,
|
||||
),
|
||||
title: title,
|
||||
documentType: docType.id,
|
||||
correspondent: correspondent.id,
|
||||
tags: tags.include,
|
||||
documentType: docType,
|
||||
correspondent: correspondent,
|
||||
tags: tags,
|
||||
createdAt: createdAt,
|
||||
asn: asn,
|
||||
);
|
||||
showSnackBar(
|
||||
context,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||
|
||||
class DocumentView extends StatefulWidget {
|
||||
final Future<Uint8List> documentBytes;
|
||||
|
||||
@@ -6,7 +6,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/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';
|
||||
import 'package:paperless_mobile/features/app_drawer/view/app_drawer.dart';
|
||||
@@ -19,12 +18,10 @@ import 'package:paperless_mobile/features/documents/view/widgets/selection/docum
|
||||
import 'package:paperless_mobile/features/documents/view/widgets/selection/view_type_selection_widget.dart';
|
||||
import 'package:paperless_mobile/features/documents/view/widgets/sort_documents_button.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/view/saved_view_list.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/message_helpers.dart';
|
||||
import 'package:paperless_mobile/routes/document_details_route.dart';
|
||||
|
||||
class DocumentFilterIntent {
|
||||
final DocumentFilter? filter;
|
||||
@@ -370,21 +367,7 @@ class _DocumentsPageState extends State<DocumentsPage> with SingleTickerProvider
|
||||
}
|
||||
|
||||
void _onCreateSavedView(DocumentFilter filter) async {
|
||||
final newView = await Navigator.of(context).push<SavedView?>(
|
||||
MaterialPageRoute(
|
||||
builder: (context) => BlocBuilder<SavedViewCubit, SavedViewState>(
|
||||
builder: (context, state) {
|
||||
return AddSavedViewPage(
|
||||
currentFilter: filter,
|
||||
correspondents: context.read<LabelRepository>().state.correspondents,
|
||||
documentTypes: context.read<LabelRepository>().state.documentTypes,
|
||||
storagePaths: context.read<LabelRepository>().state.storagePaths,
|
||||
tags: context.read<LabelRepository>().state.tags,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
final newView = await pushAddSavedViewRoute(context, filter: filter);
|
||||
if (newView != null) {
|
||||
try {
|
||||
await context.read<SavedViewCubit>().add(newView);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/features/documents/view/widgets/document_preview.dart';
|
||||
import 'package:paperless_mobile/features/documents/view/widgets/items/document_item.dart';
|
||||
import 'package:paperless_mobile/features/labels/correspondent/view/widgets/correspondent_widget.dart';
|
||||
|
||||
@@ -61,8 +61,8 @@ class DocumentsListLoadingWidget extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
TagsPlaceholder(count: 2, dense: true),
|
||||
SizedBox(height: 2),
|
||||
const TagsPlaceholder(count: 2, dense: true),
|
||||
const SizedBox(height: 2),
|
||||
TextPlaceholder(
|
||||
length: 250,
|
||||
fontSize: Theme.of(context).textTheme.labelSmall!.fontSize!,
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_form_builder/flutter_form_builder.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/database/tables/local_user_account.dart';
|
||||
import 'package:paperless_mobile/core/widgets/form_builder_fields/extended_date_range_form_field/form_builder_extended_date_range_picker.dart';
|
||||
import 'package:paperless_mobile/features/labels/cubit/label_cubit.dart';
|
||||
import 'package:paperless_mobile/features/labels/tags/view/widgets/tags_form_field.dart';
|
||||
import 'package:paperless_mobile/features/labels/tags/view/widgets/tags_form_field.dart';
|
||||
import 'package:paperless_mobile/features/labels/view/widgets/label_form_field.dart';
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||
@@ -156,6 +154,10 @@ class _DocumentFilterFormState extends State<DocumentFilterForm> {
|
||||
initialValue: widget.initialFilter.documentType,
|
||||
prefixIcon: const Icon(Icons.description_outlined),
|
||||
allowSelectUnassigned: false,
|
||||
canCreateNewLabel: LocalUserAccount.current.paperlessUser.hasPermission(
|
||||
PermissionAction.add,
|
||||
PermissionTarget.documentType,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -167,6 +169,10 @@ class _DocumentFilterFormState extends State<DocumentFilterForm> {
|
||||
initialValue: widget.initialFilter.correspondent,
|
||||
prefixIcon: const Icon(Icons.person_outline),
|
||||
allowSelectUnassigned: false,
|
||||
canCreateNewLabel: LocalUserAccount.current.paperlessUser.hasPermission(
|
||||
PermissionAction.add,
|
||||
PermissionTarget.correspondent,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -178,6 +184,10 @@ class _DocumentFilterFormState extends State<DocumentFilterForm> {
|
||||
initialValue: widget.initialFilter.storagePath,
|
||||
prefixIcon: const Icon(Icons.folder_outlined),
|
||||
allowSelectUnassigned: false,
|
||||
canCreateNewLabel: LocalUserAccount.current.paperlessUser.hasPermission(
|
||||
PermissionAction.add,
|
||||
PermissionTarget.storagePath,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_form_builder/flutter_form_builder.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/widgets/form_builder_fields/form_builder_type_ahead.dart';
|
||||
import 'package:paperless_mobile/features/documents/cubit/documents_cubit.dart';
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ class EditLabelPage<T extends Label> extends StatelessWidget {
|
||||
final List<Widget> additionalFields;
|
||||
final Future<T> Function(BuildContext context, T label) onSubmit;
|
||||
final Future<void> Function(BuildContext context, T label) onDelete;
|
||||
final bool canDelete;
|
||||
|
||||
const EditLabelPage({
|
||||
super.key,
|
||||
@@ -26,6 +27,7 @@ class EditLabelPage<T extends Label> extends StatelessWidget {
|
||||
this.additionalFields = const [],
|
||||
required this.onSubmit,
|
||||
required this.onDelete,
|
||||
required this.canDelete,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -40,6 +42,7 @@ class EditLabelPage<T extends Label> extends StatelessWidget {
|
||||
fromJsonT: fromJsonT,
|
||||
onSubmit: onSubmit,
|
||||
onDelete: onDelete,
|
||||
canDelete: canDelete,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -51,6 +54,7 @@ class EditLabelForm<T extends Label> extends StatelessWidget {
|
||||
final List<Widget> additionalFields;
|
||||
final Future<T> Function(BuildContext context, T label) onSubmit;
|
||||
final Future<void> Function(BuildContext context, T label) onDelete;
|
||||
final bool canDelete;
|
||||
|
||||
const EditLabelForm({
|
||||
super.key,
|
||||
@@ -59,6 +63,7 @@ class EditLabelForm<T extends Label> extends StatelessWidget {
|
||||
required this.additionalFields,
|
||||
required this.onSubmit,
|
||||
required this.onDelete,
|
||||
required this.canDelete,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -68,7 +73,7 @@ class EditLabelForm<T extends Label> extends StatelessWidget {
|
||||
title: Text(S.of(context)!.edit),
|
||||
actions: [
|
||||
IconButton(
|
||||
onPressed: () => _onDelete(context),
|
||||
onPressed: canDelete ? () => _onDelete(context) : null,
|
||||
icon: const Icon(Icons.delete),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -1,6 +1,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/database/tables/local_user_account.dart';
|
||||
import 'package:paperless_mobile/features/edit_label/cubit/edit_label_cubit.dart';
|
||||
import 'package:paperless_mobile/features/edit_label/view/edit_label_page.dart';
|
||||
|
||||
@@ -19,10 +20,12 @@ class EditCorrespondentPage extends StatelessWidget {
|
||||
return EditLabelPage<Correspondent>(
|
||||
label: correspondent,
|
||||
fromJsonT: Correspondent.fromJson,
|
||||
onSubmit: (context, label) =>
|
||||
context.read<EditLabelCubit>().replaceCorrespondent(label),
|
||||
onDelete: (context, label) =>
|
||||
context.read<EditLabelCubit>().removeCorrespondent(label),
|
||||
onSubmit: (context, label) => context.read<EditLabelCubit>().replaceCorrespondent(label),
|
||||
onDelete: (context, label) => context.read<EditLabelCubit>().removeCorrespondent(label),
|
||||
canDelete: LocalUserAccount.current.paperlessUser.hasPermission(
|
||||
PermissionAction.delete,
|
||||
PermissionTarget.correspondent,
|
||||
),
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'package:flutter/widgets.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/database/tables/local_user_account.dart';
|
||||
import 'package:paperless_mobile/features/edit_label/cubit/edit_label_cubit.dart';
|
||||
import 'package:paperless_mobile/features/edit_label/view/edit_label_page.dart';
|
||||
|
||||
@@ -18,10 +18,12 @@ class EditDocumentTypePage extends StatelessWidget {
|
||||
child: EditLabelPage<DocumentType>(
|
||||
label: documentType,
|
||||
fromJsonT: DocumentType.fromJson,
|
||||
onSubmit: (context, label) =>
|
||||
context.read<EditLabelCubit>().replaceDocumentType(label),
|
||||
onDelete: (context, label) =>
|
||||
context.read<EditLabelCubit>().removeDocumentType(label),
|
||||
onSubmit: (context, label) => context.read<EditLabelCubit>().replaceDocumentType(label),
|
||||
onDelete: (context, label) => context.read<EditLabelCubit>().removeDocumentType(label),
|
||||
canDelete: LocalUserAccount.current.paperlessUser.hasPermission(
|
||||
PermissionAction.delete,
|
||||
PermissionTarget.documentType,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,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/database/tables/local_user_account.dart';
|
||||
import 'package:paperless_mobile/features/edit_label/cubit/edit_label_cubit.dart';
|
||||
import 'package:paperless_mobile/features/edit_label/view/edit_label_page.dart';
|
||||
import 'package:paperless_mobile/features/labels/storage_path/view/widgets/storage_path_autofill_form_builder_field.dart';
|
||||
@@ -18,10 +19,12 @@ class EditStoragePathPage extends StatelessWidget {
|
||||
child: EditLabelPage<StoragePath>(
|
||||
label: storagePath,
|
||||
fromJsonT: StoragePath.fromJson,
|
||||
onSubmit: (context, label) =>
|
||||
context.read<EditLabelCubit>().replaceStoragePath(label),
|
||||
onDelete: (context, label) =>
|
||||
context.read<EditLabelCubit>().removeStoragePath(label),
|
||||
onSubmit: (context, label) => context.read<EditLabelCubit>().replaceStoragePath(label),
|
||||
onDelete: (context, label) => context.read<EditLabelCubit>().removeStoragePath(label),
|
||||
canDelete: LocalUserAccount.current.paperlessUser.hasPermission(
|
||||
PermissionAction.delete,
|
||||
PermissionTarget.storagePath,
|
||||
),
|
||||
additionalFields: [
|
||||
StoragePathAutofillFormBuilderField(
|
||||
name: StoragePath.pathKey,
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_form_builder/flutter_form_builder.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/database/tables/local_user_account.dart';
|
||||
import 'package:paperless_mobile/core/widgets/form_builder_fields/form_builder_color_picker.dart';
|
||||
import 'package:paperless_mobile/features/edit_label/cubit/edit_label_cubit.dart';
|
||||
import 'package:paperless_mobile/features/edit_label/view/edit_label_page.dart';
|
||||
@@ -21,10 +22,12 @@ class EditTagPage extends StatelessWidget {
|
||||
child: EditLabelPage<Tag>(
|
||||
label: tag,
|
||||
fromJsonT: Tag.fromJson,
|
||||
onSubmit: (context, label) =>
|
||||
context.read<EditLabelCubit>().replaceTag(label),
|
||||
onDelete: (context, label) =>
|
||||
context.read<EditLabelCubit>().removeTag(label),
|
||||
onSubmit: (context, label) => context.read<EditLabelCubit>().replaceTag(label),
|
||||
onDelete: (context, label) => context.read<EditLabelCubit>().removeTag(label),
|
||||
canDelete: LocalUserAccount.current.paperlessUser.hasPermission(
|
||||
PermissionAction.delete,
|
||||
PermissionTarget.tag,
|
||||
),
|
||||
additionalFields: [
|
||||
FormBuilderColorPickerField(
|
||||
initialValue: tag.color,
|
||||
|
||||
@@ -8,7 +8,6 @@ import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||
|
||||
import 'package:paperless_mobile/helpers/message_helpers.dart';
|
||||
import 'package:paperless_mobile/constants.dart';
|
||||
|
||||
class SubmitButtonConfig<T extends Label> {
|
||||
final Widget icon;
|
||||
|
||||
@@ -6,38 +6,26 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
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/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/database/tables/local_user_account.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';
|
||||
import 'package:paperless_mobile/features/document_scan/view/scanner_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/documents/cubit/documents_cubit.dart';
|
||||
import 'package:paperless_mobile/features/documents/view/pages/documents_page.dart';
|
||||
import 'package:paperless_mobile/features/home/view/route_description.dart';
|
||||
import 'package:paperless_mobile/features/inbox/cubit/inbox_cubit.dart';
|
||||
import 'package:paperless_mobile/features/inbox/view/pages/inbox_page.dart';
|
||||
import 'package:paperless_mobile/features/labels/cubit/label_cubit.dart';
|
||||
import 'package:paperless_mobile/features/labels/view/pages/labels_page.dart';
|
||||
import 'package:paperless_mobile/features/login/cubit/authentication_cubit.dart';
|
||||
import 'package:paperless_mobile/core/database/tables/local_user_account.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/sharing/share_intent_queue.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/message_helpers.dart';
|
||||
import 'package:receive_sharing_intent/receive_sharing_intent.dart';
|
||||
import 'package:responsive_builder/responsive_builder.dart';
|
||||
|
||||
@@ -196,7 +184,8 @@ class _HomePageState extends State<HomePage> with WidgetsBindingObserver {
|
||||
),
|
||||
label: S.of(context)!.documents,
|
||||
),
|
||||
if (LocalUserAccount.current.paperlessUser.hasPermission(UserPermissions.addDocument))
|
||||
if (LocalUserAccount.current.paperlessUser
|
||||
.hasPermission(PermissionAction.add, PermissionTarget.document))
|
||||
RouteDescription(
|
||||
icon: const Icon(Icons.document_scanner_outlined),
|
||||
selectedIcon: Icon(
|
||||
@@ -222,32 +211,31 @@ class _HomePageState extends State<HomePage> with WidgetsBindingObserver {
|
||||
label: S.of(context)!.inbox,
|
||||
badgeBuilder: (icon) => BlocBuilder<InboxCubit, InboxState>(
|
||||
builder: (context, state) {
|
||||
if (state.itemsInInboxCount > 0) {
|
||||
return Badge.count(
|
||||
count: state.itemsInInboxCount,
|
||||
child: icon,
|
||||
);
|
||||
}
|
||||
return icon;
|
||||
return Badge.count(
|
||||
isLabelVisible: state.itemsInInboxCount > 0,
|
||||
count: state.itemsInInboxCount,
|
||||
child: icon,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
];
|
||||
final routes = <Widget>[
|
||||
const DocumentsPage(),
|
||||
if (LocalUserAccount.current.paperlessUser.hasPermission(UserPermissions.addDocument))
|
||||
if (LocalUserAccount.current.paperlessUser
|
||||
.hasPermission(PermissionAction.add, PermissionTarget.document))
|
||||
const ScannerPage(),
|
||||
const LabelsPage(),
|
||||
const InboxPage(),
|
||||
];
|
||||
|
||||
return MultiBlocListener(
|
||||
listeners: [
|
||||
BlocListener<ConnectivityCubit, ConnectivityState>(
|
||||
//Only re-initialize data if the connectivity changed from not connected to connected
|
||||
// If app was started offline, load data once it comes back online.
|
||||
listenWhen: (previous, current) => current == ConnectivityState.connected,
|
||||
listener: (context, state) {
|
||||
_initializeData(context);
|
||||
context.read<LabelRepository>().initialize();
|
||||
context.read<SavedViewRepository>().initialize();
|
||||
},
|
||||
),
|
||||
BlocListener<TaskStatusCubit, TaskStatusState>(
|
||||
@@ -299,14 +287,4 @@ class _HomePageState extends State<HomePage> with WidgetsBindingObserver {
|
||||
setState(() => _currentIndex = index);
|
||||
}
|
||||
}
|
||||
|
||||
void _initializeData(BuildContext context) {
|
||||
Future.wait([
|
||||
context.read<LabelRepository>().initialize(),
|
||||
context.read<SavedViewRepository>().findAll(),
|
||||
]).onError<PaperlessServerException>((error, stackTrace) {
|
||||
showErrorMessage(context, error, stackTrace);
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import 'package:flutter/material.dart';
|
||||
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';
|
||||
@@ -45,9 +44,10 @@ class HomeRoute extends StatelessWidget {
|
||||
return GlobalSettingsBuilder(
|
||||
builder: (context, settings) {
|
||||
final currentLocalUserId = settings.currentLoggedInUser!;
|
||||
final apiVersion = ApiVersion(paperlessApiVersion);
|
||||
return MultiProvider(
|
||||
providers: [
|
||||
Provider.value(value: ApiVersion(paperlessApiVersion)),
|
||||
Provider.value(value: apiVersion),
|
||||
Provider<CacheManager>(
|
||||
create: (context) => CacheManager(
|
||||
Config(
|
||||
@@ -87,7 +87,7 @@ class HomeRoute extends StatelessWidget {
|
||||
apiVersion: paperlessApiVersion,
|
||||
),
|
||||
),
|
||||
if (paperlessApiVersion >= 3)
|
||||
if (apiVersion.hasMultiUserSupport)
|
||||
ProxyProvider<SessionManager, PaperlessUserApiV3>(
|
||||
update: (context, value, previous) => PaperlessUserApiV3Impl(
|
||||
value.client,
|
||||
@@ -98,7 +98,7 @@ class HomeRoute extends StatelessWidget {
|
||||
return MultiProvider(
|
||||
providers: [
|
||||
ProxyProvider<PaperlessLabelsApi, LabelRepository>(
|
||||
update: (context, value, previous) => LabelRepository(value)..initialize(),
|
||||
update: (context, value, previous) => LabelRepository(value),
|
||||
),
|
||||
ProxyProvider<PaperlessSavedViewsApi, SavedViewRepository>(
|
||||
update: (context, value, previous) => SavedViewRepository(value)..initialize(),
|
||||
|
||||
@@ -3,6 +3,5 @@ class ApiVersion {
|
||||
|
||||
ApiVersion(this.version);
|
||||
|
||||
bool get supportsPermissions => version >= 3;
|
||||
bool get hasMultiUserSupport => version >= 3;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hydrated_bloc/hydrated_bloc.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
||||
import 'package:paperless_mobile/core/repository/saved_view_repository.dart';
|
||||
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
||||
import 'package:paperless_mobile/features/login/cubit/authentication_cubit.dart';
|
||||
import 'package:paperless_mobile/core/database/tables/global_settings.dart';
|
||||
|
||||
import 'package:paperless_mobile/features/settings/view/widgets/user_settings_builder.dart';
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/exception/server_message_exception.dart';
|
||||
import 'package:paperless_mobile/core/widgets/dialog_utils/dialog_cancel_button.dart';
|
||||
import 'package:paperless_mobile/core/widgets/dialog_utils/dialog_confirm_button.dart';
|
||||
import 'package:paperless_mobile/core/widgets/hint_card.dart';
|
||||
@@ -10,7 +11,6 @@ import 'package:paperless_mobile/extensions/dart_extensions.dart';
|
||||
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
||||
import 'package:paperless_mobile/features/app_drawer/view/app_drawer.dart';
|
||||
import 'package:paperless_mobile/features/document_search/view/sliver_search_bar.dart';
|
||||
import 'package:paperless_mobile/features/documents/view/widgets/placeholder/documents_list_loading_widget.dart';
|
||||
import 'package:paperless_mobile/features/inbox/cubit/inbox_cubit.dart';
|
||||
import 'package:paperless_mobile/features/inbox/view/widgets/inbox_empty_widget.dart';
|
||||
import 'package:paperless_mobile/features/inbox/view/widgets/inbox_item.dart';
|
||||
@@ -26,10 +26,8 @@ class InboxPage extends StatefulWidget {
|
||||
State<InboxPage> createState() => _InboxPageState();
|
||||
}
|
||||
|
||||
class _InboxPageState extends State<InboxPage>
|
||||
with DocumentPagingViewMixin<InboxPage, InboxCubit> {
|
||||
final SliverOverlapAbsorberHandle searchBarHandle =
|
||||
SliverOverlapAbsorberHandle();
|
||||
class _InboxPageState extends State<InboxPage> with DocumentPagingViewMixin<InboxPage, InboxCubit> {
|
||||
final SliverOverlapAbsorberHandle searchBarHandle = SliverOverlapAbsorberHandle();
|
||||
|
||||
@override
|
||||
final pagingScrollController = ScrollController();
|
||||
@@ -80,8 +78,7 @@ class _InboxPageState extends State<InboxPage>
|
||||
} else if (state.documents.isEmpty) {
|
||||
return Center(
|
||||
child: InboxEmptyWidget(
|
||||
emptyStateRefreshIndicatorKey:
|
||||
_emptyStateRefreshIndicatorKey,
|
||||
emptyStateRefreshIndicatorKey: _emptyStateRefreshIndicatorKey,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
@@ -92,8 +89,7 @@ class _InboxPageState extends State<InboxPage>
|
||||
SliverToBoxAdapter(
|
||||
child: HintCard(
|
||||
show: !state.isHintAcknowledged,
|
||||
hintText:
|
||||
S.of(context)!.swipeLeftToMarkADocumentAsSeen,
|
||||
hintText: S.of(context)!.swipeLeftToMarkADocumentAsSeen,
|
||||
onHintAcknowledged: () =>
|
||||
context.read<InboxCubit>().acknowledgeHint(),
|
||||
),
|
||||
@@ -108,13 +104,10 @@ class _InboxPageState extends State<InboxPage>
|
||||
child: Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: ClipRRect(
|
||||
borderRadius:
|
||||
BorderRadius.circular(32.0),
|
||||
borderRadius: BorderRadius.circular(32.0),
|
||||
child: Text(
|
||||
entry.key,
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodySmall,
|
||||
style: Theme.of(context).textTheme.bodySmall,
|
||||
textAlign: TextAlign.center,
|
||||
).padded(),
|
||||
),
|
||||
@@ -182,7 +175,7 @@ class _InboxPageState extends State<InboxPage>
|
||||
],
|
||||
).padded(),
|
||||
confirmDismiss: (_) => _onItemDismissed(doc),
|
||||
key: UniqueKey(),
|
||||
key: ValueKey(doc.id),
|
||||
child: InboxItem(document: doc),
|
||||
);
|
||||
}
|
||||
@@ -227,14 +220,15 @@ class _InboxPageState extends State<InboxPage>
|
||||
return true;
|
||||
} on PaperlessServerException catch (error, stackTrace) {
|
||||
showErrorMessage(context, error, stackTrace);
|
||||
return false;
|
||||
} on ServerMessageException catch (error) {
|
||||
showGenericError(context, error.message);
|
||||
} catch (error) {
|
||||
showErrorMessage(
|
||||
context,
|
||||
const PaperlessServerException.unknown(),
|
||||
);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Future<void> _onUndoMarkAsSeen(
|
||||
@@ -242,9 +236,7 @@ class _InboxPageState extends State<InboxPage>
|
||||
Iterable<int> removedTags,
|
||||
) async {
|
||||
try {
|
||||
await context
|
||||
.read<InboxCubit>()
|
||||
.undoRemoveFromInbox(document, removedTags);
|
||||
await context.read<InboxCubit>().undoRemoveFromInbox(document, removedTags);
|
||||
} on PaperlessServerException catch (error, stackTrace) {
|
||||
showErrorMessage(context, error, stackTrace);
|
||||
}
|
||||
|
||||
@@ -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/database/tables/local_user_account.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';
|
||||
@@ -12,8 +13,6 @@ import 'package:paperless_mobile/features/labels/tags/view/widgets/tags_widget.d
|
||||
import 'package:paperless_mobile/features/labels/view/widgets/label_text.dart';
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||
|
||||
import 'package:paperless_mobile/routes/document_details_route.dart';
|
||||
|
||||
class InboxItem extends StatefulWidget {
|
||||
static const a4AspectRatio = 1 / 1.4142;
|
||||
|
||||
@@ -108,8 +107,8 @@ class _InboxItemState extends State<InboxItem> {
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 56,
|
||||
LimitedBox(
|
||||
maxHeight: 56,
|
||||
child: _buildActions(context),
|
||||
),
|
||||
],
|
||||
@@ -121,58 +120,46 @@ class _InboxItemState extends State<InboxItem> {
|
||||
}
|
||||
|
||||
Widget _buildActions(BuildContext context) {
|
||||
final canEdit = LocalUserAccount.current.paperlessUser
|
||||
.hasPermission(PermissionAction.change, PermissionTarget.document);
|
||||
final canDelete = LocalUserAccount.current.paperlessUser
|
||||
.hasPermission(PermissionAction.delete, PermissionTarget.document);
|
||||
final chipShape = RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(32),
|
||||
);
|
||||
final actions = [
|
||||
_buildAssignAsnAction(chipShape, context),
|
||||
const SizedBox(width: 8.0),
|
||||
ColoredChipWrapper(
|
||||
child: ActionChip(
|
||||
avatar: const Icon(Icons.delete_outline),
|
||||
shape: chipShape,
|
||||
label: Text(S.of(context)!.deleteDocument),
|
||||
onPressed: () async {
|
||||
final shouldDelete = await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (context) => DeleteDocumentConfirmationDialog(document: widget.document),
|
||||
) ??
|
||||
false;
|
||||
if (shouldDelete) {
|
||||
context.read<InboxCubit>().delete(widget.document);
|
||||
}
|
||||
},
|
||||
if (canEdit) _buildAssignAsnAction(chipShape, context),
|
||||
if (canEdit && canDelete) const SizedBox(width: 8.0),
|
||||
if (canDelete)
|
||||
ColoredChipWrapper(
|
||||
child: ActionChip(
|
||||
avatar: const Icon(Icons.delete_outline),
|
||||
shape: chipShape,
|
||||
label: Text(S.of(context)!.deleteDocument),
|
||||
onPressed: () async {
|
||||
final shouldDelete = await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (context) =>
|
||||
DeleteDocumentConfirmationDialog(document: widget.document),
|
||||
) ??
|
||||
false;
|
||||
if (shouldDelete) {
|
||||
context.read<InboxCubit>().delete(widget.document);
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
];
|
||||
|
||||
// return FutureBuilder<FieldSuggestions>(
|
||||
// future: _fieldSuggestions,
|
||||
// builder: (context, snapshot) {
|
||||
// List<Widget>? suggestions;
|
||||
// if (!snapshot.hasData) {
|
||||
// suggestions = [
|
||||
// const SizedBox(width: 4),
|
||||
// ];
|
||||
// } else {
|
||||
// if (snapshot.data!.hasSuggestions) {
|
||||
// suggestions = [
|
||||
// const SizedBox(width: 4),
|
||||
// ..._buildSuggestionChips(
|
||||
// chipShape,
|
||||
// snapshot.data!,
|
||||
// context.watch<InboxCubit>().state,
|
||||
// ),
|
||||
// ];
|
||||
// }
|
||||
// }
|
||||
if (actions.isEmpty) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
return Row(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Icon(Icons.bolt_outlined),
|
||||
const Icon(Icons.auto_awesome),
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: 50,
|
||||
@@ -229,6 +216,7 @@ class _InboxItemState extends State<InboxItem> {
|
||||
setState(() {
|
||||
_isAsnAssignLoading = true;
|
||||
});
|
||||
|
||||
context.read<InboxCubit>().assignAsn(widget.document).whenComplete(
|
||||
() => setState(() => _isAsnAssignLoading = false),
|
||||
);
|
||||
|
||||
@@ -3,7 +3,6 @@ import 'package:paperless_mobile/core/widgets/shimmer_placeholder.dart';
|
||||
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
||||
import 'package:paperless_mobile/features/documents/view/widgets/placeholder/tags_placeholder.dart';
|
||||
import 'package:paperless_mobile/features/documents/view/widgets/placeholder/text_placeholder.dart';
|
||||
import 'package:paperless_mobile/features/inbox/view/widgets/inbox_item.dart';
|
||||
|
||||
class InboxListLoadingWidget extends StatelessWidget {
|
||||
const InboxListLoadingWidget({super.key});
|
||||
@@ -48,10 +47,10 @@ class InboxListLoadingWidget extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Flexible(
|
||||
const Flexible(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: const [
|
||||
children: [
|
||||
Spacer(),
|
||||
TextPlaceholder(length: 200, fontSize: 14),
|
||||
Spacer(),
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:animations/animations.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_form_builder/flutter_form_builder.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/database/tables/local_user_account.dart';
|
||||
import 'package:paperless_mobile/core/workarounds/colored_chip.dart';
|
||||
import 'package:paperless_mobile/features/labels/tags/view/widgets/fullscreen_tags_form.dart';
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||
@@ -72,7 +71,11 @@ class TagsFormField extends StatelessWidget {
|
||||
onSubmit: closeForm,
|
||||
initialValue: field.value,
|
||||
allowOnlySelection: allowOnlySelection,
|
||||
allowCreation: allowCreation,
|
||||
allowCreation: allowCreation &&
|
||||
LocalUserAccount.current.paperlessUser.hasPermission(
|
||||
PermissionAction.add,
|
||||
PermissionTarget.tag,
|
||||
),
|
||||
allowExclude: allowExclude,
|
||||
),
|
||||
onClosed: (data) {
|
||||
|
||||
@@ -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/database/tables/local_user_account.dart';
|
||||
import 'package:paperless_mobile/core/delegate/customizable_sliver_persistent_header_delegate.dart';
|
||||
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
||||
import 'package:paperless_mobile/core/widgets/material/colored_tab_bar.dart';
|
||||
@@ -16,7 +17,6 @@ import 'package:paperless_mobile/features/edit_label/view/impl/edit_document_typ
|
||||
import 'package:paperless_mobile/features/edit_label/view/impl/edit_storage_path_page.dart';
|
||||
import 'package:paperless_mobile/features/edit_label/view/impl/edit_tag_page.dart';
|
||||
import 'package:paperless_mobile/features/labels/cubit/label_cubit.dart';
|
||||
import 'package:paperless_mobile/features/labels/cubit/label_cubit_mixin.dart';
|
||||
import 'package:paperless_mobile/features/labels/view/widgets/label_tab_view.dart';
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||
|
||||
@@ -148,6 +148,10 @@ class _LabelsPageState extends State<LabelsPage> with SingleTickerProviderStateM
|
||||
correspondent: IdQueryParameter.fromId(label.id!),
|
||||
pageSize: label.documentCount ?? 0,
|
||||
),
|
||||
canEdit: LocalUserAccount.current.paperlessUser.hasPermission(
|
||||
PermissionAction.change, PermissionTarget.correspondent),
|
||||
canAddNew: LocalUserAccount.current.paperlessUser.hasPermission(
|
||||
PermissionAction.add, PermissionTarget.correspondent),
|
||||
onEdit: _openEditCorrespondentPage,
|
||||
emptyStateActionButtonLabel: S.of(context)!.addNewCorrespondent,
|
||||
emptyStateDescription: S.of(context)!.noCorrespondentsSetUp,
|
||||
@@ -169,6 +173,10 @@ class _LabelsPageState extends State<LabelsPage> with SingleTickerProviderStateM
|
||||
documentType: IdQueryParameter.fromId(label.id!),
|
||||
pageSize: label.documentCount ?? 0,
|
||||
),
|
||||
canEdit: LocalUserAccount.current.paperlessUser.hasPermission(
|
||||
PermissionAction.change, PermissionTarget.documentType),
|
||||
canAddNew: LocalUserAccount.current.paperlessUser.hasPermission(
|
||||
PermissionAction.add, PermissionTarget.documentType),
|
||||
onEdit: _openEditDocumentTypePage,
|
||||
emptyStateActionButtonLabel: S.of(context)!.addNewDocumentType,
|
||||
emptyStateDescription: S.of(context)!.noDocumentTypesSetUp,
|
||||
@@ -190,6 +198,10 @@ class _LabelsPageState extends State<LabelsPage> with SingleTickerProviderStateM
|
||||
tags: TagsQuery.ids(include: [label.id!]),
|
||||
pageSize: label.documentCount ?? 0,
|
||||
),
|
||||
canEdit: LocalUserAccount.current.paperlessUser
|
||||
.hasPermission(PermissionAction.change, PermissionTarget.tag),
|
||||
canAddNew: LocalUserAccount.current.paperlessUser
|
||||
.hasPermission(PermissionAction.add, PermissionTarget.tag),
|
||||
onEdit: _openEditTagPage,
|
||||
leadingBuilder: (t) => CircleAvatar(
|
||||
backgroundColor: t.color,
|
||||
@@ -221,6 +233,10 @@ class _LabelsPageState extends State<LabelsPage> with SingleTickerProviderStateM
|
||||
storagePath: IdQueryParameter.fromId(label.id!),
|
||||
pageSize: label.documentCount ?? 0,
|
||||
),
|
||||
canEdit: LocalUserAccount.current.paperlessUser.hasPermission(
|
||||
PermissionAction.change, PermissionTarget.storagePath),
|
||||
canAddNew: LocalUserAccount.current.paperlessUser.hasPermission(
|
||||
PermissionAction.add, PermissionTarget.storagePath),
|
||||
contentBuilder: (path) => Text(path.path),
|
||||
emptyStateActionButtonLabel: S.of(context)!.addNewStoragePath,
|
||||
emptyStateDescription: S.of(context)!.noStoragePathsSetUp,
|
||||
|
||||
@@ -16,6 +16,7 @@ class FullscreenLabelForm<T extends Label> extends StatefulWidget {
|
||||
final String? addNewLabelText;
|
||||
final bool autofocus;
|
||||
final bool allowSelectUnassigned;
|
||||
final bool canCreateNewLabel;
|
||||
|
||||
FullscreenLabelForm({
|
||||
super.key,
|
||||
@@ -29,6 +30,7 @@ class FullscreenLabelForm<T extends Label> extends StatefulWidget {
|
||||
this.addNewLabelText,
|
||||
this.autofocus = true,
|
||||
this.allowSelectUnassigned = true,
|
||||
required this.canCreateNewLabel,
|
||||
}) : assert(
|
||||
!(initialValue?.isOnlyAssigned() ?? false) || showAnyAssignedOption,
|
||||
),
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:animations/animations.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -28,6 +26,7 @@ class LabelFormField<T extends Label> extends StatelessWidget {
|
||||
final List<T> suggestions;
|
||||
final String? addLabelText;
|
||||
final bool allowSelectUnassigned;
|
||||
final bool canCreateNewLabel;
|
||||
|
||||
const LabelFormField({
|
||||
Key? key,
|
||||
@@ -44,6 +43,7 @@ class LabelFormField<T extends Label> extends StatelessWidget {
|
||||
this.suggestions = const [],
|
||||
this.addLabelText,
|
||||
required this.allowSelectUnassigned,
|
||||
required this.canCreateNewLabel,
|
||||
}) : super(key: key);
|
||||
|
||||
String _buildText(BuildContext context, IdQueryParameter? value) {
|
||||
@@ -103,6 +103,7 @@ class LabelFormField<T extends Label> extends StatelessWidget {
|
||||
),
|
||||
openBuilder: (context, closeForm) => FullscreenLabelForm<T>(
|
||||
allowSelectUnassigned: allowSelectUnassigned,
|
||||
canCreateNewLabel: canCreateNewLabel,
|
||||
addNewLabelText: addLabelText,
|
||||
leadingIcon: prefixIcon,
|
||||
onCreateNewLabel: addLabelPageBuilder != null
|
||||
|
||||
@@ -1,19 +1,14 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.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/features/linked_documents/cubit/linked_documents_cubit.dart';
|
||||
import 'package:paperless_mobile/features/linked_documents/view/linked_documents_page.dart';
|
||||
import 'package:paperless_mobile/core/database/tables/local_user_account.dart';
|
||||
import 'package:paperless_mobile/core/database/tables/global_settings.dart';
|
||||
import 'package:paperless_mobile/core/navigation/push_routes.dart';
|
||||
import 'package:paperless_mobile/helpers/format_helpers.dart';
|
||||
|
||||
class LabelItem<T extends Label> extends StatelessWidget {
|
||||
final T label;
|
||||
final String name;
|
||||
final Widget content;
|
||||
final void Function(T) onOpenEditPage;
|
||||
final void Function(T)? onOpenEditPage;
|
||||
final DocumentFilter Function(T) filterBuilder;
|
||||
final Widget? leading;
|
||||
|
||||
@@ -33,38 +28,25 @@ class LabelItem<T extends Label> extends StatelessWidget {
|
||||
title: Text(name),
|
||||
subtitle: content,
|
||||
leading: leading,
|
||||
onTap: () => onOpenEditPage(label),
|
||||
onTap: onOpenEditPage != null ? () => onOpenEditPage!(label) : null,
|
||||
trailing: _buildReferencedDocumentsWidget(context),
|
||||
isThreeLine: true,
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildReferencedDocumentsWidget(BuildContext context) {
|
||||
final canOpen = (label.documentCount ?? 0) > 0 &&
|
||||
LocalUserAccount.current.paperlessUser
|
||||
.hasPermission(PermissionAction.view, PermissionTarget.document);
|
||||
return TextButton.icon(
|
||||
label: const Icon(Icons.link),
|
||||
icon: Text(formatMaxCount(label.documentCount)),
|
||||
onPressed: (label.documentCount ?? 0) == 0
|
||||
? null
|
||||
: () {
|
||||
final currentUser = Hive.box<GlobalSettings>(HiveBoxes.globalSettings)
|
||||
.getValue()!
|
||||
.currentLoggedInUser!;
|
||||
onPressed: canOpen
|
||||
? () {
|
||||
final filter = filterBuilder(label);
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => BlocProvider(
|
||||
create: (context) => LinkedDocumentsCubit(
|
||||
filter,
|
||||
context.read(),
|
||||
context.read(),
|
||||
context.read(),
|
||||
),
|
||||
child: const LinkedDocumentsPage(),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
pushLinkedDocumentsView(context, filter: filter);
|
||||
}
|
||||
: null,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,9 @@ class LabelTabView<T extends Label> extends StatelessWidget {
|
||||
final Map<int, T> labels;
|
||||
final DocumentFilter Function(Label) filterBuilder;
|
||||
final void Function(T) onEdit;
|
||||
final bool canEdit;
|
||||
final void Function() onAddNew;
|
||||
final bool canAddNew;
|
||||
|
||||
/// Displayed as the subtitle of the [ListTile]
|
||||
final Widget Function(T)? contentBuilder;
|
||||
@@ -33,6 +35,8 @@ class LabelTabView<T extends Label> extends StatelessWidget {
|
||||
required this.onAddNew,
|
||||
required this.emptyStateActionButtonLabel,
|
||||
required this.labels,
|
||||
required this.canEdit,
|
||||
required this.canAddNew,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -54,7 +58,7 @@ class LabelTabView<T extends Label> extends StatelessWidget {
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
TextButton(
|
||||
onPressed: onAddNew,
|
||||
onPressed: canAddNew ? onAddNew : null,
|
||||
child: Text(emptyStateActionButtonLabel),
|
||||
),
|
||||
].padded(),
|
||||
@@ -70,14 +74,11 @@ class LabelTabView<T extends Label> extends StatelessWidget {
|
||||
name: l.name,
|
||||
content: contentBuilder?.call(l) ??
|
||||
Text(
|
||||
translateMatchingAlgorithmName(
|
||||
context, l.matchingAlgorithm) +
|
||||
((l.match?.isNotEmpty ?? false)
|
||||
? ": ${l.match}"
|
||||
: ""),
|
||||
translateMatchingAlgorithmName(context, l.matchingAlgorithm) +
|
||||
((l.match?.isNotEmpty ?? false) ? ": ${l.match}" : ""),
|
||||
maxLines: 2,
|
||||
),
|
||||
onOpenEditPage: onEdit,
|
||||
onOpenEditPage: canEdit ? onEdit : null,
|
||||
filterBuilder: filterBuilder,
|
||||
leading: leadingBuilder?.call(l),
|
||||
label: l,
|
||||
|
||||
@@ -20,6 +20,5 @@ class LabelText<T extends Label> extends StatelessWidget {
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
);
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import 'package:paperless_mobile/features/linked_documents/cubit/linked_document
|
||||
import 'package:paperless_mobile/features/paged_document_view/view/document_paging_view_mixin.dart';
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||
|
||||
import 'package:paperless_mobile/routes/document_details_route.dart';
|
||||
|
||||
class LinkedDocumentsPage extends StatefulWidget {
|
||||
const LinkedDocumentsPage({super.key});
|
||||
|
||||
@@ -179,6 +179,7 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
final userCredentialsBox = await _getUserCredentialsBox();
|
||||
final authentication = userCredentialsBox.get(globalSettings.currentLoggedInUser!);
|
||||
await userCredentialsBox.close();
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
import 'package:paperless_mobile/core/config/hive/hive_config.dart';
|
||||
import 'package:paperless_mobile/features/login/model/client_certificate.dart';
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:hive_flutter/adapters.dart';
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
|
||||
class ClientCertificateFormModel {
|
||||
|
||||
@@ -4,12 +4,9 @@ import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_form_builder/flutter_form_builder.dart';
|
||||
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
||||
import 'package:paperless_mobile/features/login/model/client_certificate.dart';
|
||||
import 'package:paperless_mobile/features/login/model/client_certificate_form_model.dart';
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||
|
||||
import 'package:paperless_mobile/constants.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
|
||||
import 'obscured_input_text_form_field.dart';
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_form_builder/flutter_form_builder.dart';
|
||||
@@ -49,6 +48,7 @@ class _ServerAddressFormFieldState extends State<ServerAddressFormField> {
|
||||
if (!RegExp(r"https?://.*").hasMatch(value!)) {
|
||||
return S.of(context)!.serverAddressMustIncludeAScheme;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
decoration: InputDecoration(
|
||||
hintText: "http://192.168.1.50:8000",
|
||||
|
||||
@@ -39,6 +39,7 @@ class _UserCredentialsFormFieldState extends State<UserCredentialsFormField> {
|
||||
if (value?.trim().isEmpty ?? true) {
|
||||
return S.of(context)!.usernameMustNotBeEmpty;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
autofillHints: const [AutofillHints.username],
|
||||
decoration: InputDecoration(
|
||||
@@ -56,6 +57,7 @@ class _UserCredentialsFormFieldState extends State<UserCredentialsFormField> {
|
||||
if (value?.trim().isEmpty ?? true) {
|
||||
return S.of(context)!.passwordMustNotBeEmpty;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
].map((child) => child.padded()).toList(),
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_form_builder/flutter_form_builder.dart';
|
||||
import 'package:paperless_mobile/core/service/connectivity_status_service.dart';
|
||||
import 'package:paperless_mobile/core/widgets/paperless_logo.dart';
|
||||
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
||||
import 'package:paperless_mobile/features/login/model/client_certificate.dart';
|
||||
import 'package:paperless_mobile/features/login/model/client_certificate_form_model.dart';
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
import 'package:open_filex/open_filex.dart';
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
|
||||
///
|
||||
|
||||
@@ -3,7 +3,6 @@ import 'dart:async';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
||||
import 'package:paperless_mobile/core/repository/saved_view_repository.dart';
|
||||
|
||||
part 'saved_view_state.dart';
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:hive/hive.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/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';
|
||||
import 'package:paperless_mobile/features/saved_view_details/view/saved_view_details_page.dart';
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||
|
||||
class SavedViewList extends StatelessWidget {
|
||||
@@ -23,7 +17,7 @@ class SavedViewList extends StatelessWidget {
|
||||
builder: (context, state) {
|
||||
return state.when(
|
||||
initial: () => SliverToBoxAdapter(child: Container()),
|
||||
loading: () => SliverToBoxAdapter(
|
||||
loading: () => const SliverToBoxAdapter(
|
||||
child: Center(
|
||||
child: Text("Saved views loading..."), //TODO: INTL
|
||||
),
|
||||
@@ -55,7 +49,7 @@ class SavedViewList extends StatelessWidget {
|
||||
),
|
||||
);
|
||||
},
|
||||
error: () => Center(
|
||||
error: () => const Center(
|
||||
child: Text(
|
||||
"An error occurred while trying to load the saved views.",
|
||||
),
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import 'package:hydrated_bloc/hydrated_bloc.dart';
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/database/tables/local_user_app_state.dart';
|
||||
import 'package:paperless_mobile/core/notifier/document_changed_notifier.dart';
|
||||
|
||||
@@ -9,7 +9,6 @@ import 'package:paperless_mobile/features/documents/view/widgets/selection/confi
|
||||
import 'package:paperless_mobile/features/documents/view/widgets/selection/view_type_selection_widget.dart';
|
||||
import 'package:paperless_mobile/features/paged_document_view/view/document_paging_view_mixin.dart';
|
||||
import 'package:paperless_mobile/features/saved_view_details/cubit/saved_view_details_cubit.dart';
|
||||
import 'package:paperless_mobile/routes/document_details_route.dart';
|
||||
|
||||
class SavedViewDetailsPage extends StatefulWidget {
|
||||
final Future<void> Function(SavedView savedView) onDelete;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:hive_flutter/adapters.dart';
|
||||
import 'package:paperless_mobile/core/config/hive/hive_config.dart';
|
||||
import 'package:paperless_mobile/core/database/tables/global_settings.dart';
|
||||
@@ -49,7 +48,6 @@ class ManageAccountsPage extends StatelessWidget {
|
||||
children: [
|
||||
_buildAccountTile(context, globalSettings.currentLoggedInUser!,
|
||||
box.get(globalSettings.currentLoggedInUser!)!, globalSettings),
|
||||
// if (otherAccounts.isNotEmpty) Text("Other accounts"),
|
||||
Column(
|
||||
children: [
|
||||
for (int index = 0; index < otherAccounts.length; index++)
|
||||
@@ -69,17 +67,11 @@ class ManageAccountsPage extends StatelessWidget {
|
||||
_onAddAccount(context, globalSettings.currentLoggedInUser!);
|
||||
},
|
||||
),
|
||||
Consumer<ApiVersion>(
|
||||
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();
|
||||
},
|
||||
)
|
||||
if (context.watch<ApiVersion>().hasMultiUserSupport)
|
||||
const ListTile(
|
||||
leading: Icon(Icons.admin_panel_settings),
|
||||
title: Text("Manage permissions"), //TODO: INTL
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
@@ -106,9 +98,7 @@ class ManageAccountsPage extends StatelessWidget {
|
||||
if (account.paperlessUser.fullName != null) Text(account.paperlessUser.fullName!),
|
||||
Text(
|
||||
account.serverUrl.replaceFirst(RegExp(r'https://?'), ''),
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
style: TextStyle(color: theme.colorScheme.primary),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -10,10 +10,10 @@ class SecuritySettingsPage extends StatelessWidget {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(S.of(context)!.security),
|
||||
actions: [
|
||||
actions: const [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: const Icon(Icons.person_outline),
|
||||
padding: EdgeInsets.all(16.0),
|
||||
child: Icon(Icons.person_outline),
|
||||
)
|
||||
],
|
||||
),
|
||||
|
||||
@@ -13,9 +13,9 @@ class ClearCacheSetting extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListTile(
|
||||
title: Text("Clear downloaded files"), //TODO: INTL
|
||||
title: const Text("Clear downloaded files"), //TODO: INTL
|
||||
subtitle:
|
||||
Text("Deletes all files downloaded from this app."), //TODO: INTL
|
||||
const Text("Deletes all files downloaded from this app."), //TODO: INTL
|
||||
onTap: () async {
|
||||
final dir = await FileService.downloadsDirectory;
|
||||
final deletedSize = _dirSize(dir);
|
||||
@@ -36,8 +36,8 @@ class ClearDownloadsSetting extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListTile(
|
||||
title: Text("Clear downloads"), //TODO: INTL
|
||||
subtitle: Text(
|
||||
title: const Text("Clear downloads"), //TODO: INTL
|
||||
subtitle: const Text(
|
||||
"Remove downloaded files, scans and clear the cache's content"), //TODO: INTL
|
||||
onTap: () {
|
||||
FileService.documentsDirectory;
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:hive_flutter/adapters.dart';
|
||||
import 'package:paperless_mobile/constants.dart';
|
||||
import 'package:paperless_mobile/core/config/hive/hive_config.dart';
|
||||
import 'package:paperless_mobile/core/translation/color_scheme_option_localization_mapper.dart';
|
||||
import 'package:paperless_mobile/core/widgets/hint_card.dart';
|
||||
import 'package:paperless_mobile/core/database/tables/global_settings.dart';
|
||||
import 'package:paperless_mobile/features/settings/model/color_scheme_option.dart';
|
||||
import 'package:paperless_mobile/features/settings/view/widgets/global_settings_builder.dart';
|
||||
import 'package:paperless_mobile/features/settings/view/widgets/radio_settings_dialog.dart';
|
||||
@@ -69,7 +65,7 @@ class ColorSchemeOptionSetting extends StatelessWidget {
|
||||
|
||||
bool _isBelowAndroid12() {
|
||||
if (Platform.isAndroid) {
|
||||
final int version = int.tryParse(androidInfo!.version.release ?? '0') ?? 0;
|
||||
final int version = int.tryParse(androidInfo!.version.release) ?? 0;
|
||||
return version < 12;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/src/widgets/framework.dart';
|
||||
import 'package:flutter/src/widgets/placeholder.dart';
|
||||
import 'package:hive_flutter/adapters.dart';
|
||||
import 'package:paperless_mobile/core/config/hive/hive_config.dart';
|
||||
import 'package:paperless_mobile/core/database/tables/global_settings.dart';
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:paperless_mobile/core/widgets/dialog_utils/dialog_cancel_button.dart';
|
||||
import 'package:paperless_mobile/core/widgets/dialog_utils/dialog_confirm_button.dart';
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||
|
||||
class RadioSettingsDialog<T> extends StatefulWidget {
|
||||
final List<RadioOption<T>> options;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:paperless_mobile/features/settings/view/widgets/global_settings_builder.dart';
|
||||
import 'package:paperless_mobile/features/settings/view/widgets/radio_settings_dialog.dart';
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/database/tables/local_user_account.dart';
|
||||
import 'package:paperless_mobile/core/repository/user_repository.dart';
|
||||
|
||||
class UserAvatar extends StatelessWidget {
|
||||
final String userId;
|
||||
|
||||
@@ -3,7 +3,6 @@ import 'package:hive_flutter/adapters.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/database/tables/global_settings.dart';
|
||||
import 'package:paperless_mobile/core/database/tables/local_user_settings.dart';
|
||||
|
||||
class UserAccountBuilder extends StatelessWidget {
|
||||
final Widget Function(
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import 'dart:collection';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:receive_sharing_intent/receive_sharing_intent.dart';
|
||||
|
||||
@@ -2,9 +2,7 @@ import 'dart:developer';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/service/github_issue_service.dart';
|
||||
import 'package:paperless_mobile/core/translation/error_code_localization_mapper.dart';
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||
|
||||
class SnackBarActionConfig {
|
||||
final String label;
|
||||
@@ -67,13 +65,13 @@ void showGenericError(
|
||||
showSnackBar(
|
||||
context,
|
||||
error.toString(),
|
||||
action: SnackBarActionConfig(
|
||||
label: S.of(context)!.report,
|
||||
onPressed: () => GithubIssueService.createIssueFromError(
|
||||
context,
|
||||
stackTrace: stackTrace,
|
||||
),
|
||||
),
|
||||
// action: SnackBarActionConfig(
|
||||
// label: S.of(context)!.report,
|
||||
// onPressed: () => GithubIssueService.createIssueFromError(
|
||||
// context,
|
||||
// stackTrace: stackTrace,
|
||||
// ),
|
||||
// ),
|
||||
);
|
||||
log(
|
||||
"An error has occurred.",
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:connectivity_plus/connectivity_plus.dart';
|
||||
@@ -56,10 +57,8 @@ String get defaultPreferredLocaleSubtag {
|
||||
|
||||
Future<void> _initHive() async {
|
||||
await Hive.initFlutter();
|
||||
// //TODO: REMOVE!
|
||||
// await getApplicationDocumentsDirectory().then((value) => value.delete(recursive: true));
|
||||
|
||||
registerHiveAdapters();
|
||||
// await getApplicationDocumentsDirectory().then((value) => value.deleteSync(recursive: true));
|
||||
await Hive.openBox<LocalUserAccount>(HiveBoxes.localUserAccount);
|
||||
await Hive.openBox<LocalUserAppState>(HiveBoxes.localUserAppState);
|
||||
final globalSettingsBox = await Hive.openBox<GlobalSettings>(HiveBoxes.globalSettings);
|
||||
@@ -126,9 +125,7 @@ void main() async {
|
||||
providers: [
|
||||
ChangeNotifierProvider.value(value: sessionManager),
|
||||
Provider<LocalAuthenticationService>.value(value: localAuthService),
|
||||
Provider<ConnectivityStatusService>.value(
|
||||
value: connectivityStatusService,
|
||||
),
|
||||
Provider<ConnectivityStatusService>.value(value: connectivityStatusService),
|
||||
Provider<LocalNotificationService>.value(value: localNotificationService),
|
||||
Provider.value(value: DocumentChangedNotifier()),
|
||||
],
|
||||
@@ -136,12 +133,7 @@ void main() async {
|
||||
providers: [
|
||||
BlocProvider<ConnectivityCubit>.value(value: connectivityCubit),
|
||||
BlocProvider(
|
||||
create: (context) => AuthenticationCubit(
|
||||
localAuthService,
|
||||
apiFactory,
|
||||
sessionManager,
|
||||
),
|
||||
child: Container(),
|
||||
create: (context) => AuthenticationCubit(localAuthService, apiFactory, sessionManager),
|
||||
)
|
||||
],
|
||||
child: PaperlessMobileEntrypoint(
|
||||
@@ -215,6 +207,7 @@ class AuthenticationWrapper extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _AuthenticationWrapperState extends State<AuthenticationWrapper> {
|
||||
late final StreamSubscription _shareMediaSubscription;
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
@@ -223,6 +216,12 @@ class _AuthenticationWrapperState extends State<AuthenticationWrapper> {
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_shareMediaSubscription.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
@@ -233,7 +232,8 @@ class _AuthenticationWrapperState extends State<AuthenticationWrapper> {
|
||||
}
|
||||
initializeDateFormatting();
|
||||
// For sharing files coming from outside the app while the app is still opened
|
||||
ReceiveSharingIntent.getMediaStream().listen(ShareIntentQueue.instance.addAll);
|
||||
_shareMediaSubscription =
|
||||
ReceiveSharingIntent.getMediaStream().listen(ShareIntentQueue.instance.addAll);
|
||||
// For sharing files coming from outside the app while the app is closed
|
||||
ReceiveSharingIntent.getInitialMedia().then(ShareIntentQueue.instance.addAll);
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ ThemeData buildTheme({
|
||||
inputDecorationTheme: _defaultInputDecorationTheme,
|
||||
listTileTheme: _defaultListTileTheme,
|
||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
appBarTheme: AppBarTheme(
|
||||
appBarTheme: const AppBarTheme(
|
||||
scrolledUnderElevation: 0,
|
||||
),
|
||||
chipTheme: ChipThemeData(
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_api/src/models/user_model.dart';
|
||||
|
||||
class PaperlessApiHiveTypeIds {
|
||||
PaperlessApiHiveTypeIds._();
|
||||
@@ -56,7 +55,6 @@ void registerPaperlessApiHiveTypeAdapters() {
|
||||
// Users and permissions
|
||||
Hive.registerAdapter(UserModelV3Adapter());
|
||||
Hive.registerAdapter(UserModelV2Adapter());
|
||||
Hive.registerAdapter(UserPermissionsAdapter());
|
||||
Hive.registerAdapter(InheritedPermissionsAdapter());
|
||||
Hive.registerAdapter(GroupModelAdapter());
|
||||
Hive.registerAdapter(PermissionsAdapter());
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
import 'package:paperless_api/src/models/models.dart';
|
||||
import 'package:paperless_api/src/models/query_parameters/date_range_queries/absolute_date_range_query.dart';
|
||||
import 'package:paperless_api/src/models/query_parameters/date_range_queries/relative_date_range_query.dart';
|
||||
|
||||
class DateRangeQueryJsonConverter
|
||||
extends JsonConverter<DateRangeQuery, Map<String, dynamic>> {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
// ignore_for_file: unused_field
|
||||
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_api/src/constants.dart';
|
||||
import 'package:paperless_api/src/converters/local_date_time_json_converter.dart';
|
||||
import 'package:paperless_api/src/models/query_parameters/tags_query/tags_query.dart';
|
||||
|
||||
part 'filter_rule_model.g.dart';
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ class GroupModel with _$GroupModel {
|
||||
const factory GroupModel({
|
||||
@HiveField(0) required int id,
|
||||
@HiveField(1) required String name,
|
||||
@HiveField(2) required List<UserPermissions> permissions,
|
||||
@HiveField(2) required List<String> permissions,
|
||||
}) = _GroupModel;
|
||||
|
||||
factory GroupModel.fromJson(Map<String, dynamic> json) => _$GroupModelFromJson(json);
|
||||
|
||||
@@ -25,7 +25,7 @@ mixin _$GroupModel {
|
||||
@HiveField(1)
|
||||
String get name => throw _privateConstructorUsedError;
|
||||
@HiveField(2)
|
||||
List<UserPermissions> get permissions => throw _privateConstructorUsedError;
|
||||
List<String> get permissions => throw _privateConstructorUsedError;
|
||||
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
@JsonKey(ignore: true)
|
||||
@@ -42,7 +42,7 @@ abstract class $GroupModelCopyWith<$Res> {
|
||||
$Res call(
|
||||
{@HiveField(0) int id,
|
||||
@HiveField(1) String name,
|
||||
@HiveField(2) List<UserPermissions> permissions});
|
||||
@HiveField(2) List<String> permissions});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -74,7 +74,7 @@ class _$GroupModelCopyWithImpl<$Res, $Val extends GroupModel>
|
||||
permissions: null == permissions
|
||||
? _value.permissions
|
||||
: permissions // ignore: cast_nullable_to_non_nullable
|
||||
as List<UserPermissions>,
|
||||
as List<String>,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
@@ -90,7 +90,7 @@ abstract class _$$_GroupModelCopyWith<$Res>
|
||||
$Res call(
|
||||
{@HiveField(0) int id,
|
||||
@HiveField(1) String name,
|
||||
@HiveField(2) List<UserPermissions> permissions});
|
||||
@HiveField(2) List<String> permissions});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -120,7 +120,7 @@ class __$$_GroupModelCopyWithImpl<$Res>
|
||||
permissions: null == permissions
|
||||
? _value._permissions
|
||||
: permissions // ignore: cast_nullable_to_non_nullable
|
||||
as List<UserPermissions>,
|
||||
as List<String>,
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -131,7 +131,7 @@ class _$_GroupModel implements _GroupModel {
|
||||
const _$_GroupModel(
|
||||
{@HiveField(0) required this.id,
|
||||
@HiveField(1) required this.name,
|
||||
@HiveField(2) required final List<UserPermissions> permissions})
|
||||
@HiveField(2) required final List<String> permissions})
|
||||
: _permissions = permissions;
|
||||
|
||||
factory _$_GroupModel.fromJson(Map<String, dynamic> json) =>
|
||||
@@ -143,10 +143,10 @@ class _$_GroupModel implements _GroupModel {
|
||||
@override
|
||||
@HiveField(1)
|
||||
final String name;
|
||||
final List<UserPermissions> _permissions;
|
||||
final List<String> _permissions;
|
||||
@override
|
||||
@HiveField(2)
|
||||
List<UserPermissions> get permissions {
|
||||
List<String> get permissions {
|
||||
if (_permissions is EqualUnmodifiableListView) return _permissions;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_permissions);
|
||||
@@ -189,10 +189,9 @@ class _$_GroupModel implements _GroupModel {
|
||||
|
||||
abstract class _GroupModel implements GroupModel {
|
||||
const factory _GroupModel(
|
||||
{@HiveField(0) required final int id,
|
||||
@HiveField(1) required final String name,
|
||||
@HiveField(2) required final List<UserPermissions> permissions}) =
|
||||
_$_GroupModel;
|
||||
{@HiveField(0) required final int id,
|
||||
@HiveField(1) required final String name,
|
||||
@HiveField(2) required final List<String> permissions}) = _$_GroupModel;
|
||||
|
||||
factory _GroupModel.fromJson(Map<String, dynamic> json) =
|
||||
_$_GroupModel.fromJson;
|
||||
@@ -205,7 +204,7 @@ abstract class _GroupModel implements GroupModel {
|
||||
String get name;
|
||||
@override
|
||||
@HiveField(2)
|
||||
List<UserPermissions> get permissions;
|
||||
List<String> get permissions;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$$_GroupModelCopyWith<_$_GroupModel> get copyWith =>
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import 'dart:developer';
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
import 'package:paperless_api/src/converters/hex_color_json_converter.dart';
|
||||
import 'package:paperless_api/src/models/labels/label_model.dart';
|
||||
@@ -24,7 +22,7 @@ class Tag extends Label {
|
||||
|
||||
final bool isInboxTag;
|
||||
|
||||
Tag({
|
||||
const Tag({
|
||||
super.id,
|
||||
required super.name,
|
||||
super.documentCount,
|
||||
|
||||
@@ -53,6 +53,5 @@ enum ErrorCode {
|
||||
requestTimedOut,
|
||||
unsupportedFileFormat,
|
||||
missingClientCertificate,
|
||||
acknowledgeTasksError,
|
||||
notAuthorized;
|
||||
acknowledgeTasksError;
|
||||
}
|
||||
|
||||
@@ -1,117 +1,30 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:paperless_api/config/hive/hive_type_ids.dart';
|
||||
part 'user_permissions.g.dart';
|
||||
|
||||
@HiveType(typeId: PaperlessApiHiveTypeIds.userPermissions)
|
||||
@JsonEnum(valueField: "value")
|
||||
enum UserPermissions {
|
||||
@HiveField(0)
|
||||
addCorrespondent("add_correspondent"),
|
||||
@HiveField(1)
|
||||
addDocument("add_document"),
|
||||
@HiveField(2)
|
||||
addDocumenttype("add_documenttype"),
|
||||
@HiveField(3)
|
||||
addGroup("add_group"),
|
||||
@HiveField(4)
|
||||
addMailaccount("add_mailaccount"),
|
||||
@HiveField(5)
|
||||
addMailrule("add_mailrule"),
|
||||
@HiveField(6)
|
||||
addNote("add_note"),
|
||||
@HiveField(7)
|
||||
addPaperlesstask("add_paperlesstask"),
|
||||
@HiveField(8)
|
||||
addSavedview("add_savedview"),
|
||||
@HiveField(9)
|
||||
addStoragepath("add_storagepath"),
|
||||
@HiveField(10)
|
||||
addTag("add_tag"),
|
||||
@HiveField(11)
|
||||
addUisettings("add_uisettings"),
|
||||
@HiveField(12)
|
||||
addUser("add_user"),
|
||||
@HiveField(13)
|
||||
changeCorrespondent("change_correspondent"),
|
||||
@HiveField(14)
|
||||
changeDocument("change_document"),
|
||||
@HiveField(15)
|
||||
changeDocumenttype("change_documenttype"),
|
||||
@HiveField(16)
|
||||
changeGroup("change_group"),
|
||||
@HiveField(17)
|
||||
changeMailaccount("change_mailaccount"),
|
||||
@HiveField(18)
|
||||
changeMailrule("change_mailrule"),
|
||||
@HiveField(19)
|
||||
changeNote("change_note"),
|
||||
@HiveField(20)
|
||||
changePaperlesstask("change_paperlesstask"),
|
||||
@HiveField(21)
|
||||
changeSavedview("change_savedview"),
|
||||
@HiveField(22)
|
||||
changeStoragepath("change_storagepath"),
|
||||
@HiveField(23)
|
||||
changeTag("change_tag"),
|
||||
@HiveField(24)
|
||||
changeUisettings("change_uisettings"),
|
||||
@HiveField(25)
|
||||
changeUser("change_user"),
|
||||
@HiveField(26)
|
||||
deleteCorrespondent("delete_correspondent"),
|
||||
@HiveField(27)
|
||||
deleteDocument("delete_document"),
|
||||
@HiveField(28)
|
||||
deleteDocumenttype("delete_documenttype"),
|
||||
@HiveField(29)
|
||||
deleteGroup("delete_group"),
|
||||
@HiveField(30)
|
||||
deleteMailaccount("delete_mailaccount"),
|
||||
@HiveField(31)
|
||||
deleteMailrule("delete_mailrule"),
|
||||
@HiveField(32)
|
||||
deleteNote("delete_note"),
|
||||
@HiveField(33)
|
||||
deletePaperlesstask("delete_paperlesstask"),
|
||||
@HiveField(34)
|
||||
deleteSavedview("delete_savedview"),
|
||||
@HiveField(35)
|
||||
deleteStoragepath("delete_storagepath"),
|
||||
@HiveField(36)
|
||||
deleteTag("delete_tag"),
|
||||
@HiveField(37)
|
||||
deleteUisettings("delete_uisettings"),
|
||||
@HiveField(38)
|
||||
deleteUser("delete_user"),
|
||||
@HiveField(39)
|
||||
viewCorrespondent("view_correspondent"),
|
||||
@HiveField(40)
|
||||
viewDocument("view_document"),
|
||||
@HiveField(41)
|
||||
viewDocumenttype("view_documenttype"),
|
||||
@HiveField(42)
|
||||
viewGroup("view_group"),
|
||||
@HiveField(43)
|
||||
viewMailaccount("view_mailaccount"),
|
||||
@HiveField(44)
|
||||
viewMailrule("view_mailrule"),
|
||||
@HiveField(45)
|
||||
viewNote("view_note"),
|
||||
@HiveField(46)
|
||||
viewPaperlesstask("view_paperlesstask"),
|
||||
@HiveField(47)
|
||||
viewSavedview("view_savedview"),
|
||||
@HiveField(48)
|
||||
viewStoragepath("view_storagepath"),
|
||||
@HiveField(49)
|
||||
viewTag("view_tag"),
|
||||
@HiveField(50)
|
||||
viewUisettings("view_uisettings"),
|
||||
@HiveField(51)
|
||||
viewUser("view_user");
|
||||
|
||||
const UserPermissions(this.value);
|
||||
enum PermissionAction {
|
||||
add("add"),
|
||||
change("change"),
|
||||
delete("delete"),
|
||||
view("view");
|
||||
|
||||
final String value;
|
||||
const PermissionAction(this.value);
|
||||
}
|
||||
|
||||
enum PermissionTarget {
|
||||
correspondent("correspondent"),
|
||||
document("document"),
|
||||
documentType("documenttype"),
|
||||
group("group"),
|
||||
mailAccount("mailaccount"),
|
||||
mailrule("mailrule"),
|
||||
note("note"),
|
||||
paperlesstask("paperlesstask"),
|
||||
savedView("savedview"),
|
||||
storagePath("storagepath"),
|
||||
tag("tag"),
|
||||
uiSettings("uisettings"),
|
||||
user("user"),
|
||||
logentry("logentry"),
|
||||
permission("permission");
|
||||
|
||||
final String value;
|
||||
const PermissionTarget(this.value);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:paperless_api/config/hive/hive_type_ids.dart';
|
||||
import 'package:paperless_api/src/models/query_parameters/date_range_queries/date_range_query_field.dart';
|
||||
|
||||
import 'date_range_query.dart';
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user