mirror of
https://github.com/Xevion/paperless-mobile.git
synced 2025-12-07 03:15:49 -06:00
feat: More resturcturings, adapt code to previous changes
This commit is contained in:
@@ -16,13 +16,13 @@ class LocalUserAccount extends HiveObject {
|
|||||||
@HiveField(4)
|
@HiveField(4)
|
||||||
final LocalUserSettings settings;
|
final LocalUserSettings settings;
|
||||||
|
|
||||||
@HiveField(6)
|
@HiveField(7)
|
||||||
final int paperlessUserId;
|
final UserModel paperlessUser;
|
||||||
|
|
||||||
LocalUserAccount({
|
LocalUserAccount({
|
||||||
required this.id,
|
required this.id,
|
||||||
required this.serverUrl,
|
required this.serverUrl,
|
||||||
required this.settings,
|
required this.settings,
|
||||||
required this.paperlessUserId,
|
required this.paperlessUser,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,4 +7,6 @@ abstract class PaperlessApiFactory {
|
|||||||
PaperlessLabelsApi createLabelsApi(Dio dio, {required int apiVersion});
|
PaperlessLabelsApi createLabelsApi(Dio dio, {required int apiVersion});
|
||||||
PaperlessServerStatsApi createServerStatsApi(Dio dio, {required int apiVersion});
|
PaperlessServerStatsApi createServerStatsApi(Dio dio, {required int apiVersion});
|
||||||
PaperlessTasksApi createTasksApi(Dio dio, {required int apiVersion});
|
PaperlessTasksApi createTasksApi(Dio dio, {required int apiVersion});
|
||||||
|
PaperlessAuthenticationApi createAuthenticationApi(Dio dio);
|
||||||
|
PaperlessUserApi createUserApi(Dio dio, {required int apiVersion});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,4 +32,19 @@ class PaperlessApiFactoryImpl implements PaperlessApiFactory {
|
|||||||
PaperlessTasksApi createTasksApi(Dio dio, {required int apiVersion}) {
|
PaperlessTasksApi createTasksApi(Dio dio, {required int apiVersion}) {
|
||||||
return PaperlessTasksApiImpl(dio);
|
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.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,28 +4,13 @@ import 'package:flutter/widgets.dart';
|
|||||||
import 'package:hydrated_bloc/hydrated_bloc.dart';
|
import 'package:hydrated_bloc/hydrated_bloc.dart';
|
||||||
import 'package:paperless_api/paperless_api.dart';
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
import 'package:paperless_mobile/core/repository/label_repository_state.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 PaperlessLabelsApi _api;
|
||||||
final Map<Object, StreamSubscription> _subscribers = {};
|
|
||||||
|
|
||||||
LabelRepository(this._api) : super(const LabelRepositoryState());
|
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() {
|
Future<void> initialize() {
|
||||||
debugPrint("Initializing labels...");
|
debugPrint("Initializing labels...");
|
||||||
return Future.wait([
|
return Future.wait([
|
||||||
@@ -195,14 +180,6 @@ class LabelRepository extends HydratedCubit<LabelRepositoryState> {
|
|||||||
return updated;
|
return updated;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> close() {
|
|
||||||
_subscribers.forEach((key, subscription) {
|
|
||||||
subscription.cancel();
|
|
||||||
});
|
|
||||||
return super.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> clear() async {
|
Future<void> clear() async {
|
||||||
await super.clear();
|
await super.clear();
|
||||||
|
|||||||
32
lib/core/repository/persistent_repository.dart
Normal file
32
lib/core/repository/persistent_repository.dart
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,28 +1,11 @@
|
|||||||
import 'dart:async';
|
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_api/paperless_api.dart';
|
||||||
|
import 'package:paperless_mobile/core/repository/persistent_repository.dart';
|
||||||
import 'package:paperless_mobile/core/repository/saved_view_repository_state.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 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());
|
SavedViewRepository(this._api) : super(const SavedViewRepositoryState());
|
||||||
|
|
||||||
@@ -63,14 +46,6 @@ class SavedViewRepository extends HydratedCubit<SavedViewRepositoryState> {
|
|||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> close() {
|
|
||||||
_subscribers.forEach((key, subscription) {
|
|
||||||
subscription.cancel();
|
|
||||||
});
|
|
||||||
return super.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> clear() async {
|
Future<void> clear() async {
|
||||||
await super.clear();
|
await super.clear();
|
||||||
|
|||||||
40
lib/core/repository/user_repository.dart
Normal file
40
lib/core/repository/user_repository.dart
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
161
lib/core/repository/user_repository.freezed.dart
Normal file
161
lib/core/repository/user_repository.freezed.dart
Normal 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;
|
||||||
|
}
|
||||||
11
lib/core/repository/user_repository_state.dart
Normal file
11
lib/core/repository/user_repository_state.dart
Normal 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);
|
||||||
|
}
|
||||||
@@ -39,20 +39,13 @@ class DocumentDetailsPage extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
|
class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
|
||||||
late Future<DocumentMetaData> _metaData;
|
|
||||||
static const double _itemSpacing = 24;
|
static const double _itemSpacing = 24;
|
||||||
|
|
||||||
final _pagingScrollController = ScrollController();
|
final _pagingScrollController = ScrollController();
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
_loadMetaData();
|
|
||||||
}
|
|
||||||
|
|
||||||
void _loadMetaData() {
|
@override
|
||||||
_metaData = context
|
void didChangeDependencies() {
|
||||||
.read<PaperlessDocumentsApi>()
|
super.didChangeDependencies();
|
||||||
.getMetaData(context.read<DocumentDetailsCubit>().state.document);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -67,8 +60,7 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
|
|||||||
child: BlocListener<ConnectivityCubit, ConnectivityState>(
|
child: BlocListener<ConnectivityCubit, ConnectivityState>(
|
||||||
listenWhen: (previous, current) => !previous.isConnected && current.isConnected,
|
listenWhen: (previous, current) => !previous.isConnected && current.isConnected,
|
||||||
listener: (context, state) {
|
listener: (context, state) {
|
||||||
_loadMetaData();
|
context.read<DocumentDetailsCubit>().loadMetaData();
|
||||||
setState(() {});
|
|
||||||
},
|
},
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
extendBodyBehindAppBar: false,
|
extendBodyBehindAppBar: false,
|
||||||
@@ -98,7 +90,7 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Positioned.fill(
|
Positioned.fill(
|
||||||
top: 0,
|
top: 0,
|
||||||
child: Container(
|
child: Container(
|
||||||
height: 100,
|
height: 100,
|
||||||
@@ -285,7 +277,6 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
|
|||||||
DocumentDownloadButton(
|
DocumentDownloadButton(
|
||||||
document: state.document,
|
document: state.document,
|
||||||
enabled: isConnected,
|
enabled: isConnected,
|
||||||
metaData: _metaData,
|
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
tooltip: S.of(context)!.previewTooltip,
|
tooltip: S.of(context)!.previewTooltip,
|
||||||
|
|||||||
@@ -20,12 +20,10 @@ import 'package:permission_handler/permission_handler.dart';
|
|||||||
class DocumentDownloadButton extends StatefulWidget {
|
class DocumentDownloadButton extends StatefulWidget {
|
||||||
final DocumentModel? document;
|
final DocumentModel? document;
|
||||||
final bool enabled;
|
final bool enabled;
|
||||||
final Future<DocumentMetaData> metaData;
|
|
||||||
const DocumentDownloadButton({
|
const DocumentDownloadButton({
|
||||||
super.key,
|
super.key,
|
||||||
required this.document,
|
required this.document,
|
||||||
this.enabled = true,
|
this.enabled = true,
|
||||||
required this.metaData,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -38,12 +38,9 @@ class ScannerPage extends StatefulWidget {
|
|||||||
State<ScannerPage> createState() => _ScannerPageState();
|
State<ScannerPage> createState() => _ScannerPageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ScannerPageState extends State<ScannerPage>
|
class _ScannerPageState extends State<ScannerPage> with SingleTickerProviderStateMixin {
|
||||||
with SingleTickerProviderStateMixin {
|
final SliverOverlapAbsorberHandle searchBarHandle = SliverOverlapAbsorberHandle();
|
||||||
final SliverOverlapAbsorberHandle searchBarHandle =
|
final SliverOverlapAbsorberHandle actionsHandle = SliverOverlapAbsorberHandle();
|
||||||
SliverOverlapAbsorberHandle();
|
|
||||||
final SliverOverlapAbsorberHandle actionsHandle =
|
|
||||||
SliverOverlapAbsorberHandle();
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@@ -180,8 +177,7 @@ class _ScannerPageState extends State<ScannerPage>
|
|||||||
final success = await EdgeDetection.detectEdge(file.path);
|
final success = await EdgeDetection.detectEdge(file.path);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
if (kDebugMode) {
|
if (kDebugMode) {
|
||||||
dev.log(
|
dev.log('[ScannerPage] Scan either not successful or canceled by user.');
|
||||||
'[ScannerPage] Scan either not successful or canceled by user.');
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -198,7 +194,7 @@ class _ScannerPageState extends State<ScannerPage>
|
|||||||
final uploadResult = await Navigator.of(context).push<DocumentUploadResult>(
|
final uploadResult = await Navigator.of(context).push<DocumentUploadResult>(
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (_) => BlocProvider(
|
builder: (_) => BlocProvider(
|
||||||
create: (context) => DocumentUploadCubit(
|
create: (_) => DocumentUploadCubit(
|
||||||
context.read(),
|
context.read(),
|
||||||
context.read(),
|
context.read(),
|
||||||
),
|
),
|
||||||
@@ -212,9 +208,7 @@ class _ScannerPageState extends State<ScannerPage>
|
|||||||
if ((uploadResult?.success ?? false) && uploadResult?.taskId != null) {
|
if ((uploadResult?.success ?? false) && uploadResult?.taskId != null) {
|
||||||
// For paperless version older than 1.11.3, task id will always be null!
|
// For paperless version older than 1.11.3, task id will always be null!
|
||||||
context.read<DocumentScannerCubit>().reset();
|
context.read<DocumentScannerCubit>().reset();
|
||||||
context
|
context.read<TaskStatusCubit>().listenToTaskChanges(uploadResult!.taskId!);
|
||||||
.read<TaskStatusCubit>()
|
|
||||||
.listenToTaskChanges(uploadResult!.taskId!);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -226,13 +226,10 @@ class _DocumentSearchPageState extends State<DocumentSearchPage> {
|
|||||||
hasLoaded: state.hasLoaded,
|
hasLoaded: state.hasLoaded,
|
||||||
enableHeroAnimation: false,
|
enableHeroAnimation: false,
|
||||||
onTap: (document) {
|
onTap: (document) {
|
||||||
Navigator.pushNamed(
|
pushDocumentDetailsRoute(
|
||||||
context,
|
context,
|
||||||
DocumentDetailsRoute.routeName,
|
document: document,
|
||||||
arguments: DocumentDetailsRouteArguments(
|
isLabelClickable: false,
|
||||||
document: document,
|
|
||||||
isLabelClickable: false,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
correspondents: state.correspondents,
|
correspondents: state.correspondents,
|
||||||
|
|||||||
@@ -47,7 +47,10 @@ class SliverSearchBar extends StatelessWidget {
|
|||||||
Hive.box<LocalUserAccount>(HiveBoxes.localUserAccount).listenable(),
|
Hive.box<LocalUserAccount>(HiveBoxes.localUserAccount).listenable(),
|
||||||
builder: (context, box, _) {
|
builder: (context, box, _) {
|
||||||
final account = box.get(settings.currentLoggedInUser!)!;
|
final account = box.get(settings.currentLoggedInUser!)!;
|
||||||
return UserAvatar(userId: settings.currentLoggedInUser!, account: account);
|
return UserAvatar(
|
||||||
|
userId: settings.currentLoggedInUser!,
|
||||||
|
account: account,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ class DocumentUploadPreparationPage extends StatefulWidget {
|
|||||||
final String? filename;
|
final String? filename;
|
||||||
final String? fileExtension;
|
final String? fileExtension;
|
||||||
|
|
||||||
|
|
||||||
const DocumentUploadPreparationPage({
|
const DocumentUploadPreparationPage({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.fileBytes,
|
required this.fileBytes,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
import 'package:paperless_api/paperless_api.dart';
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
import 'package:paperless_mobile/core/bloc/connectivity_cubit.dart';
|
import 'package:paperless_mobile/core/bloc/connectivity_cubit.dart';
|
||||||
import 'package:paperless_mobile/core/delegate/customizable_sliver_persistent_header_delegate.dart';
|
import 'package:paperless_mobile/core/delegate/customizable_sliver_persistent_header_delegate.dart';
|
||||||
|
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
||||||
import 'package:paperless_mobile/core/widgets/material/colored_tab_bar.dart';
|
import 'package:paperless_mobile/core/widgets/material/colored_tab_bar.dart';
|
||||||
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
||||||
import 'package:paperless_mobile/features/app_drawer/view/app_drawer.dart';
|
import 'package:paperless_mobile/features/app_drawer/view/app_drawer.dart';
|
||||||
@@ -443,12 +444,9 @@ class _DocumentsPageState extends State<DocumentsPage> with SingleTickerProvider
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _openDetails(DocumentModel document) {
|
void _openDetails(DocumentModel document) {
|
||||||
Navigator.pushNamed(
|
pushDocumentDetailsRoute(
|
||||||
context,
|
context,
|
||||||
DocumentDetailsRoute.routeName,
|
document: document,
|
||||||
arguments: DocumentDetailsRouteArguments(
|
|
||||||
document: document,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import 'package:cached_network_image/cached_network_image.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
|
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
|
||||||
import 'package:paperless_api/paperless_api.dart';
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
import 'package:paperless_mobile/features/documents/view/pages/document_view.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:shimmer/shimmer.dart';
|
import 'package:shimmer/shimmer.dart';
|
||||||
|
|
||||||
|
|||||||
@@ -23,8 +23,13 @@ import 'package:paperless_mobile/features/tasks/cubit/task_status_cubit.dart';
|
|||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class HomeRoute extends StatelessWidget {
|
class HomeRoute extends StatelessWidget {
|
||||||
|
/// The id of the currently authenticated user (e.g. demo@paperless.example.com)
|
||||||
final String localUserId;
|
final String localUserId;
|
||||||
|
|
||||||
|
/// The Paperless API version of the currently connected instance
|
||||||
final int paperlessApiVersion;
|
final int paperlessApiVersion;
|
||||||
|
|
||||||
|
// A factory providing the API implementations given an API version
|
||||||
final PaperlessApiFactory paperlessProviderFactory;
|
final PaperlessApiFactory paperlessProviderFactory;
|
||||||
|
|
||||||
const HomeRoute({
|
const HomeRoute({
|
||||||
@@ -44,6 +49,7 @@ class HomeRoute extends StatelessWidget {
|
|||||||
Provider<CacheManager>(
|
Provider<CacheManager>(
|
||||||
create: (context) => CacheManager(
|
create: (context) => CacheManager(
|
||||||
Config(
|
Config(
|
||||||
|
// Isolated cache per user.
|
||||||
localUserId,
|
localUserId,
|
||||||
fileService: DioFileService(context.read<SessionManager>().client),
|
fileService: DioFileService(context.read<SessionManager>().client),
|
||||||
),
|
),
|
||||||
@@ -121,11 +127,15 @@ class HomeRoute extends StatelessWidget {
|
|||||||
)..initialize(),
|
)..initialize(),
|
||||||
),
|
),
|
||||||
ProxyProvider<PaperlessServerStatsApi, ServerInformationCubit>(
|
ProxyProvider<PaperlessServerStatsApi, ServerInformationCubit>(
|
||||||
update: (context, value, previous) => ServerInformationCubit(value),
|
update: (context, value, previous) =>
|
||||||
|
ServerInformationCubit(value)..updateInformation(),
|
||||||
),
|
),
|
||||||
ProxyProvider<LabelRepository, LabelCubit>(
|
ProxyProvider<LabelRepository, LabelCubit>(
|
||||||
update: (context, value, previous) => LabelCubit(value),
|
update: (context, value, previous) => LabelCubit(value),
|
||||||
),
|
),
|
||||||
|
ProxyProvider<PaperlessTasksApi, TaskStatusCubit>(
|
||||||
|
update: (context, value, previous) => TaskStatusCubit(value),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
child: const HomePage(),
|
child: const HomePage(),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -37,14 +37,11 @@ class _InboxItemState extends State<InboxItem> {
|
|||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
behavior: HitTestBehavior.translucent,
|
behavior: HitTestBehavior.translucent,
|
||||||
onTap: () async {
|
onTap: () {
|
||||||
Navigator.pushNamed(
|
pushDocumentDetailsRoute(
|
||||||
context,
|
context,
|
||||||
DocumentDetailsRoute.routeName,
|
document: widget.document,
|
||||||
arguments: DocumentDetailsRouteArguments(
|
isLabelClickable: false,
|
||||||
document: widget.document,
|
|
||||||
isLabelClickable: false,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
|
|||||||
@@ -52,13 +52,10 @@ class _LinkedDocumentsPageState extends State<LinkedDocumentsPage>
|
|||||||
isLoading: state.isLoading,
|
isLoading: state.isLoading,
|
||||||
hasLoaded: state.hasLoaded,
|
hasLoaded: state.hasLoaded,
|
||||||
onTap: (document) {
|
onTap: (document) {
|
||||||
Navigator.pushNamed(
|
pushDocumentDetailsRoute(
|
||||||
context,
|
context,
|
||||||
DocumentDetailsRoute.routeName,
|
document: document,
|
||||||
arguments: DocumentDetailsRouteArguments(
|
isLabelClickable: false,
|
||||||
document: document,
|
|
||||||
isLabelClickable: false,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
correspondents: state.correspondents,
|
correspondents: state.correspondents,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
|
||||||
import 'package:equatable/equatable.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
import 'package:hive_flutter/adapters.dart';
|
import 'package:hive_flutter/adapters.dart';
|
||||||
@@ -9,6 +9,7 @@ import 'package:hydrated_bloc/hydrated_bloc.dart';
|
|||||||
import 'package:paperless_api/paperless_api.dart';
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
import 'package:paperless_mobile/core/config/hive/hive_config.dart';
|
import 'package:paperless_mobile/core/config/hive/hive_config.dart';
|
||||||
import 'package:paperless_mobile/core/database/tables/local_user_app_state.dart';
|
import 'package:paperless_mobile/core/database/tables/local_user_app_state.dart';
|
||||||
|
import 'package:paperless_mobile/core/factory/paperless_api_factory.dart';
|
||||||
import 'package:paperless_mobile/core/security/session_manager.dart';
|
import 'package:paperless_mobile/core/security/session_manager.dart';
|
||||||
import 'package:paperless_mobile/features/login/model/client_certificate.dart';
|
import 'package:paperless_mobile/features/login/model/client_certificate.dart';
|
||||||
import 'package:paperless_mobile/features/login/model/login_form_credentials.dart';
|
import 'package:paperless_mobile/features/login/model/login_form_credentials.dart';
|
||||||
@@ -23,16 +24,14 @@ part 'authentication_state.dart';
|
|||||||
part 'authentication_cubit.freezed.dart';
|
part 'authentication_cubit.freezed.dart';
|
||||||
|
|
||||||
class AuthenticationCubit extends Cubit<AuthenticationState> {
|
class AuthenticationCubit extends Cubit<AuthenticationState> {
|
||||||
final PaperlessUserApi _userApi;
|
|
||||||
final LocalAuthenticationService _localAuthService;
|
final LocalAuthenticationService _localAuthService;
|
||||||
final PaperlessAuthenticationApi _authApi;
|
final PaperlessApiFactory _apiFactory;
|
||||||
final SessionManager _sessionManager;
|
final SessionManager _sessionManager;
|
||||||
|
|
||||||
AuthenticationCubit(
|
AuthenticationCubit(
|
||||||
this._localAuthService,
|
this._localAuthService,
|
||||||
this._authApi,
|
this._apiFactory,
|
||||||
this._sessionManager,
|
this._sessionManager,
|
||||||
this._userApi,
|
|
||||||
) : super(const AuthenticationState.unauthenticated());
|
) : super(const AuthenticationState.unauthenticated());
|
||||||
|
|
||||||
Future<void> login({
|
Future<void> login({
|
||||||
@@ -43,7 +42,7 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
|
|||||||
assert(credentials.username != null && credentials.password != null);
|
assert(credentials.username != null && credentials.password != null);
|
||||||
final localUserId = "${credentials.username}@$serverUrl";
|
final localUserId = "${credentials.username}@$serverUrl";
|
||||||
|
|
||||||
final serverUser = await _addUser(
|
await _addUser(
|
||||||
localUserId,
|
localUserId,
|
||||||
serverUrl,
|
serverUrl,
|
||||||
credentials,
|
credentials,
|
||||||
@@ -51,13 +50,13 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
|
|||||||
_sessionManager,
|
_sessionManager,
|
||||||
);
|
);
|
||||||
|
|
||||||
final response = await _sessionManager.client.get("/api/");
|
final apiVersion = await _getApiVersion(_sessionManager.client);
|
||||||
final apiVersion = response.headers["x-api-version"] as int;
|
|
||||||
|
|
||||||
// Mark logged in user as currently active user.
|
// Mark logged in user as currently active user.
|
||||||
final globalSettings = Hive.box<GlobalSettings>(HiveBoxes.globalSettings).getValue()!;
|
final globalSettings = Hive.box<GlobalSettings>(HiveBoxes.globalSettings).getValue()!;
|
||||||
globalSettings.currentLoggedInUser = localUserId;
|
globalSettings.currentLoggedInUser = localUserId;
|
||||||
await globalSettings.save();
|
await globalSettings.save();
|
||||||
|
|
||||||
emit(
|
emit(
|
||||||
AuthenticationState.authenticated(
|
AuthenticationState.authenticated(
|
||||||
apiVersion: apiVersion,
|
apiVersion: apiVersion,
|
||||||
@@ -110,8 +109,8 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
|
|||||||
globalSettings.currentLoggedInUser = localUserId;
|
globalSettings.currentLoggedInUser = localUserId;
|
||||||
await globalSettings.save();
|
await globalSettings.save();
|
||||||
|
|
||||||
final response = await _sessionManager.client.get("/api/");
|
final apiVersion = await _getApiVersion(_sessionManager.client);
|
||||||
final apiVersion = response.headers["x-api-version"] as int;
|
|
||||||
emit(AuthenticationState.authenticated(
|
emit(AuthenticationState.authenticated(
|
||||||
localUserId: localUserId,
|
localUserId: localUserId,
|
||||||
apiVersion: apiVersion,
|
apiVersion: apiVersion,
|
||||||
@@ -188,8 +187,7 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
|
|||||||
authToken: authentication.token,
|
authToken: authentication.token,
|
||||||
baseUrl: userAccount.serverUrl,
|
baseUrl: userAccount.serverUrl,
|
||||||
);
|
);
|
||||||
final response = await _sessionManager.client.get("/api/");
|
final apiVersion = await _getApiVersion(_sessionManager.client);
|
||||||
final apiVersion = response.headers["x-api-version"] as int;
|
|
||||||
emit(
|
emit(
|
||||||
AuthenticationState.authenticated(
|
AuthenticationState.authenticated(
|
||||||
apiVersion: apiVersion,
|
apiVersion: apiVersion,
|
||||||
@@ -247,26 +245,34 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
|
|||||||
baseUrl: serverUrl,
|
baseUrl: serverUrl,
|
||||||
clientCertificate: clientCert,
|
clientCertificate: clientCert,
|
||||||
);
|
);
|
||||||
final authApi = PaperlessAuthenticationApiImpl(sessionManager.client);
|
|
||||||
|
final authApi = _apiFactory.createAuthenticationApi(sessionManager.client);
|
||||||
|
|
||||||
final token = await authApi.login(
|
final token = await authApi.login(
|
||||||
username: credentials.username!,
|
username: credentials.username!,
|
||||||
password: credentials.password!,
|
password: credentials.password!,
|
||||||
);
|
);
|
||||||
|
|
||||||
sessionManager.updateSettings(
|
sessionManager.updateSettings(
|
||||||
baseUrl: serverUrl,
|
baseUrl: serverUrl,
|
||||||
clientCertificate: clientCert,
|
clientCertificate: clientCert,
|
||||||
authToken: token,
|
authToken: token,
|
||||||
);
|
);
|
||||||
|
|
||||||
final userAccountBox = Hive.box<LocalUserAccount>(HiveBoxes.localUserAccount);
|
final userAccountBox = Hive.box<LocalUserAccount>(HiveBoxes.localUserAccount);
|
||||||
final userStateBox = Hive.box<LocalUserAppState>(HiveBoxes.localUserAppState);
|
final userStateBox = Hive.box<LocalUserAppState>(HiveBoxes.localUserAppState);
|
||||||
|
|
||||||
if (userAccountBox.containsKey(localUserId)) {
|
if (userAccountBox.containsKey(localUserId)) {
|
||||||
throw Exception("User with id $localUserId already exists!");
|
throw Exception("User with id $localUserId already exists!");
|
||||||
}
|
}
|
||||||
|
final apiVersion = await _getApiVersion(sessionManager.client);
|
||||||
|
|
||||||
final serverUserId = await _userApi.findCurrentUserId();
|
final serverUser = await _apiFactory
|
||||||
|
.createUserApi(
|
||||||
|
sessionManager.client,
|
||||||
|
apiVersion: apiVersion,
|
||||||
|
)
|
||||||
|
.findCurrentUser();
|
||||||
|
|
||||||
// Create user account
|
// Create user account
|
||||||
await userAccountBox.put(
|
await userAccountBox.put(
|
||||||
@@ -275,7 +281,7 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
|
|||||||
id: localUserId,
|
id: localUserId,
|
||||||
settings: LocalUserSettings(),
|
settings: LocalUserSettings(),
|
||||||
serverUrl: serverUrl,
|
serverUrl: serverUrl,
|
||||||
paperlessUserId: 1,
|
paperlessUser: serverUser,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -295,6 +301,11 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
userCredentialsBox.close();
|
userCredentialsBox.close();
|
||||||
return serverUserId;
|
return serverUser.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<int> _getApiVersion(Dio dio) async {
|
||||||
|
final response = await dio.get("/api/");
|
||||||
|
return int.parse(response.headers.value('x-api-version') ?? "3");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:equatable/equatable.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
import 'package:paperless_api/paperless_api.dart';
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
@@ -37,18 +36,20 @@ class SavedViewCubit extends Cubit<SavedViewState> {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
_savedViewRepository.subscribe(this, (views) {
|
_savedViewRepository.addListener(
|
||||||
emit(
|
this,
|
||||||
state.maybeWhen(
|
onChanged: (views) {
|
||||||
loaded:
|
emit(
|
||||||
(savedViews, correspondents, documentTypes, tags, storagePaths) =>
|
state.maybeWhen(
|
||||||
(state as _SavedViewLoadedState).copyWith(
|
loaded: (savedViews, correspondents, documentTypes, tags, storagePaths) =>
|
||||||
savedViews: views,
|
(state as _SavedViewLoadedState).copyWith(
|
||||||
|
savedViews: views.savedViews,
|
||||||
|
),
|
||||||
|
orElse: () => state,
|
||||||
),
|
),
|
||||||
orElse: () => state,
|
);
|
||||||
),
|
},
|
||||||
);
|
);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<SavedView> add(SavedView view) async {
|
Future<SavedView> add(SavedView view) async {
|
||||||
@@ -77,7 +78,7 @@ class SavedViewCubit extends Cubit<SavedViewState> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> close() {
|
Future<void> close() {
|
||||||
_savedViewRepository.unsubscribe(this);
|
_savedViewRepository.removeListener(this);
|
||||||
_labelRepository.removeListener(this);
|
_labelRepository.removeListener(this);
|
||||||
return super.close();
|
return super.close();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,12 +76,13 @@ class _SavedViewDetailsPageState extends State<SavedViewDetailsPage>
|
|||||||
isLoading: state.isLoading,
|
isLoading: state.isLoading,
|
||||||
hasLoaded: state.hasLoaded,
|
hasLoaded: state.hasLoaded,
|
||||||
onTap: (document) {
|
onTap: (document) {
|
||||||
Navigator.pushNamed(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
DocumentDetailsRoute.routeName,
|
MaterialPageRoute(
|
||||||
arguments: DocumentDetailsRouteArguments(
|
builder: (context) => DocumentDetailsRoute(
|
||||||
document: document,
|
document: document,
|
||||||
isLabelClickable: false,
|
isLabelClickable: false,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -86,11 +86,11 @@ class ManageAccountsPage extends StatelessWidget {
|
|||||||
final child = SizedBox(
|
final child = SizedBox(
|
||||||
width: double.maxFinite,
|
width: double.maxFinite,
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
title: Text(account.username),
|
title: Text(account.paperlessUser.username),
|
||||||
subtitle: Column(
|
subtitle: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
if (account.fullName != null) Text(account.fullName!),
|
if (account.paperlessUser.fullName != null) Text(account.paperlessUser.fullName!),
|
||||||
Text(
|
Text(
|
||||||
account.serverUrl.replaceFirst(RegExp(r'https://?'), ''),
|
account.serverUrl.replaceFirst(RegExp(r'https://?'), ''),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
@@ -99,7 +99,7 @@ class ManageAccountsPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
isThreeLine: account.fullName != null,
|
isThreeLine: account.paperlessUser.fullName != null,
|
||||||
leading: UserAvatar(
|
leading: UserAvatar(
|
||||||
account: account,
|
account: account,
|
||||||
userId: userId,
|
userId: userId,
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ class SettingsPage extends StatelessWidget {
|
|||||||
final host = user!.serverUrl.replaceFirst(RegExp(r"https?://"), "");
|
final host = user!.serverUrl.replaceFirst(RegExp(r"https?://"), "");
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text(
|
title: Text(
|
||||||
S.of(context)!.loggedInAs(user.username) + "@$host",
|
S.of(context)!.loggedInAs(user.paperlessUser.username) + "@$host",
|
||||||
style: Theme.of(context).textTheme.labelSmall,
|
style: Theme.of(context).textTheme.labelSmall,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
import 'package:paperless_mobile/core/database/tables/local_user_account.dart';
|
import 'package:paperless_mobile/core/database/tables/local_user_account.dart';
|
||||||
|
import 'package:paperless_mobile/core/repository/user_repository.dart';
|
||||||
|
|
||||||
class UserAvatar extends StatelessWidget {
|
class UserAvatar extends StatelessWidget {
|
||||||
final String userId;
|
final String userId;
|
||||||
@@ -16,7 +19,7 @@ class UserAvatar extends StatelessWidget {
|
|||||||
final backgroundColor = Colors.primaries[userId.hashCode % Colors.primaries.length];
|
final backgroundColor = Colors.primaries[userId.hashCode % Colors.primaries.length];
|
||||||
final foregroundColor = backgroundColor.computeLuminance() > 0.5 ? Colors.black : Colors.white;
|
final foregroundColor = backgroundColor.computeLuminance() > 0.5 ? Colors.black : Colors.white;
|
||||||
return CircleAvatar(
|
return CircleAvatar(
|
||||||
child: Text((account.fullName ?? account.username)
|
child: Text((account.paperlessUser.fullName ?? account.paperlessUser.username)
|
||||||
.split(" ")
|
.split(" ")
|
||||||
.take(2)
|
.take(2)
|
||||||
.map((e) => e.substring(0, 1))
|
.map((e) => e.substring(0, 1))
|
||||||
|
|||||||
@@ -36,10 +36,8 @@ class _SimilarDocumentsViewState extends State<SimilarDocumentsView>
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocConsumer<ConnectivityCubit, ConnectivityState>(
|
return BlocConsumer<ConnectivityCubit, ConnectivityState>(
|
||||||
listenWhen: (previous, current) =>
|
listenWhen: (previous, current) => !previous.isConnected && current.isConnected,
|
||||||
!previous.isConnected && current.isConnected,
|
listener: (context, state) => context.read<SimilarDocumentsCubit>().initialize(),
|
||||||
listener: (context, state) =>
|
|
||||||
context.read<SimilarDocumentsCubit>().initialize(),
|
|
||||||
builder: (context, connectivity) {
|
builder: (context, connectivity) {
|
||||||
return BlocBuilder<SimilarDocumentsCubit, SimilarDocumentsState>(
|
return BlocBuilder<SimilarDocumentsCubit, SimilarDocumentsState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
@@ -48,9 +46,7 @@ class _SimilarDocumentsViewState extends State<SimilarDocumentsView>
|
|||||||
child: OfflineWidget(),
|
child: OfflineWidget(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (state.hasLoaded &&
|
if (state.hasLoaded && !state.isLoading && state.documents.isEmpty) {
|
||||||
!state.isLoading &&
|
|
||||||
state.documents.isEmpty) {
|
|
||||||
return SliverToBoxAdapter(
|
return SliverToBoxAdapter(
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Text(S.of(context)!.noItemsFound),
|
child: Text(S.of(context)!.noItemsFound),
|
||||||
@@ -65,13 +61,10 @@ class _SimilarDocumentsViewState extends State<SimilarDocumentsView>
|
|||||||
hasLoaded: state.hasLoaded,
|
hasLoaded: state.hasLoaded,
|
||||||
enableHeroAnimation: false,
|
enableHeroAnimation: false,
|
||||||
onTap: (document) {
|
onTap: (document) {
|
||||||
Navigator.pushNamed(
|
pushDocumentDetailsRoute(
|
||||||
context,
|
context,
|
||||||
DocumentDetailsRoute.routeName,
|
document: document,
|
||||||
arguments: DocumentDetailsRouteArguments(
|
isLabelClickable: false,
|
||||||
document: document,
|
|
||||||
isLabelClickable: false,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
correspondents: state.correspondents,
|
correspondents: state.correspondents,
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import 'package:device_info_plus/device_info_plus.dart';
|
|||||||
import 'package:dynamic_color/dynamic_color.dart';
|
import 'package:dynamic_color/dynamic_color.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_cache_manager/flutter_cache_manager.dart' as cm;
|
|
||||||
import 'package:flutter_displaymode/flutter_displaymode.dart';
|
import 'package:flutter_displaymode/flutter_displaymode.dart';
|
||||||
import 'package:flutter_native_splash/flutter_native_splash.dart';
|
import 'package:flutter_native_splash/flutter_native_splash.dart';
|
||||||
import 'package:hive_flutter/adapters.dart';
|
import 'package:hive_flutter/adapters.dart';
|
||||||
@@ -26,11 +25,8 @@ import 'package:paperless_mobile/core/factory/paperless_api_factory_impl.dart';
|
|||||||
import 'package:paperless_mobile/core/interceptor/dio_http_error_interceptor.dart';
|
import 'package:paperless_mobile/core/interceptor/dio_http_error_interceptor.dart';
|
||||||
import 'package:paperless_mobile/core/interceptor/language_header.interceptor.dart';
|
import 'package:paperless_mobile/core/interceptor/language_header.interceptor.dart';
|
||||||
import 'package:paperless_mobile/core/notifier/document_changed_notifier.dart';
|
import 'package:paperless_mobile/core/notifier/document_changed_notifier.dart';
|
||||||
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
|
||||||
import 'package:paperless_mobile/core/repository/saved_view_repository.dart';
|
|
||||||
import 'package:paperless_mobile/core/security/session_manager.dart';
|
import 'package:paperless_mobile/core/security/session_manager.dart';
|
||||||
import 'package:paperless_mobile/core/service/connectivity_status_service.dart';
|
import 'package:paperless_mobile/core/service/connectivity_status_service.dart';
|
||||||
import 'package:paperless_mobile/core/service/dio_file_service.dart';
|
|
||||||
import 'package:paperless_mobile/core/type/types.dart';
|
import 'package:paperless_mobile/core/type/types.dart';
|
||||||
import 'package:paperless_mobile/features/app_intro/application_intro_slideshow.dart';
|
import 'package:paperless_mobile/features/app_intro/application_intro_slideshow.dart';
|
||||||
import 'package:paperless_mobile/features/home/view/home_route.dart';
|
import 'package:paperless_mobile/features/home/view/home_route.dart';
|
||||||
@@ -125,6 +121,8 @@ void main() async {
|
|||||||
languageHeaderInterceptor.preferredLocaleSubtag = globalSettings.preferredLocaleSubtag;
|
languageHeaderInterceptor.preferredLocaleSubtag = globalSettings.preferredLocaleSubtag;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
final apiFactory = PaperlessApiFactoryImpl(sessionManager);
|
||||||
|
|
||||||
runApp(
|
runApp(
|
||||||
MultiProvider(
|
MultiProvider(
|
||||||
providers: [
|
providers: [
|
||||||
@@ -139,9 +137,17 @@ void main() async {
|
|||||||
child: MultiBlocProvider(
|
child: MultiBlocProvider(
|
||||||
providers: [
|
providers: [
|
||||||
BlocProvider<ConnectivityCubit>.value(value: connectivityCubit),
|
BlocProvider<ConnectivityCubit>.value(value: connectivityCubit),
|
||||||
|
BlocProvider(
|
||||||
|
create: (context) => AuthenticationCubit(
|
||||||
|
localAuthService,
|
||||||
|
apiFactory,
|
||||||
|
sessionManager,
|
||||||
|
),
|
||||||
|
child: Container(),
|
||||||
|
)
|
||||||
],
|
],
|
||||||
child: PaperlessMobileEntrypoint(
|
child: PaperlessMobileEntrypoint(
|
||||||
paperlessProviderFactory: PaperlessApiFactoryImpl(sessionManager),
|
paperlessProviderFactory: apiFactory,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -187,9 +193,6 @@ class _PaperlessMobileEntrypointState extends State<PaperlessMobileEntrypoint> {
|
|||||||
localizationsDelegates: const [
|
localizationsDelegates: const [
|
||||||
...S.localizationsDelegates,
|
...S.localizationsDelegates,
|
||||||
],
|
],
|
||||||
routes: {
|
|
||||||
DocumentDetailsRoute.routeName: (context) => const DocumentDetailsRoute(),
|
|
||||||
},
|
|
||||||
home: AuthenticationWrapper(
|
home: AuthenticationWrapper(
|
||||||
paperlessProviderFactory: widget.paperlessProviderFactory,
|
paperlessProviderFactory: widget.paperlessProviderFactory,
|
||||||
),
|
),
|
||||||
@@ -217,7 +220,10 @@ class _AuthenticationWrapperState extends State<AuthenticationWrapper> {
|
|||||||
@override
|
@override
|
||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
FlutterNativeSplash.remove();
|
context
|
||||||
|
.read<AuthenticationCubit>()
|
||||||
|
.restoreSessionState()
|
||||||
|
.then((value) => FlutterNativeSplash.remove());
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -1,34 +1,44 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
|
||||||
import 'package:paperless_api/paperless_api.dart';
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
|
import 'package:paperless_mobile/core/notifier/document_changed_notifier.dart';
|
||||||
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
||||||
import 'package:paperless_mobile/features/document_details/cubit/document_details_cubit.dart';
|
import 'package:paperless_mobile/features/document_details/cubit/document_details_cubit.dart';
|
||||||
import 'package:paperless_mobile/features/document_details/view/pages/document_details_page.dart';
|
import 'package:paperless_mobile/features/document_details/view/pages/document_details_page.dart';
|
||||||
|
import 'package:paperless_mobile/features/notifications/services/local_notification_service.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class DocumentDetailsRoute extends StatelessWidget {
|
class DocumentDetailsRoute extends StatelessWidget {
|
||||||
static const String routeName = "/documentDetails";
|
final DocumentModel document;
|
||||||
const DocumentDetailsRoute({super.key});
|
final bool isLabelClickable;
|
||||||
|
final bool allowEdit;
|
||||||
|
final String? titleAndContentQueryString;
|
||||||
|
|
||||||
|
const DocumentDetailsRoute({
|
||||||
|
super.key,
|
||||||
|
required this.document,
|
||||||
|
this.isLabelClickable = true,
|
||||||
|
this.allowEdit = true,
|
||||||
|
this.titleAndContentQueryString,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final args = ModalRoute.of(context)!.settings.arguments
|
|
||||||
as DocumentDetailsRouteArguments;
|
|
||||||
|
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) => DocumentDetailsCubit(
|
create: (_) => DocumentDetailsCubit(
|
||||||
context.read(),
|
context.read(),
|
||||||
context.read(),
|
context.read(),
|
||||||
context.read(),
|
context.read(),
|
||||||
context.read(),
|
context.read(),
|
||||||
initialDocument: args.document,
|
initialDocument: document,
|
||||||
),
|
),
|
||||||
child: RepositoryProvider.value(
|
lazy: false,
|
||||||
value: context.read<LabelRepository>(),
|
child: DocumentDetailsPage(
|
||||||
child: DocumentDetailsPage(
|
allowEdit: allowEdit,
|
||||||
allowEdit: args.allowEdit,
|
isLabelClickable: isLabelClickable,
|
||||||
isLabelClickable: args.isLabelClickable,
|
titleAndContentQueryString: titleAndContentQueryString,
|
||||||
titleAndContentQueryString: args.titleAndContentQueryString,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -47,3 +57,33 @@ class DocumentDetailsRouteArguments {
|
|||||||
this.titleAndContentQueryString,
|
this.titleAndContentQueryString,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> pushDocumentDetailsRoute(
|
||||||
|
BuildContext context, {
|
||||||
|
required DocumentModel document,
|
||||||
|
bool isLabelClickable = true,
|
||||||
|
bool allowEdit = true,
|
||||||
|
String? titleAndContentQueryString,
|
||||||
|
}) {
|
||||||
|
final LabelRepository labelRepository = context.read();
|
||||||
|
final DocumentChangedNotifier changeNotifier = context.read();
|
||||||
|
final PaperlessDocumentsApi documentsApi = context.read();
|
||||||
|
final LocalNotificationService notificationservice = context.read();
|
||||||
|
final CacheManager cacheManager = context.read();
|
||||||
|
return Navigator.of(context).push(MaterialPageRoute(
|
||||||
|
builder: (_) => MultiProvider(
|
||||||
|
providers: [
|
||||||
|
Provider.value(value: documentsApi),
|
||||||
|
Provider.value(value: labelRepository),
|
||||||
|
Provider.value(value: changeNotifier),
|
||||||
|
Provider.value(value: notificationservice),
|
||||||
|
Provider.value(value: cacheManager),
|
||||||
|
],
|
||||||
|
child: DocumentDetailsRoute(
|
||||||
|
document: document,
|
||||||
|
allowEdit: allowEdit,
|
||||||
|
isLabelClickable: isLabelClickable,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ class UserModel with _$UserModel {
|
|||||||
if (value.firstName == null) {
|
if (value.firstName == null) {
|
||||||
return value.lastName;
|
return value.lastName;
|
||||||
}
|
}
|
||||||
return value.firstName! + (value.lastName ?? '');
|
return "${value.firstName!} ${value.lastName ?? ''}";
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,12 @@ class PaperlessServerStatsApiImpl implements PaperlessServerStatsApi {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<PaperlessServerInformationModel> getServerInformation() async {
|
Future<PaperlessServerInformationModel> getServerInformation() async {
|
||||||
final response = await client.get("/api/");
|
final response = await client.get("/api/remote_version/");
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
final version = response.data["version"] as String;
|
||||||
|
final updateAvailable = response.data["update_available"] as bool;
|
||||||
|
}
|
||||||
|
throw PaperlessServerException.unknown();
|
||||||
final version =
|
final version =
|
||||||
response.headers[PaperlessServerInformationModel.versionHeader]?.first ?? 'unknown';
|
response.headers[PaperlessServerInformationModel.versionHeader]?.first ?? 'unknown';
|
||||||
final apiVersion = int.tryParse(
|
final apiVersion = int.tryParse(
|
||||||
|
|||||||
@@ -2,5 +2,5 @@ import 'package:paperless_api/paperless_api.dart';
|
|||||||
|
|
||||||
abstract class PaperlessUserApi {
|
abstract class PaperlessUserApi {
|
||||||
Future<int> findCurrentUserId();
|
Future<int> findCurrentUserId();
|
||||||
Future<UserModel> find(int id);
|
Future<UserModel> findCurrentUser();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:paperless_api/paperless_api.dart';
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
import 'package:paperless_api/src/modules/user_api/paperless_user_api.dart';
|
|
||||||
|
|
||||||
class PaperlessUserApiV2Impl implements PaperlessUserApi {
|
class PaperlessUserApiV2Impl implements PaperlessUserApi {
|
||||||
final Dio client;
|
final Dio client;
|
||||||
@@ -11,13 +10,13 @@ class PaperlessUserApiV2Impl implements PaperlessUserApi {
|
|||||||
Future<int> findCurrentUserId() async {
|
Future<int> findCurrentUserId() async {
|
||||||
final response = await client.get("/api/ui_settings/");
|
final response = await client.get("/api/ui_settings/");
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
return response.data['user']['id'];
|
return response.data['user_id'];
|
||||||
}
|
}
|
||||||
throw const PaperlessServerException.unknown();
|
throw const PaperlessServerException.unknown();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<UserModel> find(int id) async {
|
Future<UserModel> findCurrentUser() async {
|
||||||
final response = await client.get("/api/ui_settings/");
|
final response = await client.get("/api/ui_settings/");
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
return UserModelV2.fromJson(response.data);
|
return UserModelV2.fromJson(response.data);
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import 'package:paperless_api/src/models/user_model.dart';
|
import 'package:paperless_api/src/models/user_model.dart';
|
||||||
|
|
||||||
abstract class PaperlessUserApiV3 {
|
abstract class PaperlessUserApiV3 {
|
||||||
Future<Iterable<UserModel>> findWhere({
|
Future<UserModelV3> find(int id);
|
||||||
|
Future<Iterable<UserModelV3>> findAll();
|
||||||
|
Future<Iterable<UserModelV3>> findWhere({
|
||||||
String startsWith,
|
String startsWith,
|
||||||
String endsWith,
|
String endsWith,
|
||||||
String contains,
|
String contains,
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:paperless_api/paperless_api.dart';
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
import 'package:paperless_api/src/modules/user_api/paperless_user_api.dart';
|
|
||||||
import 'package:paperless_api/src/modules/user_api/paperless_user_api_v3.dart';
|
|
||||||
|
|
||||||
class PaperlessUserApiV3Impl implements PaperlessUserApi, PaperlessUserApiV3 {
|
class PaperlessUserApiV3Impl implements PaperlessUserApi, PaperlessUserApiV3 {
|
||||||
final Dio dio;
|
final Dio dio;
|
||||||
@@ -9,7 +7,7 @@ class PaperlessUserApiV3Impl implements PaperlessUserApi, PaperlessUserApiV3 {
|
|||||||
PaperlessUserApiV3Impl(this.dio);
|
PaperlessUserApiV3Impl(this.dio);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<UserModel> find(int id) async {
|
Future<UserModelV3> find(int id) async {
|
||||||
final response = await dio.get("/api/users/$id/");
|
final response = await dio.get("/api/users/$id/");
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
return UserModelV3.fromJson(response.data);
|
return UserModelV3.fromJson(response.data);
|
||||||
@@ -18,7 +16,7 @@ class PaperlessUserApiV3Impl implements PaperlessUserApi, PaperlessUserApiV3 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Iterable<UserModel>> findWhere({
|
Future<Iterable<UserModelV3>> findWhere({
|
||||||
String startsWith = '',
|
String startsWith = '',
|
||||||
String endsWith = '',
|
String endsWith = '',
|
||||||
String contains = '',
|
String contains = '',
|
||||||
@@ -31,9 +29,9 @@ class PaperlessUserApiV3Impl implements PaperlessUserApi, PaperlessUserApiV3 {
|
|||||||
"username__iexact": username,
|
"username__iexact": username,
|
||||||
});
|
});
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
return PagedSearchResult<UserModel>.fromJson(
|
return PagedSearchResult<UserModelV3>.fromJson(
|
||||||
response.data,
|
response.data,
|
||||||
UserModelV3.fromJson as UserModel Function(Object?),
|
UserModelV3.fromJson as UserModelV3 Function(Object?),
|
||||||
).results;
|
).results;
|
||||||
}
|
}
|
||||||
throw const PaperlessServerException.unknown();
|
throw const PaperlessServerException.unknown();
|
||||||
@@ -43,8 +41,26 @@ class PaperlessUserApiV3Impl implements PaperlessUserApi, PaperlessUserApiV3 {
|
|||||||
Future<int> findCurrentUserId() async {
|
Future<int> findCurrentUserId() async {
|
||||||
final response = await dio.get("/api/ui_settings/");
|
final response = await dio.get("/api/ui_settings/");
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
return response.data['user_id'];
|
return response.data['user']['id'];
|
||||||
}
|
}
|
||||||
throw const PaperlessServerException.unknown();
|
throw const PaperlessServerException.unknown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Iterable<UserModelV3>> findAll() async {
|
||||||
|
final response = await dio.get("/api/users/");
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
return PagedSearchResult<UserModelV3>.fromJson(
|
||||||
|
response.data,
|
||||||
|
UserModelV3.fromJson as UserModelV3 Function(Object?),
|
||||||
|
).results;
|
||||||
|
}
|
||||||
|
throw const PaperlessServerException.unknown();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<UserModel> findCurrentUser() async {
|
||||||
|
final id = await findCurrentUserId();
|
||||||
|
return find(id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user