feat: More resturcturings, adapt code to previous changes

This commit is contained in:
Anton Stubenbord
2023-05-01 23:05:54 +02:00
parent 88085b5662
commit d5c68e023c
35 changed files with 475 additions and 200 deletions

View File

@@ -16,13 +16,13 @@ class LocalUserAccount extends HiveObject {
@HiveField(4)
final LocalUserSettings settings;
@HiveField(6)
final int paperlessUserId;
@HiveField(7)
final UserModel paperlessUser;
LocalUserAccount({
required this.id,
required this.serverUrl,
required this.settings,
required this.paperlessUserId,
required this.paperlessUser,
});
}

View File

@@ -7,4 +7,6 @@ abstract class PaperlessApiFactory {
PaperlessLabelsApi createLabelsApi(Dio dio, {required int apiVersion});
PaperlessServerStatsApi createServerStatsApi(Dio dio, {required int apiVersion});
PaperlessTasksApi createTasksApi(Dio dio, {required int apiVersion});
PaperlessAuthenticationApi createAuthenticationApi(Dio dio);
PaperlessUserApi createUserApi(Dio dio, {required int apiVersion});
}

View File

@@ -32,4 +32,19 @@ class PaperlessApiFactoryImpl implements PaperlessApiFactory {
PaperlessTasksApi createTasksApi(Dio dio, {required int apiVersion}) {
return PaperlessTasksApiImpl(dio);
}
@override
PaperlessAuthenticationApi createAuthenticationApi(Dio dio) {
return PaperlessAuthenticationApiImpl(dio);
}
@override
PaperlessUserApi createUserApi(Dio dio, {required int apiVersion}) {
if (apiVersion == 3) {
return PaperlessUserApiV3Impl(dio);
} else if (apiVersion == 1 || apiVersion == 2) {
return PaperlessUserApiV2Impl(dio);
}
throw Exception("API $apiVersion not supported.");
}
}

View File

@@ -4,28 +4,13 @@ import 'package:flutter/widgets.dart';
import 'package:hydrated_bloc/hydrated_bloc.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 HydratedCubit<LabelRepositoryState> {
class LabelRepository extends PersistentRepository<LabelRepositoryState> {
final PaperlessLabelsApi _api;
final Map<Object, StreamSubscription> _subscribers = {};
LabelRepository(this._api) : super(const LabelRepositoryState());
void addListener(
Object source, {
required void Function(LabelRepositoryState) onChanged,
}) {
onChanged(state);
_subscribers.putIfAbsent(source, () {
return stream.listen((event) => onChanged(event));
});
}
void removeListener(Object source) async {
await _subscribers[source]?.cancel();
_subscribers.remove(source);
}
Future<void> initialize() {
debugPrint("Initializing labels...");
return Future.wait([
@@ -195,14 +180,6 @@ class LabelRepository extends HydratedCubit<LabelRepositoryState> {
return updated;
}
@override
Future<void> close() {
_subscribers.forEach((key, subscription) {
subscription.cancel();
});
return super.close();
}
@override
Future<void> clear() async {
await super.clear();

View File

@@ -0,0 +1,32 @@
import 'dart:async';
import 'package:hydrated_bloc/hydrated_bloc.dart';
abstract class PersistentRepository<T> extends HydratedCubit<T> {
final Map<Object, StreamSubscription> _subscribers = {};
PersistentRepository(T initialState) : super(initialState);
void addListener(
Object source, {
required void Function(T) onChanged,
}) {
onChanged(state);
_subscribers.putIfAbsent(source, () {
return stream.listen((event) => onChanged(event));
});
}
void removeListener(Object source) async {
await _subscribers[source]?.cancel();
_subscribers.remove(source);
}
@override
Future<void> close() {
_subscribers.forEach((key, subscription) {
subscription.cancel();
});
return super.close();
}
}

View File

@@ -1,28 +1,11 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:hydrated_bloc/hydrated_bloc.dart';
import 'package:paperless_api/paperless_api.dart';
import 'package:paperless_mobile/core/repository/persistent_repository.dart';
import 'package:paperless_mobile/core/repository/saved_view_repository_state.dart';
class SavedViewRepository extends HydratedCubit<SavedViewRepositoryState> {
class SavedViewRepository extends PersistentRepository<SavedViewRepositoryState> {
final PaperlessSavedViewsApi _api;
final Map<Object, StreamSubscription> _subscribers = {};
void subscribe(
Object source,
void Function(Map<int, SavedView>) onChanged,
) {
_subscribers.putIfAbsent(source, () {
onChanged(state.savedViews);
return stream.listen((event) => onChanged(event.savedViews));
});
}
void unsubscribe(Object source) async {
await _subscribers[source]?.cancel();
_subscribers.remove(source);
}
SavedViewRepository(this._api) : super(const SavedViewRepositoryState());
@@ -63,14 +46,6 @@ class SavedViewRepository extends HydratedCubit<SavedViewRepositoryState> {
return found;
}
@override
Future<void> close() {
_subscribers.forEach((key, subscription) {
subscription.cancel();
});
return super.close();
}
@override
Future<void> clear() async {
await super.clear();

View File

@@ -0,0 +1,40 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:paperless_api/paperless_api.dart';
import 'package:paperless_mobile/core/repository/persistent_repository.dart';
part 'user_repository_state.dart';
part 'user_repository.freezed.dart';
part 'user_repository.g.dart';
/// Repository for new users (API v3, server version 1.14.2+)
class UserRepository extends PersistentRepository<UserRepositoryState> {
final PaperlessUserApiV3 _userApiV3;
UserRepository(this._userApiV3) : 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;
}
Future<UserModel?> find(int id) async {
final user = await _userApiV3.find(id);
emit(state.copyWith(users: state.users..[id] = user));
return user;
}
@override
UserRepositoryState? fromJson(Map<String, dynamic> json) {
return UserRepositoryState.fromJson(json);
}
@override
Map<String, dynamic>? toJson(UserRepositoryState state) {
return state.toJson();
}
}

View File

@@ -0,0 +1,161 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'user_repository.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
UserRepositoryState _$UserRepositoryStateFromJson(Map<String, dynamic> json) {
return _UserRepositoryState.fromJson(json);
}
/// @nodoc
mixin _$UserRepositoryState {
Map<int, UserModel> get users => throw _privateConstructorUsedError;
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$UserRepositoryStateCopyWith<UserRepositoryState> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $UserRepositoryStateCopyWith<$Res> {
factory $UserRepositoryStateCopyWith(
UserRepositoryState value, $Res Function(UserRepositoryState) then) =
_$UserRepositoryStateCopyWithImpl<$Res, UserRepositoryState>;
@useResult
$Res call({Map<int, UserModel> users});
}
/// @nodoc
class _$UserRepositoryStateCopyWithImpl<$Res, $Val extends UserRepositoryState>
implements $UserRepositoryStateCopyWith<$Res> {
_$UserRepositoryStateCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
@pragma('vm:prefer-inline')
@override
$Res call({
Object? users = null,
}) {
return _then(_value.copyWith(
users: null == users
? _value.users
: users // ignore: cast_nullable_to_non_nullable
as Map<int, UserModel>,
) as $Val);
}
}
/// @nodoc
abstract class _$$_UserRepositoryStateCopyWith<$Res>
implements $UserRepositoryStateCopyWith<$Res> {
factory _$$_UserRepositoryStateCopyWith(_$_UserRepositoryState value,
$Res Function(_$_UserRepositoryState) then) =
__$$_UserRepositoryStateCopyWithImpl<$Res>;
@override
@useResult
$Res call({Map<int, UserModel> users});
}
/// @nodoc
class __$$_UserRepositoryStateCopyWithImpl<$Res>
extends _$UserRepositoryStateCopyWithImpl<$Res, _$_UserRepositoryState>
implements _$$_UserRepositoryStateCopyWith<$Res> {
__$$_UserRepositoryStateCopyWithImpl(_$_UserRepositoryState _value,
$Res Function(_$_UserRepositoryState) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@override
$Res call({
Object? users = null,
}) {
return _then(_$_UserRepositoryState(
users: null == users
? _value._users
: users // ignore: cast_nullable_to_non_nullable
as Map<int, UserModel>,
));
}
}
/// @nodoc
@JsonSerializable()
class _$_UserRepositoryState implements _UserRepositoryState {
const _$_UserRepositoryState({final Map<int, UserModel> users = const {}})
: _users = users;
factory _$_UserRepositoryState.fromJson(Map<String, dynamic> json) =>
_$$_UserRepositoryStateFromJson(json);
final Map<int, UserModel> _users;
@override
@JsonKey()
Map<int, UserModel> get users {
if (_users is EqualUnmodifiableMapView) return _users;
// ignore: implicit_dynamic_type
return EqualUnmodifiableMapView(_users);
}
@override
String toString() {
return 'UserRepositoryState(users: $users)';
}
@override
bool operator ==(dynamic other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$_UserRepositoryState &&
const DeepCollectionEquality().equals(other._users, _users));
}
@JsonKey(ignore: true)
@override
int get hashCode =>
Object.hash(runtimeType, const DeepCollectionEquality().hash(_users));
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$_UserRepositoryStateCopyWith<_$_UserRepositoryState> get copyWith =>
__$$_UserRepositoryStateCopyWithImpl<_$_UserRepositoryState>(
this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$_UserRepositoryStateToJson(
this,
);
}
}
abstract class _UserRepositoryState implements UserRepositoryState {
const factory _UserRepositoryState({final Map<int, UserModel> users}) =
_$_UserRepositoryState;
factory _UserRepositoryState.fromJson(Map<String, dynamic> json) =
_$_UserRepositoryState.fromJson;
@override
Map<int, UserModel> get users;
@override
@JsonKey(ignore: true)
_$$_UserRepositoryStateCopyWith<_$_UserRepositoryState> get copyWith =>
throw _privateConstructorUsedError;
}

View File

@@ -0,0 +1,11 @@
part of 'user_repository.dart';
@freezed
class UserRepositoryState with _$UserRepositoryState {
const factory UserRepositoryState({
@Default({}) Map<int, UserModel> users,
}) = _UserRepositoryState;
factory UserRepositoryState.fromJson(Map<String, dynamic> json) =>
_$UserRepositoryStateFromJson(json);
}