mirror of
https://github.com/Xevion/paperless-mobile.git
synced 2025-12-07 16:07:53 -06:00
fix: Adapt to new provider strucutre
This commit is contained in:
@@ -1,17 +0,0 @@
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
||||||
import 'package:paperless_api/paperless_api.dart';
|
|
||||||
import 'package:paperless_mobile/core/bloc/server_information_state.dart';
|
|
||||||
|
|
||||||
class ServerInformationCubit extends Cubit<ServerInformationState> {
|
|
||||||
final PaperlessServerStatsApi _api;
|
|
||||||
|
|
||||||
ServerInformationCubit(this._api) : super(ServerInformationState());
|
|
||||||
|
|
||||||
Future<void> updateInformation() async {
|
|
||||||
final information = await _api.getServerInformation();
|
|
||||||
emit(ServerInformationState(
|
|
||||||
isLoaded: true,
|
|
||||||
information: information,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
import 'package:paperless_api/paperless_api.dart';
|
|
||||||
|
|
||||||
class ServerInformationState {
|
|
||||||
final bool isLoaded;
|
|
||||||
final PaperlessServerInformationModel? information;
|
|
||||||
|
|
||||||
ServerInformationState({
|
|
||||||
this.isLoaded = false,
|
|
||||||
this.information,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import 'package:hive_flutter/adapters.dart';
|
import 'package:hive_flutter/adapters.dart';
|
||||||
import 'package:paperless_mobile/core/config/hive/hive_config.dart';
|
import 'package:paperless_mobile/core/config/hive/hive_config.dart';
|
||||||
|
import 'package:paperless_mobile/core/database/tables/global_settings.dart';
|
||||||
import 'package:paperless_mobile/core/database/tables/local_user_settings.dart';
|
import 'package:paperless_mobile/core/database/tables/local_user_settings.dart';
|
||||||
import 'package:paperless_api/paperless_api.dart';
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
|
|
||||||
@@ -17,7 +18,7 @@ class LocalUserAccount extends HiveObject {
|
|||||||
final LocalUserSettings settings;
|
final LocalUserSettings settings;
|
||||||
|
|
||||||
@HiveField(7)
|
@HiveField(7)
|
||||||
final UserModel paperlessUser;
|
UserModel paperlessUser;
|
||||||
|
|
||||||
LocalUserAccount({
|
LocalUserAccount({
|
||||||
required this.id,
|
required this.id,
|
||||||
@@ -25,4 +26,7 @@ class LocalUserAccount extends HiveObject {
|
|||||||
required this.settings,
|
required this.settings,
|
||||||
required this.paperlessUser,
|
required this.paperlessUser,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
static LocalUserAccount get current => Hive.box<LocalUserAccount>(HiveBoxes.localUserAccount)
|
||||||
|
.get(Hive.box<GlobalSettings>(HiveBoxes.globalSettings).getValue()!.currentLoggedInUser)!;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'package:hive_flutter/adapters.dart';
|
import 'package:hive_flutter/adapters.dart';
|
||||||
import 'package:paperless_api/paperless_api.dart';
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
import 'package:paperless_mobile/core/config/hive/hive_config.dart';
|
import 'package:paperless_mobile/core/config/hive/hive_config.dart';
|
||||||
|
import 'package:paperless_mobile/core/database/tables/global_settings.dart';
|
||||||
import 'package:paperless_mobile/features/settings/model/view_type.dart';
|
import 'package:paperless_mobile/features/settings/model/view_type.dart';
|
||||||
|
|
||||||
part 'local_user_app_state.g.dart';
|
part 'local_user_app_state.g.dart';
|
||||||
@@ -37,4 +38,10 @@ class LocalUserAppState extends HiveObject {
|
|||||||
this.documentSearchViewType = ViewType.list,
|
this.documentSearchViewType = ViewType.list,
|
||||||
this.savedViewsViewType = ViewType.list,
|
this.savedViewsViewType = ViewType.list,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
static LocalUserAppState get current {
|
||||||
|
final currentLocalUserId =
|
||||||
|
Hive.box<GlobalSettings>(HiveBoxes.globalSettings).getValue()!.currentLoggedInUser!;
|
||||||
|
return Hive.box<LocalUserAppState>(HiveBoxes.localUserAppState).get(currentLocalUserId)!;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,15 @@ class DioHttpErrorInterceptor extends Interceptor {
|
|||||||
} else if (data is String) {
|
} else if (data is String) {
|
||||||
return _handlePlainError(data, handler, err);
|
return _handlePlainError(data, handler, err);
|
||||||
}
|
}
|
||||||
|
} else if (err.response?.statusCode == 403) {
|
||||||
|
handler.reject(
|
||||||
|
DioError(
|
||||||
|
requestOptions: err.requestOptions,
|
||||||
|
error: const PaperlessServerException(ErrorCode.notAuthorized),
|
||||||
|
response: err.response,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return;
|
||||||
} else if (err.error is SocketException) {
|
} else if (err.error is SocketException) {
|
||||||
final ex = err.error as SocketException;
|
final ex = err.error as SocketException;
|
||||||
if (ex.osError?.errorCode == _OsErrorCodes.serverUnreachable.code) {
|
if (ex.osError?.errorCode == _OsErrorCodes.serverUnreachable.code) {
|
||||||
@@ -67,8 +76,7 @@ class DioHttpErrorInterceptor extends Interceptor {
|
|||||||
DioError(
|
DioError(
|
||||||
requestOptions: err.requestOptions,
|
requestOptions: err.requestOptions,
|
||||||
type: DioErrorType.badResponse,
|
type: DioErrorType.badResponse,
|
||||||
error: const PaperlessServerException(
|
error: const PaperlessServerException(ErrorCode.missingClientCertificate),
|
||||||
ErrorCode.missingClientCertificate),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
107
lib/core/navigation/push_routes.dart
Normal file
107
lib/core/navigation/push_routes.dart
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
|
||||||
|
import 'package:hive/hive.dart';
|
||||||
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
|
import 'package:paperless_mobile/core/config/hive/hive_config.dart';
|
||||||
|
import 'package:paperless_mobile/core/database/tables/global_settings.dart';
|
||||||
|
import 'package:paperless_mobile/core/database/tables/local_user_app_state.dart';
|
||||||
|
import 'package:paperless_mobile/core/notifier/document_changed_notifier.dart';
|
||||||
|
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
||||||
|
import 'package:paperless_mobile/core/repository/user_repository.dart';
|
||||||
|
import 'package:paperless_mobile/features/document_search/cubit/document_search_cubit.dart';
|
||||||
|
import 'package:paperless_mobile/features/document_search/view/document_search_page.dart';
|
||||||
|
import 'package:paperless_mobile/features/home/view/model/api_version.dart';
|
||||||
|
import 'package:paperless_mobile/features/notifications/services/local_notification_service.dart';
|
||||||
|
import 'package:paperless_mobile/features/saved_view/cubit/saved_view_cubit.dart';
|
||||||
|
import 'package:paperless_mobile/features/saved_view_details/cubit/saved_view_details_cubit.dart';
|
||||||
|
import 'package:paperless_mobile/features/saved_view_details/view/saved_view_details_page.dart';
|
||||||
|
import 'package:paperless_mobile/routes/document_details_route.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
Future<void> pushDocumentSearchPage(BuildContext context) {
|
||||||
|
final currentUser =
|
||||||
|
Hive.box<GlobalSettings>(HiveBoxes.globalSettings).getValue()!.currentLoggedInUser;
|
||||||
|
return Navigator.of(context).push(
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (_) => MultiProvider(
|
||||||
|
providers: [
|
||||||
|
Provider.value(value: context.read<LabelRepository>()),
|
||||||
|
Provider.value(value: context.read<PaperlessDocumentsApi>()),
|
||||||
|
Provider.value(value: context.read<DocumentChangedNotifier>()),
|
||||||
|
Provider.value(value: context.read<CacheManager>()),
|
||||||
|
],
|
||||||
|
builder: (context, _) {
|
||||||
|
return BlocProvider(
|
||||||
|
create: (context) => DocumentSearchCubit(
|
||||||
|
context.read(),
|
||||||
|
context.read(),
|
||||||
|
context.read(),
|
||||||
|
Hive.box<LocalUserAppState>(HiveBoxes.localUserAppState).get(currentUser)!,
|
||||||
|
),
|
||||||
|
child: const DocumentSearchPage(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> pushDocumentDetailsRoute(
|
||||||
|
BuildContext context, {
|
||||||
|
required DocumentModel document,
|
||||||
|
bool isLabelClickable = true,
|
||||||
|
bool allowEdit = true,
|
||||||
|
String? titleAndContentQueryString,
|
||||||
|
}) {
|
||||||
|
return Navigator.of(context).push(
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (_) => MultiProvider(
|
||||||
|
providers: [
|
||||||
|
Provider.value(value: context.read<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>()),
|
||||||
|
if (context.read<ApiVersion>().hasMultiUserSupport)
|
||||||
|
Provider.value(value: context.read<UserRepository>()),
|
||||||
|
],
|
||||||
|
child: DocumentDetailsRoute(
|
||||||
|
document: document,
|
||||||
|
isLabelClickable: isLabelClickable,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> pushSavedViewDetailsRoute(BuildContext context, {required SavedView savedView}) {
|
||||||
|
return Navigator.of(context).push(
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (_) => MultiProvider(
|
||||||
|
providers: [
|
||||||
|
Provider.value(value: context.read<LabelRepository>()),
|
||||||
|
Provider.value(value: context.read<DocumentChangedNotifier>()),
|
||||||
|
Provider.value(value: context.read<PaperlessDocumentsApi>()),
|
||||||
|
Provider.value(value: context.read<CacheManager>()),
|
||||||
|
],
|
||||||
|
child: SavedViewDetailsPage(
|
||||||
|
onDelete: context.read<SavedViewCubit>().remove,
|
||||||
|
),
|
||||||
|
builder: (_, child) {
|
||||||
|
return BlocProvider(
|
||||||
|
create: (context) => SavedViewDetailsCubit(
|
||||||
|
context.read(),
|
||||||
|
context.read(),
|
||||||
|
context.read(),
|
||||||
|
LocalUserAppState.current,
|
||||||
|
savedView: savedView,
|
||||||
|
),
|
||||||
|
child: SavedViewDetailsPage(onDelete: context.read<SavedViewCubit>().remove),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -72,5 +72,7 @@ String translateError(BuildContext context, ErrorCode code) {
|
|||||||
return S.of(context)!.couldNotLoadSuggestions;
|
return S.of(context)!.couldNotLoadSuggestions;
|
||||||
case ErrorCode.acknowledgeTasksError:
|
case ErrorCode.acknowledgeTasksError:
|
||||||
return S.of(context)!.couldNotAcknowledgeTasks;
|
return S.of(context)!.couldNotAcknowledgeTasks;
|
||||||
|
case ErrorCode.notAuthorized:
|
||||||
|
return "You do not have the permission to perform this action."; //TODO: INTL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,14 +3,13 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:paperless_mobile/constants.dart';
|
import 'package:paperless_mobile/constants.dart';
|
||||||
import 'package:paperless_mobile/core/bloc/server_information_cubit.dart';
|
|
||||||
import 'package:paperless_mobile/core/widgets/paperless_logo.dart';
|
import 'package:paperless_mobile/core/widgets/paperless_logo.dart';
|
||||||
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
||||||
|
import 'package:paperless_mobile/features/home/view/model/api_version.dart';
|
||||||
import 'package:paperless_mobile/features/settings/view/settings_page.dart';
|
import 'package:paperless_mobile/features/settings/view/settings_page.dart';
|
||||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
import 'package:url_launcher/link.dart';
|
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
|
||||||
import 'package:url_launcher/url_launcher_string.dart';
|
import 'package:url_launcher/url_launcher_string.dart';
|
||||||
|
|
||||||
class AppDrawer extends StatelessWidget {
|
class AppDrawer extends StatelessWidget {
|
||||||
@@ -42,7 +41,16 @@ class AppDrawer extends StatelessWidget {
|
|||||||
ListTile(
|
ListTile(
|
||||||
dense: true,
|
dense: true,
|
||||||
leading: const Icon(Icons.bug_report_outlined),
|
leading: const Icon(Icons.bug_report_outlined),
|
||||||
title: Text(S.of(context)!.reportABug),
|
title: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(S.of(context)!.reportABug),
|
||||||
|
const Icon(
|
||||||
|
Icons.open_in_new,
|
||||||
|
size: 16,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
launchUrlString(
|
launchUrlString(
|
||||||
'https://github.com/astubenbord/paperless-mobile/issues/new',
|
'https://github.com/astubenbord/paperless-mobile/issues/new',
|
||||||
@@ -64,7 +72,7 @@ class AppDrawer extends StatelessWidget {
|
|||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text(S.of(context)!.donateCoffee),
|
Text(S.of(context)!.donateCoffee),
|
||||||
Icon(
|
const Icon(
|
||||||
Icons.open_in_new,
|
Icons.open_in_new,
|
||||||
size: 16,
|
size: 16,
|
||||||
)
|
)
|
||||||
@@ -85,8 +93,8 @@ class AppDrawer extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
onTap: () => Navigator.of(context).push(
|
onTap: () => Navigator.of(context).push(
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (_) => BlocProvider.value(
|
builder: (_) => Provider.value(
|
||||||
value: context.read<ServerInformationCubit>(),
|
value: context.read<ApiVersion>(),
|
||||||
child: const SettingsPage(),
|
child: const SettingsPage(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -148,19 +156,19 @@ class AppDrawer extends StatelessWidget {
|
|||||||
return RichText(
|
return RichText(
|
||||||
text: TextSpan(
|
text: TextSpan(
|
||||||
children: [
|
children: [
|
||||||
TextSpan(
|
const TextSpan(
|
||||||
text: 'Onboarding images by ',
|
text: 'Onboarding images by ',
|
||||||
),
|
),
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: 'pch.vector',
|
text: 'pch.vector',
|
||||||
style: TextStyle(color: Colors.blue),
|
style: const TextStyle(color: Colors.blue),
|
||||||
recognizer: TapGestureRecognizer()
|
recognizer: TapGestureRecognizer()
|
||||||
..onTap = () {
|
..onTap = () {
|
||||||
launchUrlString(
|
launchUrlString(
|
||||||
'https://www.freepik.com/free-vector/business-team-working-cogwheel-mechanism-together_8270974.htm#query=setting&position=4&from_view=author');
|
'https://www.freepik.com/free-vector/business-team-working-cogwheel-mechanism-together_8270974.htm#query=setting&position=4&from_view=author');
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
TextSpan(
|
const TextSpan(
|
||||||
text: ' on Freepik.',
|
text: ' on Freepik.',
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,8 +1,13 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:hive_flutter/adapters.dart';
|
||||||
import 'package:open_filex/open_filex.dart';
|
import 'package:open_filex/open_filex.dart';
|
||||||
import 'package:paperless_api/paperless_api.dart';
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
import 'package:paperless_mobile/core/bloc/connectivity_cubit.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/translation/error_code_localization_mapper.dart';
|
||||||
import 'package:paperless_mobile/core/widgets/material/colored_tab_bar.dart';
|
import 'package:paperless_mobile/core/widgets/material/colored_tab_bar.dart';
|
||||||
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
||||||
@@ -11,19 +16,20 @@ import 'package:paperless_mobile/features/document_details/view/widgets/document
|
|||||||
import 'package:paperless_mobile/features/document_details/view/widgets/document_download_button.dart';
|
import 'package:paperless_mobile/features/document_details/view/widgets/document_download_button.dart';
|
||||||
import 'package:paperless_mobile/features/document_details/view/widgets/document_meta_data_widget.dart';
|
import 'package:paperless_mobile/features/document_details/view/widgets/document_meta_data_widget.dart';
|
||||||
import 'package:paperless_mobile/features/document_details/view/widgets/document_overview_widget.dart';
|
import 'package:paperless_mobile/features/document_details/view/widgets/document_overview_widget.dart';
|
||||||
|
import 'package:paperless_mobile/features/document_details/view/widgets/document_permissions_widget.dart';
|
||||||
import 'package:paperless_mobile/features/document_details/view/widgets/document_share_button.dart';
|
import 'package:paperless_mobile/features/document_details/view/widgets/document_share_button.dart';
|
||||||
import 'package:paperless_mobile/features/document_edit/cubit/document_edit_cubit.dart';
|
import 'package:paperless_mobile/features/document_edit/cubit/document_edit_cubit.dart';
|
||||||
import 'package:paperless_mobile/features/document_edit/view/document_edit_page.dart';
|
import 'package:paperless_mobile/features/document_edit/view/document_edit_page.dart';
|
||||||
import 'package:paperless_mobile/features/documents/view/pages/document_view.dart';
|
import 'package:paperless_mobile/features/documents/view/pages/document_view.dart';
|
||||||
import 'package:paperless_mobile/features/documents/view/widgets/delete_document_confirmation_dialog.dart';
|
import 'package:paperless_mobile/features/documents/view/widgets/delete_document_confirmation_dialog.dart';
|
||||||
import 'package:paperless_mobile/features/documents/view/widgets/document_preview.dart';
|
import 'package:paperless_mobile/features/documents/view/widgets/document_preview.dart';
|
||||||
|
import 'package:paperless_mobile/features/home/view/model/api_version.dart';
|
||||||
import 'package:paperless_mobile/features/similar_documents/cubit/similar_documents_cubit.dart';
|
import 'package:paperless_mobile/features/similar_documents/cubit/similar_documents_cubit.dart';
|
||||||
import 'package:paperless_mobile/features/similar_documents/view/similar_documents_view.dart';
|
import 'package:paperless_mobile/features/similar_documents/view/similar_documents_view.dart';
|
||||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||||
import 'package:paperless_mobile/helpers/message_helpers.dart';
|
import 'package:paperless_mobile/helpers/message_helpers.dart';
|
||||||
|
|
||||||
class DocumentDetailsPage extends StatefulWidget {
|
class DocumentDetailsPage extends StatefulWidget {
|
||||||
final bool allowEdit;
|
|
||||||
final bool isLabelClickable;
|
final bool isLabelClickable;
|
||||||
final String? titleAndContentQueryString;
|
final String? titleAndContentQueryString;
|
||||||
|
|
||||||
@@ -31,7 +37,6 @@ class DocumentDetailsPage extends StatefulWidget {
|
|||||||
Key? key,
|
Key? key,
|
||||||
this.isLabelClickable = true,
|
this.isLabelClickable = true,
|
||||||
this.titleAndContentQueryString,
|
this.titleAndContentQueryString,
|
||||||
this.allowEdit = true,
|
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -50,13 +55,16 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final apiVersion = context.watch<ApiVersion>();
|
||||||
|
|
||||||
|
final tabLength = 4 + (apiVersion.supportsPermissions ? 1 : 0);
|
||||||
return WillPopScope(
|
return WillPopScope(
|
||||||
onWillPop: () async {
|
onWillPop: () async {
|
||||||
Navigator.of(context).pop(context.read<DocumentDetailsCubit>().state.document);
|
Navigator.of(context).pop(context.read<DocumentDetailsCubit>().state.document);
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
child: DefaultTabController(
|
child: DefaultTabController(
|
||||||
length: 4,
|
length: tabLength,
|
||||||
child: BlocListener<ConnectivityCubit, ConnectivityState>(
|
child: BlocListener<ConnectivityCubit, ConnectivityState>(
|
||||||
listenWhen: (previous, current) => !previous.isConnected && current.isConnected,
|
listenWhen: (previous, current) => !previous.isConnected && current.isConnected,
|
||||||
listener: (context, state) {
|
listener: (context, state) {
|
||||||
@@ -65,7 +73,7 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
|
|||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
extendBodyBehindAppBar: false,
|
extendBodyBehindAppBar: false,
|
||||||
floatingActionButtonLocation: FloatingActionButtonLocation.endDocked,
|
floatingActionButtonLocation: FloatingActionButtonLocation.endDocked,
|
||||||
floatingActionButton: widget.allowEdit ? _buildEditButton() : null,
|
floatingActionButton: _buildEditButton(),
|
||||||
bottomNavigationBar: _buildBottomAppBar(),
|
bottomNavigationBar: _buildBottomAppBar(),
|
||||||
body: NestedScrollView(
|
body: NestedScrollView(
|
||||||
headerSliverBuilder: (context, innerBoxIsScrolled) => [
|
headerSliverBuilder: (context, innerBoxIsScrolled) => [
|
||||||
@@ -147,6 +155,15 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
if (apiVersion.supportsPermissions)
|
||||||
|
Tab(
|
||||||
|
child: Text(
|
||||||
|
"Permissions",
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).colorScheme.onPrimaryContainer,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -220,6 +237,15 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
CustomScrollView(
|
||||||
|
controller: _pagingScrollController,
|
||||||
|
slivers: [
|
||||||
|
SliverOverlapInjector(
|
||||||
|
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
|
||||||
|
),
|
||||||
|
const DocumentPermissionsWidget(),
|
||||||
|
],
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -234,25 +260,29 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildEditButton() {
|
Widget _buildEditButton() {
|
||||||
|
bool canEdit = context.watchInternetConnection;
|
||||||
|
final apiVersion = context.watch<ApiVersion>();
|
||||||
|
|
||||||
|
if (apiVersion.supportsPermissions) {
|
||||||
|
canEdit =
|
||||||
|
LocalUserAccount.current.paperlessUser.hasPermission(UserPermissions.changeDocument);
|
||||||
|
}
|
||||||
|
if (!canEdit) {
|
||||||
|
return const SizedBox.shrink();
|
||||||
|
}
|
||||||
return BlocBuilder<DocumentDetailsCubit, DocumentDetailsState>(
|
return BlocBuilder<DocumentDetailsCubit, DocumentDetailsState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
// final _filteredSuggestions =
|
// final _filteredSuggestions =
|
||||||
// state.suggestions?.documentDifference(state.document);
|
// state.suggestions?.documentDifference(state.document);
|
||||||
return BlocBuilder<ConnectivityCubit, ConnectivityState>(
|
|
||||||
builder: (context, connectivityState) {
|
return Tooltip(
|
||||||
if (!connectivityState.isConnected) {
|
message: S.of(context)!.editDocumentTooltip,
|
||||||
return const SizedBox.shrink();
|
preferBelow: false,
|
||||||
}
|
verticalOffset: 40,
|
||||||
return Tooltip(
|
child: FloatingActionButton(
|
||||||
message: S.of(context)!.editDocumentTooltip,
|
child: const Icon(Icons.edit),
|
||||||
preferBelow: false,
|
onPressed: canEdit ? () => _onEdit(state.document) : null,
|
||||||
verticalOffset: 40,
|
),
|
||||||
child: FloatingActionButton(
|
|
||||||
child: const Icon(Icons.edit),
|
|
||||||
onPressed: () => _onEdit(state.document),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -265,14 +295,16 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
|
|||||||
child: BlocBuilder<ConnectivityCubit, ConnectivityState>(
|
child: BlocBuilder<ConnectivityCubit, ConnectivityState>(
|
||||||
builder: (context, connectivityState) {
|
builder: (context, connectivityState) {
|
||||||
final isConnected = connectivityState.isConnected;
|
final isConnected = connectivityState.isConnected;
|
||||||
|
|
||||||
|
final canDelete = LocalUserAccount.current.paperlessUser
|
||||||
|
.hasPermission(UserPermissions.deleteDocument);
|
||||||
return Row(
|
return Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
IconButton(
|
IconButton(
|
||||||
tooltip: S.of(context)!.deleteDocumentTooltip,
|
tooltip: S.of(context)!.deleteDocumentTooltip,
|
||||||
icon: const Icon(Icons.delete),
|
icon: const Icon(Icons.delete),
|
||||||
onPressed:
|
onPressed: (isConnected && canDelete) ? () => _onDelete(state.document) : null,
|
||||||
widget.allowEdit && isConnected ? () => _onDelete(state.document) : null,
|
|
||||||
).paddedSymmetrically(horizontal: 4),
|
).paddedSymmetrically(horizontal: 4),
|
||||||
DocumentDownloadButton(
|
DocumentDownloadButton(
|
||||||
document: state.document,
|
document: state.document,
|
||||||
@@ -374,7 +406,7 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
|
|||||||
Future<void> _onOpen(DocumentModel document) async {
|
Future<void> _onOpen(DocumentModel document) async {
|
||||||
Navigator.of(context).push(
|
Navigator.of(context).push(
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => DocumentView(
|
builder: (_) => DocumentView(
|
||||||
documentBytes: context.read<PaperlessDocumentsApi>().getPreview(document.id),
|
documentBytes: context.read<PaperlessDocumentsApi>().getPreview(document.id),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -29,7 +29,11 @@ class _DocumentMetaDataWidgetState extends State<DocumentMetaDataWidget> {
|
|||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
debugPrint("Building state...");
|
debugPrint("Building state...");
|
||||||
if (state.metaData == null) {
|
if (state.metaData == null) {
|
||||||
return const Center(child: CircularProgressIndicator());
|
return SliverToBoxAdapter(
|
||||||
|
child: const Center(
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return SliverList(
|
return SliverList(
|
||||||
delegate: SliverChildListDelegate(
|
delegate: SliverChildListDelegate(
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class DocumentPermissionsWidget extends StatelessWidget {
|
||||||
|
const DocumentPermissionsWidget({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return const SliverToBoxAdapter(
|
||||||
|
child: Placeholder(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -264,9 +264,12 @@ class _DocumentEditPageState extends State<DocumentEditPage> {
|
|||||||
var mergedDocument = document.copyWith(
|
var mergedDocument = document.copyWith(
|
||||||
title: values[fkTitle],
|
title: values[fkTitle],
|
||||||
created: values[fkCreatedDate],
|
created: values[fkCreatedDate],
|
||||||
documentType: () => (values[fkDocumentType] as SetIdQueryParameter).id,
|
documentType: () =>
|
||||||
correspondent: () => (values[fkCorrespondent] as SetIdQueryParameter).id,
|
(values[fkDocumentType] as IdQueryParameter).whenOrNull(fromId: (id) => id),
|
||||||
storagePath: () => (values[fkStoragePath] as SetIdQueryParameter).id,
|
correspondent: () =>
|
||||||
|
(values[fkCorrespondent] as IdQueryParameter).whenOrNull(fromId: (id) => id),
|
||||||
|
storagePath: () =>
|
||||||
|
(values[fkStoragePath] as IdQueryParameter).whenOrNull(fromId: (id) => id),
|
||||||
tags: (values[fkTags] as IdsTagsQuery).include,
|
tags: (values[fkTags] as IdsTagsQuery).include,
|
||||||
content: values[fkContent],
|
content: values[fkContent],
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import 'package:paperless_api/paperless_api.dart';
|
|||||||
import 'package:paperless_mobile/core/bloc/connectivity_cubit.dart';
|
import 'package:paperless_mobile/core/bloc/connectivity_cubit.dart';
|
||||||
import 'package:paperless_mobile/core/delegate/customizable_sliver_persistent_header_delegate.dart';
|
import 'package:paperless_mobile/core/delegate/customizable_sliver_persistent_header_delegate.dart';
|
||||||
import 'package:paperless_mobile/core/global/constants.dart';
|
import 'package:paperless_mobile/core/global/constants.dart';
|
||||||
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
|
||||||
import 'package:paperless_mobile/core/service/file_description.dart';
|
import 'package:paperless_mobile/core/service/file_description.dart';
|
||||||
import 'package:paperless_mobile/core/service/file_service.dart';
|
import 'package:paperless_mobile/core/service/file_service.dart';
|
||||||
import 'package:paperless_mobile/features/app_drawer/view/app_drawer.dart';
|
import 'package:paperless_mobile/features/app_drawer/view/app_drawer.dart';
|
||||||
@@ -23,7 +22,6 @@ import 'package:paperless_mobile/features/document_upload/view/document_upload_p
|
|||||||
import 'package:paperless_mobile/features/documents/view/pages/document_view.dart';
|
import 'package:paperless_mobile/features/documents/view/pages/document_view.dart';
|
||||||
import 'package:paperless_mobile/features/tasks/cubit/task_status_cubit.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/generated/l10n/app_localizations.dart';
|
||||||
import 'package:paperless_mobile/helpers/file_helpers.dart';
|
|
||||||
import 'package:paperless_mobile/helpers/message_helpers.dart';
|
import 'package:paperless_mobile/helpers/message_helpers.dart';
|
||||||
import 'package:paperless_mobile/helpers/permission_helpers.dart';
|
import 'package:paperless_mobile/helpers/permission_helpers.dart';
|
||||||
import 'package:path/path.dart' as p;
|
import 'package:path/path.dart' as p;
|
||||||
|
|||||||
@@ -3,10 +3,15 @@ import 'dart:async';
|
|||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
|
||||||
import 'package:hive/hive.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/config/hive/hive_config.dart';
|
||||||
import 'package:paperless_mobile/core/database/tables/global_settings.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_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/extensions/flutter_extensions.dart';
|
||||||
import 'package:paperless_mobile/features/document_search/cubit/document_search_cubit.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';
|
import 'package:paperless_mobile/features/document_search/view/remove_history_entry_dialog.dart';
|
||||||
@@ -17,23 +22,7 @@ import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
|||||||
import 'package:paperless_mobile/routes/document_details_route.dart';
|
import 'package:paperless_mobile/routes/document_details_route.dart';
|
||||||
import 'dart:math' as math;
|
import 'dart:math' as math;
|
||||||
|
|
||||||
Future<void> showDocumentSearchPage(BuildContext context) {
|
import 'package:provider/provider.dart';
|
||||||
final currentUser =
|
|
||||||
Hive.box<GlobalSettings>(HiveBoxes.globalSettings).getValue()!.currentLoggedInUser;
|
|
||||||
return Navigator.of(context).push(
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => BlocProvider(
|
|
||||||
create: (context) => DocumentSearchCubit(
|
|
||||||
context.read(),
|
|
||||||
context.read(),
|
|
||||||
context.read(),
|
|
||||||
Hive.box<LocalUserAppState>(HiveBoxes.localUserAppState).get(currentUser)!,
|
|
||||||
),
|
|
||||||
child: const DocumentSearchPage(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
class DocumentSearchPage extends StatefulWidget {
|
class DocumentSearchPage extends StatefulWidget {
|
||||||
const DocumentSearchPage({super.key});
|
const DocumentSearchPage({super.key});
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:hive_flutter/adapters.dart';
|
import 'package:hive_flutter/adapters.dart';
|
||||||
import 'package:paperless_mobile/core/bloc/server_information_cubit.dart';
|
|
||||||
import 'package:paperless_mobile/core/config/hive/hive_config.dart';
|
import 'package:paperless_mobile/core/config/hive/hive_config.dart';
|
||||||
import 'package:paperless_mobile/core/database/tables/local_user_account.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/delegate/customizable_sliver_persistent_header_delegate.dart';
|
||||||
|
import 'package:paperless_mobile/core/navigation/push_routes.dart';
|
||||||
import 'package:paperless_mobile/core/widgets/material/search/m3_search_bar.dart' as s;
|
import 'package:paperless_mobile/core/widgets/material/search/m3_search_bar.dart' as s;
|
||||||
import 'package:paperless_mobile/features/document_search/view/document_search_page.dart';
|
import 'package:paperless_mobile/features/home/view/model/api_version.dart';
|
||||||
import 'package:paperless_mobile/features/settings/view/manage_accounts_page.dart';
|
import 'package:paperless_mobile/features/settings/view/manage_accounts_page.dart';
|
||||||
import 'package:paperless_mobile/features/settings/view/widgets/global_settings_builder.dart';
|
import 'package:paperless_mobile/features/settings/view/widgets/global_settings_builder.dart';
|
||||||
import 'package:paperless_mobile/features/settings/view/widgets/user_avatar.dart';
|
import 'package:paperless_mobile/features/settings/view/widgets/user_avatar.dart';
|
||||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class SliverSearchBar extends StatelessWidget {
|
class SliverSearchBar extends StatelessWidget {
|
||||||
final bool floating;
|
final bool floating;
|
||||||
@@ -34,7 +35,7 @@ class SliverSearchBar extends StatelessWidget {
|
|||||||
child: s.SearchBar(
|
child: s.SearchBar(
|
||||||
height: kToolbarHeight,
|
height: kToolbarHeight,
|
||||||
supportingText: S.of(context)!.searchDocuments,
|
supportingText: S.of(context)!.searchDocuments,
|
||||||
onTap: () => showDocumentSearchPage(context),
|
onTap: () => pushDocumentSearchPage(context),
|
||||||
leadingIcon: IconButton(
|
leadingIcon: IconButton(
|
||||||
icon: const Icon(Icons.menu),
|
icon: const Icon(Icons.menu),
|
||||||
onPressed: Scaffold.of(context).openDrawer,
|
onPressed: Scaffold.of(context).openDrawer,
|
||||||
@@ -58,8 +59,8 @@ class SliverSearchBar extends StatelessWidget {
|
|||||||
onPressed: () {
|
onPressed: () {
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (_) => BlocProvider.value(
|
builder: (_) => Provider.value(
|
||||||
value: context.read<ServerInformationCubit>(),
|
value: context.read<ApiVersion>(),
|
||||||
child: const ManageAccountsPage(),
|
child: const ManageAccountsPage(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import 'package:paperless_mobile/features/settings/model/view_type.dart';
|
|||||||
part 'documents_cubit.g.dart';
|
part 'documents_cubit.g.dart';
|
||||||
part 'documents_state.dart';
|
part 'documents_state.dart';
|
||||||
|
|
||||||
class DocumentsCubit extends Cubit<DocumentsState> with DocumentPagingBlocMixin {
|
class DocumentsCubit extends HydratedCubit<DocumentsState> with DocumentPagingBlocMixin {
|
||||||
@override
|
@override
|
||||||
final PaperlessDocumentsApi api;
|
final PaperlessDocumentsApi api;
|
||||||
|
|
||||||
@@ -123,4 +123,14 @@ class DocumentsCubit extends Cubit<DocumentsState> with DocumentPagingBlocMixin
|
|||||||
_userState.currentDocumentFilter = filter;
|
_userState.currentDocumentFilter = filter;
|
||||||
await _userState.save();
|
await _userState.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
DocumentsState? fromJson(Map<String, dynamic> json) {
|
||||||
|
return DocumentsState.fromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic>? toJson(DocumentsState state) {
|
||||||
|
return state.toJson();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ import 'package:flutter/foundation.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||||
|
|
||||||
import 'package:pdfx/pdfx.dart';
|
|
||||||
|
|
||||||
class DocumentView extends StatefulWidget {
|
class DocumentView extends StatefulWidget {
|
||||||
final Future<Uint8List> documentBytes;
|
final Future<Uint8List> documentBytes;
|
||||||
|
|
||||||
@@ -17,36 +15,37 @@ class DocumentView extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _DocumentViewState extends State<DocumentView> {
|
class _DocumentViewState extends State<DocumentView> {
|
||||||
late PdfController _pdfController;
|
// late PdfController _pdfController;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_pdfController = PdfController(
|
// _pdfController = PdfController(
|
||||||
document: PdfDocument.openData(
|
// document: PdfDocument.openData(
|
||||||
widget.documentBytes,
|
// widget.documentBytes,
|
||||||
),
|
// ),
|
||||||
);
|
// );
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Container();
|
||||||
appBar: AppBar(
|
// return Scaffold(
|
||||||
title: Text(S.of(context)!.preview),
|
// appBar: AppBar(
|
||||||
),
|
// title: Text(S.of(context)!.preview),
|
||||||
body: PdfView(
|
// ),
|
||||||
builders: PdfViewBuilders<DefaultBuilderOptions>(
|
// body: PdfView(
|
||||||
options: const DefaultBuilderOptions(
|
// builders: PdfViewBuilders<DefaultBuilderOptions>(
|
||||||
loaderSwitchDuration: Duration(milliseconds: 500),
|
// options: const DefaultBuilderOptions(
|
||||||
),
|
// loaderSwitchDuration: Duration(milliseconds: 500),
|
||||||
pageLoaderBuilder: (context) => const Center(
|
// ),
|
||||||
child: CircularProgressIndicator(),
|
// pageLoaderBuilder: (context) => const Center(
|
||||||
),
|
// child: CircularProgressIndicator(),
|
||||||
),
|
// ),
|
||||||
scrollDirection: Axis.vertical,
|
// ),
|
||||||
controller: _pdfController,
|
// scrollDirection: Axis.vertical,
|
||||||
),
|
// controller: _pdfController,
|
||||||
);
|
// ),
|
||||||
|
// );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
import 'package:paperless_api/paperless_api.dart';
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
import 'package:paperless_mobile/core/bloc/connectivity_cubit.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/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/repository/label_repository.dart';
|
||||||
import 'package:paperless_mobile/core/widgets/material/colored_tab_bar.dart';
|
import 'package:paperless_mobile/core/widgets/material/colored_tab_bar.dart';
|
||||||
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
||||||
@@ -375,10 +376,10 @@ class _DocumentsPageState extends State<DocumentsPage> with SingleTickerProvider
|
|||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
return AddSavedViewPage(
|
return AddSavedViewPage(
|
||||||
currentFilter: filter,
|
currentFilter: filter,
|
||||||
correspondents: state.correspondents,
|
correspondents: context.read<LabelRepository>().state.correspondents,
|
||||||
documentTypes: state.documentTypes,
|
documentTypes: context.read<LabelRepository>().state.documentTypes,
|
||||||
storagePaths: state.storagePaths,
|
storagePaths: context.read<LabelRepository>().state.storagePaths,
|
||||||
tags: state.tags,
|
tags: context.read<LabelRepository>().state.tags,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
||||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
import 'package:paperless_api/paperless_api.dart';
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
import 'package:paperless_mobile/core/translation/sort_field_localization_mapper.dart';
|
import 'package:paperless_mobile/core/translation/sort_field_localization_mapper.dart';
|
||||||
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
||||||
import 'package:paperless_mobile/features/labels/cubit/label_cubit.dart';
|
|
||||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||||
|
|
||||||
class SortFieldSelectionBottomSheet extends StatefulWidget {
|
class SortFieldSelectionBottomSheet extends StatefulWidget {
|
||||||
@@ -29,12 +27,10 @@ class SortFieldSelectionBottomSheet extends StatefulWidget {
|
|||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<SortFieldSelectionBottomSheet> createState() =>
|
State<SortFieldSelectionBottomSheet> createState() => _SortFieldSelectionBottomSheetState();
|
||||||
_SortFieldSelectionBottomSheetState();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class _SortFieldSelectionBottomSheetState
|
class _SortFieldSelectionBottomSheetState extends State<SortFieldSelectionBottomSheet> {
|
||||||
extends State<SortFieldSelectionBottomSheet> {
|
|
||||||
late SortField? _currentSortField;
|
late SortField? _currentSortField;
|
||||||
late SortOrder _currentSortOrder;
|
late SortOrder _currentSortOrder;
|
||||||
|
|
||||||
@@ -62,8 +58,8 @@ class _SortFieldSelectionBottomSheetState
|
|||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
child: Text(S.of(context)!.apply),
|
child: Text(S.of(context)!.apply),
|
||||||
onPressed: () {
|
onPressed: () async {
|
||||||
widget.onSubmit(
|
await widget.onSubmit(
|
||||||
_currentSortField,
|
_currentSortField,
|
||||||
_currentSortOrder,
|
_currentSortOrder,
|
||||||
);
|
);
|
||||||
@@ -131,7 +127,9 @@ class _SortFieldSelectionBottomSheetState
|
|||||||
contentPadding: const EdgeInsets.only(left: 32, right: 16),
|
contentPadding: const EdgeInsets.only(left: 32, right: 16),
|
||||||
title: Text(translateSortField(context, field)),
|
title: Text(translateSortField(context, field)),
|
||||||
trailing: _currentSortField == field ? const Icon(Icons.done) : null,
|
trailing: _currentSortField == field ? const Icon(Icons.done) : null,
|
||||||
onTap: () => setState(() => _currentSortField = field),
|
onTap: () {
|
||||||
|
setState(() => _currentSortField = field);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:paperless_api/paperless_api.dart';
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
|
||||||
import 'package:paperless_mobile/core/translation/sort_field_localization_mapper.dart';
|
import 'package:paperless_mobile/core/translation/sort_field_localization_mapper.dart';
|
||||||
import 'package:paperless_mobile/features/documents/cubit/documents_cubit.dart';
|
import 'package:paperless_mobile/features/documents/cubit/documents_cubit.dart';
|
||||||
import 'package:paperless_mobile/features/documents/view/widgets/search/sort_field_selection_bottom_sheet.dart';
|
import 'package:paperless_mobile/features/documents/view/widgets/search/sort_field_selection_bottom_sheet.dart';
|
||||||
@@ -21,6 +20,7 @@ class SortDocumentsButton extends StatelessWidget {
|
|||||||
if (state.filter.sortField == null) {
|
if (state.filter.sortField == null) {
|
||||||
return const SizedBox.shrink();
|
return const SizedBox.shrink();
|
||||||
}
|
}
|
||||||
|
print(state.filter.sortField);
|
||||||
return TextButton.icon(
|
return TextButton.icon(
|
||||||
icon: Icon(state.filter.sortOrder == SortOrder.ascending
|
icon: Icon(state.filter.sortOrder == SortOrder.ascending
|
||||||
? Icons.arrow_upward
|
? Icons.arrow_upward
|
||||||
@@ -49,14 +49,14 @@ class SortDocumentsButton extends StatelessWidget {
|
|||||||
child: SortFieldSelectionBottomSheet(
|
child: SortFieldSelectionBottomSheet(
|
||||||
initialSortField: state.filter.sortField,
|
initialSortField: state.filter.sortField,
|
||||||
initialSortOrder: state.filter.sortOrder,
|
initialSortOrder: state.filter.sortOrder,
|
||||||
onSubmit: (field, order) => context
|
onSubmit: (field, order) {
|
||||||
.read<DocumentsCubit>()
|
return context.read<DocumentsCubit>().updateCurrentFilter(
|
||||||
.updateCurrentFilter(
|
(filter) => filter.copyWith(
|
||||||
(filter) => filter.copyWith(
|
sortField: field,
|
||||||
sortField: field,
|
sortOrder: order,
|
||||||
sortOrder: order,
|
),
|
||||||
),
|
);
|
||||||
),
|
},
|
||||||
correspondents: state.correspondents,
|
correspondents: state.correspondents,
|
||||||
documentTypes: state.documentTypes,
|
documentTypes: state.documentTypes,
|
||||||
storagePaths: state.storagePaths,
|
storagePaths: state.storagePaths,
|
||||||
|
|||||||
@@ -9,13 +9,13 @@ import 'package:fluttertoast/fluttertoast.dart';
|
|||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
import 'package:paperless_api/paperless_api.dart';
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
import 'package:paperless_mobile/core/bloc/connectivity_cubit.dart';
|
import 'package:paperless_mobile/core/bloc/connectivity_cubit.dart';
|
||||||
import 'package:paperless_mobile/core/bloc/server_information_cubit.dart';
|
|
||||||
import 'package:paperless_mobile/core/config/hive/hive_config.dart';
|
import 'package:paperless_mobile/core/config/hive/hive_config.dart';
|
||||||
import 'package:paperless_mobile/core/database/tables/global_settings.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_app_state.dart';
|
||||||
import 'package:paperless_mobile/core/global/constants.dart';
|
import 'package:paperless_mobile/core/global/constants.dart';
|
||||||
import 'package:paperless_mobile/core/repository/label_repository.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/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/service/file_description.dart';
|
||||||
import 'package:paperless_mobile/core/translation/error_code_localization_mapper.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/cubit/document_scanner_cubit.dart';
|
||||||
@@ -44,7 +44,8 @@ import 'package:responsive_builder/responsive_builder.dart';
|
|||||||
/// Wrapper around all functionality for a logged in user.
|
/// Wrapper around all functionality for a logged in user.
|
||||||
/// Performs initialization logic.
|
/// Performs initialization logic.
|
||||||
class HomePage extends StatefulWidget {
|
class HomePage extends StatefulWidget {
|
||||||
const HomePage({Key? key}) : super(key: key);
|
final int paperlessApiVersion;
|
||||||
|
const HomePage({Key? key, required this.paperlessApiVersion}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_HomePageState createState() => _HomePageState();
|
_HomePageState createState() => _HomePageState();
|
||||||
@@ -186,8 +187,6 @@ class _HomePageState extends State<HomePage> with WidgetsBindingObserver {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final userId =
|
|
||||||
Hive.box<GlobalSettings>(HiveBoxes.globalSettings).getValue()!.currentLoggedInUser!;
|
|
||||||
final destinations = [
|
final destinations = [
|
||||||
RouteDescription(
|
RouteDescription(
|
||||||
icon: const Icon(Icons.description_outlined),
|
icon: const Icon(Icons.description_outlined),
|
||||||
@@ -235,6 +234,7 @@ class _HomePageState extends State<HomePage> with WidgetsBindingObserver {
|
|||||||
];
|
];
|
||||||
final routes = <Widget>[
|
final routes = <Widget>[
|
||||||
const DocumentsPage(),
|
const DocumentsPage(),
|
||||||
|
if (LocalUserAccount.current.paperlessUser.hasPermission(UserPermissions.changeDocument))
|
||||||
const ScannerPage(),
|
const ScannerPage(),
|
||||||
const LabelsPage(),
|
const LabelsPage(),
|
||||||
const InboxPage(),
|
const InboxPage(),
|
||||||
@@ -303,7 +303,6 @@ class _HomePageState extends State<HomePage> with WidgetsBindingObserver {
|
|||||||
Future.wait([
|
Future.wait([
|
||||||
context.read<LabelRepository>().initialize(),
|
context.read<LabelRepository>().initialize(),
|
||||||
context.read<SavedViewRepository>().findAll(),
|
context.read<SavedViewRepository>().findAll(),
|
||||||
context.read<ServerInformationCubit>().updateInformation(),
|
|
||||||
]).onError<PaperlessServerException>((error, stackTrace) {
|
]).onError<PaperlessServerException>((error, stackTrace) {
|
||||||
showErrorMessage(context, error, stackTrace);
|
showErrorMessage(context, error, stackTrace);
|
||||||
throw error;
|
throw error;
|
||||||
|
|||||||
@@ -3,18 +3,19 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
|
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
|
||||||
import 'package:hive_flutter/adapters.dart';
|
import 'package:hive_flutter/adapters.dart';
|
||||||
import 'package:paperless_api/paperless_api.dart';
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
import 'package:paperless_mobile/core/bloc/server_information_cubit.dart';
|
|
||||||
import 'package:paperless_mobile/core/config/hive/hive_config.dart';
|
import 'package:paperless_mobile/core/config/hive/hive_config.dart';
|
||||||
import 'package:paperless_mobile/core/database/tables/local_user_app_state.dart';
|
import 'package:paperless_mobile/core/database/tables/local_user_app_state.dart';
|
||||||
import 'package:paperless_mobile/core/factory/paperless_api_factory.dart';
|
import 'package:paperless_mobile/core/factory/paperless_api_factory.dart';
|
||||||
import 'package:paperless_mobile/core/notifier/document_changed_notifier.dart';
|
import 'package:paperless_mobile/core/notifier/document_changed_notifier.dart';
|
||||||
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
||||||
import 'package:paperless_mobile/core/repository/saved_view_repository.dart';
|
import 'package:paperless_mobile/core/repository/saved_view_repository.dart';
|
||||||
|
import 'package:paperless_mobile/core/repository/user_repository.dart';
|
||||||
import 'package:paperless_mobile/core/security/session_manager.dart';
|
import 'package:paperless_mobile/core/security/session_manager.dart';
|
||||||
import 'package:paperless_mobile/core/service/dio_file_service.dart';
|
import 'package:paperless_mobile/core/service/dio_file_service.dart';
|
||||||
import 'package:paperless_mobile/features/document_scan/cubit/document_scanner_cubit.dart';
|
import 'package:paperless_mobile/features/document_scan/cubit/document_scanner_cubit.dart';
|
||||||
import 'package:paperless_mobile/features/documents/cubit/documents_cubit.dart';
|
import 'package:paperless_mobile/features/documents/cubit/documents_cubit.dart';
|
||||||
import 'package:paperless_mobile/features/home/view/home_page.dart';
|
import 'package:paperless_mobile/features/home/view/home_page.dart';
|
||||||
|
import 'package:paperless_mobile/features/home/view/model/api_version.dart';
|
||||||
import 'package:paperless_mobile/features/inbox/cubit/inbox_cubit.dart';
|
import 'package:paperless_mobile/features/inbox/cubit/inbox_cubit.dart';
|
||||||
import 'package:paperless_mobile/features/labels/cubit/label_cubit.dart';
|
import 'package:paperless_mobile/features/labels/cubit/label_cubit.dart';
|
||||||
import 'package:paperless_mobile/features/saved_view/cubit/saved_view_cubit.dart';
|
import 'package:paperless_mobile/features/saved_view/cubit/saved_view_cubit.dart';
|
||||||
@@ -46,6 +47,7 @@ class HomeRoute extends StatelessWidget {
|
|||||||
final currentLocalUserId = settings.currentLoggedInUser!;
|
final currentLocalUserId = settings.currentLoggedInUser!;
|
||||||
return MultiProvider(
|
return MultiProvider(
|
||||||
providers: [
|
providers: [
|
||||||
|
Provider.value(value: ApiVersion(paperlessApiVersion)),
|
||||||
Provider<CacheManager>(
|
Provider<CacheManager>(
|
||||||
create: (context) => CacheManager(
|
create: (context) => CacheManager(
|
||||||
Config(
|
Config(
|
||||||
@@ -85,6 +87,12 @@ class HomeRoute extends StatelessWidget {
|
|||||||
apiVersion: paperlessApiVersion,
|
apiVersion: paperlessApiVersion,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
if (paperlessApiVersion >= 3)
|
||||||
|
ProxyProvider<SessionManager, PaperlessUserApiV3>(
|
||||||
|
update: (context, value, previous) => PaperlessUserApiV3Impl(
|
||||||
|
value.client,
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
builder: (context, child) {
|
builder: (context, child) {
|
||||||
return MultiProvider(
|
return MultiProvider(
|
||||||
@@ -97,7 +105,7 @@ class HomeRoute extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
builder: (context, child) {
|
builder: (context, child) {
|
||||||
return MultiBlocProvider(
|
return MultiProvider(
|
||||||
providers: [
|
providers: [
|
||||||
ProxyProvider3<PaperlessDocumentsApi, DocumentChangedNotifier, LabelRepository,
|
ProxyProvider3<PaperlessDocumentsApi, DocumentChangedNotifier, LabelRepository,
|
||||||
DocumentsCubit>(
|
DocumentsCubit>(
|
||||||
@@ -120,24 +128,23 @@ class HomeRoute extends StatelessWidget {
|
|||||||
notifier,
|
notifier,
|
||||||
)..initialize(),
|
)..initialize(),
|
||||||
),
|
),
|
||||||
ProxyProvider2<SavedViewRepository, LabelRepository, SavedViewCubit>(
|
ProxyProvider<SavedViewRepository, SavedViewCubit>(
|
||||||
update: (context, savedViewRepo, labelRepo, previous) => SavedViewCubit(
|
update: (context, savedViewRepo, previous) => SavedViewCubit(
|
||||||
savedViewRepo,
|
savedViewRepo,
|
||||||
labelRepo,
|
|
||||||
)..initialize(),
|
)..initialize(),
|
||||||
),
|
),
|
||||||
ProxyProvider<PaperlessServerStatsApi, ServerInformationCubit>(
|
|
||||||
update: (context, value, previous) =>
|
|
||||||
ServerInformationCubit(value)..updateInformation(),
|
|
||||||
),
|
|
||||||
ProxyProvider<LabelRepository, LabelCubit>(
|
ProxyProvider<LabelRepository, LabelCubit>(
|
||||||
update: (context, value, previous) => LabelCubit(value),
|
update: (context, value, previous) => LabelCubit(value),
|
||||||
),
|
),
|
||||||
ProxyProvider<PaperlessTasksApi, TaskStatusCubit>(
|
ProxyProvider<PaperlessTasksApi, TaskStatusCubit>(
|
||||||
update: (context, value, previous) => TaskStatusCubit(value),
|
update: (context, value, previous) => TaskStatusCubit(value),
|
||||||
),
|
),
|
||||||
|
if (paperlessApiVersion >= 3)
|
||||||
|
ProxyProvider<PaperlessUserApiV3, UserRepository>(
|
||||||
|
update: (context, value, previous) => UserRepository(value)..initialize(),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
child: const HomePage(),
|
child: HomePage(paperlessApiVersion: paperlessApiVersion),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
8
lib/features/home/view/model/api_version.dart
Normal file
8
lib/features/home/view/model/api_version.dart
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
class ApiVersion {
|
||||||
|
final int version;
|
||||||
|
|
||||||
|
ApiVersion(this.version);
|
||||||
|
|
||||||
|
bool get supportsPermissions => version >= 3;
|
||||||
|
bool get hasMultiUserSupport => version >= 3;
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ import 'package:collection/collection.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:paperless_api/paperless_api.dart';
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
|
import 'package:paperless_mobile/core/navigation/push_routes.dart';
|
||||||
import 'package:paperless_mobile/core/workarounds/colored_chip.dart';
|
import 'package:paperless_mobile/core/workarounds/colored_chip.dart';
|
||||||
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
||||||
import 'package:paperless_mobile/features/documents/view/widgets/delete_document_confirmation_dialog.dart';
|
import 'package:paperless_mobile/features/documents/view/widgets/delete_document_confirmation_dialog.dart';
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:paperless_mobile/core/bloc/connectivity_cubit.dart';
|
import 'package:paperless_mobile/core/bloc/connectivity_cubit.dart';
|
||||||
|
import 'package:paperless_mobile/core/navigation/push_routes.dart';
|
||||||
import 'package:paperless_mobile/features/documents/view/widgets/adaptive_documents_view.dart';
|
import 'package:paperless_mobile/features/documents/view/widgets/adaptive_documents_view.dart';
|
||||||
import 'package:paperless_mobile/features/documents/view/widgets/selection/view_type_selection_widget.dart';
|
import 'package:paperless_mobile/features/documents/view/widgets/selection/view_type_selection_widget.dart';
|
||||||
import 'package:paperless_mobile/features/linked_documents/cubit/linked_documents_cubit.dart';
|
import 'package:paperless_mobile/features/linked_documents/cubit/linked_documents_cubit.dart';
|
||||||
|
|||||||
@@ -3,25 +3,24 @@ import 'dart:typed_data';
|
|||||||
|
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
|
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
import 'package:hive_flutter/adapters.dart';
|
import 'package:hive_flutter/adapters.dart';
|
||||||
import 'package:hydrated_bloc/hydrated_bloc.dart';
|
import 'package:hydrated_bloc/hydrated_bloc.dart';
|
||||||
import 'package:paperless_api/paperless_api.dart';
|
|
||||||
import 'package:paperless_mobile/core/config/hive/hive_config.dart';
|
import 'package:paperless_mobile/core/config/hive/hive_config.dart';
|
||||||
|
import 'package:paperless_mobile/core/database/tables/global_settings.dart';
|
||||||
|
import 'package:paperless_mobile/core/database/tables/local_user_account.dart';
|
||||||
import 'package:paperless_mobile/core/database/tables/local_user_app_state.dart';
|
import 'package:paperless_mobile/core/database/tables/local_user_app_state.dart';
|
||||||
|
import 'package:paperless_mobile/core/database/tables/local_user_settings.dart';
|
||||||
|
import 'package:paperless_mobile/core/database/tables/user_credentials.dart';
|
||||||
import 'package:paperless_mobile/core/factory/paperless_api_factory.dart';
|
import 'package:paperless_mobile/core/factory/paperless_api_factory.dart';
|
||||||
import 'package:paperless_mobile/core/security/session_manager.dart';
|
import 'package:paperless_mobile/core/security/session_manager.dart';
|
||||||
import 'package:paperless_mobile/features/login/model/client_certificate.dart';
|
import 'package:paperless_mobile/features/login/model/client_certificate.dart';
|
||||||
import 'package:paperless_mobile/features/login/model/login_form_credentials.dart';
|
import 'package:paperless_mobile/features/login/model/login_form_credentials.dart';
|
||||||
import 'package:paperless_mobile/core/database/tables/local_user_account.dart';
|
|
||||||
import 'package:paperless_mobile/core/database/tables/user_credentials.dart';
|
|
||||||
import 'package:paperless_mobile/features/login/services/authentication_service.dart';
|
import 'package:paperless_mobile/features/login/services/authentication_service.dart';
|
||||||
import 'package:paperless_mobile/core/database/tables/global_settings.dart';
|
|
||||||
import 'package:paperless_mobile/core/database/tables/local_user_settings.dart';
|
|
||||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
|
||||||
|
|
||||||
part 'authentication_state.dart';
|
|
||||||
part 'authentication_cubit.freezed.dart';
|
part 'authentication_cubit.freezed.dart';
|
||||||
|
part 'authentication_state.dart';
|
||||||
|
|
||||||
class AuthenticationCubit extends Cubit<AuthenticationState> {
|
class AuthenticationCubit extends Cubit<AuthenticationState> {
|
||||||
final LocalAuthenticationService _localAuthService;
|
final LocalAuthenticationService _localAuthService;
|
||||||
@@ -111,6 +110,12 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
|
|||||||
|
|
||||||
final apiVersion = await _getApiVersion(_sessionManager.client);
|
final apiVersion = await _getApiVersion(_sessionManager.client);
|
||||||
|
|
||||||
|
await _updateRemoteUser(
|
||||||
|
_sessionManager,
|
||||||
|
Hive.box<LocalUserAccount>(HiveBoxes.localUserAccount).get(localUserId)!,
|
||||||
|
apiVersion,
|
||||||
|
);
|
||||||
|
|
||||||
emit(AuthenticationState.authenticated(
|
emit(AuthenticationState.authenticated(
|
||||||
localUserId: localUserId,
|
localUserId: localUserId,
|
||||||
apiVersion: apiVersion,
|
apiVersion: apiVersion,
|
||||||
@@ -163,10 +168,10 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
|
|||||||
// If there is nothing to restore, we can quit here.
|
// If there is nothing to restore, we can quit here.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
final localUserAccountBox = Hive.box<LocalUserAccount>(HiveBoxes.localUserAccount);
|
||||||
|
final localUserAccount = localUserAccountBox.get(localUserId)!;
|
||||||
|
|
||||||
final userAccount = Hive.box<LocalUserAccount>(HiveBoxes.localUserAccount).get(localUserId)!;
|
if (localUserAccount.settings.isBiometricAuthenticationEnabled) {
|
||||||
|
|
||||||
if (userAccount.settings.isBiometricAuthenticationEnabled) {
|
|
||||||
final localAuthSuccess =
|
final localAuthSuccess =
|
||||||
await _localAuthService.authenticateLocalUser("Authenticate to log back in"); //TODO: INTL
|
await _localAuthService.authenticateLocalUser("Authenticate to log back in"); //TODO: INTL
|
||||||
if (!localAuthSuccess) {
|
if (!localAuthSuccess) {
|
||||||
@@ -176,18 +181,23 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
|
|||||||
}
|
}
|
||||||
final userCredentialsBox = await _getUserCredentialsBox();
|
final userCredentialsBox = await _getUserCredentialsBox();
|
||||||
final authentication = userCredentialsBox.get(globalSettings.currentLoggedInUser!);
|
final authentication = userCredentialsBox.get(globalSettings.currentLoggedInUser!);
|
||||||
|
|
||||||
await userCredentialsBox.close();
|
await userCredentialsBox.close();
|
||||||
|
|
||||||
if (authentication == null) {
|
if (authentication == null) {
|
||||||
throw Exception("User should be authenticated but no authentication information was found.");
|
throw Exception(
|
||||||
|
"User should be authenticated but no authentication information was found."); //TODO: INTL
|
||||||
}
|
}
|
||||||
_sessionManager.updateSettings(
|
_sessionManager.updateSettings(
|
||||||
clientCertificate: authentication.clientCertificate,
|
clientCertificate: authentication.clientCertificate,
|
||||||
authToken: authentication.token,
|
authToken: authentication.token,
|
||||||
baseUrl: userAccount.serverUrl,
|
baseUrl: localUserAccount.serverUrl,
|
||||||
);
|
);
|
||||||
final apiVersion = await _getApiVersion(_sessionManager.client);
|
final apiVersion = await _getApiVersion(_sessionManager.client);
|
||||||
|
await _updateRemoteUser(
|
||||||
|
_sessionManager,
|
||||||
|
localUserAccount,
|
||||||
|
apiVersion,
|
||||||
|
);
|
||||||
emit(
|
emit(
|
||||||
AuthenticationState.authenticated(
|
AuthenticationState.authenticated(
|
||||||
apiVersion: apiVersion,
|
apiVersion: apiVersion,
|
||||||
@@ -308,4 +318,20 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
|
|||||||
final response = await dio.get("/api/");
|
final response = await dio.get("/api/");
|
||||||
return int.parse(response.headers.value('x-api-version') ?? "3");
|
return int.parse(response.headers.value('x-api-version') ?? "3");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Fetches possibly updated (permissions, name, updated server version and thus new user model, ...) remote user data.
|
||||||
|
Future<void> _updateRemoteUser(
|
||||||
|
SessionManager sessionManager,
|
||||||
|
LocalUserAccount localUserAccount,
|
||||||
|
int apiVersion,
|
||||||
|
) async {
|
||||||
|
final updatedPaperlessUser = await _apiFactory
|
||||||
|
.createUserApi(
|
||||||
|
sessionManager.client,
|
||||||
|
apiVersion: apiVersion,
|
||||||
|
)
|
||||||
|
.findCurrentUser();
|
||||||
|
localUserAccount.paperlessUser = updatedPaperlessUser;
|
||||||
|
await localUserAccount.save();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,38 +11,14 @@ part 'saved_view_cubit.freezed.dart';
|
|||||||
|
|
||||||
class SavedViewCubit extends Cubit<SavedViewState> {
|
class SavedViewCubit extends Cubit<SavedViewState> {
|
||||||
final SavedViewRepository _savedViewRepository;
|
final SavedViewRepository _savedViewRepository;
|
||||||
final LabelRepository _labelRepository;
|
|
||||||
|
|
||||||
SavedViewCubit(this._savedViewRepository, this._labelRepository)
|
|
||||||
: super(
|
|
||||||
SavedViewState.initial(
|
|
||||||
correspondents: _labelRepository.state.correspondents,
|
|
||||||
documentTypes: _labelRepository.state.documentTypes,
|
|
||||||
storagePaths: _labelRepository.state.storagePaths,
|
|
||||||
tags: _labelRepository.state.tags,
|
|
||||||
),
|
|
||||||
) {
|
|
||||||
_labelRepository.addListener(
|
|
||||||
this,
|
|
||||||
onChanged: (labels) {
|
|
||||||
emit(
|
|
||||||
state.copyWith(
|
|
||||||
correspondents: labels.correspondents,
|
|
||||||
documentTypes: labels.documentTypes,
|
|
||||||
tags: labels.tags,
|
|
||||||
storagePaths: labels.storagePaths,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
|
SavedViewCubit(this._savedViewRepository) : super(const SavedViewState.initial()) {
|
||||||
_savedViewRepository.addListener(
|
_savedViewRepository.addListener(
|
||||||
this,
|
this,
|
||||||
onChanged: (views) {
|
onChanged: (views) {
|
||||||
emit(
|
emit(
|
||||||
state.maybeWhen(
|
state.maybeWhen(
|
||||||
loaded: (savedViews, correspondents, documentTypes, tags, storagePaths) =>
|
loaded: (savedViews) => (state as _SavedViewLoadedState).copyWith(
|
||||||
(state as _SavedViewLoadedState).copyWith(
|
|
||||||
savedViews: views.savedViews,
|
savedViews: views.savedViews,
|
||||||
),
|
),
|
||||||
orElse: () => state,
|
orElse: () => state,
|
||||||
@@ -64,13 +40,11 @@ class SavedViewCubit extends Cubit<SavedViewState> {
|
|||||||
final views = await _savedViewRepository.findAll();
|
final views = await _savedViewRepository.findAll();
|
||||||
final values = {for (var element in views) element.id!: element};
|
final values = {for (var element in views) element.id!: element};
|
||||||
if (!isClosed) {
|
if (!isClosed) {
|
||||||
emit(SavedViewState.loaded(
|
emit(
|
||||||
savedViews: values,
|
SavedViewState.loaded(
|
||||||
correspondents: state.correspondents,
|
savedViews: values,
|
||||||
documentTypes: state.documentTypes,
|
),
|
||||||
storagePaths: state.storagePaths,
|
);
|
||||||
tags: state.tags,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,7 +53,6 @@ class SavedViewCubit extends Cubit<SavedViewState> {
|
|||||||
@override
|
@override
|
||||||
Future<void> close() {
|
Future<void> close() {
|
||||||
_savedViewRepository.removeListener(this);
|
_savedViewRepository.removeListener(this);
|
||||||
_labelRepository.removeListener(this);
|
|
||||||
return super.close();
|
return super.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -2,32 +2,12 @@ part of 'saved_view_cubit.dart';
|
|||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
class SavedViewState with _$SavedViewState {
|
class SavedViewState with _$SavedViewState {
|
||||||
const factory SavedViewState.initial({
|
const factory SavedViewState.initial() = _SavedViewIntialState;
|
||||||
required Map<int, Correspondent> correspondents,
|
|
||||||
required Map<int, DocumentType> documentTypes,
|
|
||||||
required Map<int, Tag> tags,
|
|
||||||
required Map<int, StoragePath> storagePaths,
|
|
||||||
}) = _SavedViewIntialState;
|
|
||||||
|
|
||||||
const factory SavedViewState.loading({
|
const factory SavedViewState.loading() = _SavedViewLoadingState;
|
||||||
required Map<int, Correspondent> correspondents,
|
|
||||||
required Map<int, DocumentType> documentTypes,
|
|
||||||
required Map<int, Tag> tags,
|
|
||||||
required Map<int, StoragePath> storagePaths,
|
|
||||||
}) = _SavedViewLoadingState;
|
|
||||||
|
|
||||||
const factory SavedViewState.loaded({
|
const factory SavedViewState.loaded({required Map<int, SavedView> savedViews}) =
|
||||||
required Map<int, SavedView> savedViews,
|
_SavedViewLoadedState;
|
||||||
required Map<int, Correspondent> correspondents,
|
|
||||||
required Map<int, DocumentType> documentTypes,
|
|
||||||
required Map<int, Tag> tags,
|
|
||||||
required Map<int, StoragePath> storagePaths,
|
|
||||||
}) = _SavedViewLoadedState;
|
|
||||||
|
|
||||||
const factory SavedViewState.error({
|
const factory SavedViewState.error() = _SavedViewErrorState;
|
||||||
required Map<int, Correspondent> correspondents,
|
|
||||||
required Map<int, DocumentType> documentTypes,
|
|
||||||
required Map<int, Tag> tags,
|
|
||||||
required Map<int, StoragePath> storagePaths,
|
|
||||||
}) = _SavedViewErrorState;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import 'package:paperless_mobile/core/bloc/connectivity_cubit.dart';
|
|||||||
import 'package:paperless_mobile/core/config/hive/hive_config.dart';
|
import 'package:paperless_mobile/core/config/hive/hive_config.dart';
|
||||||
import 'package:paperless_mobile/core/database/tables/global_settings.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_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/core/widgets/hint_card.dart';
|
||||||
import 'package:paperless_mobile/features/saved_view/cubit/saved_view_cubit.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/cubit/saved_view_details_cubit.dart';
|
||||||
@@ -21,17 +22,13 @@ class SavedViewList extends StatelessWidget {
|
|||||||
return BlocBuilder<SavedViewCubit, SavedViewState>(
|
return BlocBuilder<SavedViewCubit, SavedViewState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
return state.when(
|
return state.when(
|
||||||
initial: (correspondents, documentTypes, tags, storagePaths) => Container(),
|
initial: () => SliverToBoxAdapter(child: Container()),
|
||||||
loading: (correspondents, documentTypes, tags, storagePaths) => Center(
|
loading: () => SliverToBoxAdapter(
|
||||||
child: Text("Saved views loading..."), //TODO: INTL
|
child: Center(
|
||||||
|
child: Text("Saved views loading..."), //TODO: INTL
|
||||||
|
),
|
||||||
),
|
),
|
||||||
loaded: (
|
loaded: (savedViews) {
|
||||||
savedViews,
|
|
||||||
correspondents,
|
|
||||||
documentTypes,
|
|
||||||
tags,
|
|
||||||
storagePaths,
|
|
||||||
) {
|
|
||||||
if (savedViews.isEmpty) {
|
if (savedViews.isEmpty) {
|
||||||
return SliverToBoxAdapter(
|
return SliverToBoxAdapter(
|
||||||
child: HintCard(
|
child: HintCard(
|
||||||
@@ -50,30 +47,7 @@ class SavedViewList extends StatelessWidget {
|
|||||||
S.of(context)!.nFiltersSet(view.filterRules.length),
|
S.of(context)!.nFiltersSet(view.filterRules.length),
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.of(context).push(
|
pushSavedViewDetailsRoute(context, savedView: view);
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (ctxt) => MultiBlocProvider(
|
|
||||||
providers: [
|
|
||||||
BlocProvider(
|
|
||||||
create: (context) => SavedViewDetailsCubit(
|
|
||||||
ctxt.read(),
|
|
||||||
ctxt.read(),
|
|
||||||
context.read(),
|
|
||||||
Hive.box<LocalUserAppState>(HiveBoxes.localUserAppState).get(
|
|
||||||
Hive.box<GlobalSettings>(HiveBoxes.globalSettings)
|
|
||||||
.getValue()!
|
|
||||||
.currentLoggedInUser!,
|
|
||||||
)!,
|
|
||||||
savedView: view,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
child: SavedViewDetailsPage(
|
|
||||||
onDelete: context.read<SavedViewCubit>().remove,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -81,13 +55,7 @@ class SavedViewList extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
error: (
|
error: () => Center(
|
||||||
correspondents,
|
|
||||||
documentTypes,
|
|
||||||
tags,
|
|
||||||
storagePaths,
|
|
||||||
) =>
|
|
||||||
Center(
|
|
||||||
child: Text(
|
child: Text(
|
||||||
"An error occurred while trying to load the saved views.",
|
"An error occurred while trying to load the saved views.",
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:paperless_api/paperless_api.dart';
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
import 'package:paperless_mobile/core/bloc/connectivity_cubit.dart';
|
import 'package:paperless_mobile/core/bloc/connectivity_cubit.dart';
|
||||||
|
import 'package:paperless_mobile/core/navigation/push_routes.dart';
|
||||||
import 'package:paperless_mobile/features/documents/view/widgets/adaptive_documents_view.dart';
|
import 'package:paperless_mobile/features/documents/view/widgets/adaptive_documents_view.dart';
|
||||||
import 'package:paperless_mobile/features/documents/view/widgets/documents_empty_state.dart';
|
import 'package:paperless_mobile/features/documents/view/widgets/documents_empty_state.dart';
|
||||||
import 'package:paperless_mobile/features/documents/view/widgets/selection/confirm_delete_saved_view_dialog.dart';
|
import 'package:paperless_mobile/features/documents/view/widgets/selection/confirm_delete_saved_view_dialog.dart';
|
||||||
@@ -76,14 +77,10 @@ class _SavedViewDetailsPageState extends State<SavedViewDetailsPage>
|
|||||||
isLoading: state.isLoading,
|
isLoading: state.isLoading,
|
||||||
hasLoaded: state.hasLoaded,
|
hasLoaded: state.hasLoaded,
|
||||||
onTap: (document) {
|
onTap: (document) {
|
||||||
Navigator.push(
|
pushDocumentDetailsRoute(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
document: document,
|
||||||
builder: (context) => DocumentDetailsRoute(
|
isLabelClickable: false,
|
||||||
document: document,
|
|
||||||
isLabelClickable: false,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
viewType: state.viewType,
|
viewType: state.viewType,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import 'package:hive_flutter/adapters.dart';
|
|||||||
import 'package:paperless_mobile/core/config/hive/hive_config.dart';
|
import 'package:paperless_mobile/core/config/hive/hive_config.dart';
|
||||||
import 'package:paperless_mobile/core/database/tables/global_settings.dart';
|
import 'package:paperless_mobile/core/database/tables/global_settings.dart';
|
||||||
import 'package:paperless_mobile/core/database/tables/local_user_account.dart';
|
import 'package:paperless_mobile/core/database/tables/local_user_account.dart';
|
||||||
|
import 'package:paperless_mobile/features/home/view/model/api_version.dart';
|
||||||
import 'package:paperless_mobile/features/login/cubit/authentication_cubit.dart';
|
import 'package:paperless_mobile/features/login/cubit/authentication_cubit.dart';
|
||||||
import 'package:paperless_mobile/features/login/model/login_form_credentials.dart';
|
import 'package:paperless_mobile/features/login/model/login_form_credentials.dart';
|
||||||
import 'package:paperless_mobile/features/login/view/login_page.dart';
|
import 'package:paperless_mobile/features/login/view/login_page.dart';
|
||||||
@@ -13,6 +14,7 @@ import 'package:paperless_mobile/features/settings/view/pages/switching_accounts
|
|||||||
import 'package:paperless_mobile/features/settings/view/widgets/global_settings_builder.dart';
|
import 'package:paperless_mobile/features/settings/view/widgets/global_settings_builder.dart';
|
||||||
import 'package:paperless_mobile/features/settings/view/widgets/user_avatar.dart';
|
import 'package:paperless_mobile/features/settings/view/widgets/user_avatar.dart';
|
||||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class ManageAccountsPage extends StatelessWidget {
|
class ManageAccountsPage extends StatelessWidget {
|
||||||
const ManageAccountsPage({super.key});
|
const ManageAccountsPage({super.key});
|
||||||
@@ -67,6 +69,17 @@ class ManageAccountsPage extends StatelessWidget {
|
|||||||
_onAddAccount(context, globalSettings.currentLoggedInUser!);
|
_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();
|
||||||
|
},
|
||||||
|
)
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
import 'package:flutter/material.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/bloc/server_information_cubit.dart';
|
|
||||||
import 'package:paperless_mobile/core/bloc/server_information_state.dart';
|
|
||||||
import 'package:paperless_mobile/features/settings/view/pages/application_settings_page.dart';
|
import 'package:paperless_mobile/features/settings/view/pages/application_settings_page.dart';
|
||||||
import 'package:paperless_mobile/features/settings/view/pages/security_settings_page.dart';
|
import 'package:paperless_mobile/features/settings/view/pages/security_settings_page.dart';
|
||||||
import 'package:paperless_mobile/features/settings/view/widgets/user_settings_builder.dart';
|
import 'package:paperless_mobile/features/settings/view/widgets/user_settings_builder.dart';
|
||||||
@@ -26,13 +24,21 @@ class SettingsPage extends StatelessWidget {
|
|||||||
style: Theme.of(context).textTheme.labelSmall,
|
style: Theme.of(context).textTheme.labelSmall,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
subtitle: BlocBuilder<ServerInformationCubit, ServerInformationState>(
|
subtitle: FutureBuilder<PaperlessServerInformationModel>(
|
||||||
builder: (context, state) {
|
builder: (context, snapshot) {
|
||||||
|
if (!snapshot.hasData) {
|
||||||
|
return Text(
|
||||||
|
"Loading server information...",
|
||||||
|
style: Theme.of(context).textTheme.labelSmall,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
final serverData = snapshot.data!;
|
||||||
return Text(
|
return Text(
|
||||||
S.of(context)!.paperlessServerVersion +
|
S.of(context)!.paperlessServerVersion +
|
||||||
' ' +
|
' ' +
|
||||||
state.information!.version.toString() +
|
serverData.version.toString() +
|
||||||
' (API v${state.information!.apiVersion})',
|
' (API v${serverData.apiVersion})',
|
||||||
style: Theme.of(context).textTheme.labelSmall,
|
style: Theme.of(context).textTheme.labelSmall,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,14 +2,13 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:paperless_api/paperless_api.dart';
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
import 'package:paperless_mobile/core/bloc/connectivity_cubit.dart';
|
import 'package:paperless_mobile/core/bloc/connectivity_cubit.dart';
|
||||||
|
import 'package:paperless_mobile/core/navigation/push_routes.dart';
|
||||||
import 'package:paperless_mobile/core/widgets/offline_widget.dart';
|
import 'package:paperless_mobile/core/widgets/offline_widget.dart';
|
||||||
import 'package:paperless_mobile/features/documents/view/widgets/adaptive_documents_view.dart';
|
import 'package:paperless_mobile/features/documents/view/widgets/adaptive_documents_view.dart';
|
||||||
import 'package:paperless_mobile/features/documents/view/widgets/documents_empty_state.dart';
|
|
||||||
import 'package:paperless_mobile/features/paged_document_view/view/document_paging_view_mixin.dart';
|
import 'package:paperless_mobile/features/paged_document_view/view/document_paging_view_mixin.dart';
|
||||||
import 'package:paperless_mobile/features/similar_documents/cubit/similar_documents_cubit.dart';
|
import 'package:paperless_mobile/features/similar_documents/cubit/similar_documents_cubit.dart';
|
||||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||||
import 'package:paperless_mobile/helpers/message_helpers.dart';
|
import 'package:paperless_mobile/helpers/message_helpers.dart';
|
||||||
import 'package:paperless_mobile/routes/document_details_route.dart';
|
|
||||||
|
|
||||||
class SimilarDocumentsView extends StatefulWidget {
|
class SimilarDocumentsView extends StatefulWidget {
|
||||||
final ScrollController pagingScrollController;
|
final ScrollController pagingScrollController;
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ import 'package:paperless_mobile/features/settings/view/widgets/global_settings_
|
|||||||
import 'package:paperless_mobile/features/sharing/share_intent_queue.dart';
|
import 'package:paperless_mobile/features/sharing/share_intent_queue.dart';
|
||||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||||
import 'package:paperless_mobile/helpers/message_helpers.dart';
|
import 'package:paperless_mobile/helpers/message_helpers.dart';
|
||||||
import 'package:paperless_mobile/routes/document_details_route.dart';
|
|
||||||
import 'package:paperless_mobile/theme.dart';
|
import 'package:paperless_mobile/theme.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
@@ -122,7 +121,6 @@ void main() async {
|
|||||||
});
|
});
|
||||||
|
|
||||||
final apiFactory = PaperlessApiFactoryImpl(sessionManager);
|
final apiFactory = PaperlessApiFactoryImpl(sessionManager);
|
||||||
|
|
||||||
runApp(
|
runApp(
|
||||||
MultiProvider(
|
MultiProvider(
|
||||||
providers: [
|
providers: [
|
||||||
@@ -220,10 +218,9 @@ class _AuthenticationWrapperState extends State<AuthenticationWrapper> {
|
|||||||
@override
|
@override
|
||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
context
|
context.read<AuthenticationCubit>().restoreSessionState().then((value) {
|
||||||
.read<AuthenticationCubit>()
|
FlutterNativeSplash.remove();
|
||||||
.restoreSessionState()
|
});
|
||||||
.then((value) => FlutterNativeSplash.remove());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -1,26 +1,19 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
|
|
||||||
import 'package:paperless_api/paperless_api.dart';
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
import 'package:paperless_mobile/core/notifier/document_changed_notifier.dart';
|
|
||||||
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
|
||||||
import 'package:paperless_mobile/features/document_details/cubit/document_details_cubit.dart';
|
import 'package:paperless_mobile/features/document_details/cubit/document_details_cubit.dart';
|
||||||
import 'package:paperless_mobile/features/document_details/view/pages/document_details_page.dart';
|
import 'package:paperless_mobile/features/document_details/view/pages/document_details_page.dart';
|
||||||
import 'package:paperless_mobile/features/notifications/services/local_notification_service.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
|
|
||||||
class DocumentDetailsRoute extends StatelessWidget {
|
class DocumentDetailsRoute extends StatelessWidget {
|
||||||
final DocumentModel document;
|
final DocumentModel document;
|
||||||
final bool isLabelClickable;
|
final bool isLabelClickable;
|
||||||
final bool allowEdit;
|
|
||||||
final String? titleAndContentQueryString;
|
final String? titleAndContentQueryString;
|
||||||
|
|
||||||
const DocumentDetailsRoute({
|
const DocumentDetailsRoute({
|
||||||
super.key,
|
super.key,
|
||||||
required this.document,
|
required this.document,
|
||||||
this.isLabelClickable = true,
|
this.isLabelClickable = true,
|
||||||
this.allowEdit = true,
|
|
||||||
this.titleAndContentQueryString,
|
this.titleAndContentQueryString,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -36,7 +29,6 @@ class DocumentDetailsRoute extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
lazy: false,
|
lazy: false,
|
||||||
child: DocumentDetailsPage(
|
child: DocumentDetailsPage(
|
||||||
allowEdit: allowEdit,
|
|
||||||
isLabelClickable: isLabelClickable,
|
isLabelClickable: isLabelClickable,
|
||||||
titleAndContentQueryString: titleAndContentQueryString,
|
titleAndContentQueryString: titleAndContentQueryString,
|
||||||
),
|
),
|
||||||
@@ -57,33 +49,3 @@ class DocumentDetailsRouteArguments {
|
|||||||
this.titleAndContentQueryString,
|
this.titleAndContentQueryString,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> pushDocumentDetailsRoute(
|
|
||||||
BuildContext context, {
|
|
||||||
required DocumentModel document,
|
|
||||||
bool isLabelClickable = true,
|
|
||||||
bool allowEdit = true,
|
|
||||||
String? titleAndContentQueryString,
|
|
||||||
}) {
|
|
||||||
final LabelRepository labelRepository = context.read();
|
|
||||||
final DocumentChangedNotifier changeNotifier = context.read();
|
|
||||||
final PaperlessDocumentsApi documentsApi = context.read();
|
|
||||||
final LocalNotificationService notificationservice = context.read();
|
|
||||||
final CacheManager cacheManager = context.read();
|
|
||||||
return Navigator.of(context).push(MaterialPageRoute(
|
|
||||||
builder: (_) => MultiProvider(
|
|
||||||
providers: [
|
|
||||||
Provider.value(value: documentsApi),
|
|
||||||
Provider.value(value: labelRepository),
|
|
||||||
Provider.value(value: changeNotifier),
|
|
||||||
Provider.value(value: notificationservice),
|
|
||||||
Provider.value(value: cacheManager),
|
|
||||||
],
|
|
||||||
child: DocumentDetailsRoute(
|
|
||||||
document: document,
|
|
||||||
allowEdit: allowEdit,
|
|
||||||
isLabelClickable: isLabelClickable,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -53,5 +53,6 @@ enum ErrorCode {
|
|||||||
requestTimedOut,
|
requestTimedOut,
|
||||||
unsupportedFileFormat,
|
unsupportedFileFormat,
|
||||||
missingClientCertificate,
|
missingClientCertificate,
|
||||||
acknowledgeTasksError;
|
acknowledgeTasksError,
|
||||||
|
notAuthorized;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,25 +3,17 @@ import 'package:paperless_api/src/request_utils.dart';
|
|||||||
class PaperlessServerInformationModel {
|
class PaperlessServerInformationModel {
|
||||||
static const String versionHeader = 'x-version';
|
static const String versionHeader = 'x-version';
|
||||||
static const String apiVersionHeader = 'x-api-version';
|
static const String apiVersionHeader = 'x-api-version';
|
||||||
static const String hostHeader = 'x-served-by';
|
final String version;
|
||||||
final String? version;
|
final int apiVersion;
|
||||||
final int? apiVersion;
|
final bool isUpdateAvailable;
|
||||||
final String? username;
|
|
||||||
final String? host;
|
|
||||||
|
|
||||||
String? get userInitials {
|
|
||||||
return username?.substring(0, 1).toUpperCase();
|
|
||||||
}
|
|
||||||
|
|
||||||
PaperlessServerInformationModel({
|
PaperlessServerInformationModel({
|
||||||
this.host,
|
required this.version,
|
||||||
this.username,
|
required this.apiVersion,
|
||||||
this.version = 'unknown',
|
required this.isUpdateAvailable,
|
||||||
this.apiVersion = 1,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
int compareToOtherVersion(String? other) {
|
int compareToOtherVersion(String other) {
|
||||||
return getExtendedVersionNumber(version ?? '0.0.0')
|
return getExtendedVersionNumber(version).compareTo(getExtendedVersionNumber(other));
|
||||||
.compareTo(getExtendedVersionNumber(other ?? '0.0.0'));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -130,7 +130,9 @@ enum InheritedPermissions {
|
|||||||
@HiveField(60)
|
@HiveField(60)
|
||||||
documentsChangeSavedviewfilterrule("documents.change_savedviewfilterrule"),
|
documentsChangeSavedviewfilterrule("documents.change_savedviewfilterrule"),
|
||||||
@HiveField(61)
|
@HiveField(61)
|
||||||
documentsChangeStoragepathdocuments("documents.change_storagepathdocuments.change_tag"),
|
documentsChangeStoragepath("documents.change_storagepath"),
|
||||||
|
@HiveField(111)
|
||||||
|
documentsChangeTag("documents.change_tag"),
|
||||||
@HiveField(62)
|
@HiveField(62)
|
||||||
documentsChangeUisettings("documents.change_uisettings"),
|
documentsChangeUisettings("documents.change_uisettings"),
|
||||||
@HiveField(63)
|
@HiveField(63)
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ class UserModel with _$UserModel {
|
|||||||
return value.userPermissions.contains(permission);
|
return value.userPermissions.contains(permission);
|
||||||
},
|
},
|
||||||
v2: (value) {
|
v2: (value) {
|
||||||
// In previous versions, all users have access to all
|
// In previous versions, all users have all permissions.
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -78,7 +78,6 @@ class PaperlessDocumentsApiImpl implements PaperlessDocumentsApi {
|
|||||||
throw const PaperlessServerException(ErrorCode.documentUpdateFailed);
|
throw const PaperlessServerException(ErrorCode.documentUpdateFailed);
|
||||||
}
|
}
|
||||||
} on DioError catch (err) {
|
} on DioError catch (err) {
|
||||||
//TODO: Handle 403 permission errors for 1.14.0
|
|
||||||
throw err.error!;
|
throw err.error!;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,16 +22,13 @@ class PaperlessServerStatsApiImpl implements PaperlessServerStatsApi {
|
|||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
final version = response.data["version"] as String;
|
final version = response.data["version"] as String;
|
||||||
final updateAvailable = response.data["update_available"] as bool;
|
final updateAvailable = response.data["update_available"] as bool;
|
||||||
|
return PaperlessServerInformationModel(
|
||||||
|
apiVersion: int.parse(response.headers.value('x-api-version')!),
|
||||||
|
version: version,
|
||||||
|
isUpdateAvailable: updateAvailable,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
throw PaperlessServerException.unknown();
|
throw const PaperlessServerException.unknown();
|
||||||
final version =
|
|
||||||
response.headers[PaperlessServerInformationModel.versionHeader]?.first ?? 'unknown';
|
|
||||||
final apiVersion = int.tryParse(
|
|
||||||
response.headers[PaperlessServerInformationModel.apiVersionHeader]?.first ?? '1');
|
|
||||||
return PaperlessServerInformationModel(
|
|
||||||
version: version,
|
|
||||||
apiVersion: apiVersion,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ class PaperlessUserApiV3Impl implements PaperlessUserApi, PaperlessUserApiV3 {
|
|||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
return PagedSearchResult<UserModelV3>.fromJson(
|
return PagedSearchResult<UserModelV3>.fromJson(
|
||||||
response.data,
|
response.data,
|
||||||
UserModelV3.fromJson as UserModelV3 Function(Object?),
|
(json) => UserModelV3.fromJson(json as dynamic),
|
||||||
).results;
|
).results;
|
||||||
}
|
}
|
||||||
throw const PaperlessServerException.unknown();
|
throw const PaperlessServerException.unknown();
|
||||||
|
|||||||
Reference in New Issue
Block a user