mirror of
https://github.com/Xevion/paperless-mobile.git
synced 2025-12-09 10:08:00 -06:00
feat: Implement switching between accounts (multi user support), still WIP
This commit is contained in:
@@ -2,16 +2,19 @@ import 'package:hive_flutter/adapters.dart';
|
||||
import 'package:paperless_mobile/core/config/hive/custpm_adapters/theme_mode_adapter.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/settings/global_app_settings.dart';
|
||||
import 'package:paperless_mobile/features/login/model/user_account.dart';
|
||||
import 'package:paperless_mobile/features/login/model/user_credentials.dart';
|
||||
import 'package:paperless_mobile/features/settings/model/global_settings.dart';
|
||||
import 'package:paperless_mobile/features/settings/model/color_scheme_option.dart';
|
||||
import 'package:paperless_mobile/features/settings/user_app_settings.dart';
|
||||
import 'package:paperless_mobile/features/settings/model/user_settings.dart';
|
||||
|
||||
class HiveBoxes {
|
||||
HiveBoxes._();
|
||||
static const globalSettings = 'globalSettings';
|
||||
static const userSettings = 'userSettings';
|
||||
static const authentication = 'authentication';
|
||||
static const vault = 'vault';
|
||||
static const userCredentials = 'userCredentials';
|
||||
static const userAccount = 'userAccount';
|
||||
}
|
||||
|
||||
class HiveTypeIds {
|
||||
@@ -22,18 +25,26 @@ class HiveTypeIds {
|
||||
static const colorSchemeOption = 3;
|
||||
static const authentication = 4;
|
||||
static const clientCertificate = 5;
|
||||
}
|
||||
|
||||
class HiveBoxSingleValueKey {
|
||||
HiveBoxSingleValueKey._();
|
||||
static const value = 'value';
|
||||
static const userCredentials = 6;
|
||||
static const userAccount = 7;
|
||||
}
|
||||
|
||||
void registerHiveAdapters() {
|
||||
Hive.registerAdapter(ColorSchemeOptionAdapter());
|
||||
Hive.registerAdapter(ThemeModeAdapter());
|
||||
Hive.registerAdapter(GlobalAppSettingsAdapter());
|
||||
Hive.registerAdapter(UserAppSettingsAdapter());
|
||||
Hive.registerAdapter(GlobalSettingsAdapter());
|
||||
Hive.registerAdapter(AuthenticationInformationAdapter());
|
||||
Hive.registerAdapter(ClientCertificateAdapter());
|
||||
Hive.registerAdapter(UserSettingsAdapter());
|
||||
Hive.registerAdapter(UserCredentialsAdapter());
|
||||
Hive.registerAdapter(UserAccountAdapter());
|
||||
}
|
||||
|
||||
extension HiveSingleValueBox<T> on Box<T> {
|
||||
static const _valueKey = 'SINGLE_VALUE';
|
||||
bool get hasValue => containsKey(_valueKey);
|
||||
|
||||
T? getValue() => get(_valueKey);
|
||||
|
||||
Future<void> setValue(T value) => put(_valueKey, value);
|
||||
}
|
||||
|
||||
@@ -38,8 +38,7 @@ class LabelRepository extends HydratedCubit<LabelRepositoryState> {
|
||||
|
||||
Future<Tag> createTag(Tag object) async {
|
||||
final created = await _api.saveTag(object);
|
||||
final updatedState = {...state.tags}
|
||||
..putIfAbsent(created.id!, () => created);
|
||||
final updatedState = {...state.tags}..putIfAbsent(created.id!, () => created);
|
||||
emit(state.copyWith(tags: updatedState));
|
||||
return created;
|
||||
}
|
||||
@@ -63,8 +62,7 @@ class LabelRepository extends HydratedCubit<LabelRepositoryState> {
|
||||
|
||||
Future<Iterable<Tag>> findAllTags([Iterable<int>? ids]) async {
|
||||
final tags = await _api.getTags(ids);
|
||||
final updatedState = {...state.tags}
|
||||
..addEntries(tags.map((e) => MapEntry(e.id!, e)));
|
||||
final updatedState = {...state.tags}..addEntries(tags.map((e) => MapEntry(e.id!, e)));
|
||||
emit(state.copyWith(tags: updatedState));
|
||||
return tags;
|
||||
}
|
||||
@@ -78,16 +76,14 @@ class LabelRepository extends HydratedCubit<LabelRepositoryState> {
|
||||
|
||||
Future<Correspondent> createCorrespondent(Correspondent correspondent) async {
|
||||
final created = await _api.saveCorrespondent(correspondent);
|
||||
final updatedState = {...state.correspondents}
|
||||
..putIfAbsent(created.id!, () => created);
|
||||
final updatedState = {...state.correspondents}..putIfAbsent(created.id!, () => created);
|
||||
emit(state.copyWith(correspondents: updatedState));
|
||||
return created;
|
||||
}
|
||||
|
||||
Future<int> deleteCorrespondent(Correspondent correspondent) async {
|
||||
await _api.deleteCorrespondent(correspondent);
|
||||
final updatedState = {...state.correspondents}
|
||||
..removeWhere((k, v) => k == correspondent.id);
|
||||
final updatedState = {...state.correspondents}..removeWhere((k, v) => k == correspondent.id);
|
||||
emit(state.copyWith(correspondents: updatedState));
|
||||
|
||||
return correspondent.id!;
|
||||
@@ -104,8 +100,7 @@ class LabelRepository extends HydratedCubit<LabelRepositoryState> {
|
||||
return null;
|
||||
}
|
||||
|
||||
Future<Iterable<Correspondent>> findAllCorrespondents(
|
||||
[Iterable<int>? ids]) async {
|
||||
Future<Iterable<Correspondent>> findAllCorrespondents([Iterable<int>? ids]) async {
|
||||
final correspondents = await _api.getCorrespondents(ids);
|
||||
final updatedState = {...state.correspondents}
|
||||
..addEntries(correspondents.map((e) => MapEntry(e.id!, e)));
|
||||
@@ -116,8 +111,7 @@ class LabelRepository extends HydratedCubit<LabelRepositoryState> {
|
||||
|
||||
Future<Correspondent> updateCorrespondent(Correspondent correspondent) async {
|
||||
final updated = await _api.updateCorrespondent(correspondent);
|
||||
final updatedState = {...state.correspondents}
|
||||
..update(updated.id!, (_) => updated);
|
||||
final updatedState = {...state.correspondents}..update(updated.id!, (_) => updated);
|
||||
emit(state.copyWith(correspondents: updatedState));
|
||||
|
||||
return updated;
|
||||
@@ -125,16 +119,14 @@ class LabelRepository extends HydratedCubit<LabelRepositoryState> {
|
||||
|
||||
Future<DocumentType> createDocumentType(DocumentType documentType) async {
|
||||
final created = await _api.saveDocumentType(documentType);
|
||||
final updatedState = {...state.documentTypes}
|
||||
..putIfAbsent(created.id!, () => created);
|
||||
final updatedState = {...state.documentTypes}..putIfAbsent(created.id!, () => created);
|
||||
emit(state.copyWith(documentTypes: updatedState));
|
||||
return created;
|
||||
}
|
||||
|
||||
Future<int> deleteDocumentType(DocumentType documentType) async {
|
||||
await _api.deleteDocumentType(documentType);
|
||||
final updatedState = {...state.documentTypes}
|
||||
..removeWhere((k, v) => k == documentType.id);
|
||||
final updatedState = {...state.documentTypes}..removeWhere((k, v) => k == documentType.id);
|
||||
emit(state.copyWith(documentTypes: updatedState));
|
||||
return documentType.id!;
|
||||
}
|
||||
@@ -149,8 +141,7 @@ class LabelRepository extends HydratedCubit<LabelRepositoryState> {
|
||||
return null;
|
||||
}
|
||||
|
||||
Future<Iterable<DocumentType>> findAllDocumentTypes(
|
||||
[Iterable<int>? ids]) async {
|
||||
Future<Iterable<DocumentType>> findAllDocumentTypes([Iterable<int>? ids]) async {
|
||||
final documentTypes = await _api.getDocumentTypes(ids);
|
||||
final updatedState = {...state.documentTypes}
|
||||
..addEntries(documentTypes.map((e) => MapEntry(e.id!, e)));
|
||||
@@ -160,24 +151,21 @@ class LabelRepository extends HydratedCubit<LabelRepositoryState> {
|
||||
|
||||
Future<DocumentType> updateDocumentType(DocumentType documentType) async {
|
||||
final updated = await _api.updateDocumentType(documentType);
|
||||
final updatedState = {...state.documentTypes}
|
||||
..update(updated.id!, (_) => updated);
|
||||
final updatedState = {...state.documentTypes}..update(updated.id!, (_) => updated);
|
||||
emit(state.copyWith(documentTypes: updatedState));
|
||||
return updated;
|
||||
}
|
||||
|
||||
Future<StoragePath> createStoragePath(StoragePath storagePath) async {
|
||||
final created = await _api.saveStoragePath(storagePath);
|
||||
final updatedState = {...state.storagePaths}
|
||||
..putIfAbsent(created.id!, () => created);
|
||||
final updatedState = {...state.storagePaths}..putIfAbsent(created.id!, () => created);
|
||||
emit(state.copyWith(storagePaths: updatedState));
|
||||
return created;
|
||||
}
|
||||
|
||||
Future<int> deleteStoragePath(StoragePath storagePath) async {
|
||||
await _api.deleteStoragePath(storagePath);
|
||||
final updatedState = {...state.storagePaths}
|
||||
..removeWhere((k, v) => k == storagePath.id);
|
||||
final updatedState = {...state.storagePaths}..removeWhere((k, v) => k == storagePath.id);
|
||||
emit(state.copyWith(storagePaths: updatedState));
|
||||
return storagePath.id!;
|
||||
}
|
||||
@@ -192,8 +180,7 @@ class LabelRepository extends HydratedCubit<LabelRepositoryState> {
|
||||
return null;
|
||||
}
|
||||
|
||||
Future<Iterable<StoragePath>> findAllStoragePaths(
|
||||
[Iterable<int>? ids]) async {
|
||||
Future<Iterable<StoragePath>> findAllStoragePaths([Iterable<int>? ids]) async {
|
||||
final storagePaths = await _api.getStoragePaths(ids);
|
||||
final updatedState = {...state.storagePaths}
|
||||
..addEntries(storagePaths.map((e) => MapEntry(e.id!, e)));
|
||||
@@ -203,8 +190,7 @@ class LabelRepository extends HydratedCubit<LabelRepositoryState> {
|
||||
|
||||
Future<StoragePath> updateStoragePath(StoragePath storagePath) async {
|
||||
final updated = await _api.updateStoragePath(storagePath);
|
||||
final updatedState = {...state.storagePaths}
|
||||
..update(updated.id!, (_) => updated);
|
||||
final updatedState = {...state.storagePaths}..update(updated.id!, (_) => updated);
|
||||
emit(state.copyWith(storagePaths: updatedState));
|
||||
return updated;
|
||||
}
|
||||
@@ -217,6 +203,12 @@ class LabelRepository extends HydratedCubit<LabelRepositoryState> {
|
||||
return super.close();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> clear() async {
|
||||
await super.clear();
|
||||
emit(const LabelRepositoryState());
|
||||
}
|
||||
|
||||
@override
|
||||
LabelRepositoryState? fromJson(Map<String, dynamic> json) {
|
||||
return LabelRepositoryState.fromJson(json);
|
||||
|
||||
@@ -27,8 +27,7 @@ class SavedViewRepository extends HydratedCubit<SavedViewRepositoryState> {
|
||||
|
||||
Future<SavedView> create(SavedView object) async {
|
||||
final created = await _api.save(object);
|
||||
final updatedState = {...state.savedViews}
|
||||
..putIfAbsent(created.id!, () => created);
|
||||
final updatedState = {...state.savedViews}..putIfAbsent(created.id!, () => created);
|
||||
emit(state.copyWith(savedViews: updatedState));
|
||||
return created;
|
||||
}
|
||||
@@ -43,8 +42,7 @@ class SavedViewRepository extends HydratedCubit<SavedViewRepositoryState> {
|
||||
Future<SavedView?> find(int id) async {
|
||||
final found = await _api.find(id);
|
||||
if (found != null) {
|
||||
final updatedState = {...state.savedViews}
|
||||
..update(id, (_) => found, ifAbsent: () => found);
|
||||
final updatedState = {...state.savedViews}..update(id, (_) => found, ifAbsent: () => found);
|
||||
emit(state.copyWith(savedViews: updatedState));
|
||||
}
|
||||
return found;
|
||||
@@ -68,6 +66,12 @@ class SavedViewRepository extends HydratedCubit<SavedViewRepositoryState> {
|
||||
return super.close();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> clear() async {
|
||||
await super.clear();
|
||||
emit(const SavedViewRepositoryState());
|
||||
}
|
||||
|
||||
@override
|
||||
SavedViewRepositoryState? fromJson(Map<String, dynamic> json) {
|
||||
return SavedViewRepositoryState.fromJson(json);
|
||||
|
||||
@@ -32,8 +32,7 @@ class ConnectivityStatusServiceImpl implements ConnectivityStatusService {
|
||||
|
||||
@override
|
||||
Future<bool> isConnectedToInternet() async {
|
||||
return _hasActiveInternetConnection(
|
||||
await (Connectivity().checkConnectivity()));
|
||||
return _hasActiveInternetConnection(await (Connectivity().checkConnectivity()));
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -72,11 +71,10 @@ class ConnectivityStatusServiceImpl implements ConnectivityStatusService {
|
||||
return ReachabilityStatus.unknown;
|
||||
}
|
||||
try {
|
||||
SessionManager manager =
|
||||
SessionManager([ServerReachabilityErrorInterceptor()])
|
||||
..updateSettings(clientCertificate: clientCertificate)
|
||||
..client.options.connectTimeout = const Duration(seconds: 5)
|
||||
..client.options.receiveTimeout = const Duration(seconds: 5);
|
||||
SessionManager manager = SessionManager([ServerReachabilityErrorInterceptor()])
|
||||
..updateSettings(clientCertificate: clientCertificate)
|
||||
..client.options.connectTimeout = const Duration(seconds: 5)
|
||||
..client.options.receiveTimeout = const Duration(seconds: 5);
|
||||
|
||||
final response = await manager.client.get('$serverAddress/api/');
|
||||
if (response.statusCode == 200) {
|
||||
@@ -84,8 +82,7 @@ class ConnectivityStatusServiceImpl implements ConnectivityStatusService {
|
||||
}
|
||||
return ReachabilityStatus.notReachable;
|
||||
} on DioError catch (error) {
|
||||
if (error.type == DioErrorType.unknown &&
|
||||
error.error is ReachabilityStatus) {
|
||||
if (error.type == DioErrorType.unknown && error.error is ReachabilityStatus) {
|
||||
return error.error as ReachabilityStatus;
|
||||
}
|
||||
} on TlsException catch (error) {
|
||||
|
||||
@@ -9,11 +9,12 @@ import 'package:paperless_mobile/core/bloc/document_status_cubit.dart';
|
||||
import 'package:paperless_mobile/core/model/document_processing_status.dart';
|
||||
import 'package:paperless_mobile/features/login/model/authentication_information.dart';
|
||||
import 'package:paperless_mobile/constants.dart';
|
||||
import 'package:paperless_mobile/features/login/model/user_credentials.dart';
|
||||
import 'package:web_socket_channel/io.dart';
|
||||
|
||||
abstract class StatusService {
|
||||
Future<void> startListeningBeforeDocumentUpload(String httpUrl,
|
||||
AuthenticationInformation credentials, String documentFileName);
|
||||
Future<void> startListeningBeforeDocumentUpload(
|
||||
String httpUrl, UserCredentials credentials, String documentFileName);
|
||||
}
|
||||
|
||||
class WebSocketStatusService implements StatusService {
|
||||
@@ -25,7 +26,7 @@ class WebSocketStatusService implements StatusService {
|
||||
@override
|
||||
Future<void> startListeningBeforeDocumentUpload(
|
||||
String httpUrl,
|
||||
AuthenticationInformation credentials,
|
||||
UserCredentials credentials,
|
||||
String documentFileName,
|
||||
) async {
|
||||
// socket = await WebSocket.connect(
|
||||
@@ -57,7 +58,7 @@ class LongPollingStatusService implements StatusService {
|
||||
@override
|
||||
Future<void> startListeningBeforeDocumentUpload(
|
||||
String httpUrl,
|
||||
AuthenticationInformation credentials,
|
||||
UserCredentials credentials,
|
||||
String documentFileName,
|
||||
) async {
|
||||
// final today = DateTime.now();
|
||||
|
||||
Reference in New Issue
Block a user