mirror of
https://github.com/Xevion/paperless-mobile.git
synced 2025-12-13 22:12:17 -06:00
WIP - Provider refactorings
This commit is contained in:
@@ -2,11 +2,7 @@ import 'dart:async';
|
|||||||
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:paperless_mobile/core/service/connectivity_status.service.dart';
|
import 'package:paperless_mobile/core/service/connectivity_status.service.dart';
|
||||||
import 'package:injectable/injectable.dart';
|
|
||||||
|
|
||||||
@prod
|
|
||||||
@test
|
|
||||||
@lazySingleton
|
|
||||||
class ConnectivityCubit extends Cubit<ConnectivityState> {
|
class ConnectivityCubit extends Cubit<ConnectivityState> {
|
||||||
final ConnectivityStatusService connectivityStatusService;
|
final ConnectivityStatusService connectivityStatusService;
|
||||||
StreamSubscription<bool>? _sub;
|
StreamSubscription<bool>? _sub;
|
||||||
|
|||||||
@@ -2,27 +2,25 @@ import 'dart:developer';
|
|||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:http_interceptor/http_interceptor.dart';
|
import 'package:http_interceptor/http_interceptor.dart';
|
||||||
import 'package:paperless_mobile/core/store/local_vault.dart';
|
|
||||||
|
|
||||||
class AuthenticationInterceptor implements InterceptorContract {
|
class AuthenticationInterceptor implements InterceptorContract {
|
||||||
final LocalVault _localVault;
|
String? serverUrl;
|
||||||
AuthenticationInterceptor(this._localVault);
|
String? token;
|
||||||
|
AuthenticationInterceptor({this.serverUrl, this.token});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<BaseRequest> interceptRequest({required BaseRequest request}) async {
|
Future<BaseRequest> interceptRequest({required BaseRequest request}) async {
|
||||||
final auth = await _localVault.loadAuthenticationInformation();
|
|
||||||
|
|
||||||
if (kDebugMode) {
|
if (kDebugMode) {
|
||||||
log("Intercepted ${request.method} request to ${request.url.toString()}");
|
log("Intercepted ${request.method} request to ${request.url.toString()}");
|
||||||
}
|
}
|
||||||
|
|
||||||
return request.copyWith(
|
return request.copyWith(
|
||||||
//Append server Url
|
url: Uri.parse((serverUrl ?? '') + request.url.toString()),
|
||||||
headers: auth?.token?.isEmpty ?? true
|
headers: token?.isEmpty ?? true
|
||||||
? request.headers
|
? request.headers
|
||||||
: {
|
: {
|
||||||
...request.headers,
|
...request.headers,
|
||||||
'Authorization': 'Token ${auth!.token}',
|
'Authorization': 'Token $token',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
38
lib/core/interceptor/dio_http_error_interceptor.dart
Normal file
38
lib/core/interceptor/dio_http_error_interceptor.dart
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:dio/dio.dart';
|
||||||
|
import 'package:paperless_mobile/core/type/types.dart';
|
||||||
|
|
||||||
|
class DioHttpErrorInterceptor implements InterceptorsWrapper {
|
||||||
|
@override
|
||||||
|
void onError(DioError e, ErrorInterceptorHandler handler) {
|
||||||
|
//TODO: Implement and debug how error handling works, or if request has to be resolved.
|
||||||
|
if (e.response?.statusCode == 400) {
|
||||||
|
// try to parse contained error message, otherwise return response
|
||||||
|
final Map<String, dynamic> json = jsonDecode(e.response?.data);
|
||||||
|
final PaperlessValidationErrors errorMessages = {};
|
||||||
|
for (final entry in json.entries) {
|
||||||
|
if (entry.value is List) {
|
||||||
|
errorMessages.putIfAbsent(
|
||||||
|
entry.key, () => (entry.value as List).cast<String>().first);
|
||||||
|
} else if (entry.value is String) {
|
||||||
|
errorMessages.putIfAbsent(entry.key, () => entry.value);
|
||||||
|
} else {
|
||||||
|
errorMessages.putIfAbsent(entry.key, () => entry.value.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw errorMessages;
|
||||||
|
}
|
||||||
|
handler.next(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
|
||||||
|
handler.next(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onResponse(Response response, ResponseInterceptorHandler handler) {
|
||||||
|
handler.next(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,20 +12,16 @@ class LabelRepositoriesProvider extends StatelessWidget {
|
|||||||
return MultiRepositoryProvider(
|
return MultiRepositoryProvider(
|
||||||
providers: [
|
providers: [
|
||||||
RepositoryProvider(
|
RepositoryProvider(
|
||||||
create: (context) =>
|
create: (context) => context.read<LabelRepository<Correspondent>>(),
|
||||||
RepositoryProvider.of<LabelRepository<Correspondent>>(context),
|
|
||||||
),
|
),
|
||||||
RepositoryProvider(
|
RepositoryProvider(
|
||||||
create: (context) =>
|
create: (context) => context.read<LabelRepository<DocumentType>>(),
|
||||||
RepositoryProvider.of<LabelRepository<DocumentType>>(context),
|
|
||||||
),
|
),
|
||||||
RepositoryProvider(
|
RepositoryProvider(
|
||||||
create: (context) =>
|
create: (context) => context.read<LabelRepository<StoragePath>>(),
|
||||||
RepositoryProvider.of<LabelRepository<StoragePath>>(context),
|
|
||||||
),
|
),
|
||||||
RepositoryProvider(
|
RepositoryProvider(
|
||||||
create: (context) =>
|
create: (context) => context.read<LabelRepository<Tag>>(),
|
||||||
RepositoryProvider.of<LabelRepository<Tag>>(context),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
child: child,
|
child: child,
|
||||||
|
|||||||
60
lib/core/security/authentication_aware_dio_manager.dart
Normal file
60
lib/core/security/authentication_aware_dio_manager.dart
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:dio/adapter.dart';
|
||||||
|
import 'package:dio/dio.dart';
|
||||||
|
import 'package:paperless_mobile/core/interceptor/dio_http_error_interceptor.dart';
|
||||||
|
import 'package:paperless_mobile/extensions/security_context_extension.dart';
|
||||||
|
import 'package:paperless_mobile/features/login/model/client_certificate.dart';
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Convenience http client handling timeouts.
|
||||||
|
///
|
||||||
|
class AuthenticationAwareDioManager {
|
||||||
|
final Dio _dio;
|
||||||
|
|
||||||
|
/// Some dependencies require an [HttpClient], therefore this is also maintained here.
|
||||||
|
|
||||||
|
AuthenticationAwareDioManager() : _dio = _initDio();
|
||||||
|
|
||||||
|
Dio get client => _dio;
|
||||||
|
|
||||||
|
Stream<SecurityContext> get securityContextChanges =>
|
||||||
|
_securityContextStreamController.stream.asBroadcastStream();
|
||||||
|
|
||||||
|
final StreamController<SecurityContext> _securityContextStreamController =
|
||||||
|
StreamController.broadcast();
|
||||||
|
|
||||||
|
static Dio _initDio() {
|
||||||
|
//en- and decoded by utf8 by default
|
||||||
|
final Dio dio = Dio(BaseOptions());
|
||||||
|
dio.options.receiveTimeout = const Duration(seconds: 25).inMilliseconds;
|
||||||
|
dio.options.responseType = ResponseType.json;
|
||||||
|
(dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
|
||||||
|
(client) => client..badCertificateCallback = (cert, host, port) => true;
|
||||||
|
dio.interceptors.add(DioHttpErrorInterceptor());
|
||||||
|
return dio;
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateSettings({
|
||||||
|
String? baseUrl,
|
||||||
|
String? authToken,
|
||||||
|
ClientCertificate? clientCertificate,
|
||||||
|
}) {
|
||||||
|
if (clientCertificate != null) {
|
||||||
|
final context =
|
||||||
|
SecurityContext().withClientCertificate(clientCertificate);
|
||||||
|
(_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
|
||||||
|
(client) => HttpClient(context: context)
|
||||||
|
..badCertificateCallback =
|
||||||
|
(X509Certificate cert, String host, int port) => true;
|
||||||
|
_securityContextStreamController.add(context);
|
||||||
|
}
|
||||||
|
if (baseUrl != null) {
|
||||||
|
_dio.options.baseUrl = baseUrl;
|
||||||
|
}
|
||||||
|
if (authToken != null) {
|
||||||
|
_dio.options.headers.addAll({'Authorization': 'Token $authToken'});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
import 'dart:async';
|
|
||||||
import 'dart:convert';
|
|
||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:dio/adapter.dart';
|
|
||||||
import 'package:dio/dio.dart';
|
|
||||||
import 'package:paperless_mobile/core/type/types.dart';
|
|
||||||
import 'package:paperless_mobile/features/login/model/client_certificate.dart';
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Convenience http client handling timeouts.
|
|
||||||
///
|
|
||||||
class SecurityContextAwareDioManager {
|
|
||||||
final Dio _dio;
|
|
||||||
// Some dependencies require an [HttpClient], therefore this is also maintained here.
|
|
||||||
final HttpClient _httpClient;
|
|
||||||
SecurityContextAwareDioManager()
|
|
||||||
: _dio = _initDio(),
|
|
||||||
_httpClient = HttpClient();
|
|
||||||
|
|
||||||
Dio get client => _dio;
|
|
||||||
|
|
||||||
Stream<SecurityContext> get securityContextChanges =>
|
|
||||||
_securityContextStreamController.stream.asBroadcastStream();
|
|
||||||
|
|
||||||
final StreamController<SecurityContext> _securityContextStreamController =
|
|
||||||
StreamController.broadcast();
|
|
||||||
|
|
||||||
static Dio _initDio() {
|
|
||||||
//en- and decoded by utf8 by default
|
|
||||||
final Dio dio = Dio(BaseOptions());
|
|
||||||
dio.options.receiveTimeout = const Duration(seconds: 25).inMilliseconds;
|
|
||||||
dio.options.responseType = ResponseType.json;
|
|
||||||
(dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
|
|
||||||
(client) => client
|
|
||||||
..badCertificateCallback =
|
|
||||||
(X509Certificate cert, String host, int port) => true;
|
|
||||||
dio.interceptors.add(
|
|
||||||
//TODO: Refactor, create own class...
|
|
||||||
InterceptorsWrapper(
|
|
||||||
onError: (e, handler) {
|
|
||||||
//TODO: Implement and debug how error handling works, or if request has to be resolved.
|
|
||||||
if (e.response?.statusCode == 400) {
|
|
||||||
// try to parse contained error message, otherwise return response
|
|
||||||
final JSON json = jsonDecode(e.response?.data);
|
|
||||||
final PaperlessValidationErrors errorMessages = {};
|
|
||||||
for (final entry in json.entries) {
|
|
||||||
if (entry.value is List) {
|
|
||||||
errorMessages.putIfAbsent(entry.key,
|
|
||||||
() => (entry.value as List).cast<String>().first);
|
|
||||||
} else if (entry.value is String) {
|
|
||||||
errorMessages.putIfAbsent(entry.key, () => entry.value);
|
|
||||||
} else {
|
|
||||||
errorMessages.putIfAbsent(
|
|
||||||
entry.key, () => entry.value.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw errorMessages;
|
|
||||||
}
|
|
||||||
handler.next(e);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
return dio;
|
|
||||||
}
|
|
||||||
|
|
||||||
void updateSettings({
|
|
||||||
String? baseUrl,
|
|
||||||
String? authToken,
|
|
||||||
ClientCertificate? clientCertificate,
|
|
||||||
}) {
|
|
||||||
if (clientCertificate != null) {
|
|
||||||
final sc = SecurityContext()
|
|
||||||
..usePrivateKeyBytes(
|
|
||||||
clientCertificate.bytes,
|
|
||||||
password: clientCertificate.passphrase,
|
|
||||||
)
|
|
||||||
..useCertificateChainBytes(
|
|
||||||
clientCertificate.bytes,
|
|
||||||
password: clientCertificate.passphrase,
|
|
||||||
)
|
|
||||||
..setTrustedCertificatesBytes(
|
|
||||||
clientCertificate.bytes,
|
|
||||||
password: clientCertificate.passphrase,
|
|
||||||
);
|
|
||||||
(_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
|
|
||||||
(client) => HttpClient(
|
|
||||||
context: sc,
|
|
||||||
)..badCertificateCallback =
|
|
||||||
(X509Certificate cert, String host, int port) => true;
|
|
||||||
_securityContextStreamController.add(sc);
|
|
||||||
}
|
|
||||||
if (baseUrl != null) {
|
|
||||||
_dio.options.baseUrl = baseUrl;
|
|
||||||
}
|
|
||||||
if (authToken != null) {
|
|
||||||
_dio.options.headers.addAll({'Authorization': 'Token $authToken'});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
22
lib/extensions/security_context_extension.dart
Normal file
22
lib/extensions/security_context_extension.dart
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:paperless_mobile/features/login/model/client_certificate.dart';
|
||||||
|
|
||||||
|
extension ClientCertificateHandlingSecurityContext on SecurityContext {
|
||||||
|
SecurityContext withClientCertificate(ClientCertificate? clientCertificate) {
|
||||||
|
if (clientCertificate == null) return this;
|
||||||
|
return this
|
||||||
|
..usePrivateKeyBytes(
|
||||||
|
clientCertificate.bytes,
|
||||||
|
password: clientCertificate.passphrase,
|
||||||
|
)
|
||||||
|
..useCertificateChainBytes(
|
||||||
|
clientCertificate.bytes,
|
||||||
|
password: clientCertificate.passphrase,
|
||||||
|
)
|
||||||
|
..setTrustedCertificatesBytes(
|
||||||
|
clientCertificate.bytes,
|
||||||
|
password: clientCertificate.passphrase,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -187,14 +187,14 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
|
|||||||
Navigator.push<bool>(
|
Navigator.push<bool>(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => BlocProvider(
|
builder: (context) => BlocProvider.value(
|
||||||
create: (context) => EditDocumentCubit(
|
value: EditDocumentCubit(
|
||||||
document,
|
document,
|
||||||
documentsApi: context.watch(),
|
documentsApi: context.read(),
|
||||||
correspondentRepository: context.watch(),
|
correspondentRepository: context.read(),
|
||||||
documentTypeRepository: context.watch(),
|
documentTypeRepository: context.read(),
|
||||||
storagePathRepository: context.watch(),
|
storagePathRepository: context.read(),
|
||||||
tagRepository: context.watch(),
|
tagRepository: context.read(),
|
||||||
),
|
),
|
||||||
child: BlocListener<EditDocumentCubit, EditDocumentState>(
|
child: BlocListener<EditDocumentCubit, EditDocumentState>(
|
||||||
listenWhen: (previous, current) =>
|
listenWhen: (previous, current) =>
|
||||||
|
|||||||
@@ -166,8 +166,9 @@ class _DocumentUploadPreparationPageState
|
|||||||
notAssignedSelectable: false,
|
notAssignedSelectable: false,
|
||||||
formBuilderState: _formKey.currentState,
|
formBuilderState: _formKey.currentState,
|
||||||
labelCreationWidgetBuilder: (initialName) =>
|
labelCreationWidgetBuilder: (initialName) =>
|
||||||
RepositoryProvider<LabelRepository<DocumentType>>(
|
RepositoryProvider(
|
||||||
create: (context) => context.watch(),
|
create: (context) =>
|
||||||
|
context.read<LabelRepository<DocumentType>>(),
|
||||||
child: AddDocumentTypePage(initialName: initialName),
|
child: AddDocumentTypePage(initialName: initialName),
|
||||||
),
|
),
|
||||||
textFieldLabel:
|
textFieldLabel:
|
||||||
@@ -180,8 +181,9 @@ class _DocumentUploadPreparationPageState
|
|||||||
notAssignedSelectable: false,
|
notAssignedSelectable: false,
|
||||||
formBuilderState: _formKey.currentState,
|
formBuilderState: _formKey.currentState,
|
||||||
labelCreationWidgetBuilder: (initialName) =>
|
labelCreationWidgetBuilder: (initialName) =>
|
||||||
RepositoryProvider<LabelRepository<Correspondent>>(
|
RepositoryProvider(
|
||||||
create: (context) => context.watch(),
|
create: (context) =>
|
||||||
|
context.read<LabelRepository<Correspondent>>(),
|
||||||
child: AddCorrespondentPage(initialName: initialName),
|
child: AddCorrespondentPage(initialName: initialName),
|
||||||
),
|
),
|
||||||
textFieldLabel:
|
textFieldLabel:
|
||||||
|
|||||||
@@ -99,9 +99,8 @@ class _DocumentEditPageState extends State<DocumentEditPage> {
|
|||||||
return LabelFormField<StoragePath>(
|
return LabelFormField<StoragePath>(
|
||||||
notAssignedSelectable: false,
|
notAssignedSelectable: false,
|
||||||
formBuilderState: _formKey.currentState,
|
formBuilderState: _formKey.currentState,
|
||||||
labelCreationWidgetBuilder: (initialValue) =>
|
labelCreationWidgetBuilder: (initialValue) => RepositoryProvider(
|
||||||
RepositoryProvider<LabelRepository<StoragePath>>(
|
create: (context) => context.read<LabelRepository<StoragePath>>(),
|
||||||
create: (context) => context.watch(),
|
|
||||||
child: AddStoragePathPage(initalValue: initialValue),
|
child: AddStoragePathPage(initalValue: initialValue),
|
||||||
),
|
),
|
||||||
textFieldLabel: S.of(context).documentStoragePathPropertyLabel,
|
textFieldLabel: S.of(context).documentStoragePathPropertyLabel,
|
||||||
@@ -117,9 +116,8 @@ class _DocumentEditPageState extends State<DocumentEditPage> {
|
|||||||
return LabelFormField<Correspondent>(
|
return LabelFormField<Correspondent>(
|
||||||
notAssignedSelectable: false,
|
notAssignedSelectable: false,
|
||||||
formBuilderState: _formKey.currentState,
|
formBuilderState: _formKey.currentState,
|
||||||
labelCreationWidgetBuilder: (initialValue) =>
|
labelCreationWidgetBuilder: (initialValue) => RepositoryProvider(
|
||||||
RepositoryProvider<LabelRepository<Correspondent>>(
|
create: (context) => context.read<LabelRepository<Correspondent>>(),
|
||||||
create: context.watch(),
|
|
||||||
child: AddCorrespondentPage(initialName: initialValue),
|
child: AddCorrespondentPage(initialName: initialValue),
|
||||||
),
|
),
|
||||||
textFieldLabel: S.of(context).documentCorrespondentPropertyLabel,
|
textFieldLabel: S.of(context).documentCorrespondentPropertyLabel,
|
||||||
@@ -135,9 +133,8 @@ class _DocumentEditPageState extends State<DocumentEditPage> {
|
|||||||
return LabelFormField<DocumentType>(
|
return LabelFormField<DocumentType>(
|
||||||
notAssignedSelectable: false,
|
notAssignedSelectable: false,
|
||||||
formBuilderState: _formKey.currentState,
|
formBuilderState: _formKey.currentState,
|
||||||
labelCreationWidgetBuilder: (currentInput) =>
|
labelCreationWidgetBuilder: (currentInput) => RepositoryProvider(
|
||||||
RepositoryProvider<LabelRepository<DocumentType>>(
|
create: (context) => context.read<LabelRepository<DocumentType>>(),
|
||||||
create: (context) => context.watch(),
|
|
||||||
child: AddDocumentTypePage(
|
child: AddDocumentTypePage(
|
||||||
initialName: currentInput,
|
initialName: currentInput,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -32,9 +32,6 @@ class DocumentsPage extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _DocumentsPageState extends State<DocumentsPage> {
|
class _DocumentsPageState extends State<DocumentsPage> {
|
||||||
late final DocumentsCubit _documentsCubit;
|
|
||||||
late final SavedViewCubit _savedViewCubit;
|
|
||||||
|
|
||||||
final _pagingController = PagingController<int, DocumentModel>(
|
final _pagingController = PagingController<int, DocumentModel>(
|
||||||
firstPageKey: 1,
|
firstPageKey: 1,
|
||||||
);
|
);
|
||||||
@@ -42,10 +39,8 @@ class _DocumentsPageState extends State<DocumentsPage> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_documentsCubit = context.watch();
|
|
||||||
_savedViewCubit = context.watch();
|
|
||||||
try {
|
try {
|
||||||
_documentsCubit.load();
|
context.read<DocumentsCubit>().load();
|
||||||
} on PaperlessServerException catch (error, stackTrace) {
|
} on PaperlessServerException catch (error, stackTrace) {
|
||||||
showErrorMessage(context, error, stackTrace);
|
showErrorMessage(context, error, stackTrace);
|
||||||
}
|
}
|
||||||
@@ -66,7 +61,7 @@ class _DocumentsPageState extends State<DocumentsPage> {
|
|||||||
current == ConnectivityState.connected,
|
current == ConnectivityState.connected,
|
||||||
listener: (context, state) {
|
listener: (context, state) {
|
||||||
try {
|
try {
|
||||||
_documentsCubit.load();
|
context.read<DocumentsCubit>().load();
|
||||||
} on PaperlessServerException catch (error, stackTrace) {
|
} on PaperlessServerException catch (error, stackTrace) {
|
||||||
showErrorMessage(context, error, stackTrace);
|
showErrorMessage(context, error, stackTrace);
|
||||||
}
|
}
|
||||||
@@ -74,9 +69,9 @@ class _DocumentsPageState extends State<DocumentsPage> {
|
|||||||
builder: (context, connectivityState) {
|
builder: (context, connectivityState) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
drawer: BlocProvider.value(
|
drawer: BlocProvider.value(
|
||||||
value: BlocProvider.of<AuthenticationCubit>(context),
|
value: context.read<AuthenticationCubit>(),
|
||||||
child: InfoDrawer(
|
child: InfoDrawer(
|
||||||
afterInboxClosed: () => _documentsCubit.reload(),
|
afterInboxClosed: () => context.read<DocumentsCubit>().reload(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
floatingActionButton: BlocBuilder<DocumentsCubit, DocumentsState>(
|
floatingActionButton: BlocBuilder<DocumentsCubit, DocumentsState>(
|
||||||
@@ -111,22 +106,25 @@ class _DocumentsPageState extends State<DocumentsPage> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
isScrollControlled: true,
|
isScrollControlled: true,
|
||||||
builder: (context) => DraggableScrollableSheet(
|
builder: (_) => BlocProvider.value(
|
||||||
|
value: context.read<DocumentsCubit>(),
|
||||||
|
child: DraggableScrollableSheet(
|
||||||
expand: false,
|
expand: false,
|
||||||
snap: true,
|
snap: true,
|
||||||
initialChildSize: .9,
|
initialChildSize: .9,
|
||||||
maxChildSize: .9,
|
maxChildSize: .9,
|
||||||
builder: (context, controller) => LabelsBlocProvider(
|
builder: (context, controller) => LabelsBlocProvider(
|
||||||
child: DocumentFilterPanel(
|
child: DocumentFilterPanel(
|
||||||
initialFilter: _documentsCubit.state.filter,
|
initialFilter: context.read<DocumentsCubit>().state.filter,
|
||||||
scrollController: controller,
|
scrollController: controller,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
if (filter != null) {
|
if (filter != null) {
|
||||||
_documentsCubit.updateFilter(filter: filter);
|
context.read<DocumentsCubit>().updateFilter(filter: filter);
|
||||||
_savedViewCubit.resetSelection();
|
context.read<SavedViewCubit>().resetSelection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,8 +175,8 @@ class _DocumentsPageState extends State<DocumentsPage> {
|
|||||||
child: DocumentsEmptyState(
|
child: DocumentsEmptyState(
|
||||||
state: state,
|
state: state,
|
||||||
onReset: () {
|
onReset: () {
|
||||||
_documentsCubit.resetFilter();
|
context.read<DocumentsCubit>().resetFilter();
|
||||||
_savedViewCubit.resetSelection();
|
context.read<SavedViewCubit>().resetSelection();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -196,13 +194,15 @@ class _DocumentsPageState extends State<DocumentsPage> {
|
|||||||
listener: (context, state) {
|
listener: (context, state) {
|
||||||
try {
|
try {
|
||||||
if (state.selectedSavedViewId == null) {
|
if (state.selectedSavedViewId == null) {
|
||||||
_documentsCubit.resetFilter();
|
context.read<DocumentsCubit>().resetFilter();
|
||||||
} else {
|
} else {
|
||||||
final newFilter = state
|
final newFilter = state
|
||||||
.value[state.selectedSavedViewId]
|
.value[state.selectedSavedViewId]
|
||||||
?.toDocumentFilter();
|
?.toDocumentFilter();
|
||||||
if (newFilter != null) {
|
if (newFilter != null) {
|
||||||
_documentsCubit.updateFilter(filter: newFilter);
|
context
|
||||||
|
.read<DocumentsCubit>()
|
||||||
|
.updateFilter(filter: newFilter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} on PaperlessServerException catch (error, stackTrace) {
|
} on PaperlessServerException catch (error, stackTrace) {
|
||||||
@@ -220,8 +220,8 @@ class _DocumentsPageState extends State<DocumentsPage> {
|
|||||||
? Icons.list
|
? Icons.list
|
||||||
: Icons.grid_view,
|
: Icons.grid_view,
|
||||||
),
|
),
|
||||||
onPressed: () =>
|
onPressed: () => context
|
||||||
BlocProvider.of<ApplicationSettingsCubit>(context)
|
.read<ApplicationSettingsCubit>()
|
||||||
.setViewType(
|
.setViewType(
|
||||||
settings.preferredViewType.toggle(),
|
settings.preferredViewType.toggle(),
|
||||||
),
|
),
|
||||||
@@ -243,7 +243,7 @@ class _DocumentsPageState extends State<DocumentsPage> {
|
|||||||
await Navigator.of(context).push<DocumentModel?>(
|
await Navigator.of(context).push<DocumentModel?>(
|
||||||
_buildDetailsPageRoute(document),
|
_buildDetailsPageRoute(document),
|
||||||
);
|
);
|
||||||
_documentsCubit.reload();
|
context.read<DocumentsCubit>().reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialPageRoute<DocumentModel?> _buildDetailsPageRoute(
|
MaterialPageRoute<DocumentModel?> _buildDetailsPageRoute(
|
||||||
@@ -251,7 +251,7 @@ class _DocumentsPageState extends State<DocumentsPage> {
|
|||||||
return MaterialPageRoute(
|
return MaterialPageRoute(
|
||||||
builder: (_) => BlocProvider(
|
builder: (_) => BlocProvider(
|
||||||
create: (context) => DocumentDetailsCubit(
|
create: (context) => DocumentDetailsCubit(
|
||||||
context.watch(),
|
context.read<PaperlessDocumentsApi>(),
|
||||||
document,
|
document,
|
||||||
),
|
),
|
||||||
child: const LabelRepositoriesProvider(
|
child: const LabelRepositoriesProvider(
|
||||||
@@ -263,17 +263,18 @@ class _DocumentsPageState extends State<DocumentsPage> {
|
|||||||
|
|
||||||
void _addTagToFilter(int tagId) {
|
void _addTagToFilter(int tagId) {
|
||||||
try {
|
try {
|
||||||
final tagsQuery = _documentsCubit.state.filter.tags is IdsTagsQuery
|
final tagsQuery =
|
||||||
? _documentsCubit.state.filter.tags as IdsTagsQuery
|
context.read<DocumentsCubit>().state.filter.tags is IdsTagsQuery
|
||||||
|
? context.read<DocumentsCubit>().state.filter.tags as IdsTagsQuery
|
||||||
: const IdsTagsQuery();
|
: const IdsTagsQuery();
|
||||||
if (tagsQuery.includedIds.contains(tagId)) {
|
if (tagsQuery.includedIds.contains(tagId)) {
|
||||||
_documentsCubit.updateCurrentFilter(
|
context.read<DocumentsCubit>().updateCurrentFilter(
|
||||||
(filter) => filter.copyWith(
|
(filter) => filter.copyWith(
|
||||||
tags: tagsQuery.withIdsRemoved([tagId]),
|
tags: tagsQuery.withIdsRemoved([tagId]),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
_documentsCubit.updateCurrentFilter(
|
context.read<DocumentsCubit>().updateCurrentFilter(
|
||||||
(filter) => filter.copyWith(
|
(filter) => filter.copyWith(
|
||||||
tags: tagsQuery.withIdQueriesAdded([IncludeTagIdQuery(tagId)]),
|
tags: tagsQuery.withIdQueriesAdded([IncludeTagIdQuery(tagId)]),
|
||||||
),
|
),
|
||||||
@@ -285,7 +286,7 @@ class _DocumentsPageState extends State<DocumentsPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _addCorrespondentToFilter(int? correspondentId) {
|
void _addCorrespondentToFilter(int? correspondentId) {
|
||||||
final cubit = BlocProvider.of<DocumentsCubit>(context);
|
final cubit = context.read<DocumentsCubit>();
|
||||||
try {
|
try {
|
||||||
if (cubit.state.filter.correspondent.id == correspondentId) {
|
if (cubit.state.filter.correspondent.id == correspondentId) {
|
||||||
cubit.updateCurrentFilter(
|
cubit.updateCurrentFilter(
|
||||||
@@ -304,7 +305,7 @@ class _DocumentsPageState extends State<DocumentsPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _addDocumentTypeToFilter(int? documentTypeId) {
|
void _addDocumentTypeToFilter(int? documentTypeId) {
|
||||||
final cubit = BlocProvider.of<DocumentsCubit>(context);
|
final cubit = context.read<DocumentsCubit>();
|
||||||
try {
|
try {
|
||||||
if (cubit.state.filter.documentType.id == documentTypeId) {
|
if (cubit.state.filter.documentType.id == documentTypeId) {
|
||||||
cubit.updateCurrentFilter(
|
cubit.updateCurrentFilter(
|
||||||
@@ -323,7 +324,7 @@ class _DocumentsPageState extends State<DocumentsPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _addStoragePathToFilter(int? pathId) {
|
void _addStoragePathToFilter(int? pathId) {
|
||||||
final cubit = BlocProvider.of<DocumentsCubit>(context);
|
final cubit = context.read<DocumentsCubit>();
|
||||||
try {
|
try {
|
||||||
if (cubit.state.filter.correspondent.id == pathId) {
|
if (cubit.state.filter.correspondent.id == pathId) {
|
||||||
cubit.updateCurrentFilter(
|
cubit.updateCurrentFilter(
|
||||||
@@ -342,28 +343,29 @@ class _DocumentsPageState extends State<DocumentsPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _loadNewPage(int pageKey) async {
|
Future<void> _loadNewPage(int pageKey) async {
|
||||||
final pageCount = _documentsCubit.state
|
final documentsCubit = context.read<DocumentsCubit>();
|
||||||
.inferPageCount(pageSize: _documentsCubit.state.filter.pageSize);
|
final pageCount = documentsCubit.state
|
||||||
|
.inferPageCount(pageSize: documentsCubit.state.filter.pageSize);
|
||||||
if (pageCount <= pageKey + 1) {
|
if (pageCount <= pageKey + 1) {
|
||||||
_pagingController.nextPageKey = null;
|
_pagingController.nextPageKey = null;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
await _documentsCubit.loadMore();
|
await documentsCubit.loadMore();
|
||||||
} on PaperlessServerException catch (error, stackTrace) {
|
} on PaperlessServerException catch (error, stackTrace) {
|
||||||
showErrorMessage(context, error, stackTrace);
|
showErrorMessage(context, error, stackTrace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onSelected(DocumentModel model) {
|
void _onSelected(DocumentModel model) {
|
||||||
_documentsCubit.toggleDocumentSelection(model);
|
context.read<DocumentsCubit>().toggleDocumentSelection(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onRefresh() async {
|
Future<void> _onRefresh() async {
|
||||||
try {
|
try {
|
||||||
_documentsCubit.updateCurrentFilter(
|
context.read<DocumentsCubit>().updateCurrentFilter(
|
||||||
(filter) => filter.copyWith(page: 1),
|
(filter) => filter.copyWith(page: 1),
|
||||||
);
|
);
|
||||||
_savedViewCubit.reload();
|
context.read<SavedViewCubit>().reload();
|
||||||
} on PaperlessServerException catch (error, stackTrace) {
|
} on PaperlessServerException catch (error, stackTrace) {
|
||||||
showErrorMessage(context, error, stackTrace);
|
showErrorMessage(context, error, stackTrace);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,15 +30,14 @@ class DocumentPreview extends StatelessWidget {
|
|||||||
fit: fit,
|
fit: fit,
|
||||||
alignment: Alignment.topCenter,
|
alignment: Alignment.topCenter,
|
||||||
cacheKey: "thumb_$id",
|
cacheKey: "thumb_$id",
|
||||||
imageUrl:
|
imageUrl: context.read<PaperlessDocumentsApi>().getThumbnailUrl(id),
|
||||||
Provider.of<PaperlessDocumentsApi>(context).getThumbnailUrl(id),
|
|
||||||
errorWidget: (ctxt, msg, __) => Text(msg),
|
errorWidget: (ctxt, msg, __) => Text(msg),
|
||||||
placeholder: (context, value) => Shimmer.fromColors(
|
placeholder: (context, value) => Shimmer.fromColors(
|
||||||
baseColor: Colors.grey[300]!,
|
baseColor: Colors.grey[300]!,
|
||||||
highlightColor: Colors.grey[100]!,
|
highlightColor: Colors.grey[100]!,
|
||||||
child: const SizedBox(height: 100, width: 100),
|
child: const SizedBox(height: 100, width: 100),
|
||||||
),
|
),
|
||||||
cacheManager: context.watch(),
|
cacheManager: context.watch<CacheManager>(),
|
||||||
),
|
),
|
||||||
// ),
|
// ),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -48,8 +48,7 @@ class _DocumentsPageAppBarState extends State<DocumentsPageAppBar> {
|
|||||||
),
|
),
|
||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
icon: const Icon(Icons.close),
|
icon: const Icon(Icons.close),
|
||||||
onPressed: () =>
|
onPressed: () => context.read<DocumentsCubit>().resetSelection(),
|
||||||
BlocProvider.of<DocumentsCubit>(context).resetSelection(),
|
|
||||||
),
|
),
|
||||||
title: Text(
|
title: Text(
|
||||||
'${documentsState.selection.length} ${S.of(context).documentsSelectedText}'),
|
'${documentsState.selection.length} ${S.of(context).documentsSelectedText}'),
|
||||||
@@ -111,7 +110,8 @@ class _DocumentsPageAppBarState extends State<DocumentsPageAppBar> {
|
|||||||
false;
|
false;
|
||||||
if (shouldDelete) {
|
if (shouldDelete) {
|
||||||
try {
|
try {
|
||||||
await BlocProvider.of<DocumentsCubit>(context)
|
await context
|
||||||
|
.read<DocumentsCubit>()
|
||||||
.bulkRemove(documentsState.selection);
|
.bulkRemove(documentsState.selection);
|
||||||
showSnackBar(
|
showSnackBar(
|
||||||
context,
|
context,
|
||||||
|
|||||||
@@ -29,20 +29,19 @@ class SortDocumentsButton extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
builder: (_) => BlocProvider<DocumentsCubit>.value(
|
builder: (_) => BlocProvider<DocumentsCubit>.value(
|
||||||
value: BlocProvider.of<DocumentsCubit>(context),
|
value: context.read<DocumentsCubit>(),
|
||||||
child: FractionallySizedBox(
|
child: FractionallySizedBox(
|
||||||
heightFactor: .6,
|
heightFactor: .6,
|
||||||
child: MultiBlocProvider(
|
child: MultiBlocProvider(
|
||||||
providers: [
|
providers: [
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
create: (context) => LabelCubit<DocumentType>(
|
create: (context) => LabelCubit<DocumentType>(
|
||||||
RepositoryProvider.of<LabelRepository<DocumentType>>(context),
|
context.read<LabelRepository<DocumentType>>(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
create: (context) => LabelCubit<Correspondent>(
|
create: (context) => LabelCubit<Correspondent>(
|
||||||
RepositoryProvider.of<LabelRepository<Correspondent>>(
|
context.read<LabelRepository<Correspondent>>(),
|
||||||
context),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -52,8 +51,7 @@ class SortDocumentsButton extends StatelessWidget {
|
|||||||
initialSortField: state.filter.sortField,
|
initialSortField: state.filter.sortField,
|
||||||
initialSortOrder: state.filter.sortOrder,
|
initialSortOrder: state.filter.sortOrder,
|
||||||
onSubmit: (field, order) =>
|
onSubmit: (field, order) =>
|
||||||
BlocProvider.of<DocumentsCubit>(context)
|
context.read<DocumentsCubit>().updateCurrentFilter(
|
||||||
.updateCurrentFilter(
|
|
||||||
(filter) => filter.copyWith(
|
(filter) => filter.copyWith(
|
||||||
sortField: field,
|
sortField: field,
|
||||||
sortOrder: order,
|
sortOrder: order,
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ class AddLabelPage<T extends Label> extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) => EditLabelCubit(
|
create: (context) => EditLabelCubit(
|
||||||
RepositoryProvider.of<LabelRepository<T>>(context),
|
context.read<LabelRepository<T>>(),
|
||||||
),
|
),
|
||||||
child: AddLabelFormWidget(
|
child: AddLabelFormWidget(
|
||||||
pageTitle: pageTitle,
|
pageTitle: pageTitle,
|
||||||
@@ -62,7 +62,7 @@ class AddLabelFormWidget<T extends Label> extends StatelessWidget {
|
|||||||
submitButtonConfig: SubmitButtonConfig<T>(
|
submitButtonConfig: SubmitButtonConfig<T>(
|
||||||
icon: const Icon(Icons.add),
|
icon: const Icon(Icons.add),
|
||||||
label: Text(S.of(context).genericActionCreateLabel),
|
label: Text(S.of(context).genericActionCreateLabel),
|
||||||
onSubmit: BlocProvider.of<EditLabelCubit<T>>(context).create,
|
onSubmit: context.read<EditLabelCubit<T>>().create,
|
||||||
),
|
),
|
||||||
additionalFields: additionalFields,
|
additionalFields: additionalFields,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ class EditLabelPage<T extends Label> extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) => EditLabelCubit(
|
create: (context) => EditLabelCubit(
|
||||||
RepositoryProvider.of<LabelRepository<T>>(context),
|
context.read<LabelRepository<T>>(),
|
||||||
),
|
),
|
||||||
child: EditLabelForm(
|
child: EditLabelForm(
|
||||||
label: label,
|
label: label,
|
||||||
@@ -63,7 +63,7 @@ class EditLabelForm<T extends Label> extends StatelessWidget {
|
|||||||
submitButtonConfig: SubmitButtonConfig<T>(
|
submitButtonConfig: SubmitButtonConfig<T>(
|
||||||
icon: const Icon(Icons.update),
|
icon: const Icon(Icons.update),
|
||||||
label: Text(S.of(context).genericActionUpdateLabel),
|
label: Text(S.of(context).genericActionUpdateLabel),
|
||||||
onSubmit: BlocProvider.of<EditLabelCubit<T>>(context).update,
|
onSubmit: context.read<EditLabelCubit<T>>().update,
|
||||||
),
|
),
|
||||||
additionalFields: additionalFields,
|
additionalFields: additionalFields,
|
||||||
),
|
),
|
||||||
@@ -99,11 +99,11 @@ class EditLabelForm<T extends Label> extends StatelessWidget {
|
|||||||
) ??
|
) ??
|
||||||
false;
|
false;
|
||||||
if (shouldDelete) {
|
if (shouldDelete) {
|
||||||
BlocProvider.of<EditLabelCubit<T>>(context).delete(label);
|
context.read<EditLabelCubit<T>>().delete(label);
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
BlocProvider.of<EditLabelCubit<T>>(context).delete(label);
|
context.read<EditLabelCubit<T>>().delete(label);
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ class AddCorrespondentPage extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) => EditLabelCubit<Correspondent>(
|
create: (context) => EditLabelCubit<Correspondent>(
|
||||||
RepositoryProvider.of<LabelRepository<Correspondent>>(context),
|
context.read<LabelRepository<Correspondent>>(),
|
||||||
),
|
),
|
||||||
child: AddLabelPage<Correspondent>(
|
child: AddLabelPage<Correspondent>(
|
||||||
pageTitle: Text(S.of(context).addCorrespondentPageTitle),
|
pageTitle: Text(S.of(context).addCorrespondentPageTitle),
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ class AddDocumentTypePage extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) => EditLabelCubit<DocumentType>(
|
create: (context) => EditLabelCubit<DocumentType>(
|
||||||
RepositoryProvider.of<LabelRepository<DocumentType>>(context),
|
context.read<LabelRepository<DocumentType>>(),
|
||||||
),
|
),
|
||||||
child: AddLabelPage<DocumentType>(
|
child: AddLabelPage<DocumentType>(
|
||||||
pageTitle: Text(S.of(context).addDocumentTypePageTitle),
|
pageTitle: Text(S.of(context).addDocumentTypePageTitle),
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ class AddStoragePathPage extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) => EditLabelCubit<StoragePath>(
|
create: (context) => EditLabelCubit<StoragePath>(
|
||||||
RepositoryProvider.of<LabelRepository<StoragePath>>(context),
|
context.read<LabelRepository<StoragePath>>(),
|
||||||
),
|
),
|
||||||
child: AddLabelPage<StoragePath>(
|
child: AddLabelPage<StoragePath>(
|
||||||
pageTitle: Text(S.of(context).addStoragePathPageTitle),
|
pageTitle: Text(S.of(context).addStoragePathPageTitle),
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ class AddTagPage extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) => EditLabelCubit<Tag>(
|
create: (context) => EditLabelCubit<Tag>(
|
||||||
RepositoryProvider.of<LabelRepository<Tag>>(context),
|
context.read<LabelRepository<Tag>>(),
|
||||||
),
|
),
|
||||||
child: AddLabelPage<Tag>(
|
child: AddLabelPage<Tag>(
|
||||||
pageTitle: Text(S.of(context).addTagPageTitle),
|
pageTitle: Text(S.of(context).addTagPageTitle),
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ class EditCorrespondentPage extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) => EditLabelCubit<Correspondent>(
|
create: (context) => EditLabelCubit<Correspondent>(
|
||||||
RepositoryProvider.of<LabelRepository<Correspondent>>(context),
|
context.read<LabelRepository<Correspondent>>(),
|
||||||
),
|
),
|
||||||
child: EditLabelPage<Correspondent>(
|
child: EditLabelPage<Correspondent>(
|
||||||
label: correspondent,
|
label: correspondent,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class EditDocumentTypePage extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) => EditLabelCubit<DocumentType>(
|
create: (context) => EditLabelCubit<DocumentType>(
|
||||||
RepositoryProvider.of<LabelRepository<DocumentType>>(context),
|
context.read<LabelRepository<DocumentType>>(),
|
||||||
),
|
),
|
||||||
child: EditLabelPage<DocumentType>(
|
child: EditLabelPage<DocumentType>(
|
||||||
label: documentType,
|
label: documentType,
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ class EditStoragePathPage extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) => EditLabelCubit<StoragePath>(
|
create: (context) => EditLabelCubit<StoragePath>(
|
||||||
RepositoryProvider.of<LabelRepository<StoragePath>>(context),
|
context.read<LabelRepository<StoragePath>>(),
|
||||||
),
|
),
|
||||||
child: EditLabelPage<StoragePath>(
|
child: EditLabelPage<StoragePath>(
|
||||||
label: storagePath,
|
label: storagePath,
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ class EditTagPage extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) => EditLabelCubit<Tag>(
|
create: (context) => EditLabelCubit<Tag>(
|
||||||
RepositoryProvider.of<LabelRepository<Tag>>(context),
|
context.read<LabelRepository<Tag>>(),
|
||||||
),
|
),
|
||||||
child: EditLabelPage<Tag>(
|
child: EditLabelPage<Tag>(
|
||||||
label: tag,
|
label: tag,
|
||||||
|
|||||||
@@ -55,13 +55,14 @@ class _HomePageState extends State<HomePage> {
|
|||||||
body: [
|
body: [
|
||||||
MultiBlocProvider(
|
MultiBlocProvider(
|
||||||
providers: [
|
providers: [
|
||||||
BlocProvider.value(
|
BlocProvider(
|
||||||
value:
|
create: (context) => DocumentsCubit(
|
||||||
DocumentsCubit(Provider.of<PaperlessDocumentsApi>(context)),
|
context.read<PaperlessDocumentsApi>(),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
create: (context) => SavedViewCubit(
|
create: (context) => SavedViewCubit(
|
||||||
RepositoryProvider.of<SavedViewRepository>(context),
|
context.read<SavedViewRepository>(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -71,12 +72,7 @@ class _HomePageState extends State<HomePage> {
|
|||||||
value: _scannerCubit,
|
value: _scannerCubit,
|
||||||
child: const ScannerPage(),
|
child: const ScannerPage(),
|
||||||
),
|
),
|
||||||
BlocProvider(
|
const LabelsPage(),
|
||||||
create: (context) => DocumentsCubit(
|
|
||||||
Provider.of<PaperlessDocumentsApi>(context),
|
|
||||||
),
|
|
||||||
child: const LabelsPage(),
|
|
||||||
),
|
|
||||||
][_currentIndex],
|
][_currentIndex],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -155,9 +155,8 @@ class _InfoDrawerState extends State<InfoDrawer> {
|
|||||||
),
|
),
|
||||||
onTap: () => Navigator.of(context).push(
|
onTap: () => Navigator.of(context).push(
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => BlocProvider(
|
builder: (context) => BlocProvider.value(
|
||||||
create: (context) =>
|
value: context.read<ApplicationSettingsCubit>(),
|
||||||
Provider.of<ApplicationSettingsCubit>(context),
|
|
||||||
child: const SettingsPage(),
|
child: const SettingsPage(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -214,20 +213,14 @@ class _InfoDrawerState extends State<InfoDrawer> {
|
|||||||
title: Text(S.of(context).appDrawerLogoutLabel),
|
title: Text(S.of(context).appDrawerLogoutLabel),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
try {
|
try {
|
||||||
BlocProvider.of<AuthenticationCubit>(context).logout();
|
context.read<AuthenticationCubit>().logout();
|
||||||
Provider.of<LocalVault>(context).clear();
|
context.read<LocalVault>().clear();
|
||||||
BlocProvider.of<ApplicationSettingsCubit>(context).clear();
|
context.read<ApplicationSettingsCubit>().clear();
|
||||||
RepositoryProvider.of<LabelRepository<Tag>>(context)
|
context.read<LabelRepository<Tag>>().clear();
|
||||||
.clear();
|
context.read<LabelRepository<Correspondent>>().clear();
|
||||||
RepositoryProvider.of<LabelRepository<Correspondent>>(
|
context.read<LabelRepository<DocumentType>>().clear();
|
||||||
context)
|
context.read<LabelRepository<StoragePath>>().clear();
|
||||||
.clear();
|
context.read<SavedViewRepository>().clear();
|
||||||
RepositoryProvider.of<LabelRepository<DocumentType>>(
|
|
||||||
context)
|
|
||||||
.clear();
|
|
||||||
RepositoryProvider.of<LabelRepository<StoragePath>>(context)
|
|
||||||
.clear();
|
|
||||||
RepositoryProvider.of<SavedViewRepository>(context).clear();
|
|
||||||
} on PaperlessServerException catch (error, stackTrace) {
|
} on PaperlessServerException catch (error, stackTrace) {
|
||||||
showErrorMessage(context, error, stackTrace);
|
showErrorMessage(context, error, stackTrace);
|
||||||
}
|
}
|
||||||
@@ -246,8 +239,8 @@ class _InfoDrawerState extends State<InfoDrawer> {
|
|||||||
builder: (_) => LabelRepositoriesProvider(
|
builder: (_) => LabelRepositoriesProvider(
|
||||||
child: BlocProvider(
|
child: BlocProvider(
|
||||||
create: (context) => InboxCubit(
|
create: (context) => InboxCubit(
|
||||||
RepositoryProvider.of<LabelRepository<Tag>>(context),
|
context.read<LabelRepository<Tag>>(),
|
||||||
Provider.of<PaperlessDocumentsApi>(context),
|
context.read<PaperlessDocumentsApi>(),
|
||||||
)..loadInbox(),
|
)..loadInbox(),
|
||||||
child: const InboxPage(),
|
child: const InboxPage(),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ class _InboxPageState extends State<InboxPage> {
|
|||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
return RefreshIndicator(
|
return RefreshIndicator(
|
||||||
onRefresh: () => BlocProvider.of<InboxCubit>(context).loadInbox(),
|
onRefresh: () => context.read<InboxCubit>().loadInbox(),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
@@ -205,14 +205,13 @@ class _InboxPageState extends State<InboxPage> {
|
|||||||
) ??
|
) ??
|
||||||
false;
|
false;
|
||||||
if (isActionConfirmed) {
|
if (isActionConfirmed) {
|
||||||
await BlocProvider.of<InboxCubit>(context).clearInbox();
|
await context.read<InboxCubit>().clearInbox();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> _onItemDismissed(DocumentModel doc) async {
|
Future<bool> _onItemDismissed(DocumentModel doc) async {
|
||||||
try {
|
try {
|
||||||
final removedTags =
|
final removedTags = await context.read<InboxCubit>().remove(doc);
|
||||||
await BlocProvider.of<InboxCubit>(context).remove(doc);
|
|
||||||
showSnackBar(
|
showSnackBar(
|
||||||
context,
|
context,
|
||||||
S.of(context).inboxPageDocumentRemovedMessageText,
|
S.of(context).inboxPageDocumentRemovedMessageText,
|
||||||
@@ -239,8 +238,7 @@ class _InboxPageState extends State<InboxPage> {
|
|||||||
Iterable<int> removedTags,
|
Iterable<int> removedTags,
|
||||||
) async {
|
) async {
|
||||||
try {
|
try {
|
||||||
await BlocProvider.of<InboxCubit>(context)
|
await context.read<InboxCubit>().undoRemove(document, removedTags);
|
||||||
.undoRemove(document, removedTags);
|
|
||||||
} on PaperlessServerException catch (error, stackTrace) {
|
} on PaperlessServerException catch (error, stackTrace) {
|
||||||
showErrorMessage(context, error, stackTrace);
|
showErrorMessage(context, error, stackTrace);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ class InboxEmptyWidget extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return RefreshIndicator(
|
return RefreshIndicator(
|
||||||
key: _emptyStateRefreshIndicatorKey,
|
key: _emptyStateRefreshIndicatorKey,
|
||||||
onRefresh: () => BlocProvider.of<InboxCubit>(context).loadInbox(),
|
onRefresh: () => context.read<InboxCubit>().loadInbox(),
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.max,
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
|||||||
@@ -48,9 +48,9 @@ class InboxItem extends StatelessWidget {
|
|||||||
onTap: () => Navigator.push(
|
onTap: () => Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (_) => BlocProvider(
|
builder: (context) => BlocProvider(
|
||||||
create: (context) => DocumentDetailsCubit(
|
create: (context) => DocumentDetailsCubit(
|
||||||
Provider.of<PaperlessDocumentsApi>(context),
|
context.read<PaperlessDocumentsApi>(),
|
||||||
document,
|
document,
|
||||||
),
|
),
|
||||||
child: const LabelRepositoriesProvider(
|
child: const LabelRepositoriesProvider(
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ class CorrespondentBlocProvider extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) => LabelCubit<Correspondent>(
|
create: (context) => LabelCubit<Correspondent>(
|
||||||
RepositoryProvider.of<LabelRepository<Correspondent>>(context),
|
context.read<LabelRepository<Correspondent>>(),
|
||||||
),
|
),
|
||||||
child: child,
|
child: child,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ class DocumentTypeBlocProvider extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) => LabelCubit<DocumentType>(
|
create: (context) => LabelCubit<DocumentType>(
|
||||||
RepositoryProvider.of<LabelRepository<DocumentType>>(context),
|
context.read<LabelRepository<DocumentType>>(),
|
||||||
),
|
),
|
||||||
child: child,
|
child: child,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -14,22 +14,22 @@ class LabelsBlocProvider extends StatelessWidget {
|
|||||||
providers: [
|
providers: [
|
||||||
BlocProvider<LabelCubit<StoragePath>>(
|
BlocProvider<LabelCubit<StoragePath>>(
|
||||||
create: (context) => LabelCubit<StoragePath>(
|
create: (context) => LabelCubit<StoragePath>(
|
||||||
RepositoryProvider.of<LabelRepository<StoragePath>>(context),
|
context.read<LabelRepository<StoragePath>>(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
BlocProvider<LabelCubit<Correspondent>>(
|
BlocProvider<LabelCubit<Correspondent>>(
|
||||||
create: (context) => LabelCubit<Correspondent>(
|
create: (context) => LabelCubit<Correspondent>(
|
||||||
RepositoryProvider.of<LabelRepository<Correspondent>>(context),
|
context.read<LabelRepository<Correspondent>>(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
BlocProvider<LabelCubit<DocumentType>>(
|
BlocProvider<LabelCubit<DocumentType>>(
|
||||||
create: (context) => LabelCubit<DocumentType>(
|
create: (context) => LabelCubit<DocumentType>(
|
||||||
RepositoryProvider.of<LabelRepository<DocumentType>>(context),
|
context.read<LabelRepository<DocumentType>>(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
BlocProvider<LabelCubit<Tag>>(
|
BlocProvider<LabelCubit<Tag>>(
|
||||||
create: (context) => LabelCubit<Tag>(
|
create: (context) => LabelCubit<Tag>(
|
||||||
RepositoryProvider.of<LabelRepository<Tag>>(context),
|
context.read<LabelRepository<Tag>>(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ class StoragePathBlocProvider extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) => LabelCubit<StoragePath>(
|
create: (context) => LabelCubit<StoragePath>(
|
||||||
RepositoryProvider.of<LabelRepository<StoragePath>>(context),
|
context.read<LabelRepository<StoragePath>>(),
|
||||||
),
|
),
|
||||||
child: child,
|
child: child,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ class TagBlocProvider extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) => LabelCubit<Tag>(
|
create: (context) => LabelCubit<Tag>(
|
||||||
RepositoryProvider.of<LabelRepository<Tag>>(context),
|
context.read<LabelRepository<Tag>>(),
|
||||||
),
|
),
|
||||||
child: child,
|
child: child,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import 'package:paperless_api/paperless_api.dart';
|
|||||||
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
||||||
import 'package:paperless_mobile/features/labels/bloc/label_cubit.dart';
|
import 'package:paperless_mobile/features/labels/bloc/label_cubit.dart';
|
||||||
import 'package:paperless_mobile/features/labels/bloc/label_state.dart';
|
import 'package:paperless_mobile/features/labels/bloc/label_state.dart';
|
||||||
|
import 'package:paperless_mobile/features/labels/bloc/providers/document_type_bloc_provider.dart';
|
||||||
|
|
||||||
class DocumentTypeWidget extends StatelessWidget {
|
class DocumentTypeWidget extends StatelessWidget {
|
||||||
final int? documentTypeId;
|
final int? documentTypeId;
|
||||||
@@ -20,10 +21,7 @@ class DocumentTypeWidget extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider(
|
return DocumentTypeBlocProvider(
|
||||||
create: (context) => LabelCubit<DocumentType>(
|
|
||||||
RepositoryProvider.of<LabelRepository<DocumentType>>(context),
|
|
||||||
),
|
|
||||||
child: AbsorbPointer(
|
child: AbsorbPointer(
|
||||||
absorbing: !isClickable,
|
absorbing: !isClickable,
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import 'package:paperless_api/paperless_api.dart';
|
|||||||
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
||||||
import 'package:paperless_mobile/features/labels/bloc/label_cubit.dart';
|
import 'package:paperless_mobile/features/labels/bloc/label_cubit.dart';
|
||||||
import 'package:paperless_mobile/features/labels/bloc/label_state.dart';
|
import 'package:paperless_mobile/features/labels/bloc/label_state.dart';
|
||||||
|
import 'package:paperless_mobile/features/labels/bloc/providers/storage_path_bloc_provider.dart';
|
||||||
|
|
||||||
class StoragePathWidget extends StatelessWidget {
|
class StoragePathWidget extends StatelessWidget {
|
||||||
final int? pathId;
|
final int? pathId;
|
||||||
@@ -21,10 +22,7 @@ class StoragePathWidget extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider(
|
return StoragePathBlocProvider(
|
||||||
create: (context) => LabelCubit<StoragePath>(
|
|
||||||
RepositoryProvider.of<LabelRepository<StoragePath>>(context),
|
|
||||||
),
|
|
||||||
child: AbsorbPointer(
|
child: AbsorbPointer(
|
||||||
absorbing: !isClickable,
|
absorbing: !isClickable,
|
||||||
child: BlocBuilder<LabelCubit<StoragePath>, LabelState<StoragePath>>(
|
child: BlocBuilder<LabelCubit<StoragePath>, LabelState<StoragePath>>(
|
||||||
|
|||||||
@@ -218,8 +218,8 @@ class _TagFormFieldState extends State<TagFormField> {
|
|||||||
void _onAddTag(BuildContext context, FormFieldState<TagsQuery> field) async {
|
void _onAddTag(BuildContext context, FormFieldState<TagsQuery> field) async {
|
||||||
final Tag? tag = await Navigator.of(context).push<Tag>(
|
final Tag? tag = await Navigator.of(context).push<Tag>(
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (_) => RepositoryProvider.value(
|
builder: (_) => RepositoryProvider(
|
||||||
value: RepositoryProvider.of<LabelRepository<Tag>>(context),
|
create: (context) => context.read<LabelRepository<Tag>>(),
|
||||||
child: AddTagPage(initialValue: _textEditingController.text),
|
child: AddTagPage(initialValue: _textEditingController.text),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -14,6 +14,10 @@ import 'package:paperless_mobile/features/edit_label/view/impl/edit_storage_path
|
|||||||
import 'package:paperless_mobile/features/edit_label/view/impl/edit_tag_page.dart';
|
import 'package:paperless_mobile/features/edit_label/view/impl/edit_tag_page.dart';
|
||||||
import 'package:paperless_mobile/features/home/view/widget/info_drawer.dart';
|
import 'package:paperless_mobile/features/home/view/widget/info_drawer.dart';
|
||||||
import 'package:paperless_mobile/features/labels/bloc/label_cubit.dart';
|
import 'package:paperless_mobile/features/labels/bloc/label_cubit.dart';
|
||||||
|
import 'package:paperless_mobile/features/labels/bloc/providers/correspondent_bloc_provider.dart';
|
||||||
|
import 'package:paperless_mobile/features/labels/bloc/providers/document_type_bloc_provider.dart';
|
||||||
|
import 'package:paperless_mobile/features/labels/bloc/providers/storage_path_bloc_provider.dart';
|
||||||
|
import 'package:paperless_mobile/features/labels/bloc/providers/tag_bloc_provider.dart';
|
||||||
import 'package:paperless_mobile/features/labels/view/widgets/label_tab_view.dart';
|
import 'package:paperless_mobile/features/labels/view/widgets/label_tab_view.dart';
|
||||||
import 'package:paperless_mobile/generated/l10n.dart';
|
import 'package:paperless_mobile/generated/l10n.dart';
|
||||||
|
|
||||||
@@ -119,11 +123,7 @@ class _LabelsPageState extends State<LabelsPage>
|
|||||||
body: TabBarView(
|
body: TabBarView(
|
||||||
controller: _tabController,
|
controller: _tabController,
|
||||||
children: [
|
children: [
|
||||||
BlocProvider(
|
CorrespondentBlocProvider(
|
||||||
create: (context) => LabelCubit(
|
|
||||||
RepositoryProvider.of<LabelRepository<Correspondent>>(
|
|
||||||
context),
|
|
||||||
),
|
|
||||||
child: LabelTabView<Correspondent>(
|
child: LabelTabView<Correspondent>(
|
||||||
filterBuilder: (label) => DocumentFilter(
|
filterBuilder: (label) => DocumentFilter(
|
||||||
correspondent: IdQueryParameter.fromId(label.id),
|
correspondent: IdQueryParameter.fromId(label.id),
|
||||||
@@ -139,11 +139,7 @@ class _LabelsPageState extends State<LabelsPage>
|
|||||||
onAddNew: _openAddCorrespondentPage,
|
onAddNew: _openAddCorrespondentPage,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
BlocProvider(
|
DocumentTypeBlocProvider(
|
||||||
create: (context) => LabelCubit(
|
|
||||||
RepositoryProvider.of<LabelRepository<DocumentType>>(
|
|
||||||
context),
|
|
||||||
),
|
|
||||||
child: LabelTabView<DocumentType>(
|
child: LabelTabView<DocumentType>(
|
||||||
filterBuilder: (label) => DocumentFilter(
|
filterBuilder: (label) => DocumentFilter(
|
||||||
documentType: IdQueryParameter.fromId(label.id),
|
documentType: IdQueryParameter.fromId(label.id),
|
||||||
@@ -159,10 +155,7 @@ class _LabelsPageState extends State<LabelsPage>
|
|||||||
onAddNew: _openAddDocumentTypePage,
|
onAddNew: _openAddDocumentTypePage,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
BlocProvider(
|
TagBlocProvider(
|
||||||
create: (context) => LabelCubit<Tag>(
|
|
||||||
RepositoryProvider.of<LabelRepository<Tag>>(context),
|
|
||||||
),
|
|
||||||
child: LabelTabView<Tag>(
|
child: LabelTabView<Tag>(
|
||||||
filterBuilder: (label) => DocumentFilter(
|
filterBuilder: (label) => DocumentFilter(
|
||||||
tags: IdsTagsQuery.fromIds([label.id!]),
|
tags: IdsTagsQuery.fromIds([label.id!]),
|
||||||
@@ -186,11 +179,7 @@ class _LabelsPageState extends State<LabelsPage>
|
|||||||
onAddNew: _openAddTagPage,
|
onAddNew: _openAddTagPage,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
BlocProvider(
|
StoragePathBlocProvider(
|
||||||
create: (context) => LabelCubit<StoragePath>(
|
|
||||||
RepositoryProvider.of<LabelRepository<StoragePath>>(
|
|
||||||
context),
|
|
||||||
),
|
|
||||||
child: LabelTabView<StoragePath>(
|
child: LabelTabView<StoragePath>(
|
||||||
onEdit: _openEditStoragePathPage,
|
onEdit: _openEditStoragePathPage,
|
||||||
filterBuilder: (label) => DocumentFilter(
|
filterBuilder: (label) => DocumentFilter(
|
||||||
@@ -219,8 +208,8 @@ class _LabelsPageState extends State<LabelsPage>
|
|||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (_) => RepositoryProvider.value(
|
builder: (_) => RepositoryProvider(
|
||||||
value: RepositoryProvider.of<LabelRepository<Correspondent>>(context),
|
create: (context) => context.read<LabelRepository<Correspondent>>(),
|
||||||
child: EditCorrespondentPage(correspondent: correspondent),
|
child: EditCorrespondentPage(correspondent: correspondent),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -231,8 +220,8 @@ class _LabelsPageState extends State<LabelsPage>
|
|||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (_) => RepositoryProvider.value(
|
builder: (_) => RepositoryProvider(
|
||||||
value: RepositoryProvider.of<LabelRepository<DocumentType>>(context),
|
create: (context) => context.read<LabelRepository<DocumentType>>(),
|
||||||
child: EditDocumentTypePage(documentType: docType),
|
child: EditDocumentTypePage(documentType: docType),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -243,8 +232,8 @@ class _LabelsPageState extends State<LabelsPage>
|
|||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (_) => RepositoryProvider.value(
|
builder: (_) => RepositoryProvider(
|
||||||
value: RepositoryProvider.of<LabelRepository<Tag>>(context),
|
create: (context) => context.read<LabelRepository<Tag>>(),
|
||||||
child: EditTagPage(tag: tag),
|
child: EditTagPage(tag: tag),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -255,8 +244,8 @@ class _LabelsPageState extends State<LabelsPage>
|
|||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (_) => RepositoryProvider.value(
|
builder: (_) => RepositoryProvider(
|
||||||
value: RepositoryProvider.of<LabelRepository<StoragePath>>(context),
|
create: (context) => context.read<LabelRepository<StoragePath>>(),
|
||||||
child: EditStoragePathPage(
|
child: EditStoragePathPage(
|
||||||
storagePath: path,
|
storagePath: path,
|
||||||
),
|
),
|
||||||
@@ -269,8 +258,8 @@ class _LabelsPageState extends State<LabelsPage>
|
|||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (_) => RepositoryProvider.value(
|
builder: (_) => RepositoryProvider(
|
||||||
value: RepositoryProvider.of<LabelRepository<Correspondent>>(context),
|
create: (context) => context.read<LabelRepository<Correspondent>>(),
|
||||||
child: const AddCorrespondentPage(),
|
child: const AddCorrespondentPage(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -281,8 +270,8 @@ class _LabelsPageState extends State<LabelsPage>
|
|||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (_) => RepositoryProvider.value(
|
builder: (_) => RepositoryProvider(
|
||||||
value: RepositoryProvider.of<LabelRepository<DocumentType>>(context),
|
create: (context) => context.read<LabelRepository<DocumentType>>(),
|
||||||
child: const AddDocumentTypePage(),
|
child: const AddDocumentTypePage(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -293,8 +282,8 @@ class _LabelsPageState extends State<LabelsPage>
|
|||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (_) => RepositoryProvider.value(
|
builder: (_) => RepositoryProvider(
|
||||||
value: RepositoryProvider.of<LabelRepository<Tag>>(context),
|
create: (context) => context.read<LabelRepository<Tag>>(),
|
||||||
child: const AddTagPage(),
|
child: const AddTagPage(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -305,8 +294,8 @@ class _LabelsPageState extends State<LabelsPage>
|
|||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (_) => RepositoryProvider.value(
|
builder: (_) => RepositoryProvider(
|
||||||
value: RepositoryProvider.of<LabelRepository<StoragePath>>(context),
|
create: (context) => context.read<LabelRepository<StoragePath>>(),
|
||||||
child: const AddStoragePathPage(),
|
child: const AddStoragePathPage(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ class LabelItem<T extends Label> extends StatelessWidget {
|
|||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => BlocProvider(
|
builder: (context) => BlocProvider(
|
||||||
create: (context) => LinkedDocumentsCubit(
|
create: (context) => LinkedDocumentsCubit(
|
||||||
Provider.of<PaperlessDocumentsApi>(context),
|
context.read<PaperlessDocumentsApi>(),
|
||||||
filter,
|
filter,
|
||||||
),
|
),
|
||||||
child: const LinkedDocumentsPage(),
|
child: const LinkedDocumentsPage(),
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ class LabelTabView<T extends Label> extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
return RefreshIndicator(
|
return RefreshIndicator(
|
||||||
onRefresh: BlocProvider.of<LabelCubit<T>>(context).reload,
|
onRefresh: context.read<LabelCubit<T>>().reload,
|
||||||
child: ListView(
|
child: ListView(
|
||||||
children: labels
|
children: labels
|
||||||
.map(
|
.map(
|
||||||
|
|||||||
@@ -65,8 +65,7 @@ class _LinkedDocumentsPageState extends State<LinkedDocumentsPage> {
|
|||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => BlocProvider(
|
builder: (context) => BlocProvider(
|
||||||
create: (context) => DocumentDetailsCubit(
|
create: (context) => DocumentDetailsCubit(
|
||||||
Provider.of<PaperlessDocumentsApi>(
|
context.read<PaperlessDocumentsApi>(),
|
||||||
context),
|
|
||||||
document,
|
document,
|
||||||
),
|
),
|
||||||
child: const DocumentDetailsPage(
|
child: const DocumentDetailsPage(
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.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/security/security_context_aware_dio_manager.dart';
|
import 'package:paperless_mobile/core/security/authentication_aware_dio_manager.dart';
|
||||||
import 'package:paperless_mobile/core/store/local_vault.dart';
|
import 'package:paperless_mobile/core/store/local_vault.dart';
|
||||||
import 'package:paperless_mobile/features/login/bloc/authentication_state.dart';
|
import 'package:paperless_mobile/features/login/bloc/authentication_state.dart';
|
||||||
import 'package:paperless_mobile/features/login/model/authentication_information.dart';
|
import 'package:paperless_mobile/features/login/model/authentication_information.dart';
|
||||||
@@ -16,7 +15,7 @@ class AuthenticationCubit extends HydratedCubit<AuthenticationState> {
|
|||||||
final LocalAuthenticationService _localAuthService;
|
final LocalAuthenticationService _localAuthService;
|
||||||
final PaperlessAuthenticationApi _authApi;
|
final PaperlessAuthenticationApi _authApi;
|
||||||
final LocalVault _localVault;
|
final LocalVault _localVault;
|
||||||
final SecurityContextAwareDioManager _dioWrapper;
|
final AuthenticationAwareDioManager _dioWrapper;
|
||||||
|
|
||||||
AuthenticationCubit(
|
AuthenticationCubit(
|
||||||
this._localVault,
|
this._localVault,
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ class AuthenticationState {
|
|||||||
required this.wasLoginStored,
|
required this.wasLoginStored,
|
||||||
this.wasLocalAuthenticationSuccessful,
|
this.wasLocalAuthenticationSuccessful,
|
||||||
this.authentication,
|
this.authentication,
|
||||||
});
|
}) : assert(!isAuthenticated || authentication != null);
|
||||||
|
|
||||||
AuthenticationState copyWith({
|
AuthenticationState copyWith({
|
||||||
bool? wasLoginStored,
|
bool? wasLoginStored,
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ class _LoginPageState extends State<LoginPage> {
|
|||||||
setState(() => _isLoginLoading = true);
|
setState(() => _isLoginLoading = true);
|
||||||
final form = _formKey.currentState!.value;
|
final form = _formKey.currentState!.value;
|
||||||
try {
|
try {
|
||||||
await BlocProvider.of<AuthenticationCubit>(context).login(
|
await context.read<AuthenticationCubit>().login(
|
||||||
credentials: form[UserCredentialsFormField.fkCredentials],
|
credentials: form[UserCredentialsFormField.fkCredentials],
|
||||||
serverUrl: form[ServerAddressFormField.fkServerAddress],
|
serverUrl: form[ServerAddressFormField.fkServerAddress],
|
||||||
clientCertificate:
|
clientCertificate:
|
||||||
|
|||||||
@@ -63,8 +63,8 @@ class _ServerAddressFormFieldState extends State<ServerAddressFormField> {
|
|||||||
}
|
}
|
||||||
//https://stackoverflow.com/questions/49648022/check-whether-there-is-an-internet-connection-available-on-flutter-app
|
//https://stackoverflow.com/questions/49648022/check-whether-there-is-an-internet-connection-available-on-flutter-app
|
||||||
setState(() => _reachabilityStatus = ReachabilityStatus.testing);
|
setState(() => _reachabilityStatus = ReachabilityStatus.testing);
|
||||||
final isReachable =
|
final isReachable = await context
|
||||||
await Provider.of<ConnectivityStatusService>(context, listen: false)
|
.read<ConnectivityStatusService>()
|
||||||
.isServerReachable(address);
|
.isServerReachable(address);
|
||||||
if (isReachable) {
|
if (isReachable) {
|
||||||
setState(() => _reachabilityStatus = ReachabilityStatus.reachable);
|
setState(() => _reachabilityStatus = ReachabilityStatus.reachable);
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ class SavedViewSelectionWidget extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
if (newView != null) {
|
if (newView != null) {
|
||||||
try {
|
try {
|
||||||
await BlocProvider.of<SavedViewCubit>(context).add(newView);
|
await context.read<SavedViewCubit>().add(newView);
|
||||||
} on PaperlessServerException catch (error, stackTrace) {
|
} on PaperlessServerException catch (error, stackTrace) {
|
||||||
showErrorMessage(context, error, stackTrace);
|
showErrorMessage(context, error, stackTrace);
|
||||||
}
|
}
|
||||||
@@ -139,9 +139,9 @@ class SavedViewSelectionWidget extends StatelessWidget {
|
|||||||
void _onSelected(
|
void _onSelected(
|
||||||
bool isSelected, BuildContext context, SavedView view) async {
|
bool isSelected, BuildContext context, SavedView view) async {
|
||||||
if (isSelected) {
|
if (isSelected) {
|
||||||
BlocProvider.of<SavedViewCubit>(context).selectView(view);
|
context.read<SavedViewCubit>().selectView(view);
|
||||||
} else {
|
} else {
|
||||||
BlocProvider.of<SavedViewCubit>(context).selectView(null);
|
context.read<SavedViewCubit>().selectView(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,7 +154,7 @@ class SavedViewSelectionWidget extends StatelessWidget {
|
|||||||
false;
|
false;
|
||||||
if (delete) {
|
if (delete) {
|
||||||
try {
|
try {
|
||||||
BlocProvider.of<SavedViewCubit>(context).remove(view);
|
context.read<SavedViewCubit>().remove(view);
|
||||||
} on PaperlessServerException catch (error, stackTrace) {
|
} on PaperlessServerException catch (error, stackTrace) {
|
||||||
showErrorMessage(context, error, stackTrace);
|
showErrorMessage(context, error, stackTrace);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,12 +126,12 @@ class _ScannerPageState extends State<ScannerPage>
|
|||||||
if (kDebugMode) {
|
if (kDebugMode) {
|
||||||
dev.log('[ScannerPage] Wrote image to temporary file: ${file.path}');
|
dev.log('[ScannerPage] Wrote image to temporary file: ${file.path}');
|
||||||
}
|
}
|
||||||
BlocProvider.of<DocumentScannerCubit>(context).addScan(file);
|
context.read<DocumentScannerCubit>().addScan(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onPrepareDocumentUpload(BuildContext context) async {
|
void _onPrepareDocumentUpload(BuildContext context) async {
|
||||||
final doc = _buildDocumentFromImageFiles(
|
final doc = _buildDocumentFromImageFiles(
|
||||||
BlocProvider.of<DocumentScannerCubit>(context).state,
|
context.read<DocumentScannerCubit>().state,
|
||||||
);
|
);
|
||||||
final bytes = await doc.save();
|
final bytes = await doc.save();
|
||||||
final uploaded = await Navigator.of(context).push(
|
final uploaded = await Navigator.of(context).push(
|
||||||
@@ -139,19 +139,13 @@ class _ScannerPageState extends State<ScannerPage>
|
|||||||
builder: (_) => LabelRepositoriesProvider(
|
builder: (_) => LabelRepositoriesProvider(
|
||||||
child: BlocProvider(
|
child: BlocProvider(
|
||||||
create: (context) => DocumentUploadCubit(
|
create: (context) => DocumentUploadCubit(
|
||||||
localVault: Provider.of<LocalVault>(context),
|
localVault: context.read<LocalVault>(),
|
||||||
documentApi: Provider.of<PaperlessDocumentsApi>(context),
|
documentApi: context.read<PaperlessDocumentsApi>(),
|
||||||
correspondentRepository:
|
correspondentRepository:
|
||||||
RepositoryProvider.of<LabelRepository<Correspondent>>(
|
context.read<LabelRepository<Correspondent>>(),
|
||||||
context,
|
|
||||||
),
|
|
||||||
documentTypeRepository:
|
documentTypeRepository:
|
||||||
RepositoryProvider.of<LabelRepository<DocumentType>>(
|
context.read<LabelRepository<DocumentType>>(),
|
||||||
context,
|
tagRepository: context.read<LabelRepository<Tag>>(),
|
||||||
),
|
|
||||||
tagRepository: RepositoryProvider.of<LabelRepository<Tag>>(
|
|
||||||
context,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
child: DocumentUploadPreparationPage(
|
child: DocumentUploadPreparationPage(
|
||||||
fileBytes: bytes,
|
fileBytes: bytes,
|
||||||
@@ -162,7 +156,7 @@ class _ScannerPageState extends State<ScannerPage>
|
|||||||
) ??
|
) ??
|
||||||
false;
|
false;
|
||||||
if (uploaded) {
|
if (uploaded) {
|
||||||
BlocProvider.of<DocumentScannerCubit>(context).reset();
|
context.read<DocumentScannerCubit>().reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,8 +210,7 @@ class _ScannerPageState extends State<ScannerPage>
|
|||||||
file: scans[index],
|
file: scans[index],
|
||||||
onDelete: () async {
|
onDelete: () async {
|
||||||
try {
|
try {
|
||||||
BlocProvider.of<DocumentScannerCubit>(context)
|
context.read<DocumentScannerCubit>().removeScan(index);
|
||||||
.removeScan(index);
|
|
||||||
} on PaperlessServerException catch (error, stackTrace) {
|
} on PaperlessServerException catch (error, stackTrace) {
|
||||||
showErrorMessage(context, error, stackTrace);
|
showErrorMessage(context, error, stackTrace);
|
||||||
}
|
}
|
||||||
@@ -230,7 +223,7 @@ class _ScannerPageState extends State<ScannerPage>
|
|||||||
|
|
||||||
void _reset(BuildContext context) {
|
void _reset(BuildContext context) {
|
||||||
try {
|
try {
|
||||||
BlocProvider.of<DocumentScannerCubit>(context).reset();
|
context.read<DocumentScannerCubit>().reset();
|
||||||
} on PaperlessServerException catch (error, stackTrace) {
|
} on PaperlessServerException catch (error, stackTrace) {
|
||||||
showErrorMessage(context, error, stackTrace);
|
showErrorMessage(context, error, stackTrace);
|
||||||
}
|
}
|
||||||
@@ -274,19 +267,13 @@ class _ScannerPageState extends State<ScannerPage>
|
|||||||
builder: (_) => LabelRepositoriesProvider(
|
builder: (_) => LabelRepositoriesProvider(
|
||||||
child: BlocProvider(
|
child: BlocProvider(
|
||||||
create: (context) => DocumentUploadCubit(
|
create: (context) => DocumentUploadCubit(
|
||||||
localVault: Provider.of<LocalVault>(context),
|
localVault: context.read<LocalVault>(),
|
||||||
documentApi: Provider.of<PaperlessDocumentsApi>(context),
|
documentApi: context.read<PaperlessDocumentsApi>(),
|
||||||
correspondentRepository:
|
correspondentRepository:
|
||||||
RepositoryProvider.of<LabelRepository<Correspondent>>(
|
context.read<LabelRepository<Correspondent>>(),
|
||||||
context,
|
|
||||||
),
|
|
||||||
documentTypeRepository:
|
documentTypeRepository:
|
||||||
RepositoryProvider.of<LabelRepository<DocumentType>>(
|
context.read<LabelRepository<DocumentType>>(),
|
||||||
context,
|
tagRepository: context.read<LabelRepository<Tag>>(),
|
||||||
),
|
|
||||||
tagRepository: RepositoryProvider.of<LabelRepository<Tag>>(
|
|
||||||
context,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
child: DocumentUploadPreparationPage(
|
child: DocumentUploadPreparationPage(
|
||||||
fileBytes: fileBytes,
|
fileBytes: fileBytes,
|
||||||
|
|||||||
@@ -44,9 +44,10 @@ class SettingsPage extends StatelessWidget {
|
|||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (ctxt) => BlocProvider.value(
|
builder: (context) => BlocProvider.value(
|
||||||
value: BlocProvider.of<ApplicationSettingsCubit>(context),
|
value: context.read<ApplicationSettingsCubit>(),
|
||||||
child: page),
|
child: page,
|
||||||
|
),
|
||||||
maintainState: true,
|
maintainState: true,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -19,8 +19,7 @@ class BiometricAuthenticationSetting extends StatelessWidget {
|
|||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
S.of(context).appSettingsBiometricAuthenticationDescriptionText),
|
S.of(context).appSettingsBiometricAuthenticationDescriptionText),
|
||||||
onChanged: (val) async {
|
onChanged: (val) async {
|
||||||
final settingsBloc =
|
final settingsBloc = context.read<ApplicationSettingsCubit>();
|
||||||
BlocProvider.of<ApplicationSettingsCubit>(context);
|
|
||||||
final String localizedReason = val
|
final String localizedReason = val
|
||||||
? S
|
? S
|
||||||
.of(context)
|
.of(context)
|
||||||
@@ -28,8 +27,8 @@ class BiometricAuthenticationSetting extends StatelessWidget {
|
|||||||
: S
|
: S
|
||||||
.of(context)
|
.of(context)
|
||||||
.appSettingsDisableBiometricAuthenticationReasonText;
|
.appSettingsDisableBiometricAuthenticationReasonText;
|
||||||
final changeValue =
|
final changeValue = await context
|
||||||
await Provider.of<LocalAuthenticationService>(context)
|
.read<LocalAuthenticationService>()
|
||||||
.authenticateLocalUser(localizedReason);
|
.authenticateLocalUser(localizedReason);
|
||||||
if (changeValue) {
|
if (changeValue) {
|
||||||
settingsBloc.setIsBiometricAuthenticationEnabled(val);
|
settingsBloc.setIsBiometricAuthenticationEnabled(val);
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class ClearStorageSetting extends StatelessWidget {
|
|||||||
subtitle:
|
subtitle:
|
||||||
Text("Remove downloaded files, scans and clear the cache's content"),
|
Text("Remove downloaded files, scans and clear the cache's content"),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Provider.of<cm.CacheManager>(context).emptyCache();
|
context.read<cm.CacheManager>().emptyCache();
|
||||||
FileService.clearUserData();
|
FileService.clearUserData();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -44,12 +44,13 @@ class _LanguageSelectionSettingState extends State<LanguageSelectionSetting> {
|
|||||||
label: _languageOptions['cs']!,
|
label: _languageOptions['cs']!,
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
initialValue: BlocProvider.of<ApplicationSettingsCubit>(context)
|
initialValue: context
|
||||||
|
.read<ApplicationSettingsCubit>()
|
||||||
.state
|
.state
|
||||||
.preferredLocaleSubtag,
|
.preferredLocaleSubtag,
|
||||||
),
|
),
|
||||||
).then((value) => BlocProvider.of<ApplicationSettingsCubit>(context)
|
).then((value) =>
|
||||||
.setLocale(value)),
|
context.read<ApplicationSettingsCubit>().setLocale(value)),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -38,14 +38,14 @@ class ThemeModeSetting extends StatelessWidget {
|
|||||||
S.of(context).settingsPageAppearanceSettingDarkThemeLabel,
|
S.of(context).settingsPageAppearanceSettingDarkThemeLabel,
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
initialValue: BlocProvider.of<ApplicationSettingsCubit>(context)
|
initialValue: context
|
||||||
|
.read<ApplicationSettingsCubit>()
|
||||||
.state
|
.state
|
||||||
.preferredThemeMode,
|
.preferredThemeMode,
|
||||||
title: Text(S.of(context).settingsPageAppearanceSettingTitle),
|
title: Text(S.of(context).settingsPageAppearanceSettingTitle),
|
||||||
),
|
),
|
||||||
).then((value) {
|
).then((value) {
|
||||||
return BlocProvider.of<ApplicationSettingsCubit>(context)
|
return context.read<ApplicationSettingsCubit>().setThemeMode(value);
|
||||||
.setThemeMode(value);
|
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
122
lib/main.dart
122
lib/main.dart
@@ -10,19 +10,20 @@ import 'package:flutter_localizations/flutter_localizations.dart';
|
|||||||
import 'package:flutter_native_splash/flutter_native_splash.dart';
|
import 'package:flutter_native_splash/flutter_native_splash.dart';
|
||||||
import 'package:fluttertoast/fluttertoast.dart';
|
import 'package:fluttertoast/fluttertoast.dart';
|
||||||
import 'package:form_builder_validators/form_builder_validators.dart';
|
import 'package:form_builder_validators/form_builder_validators.dart';
|
||||||
|
import 'package:http/http.dart';
|
||||||
import 'package:http/io_client.dart';
|
import 'package:http/io_client.dart';
|
||||||
|
import 'package:http_interceptor/http/intercepted_client.dart';
|
||||||
import 'package:hydrated_bloc/hydrated_bloc.dart';
|
import 'package:hydrated_bloc/hydrated_bloc.dart';
|
||||||
import 'package:intl/date_symbol_data_local.dart';
|
import 'package:intl/date_symbol_data_local.dart';
|
||||||
import 'package:intl/intl_standalone.dart';
|
import 'package:intl/intl_standalone.dart';
|
||||||
import 'package:local_auth/local_auth.dart';
|
import 'package:local_auth/local_auth.dart';
|
||||||
import 'package:package_info_plus/package_info_plus.dart';
|
|
||||||
import 'package:paperless_api/paperless_api.dart';
|
import 'package:paperless_api/paperless_api.dart';
|
||||||
import 'package:paperless_mobile/core/bloc/bloc_changes_observer.dart';
|
import 'package:paperless_mobile/core/bloc/bloc_changes_observer.dart';
|
||||||
import 'package:paperless_mobile/core/bloc/connectivity_cubit.dart';
|
import 'package:paperless_mobile/core/bloc/connectivity_cubit.dart';
|
||||||
import 'package:paperless_mobile/core/bloc/paperless_server_information_cubit.dart';
|
import 'package:paperless_mobile/core/bloc/paperless_server_information_cubit.dart';
|
||||||
import 'package:paperless_mobile/core/global/constants.dart';
|
import 'package:paperless_mobile/core/global/constants.dart';
|
||||||
|
import 'package:paperless_mobile/core/interceptor/authentication.interceptor.dart';
|
||||||
import 'package:paperless_mobile/core/logic/error_code_localization_mapper.dart';
|
import 'package:paperless_mobile/core/logic/error_code_localization_mapper.dart';
|
||||||
import 'package:paperless_mobile/core/model/paperless_statistics_state.dart';
|
|
||||||
import 'package:paperless_mobile/core/repository/impl/correspondent_repository_impl.dart';
|
import 'package:paperless_mobile/core/repository/impl/correspondent_repository_impl.dart';
|
||||||
import 'package:paperless_mobile/core/repository/impl/document_type_repository_impl.dart';
|
import 'package:paperless_mobile/core/repository/impl/document_type_repository_impl.dart';
|
||||||
import 'package:paperless_mobile/core/repository/impl/saved_view_repository_impl.dart';
|
import 'package:paperless_mobile/core/repository/impl/saved_view_repository_impl.dart';
|
||||||
@@ -30,17 +31,19 @@ import 'package:paperless_mobile/core/repository/impl/storage_path_repository_im
|
|||||||
import 'package:paperless_mobile/core/repository/impl/tag_repository_impl.dart';
|
import 'package:paperless_mobile/core/repository/impl/tag_repository_impl.dart';
|
||||||
import 'package:paperless_mobile/core/repository/label_repository.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/repository/saved_view_repository.dart';
|
||||||
import 'package:paperless_mobile/core/security/security_context_aware_dio_manager.dart';
|
import 'package:paperless_mobile/core/security/authentication_aware_dio_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/file_service.dart';
|
import 'package:paperless_mobile/core/service/file_service.dart';
|
||||||
import 'package:paperless_mobile/core/store/local_vault.dart';
|
import 'package:paperless_mobile/core/store/local_vault.dart';
|
||||||
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
||||||
|
import 'package:paperless_mobile/extensions/security_context_extension.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/document_upload/cubit/document_upload_cubit.dart';
|
import 'package:paperless_mobile/features/document_upload/cubit/document_upload_cubit.dart';
|
||||||
import 'package:paperless_mobile/features/document_upload/view/document_upload_preparation_page.dart';
|
import 'package:paperless_mobile/features/document_upload/view/document_upload_preparation_page.dart';
|
||||||
import 'package:paperless_mobile/features/home/view/home_page.dart';
|
import 'package:paperless_mobile/features/home/view/home_page.dart';
|
||||||
import 'package:paperless_mobile/features/login/bloc/authentication_cubit.dart';
|
import 'package:paperless_mobile/features/login/bloc/authentication_cubit.dart';
|
||||||
import 'package:paperless_mobile/features/login/bloc/authentication_state.dart';
|
import 'package:paperless_mobile/features/login/bloc/authentication_state.dart';
|
||||||
|
import 'package:paperless_mobile/features/login/model/authentication_information.dart';
|
||||||
import 'package:paperless_mobile/features/login/services/authentication_service.dart';
|
import 'package:paperless_mobile/features/login/services/authentication_service.dart';
|
||||||
import 'package:paperless_mobile/features/login/view/login_page.dart';
|
import 'package:paperless_mobile/features/login/view/login_page.dart';
|
||||||
import 'package:paperless_mobile/features/settings/bloc/application_settings_cubit.dart';
|
import 'package:paperless_mobile/features/settings/bloc/application_settings_cubit.dart';
|
||||||
@@ -62,18 +65,12 @@ void main() async {
|
|||||||
await findSystemLocale();
|
await findSystemLocale();
|
||||||
|
|
||||||
// Required for self signed client certificates
|
// Required for self signed client certificates
|
||||||
final dioWrapper = SecurityContextAwareDioManager();
|
final dioWrapper = AuthenticationAwareDioManager();
|
||||||
IOClient httpClient = IOClient();
|
|
||||||
|
|
||||||
dioWrapper.securityContextChanges.listen(
|
|
||||||
(context) => httpClient = IOClient(HttpClient(context: context)),
|
|
||||||
);
|
|
||||||
// Initialize External dependencies
|
// Initialize External dependencies
|
||||||
final connectivity = Connectivity();
|
final connectivity = Connectivity();
|
||||||
final encryptedSharedPreferences = EncryptedSharedPreferences();
|
final encryptedSharedPreferences = EncryptedSharedPreferences();
|
||||||
final localAuthentication = LocalAuthentication();
|
final localAuthentication = LocalAuthentication();
|
||||||
final cacheManager = cm.CacheManager(cm.Config('cacheKey',
|
|
||||||
fileService: cm.HttpFileService(httpClient: httpClient)));
|
|
||||||
|
|
||||||
// Initialize Paperless APIs
|
// Initialize Paperless APIs
|
||||||
final authApi = PaperlessAuthenticationApiImpl(dioWrapper.client);
|
final authApi = PaperlessAuthenticationApiImpl(dioWrapper.client);
|
||||||
@@ -104,8 +101,35 @@ void main() async {
|
|||||||
authApi,
|
authApi,
|
||||||
dioWrapper,
|
dioWrapper,
|
||||||
);
|
);
|
||||||
//TODO: Check if hydrated cubit restores state.
|
|
||||||
//await authCubit.restoreSessionState();
|
String? currentServerUrl;
|
||||||
|
String? currentAuthToken;
|
||||||
|
|
||||||
|
if (authCubit.state.isAuthenticated) {
|
||||||
|
final auth = authCubit.state.authentication!;
|
||||||
|
dioWrapper.updateSettings(
|
||||||
|
baseUrl: auth.serverUrl,
|
||||||
|
authToken: auth.token,
|
||||||
|
clientCertificate: auth.clientCertificate,
|
||||||
|
);
|
||||||
|
currentServerUrl = auth.serverUrl;
|
||||||
|
currentAuthToken = auth.token;
|
||||||
|
}
|
||||||
|
|
||||||
|
SecurityContext securityContext = SecurityContext();
|
||||||
|
authCubit.stream.asBroadcastStream().listen((event) {
|
||||||
|
if (event.isAuthenticated) {
|
||||||
|
final auth = event.authentication!;
|
||||||
|
securityContext =
|
||||||
|
SecurityContext().withClientCertificate(auth.clientCertificate);
|
||||||
|
currentServerUrl = auth.serverUrl;
|
||||||
|
currentAuthToken = auth.token;
|
||||||
|
} else {
|
||||||
|
securityContext = SecurityContext();
|
||||||
|
currentServerUrl = null;
|
||||||
|
currentAuthToken = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Create repositories
|
// Create repositories
|
||||||
final tagRepository = TagRepositoryImpl(labelsApi);
|
final tagRepository = TagRepositoryImpl(labelsApi);
|
||||||
@@ -122,7 +146,47 @@ void main() async {
|
|||||||
Provider<PaperlessLabelsApi>.value(value: labelsApi),
|
Provider<PaperlessLabelsApi>.value(value: labelsApi),
|
||||||
Provider<PaperlessServerStatsApi>.value(value: statsApi),
|
Provider<PaperlessServerStatsApi>.value(value: statsApi),
|
||||||
Provider<PaperlessSavedViewsApi>.value(value: savedViewsApi),
|
Provider<PaperlessSavedViewsApi>.value(value: savedViewsApi),
|
||||||
Provider<cm.CacheManager>.value(value: cacheManager),
|
ProxyProvider<SecurityContext, cm.CacheManager>(
|
||||||
|
create: (context) => cm.CacheManager(
|
||||||
|
cm.Config(
|
||||||
|
'cacheKey',
|
||||||
|
fileService: cm.HttpFileService(
|
||||||
|
httpClient: InterceptedClient.build(
|
||||||
|
interceptors: [
|
||||||
|
AuthenticationInterceptor(
|
||||||
|
serverUrl: currentServerUrl,
|
||||||
|
token: currentAuthToken,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
client: IOClient(
|
||||||
|
HttpClient(
|
||||||
|
context: securityContext,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
update: (context, securityContext, previous) => cm.CacheManager(
|
||||||
|
cm.Config(
|
||||||
|
'cacheKey',
|
||||||
|
fileService: cm.HttpFileService(
|
||||||
|
httpClient: InterceptedClient.build(
|
||||||
|
interceptors: [
|
||||||
|
AuthenticationInterceptor(
|
||||||
|
serverUrl: currentServerUrl,
|
||||||
|
token: currentAuthToken,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
client: IOClient(
|
||||||
|
HttpClient(
|
||||||
|
context: securityContext,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
Provider<LocalVault>.value(value: localVault),
|
Provider<LocalVault>.value(value: localVault),
|
||||||
Provider<ConnectivityStatusService>.value(
|
Provider<ConnectivityStatusService>.value(
|
||||||
value: connectivityStatusService,
|
value: connectivityStatusService,
|
||||||
@@ -148,17 +212,8 @@ void main() async {
|
|||||||
],
|
],
|
||||||
child: MultiBlocProvider(
|
child: MultiBlocProvider(
|
||||||
providers: [
|
providers: [
|
||||||
BlocProvider(
|
BlocProvider<AuthenticationCubit>.value(value: authCubit),
|
||||||
create: (context) => AuthenticationCubit(
|
BlocProvider<ConnectivityCubit>.value(value: connectivityCubit),
|
||||||
localVault,
|
|
||||||
localAuthService,
|
|
||||||
authApi,
|
|
||||||
dioWrapper,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
BlocProvider<ConnectivityCubit>.value(
|
|
||||||
value: connectivityCubit,
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
child: const PaperlessMobileEntrypoint(),
|
child: const PaperlessMobileEntrypoint(),
|
||||||
),
|
),
|
||||||
@@ -225,10 +280,7 @@ class _PaperlessMobileEntrypointState extends State<PaperlessMobileEntrypoint> {
|
|||||||
return MultiBlocProvider(
|
return MultiBlocProvider(
|
||||||
providers: [
|
providers: [
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
create: (context) => ConnectivityCubit(context.watch()),
|
create: (context) => PaperlessServerInformationCubit(context.read()),
|
||||||
),
|
|
||||||
BlocProvider(
|
|
||||||
create: (context) => PaperlessServerInformationCubit(context.watch()),
|
|
||||||
),
|
),
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
create: (context) => ApplicationSettingsCubit(),
|
create: (context) => ApplicationSettingsCubit(),
|
||||||
@@ -313,13 +365,13 @@ class _AuthenticationWrapperState extends State<AuthenticationWrapper> {
|
|||||||
final success = await Navigator.push(
|
final success = await Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => BlocProvider(
|
builder: (context) => BlocProvider.value(
|
||||||
create: (BuildContext context) => DocumentUploadCubit(
|
value: DocumentUploadCubit(
|
||||||
localVault: context.watch(),
|
localVault: context.read(),
|
||||||
documentApi: context.watch(),
|
documentApi: context.read(),
|
||||||
tagRepository: context.watch(),
|
tagRepository: context.read(),
|
||||||
correspondentRepository: context.watch(),
|
correspondentRepository: context.read(),
|
||||||
documentTypeRepository: context.watch(),
|
documentTypeRepository: context.read(),
|
||||||
),
|
),
|
||||||
child: DocumentUploadPreparationPage(
|
child: DocumentUploadPreparationPage(
|
||||||
fileBytes: bytes,
|
fileBytes: bytes,
|
||||||
|
|||||||
Reference in New Issue
Block a user