WIP - Redesigned login flow

This commit is contained in:
Anton Stubenbord
2023-01-05 01:38:00 +01:00
parent 2445c97d44
commit 738ef99bc5
60 changed files with 1159 additions and 755 deletions

View File

@@ -0,0 +1,18 @@
///
/// Base repository class which all repositories should implement
///
abstract class BaseRepository<State, Object> {
Stream<State?> get values;
State? get current;
bool get isInitialized;
Future<Object> create(Object object);
Future<Object?> find(int id);
Future<Iterable<Object>> findAll([Iterable<int>? ids]);
Future<Object> update(Object object);
Future<int> delete(Object object);
void clear();
}

View File

@@ -7,35 +7,43 @@ import 'package:rxdart/rxdart.dart' show BehaviorSubject;
class CorrespondentRepositoryImpl implements LabelRepository<Correspondent> {
final PaperlessLabelsApi _api;
final _subject = BehaviorSubject<Map<int, Correspondent>>.seeded(const {});
final _subject = BehaviorSubject<Map<int, Correspondent>?>();
CorrespondentRepositoryImpl(this._api);
@override
Stream<Map<int, Correspondent>> get labels =>
bool get isInitialized => _subject.valueOrNull != null;
@override
Stream<Map<int, Correspondent>?> get values =>
_subject.stream.asBroadcastStream();
Map<int, Correspondent> get _currentValueOrEmpty =>
_subject.valueOrNull ?? {};
@override
Future<Correspondent> create(Correspondent correspondent) async {
final created = await _api.saveCorrespondent(correspondent);
final updatedState = {..._subject.value}
final updatedState = {..._currentValueOrEmpty}
..putIfAbsent(created.id!, () => created);
_subject.add(updatedState);
return created;
}
@override
Future<void> delete(Correspondent correspondent) async {
Future<int> delete(Correspondent correspondent) async {
await _api.deleteCorrespondent(correspondent);
final updatedState = {..._subject.value}
final updatedState = {..._currentValueOrEmpty}
..removeWhere((k, v) => k == correspondent.id);
_subject.add(updatedState);
return correspondent.id!;
}
@override
Future<Correspondent?> find(int id) async {
final correspondent = await _api.getCorrespondent(id);
if (correspondent != null) {
final updatedState = {..._subject.value}..[id] = correspondent;
final updatedState = {..._currentValueOrEmpty}..[id] = correspondent;
_subject.add(updatedState);
return correspondent;
}
@@ -45,7 +53,7 @@ class CorrespondentRepositoryImpl implements LabelRepository<Correspondent> {
@override
Future<Iterable<Correspondent>> findAll([Iterable<int>? ids]) async {
final correspondents = await _api.getCorrespondents(ids);
final updatedState = {..._subject.value}
final updatedState = {..._currentValueOrEmpty}
..addEntries(correspondents.map((e) => MapEntry(e.id!, e)));
_subject.add(updatedState);
return correspondents;
@@ -54,7 +62,7 @@ class CorrespondentRepositoryImpl implements LabelRepository<Correspondent> {
@override
Future<Correspondent> update(Correspondent correspondent) async {
final updated = await _api.updateCorrespondent(correspondent);
final updatedState = {..._subject.value}
final updatedState = {..._currentValueOrEmpty}
..update(updated.id!, (_) => updated);
_subject.add(updatedState);
return updated;
@@ -62,9 +70,9 @@ class CorrespondentRepositoryImpl implements LabelRepository<Correspondent> {
@override
void clear() {
_subject.add(const {});
_subject.add(null);
}
@override
Map<int, Correspondent> get current => _subject.value;
Map<int, Correspondent>? get current => _subject.valueOrNull;
}

View File

@@ -5,36 +5,42 @@ import 'package:rxdart/rxdart.dart' show BehaviorSubject;
class DocumentTypeRepositoryImpl implements LabelRepository<DocumentType> {
final PaperlessLabelsApi _api;
final _subject = BehaviorSubject<Map<int, DocumentType>>.seeded(const {});
final _subject = BehaviorSubject<Map<int, DocumentType>?>();
DocumentTypeRepositoryImpl(this._api);
@override
Stream<Map<int, DocumentType>> get labels =>
Stream<Map<int, DocumentType>?> get values =>
_subject.stream.asBroadcastStream();
@override
bool get isInitialized => _subject.valueOrNull != null;
Map<int, DocumentType> get _currentValueOrEmpty => _subject.valueOrNull ?? {};
@override
Future<DocumentType> create(DocumentType documentType) async {
final created = await _api.saveDocumentType(documentType);
final updatedState = {..._subject.value}
final updatedState = {..._currentValueOrEmpty}
..putIfAbsent(created.id!, () => created);
_subject.add(updatedState);
return created;
}
@override
Future<void> delete(DocumentType documentType) async {
Future<int> delete(DocumentType documentType) async {
await _api.deleteDocumentType(documentType);
final updatedState = {..._subject.value}
final updatedState = {..._currentValueOrEmpty}
..removeWhere((k, v) => k == documentType.id);
_subject.add(updatedState);
return documentType.id!;
}
@override
Future<DocumentType?> find(int id) async {
final documentType = await _api.getDocumentType(id);
if (documentType != null) {
final updatedState = {..._subject.value}..[id] = documentType;
final updatedState = {..._currentValueOrEmpty}..[id] = documentType;
_subject.add(updatedState);
return documentType;
}
@@ -44,7 +50,7 @@ class DocumentTypeRepositoryImpl implements LabelRepository<DocumentType> {
@override
Future<Iterable<DocumentType>> findAll([Iterable<int>? ids]) async {
final documentTypes = await _api.getDocumentTypes(ids);
final updatedState = {..._subject.value}
final updatedState = {..._currentValueOrEmpty}
..addEntries(documentTypes.map((e) => MapEntry(e.id!, e)));
_subject.add(updatedState);
return documentTypes;
@@ -53,7 +59,7 @@ class DocumentTypeRepositoryImpl implements LabelRepository<DocumentType> {
@override
Future<DocumentType> update(DocumentType documentType) async {
final updated = await _api.updateDocumentType(documentType);
final updatedState = {..._subject.value}
final updatedState = {..._currentValueOrEmpty}
..update(updated.id!, (_) => updated);
_subject.add(updatedState);
return updated;
@@ -65,5 +71,5 @@ class DocumentTypeRepositoryImpl implements LabelRepository<DocumentType> {
}
@override
Map<int, DocumentType> get current => _subject.value;
Map<int, DocumentType>? get current => _subject.valueOrNull;
}

View File

@@ -7,10 +7,10 @@ class SavedViewRepositoryImpl implements SavedViewRepository {
SavedViewRepositoryImpl(this._api);
final BehaviorSubject<Map<int, SavedView>?> _subject = BehaviorSubject();
final _subject = BehaviorSubject<Map<int, SavedView>?>();
@override
Stream<Map<int, SavedView>?> get savedViews =>
Stream<Map<int, SavedView>?> get values =>
_subject.stream.asBroadcastStream();
@override
@@ -54,4 +54,15 @@ class SavedViewRepositoryImpl implements SavedViewRepository {
_subject.add(updatedState);
return found;
}
@override
Map<int, SavedView>? get current => _subject.valueOrNull;
@override
bool get isInitialized => _subject.hasValue;
@override
Future<SavedView> update(SavedView object) {
throw UnimplementedError("Saved view update is not yet implemented");
}
}

View File

@@ -5,36 +5,39 @@ import 'package:rxdart/rxdart.dart' show BehaviorSubject;
class StoragePathRepositoryImpl implements LabelRepository<StoragePath> {
final PaperlessLabelsApi _api;
final _subject = BehaviorSubject<Map<int, StoragePath>>.seeded(const {});
final _subject = BehaviorSubject<Map<int, StoragePath>?>();
StoragePathRepositoryImpl(this._api);
@override
Stream<Map<int, StoragePath>> get labels =>
Stream<Map<int, StoragePath>?> get values =>
_subject.stream.asBroadcastStream();
Map<int, StoragePath> get _currentValueOrEmpty => _subject.valueOrNull ?? {};
@override
Future<StoragePath> create(StoragePath storagePath) async {
final created = await _api.saveStoragePath(storagePath);
final updatedState = {..._subject.value}
final updatedState = {..._currentValueOrEmpty}
..putIfAbsent(created.id!, () => created);
_subject.add(updatedState);
return created;
}
@override
Future<void> delete(StoragePath storagePath) async {
Future<int> delete(StoragePath storagePath) async {
await _api.deleteStoragePath(storagePath);
final updatedState = {..._subject.value}
final updatedState = {..._currentValueOrEmpty}
..removeWhere((k, v) => k == storagePath.id);
_subject.add(updatedState);
return storagePath.id!;
}
@override
Future<StoragePath?> find(int id) async {
final storagePath = await _api.getStoragePath(id);
if (storagePath != null) {
final updatedState = {..._subject.value}..[id] = storagePath;
final updatedState = {..._currentValueOrEmpty}..[id] = storagePath;
_subject.add(updatedState);
return storagePath;
}
@@ -44,7 +47,7 @@ class StoragePathRepositoryImpl implements LabelRepository<StoragePath> {
@override
Future<Iterable<StoragePath>> findAll([Iterable<int>? ids]) async {
final storagePaths = await _api.getStoragePaths(ids);
final updatedState = {..._subject.value}
final updatedState = {..._currentValueOrEmpty}
..addEntries(storagePaths.map((e) => MapEntry(e.id!, e)));
_subject.add(updatedState);
return storagePaths;
@@ -53,7 +56,7 @@ class StoragePathRepositoryImpl implements LabelRepository<StoragePath> {
@override
Future<StoragePath> update(StoragePath storagePath) async {
final updated = await _api.updateStoragePath(storagePath);
final updatedState = {..._subject.value}
final updatedState = {..._currentValueOrEmpty}
..update(updated.id!, (_) => updated);
_subject.add(updatedState);
return updated;
@@ -65,5 +68,8 @@ class StoragePathRepositoryImpl implements LabelRepository<StoragePath> {
}
@override
Map<int, StoragePath> get current => _subject.value;
Map<int, StoragePath>? get current => _subject.valueOrNull;
@override
bool get isInitialized => _subject.valueOrNull != null;
}

View File

@@ -5,35 +5,38 @@ import 'package:rxdart/rxdart.dart' show BehaviorSubject;
class TagRepositoryImpl implements LabelRepository<Tag> {
final PaperlessLabelsApi _api;
final _subject = BehaviorSubject<Map<int, Tag>>.seeded(const {});
final _subject = BehaviorSubject<Map<int, Tag>?>();
TagRepositoryImpl(this._api);
@override
Stream<Map<int, Tag>> get labels => _subject.stream.asBroadcastStream();
Stream<Map<int, Tag>?> get values => _subject.stream.asBroadcastStream();
Map<int, Tag> get _currentValueOrEmpty => _subject.valueOrNull ?? {};
@override
Future<Tag> create(Tag tag) async {
final created = await _api.saveTag(tag);
final updatedState = {..._subject.value}
final updatedState = {..._currentValueOrEmpty}
..putIfAbsent(created.id!, () => created);
_subject.add(updatedState);
return created;
}
@override
Future<void> delete(Tag tag) async {
Future<int> delete(Tag tag) async {
await _api.deleteTag(tag);
final updatedState = {..._subject.value}
final updatedState = {..._currentValueOrEmpty}
..removeWhere((k, v) => k == tag.id);
_subject.add(updatedState);
return tag.id!;
}
@override
Future<Tag?> find(int id) async {
final tag = await _api.getTag(id);
if (tag != null) {
final updatedState = {..._subject.value}..[id] = tag;
final updatedState = {..._currentValueOrEmpty}..[id] = tag;
_subject.add(updatedState);
return tag;
}
@@ -43,7 +46,7 @@ class TagRepositoryImpl implements LabelRepository<Tag> {
@override
Future<Iterable<Tag>> findAll([Iterable<int>? ids]) async {
final tags = await _api.getTags(ids);
final updatedState = {..._subject.value}
final updatedState = {..._currentValueOrEmpty}
..addEntries(tags.map((e) => MapEntry(e.id!, e)));
_subject.add(updatedState);
return tags;
@@ -52,7 +55,7 @@ class TagRepositoryImpl implements LabelRepository<Tag> {
@override
Future<Tag> update(Tag tag) async {
final updated = await _api.updateTag(tag);
final updatedState = {..._subject.value}
final updatedState = {..._currentValueOrEmpty}
..update(updated.id!, (_) => updated);
_subject.add(updatedState);
return updated;
@@ -60,9 +63,12 @@ class TagRepositoryImpl implements LabelRepository<Tag> {
@override
void clear() {
_subject.add(const {});
_subject.add(null);
}
@override
Map<int, Tag> get current => _subject.value;
Map<int, Tag>? get current => _subject.valueOrNull;
@override
bool get isInitialized => _subject.valueOrNull != null;
}

View File

@@ -1,15 +1,5 @@
import 'package:paperless_api/paperless_api.dart';
import 'package:paperless_mobile/core/repository/base_repository.dart';
abstract class LabelRepository<T extends Label> {
Stream<Map<int, T>> get labels;
Map<int, T> get current;
Future<T> create(T label);
Future<T?> find(int id);
Future<Iterable<T>> findAll([Iterable<int>? ids]);
Future<T> update(T label);
Future<void> delete(T label);
void clear();
}
abstract class LabelRepository<T extends Label>
implements BaseRepository<Map<int, T>, T> {}

View File

@@ -1,12 +1,5 @@
import 'package:paperless_api/paperless_api.dart';
import 'package:paperless_mobile/core/repository/base_repository.dart';
abstract class SavedViewRepository {
Stream<Map<int, SavedView>?> get savedViews;
Future<SavedView> create(SavedView view);
Future<SavedView?> find(int id);
Future<Iterable<SavedView>> findAll([Iterable<int>? ids]);
Future<int> delete(SavedView view);
void clear();
}
abstract class SavedViewRepository
implements BaseRepository<Map<int, SavedView>, SavedView> {}