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