mirror of
https://github.com/Xevion/paperless-mobile.git
synced 2025-12-16 16:12:33 -06:00
fix: Add custom fields, translations, add app logs to login routes
This commit is contained in:
6
lib/core/bloc/loading_status.dart
Normal file
6
lib/core/bloc/loading_status.dart
Normal file
@@ -0,0 +1,6 @@
|
||||
enum LoadingStatus {
|
||||
initial,
|
||||
loading,
|
||||
loaded,
|
||||
error;
|
||||
}
|
||||
41
lib/core/bloc/my_bloc_observer.dart
Normal file
41
lib/core/bloc/my_bloc_observer.dart
Normal file
@@ -0,0 +1,41 @@
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:paperless_mobile/core/bloc/transient_error.dart';
|
||||
import 'package:paperless_mobile/core/translation/error_code_localization_mapper.dart';
|
||||
import 'package:paperless_mobile/features/logging/data/logger.dart';
|
||||
import 'package:paperless_mobile/helpers/message_helpers.dart';
|
||||
import 'package:paperless_mobile/routing/navigation_keys.dart';
|
||||
|
||||
class MyBlocObserver extends BlocObserver {
|
||||
@override
|
||||
void onError(BlocBase bloc, Object error, StackTrace stackTrace) {
|
||||
if (error is TransientError) {
|
||||
_handleTransientError(bloc, error, stackTrace);
|
||||
}
|
||||
super.onError(bloc, error, stackTrace);
|
||||
}
|
||||
|
||||
void _handleTransientError(
|
||||
BlocBase bloc,
|
||||
TransientError error,
|
||||
StackTrace stackTrace,
|
||||
) {
|
||||
assert(rootNavigatorKey.currentContext != null);
|
||||
final message = switch (error) {
|
||||
TransientPaperlessApiError(code: var code) => translateError(
|
||||
rootNavigatorKey.currentContext!,
|
||||
code,
|
||||
),
|
||||
TransientMessageError(message: var message) => message,
|
||||
};
|
||||
final details = switch (error) {
|
||||
TransientPaperlessApiError(details: var details) => details,
|
||||
_ => null,
|
||||
};
|
||||
|
||||
showSnackBar(
|
||||
rootNavigatorKey.currentContext!,
|
||||
message,
|
||||
details: details,
|
||||
);
|
||||
}
|
||||
}
|
||||
16
lib/core/bloc/transient_error.dart
Normal file
16
lib/core/bloc/transient_error.dart
Normal file
@@ -0,0 +1,16 @@
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
|
||||
sealed class TransientError extends Error {}
|
||||
|
||||
class TransientPaperlessApiError extends TransientError {
|
||||
final ErrorCode code;
|
||||
final String? details;
|
||||
|
||||
TransientPaperlessApiError({required this.code, this.details});
|
||||
}
|
||||
|
||||
class TransientMessageError extends TransientError {
|
||||
final String message;
|
||||
|
||||
TransientMessageError({required this.message});
|
||||
}
|
||||
@@ -28,16 +28,31 @@ class DioHttpErrorInterceptor extends Interceptor {
|
||||
type: DioExceptionType.badResponse,
|
||||
),
|
||||
);
|
||||
} else if (data is String &&
|
||||
data.contains("No required SSL certificate was sent")) {
|
||||
handler.reject(
|
||||
DioException(
|
||||
requestOptions: err.requestOptions,
|
||||
type: DioExceptionType.badResponse,
|
||||
error:
|
||||
const PaperlessApiException(ErrorCode.missingClientCertificate),
|
||||
),
|
||||
);
|
||||
} else if (data is String) {
|
||||
if (data.contains("No required SSL certificate was sent")) {
|
||||
handler.reject(
|
||||
DioException(
|
||||
requestOptions: err.requestOptions,
|
||||
type: DioExceptionType.badResponse,
|
||||
error: const PaperlessApiException(
|
||||
ErrorCode.missingClientCertificate),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
handler.reject(
|
||||
DioException(
|
||||
requestOptions: err.requestOptions,
|
||||
message: data,
|
||||
error: PaperlessApiException(
|
||||
ErrorCode.documentLoadFailed,
|
||||
details: data,
|
||||
),
|
||||
response: err.response,
|
||||
stackTrace: err.stackTrace,
|
||||
type: DioExceptionType.badResponse,
|
||||
),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
handler.reject(err);
|
||||
}
|
||||
|
||||
@@ -1,192 +1,190 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/repository/label_repository_state.dart';
|
||||
import 'package:paperless_mobile/core/repository/persistent_repository.dart';
|
||||
|
||||
class LabelRepository extends PersistentRepository<LabelRepositoryState> {
|
||||
class LabelRepository extends ChangeNotifier {
|
||||
final PaperlessLabelsApi _api;
|
||||
|
||||
LabelRepository(this._api) : super(const LabelRepositoryState());
|
||||
Map<int, Correspondent> correspondents = {};
|
||||
Map<int, DocumentType> documentTypes = {};
|
||||
Map<int, StoragePath> storagePaths = {};
|
||||
Map<int, Tag> tags = {};
|
||||
|
||||
Future<void> initialize() async {
|
||||
LabelRepository(this._api);
|
||||
|
||||
// Resets the repository to its initial state and loads all data from the API.
|
||||
Future<void> initialize({
|
||||
required bool loadCorrespondents,
|
||||
required bool loadDocumentTypes,
|
||||
required bool loadStoragePaths,
|
||||
required bool loadTags,
|
||||
}) async {
|
||||
correspondents = {};
|
||||
documentTypes = {};
|
||||
storagePaths = {};
|
||||
tags = {};
|
||||
await Future.wait([
|
||||
findAllCorrespondents(),
|
||||
findAllDocumentTypes(),
|
||||
findAllStoragePaths(),
|
||||
findAllTags(),
|
||||
if (loadCorrespondents) findAllCorrespondents(),
|
||||
if (loadDocumentTypes) findAllDocumentTypes(),
|
||||
if (loadStoragePaths) findAllStoragePaths(),
|
||||
if (loadTags) findAllTags(),
|
||||
]);
|
||||
}
|
||||
|
||||
Future<Tag> createTag(Tag object) async {
|
||||
final created = await _api.saveTag(object);
|
||||
final updatedState = {...state.tags}
|
||||
..putIfAbsent(created.id!, () => created);
|
||||
emit(state.copyWith(tags: updatedState));
|
||||
tags = {...tags, created.id!: created};
|
||||
notifyListeners();
|
||||
return created;
|
||||
}
|
||||
|
||||
Future<int> deleteTag(Tag tag) async {
|
||||
await _api.deleteTag(tag);
|
||||
final updatedState = {...state.tags}..removeWhere((k, v) => k == tag.id);
|
||||
emit(state.copyWith(tags: updatedState));
|
||||
tags.remove(tag.id!);
|
||||
notifyListeners();
|
||||
return tag.id!;
|
||||
}
|
||||
|
||||
Future<Tag?> findTag(int id) async {
|
||||
final tag = await _api.getTag(id);
|
||||
if (tag != null) {
|
||||
final updatedState = {...state.tags}..[id] = tag;
|
||||
emit(state.copyWith(tags: updatedState));
|
||||
tags = {...tags, id: tag};
|
||||
notifyListeners();
|
||||
return tag;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
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)));
|
||||
emit(state.copyWith(tags: updatedState));
|
||||
return tags;
|
||||
final data = await _api.getTags(ids);
|
||||
tags = {for (var tag in data) tag.id!: tag};
|
||||
notifyListeners();
|
||||
return data;
|
||||
}
|
||||
|
||||
Future<Tag> updateTag(Tag tag) async {
|
||||
final updated = await _api.updateTag(tag);
|
||||
final updatedState = {...state.tags}..update(updated.id!, (_) => updated);
|
||||
emit(state.copyWith(tags: updatedState));
|
||||
tags = {...tags, updated.id!: updated};
|
||||
notifyListeners();
|
||||
return updated;
|
||||
}
|
||||
|
||||
Future<Correspondent> createCorrespondent(Correspondent correspondent) async {
|
||||
final created = await _api.saveCorrespondent(correspondent);
|
||||
final updatedState = {...state.correspondents}
|
||||
..putIfAbsent(created.id!, () => created);
|
||||
emit(state.copyWith(correspondents: updatedState));
|
||||
correspondents = {...correspondents, created.id!: created};
|
||||
notifyListeners();
|
||||
return created;
|
||||
}
|
||||
|
||||
Future<int> deleteCorrespondent(Correspondent correspondent) async {
|
||||
await _api.deleteCorrespondent(correspondent);
|
||||
final updatedState = {...state.correspondents}
|
||||
..removeWhere((k, v) => k == correspondent.id);
|
||||
emit(state.copyWith(correspondents: updatedState));
|
||||
|
||||
correspondents.remove(correspondent.id!);
|
||||
notifyListeners();
|
||||
return correspondent.id!;
|
||||
}
|
||||
|
||||
Future<Correspondent?> findCorrespondent(int id) async {
|
||||
final correspondent = await _api.getCorrespondent(id);
|
||||
if (correspondent != null) {
|
||||
final updatedState = {...state.correspondents}..[id] = correspondent;
|
||||
emit(state.copyWith(correspondents: updatedState));
|
||||
correspondents = {...correspondents, id: correspondent};
|
||||
notifyListeners();
|
||||
return correspondent;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Future<Iterable<Correspondent>> findAllCorrespondents(
|
||||
[Iterable<int>? ids]) async {
|
||||
final correspondents = await _api.getCorrespondents(ids);
|
||||
final updatedState = {
|
||||
...state.correspondents,
|
||||
}..addAll({for (var element in correspondents) element.id!: element});
|
||||
emit(state.copyWith(correspondents: updatedState));
|
||||
return correspondents;
|
||||
Future<Iterable<Correspondent>> findAllCorrespondents() async {
|
||||
final data = await _api.getCorrespondents();
|
||||
correspondents = {for (var element in data) element.id!: element};
|
||||
notifyListeners();
|
||||
return data;
|
||||
}
|
||||
|
||||
Future<Correspondent> updateCorrespondent(Correspondent correspondent) async {
|
||||
final updated = await _api.updateCorrespondent(correspondent);
|
||||
final updatedState = {...state.correspondents}
|
||||
..update(updated.id!, (_) => updated);
|
||||
emit(state.copyWith(correspondents: updatedState));
|
||||
|
||||
correspondents = {...correspondents, updated.id!: updated};
|
||||
notifyListeners();
|
||||
return updated;
|
||||
}
|
||||
|
||||
Future<DocumentType> createDocumentType(DocumentType documentType) async {
|
||||
final created = await _api.saveDocumentType(documentType);
|
||||
final updatedState = {...state.documentTypes}
|
||||
..putIfAbsent(created.id!, () => created);
|
||||
emit(state.copyWith(documentTypes: updatedState));
|
||||
documentTypes = {...documentTypes, created.id!: created};
|
||||
notifyListeners();
|
||||
return created;
|
||||
}
|
||||
|
||||
Future<int> deleteDocumentType(DocumentType documentType) async {
|
||||
await _api.deleteDocumentType(documentType);
|
||||
final updatedState = {...state.documentTypes}
|
||||
..removeWhere((k, v) => k == documentType.id);
|
||||
emit(state.copyWith(documentTypes: updatedState));
|
||||
documentTypes.remove(documentType.id!);
|
||||
notifyListeners();
|
||||
return documentType.id!;
|
||||
}
|
||||
|
||||
Future<DocumentType?> findDocumentType(int id) async {
|
||||
final documentType = await _api.getDocumentType(id);
|
||||
if (documentType != null) {
|
||||
final updatedState = {...state.documentTypes}..[id] = documentType;
|
||||
emit(state.copyWith(documentTypes: updatedState));
|
||||
documentTypes = {...documentTypes, id: documentType};
|
||||
notifyListeners();
|
||||
return documentType;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
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)));
|
||||
emit(state.copyWith(documentTypes: updatedState));
|
||||
Future<Iterable<DocumentType>> findAllDocumentTypes() async {
|
||||
final documentTypes = await _api.getDocumentTypes();
|
||||
this.documentTypes = {
|
||||
for (var dt in documentTypes) dt.id!: dt,
|
||||
};
|
||||
notifyListeners();
|
||||
return documentTypes;
|
||||
}
|
||||
|
||||
Future<DocumentType> updateDocumentType(DocumentType documentType) async {
|
||||
final updated = await _api.updateDocumentType(documentType);
|
||||
final updatedState = {...state.documentTypes}
|
||||
..update(updated.id!, (_) => updated);
|
||||
emit(state.copyWith(documentTypes: updatedState));
|
||||
documentTypes = {...documentTypes, updated.id!: updated};
|
||||
notifyListeners();
|
||||
return updated;
|
||||
}
|
||||
|
||||
Future<StoragePath> createStoragePath(StoragePath storagePath) async {
|
||||
final created = await _api.saveStoragePath(storagePath);
|
||||
final updatedState = {...state.storagePaths}
|
||||
..putIfAbsent(created.id!, () => created);
|
||||
emit(state.copyWith(storagePaths: updatedState));
|
||||
storagePaths = {...storagePaths, created.id!: created};
|
||||
notifyListeners();
|
||||
return created;
|
||||
}
|
||||
|
||||
Future<int> deleteStoragePath(StoragePath storagePath) async {
|
||||
await _api.deleteStoragePath(storagePath);
|
||||
final updatedState = {...state.storagePaths}
|
||||
..removeWhere((k, v) => k == storagePath.id);
|
||||
emit(state.copyWith(storagePaths: updatedState));
|
||||
storagePaths.remove(storagePath.id!);
|
||||
notifyListeners();
|
||||
return storagePath.id!;
|
||||
}
|
||||
|
||||
Future<StoragePath?> findStoragePath(int id) async {
|
||||
final storagePath = await _api.getStoragePath(id);
|
||||
if (storagePath != null) {
|
||||
final updatedState = {...state.storagePaths}..[id] = storagePath;
|
||||
emit(state.copyWith(storagePaths: updatedState));
|
||||
storagePaths = {...storagePaths, id: storagePath};
|
||||
notifyListeners();
|
||||
return storagePath;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
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)));
|
||||
emit(state.copyWith(storagePaths: updatedState));
|
||||
Future<Iterable<StoragePath>> findAllStoragePaths() async {
|
||||
final storagePaths = await _api.getStoragePaths();
|
||||
this.storagePaths = {
|
||||
for (var sp in storagePaths) sp.id!: sp,
|
||||
};
|
||||
notifyListeners();
|
||||
return storagePaths;
|
||||
}
|
||||
|
||||
Future<StoragePath> updateStoragePath(StoragePath storagePath) async {
|
||||
final updated = await _api.updateStoragePath(storagePath);
|
||||
final updatedState = {...state.storagePaths}
|
||||
..update(updated.id!, (_) => updated);
|
||||
emit(state.copyWith(storagePaths: updatedState));
|
||||
storagePaths = {...storagePaths, updated.id!: updated};
|
||||
notifyListeners();
|
||||
return updated;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
|
||||
part 'label_repository_state.freezed.dart';
|
||||
part 'label_repository_state.g.dart';
|
||||
|
||||
@freezed
|
||||
class LabelRepositoryState with _$LabelRepositoryState {
|
||||
const factory LabelRepositoryState({
|
||||
@Default({}) Map<int, Correspondent> correspondents,
|
||||
@Default({}) Map<int, DocumentType> documentTypes,
|
||||
@Default({}) Map<int, Tag> tags,
|
||||
@Default({}) Map<int, StoragePath> storagePaths,
|
||||
}) = _LabelRepositoryState;
|
||||
|
||||
factory LabelRepositoryState.fromJson(Map<String, dynamic> json) =>
|
||||
_$LabelRepositoryStateFromJson(json);
|
||||
}
|
||||
@@ -1,95 +1,54 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/repository/persistent_repository.dart';
|
||||
|
||||
part 'saved_view_repository_state.dart';
|
||||
part 'saved_view_repository.g.dart';
|
||||
part 'saved_view_repository.freezed.dart';
|
||||
|
||||
class SavedViewRepository
|
||||
extends PersistentRepository<SavedViewRepositoryState> {
|
||||
class SavedViewRepository extends ChangeNotifier {
|
||||
final PaperlessSavedViewsApi _api;
|
||||
final Completer _initialized = Completer();
|
||||
Map<int, SavedView> savedViews = {};
|
||||
|
||||
SavedViewRepository(this._api)
|
||||
: super(const SavedViewRepositoryState.initial());
|
||||
SavedViewRepository(this._api);
|
||||
|
||||
Future<void> initialize() async {
|
||||
try {
|
||||
await findAll();
|
||||
_initialized.complete();
|
||||
} catch (e) {
|
||||
_initialized.completeError(e);
|
||||
emit(const SavedViewRepositoryState.error());
|
||||
}
|
||||
await findAll();
|
||||
}
|
||||
|
||||
Future<SavedView> create(SavedView object) async {
|
||||
await _initialized.future;
|
||||
final created = await _api.save(object);
|
||||
final updatedState = {...state.savedViews}
|
||||
..putIfAbsent(created.id!, () => created);
|
||||
emit(SavedViewRepositoryState.loaded(savedViews: updatedState));
|
||||
savedViews = {...savedViews, created.id!: created};
|
||||
notifyListeners();
|
||||
return created;
|
||||
}
|
||||
|
||||
Future<SavedView> update(SavedView object) async {
|
||||
await _initialized.future;
|
||||
final updated = await _api.update(object);
|
||||
final updatedState = {...state.savedViews}..update(
|
||||
updated.id!,
|
||||
(_) => updated,
|
||||
ifAbsent: () => updated,
|
||||
);
|
||||
emit(SavedViewRepositoryState.loaded(savedViews: updatedState));
|
||||
savedViews = {...savedViews, updated.id!: updated};
|
||||
notifyListeners();
|
||||
return updated;
|
||||
}
|
||||
|
||||
Future<int> delete(SavedView view) async {
|
||||
await _initialized.future;
|
||||
await _api.delete(view);
|
||||
final updatedState = {...state.savedViews}..remove(view.id);
|
||||
emit(SavedViewRepositoryState.loaded(savedViews: updatedState));
|
||||
savedViews.remove(view.id!);
|
||||
notifyListeners();
|
||||
return view.id!;
|
||||
}
|
||||
|
||||
Future<SavedView?> find(int id) async {
|
||||
await _initialized.future;
|
||||
final found = await _api.find(id);
|
||||
if (found != null) {
|
||||
final updatedState = {...state.savedViews}
|
||||
..update(id, (_) => found, ifAbsent: () => found);
|
||||
emit(SavedViewRepositoryState.loaded(savedViews: updatedState));
|
||||
savedViews = {...savedViews, id: found};
|
||||
notifyListeners();
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
Future<Iterable<SavedView>> findAll([Iterable<int>? ids]) async {
|
||||
final found = await _api.findAll(ids);
|
||||
final updatedState = {
|
||||
...state.savedViews,
|
||||
...{for (final view in found) view.id!: view},
|
||||
savedViews = {
|
||||
for (final view in found) view.id!: view,
|
||||
};
|
||||
emit(SavedViewRepositoryState.loaded(savedViews: updatedState));
|
||||
notifyListeners();
|
||||
return found;
|
||||
}
|
||||
|
||||
// @override
|
||||
// Future<void> clear() async {
|
||||
// await _initialized.future;
|
||||
// await super.clear();
|
||||
// emit(const SavedViewRepositoryState.initial());
|
||||
// }
|
||||
|
||||
// @override
|
||||
// SavedViewRepositoryState? fromJson(Map<String, dynamic> json) {
|
||||
// return SavedViewRepositoryState.fromJson(json);
|
||||
// }
|
||||
|
||||
// @override
|
||||
// Map<String, dynamic>? toJson(SavedViewRepositoryState state) {
|
||||
// return state.toJson();
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
part of 'saved_view_repository.dart';
|
||||
|
||||
|
||||
|
||||
@freezed
|
||||
class SavedViewRepositoryState with _$SavedViewRepositoryState {
|
||||
const factory SavedViewRepositoryState.initial({
|
||||
@Default({}) Map<int, SavedView> savedViews,
|
||||
}) = _Initial;
|
||||
const factory SavedViewRepositoryState.loading({
|
||||
@Default({}) Map<int, SavedView> savedViews,
|
||||
}) = _Loading;
|
||||
const factory SavedViewRepositoryState.loaded({
|
||||
@Default({}) Map<int, SavedView> savedViews,
|
||||
}) = _Loaded;
|
||||
const factory SavedViewRepositoryState.error({
|
||||
@Default({}) Map<int, SavedView> savedViews,
|
||||
}) = _Error;
|
||||
|
||||
factory SavedViewRepositoryState.fromJson(Map<String, dynamic> json) =>
|
||||
_$SavedViewRepositoryStateFromJson(json);
|
||||
}
|
||||
@@ -1,30 +1,45 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/repository/persistent_repository.dart';
|
||||
import 'package:paperless_mobile/features/logging/data/logger.dart';
|
||||
|
||||
part 'user_repository_state.dart';
|
||||
|
||||
/// Repository for new users (API v3, server version 1.14.2+)
|
||||
class UserRepository extends PersistentRepository<UserRepositoryState> {
|
||||
final PaperlessUserApiV3 _userApiV3;
|
||||
final PaperlessUserApi _userApi;
|
||||
|
||||
UserRepository(this._userApiV3) : super(const UserRepositoryState());
|
||||
UserRepository(this._userApi) : super(const UserRepositoryState());
|
||||
|
||||
Future<void> initialize() async {
|
||||
await findAll();
|
||||
}
|
||||
|
||||
Future<Iterable<UserModel>> findAll() async {
|
||||
final users = await _userApiV3.findAll();
|
||||
emit(state.copyWith(users: {for (var e in users) e.id: e}));
|
||||
return users;
|
||||
if (_userApi is PaperlessUserApiV3Impl) {
|
||||
final users = await (_userApi as PaperlessUserApiV3Impl).findAll();
|
||||
emit(state.copyWith(users: {for (var e in users) e.id: e}));
|
||||
return users;
|
||||
}
|
||||
logger.fw(
|
||||
"Tried to access API v3 features while using an older API version.",
|
||||
className: 'UserRepository',
|
||||
methodName: 'findAll',
|
||||
);
|
||||
return [];
|
||||
}
|
||||
|
||||
Future<UserModel?> find(int id) async {
|
||||
final user = await _userApiV3.find(id);
|
||||
emit(state.copyWith(users: state.users..[id] = user));
|
||||
return user;
|
||||
if (_userApi is PaperlessUserApiV3Impl) {
|
||||
final user = await (_userApi as PaperlessUserApiV3Impl).find(id);
|
||||
emit(state.copyWith(users: state.users..[id] = user));
|
||||
return user;
|
||||
}
|
||||
logger.fw(
|
||||
"Tried to access API v3 features while using an older API version.",
|
||||
className: 'UserRepository',
|
||||
methodName: 'findAll',
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
// @override
|
||||
|
||||
@@ -14,12 +14,12 @@ class FileService {
|
||||
|
||||
static FileService? _singleton;
|
||||
|
||||
late final Directory _logDirectory;
|
||||
late final Directory _temporaryDirectory;
|
||||
late final Directory _documentsDirectory;
|
||||
late final Directory _downloadsDirectory;
|
||||
late final Directory _uploadDirectory;
|
||||
late final Directory _temporaryScansDirectory;
|
||||
late Directory _logDirectory;
|
||||
late Directory _temporaryDirectory;
|
||||
late Directory _documentsDirectory;
|
||||
late Directory _downloadsDirectory;
|
||||
late Directory _uploadDirectory;
|
||||
late Directory _temporaryScansDirectory;
|
||||
|
||||
Directory get logDirectory => _logDirectory;
|
||||
Directory get temporaryDirectory => _temporaryDirectory;
|
||||
@@ -186,14 +186,15 @@ class FileService {
|
||||
}
|
||||
|
||||
Future<void> _initTemporaryDirectory() async {
|
||||
_temporaryDirectory = await getTemporaryDirectory();
|
||||
_temporaryDirectory =
|
||||
await getTemporaryDirectory().then((value) => value.create());
|
||||
}
|
||||
|
||||
Future<void> _initializeDocumentsDirectory() async {
|
||||
if (Platform.isAndroid) {
|
||||
final dirs =
|
||||
await getExternalStorageDirectories(type: StorageDirectory.documents);
|
||||
_documentsDirectory = dirs!.first;
|
||||
_documentsDirectory = await dirs!.first.create(recursive: true);
|
||||
return;
|
||||
} else if (Platform.isIOS) {
|
||||
final dir = await getApplicationDocumentsDirectory();
|
||||
@@ -212,12 +213,12 @@ class FileService {
|
||||
.then((directory) async =>
|
||||
directory?.firstOrNull ??
|
||||
await getApplicationDocumentsDirectory())
|
||||
.then((directory) =>
|
||||
Directory('${directory.path}/logs').create(recursive: true));
|
||||
.then((directory) => Directory(p.join(directory.path, 'logs'))
|
||||
.create(recursive: true));
|
||||
return;
|
||||
} else if (Platform.isIOS) {
|
||||
_logDirectory = await getApplicationDocumentsDirectory().then(
|
||||
(value) => Directory('${value.path}/logs').create(recursive: true));
|
||||
_logDirectory = await getApplicationDocumentsDirectory().then((value) =>
|
||||
Directory(p.join(value.path, 'logs')).create(recursive: true));
|
||||
return;
|
||||
}
|
||||
throw UnsupportedError("Platform not supported.");
|
||||
@@ -246,7 +247,7 @@ class FileService {
|
||||
|
||||
Future<void> _initUploadDirectory() async {
|
||||
final dir = await getApplicationDocumentsDirectory()
|
||||
.then((dir) => Directory('${dir.path}/upload'));
|
||||
.then((dir) => Directory(p.join(dir.path, 'upload')));
|
||||
_uploadDirectory = await dir.create(recursive: true);
|
||||
}
|
||||
|
||||
@@ -265,3 +266,13 @@ enum PaperlessDirectoryType {
|
||||
upload,
|
||||
logs;
|
||||
}
|
||||
|
||||
extension ClearDirectoryExtension on Directory {
|
||||
Future<void> clear() async {
|
||||
final streamedEntities = list();
|
||||
final entities = await streamedEntities.toList();
|
||||
await Future.wait([
|
||||
for (var entity in entities) entity.delete(recursive: true),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,5 +76,11 @@ String translateError(BuildContext context, ErrorCode code) {
|
||||
ErrorCode.userNotFound => S.of(context)!.userNotFound,
|
||||
ErrorCode.updateSavedViewError => S.of(context)!.couldNotUpdateSavedView,
|
||||
ErrorCode.userAlreadyExists => S.of(context)!.userAlreadyExists,
|
||||
ErrorCode.customFieldCreateFailed =>
|
||||
'Could not create custom field, please try again.', //TODO: INTL
|
||||
ErrorCode.customFieldLoadFailed =>
|
||||
'Could not load custom field.', //TODO: INTL
|
||||
ErrorCode.customFieldDeleteFailed =>
|
||||
'Could not delete custom field, please try again.', //TODO: INTL
|
||||
};
|
||||
}
|
||||
|
||||
7
lib/core/util/lambda_utils.dart
Normal file
7
lib/core/util/lambda_utils.dart
Normal file
@@ -0,0 +1,7 @@
|
||||
bool isNotNull<T>(T element) {
|
||||
return element != null;
|
||||
}
|
||||
|
||||
bool isNull<T>(T element) {
|
||||
return element == null;
|
||||
}
|
||||
Reference in New Issue
Block a user