mirror of
https://github.com/Xevion/paperless-mobile.git
synced 2025-12-09 16:07:57 -06:00
fix: Add custom fields, translations, add app logs to login routes
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user