mirror of
https://github.com/Xevion/paperless-mobile.git
synced 2025-12-09 02:07:58 -06:00
feat: Externalize settings into LocalUserAppState, fix bugs
This commit is contained in:
@@ -1,19 +0,0 @@
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
||||||
import 'package:paperless_api/paperless_api.dart';
|
|
||||||
import 'package:paperless_mobile/core/bloc/paperless_server_information_state.dart';
|
|
||||||
|
|
||||||
class PaperlessServerInformationCubit
|
|
||||||
extends Cubit<PaperlessServerInformationState> {
|
|
||||||
final PaperlessServerStatsApi _api;
|
|
||||||
|
|
||||||
PaperlessServerInformationCubit(this._api)
|
|
||||||
: super(PaperlessServerInformationState());
|
|
||||||
|
|
||||||
Future<void> updateInformtion() async {
|
|
||||||
final information = await _api.getServerInformation();
|
|
||||||
emit(PaperlessServerInformationState(
|
|
||||||
isLoaded: true,
|
|
||||||
information: information,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
17
lib/core/bloc/server_information_cubit.dart
Normal file
17
lib/core/bloc/server_information_cubit.dart
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
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,10 +1,10 @@
|
|||||||
import 'package:paperless_api/paperless_api.dart';
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
|
|
||||||
class PaperlessServerInformationState {
|
class ServerInformationState {
|
||||||
final bool isLoaded;
|
final bool isLoaded;
|
||||||
final PaperlessServerInformationModel? information;
|
final PaperlessServerInformationModel? information;
|
||||||
|
|
||||||
PaperlessServerInformationState({
|
ServerInformationState({
|
||||||
this.isLoaded = false,
|
this.isLoaded = false,
|
||||||
this.information,
|
this.information,
|
||||||
});
|
});
|
||||||
@@ -2,35 +2,37 @@ 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/custom_adapters/theme_mode_adapter.dart';
|
import 'package:paperless_mobile/core/config/hive/custom_adapters/theme_mode_adapter.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/user_app_state.dart';
|
import 'package:paperless_mobile/core/database/tables/local_user_app_state.dart';
|
||||||
import 'package:paperless_mobile/core/database/tables/user_credentials.dart';
|
import 'package:paperless_mobile/core/database/tables/user_credentials.dart';
|
||||||
import 'package:paperless_mobile/features/login/model/authentication_information.dart';
|
import 'package:paperless_mobile/features/login/model/authentication_information.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/core/database/tables/user_account.dart';
|
import 'package:paperless_mobile/core/database/tables/local_user_account.dart';
|
||||||
import 'package:paperless_mobile/features/settings/model/color_scheme_option.dart';
|
import 'package:paperless_mobile/features/settings/model/color_scheme_option.dart';
|
||||||
import 'package:paperless_mobile/core/database/tables/user_settings.dart';
|
import 'package:paperless_mobile/core/database/tables/local_user_settings.dart';
|
||||||
|
import 'package:paperless_mobile/features/settings/model/view_type.dart';
|
||||||
|
|
||||||
class HiveBoxes {
|
class HiveBoxes {
|
||||||
HiveBoxes._();
|
HiveBoxes._();
|
||||||
static const globalSettings = 'globalSettings';
|
static const globalSettings = 'globalSettings';
|
||||||
static const authentication = 'authentication';
|
static const authentication = 'authentication';
|
||||||
static const userCredentials = 'userCredentials';
|
static const localUserCredentials = 'localUserCredentials';
|
||||||
static const userAccount = 'userAccount';
|
static const localUserAccount = 'localUserAccount';
|
||||||
static const userAppState = 'userAppState';
|
static const localUserAppState = 'localUserAppState';
|
||||||
static const userSettings = 'userSettings';
|
static const localUserSettings = 'localUserSettings';
|
||||||
}
|
}
|
||||||
|
|
||||||
class HiveTypeIds {
|
class HiveTypeIds {
|
||||||
HiveTypeIds._();
|
HiveTypeIds._();
|
||||||
static const globalSettings = 0;
|
static const globalSettings = 0;
|
||||||
static const userSettings = 1;
|
static const localUserSettings = 1;
|
||||||
static const themeMode = 2;
|
static const themeMode = 2;
|
||||||
static const colorSchemeOption = 3;
|
static const colorSchemeOption = 3;
|
||||||
static const authentication = 4;
|
static const authentication = 4;
|
||||||
static const clientCertificate = 5;
|
static const clientCertificate = 5;
|
||||||
static const userCredentials = 6;
|
static const localUserCredentials = 6;
|
||||||
static const userAccount = 7;
|
static const localUserAccount = 7;
|
||||||
static const userAppState = 8;
|
static const localUserAppState = 8;
|
||||||
|
static const viewType = 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
void registerHiveAdapters() {
|
void registerHiveAdapters() {
|
||||||
@@ -40,10 +42,11 @@ void registerHiveAdapters() {
|
|||||||
Hive.registerAdapter(GlobalSettingsAdapter());
|
Hive.registerAdapter(GlobalSettingsAdapter());
|
||||||
Hive.registerAdapter(AuthenticationInformationAdapter());
|
Hive.registerAdapter(AuthenticationInformationAdapter());
|
||||||
Hive.registerAdapter(ClientCertificateAdapter());
|
Hive.registerAdapter(ClientCertificateAdapter());
|
||||||
Hive.registerAdapter(UserSettingsAdapter());
|
Hive.registerAdapter(LocalUserSettingsAdapter());
|
||||||
Hive.registerAdapter(UserCredentialsAdapter());
|
Hive.registerAdapter(UserCredentialsAdapter());
|
||||||
Hive.registerAdapter(UserAccountAdapter());
|
Hive.registerAdapter(LocalUserAccountAdapter());
|
||||||
Hive.registerAdapter(UserAppStateAdapter());
|
Hive.registerAdapter(LocalUserAppStateAdapter());
|
||||||
|
Hive.registerAdapter(ViewTypeAdapter());
|
||||||
}
|
}
|
||||||
|
|
||||||
extension HiveSingleValueBox<T> on Box<T> {
|
extension HiveSingleValueBox<T> on Box<T> {
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
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/user_settings.dart';
|
import 'package:paperless_mobile/core/database/tables/local_user_settings.dart';
|
||||||
|
|
||||||
part 'user_account.g.dart';
|
part 'local_user_account.g.dart';
|
||||||
|
|
||||||
@HiveType(typeId: HiveTypeIds.userAccount)
|
@HiveType(typeId: HiveTypeIds.localUserAccount)
|
||||||
class UserAccount extends HiveObject {
|
class LocalUserAccount extends HiveObject {
|
||||||
@HiveField(0)
|
@HiveField(0)
|
||||||
final String serverUrl;
|
final String serverUrl;
|
||||||
|
|
||||||
@@ -19,9 +19,9 @@ class UserAccount extends HiveObject {
|
|||||||
final String id;
|
final String id;
|
||||||
|
|
||||||
@HiveField(4)
|
@HiveField(4)
|
||||||
UserSettings settings;
|
LocalUserSettings settings;
|
||||||
|
|
||||||
UserAccount({
|
LocalUserAccount({
|
||||||
required this.id,
|
required this.id,
|
||||||
required this.serverUrl,
|
required this.serverUrl,
|
||||||
required this.username,
|
required this.username,
|
||||||
40
lib/core/database/tables/local_user_app_state.dart
Normal file
40
lib/core/database/tables/local_user_app_state.dart
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
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/features/settings/model/view_type.dart';
|
||||||
|
|
||||||
|
part 'local_user_app_state.g.dart';
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Object used for the persistence of app state, e.g. set filters,
|
||||||
|
/// search history and implicit settings.
|
||||||
|
///
|
||||||
|
@HiveType(typeId: HiveTypeIds.localUserAppState)
|
||||||
|
class LocalUserAppState extends HiveObject {
|
||||||
|
@HiveField(0)
|
||||||
|
final String userId;
|
||||||
|
|
||||||
|
@HiveField(1)
|
||||||
|
DocumentFilter currentDocumentFilter;
|
||||||
|
|
||||||
|
@HiveField(2)
|
||||||
|
List<String> documentSearchHistory;
|
||||||
|
|
||||||
|
@HiveField(3)
|
||||||
|
ViewType documentsPageViewType;
|
||||||
|
|
||||||
|
@HiveField(4)
|
||||||
|
ViewType savedViewsViewType;
|
||||||
|
|
||||||
|
@HiveField(5)
|
||||||
|
ViewType documentSearchViewType;
|
||||||
|
|
||||||
|
LocalUserAppState({
|
||||||
|
required this.userId,
|
||||||
|
this.currentDocumentFilter = const DocumentFilter(),
|
||||||
|
this.documentSearchHistory = const [],
|
||||||
|
this.documentsPageViewType = ViewType.list,
|
||||||
|
this.documentSearchViewType = ViewType.list,
|
||||||
|
this.savedViewsViewType = ViewType.list,
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -1,15 +1,14 @@
|
|||||||
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';
|
||||||
|
|
||||||
part 'user_settings.g.dart';
|
part 'local_user_settings.g.dart';
|
||||||
|
|
||||||
@HiveType(typeId: HiveTypeIds.userSettings)
|
@HiveType(typeId: HiveTypeIds.localUserSettings)
|
||||||
class UserSettings with HiveObjectMixin {
|
class LocalUserSettings with HiveObjectMixin {
|
||||||
@HiveField(0)
|
@HiveField(0)
|
||||||
bool isBiometricAuthenticationEnabled;
|
bool isBiometricAuthenticationEnabled;
|
||||||
|
|
||||||
UserSettings({
|
LocalUserSettings({
|
||||||
this.isBiometricAuthenticationEnabled = false,
|
this.isBiometricAuthenticationEnabled = false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
import 'package:hive_flutter/adapters.dart';
|
|
||||||
import 'package:paperless_api/paperless_api.dart';
|
|
||||||
import 'package:paperless_mobile/core/config/hive/hive_config.dart';
|
|
||||||
part 'user_app_state.g.dart';
|
|
||||||
|
|
||||||
@HiveType(typeId: HiveTypeIds.userAppState)
|
|
||||||
class UserAppState extends HiveObject {
|
|
||||||
@HiveField(0)
|
|
||||||
final String userId;
|
|
||||||
|
|
||||||
@HiveField(1)
|
|
||||||
DocumentFilter currentDocumentFilter;
|
|
||||||
|
|
||||||
@HiveField(2)
|
|
||||||
List<String> documentSearchHistory;
|
|
||||||
|
|
||||||
UserAppState({
|
|
||||||
required this.userId,
|
|
||||||
this.currentDocumentFilter = const DocumentFilter(),
|
|
||||||
this.documentSearchHistory = const [],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -4,7 +4,7 @@ import 'package:paperless_mobile/features/login/model/client_certificate.dart';
|
|||||||
|
|
||||||
part 'user_credentials.g.dart';
|
part 'user_credentials.g.dart';
|
||||||
|
|
||||||
@HiveType(typeId: HiveTypeIds.userCredentials)
|
@HiveType(typeId: HiveTypeIds.localUserCredentials)
|
||||||
class UserCredentials extends HiveObject {
|
class UserCredentials extends HiveObject {
|
||||||
@HiveField(0)
|
@HiveField(0)
|
||||||
final String token;
|
final String token;
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import 'dart:convert';
|
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
@@ -8,14 +7,18 @@ import 'package:paperless_mobile/core/interceptor/retry_on_connection_change_int
|
|||||||
import 'package:paperless_mobile/features/login/model/client_certificate.dart';
|
import 'package:paperless_mobile/features/login/model/client_certificate.dart';
|
||||||
import 'package:pretty_dio_logger/pretty_dio_logger.dart';
|
import 'package:pretty_dio_logger/pretty_dio_logger.dart';
|
||||||
|
|
||||||
|
/// Manages the security context, authentication and base request URL for
|
||||||
|
/// an underlying [Dio] client which is injected into all services
|
||||||
|
/// requiring authenticated access to the Paperless HTTP API.
|
||||||
class SessionManager {
|
class SessionManager {
|
||||||
final Dio client;
|
final Dio _client;
|
||||||
final List<Interceptor> interceptors;
|
PaperlessServerInformationModel _serverInformation;
|
||||||
PaperlessServerInformationModel serverInformation;
|
|
||||||
|
|
||||||
SessionManager([this.interceptors = const []])
|
Dio get client => _client;
|
||||||
: client = _initDio(interceptors),
|
|
||||||
serverInformation = PaperlessServerInformationModel();
|
SessionManager([List<Interceptor> interceptors = const []])
|
||||||
|
: _client = _initDio(interceptors),
|
||||||
|
_serverInformation = PaperlessServerInformationModel();
|
||||||
|
|
||||||
static Dio _initDio(List<Interceptor> interceptors) {
|
static Dio _initDio(List<Interceptor> interceptors) {
|
||||||
//en- and decoded by utf8 by default
|
//en- and decoded by utf8 by default
|
||||||
@@ -63,8 +66,7 @@ class SessionManager {
|
|||||||
);
|
);
|
||||||
final adapter = IOHttpClientAdapter()
|
final adapter = IOHttpClientAdapter()
|
||||||
..onHttpClientCreate = (client) => HttpClient(context: context)
|
..onHttpClientCreate = (client) => HttpClient(context: context)
|
||||||
..badCertificateCallback =
|
..badCertificateCallback = (X509Certificate cert, String host, int port) => true;
|
||||||
(X509Certificate cert, String host, int port) => true;
|
|
||||||
|
|
||||||
client.httpClientAdapter = adapter;
|
client.httpClientAdapter = adapter;
|
||||||
}
|
}
|
||||||
@@ -80,7 +82,7 @@ class SessionManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (serverInformation != null) {
|
if (serverInformation != null) {
|
||||||
this.serverInformation = serverInformation;
|
_serverInformation = serverInformation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,6 +90,6 @@ class SessionManager {
|
|||||||
client.httpClientAdapter = IOHttpClientAdapter();
|
client.httpClientAdapter = IOHttpClientAdapter();
|
||||||
client.options.baseUrl = '';
|
client.options.baseUrl = '';
|
||||||
client.options.headers.remove(HttpHeaders.authorizationHeader);
|
client.options.headers.remove(HttpHeaders.authorizationHeader);
|
||||||
serverInformation = PaperlessServerInformationModel();
|
_serverInformation = PaperlessServerInformationModel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ 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/paperless_server_information_cubit.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/settings/view/settings_page.dart';
|
import 'package:paperless_mobile/features/settings/view/settings_page.dart';
|
||||||
@@ -69,7 +69,7 @@ class AppDrawer extends StatelessWidget {
|
|||||||
onTap: () => Navigator.of(context).push(
|
onTap: () => Navigator.of(context).push(
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (_) => BlocProvider.value(
|
builder: (_) => BlocProvider.value(
|
||||||
value: context.read<PaperlessServerInformationCubit>(),
|
value: context.read<ServerInformationCubit>(),
|
||||||
child: const SettingsPage(),
|
child: const SettingsPage(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -55,7 +55,9 @@ class _BulkEditLabelBottomSheetState<T extends Label> extends State<BulkEditLabe
|
|||||||
FormBuilder(
|
FormBuilder(
|
||||||
key: _formKey,
|
key: _formKey,
|
||||||
child: LabelFormField<T>(
|
child: LabelFormField<T>(
|
||||||
initialValue: IdQueryParameter.fromId(widget.initialValue),
|
initialValue: widget.initialValue != null
|
||||||
|
? IdQueryParameter.fromId(widget.initialValue!)
|
||||||
|
: const IdQueryParameter.unset(),
|
||||||
name: "labelFormField",
|
name: "labelFormField",
|
||||||
options: widget.availableOptionsSelector(state),
|
options: widget.availableOptionsSelector(state),
|
||||||
labelText: widget.formFieldLabel,
|
labelText: widget.formFieldLabel,
|
||||||
|
|||||||
@@ -111,9 +111,9 @@ class _DocumentEditPageState extends State<DocumentEditPage> {
|
|||||||
addLabelText: S.of(context)!.addCorrespondent,
|
addLabelText: S.of(context)!.addCorrespondent,
|
||||||
labelText: S.of(context)!.correspondent,
|
labelText: S.of(context)!.correspondent,
|
||||||
options: context.watch<DocumentEditCubit>().state.correspondents,
|
options: context.watch<DocumentEditCubit>().state.correspondents,
|
||||||
initialValue: IdQueryParameter.fromId(
|
initialValue: state.document.correspondent != null
|
||||||
state.document.correspondent,
|
? IdQueryParameter.fromId(state.document.correspondent!)
|
||||||
),
|
: const IdQueryParameter.unset(),
|
||||||
name: fkCorrespondent,
|
name: fkCorrespondent,
|
||||||
prefixIcon: const Icon(Icons.person_outlined),
|
prefixIcon: const Icon(Icons.person_outlined),
|
||||||
),
|
),
|
||||||
@@ -145,7 +145,9 @@ class _DocumentEditPageState extends State<DocumentEditPage> {
|
|||||||
),
|
),
|
||||||
addLabelText: S.of(context)!.addDocumentType,
|
addLabelText: S.of(context)!.addDocumentType,
|
||||||
labelText: S.of(context)!.documentType,
|
labelText: S.of(context)!.documentType,
|
||||||
initialValue: IdQueryParameter.fromId(state.document.documentType),
|
initialValue: state.document.documentType != null
|
||||||
|
? IdQueryParameter.fromId(state.document.documentType!)
|
||||||
|
: const IdQueryParameter.unset(),
|
||||||
options: state.documentTypes,
|
options: state.documentTypes,
|
||||||
name: _DocumentEditPageState.fkDocumentType,
|
name: _DocumentEditPageState.fkDocumentType,
|
||||||
prefixIcon: const Icon(Icons.description_outlined),
|
prefixIcon: const Icon(Icons.description_outlined),
|
||||||
@@ -176,7 +178,9 @@ class _DocumentEditPageState extends State<DocumentEditPage> {
|
|||||||
addLabelText: S.of(context)!.addStoragePath,
|
addLabelText: S.of(context)!.addStoragePath,
|
||||||
labelText: S.of(context)!.storagePath,
|
labelText: S.of(context)!.storagePath,
|
||||||
options: state.storagePaths,
|
options: state.storagePaths,
|
||||||
initialValue: IdQueryParameter.fromId(state.document.storagePath),
|
initialValue: state.document.storagePath != null
|
||||||
|
? IdQueryParameter.fromId(state.document.storagePath!)
|
||||||
|
: const IdQueryParameter.unset(),
|
||||||
name: fkStoragePath,
|
name: fkStoragePath,
|
||||||
prefixIcon: const Icon(Icons.folder_outlined),
|
prefixIcon: const Icon(Icons.folder_outlined),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import 'package:collection/collection.dart';
|
|||||||
import 'package:hydrated_bloc/hydrated_bloc.dart';
|
import 'package:hydrated_bloc/hydrated_bloc.dart';
|
||||||
import 'package:json_annotation/json_annotation.dart';
|
import 'package:json_annotation/json_annotation.dart';
|
||||||
import 'package:paperless_api/paperless_api.dart';
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
import 'package:paperless_mobile/core/database/tables/user_app_state.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/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/features/paged_document_view/cubit/document_paging_bloc_mixin.dart';
|
import 'package:paperless_mobile/features/paged_document_view/cubit/document_paging_bloc_mixin.dart';
|
||||||
@@ -20,7 +20,7 @@ class DocumentSearchCubit extends Cubit<DocumentSearchState> with DocumentPaging
|
|||||||
@override
|
@override
|
||||||
final DocumentChangedNotifier notifier;
|
final DocumentChangedNotifier notifier;
|
||||||
|
|
||||||
final UserAppState _userAppState;
|
final LocalUserAppState _userAppState;
|
||||||
DocumentSearchCubit(
|
DocumentSearchCubit(
|
||||||
this.api,
|
this.api,
|
||||||
this.notifier,
|
this.notifier,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.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/user_app_state.dart';
|
import 'package:paperless_mobile/core/database/tables/local_user_app_state.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';
|
||||||
@@ -27,7 +27,7 @@ Future<void> showDocumentSearchPage(BuildContext context) {
|
|||||||
context.read(),
|
context.read(),
|
||||||
context.read(),
|
context.read(),
|
||||||
context.read(),
|
context.read(),
|
||||||
Hive.box<UserAppState>(HiveBoxes.userAppState).get(currentUser)!,
|
Hive.box<LocalUserAppState>(HiveBoxes.localUserAppState).get(currentUser)!,
|
||||||
),
|
),
|
||||||
child: const DocumentSearchPage(),
|
child: const DocumentSearchPage(),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
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/paperless_server_information_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/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/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/document_search/view/document_search_page.dart';
|
||||||
@@ -43,7 +43,8 @@ class SliverSearchBar extends StatelessWidget {
|
|||||||
icon: GlobalSettingsBuilder(
|
icon: GlobalSettingsBuilder(
|
||||||
builder: (context, settings) {
|
builder: (context, settings) {
|
||||||
return ValueListenableBuilder(
|
return ValueListenableBuilder(
|
||||||
valueListenable: Hive.box<UserAccount>(HiveBoxes.userAccount).listenable(),
|
valueListenable:
|
||||||
|
Hive.box<LocalUserAccount>(HiveBoxes.localUserAccount).listenable(),
|
||||||
builder: (context, box, _) {
|
builder: (context, box, _) {
|
||||||
final account = box.get(settings.currentLoggedInUser!)!;
|
final account = box.get(settings.currentLoggedInUser!)!;
|
||||||
return UserAvatar(userId: settings.currentLoggedInUser!, account: account);
|
return UserAvatar(userId: settings.currentLoggedInUser!, account: account);
|
||||||
@@ -55,7 +56,7 @@ class SliverSearchBar extends StatelessWidget {
|
|||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (_) => BlocProvider.value(
|
builder: (_) => BlocProvider.value(
|
||||||
value: context.read<PaperlessServerInformationCubit>(),
|
value: context.read<ServerInformationCubit>(),
|
||||||
child: const ManageAccountsPage(),
|
child: const ManageAccountsPage(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -4,10 +4,9 @@ import 'package:flutter/foundation.dart';
|
|||||||
import 'package:hydrated_bloc/hydrated_bloc.dart';
|
import 'package:hydrated_bloc/hydrated_bloc.dart';
|
||||||
import 'package:json_annotation/json_annotation.dart';
|
import 'package:json_annotation/json_annotation.dart';
|
||||||
import 'package:paperless_api/paperless_api.dart';
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
import 'package:paperless_mobile/core/database/tables/user_app_state.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/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/database/tables/user_account.dart';
|
|
||||||
import 'package:paperless_mobile/features/paged_document_view/cubit/document_paging_bloc_mixin.dart';
|
import 'package:paperless_mobile/features/paged_document_view/cubit/document_paging_bloc_mixin.dart';
|
||||||
import 'package:paperless_mobile/features/paged_document_view/cubit/paged_documents_state.dart';
|
import 'package:paperless_mobile/features/paged_document_view/cubit/paged_documents_state.dart';
|
||||||
import 'package:paperless_mobile/features/settings/model/view_type.dart';
|
import 'package:paperless_mobile/features/settings/model/view_type.dart';
|
||||||
@@ -24,14 +23,17 @@ class DocumentsCubit extends Cubit<DocumentsState> with DocumentPagingBlocMixin
|
|||||||
@override
|
@override
|
||||||
final DocumentChangedNotifier notifier;
|
final DocumentChangedNotifier notifier;
|
||||||
|
|
||||||
final UserAppState _userState;
|
final LocalUserAppState _userState;
|
||||||
|
|
||||||
DocumentsCubit(
|
DocumentsCubit(
|
||||||
this.api,
|
this.api,
|
||||||
this.notifier,
|
this.notifier,
|
||||||
this._labelRepository,
|
this._labelRepository,
|
||||||
this._userState,
|
this._userState,
|
||||||
) : super(DocumentsState(filter: _userState.currentDocumentFilter)) {
|
) : super(DocumentsState(
|
||||||
|
filter: _userState.currentDocumentFilter,
|
||||||
|
viewType: _userState.documentsPageViewType,
|
||||||
|
)) {
|
||||||
notifier.addListener(
|
notifier.addListener(
|
||||||
this,
|
this,
|
||||||
onUpdated: (document) {
|
onUpdated: (document) {
|
||||||
@@ -103,16 +105,6 @@ class DocumentsCubit extends Cubit<DocumentsState> with DocumentPagingBlocMixin
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
DocumentsState? fromJson(Map<String, dynamic> json) {
|
|
||||||
return DocumentsState.fromJson(json);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Map<String, dynamic>? toJson(DocumentsState state) {
|
|
||||||
return state.toJson();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> close() {
|
Future<void> close() {
|
||||||
notifier.removeListener(this);
|
notifier.removeListener(this);
|
||||||
@@ -122,6 +114,8 @@ class DocumentsCubit extends Cubit<DocumentsState> with DocumentPagingBlocMixin
|
|||||||
|
|
||||||
void setViewType(ViewType viewType) {
|
void setViewType(ViewType viewType) {
|
||||||
emit(state.copyWith(viewType: viewType));
|
emit(state.copyWith(viewType: viewType));
|
||||||
|
_userState.documentsPageViewType = viewType;
|
||||||
|
_userState.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -482,7 +482,7 @@ class _DocumentsPageState extends State<DocumentsPage> with SingleTickerProvider
|
|||||||
try {
|
try {
|
||||||
final correspondent = cubit.state.filter.correspondent;
|
final correspondent = cubit.state.filter.correspondent;
|
||||||
if (correspondent is SetIdQueryParameter) {
|
if (correspondent is SetIdQueryParameter) {
|
||||||
if (correspondent.id == correspondentId) {
|
if (correspondentId == null || correspondent.id == correspondentId) {
|
||||||
cubit.updateCurrentFilter(
|
cubit.updateCurrentFilter(
|
||||||
(filter) => filter.copyWith(correspondent: const IdQueryParameter.unset()),
|
(filter) => filter.copyWith(correspondent: const IdQueryParameter.unset()),
|
||||||
);
|
);
|
||||||
@@ -502,7 +502,7 @@ class _DocumentsPageState extends State<DocumentsPage> with SingleTickerProvider
|
|||||||
try {
|
try {
|
||||||
final documentType = cubit.state.filter.documentType;
|
final documentType = cubit.state.filter.documentType;
|
||||||
if (documentType is SetIdQueryParameter) {
|
if (documentType is SetIdQueryParameter) {
|
||||||
if (documentType.id == documentTypeId) {
|
if (documentTypeId == null || documentType.id == documentTypeId) {
|
||||||
cubit.updateCurrentFilter(
|
cubit.updateCurrentFilter(
|
||||||
(filter) => filter.copyWith(documentType: const IdQueryParameter.unset()),
|
(filter) => filter.copyWith(documentType: const IdQueryParameter.unset()),
|
||||||
);
|
);
|
||||||
@@ -522,7 +522,7 @@ class _DocumentsPageState extends State<DocumentsPage> with SingleTickerProvider
|
|||||||
try {
|
try {
|
||||||
final path = cubit.state.filter.documentType;
|
final path = cubit.state.filter.documentType;
|
||||||
if (path is SetIdQueryParameter) {
|
if (path is SetIdQueryParameter) {
|
||||||
if (path.id == pathId) {
|
if (pathId == null || path.id == pathId) {
|
||||||
cubit.updateCurrentFilter(
|
cubit.updateCurrentFilter(
|
||||||
(filter) => filter.copyWith(storagePath: const IdQueryParameter.unset()),
|
(filter) => filter.copyWith(storagePath: const IdQueryParameter.unset()),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -9,10 +9,10 @@ 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/paperless_server_information_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/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';
|
||||||
@@ -30,7 +30,7 @@ import 'package:paperless_mobile/features/inbox/view/pages/inbox_page.dart';
|
|||||||
import 'package:paperless_mobile/features/labels/cubit/label_cubit.dart';
|
import 'package:paperless_mobile/features/labels/cubit/label_cubit.dart';
|
||||||
import 'package:paperless_mobile/features/labels/view/pages/labels_page.dart';
|
import 'package:paperless_mobile/features/labels/view/pages/labels_page.dart';
|
||||||
import 'package:paperless_mobile/features/login/cubit/authentication_cubit.dart';
|
import 'package:paperless_mobile/features/login/cubit/authentication_cubit.dart';
|
||||||
import 'package:paperless_mobile/core/database/tables/user_account.dart';
|
import 'package:paperless_mobile/core/database/tables/local_user_account.dart';
|
||||||
import 'package:paperless_mobile/features/notifications/services/local_notification_service.dart';
|
import 'package:paperless_mobile/features/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/cubit/saved_view_cubit.dart';
|
||||||
import 'package:paperless_mobile/features/sharing/share_intent_queue.dart';
|
import 'package:paperless_mobile/features/sharing/share_intent_queue.dart';
|
||||||
@@ -62,15 +62,6 @@ class _HomePageState extends State<HomePage> with WidgetsBindingObserver {
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
WidgetsBinding.instance.addObserver(this);
|
WidgetsBinding.instance.addObserver(this);
|
||||||
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
|
||||||
_listenForReceivedFiles();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void didChangeDependencies() {
|
|
||||||
super.didChangeDependencies();
|
|
||||||
_initializeData(context);
|
_initializeData(context);
|
||||||
final userId =
|
final userId =
|
||||||
Hive.box<GlobalSettings>(HiveBoxes.globalSettings).getValue()!.currentLoggedInUser;
|
Hive.box<GlobalSettings>(HiveBoxes.globalSettings).getValue()!.currentLoggedInUser;
|
||||||
@@ -78,7 +69,7 @@ class _HomePageState extends State<HomePage> with WidgetsBindingObserver {
|
|||||||
context.read(),
|
context.read(),
|
||||||
context.read(),
|
context.read(),
|
||||||
context.read(),
|
context.read(),
|
||||||
Hive.box<UserAppState>(HiveBoxes.userAppState).get(userId)!,
|
Hive.box<LocalUserAppState>(HiveBoxes.localUserAppState).get(userId)!,
|
||||||
)..reload();
|
)..reload();
|
||||||
_savedViewCubit = SavedViewCubit(
|
_savedViewCubit = SavedViewCubit(
|
||||||
context.read(),
|
context.read(),
|
||||||
@@ -91,6 +82,14 @@ class _HomePageState extends State<HomePage> with WidgetsBindingObserver {
|
|||||||
context.read(),
|
context.read(),
|
||||||
);
|
);
|
||||||
_listenToInboxChanges();
|
_listenToInboxChanges();
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||||
|
_listenForReceivedFiles();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didChangeDependencies() {
|
||||||
|
super.didChangeDependencies();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _listenToInboxChanges() {
|
void _listenToInboxChanges() {
|
||||||
@@ -352,7 +351,7 @@ 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<PaperlessServerInformationCubit>().updateInformtion(),
|
context.read<ServerInformationCubit>().updateInformation(),
|
||||||
]).onError<PaperlessServerException>((error, stackTrace) {
|
]).onError<PaperlessServerException>((error, stackTrace) {
|
||||||
showErrorMessage(context, error, stackTrace);
|
showErrorMessage(context, error, stackTrace);
|
||||||
throw error;
|
throw error;
|
||||||
|
|||||||
29
lib/features/home/view/home_route.dart
Normal file
29
lib/features/home/view/home_route.dart
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/src/widgets/framework.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:paperless_mobile/core/bloc/server_information_cubit.dart';
|
||||||
|
import 'package:paperless_mobile/features/home/view/home_page.dart';
|
||||||
|
import 'package:paperless_mobile/features/tasks/cubit/task_status_cubit.dart';
|
||||||
|
|
||||||
|
class HomeRoute extends StatelessWidget {
|
||||||
|
const HomeRoute({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return MultiBlocProvider(
|
||||||
|
providers: [
|
||||||
|
BlocProvider(
|
||||||
|
create: (context) => TaskStatusCubit(
|
||||||
|
context.read(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
BlocProvider<ServerInformationCubit>(
|
||||||
|
create: (context) => ServerInformationCubit(
|
||||||
|
context.read(),
|
||||||
|
)..updateInformation(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
child: HomePage(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -145,7 +145,7 @@ class _LabelsPageState extends State<LabelsPage> with SingleTickerProviderStateM
|
|||||||
LabelTabView<Correspondent>(
|
LabelTabView<Correspondent>(
|
||||||
labels: context.watch<LabelCubit>().state.correspondents,
|
labels: context.watch<LabelCubit>().state.correspondents,
|
||||||
filterBuilder: (label) => DocumentFilter(
|
filterBuilder: (label) => DocumentFilter(
|
||||||
correspondent: IdQueryParameter.fromId(label.id),
|
correspondent: IdQueryParameter.fromId(label.id!),
|
||||||
pageSize: label.documentCount ?? 0,
|
pageSize: label.documentCount ?? 0,
|
||||||
),
|
),
|
||||||
onEdit: _openEditCorrespondentPage,
|
onEdit: _openEditCorrespondentPage,
|
||||||
@@ -166,7 +166,7 @@ class _LabelsPageState extends State<LabelsPage> with SingleTickerProviderStateM
|
|||||||
LabelTabView<DocumentType>(
|
LabelTabView<DocumentType>(
|
||||||
labels: context.watch<LabelCubit>().state.documentTypes,
|
labels: context.watch<LabelCubit>().state.documentTypes,
|
||||||
filterBuilder: (label) => DocumentFilter(
|
filterBuilder: (label) => DocumentFilter(
|
||||||
documentType: IdQueryParameter.fromId(label.id),
|
documentType: IdQueryParameter.fromId(label.id!),
|
||||||
pageSize: label.documentCount ?? 0,
|
pageSize: label.documentCount ?? 0,
|
||||||
),
|
),
|
||||||
onEdit: _openEditDocumentTypePage,
|
onEdit: _openEditDocumentTypePage,
|
||||||
@@ -218,7 +218,7 @@ class _LabelsPageState extends State<LabelsPage> with SingleTickerProviderStateM
|
|||||||
labels: context.watch<LabelCubit>().state.storagePaths,
|
labels: context.watch<LabelCubit>().state.storagePaths,
|
||||||
onEdit: _openEditStoragePathPage,
|
onEdit: _openEditStoragePathPage,
|
||||||
filterBuilder: (label) => DocumentFilter(
|
filterBuilder: (label) => DocumentFilter(
|
||||||
storagePath: IdQueryParameter.fromId(label.id),
|
storagePath: IdQueryParameter.fromId(label.id!),
|
||||||
pageSize: label.documentCount ?? 0,
|
pageSize: label.documentCount ?? 0,
|
||||||
),
|
),
|
||||||
contentBuilder: (path) => Text(path.path),
|
contentBuilder: (path) => Text(path.path),
|
||||||
|
|||||||
@@ -80,11 +80,12 @@ class _FullscreenLabelFormState<T extends Label> extends State<FullscreenLabelFo
|
|||||||
final index = AutocompleteHighlightedOption.of(context);
|
final index = AutocompleteHighlightedOption.of(context);
|
||||||
final value = index.isNegative ? null : options.elementAt(index);
|
final value = index.isNegative ? null : options.elementAt(index);
|
||||||
widget.onSubmit(
|
widget.onSubmit(
|
||||||
returnValue: IdQueryParameter.fromId(
|
returnValue: value?.maybeWhen(
|
||||||
value?.whenOrNull(
|
fromId: (id) => IdQueryParameter.fromId(id),
|
||||||
fromId: (id) => id,
|
orElse: () => const IdQueryParameter.unset(),
|
||||||
),
|
) ??
|
||||||
));
|
const IdQueryParameter.unset(),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
autofocus: true,
|
autofocus: true,
|
||||||
style: theme.textTheme.bodyLarge?.apply(
|
style: theme.textTheme.bodyLarge?.apply(
|
||||||
@@ -167,7 +168,7 @@ class _FullscreenLabelFormState<T extends Label> extends State<FullscreenLabelFo
|
|||||||
if (widget.initialValue == null) {
|
if (widget.initialValue == null) {
|
||||||
// If nothing is selected yet, show all options first.
|
// If nothing is selected yet, show all options first.
|
||||||
for (final option in widget.options.values) {
|
for (final option in widget.options.values) {
|
||||||
yield IdQueryParameter.fromId(option.id);
|
yield IdQueryParameter.fromId(option.id!);
|
||||||
}
|
}
|
||||||
if (widget.showNotAssignedOption) {
|
if (widget.showNotAssignedOption) {
|
||||||
yield const IdQueryParameter.notAssigned();
|
yield const IdQueryParameter.notAssigned();
|
||||||
@@ -189,7 +190,7 @@ class _FullscreenLabelFormState<T extends Label> extends State<FullscreenLabelFo
|
|||||||
if (initialValue is SetIdQueryParameter && option.id == initialValue.id) {
|
if (initialValue is SetIdQueryParameter && option.id == initialValue.id) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
yield IdQueryParameter.fromId(option.id);
|
yield IdQueryParameter.fromId(option.id!);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -198,7 +199,7 @@ class _FullscreenLabelFormState<T extends Label> extends State<FullscreenLabelFo
|
|||||||
widget.options.values.where((e) => e.name.trim().toLowerCase().contains(normalizedQuery));
|
widget.options.values.where((e) => e.name.trim().toLowerCase().contains(normalizedQuery));
|
||||||
if (matches.isNotEmpty) {
|
if (matches.isNotEmpty) {
|
||||||
for (final match in matches) {
|
for (final match in matches) {
|
||||||
yield IdQueryParameter.fromId(match.id);
|
yield IdQueryParameter.fromId(match.id!);
|
||||||
}
|
}
|
||||||
if (widget.showNotAssignedOption) {
|
if (widget.showNotAssignedOption) {
|
||||||
yield const IdQueryParameter.notAssigned();
|
yield const IdQueryParameter.notAssigned();
|
||||||
@@ -225,7 +226,7 @@ class _FullscreenLabelFormState<T extends Label> extends State<FullscreenLabelFo
|
|||||||
unset: () => S.of(context)!.startTyping,
|
unset: () => S.of(context)!.startTyping,
|
||||||
notAssigned: () => S.of(context)!.notAssigned,
|
notAssigned: () => S.of(context)!.notAssigned,
|
||||||
anyAssigned: () => S.of(context)!.anyAssigned,
|
anyAssigned: () => S.of(context)!.anyAssigned,
|
||||||
fromId: (id) => widget.options[id]!.name,
|
fromId: (id) => widget.options[id]?.name ?? S.of(context)!.startTyping,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ class LabelFormField<T extends Label> extends StatelessWidget {
|
|||||||
unset: () => '',
|
unset: () => '',
|
||||||
notAssigned: () => S.of(context)!.notAssigned,
|
notAssigned: () => S.of(context)!.notAssigned,
|
||||||
anyAssigned: () => S.of(context)!.anyAssigned,
|
anyAssigned: () => S.of(context)!.anyAssigned,
|
||||||
fromId: (id) => options[id]!.name,
|
fromId: (id) => options[id]?.name,
|
||||||
) ??
|
) ??
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
@@ -142,7 +142,7 @@ class LabelFormField<T extends Label> extends StatelessWidget {
|
|||||||
child: ActionChip(
|
child: ActionChip(
|
||||||
label: Text(suggestion.name),
|
label: Text(suggestion.name),
|
||||||
onPressed: () => field.didChange(
|
onPressed: () => field.didChange(
|
||||||
IdQueryParameter.fromId(suggestion.id),
|
IdQueryParameter.fromId(suggestion.id!),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ 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/features/linked_documents/cubit/linked_documents_cubit.dart';
|
import 'package:paperless_mobile/features/linked_documents/cubit/linked_documents_cubit.dart';
|
||||||
import 'package:paperless_mobile/features/linked_documents/view/linked_documents_page.dart';
|
import 'package:paperless_mobile/features/linked_documents/view/linked_documents_page.dart';
|
||||||
import 'package:paperless_mobile/core/database/tables/user_account.dart';
|
import 'package:paperless_mobile/core/database/tables/local_user_account.dart';
|
||||||
import 'package:paperless_mobile/core/database/tables/global_settings.dart';
|
import 'package:paperless_mobile/core/database/tables/global_settings.dart';
|
||||||
import 'package:paperless_mobile/helpers/format_helpers.dart';
|
import 'package:paperless_mobile/helpers/format_helpers.dart';
|
||||||
|
|
||||||
|
|||||||
@@ -7,25 +7,25 @@ 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_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/user_app_state.dart';
|
import 'package:paperless_mobile/core/database/tables/local_user_app_state.dart';
|
||||||
import 'package:paperless_mobile/core/interceptor/dio_http_error_interceptor.dart';
|
import 'package:paperless_mobile/core/interceptor/dio_http_error_interceptor.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/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/user_account.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/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/global_settings.dart';
|
||||||
import 'package:paperless_mobile/core/database/tables/user_settings.dart';
|
import 'package:paperless_mobile/core/database/tables/local_user_settings.dart';
|
||||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||||
part 'authentication_state.dart';
|
part 'authentication_state.dart';
|
||||||
|
|
||||||
class AuthenticationCubit extends Cubit<AuthenticationState> {
|
class AuthenticationCubit extends Cubit<AuthenticationState> {
|
||||||
final LocalAuthenticationService _localAuthService;
|
final LocalAuthenticationService _localAuthService;
|
||||||
final PaperlessAuthenticationApi _authApi;
|
final PaperlessAuthenticationApi _authApi;
|
||||||
final SessionManager _dioWrapper;
|
final SessionManager _sessionManager;
|
||||||
final LabelRepository _labelRepository;
|
final LabelRepository _labelRepository;
|
||||||
final SavedViewRepository _savedViewRepository;
|
final SavedViewRepository _savedViewRepository;
|
||||||
final PaperlessServerStatsApi _serverStatsApi;
|
final PaperlessServerStatsApi _serverStatsApi;
|
||||||
@@ -33,7 +33,7 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
|
|||||||
AuthenticationCubit(
|
AuthenticationCubit(
|
||||||
this._localAuthService,
|
this._localAuthService,
|
||||||
this._authApi,
|
this._authApi,
|
||||||
this._dioWrapper,
|
this._sessionManager,
|
||||||
this._labelRepository,
|
this._labelRepository,
|
||||||
this._savedViewRepository,
|
this._savedViewRepository,
|
||||||
this._serverStatsApi,
|
this._serverStatsApi,
|
||||||
@@ -46,7 +46,7 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
|
|||||||
}) async {
|
}) async {
|
||||||
assert(credentials.username != null && credentials.password != null);
|
assert(credentials.username != null && credentials.password != null);
|
||||||
|
|
||||||
_dioWrapper.updateSettings(
|
_sessionManager.updateSettings(
|
||||||
baseUrl: serverUrl,
|
baseUrl: serverUrl,
|
||||||
clientCertificate: clientCertificate,
|
clientCertificate: clientCertificate,
|
||||||
);
|
);
|
||||||
@@ -54,13 +54,14 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
|
|||||||
username: credentials.username!,
|
username: credentials.username!,
|
||||||
password: credentials.password!,
|
password: credentials.password!,
|
||||||
);
|
);
|
||||||
_dioWrapper.updateSettings(
|
_sessionManager.updateSettings(
|
||||||
baseUrl: serverUrl,
|
baseUrl: serverUrl,
|
||||||
clientCertificate: clientCertificate,
|
clientCertificate: clientCertificate,
|
||||||
authToken: token,
|
authToken: token,
|
||||||
);
|
);
|
||||||
final userAccountBox = Hive.box<UserAccount>(HiveBoxes.userAccount);
|
|
||||||
final userStateBox = Hive.box<UserAppState>(HiveBoxes.userAppState);
|
final userAccountBox = Hive.box<LocalUserAccount>(HiveBoxes.localUserAccount);
|
||||||
|
final userStateBox = Hive.box<LocalUserAppState>(HiveBoxes.localUserAppState);
|
||||||
|
|
||||||
final userId = "${credentials.username}@$serverUrl";
|
final userId = "${credentials.username}@$serverUrl";
|
||||||
|
|
||||||
@@ -72,9 +73,9 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
|
|||||||
// Create user account
|
// Create user account
|
||||||
await userAccountBox.put(
|
await userAccountBox.put(
|
||||||
userId,
|
userId,
|
||||||
UserAccount(
|
LocalUserAccount(
|
||||||
id: userId,
|
id: userId,
|
||||||
settings: UserSettings(),
|
settings: LocalUserSettings(),
|
||||||
serverUrl: serverUrl,
|
serverUrl: serverUrl,
|
||||||
username: credentials.username!,
|
username: credentials.username!,
|
||||||
fullName: fullName,
|
fullName: fullName,
|
||||||
@@ -84,7 +85,7 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
|
|||||||
// Create user state
|
// Create user state
|
||||||
await userStateBox.put(
|
await userStateBox.put(
|
||||||
userId,
|
userId,
|
||||||
UserAppState(userId: userId),
|
LocalUserAppState(userId: userId),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Save credentials in encrypted box
|
// Save credentials in encrypted box
|
||||||
@@ -119,7 +120,7 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
|
|||||||
if (globalSettings.currentLoggedInUser == userId) {
|
if (globalSettings.currentLoggedInUser == userId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final userAccountBox = Hive.box<UserAccount>(HiveBoxes.userAccount);
|
final userAccountBox = Hive.box<LocalUserAccount>(HiveBoxes.localUserAccount);
|
||||||
|
|
||||||
if (!userAccountBox.containsKey(userId)) {
|
if (!userAccountBox.containsKey(userId)) {
|
||||||
debugPrint("User $userId not yet registered.");
|
debugPrint("User $userId not yet registered.");
|
||||||
@@ -148,7 +149,7 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
|
|||||||
|
|
||||||
await _resetExternalState();
|
await _resetExternalState();
|
||||||
|
|
||||||
_dioWrapper.updateSettings(
|
_sessionManager.updateSettings(
|
||||||
authToken: credentials!.token,
|
authToken: credentials!.token,
|
||||||
clientCertificate: credentials.clientCertificate,
|
clientCertificate: credentials.clientCertificate,
|
||||||
serverInformation: PaperlessServerInformationModel(),
|
serverInformation: PaperlessServerInformationModel(),
|
||||||
@@ -178,8 +179,8 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
|
|||||||
assert(credentials.password != null && credentials.username != null);
|
assert(credentials.password != null && credentials.username != null);
|
||||||
final userId = "${credentials.username}@$serverUrl";
|
final userId = "${credentials.username}@$serverUrl";
|
||||||
|
|
||||||
final userAccountsBox = Hive.box<UserAccount>(HiveBoxes.userAccount);
|
final userAccountsBox = Hive.box<LocalUserAccount>(HiveBoxes.localUserAccount);
|
||||||
final userStateBox = Hive.box<UserAppState>(HiveBoxes.userAppState);
|
final userStateBox = Hive.box<LocalUserAppState>(HiveBoxes.localUserAppState);
|
||||||
|
|
||||||
if (userAccountsBox.containsKey(userId)) {
|
if (userAccountsBox.containsKey(userId)) {
|
||||||
throw Exception("User already exists");
|
throw Exception("User already exists");
|
||||||
@@ -204,11 +205,11 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
|
|||||||
|
|
||||||
await userAccountsBox.put(
|
await userAccountsBox.put(
|
||||||
userId,
|
userId,
|
||||||
UserAccount(
|
LocalUserAccount(
|
||||||
id: userId,
|
id: userId,
|
||||||
serverUrl: serverUrl,
|
serverUrl: serverUrl,
|
||||||
username: credentials.username!,
|
username: credentials.username!,
|
||||||
settings: UserSettings(
|
settings: LocalUserSettings(
|
||||||
isBiometricAuthenticationEnabled: enableBiometricAuthentication,
|
isBiometricAuthenticationEnabled: enableBiometricAuthentication,
|
||||||
),
|
),
|
||||||
fullName: fullName,
|
fullName: fullName,
|
||||||
@@ -217,7 +218,7 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
|
|||||||
|
|
||||||
await userStateBox.put(
|
await userStateBox.put(
|
||||||
userId,
|
userId,
|
||||||
UserAppState(
|
LocalUserAppState(
|
||||||
userId: userId,
|
userId: userId,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -236,15 +237,15 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
|
|||||||
|
|
||||||
Future<void> removeAccount(String userId) async {
|
Future<void> removeAccount(String userId) async {
|
||||||
final globalSettings = Hive.box<GlobalSettings>(HiveBoxes.globalSettings).getValue()!;
|
final globalSettings = Hive.box<GlobalSettings>(HiveBoxes.globalSettings).getValue()!;
|
||||||
final userAccountBox = Hive.box<UserAccount>(HiveBoxes.userAccount);
|
final userAccountBox = Hive.box<LocalUserAccount>(HiveBoxes.localUserAccount);
|
||||||
final userCredentialsBox = await _getUserCredentialsBox();
|
final userCredentialsBox = await _getUserCredentialsBox();
|
||||||
final userAppStateBox = Hive.box<UserAppState>(HiveBoxes.userAppState);
|
final userAppStateBox = Hive.box<LocalUserAppState>(HiveBoxes.localUserAppState);
|
||||||
final currentUser = globalSettings.currentLoggedInUser;
|
final currentUser = globalSettings.currentLoggedInUser;
|
||||||
|
|
||||||
await userAccountBox.delete(userId);
|
await userAccountBox.delete(userId);
|
||||||
await userAppStateBox.delete(userId);
|
await userAppStateBox.delete(userId);
|
||||||
await userCredentialsBox.delete(userId);
|
await userCredentialsBox.delete(userId);
|
||||||
await userAccountBox.close();
|
await userCredentialsBox.close();
|
||||||
|
|
||||||
if (currentUser == userId) {
|
if (currentUser == userId) {
|
||||||
return logout();
|
return logout();
|
||||||
@@ -262,7 +263,7 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final userAccount = Hive.box<UserAccount>(HiveBoxes.userAccount).get(userId)!;
|
final userAccount = Hive.box<LocalUserAccount>(HiveBoxes.localUserAccount).get(userId)!;
|
||||||
|
|
||||||
if (userAccount.settings.isBiometricAuthenticationEnabled) {
|
if (userAccount.settings.isBiometricAuthenticationEnabled) {
|
||||||
final localAuthSuccess =
|
final localAuthSuccess =
|
||||||
@@ -280,7 +281,7 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
|
|||||||
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.");
|
||||||
}
|
}
|
||||||
_dioWrapper.updateSettings(
|
_sessionManager.updateSettings(
|
||||||
clientCertificate: authentication.clientCertificate,
|
clientCertificate: authentication.clientCertificate,
|
||||||
authToken: authentication.token,
|
authToken: authentication.token,
|
||||||
baseUrl: userAccount.serverUrl,
|
baseUrl: userAccount.serverUrl,
|
||||||
@@ -321,13 +322,13 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
|
|||||||
Future<Box<UserCredentials>> _getUserCredentialsBox() async {
|
Future<Box<UserCredentials>> _getUserCredentialsBox() async {
|
||||||
final keyBytes = await _getEncryptedBoxKey();
|
final keyBytes = await _getEncryptedBoxKey();
|
||||||
return Hive.openBox<UserCredentials>(
|
return Hive.openBox<UserCredentials>(
|
||||||
HiveBoxes.userCredentials,
|
HiveBoxes.localUserCredentials,
|
||||||
encryptionCipher: HiveAesCipher(keyBytes),
|
encryptionCipher: HiveAesCipher(keyBytes),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _resetExternalState() {
|
Future<void> _resetExternalState() {
|
||||||
_dioWrapper.resetSettings();
|
_sessionManager.resetSettings();
|
||||||
return Future.wait([
|
return Future.wait([
|
||||||
HydratedBloc.storage.clear(),
|
HydratedBloc.storage.clear(),
|
||||||
_labelRepository.clear(),
|
_labelRepository.clear(),
|
||||||
|
|||||||
@@ -1,10 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
||||||
import 'package:flutter_form_builder/flutter_form_builder.dart';
|
import 'package:flutter_form_builder/flutter_form_builder.dart';
|
||||||
import 'package:paperless_api/paperless_api.dart';
|
|
||||||
import 'package:paperless_mobile/core/type/types.dart';
|
|
||||||
import 'package:paperless_mobile/features/app_intro/application_intro_slideshow.dart';
|
|
||||||
import 'package:paperless_mobile/features/login/cubit/authentication_cubit.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/client_certificate_form_model.dart';
|
import 'package:paperless_mobile/features/login/model/client_certificate_form_model.dart';
|
||||||
import 'package:paperless_mobile/features/login/model/login_form_credentials.dart';
|
import 'package:paperless_mobile/features/login/model/login_form_credentials.dart';
|
||||||
@@ -12,8 +7,6 @@ import 'package:paperless_mobile/features/login/view/widgets/form_fields/client_
|
|||||||
import 'package:paperless_mobile/features/login/view/widgets/form_fields/server_address_form_field.dart';
|
import 'package:paperless_mobile/features/login/view/widgets/form_fields/server_address_form_field.dart';
|
||||||
import 'package:paperless_mobile/features/login/view/widgets/form_fields/user_credentials_form_field.dart';
|
import 'package:paperless_mobile/features/login/view/widgets/form_fields/user_credentials_form_field.dart';
|
||||||
import 'package:paperless_mobile/features/login/view/widgets/login_pages/server_connection_page.dart';
|
import 'package:paperless_mobile/features/login/view/widgets/login_pages/server_connection_page.dart';
|
||||||
import 'package:paperless_mobile/core/database/tables/global_settings.dart';
|
|
||||||
import 'package:paperless_mobile/helpers/message_helpers.dart';
|
|
||||||
|
|
||||||
import 'widgets/login_pages/server_login_page.dart';
|
import 'widgets/login_pages/server_login_page.dart';
|
||||||
import 'widgets/never_scrollable_scroll_behavior.dart';
|
import 'widgets/never_scrollable_scroll_behavior.dart';
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
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/hive.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_app_state.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';
|
||||||
@@ -17,11 +21,9 @@ 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) =>
|
initial: (correspondents, documentTypes, tags, storagePaths) => Container(),
|
||||||
Container(),
|
loading: (correspondents, documentTypes, tags, storagePaths) => Center(
|
||||||
loading: (correspondents, documentTypes, tags, storagePaths) =>
|
child: Text("Saved views loading..."), //TODO: INTL
|
||||||
Center(
|
|
||||||
child: Text("Saved views loading..."),
|
|
||||||
),
|
),
|
||||||
loaded: (
|
loaded: (
|
||||||
savedViews,
|
savedViews,
|
||||||
@@ -33,9 +35,7 @@ class SavedViewList extends StatelessWidget {
|
|||||||
if (savedViews.isEmpty) {
|
if (savedViews.isEmpty) {
|
||||||
return SliverToBoxAdapter(
|
return SliverToBoxAdapter(
|
||||||
child: HintCard(
|
child: HintCard(
|
||||||
hintText: S
|
hintText: S.of(context)!.createViewsToQuicklyFilterYourDocuments,
|
||||||
.of(context)!
|
|
||||||
.createViewsToQuicklyFilterYourDocuments,
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -59,13 +59,17 @@ class SavedViewList extends StatelessWidget {
|
|||||||
ctxt.read(),
|
ctxt.read(),
|
||||||
ctxt.read(),
|
ctxt.read(),
|
||||||
context.read(),
|
context.read(),
|
||||||
|
Hive.box<LocalUserAppState>(HiveBoxes.localUserAppState).get(
|
||||||
|
Hive.box<GlobalSettings>(HiveBoxes.globalSettings)
|
||||||
|
.getValue()!
|
||||||
|
.currentLoggedInUser!,
|
||||||
|
)!,
|
||||||
savedView: view,
|
savedView: view,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
child: SavedViewDetailsPage(
|
child: SavedViewDetailsPage(
|
||||||
onDelete:
|
onDelete: context.read<SavedViewCubit>().remove,
|
||||||
context.read<SavedViewCubit>().remove,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,17 +1,16 @@
|
|||||||
import 'package:hydrated_bloc/hydrated_bloc.dart';
|
import 'package:hydrated_bloc/hydrated_bloc.dart';
|
||||||
import 'package:json_annotation/json_annotation.dart';
|
import 'package:json_annotation/json_annotation.dart';
|
||||||
import 'package:paperless_api/paperless_api.dart';
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
|
import 'package:paperless_mobile/core/database/tables/local_user_app_state.dart';
|
||||||
import 'package:paperless_mobile/core/notifier/document_changed_notifier.dart';
|
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/features/paged_document_view/cubit/paged_documents_state.dart';
|
import 'package:paperless_mobile/features/paged_document_view/cubit/paged_documents_state.dart';
|
||||||
import 'package:paperless_mobile/features/paged_document_view/cubit/document_paging_bloc_mixin.dart';
|
import 'package:paperless_mobile/features/paged_document_view/cubit/document_paging_bloc_mixin.dart';
|
||||||
import 'package:paperless_mobile/features/settings/model/view_type.dart';
|
import 'package:paperless_mobile/features/settings/model/view_type.dart';
|
||||||
|
|
||||||
part 'saved_view_details_cubit.g.dart';
|
|
||||||
part 'saved_view_details_state.dart';
|
part 'saved_view_details_state.dart';
|
||||||
|
|
||||||
class SavedViewDetailsCubit extends HydratedCubit<SavedViewDetailsState>
|
class SavedViewDetailsCubit extends Cubit<SavedViewDetailsState> with DocumentPagingBlocMixin {
|
||||||
with DocumentPagingBlocMixin {
|
|
||||||
@override
|
@override
|
||||||
final PaperlessDocumentsApi api;
|
final PaperlessDocumentsApi api;
|
||||||
|
|
||||||
@@ -22,10 +21,13 @@ class SavedViewDetailsCubit extends HydratedCubit<SavedViewDetailsState>
|
|||||||
|
|
||||||
final SavedView savedView;
|
final SavedView savedView;
|
||||||
|
|
||||||
|
final LocalUserAppState _userState;
|
||||||
|
|
||||||
SavedViewDetailsCubit(
|
SavedViewDetailsCubit(
|
||||||
this.api,
|
this.api,
|
||||||
this.notifier,
|
this.notifier,
|
||||||
this._labelRepository, {
|
this._labelRepository,
|
||||||
|
this._userState, {
|
||||||
required this.savedView,
|
required this.savedView,
|
||||||
}) : super(
|
}) : super(
|
||||||
SavedViewDetailsState(
|
SavedViewDetailsState(
|
||||||
@@ -33,6 +35,7 @@ class SavedViewDetailsCubit extends HydratedCubit<SavedViewDetailsState>
|
|||||||
documentTypes: _labelRepository.state.documentTypes,
|
documentTypes: _labelRepository.state.documentTypes,
|
||||||
tags: _labelRepository.state.tags,
|
tags: _labelRepository.state.tags,
|
||||||
storagePaths: _labelRepository.state.storagePaths,
|
storagePaths: _labelRepository.state.storagePaths,
|
||||||
|
viewType: _userState.savedViewsViewType,
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
notifier.addListener(
|
notifier.addListener(
|
||||||
@@ -58,16 +61,9 @@ class SavedViewDetailsCubit extends HydratedCubit<SavedViewDetailsState>
|
|||||||
|
|
||||||
void setViewType(ViewType viewType) {
|
void setViewType(ViewType viewType) {
|
||||||
emit(state.copyWith(viewType: viewType));
|
emit(state.copyWith(viewType: viewType));
|
||||||
}
|
_userState
|
||||||
|
..savedViewsViewType = viewType
|
||||||
@override
|
..save();
|
||||||
SavedViewDetailsState? fromJson(Map<String, dynamic> json) {
|
|
||||||
return SavedViewDetailsState.fromJson(json);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Map<String, dynamic>? toJson(SavedViewDetailsState state) {
|
|
||||||
return state.toJson();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
part of 'saved_view_details_cubit.dart';
|
part of 'saved_view_details_cubit.dart';
|
||||||
|
|
||||||
@JsonSerializable(ignoreUnannotated: true)
|
|
||||||
class SavedViewDetailsState extends DocumentPagingState {
|
class SavedViewDetailsState extends DocumentPagingState {
|
||||||
@JsonKey()
|
|
||||||
final ViewType viewType;
|
final ViewType viewType;
|
||||||
|
|
||||||
final Map<int, Correspondent> correspondents;
|
final Map<int, Correspondent> correspondents;
|
||||||
@@ -70,9 +68,4 @@ class SavedViewDetailsState extends DocumentPagingState {
|
|||||||
storagePaths: storagePaths ?? this.storagePaths,
|
storagePaths: storagePaths ?? this.storagePaths,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
factory SavedViewDetailsState.fromJson(Map<String, dynamic> json) =>
|
|
||||||
_$SavedViewDetailsStateFromJson(json);
|
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => _$SavedViewDetailsStateToJson(this);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,15 @@
|
|||||||
|
import 'package:hive/hive.dart';
|
||||||
|
import 'package:paperless_mobile/core/config/hive/hive_config.dart';
|
||||||
|
|
||||||
|
part 'view_type.g.dart';
|
||||||
|
|
||||||
|
@HiveType(typeId: HiveTypeIds.viewType)
|
||||||
enum ViewType {
|
enum ViewType {
|
||||||
|
@HiveField(0)
|
||||||
grid,
|
grid,
|
||||||
|
@HiveField(1)
|
||||||
list,
|
list,
|
||||||
|
@HiveField(2)
|
||||||
detailed;
|
detailed;
|
||||||
|
|
||||||
ViewType toggle() {
|
ViewType toggle() {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import 'package:paperless_mobile/core/config/hive/hive_config.dart';
|
|||||||
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
import 'package:paperless_mobile/extensions/flutter_extensions.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/core/database/tables/user_account.dart';
|
import 'package:paperless_mobile/core/database/tables/local_user_account.dart';
|
||||||
import 'package:paperless_mobile/features/login/view/login_page.dart';
|
import 'package:paperless_mobile/features/login/view/login_page.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/features/settings/view/dialogs/switch_account_dialog.dart';
|
import 'package:paperless_mobile/features/settings/view/dialogs/switch_account_dialog.dart';
|
||||||
@@ -26,7 +26,7 @@ class ManageAccountsPage extends StatelessWidget {
|
|||||||
return GlobalSettingsBuilder(
|
return GlobalSettingsBuilder(
|
||||||
builder: (context, globalSettings) {
|
builder: (context, globalSettings) {
|
||||||
return ValueListenableBuilder(
|
return ValueListenableBuilder(
|
||||||
valueListenable: Hive.box<UserAccount>(HiveBoxes.userAccount).listenable(),
|
valueListenable: Hive.box<LocalUserAccount>(HiveBoxes.localUserAccount).listenable(),
|
||||||
builder: (context, box, _) {
|
builder: (context, box, _) {
|
||||||
final userIds = box.keys.toList().cast<String>();
|
final userIds = box.keys.toList().cast<String>();
|
||||||
final otherAccounts = userIds
|
final otherAccounts = userIds
|
||||||
@@ -68,7 +68,7 @@ class ManageAccountsPage extends StatelessWidget {
|
|||||||
title: Text(S.of(context)!.addAccount),
|
title: Text(S.of(context)!.addAccount),
|
||||||
leading: const Icon(Icons.person_add),
|
leading: const Icon(Icons.person_add),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
_onAddAccount(context);
|
_onAddAccount(context, globalSettings.currentLoggedInUser!);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -82,7 +82,7 @@ class ManageAccountsPage extends StatelessWidget {
|
|||||||
Widget _buildAccountTile(
|
Widget _buildAccountTile(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
String userId,
|
String userId,
|
||||||
UserAccount account,
|
LocalUserAccount account,
|
||||||
GlobalSettings settings,
|
GlobalSettings settings,
|
||||||
) {
|
) {
|
||||||
final isLoggedIn = userId == settings.currentLoggedInUser;
|
final isLoggedIn = userId == settings.currentLoggedInUser;
|
||||||
@@ -147,16 +147,7 @@ class ManageAccountsPage extends StatelessWidget {
|
|||||||
onSelected: (value) async {
|
onSelected: (value) async {
|
||||||
if (value == 0) {
|
if (value == 0) {
|
||||||
// Switch
|
// Switch
|
||||||
final navigator = Navigator.of(context);
|
_onSwitchAccount(context, settings.currentLoggedInUser!, userId);
|
||||||
if (settings.currentLoggedInUser == userId) return;
|
|
||||||
Navigator.pushReplacement(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => const SwitchingAccountsPage(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
await context.read<AuthenticationCubit>().switchAccount(userId);
|
|
||||||
navigator.popUntil((route) => route.isFirst);
|
|
||||||
} else if (value == 1) {
|
} else if (value == 1) {
|
||||||
// Remove
|
// Remove
|
||||||
final shouldPop = userId == settings.currentLoggedInUser;
|
final shouldPop = userId == settings.currentLoggedInUser;
|
||||||
@@ -177,7 +168,7 @@ class ManageAccountsPage extends StatelessWidget {
|
|||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onAddAccount(BuildContext context) async {
|
Future<void> _onAddAccount(BuildContext context, String currentUser) async {
|
||||||
final userId = await Navigator.push(
|
final userId = await Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
@@ -207,9 +198,21 @@ class ManageAccountsPage extends StatelessWidget {
|
|||||||
) ??
|
) ??
|
||||||
false;
|
false;
|
||||||
if (shoudSwitch) {
|
if (shoudSwitch) {
|
||||||
await context.read<AuthenticationCubit>().switchAccount(userId);
|
_onSwitchAccount(context, currentUser, userId);
|
||||||
Navigator.pop(context);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onSwitchAccount(BuildContext context, String currentUser, String newUser) async {
|
||||||
|
final navigator = Navigator.of(context);
|
||||||
|
if (currentUser == newUser) return;
|
||||||
|
Navigator.pushReplacement(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => const SwitchingAccountsPage(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
await context.read<AuthenticationCubit>().switchAccount(newUser);
|
||||||
|
navigator.popUntil((route) => route.isFirst);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
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/paperless_server_information_cubit.dart';
|
import 'package:paperless_mobile/core/bloc/server_information_cubit.dart';
|
||||||
import 'package:paperless_mobile/core/bloc/paperless_server_information_state.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/generated/l10n/app_localizations.dart';
|
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||||
|
|
||||||
class SettingsPage extends StatelessWidget {
|
class SettingsPage extends StatelessWidget {
|
||||||
@@ -15,23 +16,27 @@ class SettingsPage extends StatelessWidget {
|
|||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(S.of(context)!.settings),
|
title: Text(S.of(context)!.settings),
|
||||||
),
|
),
|
||||||
bottomNavigationBar:
|
bottomNavigationBar: UserAccountBuilder(
|
||||||
BlocBuilder<PaperlessServerInformationCubit, PaperlessServerInformationState>(
|
builder: (context, user) {
|
||||||
builder: (context, state) {
|
assert(user != null);
|
||||||
final info = state.information!;
|
final host = user!.serverUrl.replaceFirst(RegExp(r"https?://"), "");
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text(
|
title: Text(
|
||||||
S.of(context)!.loggedInAs(info.username ?? 'unknown') + "@${info.host}",
|
S.of(context)!.loggedInAs(user.username) + "@$host",
|
||||||
style: Theme.of(context).textTheme.labelSmall,
|
style: Theme.of(context).textTheme.labelSmall,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
subtitle: Text(
|
subtitle: BlocBuilder<ServerInformationCubit, ServerInformationState>(
|
||||||
S.of(context)!.paperlessServerVersion +
|
builder: (context, state) {
|
||||||
' ' +
|
return Text(
|
||||||
info.version.toString() +
|
S.of(context)!.paperlessServerVersion +
|
||||||
' (API v${info.apiVersion})',
|
' ' +
|
||||||
style: Theme.of(context).textTheme.labelSmall,
|
state.information!.version.toString() +
|
||||||
textAlign: TextAlign.center,
|
' (API v${state.information!.apiVersion})',
|
||||||
|
style: Theme.of(context).textTheme.labelSmall,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:paperless_mobile/core/database/tables/user_account.dart';
|
import 'package:paperless_mobile/core/database/tables/local_user_account.dart';
|
||||||
|
|
||||||
class UserAvatar extends StatelessWidget {
|
class UserAvatar extends StatelessWidget {
|
||||||
final String userId;
|
final String userId;
|
||||||
final UserAccount account;
|
final LocalUserAccount account;
|
||||||
const UserAvatar({
|
const UserAvatar({
|
||||||
super.key,
|
super.key,
|
||||||
required this.userId,
|
required this.userId,
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
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/user_account.dart';
|
import 'package:paperless_mobile/core/database/tables/local_user_account.dart';
|
||||||
import 'package:paperless_mobile/core/database/tables/global_settings.dart';
|
import 'package:paperless_mobile/core/database/tables/global_settings.dart';
|
||||||
import 'package:paperless_mobile/core/database/tables/user_settings.dart';
|
import 'package:paperless_mobile/core/database/tables/local_user_settings.dart';
|
||||||
|
|
||||||
class UserAccountBuilder extends StatelessWidget {
|
class UserAccountBuilder extends StatelessWidget {
|
||||||
final Widget Function(
|
final Widget Function(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
UserAccount? settings,
|
LocalUserAccount? settings,
|
||||||
) builder;
|
) builder;
|
||||||
|
|
||||||
const UserAccountBuilder({
|
const UserAccountBuilder({
|
||||||
@@ -18,8 +18,8 @@ class UserAccountBuilder extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ValueListenableBuilder<Box<UserAccount>>(
|
return ValueListenableBuilder<Box<LocalUserAccount>>(
|
||||||
valueListenable: Hive.box<UserAccount>(HiveBoxes.userAccount).listenable(),
|
valueListenable: Hive.box<LocalUserAccount>(HiveBoxes.localUserAccount).listenable(),
|
||||||
builder: (context, accountBox, _) {
|
builder: (context, accountBox, _) {
|
||||||
final currentUser =
|
final currentUser =
|
||||||
Hive.box<GlobalSettings>(HiveBoxes.globalSettings).getValue()!.currentLoggedInUser;
|
Hive.box<GlobalSettings>(HiveBoxes.globalSettings).getValue()!.currentLoggedInUser;
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ class SimilarDocumentsCubit extends Cubit<SimilarDocumentsState> with DocumentPa
|
|||||||
this.notifier,
|
this.notifier,
|
||||||
this._labelRepository, {
|
this._labelRepository, {
|
||||||
required this.documentId,
|
required this.documentId,
|
||||||
}) : super(SimilarDocumentsState(filter: DocumentFilter())) {
|
}) : super(const SimilarDocumentsState(filter: DocumentFilter())) {
|
||||||
notifier.addListener(
|
notifier.addListener(
|
||||||
this,
|
this,
|
||||||
onDeleted: remove,
|
onDeleted: remove,
|
||||||
|
|||||||
@@ -18,9 +18,9 @@ import 'package:package_info_plus/package_info_plus.dart';
|
|||||||
import 'package:paperless_api/paperless_api.dart';
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
import 'package:paperless_mobile/constants.dart';
|
import 'package:paperless_mobile/constants.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/paperless_server_information_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/user_app_state.dart';
|
import 'package:paperless_mobile/core/database/tables/local_user_app_state.dart';
|
||||||
import 'package:paperless_mobile/core/interceptor/dio_http_error_interceptor.dart';
|
import 'package:paperless_mobile/core/interceptor/dio_http_error_interceptor.dart';
|
||||||
import 'package:paperless_mobile/core/interceptor/language_header.interceptor.dart';
|
import 'package:paperless_mobile/core/interceptor/language_header.interceptor.dart';
|
||||||
import 'package:paperless_mobile/core/notifier/document_changed_notifier.dart';
|
import 'package:paperless_mobile/core/notifier/document_changed_notifier.dart';
|
||||||
@@ -32,11 +32,12 @@ import 'package:paperless_mobile/core/service/dio_file_service.dart';
|
|||||||
import 'package:paperless_mobile/core/type/types.dart';
|
import 'package:paperless_mobile/core/type/types.dart';
|
||||||
import 'package:paperless_mobile/features/app_intro/application_intro_slideshow.dart';
|
import 'package:paperless_mobile/features/app_intro/application_intro_slideshow.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/home_route.dart';
|
||||||
import 'package:paperless_mobile/features/home/view/widget/verify_identity_page.dart';
|
import 'package:paperless_mobile/features/home/view/widget/verify_identity_page.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/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/user_account.dart';
|
import 'package:paperless_mobile/core/database/tables/local_user_account.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/features/login/view/login_page.dart';
|
import 'package:paperless_mobile/features/login/view/login_page.dart';
|
||||||
import 'package:paperless_mobile/features/notifications/services/local_notification_service.dart';
|
import 'package:paperless_mobile/features/notifications/services/local_notification_service.dart';
|
||||||
@@ -66,8 +67,8 @@ Future<void> _initHive() async {
|
|||||||
// await getApplicationDocumentsDirectory().then((value) => value.delete(recursive: true));
|
// await getApplicationDocumentsDirectory().then((value) => value.delete(recursive: true));
|
||||||
|
|
||||||
registerHiveAdapters();
|
registerHiveAdapters();
|
||||||
await Hive.openBox<UserAccount>(HiveBoxes.userAccount);
|
await Hive.openBox<LocalUserAccount>(HiveBoxes.localUserAccount);
|
||||||
await Hive.openBox<UserAppState>(HiveBoxes.userAppState);
|
await Hive.openBox<LocalUserAppState>(HiveBoxes.localUserAppState);
|
||||||
final globalSettingsBox = await Hive.openBox<GlobalSettings>(HiveBoxes.globalSettings);
|
final globalSettingsBox = await Hive.openBox<GlobalSettings>(HiveBoxes.globalSettings);
|
||||||
|
|
||||||
if (!globalSettingsBox.hasValue) {
|
if (!globalSettingsBox.hasValue) {
|
||||||
@@ -302,26 +303,8 @@ class _AuthenticationWrapperState extends State<AuthenticationWrapper> {
|
|||||||
return BlocBuilder<AuthenticationCubit, AuthenticationState>(
|
return BlocBuilder<AuthenticationCubit, AuthenticationState>(
|
||||||
builder: (context, authentication) {
|
builder: (context, authentication) {
|
||||||
if (authentication.isAuthenticated) {
|
if (authentication.isAuthenticated) {
|
||||||
return MultiBlocProvider(
|
return HomeRoute(
|
||||||
// This key will cause the subtree to be remounted, which will again
|
|
||||||
// call the provider's create callback! Without this key, the blocs
|
|
||||||
// would not be recreated on account switch!
|
|
||||||
key: ValueKey(authentication.userId),
|
key: ValueKey(authentication.userId),
|
||||||
providers: [
|
|
||||||
BlocProvider(
|
|
||||||
create: (context) => TaskStatusCubit(
|
|
||||||
context.read<PaperlessTasksApi>(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
BlocProvider<PaperlessServerInformationCubit>(
|
|
||||||
create: (context) => PaperlessServerInformationCubit(
|
|
||||||
context.read<PaperlessServerStatsApi>(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
child: HomePage(
|
|
||||||
key: ValueKey(authentication.userId),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
} else if (authentication.showBiometricAuthenticationScreen) {
|
} else if (authentication.showBiometricAuthenticationScreen) {
|
||||||
return const VerifyIdentityPage();
|
return const VerifyIdentityPage();
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ class IdQueryParameter with _$IdQueryParameter {
|
|||||||
@HiveType(typeId: PaperlessApiHiveTypeIds.anyAssignedIdQueryParameter)
|
@HiveType(typeId: PaperlessApiHiveTypeIds.anyAssignedIdQueryParameter)
|
||||||
const factory IdQueryParameter.anyAssigned() = AnyAssignedIdQueryParameter;
|
const factory IdQueryParameter.anyAssigned() = AnyAssignedIdQueryParameter;
|
||||||
@HiveType(typeId: PaperlessApiHiveTypeIds.setIdQueryParameter)
|
@HiveType(typeId: PaperlessApiHiveTypeIds.setIdQueryParameter)
|
||||||
const factory IdQueryParameter.fromId(@HiveField(0) int? id) = SetIdQueryParameter;
|
const factory IdQueryParameter.fromId(@HiveField(0) int id) = SetIdQueryParameter;
|
||||||
|
|
||||||
Map<String, String> toQueryParameter(String field) {
|
Map<String, String> toQueryParameter(String field) {
|
||||||
return when(
|
return when(
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ mixin _$IdQueryParameter {
|
|||||||
required TResult Function() unset,
|
required TResult Function() unset,
|
||||||
required TResult Function() notAssigned,
|
required TResult Function() notAssigned,
|
||||||
required TResult Function() anyAssigned,
|
required TResult Function() anyAssigned,
|
||||||
required TResult Function(@HiveField(0) int? id) fromId,
|
required TResult Function(@HiveField(0) int id) fromId,
|
||||||
}) =>
|
}) =>
|
||||||
throw _privateConstructorUsedError;
|
throw _privateConstructorUsedError;
|
||||||
@optionalTypeArgs
|
@optionalTypeArgs
|
||||||
@@ -46,7 +46,7 @@ mixin _$IdQueryParameter {
|
|||||||
TResult? Function()? unset,
|
TResult? Function()? unset,
|
||||||
TResult? Function()? notAssigned,
|
TResult? Function()? notAssigned,
|
||||||
TResult? Function()? anyAssigned,
|
TResult? Function()? anyAssigned,
|
||||||
TResult? Function(@HiveField(0) int? id)? fromId,
|
TResult? Function(@HiveField(0) int id)? fromId,
|
||||||
}) =>
|
}) =>
|
||||||
throw _privateConstructorUsedError;
|
throw _privateConstructorUsedError;
|
||||||
@optionalTypeArgs
|
@optionalTypeArgs
|
||||||
@@ -54,7 +54,7 @@ mixin _$IdQueryParameter {
|
|||||||
TResult Function()? unset,
|
TResult Function()? unset,
|
||||||
TResult Function()? notAssigned,
|
TResult Function()? notAssigned,
|
||||||
TResult Function()? anyAssigned,
|
TResult Function()? anyAssigned,
|
||||||
TResult Function(@HiveField(0) int? id)? fromId,
|
TResult Function(@HiveField(0) int id)? fromId,
|
||||||
required TResult orElse(),
|
required TResult orElse(),
|
||||||
}) =>
|
}) =>
|
||||||
throw _privateConstructorUsedError;
|
throw _privateConstructorUsedError;
|
||||||
@@ -155,7 +155,7 @@ class _$UnsetIdQueryParameter extends UnsetIdQueryParameter {
|
|||||||
required TResult Function() unset,
|
required TResult Function() unset,
|
||||||
required TResult Function() notAssigned,
|
required TResult Function() notAssigned,
|
||||||
required TResult Function() anyAssigned,
|
required TResult Function() anyAssigned,
|
||||||
required TResult Function(@HiveField(0) int? id) fromId,
|
required TResult Function(@HiveField(0) int id) fromId,
|
||||||
}) {
|
}) {
|
||||||
return unset();
|
return unset();
|
||||||
}
|
}
|
||||||
@@ -166,7 +166,7 @@ class _$UnsetIdQueryParameter extends UnsetIdQueryParameter {
|
|||||||
TResult? Function()? unset,
|
TResult? Function()? unset,
|
||||||
TResult? Function()? notAssigned,
|
TResult? Function()? notAssigned,
|
||||||
TResult? Function()? anyAssigned,
|
TResult? Function()? anyAssigned,
|
||||||
TResult? Function(@HiveField(0) int? id)? fromId,
|
TResult? Function(@HiveField(0) int id)? fromId,
|
||||||
}) {
|
}) {
|
||||||
return unset?.call();
|
return unset?.call();
|
||||||
}
|
}
|
||||||
@@ -177,7 +177,7 @@ class _$UnsetIdQueryParameter extends UnsetIdQueryParameter {
|
|||||||
TResult Function()? unset,
|
TResult Function()? unset,
|
||||||
TResult Function()? notAssigned,
|
TResult Function()? notAssigned,
|
||||||
TResult Function()? anyAssigned,
|
TResult Function()? anyAssigned,
|
||||||
TResult Function(@HiveField(0) int? id)? fromId,
|
TResult Function(@HiveField(0) int id)? fromId,
|
||||||
required TResult orElse(),
|
required TResult orElse(),
|
||||||
}) {
|
}) {
|
||||||
if (unset != null) {
|
if (unset != null) {
|
||||||
@@ -293,7 +293,7 @@ class _$NotAssignedIdQueryParameter extends NotAssignedIdQueryParameter {
|
|||||||
required TResult Function() unset,
|
required TResult Function() unset,
|
||||||
required TResult Function() notAssigned,
|
required TResult Function() notAssigned,
|
||||||
required TResult Function() anyAssigned,
|
required TResult Function() anyAssigned,
|
||||||
required TResult Function(@HiveField(0) int? id) fromId,
|
required TResult Function(@HiveField(0) int id) fromId,
|
||||||
}) {
|
}) {
|
||||||
return notAssigned();
|
return notAssigned();
|
||||||
}
|
}
|
||||||
@@ -304,7 +304,7 @@ class _$NotAssignedIdQueryParameter extends NotAssignedIdQueryParameter {
|
|||||||
TResult? Function()? unset,
|
TResult? Function()? unset,
|
||||||
TResult? Function()? notAssigned,
|
TResult? Function()? notAssigned,
|
||||||
TResult? Function()? anyAssigned,
|
TResult? Function()? anyAssigned,
|
||||||
TResult? Function(@HiveField(0) int? id)? fromId,
|
TResult? Function(@HiveField(0) int id)? fromId,
|
||||||
}) {
|
}) {
|
||||||
return notAssigned?.call();
|
return notAssigned?.call();
|
||||||
}
|
}
|
||||||
@@ -315,7 +315,7 @@ class _$NotAssignedIdQueryParameter extends NotAssignedIdQueryParameter {
|
|||||||
TResult Function()? unset,
|
TResult Function()? unset,
|
||||||
TResult Function()? notAssigned,
|
TResult Function()? notAssigned,
|
||||||
TResult Function()? anyAssigned,
|
TResult Function()? anyAssigned,
|
||||||
TResult Function(@HiveField(0) int? id)? fromId,
|
TResult Function(@HiveField(0) int id)? fromId,
|
||||||
required TResult orElse(),
|
required TResult orElse(),
|
||||||
}) {
|
}) {
|
||||||
if (notAssigned != null) {
|
if (notAssigned != null) {
|
||||||
@@ -431,7 +431,7 @@ class _$AnyAssignedIdQueryParameter extends AnyAssignedIdQueryParameter {
|
|||||||
required TResult Function() unset,
|
required TResult Function() unset,
|
||||||
required TResult Function() notAssigned,
|
required TResult Function() notAssigned,
|
||||||
required TResult Function() anyAssigned,
|
required TResult Function() anyAssigned,
|
||||||
required TResult Function(@HiveField(0) int? id) fromId,
|
required TResult Function(@HiveField(0) int id) fromId,
|
||||||
}) {
|
}) {
|
||||||
return anyAssigned();
|
return anyAssigned();
|
||||||
}
|
}
|
||||||
@@ -442,7 +442,7 @@ class _$AnyAssignedIdQueryParameter extends AnyAssignedIdQueryParameter {
|
|||||||
TResult? Function()? unset,
|
TResult? Function()? unset,
|
||||||
TResult? Function()? notAssigned,
|
TResult? Function()? notAssigned,
|
||||||
TResult? Function()? anyAssigned,
|
TResult? Function()? anyAssigned,
|
||||||
TResult? Function(@HiveField(0) int? id)? fromId,
|
TResult? Function(@HiveField(0) int id)? fromId,
|
||||||
}) {
|
}) {
|
||||||
return anyAssigned?.call();
|
return anyAssigned?.call();
|
||||||
}
|
}
|
||||||
@@ -453,7 +453,7 @@ class _$AnyAssignedIdQueryParameter extends AnyAssignedIdQueryParameter {
|
|||||||
TResult Function()? unset,
|
TResult Function()? unset,
|
||||||
TResult Function()? notAssigned,
|
TResult Function()? notAssigned,
|
||||||
TResult Function()? anyAssigned,
|
TResult Function()? anyAssigned,
|
||||||
TResult Function(@HiveField(0) int? id)? fromId,
|
TResult Function(@HiveField(0) int id)? fromId,
|
||||||
required TResult orElse(),
|
required TResult orElse(),
|
||||||
}) {
|
}) {
|
||||||
if (anyAssigned != null) {
|
if (anyAssigned != null) {
|
||||||
@@ -521,7 +521,7 @@ abstract class _$$SetIdQueryParameterCopyWith<$Res> {
|
|||||||
$Res Function(_$SetIdQueryParameter) then) =
|
$Res Function(_$SetIdQueryParameter) then) =
|
||||||
__$$SetIdQueryParameterCopyWithImpl<$Res>;
|
__$$SetIdQueryParameterCopyWithImpl<$Res>;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({@HiveField(0) int? id});
|
$Res call({@HiveField(0) int id});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -535,13 +535,13 @@ class __$$SetIdQueryParameterCopyWithImpl<$Res>
|
|||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
@override
|
@override
|
||||||
$Res call({
|
$Res call({
|
||||||
Object? id = freezed,
|
Object? id = null,
|
||||||
}) {
|
}) {
|
||||||
return _then(_$SetIdQueryParameter(
|
return _then(_$SetIdQueryParameter(
|
||||||
freezed == id
|
null == id
|
||||||
? _value.id
|
? _value.id
|
||||||
: id // ignore: cast_nullable_to_non_nullable
|
: id // ignore: cast_nullable_to_non_nullable
|
||||||
as int?,
|
as int,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -559,7 +559,7 @@ class _$SetIdQueryParameter extends SetIdQueryParameter {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
@HiveField(0)
|
@HiveField(0)
|
||||||
final int? id;
|
final int id;
|
||||||
|
|
||||||
@JsonKey(name: 'runtimeType')
|
@JsonKey(name: 'runtimeType')
|
||||||
final String $type;
|
final String $type;
|
||||||
@@ -594,7 +594,7 @@ class _$SetIdQueryParameter extends SetIdQueryParameter {
|
|||||||
required TResult Function() unset,
|
required TResult Function() unset,
|
||||||
required TResult Function() notAssigned,
|
required TResult Function() notAssigned,
|
||||||
required TResult Function() anyAssigned,
|
required TResult Function() anyAssigned,
|
||||||
required TResult Function(@HiveField(0) int? id) fromId,
|
required TResult Function(@HiveField(0) int id) fromId,
|
||||||
}) {
|
}) {
|
||||||
return fromId(id);
|
return fromId(id);
|
||||||
}
|
}
|
||||||
@@ -605,7 +605,7 @@ class _$SetIdQueryParameter extends SetIdQueryParameter {
|
|||||||
TResult? Function()? unset,
|
TResult? Function()? unset,
|
||||||
TResult? Function()? notAssigned,
|
TResult? Function()? notAssigned,
|
||||||
TResult? Function()? anyAssigned,
|
TResult? Function()? anyAssigned,
|
||||||
TResult? Function(@HiveField(0) int? id)? fromId,
|
TResult? Function(@HiveField(0) int id)? fromId,
|
||||||
}) {
|
}) {
|
||||||
return fromId?.call(id);
|
return fromId?.call(id);
|
||||||
}
|
}
|
||||||
@@ -616,7 +616,7 @@ class _$SetIdQueryParameter extends SetIdQueryParameter {
|
|||||||
TResult Function()? unset,
|
TResult Function()? unset,
|
||||||
TResult Function()? notAssigned,
|
TResult Function()? notAssigned,
|
||||||
TResult Function()? anyAssigned,
|
TResult Function()? anyAssigned,
|
||||||
TResult Function(@HiveField(0) int? id)? fromId,
|
TResult Function(@HiveField(0) int id)? fromId,
|
||||||
required TResult orElse(),
|
required TResult orElse(),
|
||||||
}) {
|
}) {
|
||||||
if (fromId != null) {
|
if (fromId != null) {
|
||||||
@@ -671,7 +671,7 @@ class _$SetIdQueryParameter extends SetIdQueryParameter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
abstract class SetIdQueryParameter extends IdQueryParameter {
|
abstract class SetIdQueryParameter extends IdQueryParameter {
|
||||||
const factory SetIdQueryParameter(@HiveField(0) final int? id) =
|
const factory SetIdQueryParameter(@HiveField(0) final int id) =
|
||||||
_$SetIdQueryParameter;
|
_$SetIdQueryParameter;
|
||||||
const SetIdQueryParameter._() : super._();
|
const SetIdQueryParameter._() : super._();
|
||||||
|
|
||||||
@@ -679,7 +679,7 @@ abstract class SetIdQueryParameter extends IdQueryParameter {
|
|||||||
_$SetIdQueryParameter.fromJson;
|
_$SetIdQueryParameter.fromJson;
|
||||||
|
|
||||||
@HiveField(0)
|
@HiveField(0)
|
||||||
int? get id;
|
int get id;
|
||||||
@JsonKey(ignore: true)
|
@JsonKey(ignore: true)
|
||||||
_$$SetIdQueryParameterCopyWith<_$SetIdQueryParameter> get copyWith =>
|
_$$SetIdQueryParameterCopyWith<_$SetIdQueryParameter> get copyWith =>
|
||||||
throw _privateConstructorUsedError;
|
throw _privateConstructorUsedError;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import 'query_type.dart';
|
|||||||
|
|
||||||
part 'text_query.g.dart';
|
part 'text_query.g.dart';
|
||||||
|
|
||||||
|
//TODO: Realize with freezed...
|
||||||
@HiveType(typeId: PaperlessApiHiveTypeIds.textQuery)
|
@HiveType(typeId: PaperlessApiHiveTypeIds.textQuery)
|
||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
class TextQuery extends Equatable {
|
class TextQuery extends Equatable {
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ 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!;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -86,8 +87,7 @@ class PaperlessDocumentsApiImpl implements PaperlessDocumentsApi {
|
|||||||
Future<PagedSearchResult<DocumentModel>> findAll(
|
Future<PagedSearchResult<DocumentModel>> findAll(
|
||||||
DocumentFilter filter,
|
DocumentFilter filter,
|
||||||
) async {
|
) async {
|
||||||
final filterParams = filter.toQueryParameters()
|
final filterParams = filter.toQueryParameters()..addAll({'truncate_content': "true"});
|
||||||
..addAll({'truncate_content': "true"});
|
|
||||||
try {
|
try {
|
||||||
final response = await client.get(
|
final response = await client.get(
|
||||||
"/api/documents/",
|
"/api/documents/",
|
||||||
@@ -137,9 +137,8 @@ class PaperlessDocumentsApiImpl implements PaperlessDocumentsApi {
|
|||||||
try {
|
try {
|
||||||
final response = await client.get(
|
final response = await client.get(
|
||||||
getPreviewUrl(documentId),
|
getPreviewUrl(documentId),
|
||||||
options: Options(
|
options:
|
||||||
responseType: ResponseType
|
Options(responseType: ResponseType.bytes), //TODO: Check if bytes or stream is required
|
||||||
.bytes), //TODO: Check if bytes or stream is required
|
|
||||||
);
|
);
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
return response.data;
|
return response.data;
|
||||||
@@ -219,8 +218,7 @@ class PaperlessDocumentsApiImpl implements PaperlessDocumentsApi {
|
|||||||
final response = await client.download(
|
final response = await client.download(
|
||||||
"/api/documents/${document.id}/download/",
|
"/api/documents/${document.id}/download/",
|
||||||
localFilePath,
|
localFilePath,
|
||||||
onReceiveProgress: (count, total) =>
|
onReceiveProgress: (count, total) => onProgressChanged?.call(count / total),
|
||||||
onProgressChanged?.call(count / total),
|
|
||||||
queryParameters: {'original': original},
|
queryParameters: {'original': original},
|
||||||
);
|
);
|
||||||
return response.data;
|
return response.data;
|
||||||
@@ -232,8 +230,7 @@ class PaperlessDocumentsApiImpl implements PaperlessDocumentsApi {
|
|||||||
@override
|
@override
|
||||||
Future<DocumentMetaData> getMetaData(DocumentModel document) async {
|
Future<DocumentMetaData> getMetaData(DocumentModel document) async {
|
||||||
try {
|
try {
|
||||||
final response =
|
final response = await client.get("/api/documents/${document.id}/metadata/");
|
||||||
await client.get("/api/documents/${document.id}/metadata/");
|
|
||||||
return compute(
|
return compute(
|
||||||
DocumentMetaData.fromJson,
|
DocumentMetaData.fromJson,
|
||||||
response.data as Map<String, dynamic>,
|
response.data as Map<String, dynamic>,
|
||||||
@@ -265,11 +262,9 @@ class PaperlessDocumentsApiImpl implements PaperlessDocumentsApi {
|
|||||||
@override
|
@override
|
||||||
Future<FieldSuggestions> findSuggestions(DocumentModel document) async {
|
Future<FieldSuggestions> findSuggestions(DocumentModel document) async {
|
||||||
try {
|
try {
|
||||||
final response =
|
final response = await client.get("/api/documents/${document.id}/suggestions/");
|
||||||
await client.get("/api/documents/${document.id}/suggestions/");
|
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
return FieldSuggestions.fromJson(response.data)
|
return FieldSuggestions.fromJson(response.data).forDocumentId(document.id);
|
||||||
.forDocumentId(document.id);
|
|
||||||
}
|
}
|
||||||
throw const PaperlessServerException(ErrorCode.suggestionsQueryError);
|
throw const PaperlessServerException(ErrorCode.suggestionsQueryError);
|
||||||
} on DioError catch (err) {
|
} on DioError catch (err) {
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
import 'dart:convert';
|
|
||||||
|
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:http/http.dart';
|
|
||||||
import 'package:paperless_api/src/models/paperless_server_exception.dart';
|
import 'package:paperless_api/src/models/paperless_server_exception.dart';
|
||||||
import 'package:paperless_api/src/models/paperless_server_information_model.dart';
|
import 'package:paperless_api/src/models/paperless_server_information_model.dart';
|
||||||
import 'package:paperless_api/src/models/paperless_server_statistics_model.dart';
|
import 'package:paperless_api/src/models/paperless_server_statistics_model.dart';
|
||||||
@@ -21,20 +18,14 @@ class PaperlessServerStatsApiImpl implements PaperlessServerStatsApi {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<PaperlessServerInformationModel> getServerInformation() async {
|
Future<PaperlessServerInformationModel> getServerInformation() async {
|
||||||
final response = await client.get("/api/ui_settings/");
|
final response = await client.get("/api/");
|
||||||
final version =
|
final version =
|
||||||
response.headers[PaperlessServerInformationModel.versionHeader]?.first ?? 'unknown';
|
response.headers[PaperlessServerInformationModel.versionHeader]?.first ?? 'unknown';
|
||||||
final apiVersion = int.tryParse(
|
final apiVersion = int.tryParse(
|
||||||
response.headers[PaperlessServerInformationModel.apiVersionHeader]?.first ?? '1');
|
response.headers[PaperlessServerInformationModel.apiVersionHeader]?.first ?? '1');
|
||||||
final String username = response.data['username'];
|
|
||||||
final String host = response.headers[PaperlessServerInformationModel.hostHeader]?.first ??
|
|
||||||
response.headers[PaperlessServerInformationModel.hostHeader]?.first ??
|
|
||||||
('${response.requestOptions.uri.host}:${response.requestOptions.uri.port}');
|
|
||||||
return PaperlessServerInformationModel(
|
return PaperlessServerInformationModel(
|
||||||
username: username,
|
|
||||||
version: version,
|
version: version,
|
||||||
apiVersion: apiVersion,
|
apiVersion: apiVersion,
|
||||||
host: host,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user