mirror of
https://github.com/Xevion/paperless-mobile.git
synced 2025-12-09 10:08:00 -06:00
feat: Add debug output, run app in guarded zone
This commit is contained in:
@@ -19,11 +19,15 @@ class DioHttpErrorInterceptor extends Interceptor {
|
||||
} else if (err.response?.statusCode == 403) {
|
||||
var data = err.response!.data;
|
||||
if (data is Map && data.containsKey("detail")) {
|
||||
handler.reject(DioError(
|
||||
requestOptions: err.requestOptions,
|
||||
error: ServerMessageException(data['detail']),
|
||||
response: err.response,
|
||||
));
|
||||
handler.reject(
|
||||
DioError(
|
||||
message: data['detail'],
|
||||
requestOptions: err.requestOptions,
|
||||
error: ServerMessageException(data['detail']),
|
||||
response: err.response,
|
||||
type: DioErrorType.unknown,
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
} else if (err.error is SocketException) {
|
||||
@@ -31,6 +35,7 @@ class DioHttpErrorInterceptor extends Interceptor {
|
||||
if (ex.osError?.errorCode == _OsErrorCodes.serverUnreachable.code) {
|
||||
return handler.reject(
|
||||
DioError(
|
||||
message: "The server could not be reached. Is the device offline?",
|
||||
error: const PaperlessServerException(ErrorCode.deviceOffline),
|
||||
requestOptions: err.requestOptions,
|
||||
type: DioErrorType.connectionTimeout,
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'dart:io';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:dio/io.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:paperless_mobile/core/interceptor/dio_http_error_interceptor.dart';
|
||||
import 'package:paperless_mobile/core/interceptor/retry_on_connection_change_interceptor.dart';
|
||||
import 'package:paperless_mobile/features/login/model/client_certificate.dart';
|
||||
import 'package:pretty_dio_logger/pretty_dio_logger.dart';
|
||||
@@ -22,13 +23,14 @@ class SessionManager extends ValueNotifier<Dio> {
|
||||
BaseOptions(contentType: Headers.jsonContentType),
|
||||
);
|
||||
dio.options
|
||||
..receiveTimeout = const Duration(seconds: 20)
|
||||
..receiveTimeout = const Duration(seconds: 30)
|
||||
..sendTimeout = const Duration(seconds: 60)
|
||||
..responseType = ResponseType.json;
|
||||
(dio.httpClientAdapter as IOHttpClientAdapter).onHttpClientCreate =
|
||||
(client) => client..badCertificateCallback = (cert, host, port) => true;
|
||||
dio.interceptors.addAll([
|
||||
...interceptors,
|
||||
DioHttpErrorInterceptor(),
|
||||
PrettyDioLogger(
|
||||
compact: true,
|
||||
responseBody: false,
|
||||
|
||||
@@ -12,6 +12,7 @@ import 'package:paperless_mobile/core/bloc/connectivity_cubit.dart';
|
||||
import 'package:paperless_mobile/core/config/hive/hive_config.dart';
|
||||
import 'package:paperless_mobile/core/database/tables/global_settings.dart';
|
||||
import 'package:paperless_mobile/core/database/tables/local_user_account.dart';
|
||||
import 'package:paperless_mobile/core/exception/server_message_exception.dart';
|
||||
import 'package:paperless_mobile/core/global/constants.dart';
|
||||
import 'package:paperless_mobile/core/navigation/push_routes.dart';
|
||||
import 'package:paperless_mobile/core/repository/label_repository.dart';
|
||||
|
||||
@@ -130,10 +130,17 @@ class HomeRoute extends StatelessWidget {
|
||||
.get(currentLocalUserId)!,
|
||||
)..initialize(),
|
||||
),
|
||||
Provider(create: (context) => DocumentScannerCubit(context.read())),
|
||||
ProxyProvider4<PaperlessDocumentsApi, PaperlessServerStatsApi, LabelRepository,
|
||||
DocumentChangedNotifier, InboxCubit>(
|
||||
update: (context, docApi, statsApi, labelRepo, notifier, previous) =>
|
||||
Provider(
|
||||
create: (context) =>
|
||||
DocumentScannerCubit(context.read())),
|
||||
ProxyProvider4<
|
||||
PaperlessDocumentsApi,
|
||||
PaperlessServerStatsApi,
|
||||
LabelRepository,
|
||||
DocumentChangedNotifier,
|
||||
InboxCubit>(
|
||||
update: (context, docApi, statsApi, labelRepo, notifier,
|
||||
previous) =>
|
||||
InboxCubit(
|
||||
docApi,
|
||||
statsApi,
|
||||
@@ -143,9 +150,7 @@ class HomeRoute extends StatelessWidget {
|
||||
),
|
||||
ProxyProvider<SavedViewRepository, SavedViewCubit>(
|
||||
update: (context, savedViewRepo, previous) =>
|
||||
SavedViewCubit(
|
||||
savedViewRepo,
|
||||
),
|
||||
SavedViewCubit(savedViewRepo),
|
||||
),
|
||||
ProxyProvider<LabelRepository, LabelCubit>(
|
||||
update: (context, value, previous) => LabelCubit(value),
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'package:flutter/widgets.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:hive_flutter/adapters.dart';
|
||||
import 'package:hydrated_bloc/hydrated_bloc.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/config/hive/hive_config.dart';
|
||||
import 'package:paperless_mobile/core/config/hive/hive_extensions.dart';
|
||||
import 'package:paperless_mobile/core/database/tables/global_settings.dart';
|
||||
@@ -37,7 +38,10 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
|
||||
}) async {
|
||||
assert(credentials.username != null && credentials.password != null);
|
||||
final localUserId = "${credentials.username}@$serverUrl";
|
||||
|
||||
_debugPrintMessage(
|
||||
"login",
|
||||
"Trying to login $localUserId...",
|
||||
);
|
||||
await _addUser(
|
||||
localUserId,
|
||||
serverUrl,
|
||||
@@ -60,6 +64,10 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
|
||||
localUserId: localUserId,
|
||||
),
|
||||
);
|
||||
_debugPrintMessage(
|
||||
"login",
|
||||
"User successfully logged in.",
|
||||
);
|
||||
}
|
||||
|
||||
/// Switches to another account if it exists.
|
||||
@@ -161,26 +169,57 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
|
||||
/// Performs a conditional hydration based on the local authentication success.
|
||||
///
|
||||
Future<void> restoreSessionState() async {
|
||||
_debugPrintMessage(
|
||||
"restoreSessionState",
|
||||
"Trying to restore previous session...",
|
||||
);
|
||||
final globalSettings =
|
||||
Hive.box<GlobalSettings>(HiveBoxes.globalSettings).getValue()!;
|
||||
final localUserId = globalSettings.currentLoggedInUser;
|
||||
if (localUserId == null) {
|
||||
_debugPrintMessage(
|
||||
"restoreSessionState",
|
||||
"There is nothing to restore.",
|
||||
);
|
||||
// If there is nothing to restore, we can quit here.
|
||||
return;
|
||||
}
|
||||
final localUserAccountBox =
|
||||
Hive.box<LocalUserAccount>(HiveBoxes.localUserAccount);
|
||||
final localUserAccount = localUserAccountBox.get(localUserId)!;
|
||||
|
||||
_debugPrintMessage(
|
||||
"restoreSessionState",
|
||||
"Checking if biometric authentication is required...",
|
||||
);
|
||||
if (localUserAccount.settings.isBiometricAuthenticationEnabled) {
|
||||
_debugPrintMessage(
|
||||
"restoreSessionState",
|
||||
"Biometric authentication required, waiting for user to authenticate...",
|
||||
);
|
||||
final localAuthSuccess = await _localAuthService
|
||||
.authenticateLocalUser("Authenticate to log back in"); //TODO: INTL
|
||||
if (!localAuthSuccess) {
|
||||
emit(const AuthenticationState.requriresLocalAuthentication());
|
||||
_debugPrintMessage(
|
||||
"restoreSessionState",
|
||||
"User could not be authenticated.",
|
||||
);
|
||||
return;
|
||||
}
|
||||
_debugPrintMessage(
|
||||
"restoreSessionState",
|
||||
"User successfully autheticated.",
|
||||
);
|
||||
} else {
|
||||
_debugPrintMessage(
|
||||
"restoreSessionState",
|
||||
"Biometric authentication not configured, skipping.",
|
||||
);
|
||||
}
|
||||
|
||||
_debugPrintMessage(
|
||||
"restoreSessionState",
|
||||
"Trying to retrieve authentication credentials...",
|
||||
);
|
||||
final authentication =
|
||||
await withEncryptedBox<UserCredentials, UserCredentials>(
|
||||
HiveBoxes.localUserCredentials, (box) {
|
||||
@@ -188,14 +227,32 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
|
||||
});
|
||||
|
||||
if (authentication == null) {
|
||||
_debugPrintMessage(
|
||||
"restoreSessionState",
|
||||
"Could not retrieve existing authentication credentials.",
|
||||
);
|
||||
throw Exception(
|
||||
"User should be authenticated but no authentication information was found."); //TODO: INTL
|
||||
"User should be authenticated but no authentication information was found.",
|
||||
); //TODO: INTL
|
||||
}
|
||||
_debugPrintMessage(
|
||||
"restoreSessionState",
|
||||
"Authentication credentials successfully retrieved.",
|
||||
);
|
||||
_debugPrintMessage(
|
||||
"restoreSessionState",
|
||||
"Updating current session state...",
|
||||
);
|
||||
_sessionManager.updateSettings(
|
||||
clientCertificate: authentication.clientCertificate,
|
||||
authToken: authentication.token,
|
||||
baseUrl: localUserAccount.serverUrl,
|
||||
);
|
||||
_debugPrintMessage(
|
||||
"restoreSessionState",
|
||||
"Current session state successfully updated.",
|
||||
);
|
||||
|
||||
final apiVersion = await _getApiVersion(_sessionManager.client);
|
||||
await _updateRemoteUser(
|
||||
_sessionManager,
|
||||
@@ -208,20 +265,41 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
|
||||
localUserId: localUserId,
|
||||
),
|
||||
);
|
||||
_debugPrintMessage(
|
||||
"restoreSessionState",
|
||||
"Session was successfully restored.",
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> logout() async {
|
||||
_debugPrintMessage(
|
||||
"logout",
|
||||
"Trying to log out current user...",
|
||||
);
|
||||
await _resetExternalState();
|
||||
final globalSettings =
|
||||
Hive.box<GlobalSettings>(HiveBoxes.globalSettings).getValue()!;
|
||||
globalSettings.currentLoggedInUser = null;
|
||||
await globalSettings.save();
|
||||
|
||||
emit(const AuthenticationState.unauthenticated());
|
||||
_debugPrintMessage(
|
||||
"logout",
|
||||
"User successfully logged out.",
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _resetExternalState() async {
|
||||
_debugPrintMessage(
|
||||
"_resetExternalState",
|
||||
"Resetting session manager and clearing storage...",
|
||||
);
|
||||
_sessionManager.resetSettings();
|
||||
await HydratedBloc.storage.clear();
|
||||
_debugPrintMessage(
|
||||
"_resetExternalState",
|
||||
"Session manager successfully reset and storage cleared.",
|
||||
);
|
||||
}
|
||||
|
||||
Future<int> _addUser(
|
||||
@@ -232,6 +310,7 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
|
||||
SessionManager sessionManager,
|
||||
) async {
|
||||
assert(credentials.username != null && credentials.password != null);
|
||||
_debugPrintMessage("_addUser", "Adding new user $localUserId...");
|
||||
|
||||
sessionManager.updateSettings(
|
||||
baseUrl: serverUrl,
|
||||
@@ -240,11 +319,21 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
|
||||
|
||||
final authApi = _apiFactory.createAuthenticationApi(sessionManager.client);
|
||||
|
||||
_debugPrintMessage(
|
||||
"_addUser",
|
||||
"Trying to login user ${credentials.username} on $serverUrl...",
|
||||
);
|
||||
|
||||
final token = await authApi.login(
|
||||
username: credentials.username!,
|
||||
password: credentials.password!,
|
||||
);
|
||||
|
||||
_debugPrintMessage(
|
||||
"_addUser",
|
||||
"Successfully acquired token.",
|
||||
);
|
||||
|
||||
sessionManager.updateSettings(
|
||||
baseUrl: serverUrl,
|
||||
clientCertificate: clientCert,
|
||||
@@ -257,17 +346,41 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
|
||||
Hive.box<LocalUserAppState>(HiveBoxes.localUserAppState);
|
||||
|
||||
if (userAccountBox.containsKey(localUserId)) {
|
||||
_debugPrintMessage(
|
||||
"_addUser",
|
||||
"An error occurred! The user $localUserId already exists.",
|
||||
);
|
||||
throw Exception("User already exists!");
|
||||
}
|
||||
final apiVersion = await _getApiVersion(sessionManager.client);
|
||||
|
||||
final serverUser = await _apiFactory
|
||||
.createUserApi(
|
||||
sessionManager.client,
|
||||
apiVersion: apiVersion,
|
||||
)
|
||||
.findCurrentUser();
|
||||
|
||||
_debugPrintMessage(
|
||||
"_addUser",
|
||||
"Trying to fetch user object for $localUserId...",
|
||||
);
|
||||
late UserModel serverUser;
|
||||
try {
|
||||
serverUser = await _apiFactory
|
||||
.createUserApi(
|
||||
sessionManager.client,
|
||||
apiVersion: apiVersion,
|
||||
)
|
||||
.findCurrentUser();
|
||||
} on DioError catch (error, stackTrace) {
|
||||
_debugPrintMessage(
|
||||
"_addUser",
|
||||
"An error occurred: ${error.message}",
|
||||
stackTrace: stackTrace,
|
||||
);
|
||||
rethrow;
|
||||
}
|
||||
_debugPrintMessage(
|
||||
"_addUser",
|
||||
"User object successfully fetched.",
|
||||
);
|
||||
_debugPrintMessage(
|
||||
"_addUser",
|
||||
"Persisting local user account...",
|
||||
);
|
||||
// Create user account
|
||||
await userAccountBox.put(
|
||||
localUserId,
|
||||
@@ -278,15 +391,29 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
|
||||
paperlessUser: serverUser,
|
||||
),
|
||||
);
|
||||
|
||||
_debugPrintMessage(
|
||||
"_addUser",
|
||||
"Local user account successfully persisted.",
|
||||
);
|
||||
_debugPrintMessage(
|
||||
"_addUser",
|
||||
"Persisting user state...",
|
||||
);
|
||||
// Create user state
|
||||
await userStateBox.put(
|
||||
localUserId,
|
||||
LocalUserAppState(userId: localUserId),
|
||||
);
|
||||
|
||||
_debugPrintMessage(
|
||||
"_addUser",
|
||||
"User state successfully persisted.",
|
||||
);
|
||||
// Save credentials in encrypted box
|
||||
await withEncryptedBox(HiveBoxes.localUserCredentials, (box) async {
|
||||
_debugPrintMessage(
|
||||
"_addUser",
|
||||
"Saving user credentials inside encrypted storage...",
|
||||
);
|
||||
await box.put(
|
||||
localUserId,
|
||||
UserCredentials(
|
||||
@@ -294,17 +421,32 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
|
||||
clientCertificate: clientCert,
|
||||
),
|
||||
);
|
||||
_debugPrintMessage(
|
||||
"_addUser",
|
||||
"User credentials successfully saved.",
|
||||
);
|
||||
});
|
||||
final hostsBox = Hive.box<String>(HiveBoxes.hosts);
|
||||
if (!hostsBox.values.contains(serverUrl)) {
|
||||
await hostsBox.add(serverUrl);
|
||||
}
|
||||
|
||||
return serverUser.id;
|
||||
}
|
||||
|
||||
Future<int> _getApiVersion(Dio dio) async {
|
||||
_debugPrintMessage(
|
||||
"_getApiVersion",
|
||||
"Trying to fetch API version...",
|
||||
);
|
||||
final response = await dio.get("/api/");
|
||||
return int.parse(response.headers.value('x-api-version') ?? "3");
|
||||
final apiVersion =
|
||||
int.parse(response.headers.value('x-api-version') ?? "3");
|
||||
_debugPrintMessage(
|
||||
"_getApiVersion",
|
||||
"API version ($apiVersion) successfully retrieved.",
|
||||
);
|
||||
return apiVersion;
|
||||
}
|
||||
|
||||
/// Fetches possibly updated (permissions, name, updated server version and thus new user model, ...) remote user data.
|
||||
@@ -313,13 +455,37 @@ class AuthenticationCubit extends Cubit<AuthenticationState> {
|
||||
LocalUserAccount localUserAccount,
|
||||
int apiVersion,
|
||||
) async {
|
||||
_debugPrintMessage(
|
||||
"_updateRemoteUser",
|
||||
"Updating paperless user object...",
|
||||
);
|
||||
final updatedPaperlessUser = await _apiFactory
|
||||
.createUserApi(
|
||||
sessionManager.client,
|
||||
apiVersion: apiVersion,
|
||||
)
|
||||
.findCurrentUser();
|
||||
|
||||
localUserAccount.paperlessUser = updatedPaperlessUser;
|
||||
await localUserAccount.save();
|
||||
_debugPrintMessage(
|
||||
"_updateRemoteUser",
|
||||
"Paperless user object successfully updated.",
|
||||
);
|
||||
}
|
||||
|
||||
void _debugPrintMessage(
|
||||
String methodName,
|
||||
String message, {
|
||||
Object? error,
|
||||
StackTrace? stackTrace,
|
||||
}) {
|
||||
debugPrint("AuthenticationCubit#$methodName: $message");
|
||||
if (error != null) {
|
||||
debugPrint(error.toString());
|
||||
}
|
||||
if (stackTrace != null) {
|
||||
debugPrintStack(stackTrace: stackTrace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,10 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_form_builder/flutter_form_builder.dart';
|
||||
import 'package:hive_flutter/adapters.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/config/hive/hive_config.dart';
|
||||
import 'package:paperless_mobile/core/database/tables/local_user_account.dart';
|
||||
import 'package:paperless_mobile/core/exception/server_message_exception.dart';
|
||||
import 'package:paperless_mobile/features/login/cubit/authentication_cubit.dart';
|
||||
import 'package:paperless_mobile/features/login/model/client_certificate.dart';
|
||||
import 'package:paperless_mobile/features/login/model/client_certificate_form_model.dart';
|
||||
@@ -147,7 +149,11 @@ class _LoginPageState extends State<LoginPage> {
|
||||
form[ServerAddressFormField.fkServerAddress],
|
||||
clientCert,
|
||||
);
|
||||
} on Exception catch (error) {
|
||||
} on PaperlessServerException catch (error) {
|
||||
showErrorMessage(context, error);
|
||||
} on ServerMessageException catch (error) {
|
||||
showLocalizedError(context, error.message);
|
||||
} catch (error) {
|
||||
showGenericError(context, error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,11 +24,13 @@ mixin DocumentPagingBlocMixin<State extends DocumentPagingState>
|
||||
final newFilter = state.filter.copyWith(page: state.filter.page + 1);
|
||||
try {
|
||||
final result = await api.findAll(newFilter);
|
||||
emit(state.copyWithPaged(
|
||||
hasLoaded: true,
|
||||
filter: newFilter,
|
||||
value: [...state.value, result],
|
||||
));
|
||||
emit(
|
||||
state.copyWithPaged(
|
||||
hasLoaded: true,
|
||||
filter: newFilter,
|
||||
value: [...state.value, result],
|
||||
),
|
||||
);
|
||||
} finally {
|
||||
await onFilterUpdated(newFilter);
|
||||
emit(state.copyWithPaged(isLoading: false));
|
||||
|
||||
170
lib/main.dart
170
lib/main.dart
@@ -14,6 +14,7 @@ import 'package:hydrated_bloc/hydrated_bloc.dart';
|
||||
import 'package:intl/date_symbol_data_local.dart';
|
||||
import 'package:intl/intl_standalone.dart';
|
||||
import 'package:local_auth/local_auth.dart';
|
||||
import 'package:mock_server/mock_server.dart';
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/constants.dart';
|
||||
@@ -22,6 +23,7 @@ import 'package:paperless_mobile/core/config/hive/hive_config.dart';
|
||||
import 'package:paperless_mobile/core/database/tables/global_settings.dart';
|
||||
import 'package:paperless_mobile/core/database/tables/local_user_account.dart';
|
||||
import 'package:paperless_mobile/core/database/tables/local_user_app_state.dart';
|
||||
import 'package:paperless_mobile/core/exception/server_message_exception.dart';
|
||||
import 'package:paperless_mobile/core/factory/paperless_api_factory.dart';
|
||||
import 'package:paperless_mobile/core/factory/paperless_api_factory_impl.dart';
|
||||
import 'package:paperless_mobile/core/interceptor/dio_http_error_interceptor.dart';
|
||||
@@ -41,14 +43,11 @@ import 'package:paperless_mobile/features/login/view/login_page.dart';
|
||||
import 'package:paperless_mobile/features/notifications/services/local_notification_service.dart';
|
||||
import 'package:paperless_mobile/features/settings/view/pages/switching_accounts_page.dart';
|
||||
import 'package:paperless_mobile/features/settings/view/widgets/global_settings_builder.dart';
|
||||
import 'package:paperless_mobile/features/sharing/share_intent_queue.dart';
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||
import 'package:paperless_mobile/helpers/message_helpers.dart';
|
||||
import 'package:paperless_mobile/theme.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:receive_sharing_intent/receive_sharing_intent.dart';
|
||||
import 'package:mock_server/mock_server.dart';
|
||||
|
||||
String get defaultPreferredLocaleSubtag {
|
||||
String preferredLocale = Platform.localeName.split("_").first;
|
||||
@@ -77,95 +76,112 @@ Future<void> _initHive() async {
|
||||
}
|
||||
|
||||
void main() async {
|
||||
Paint.enableDithering = true;
|
||||
if (kDebugMode) {
|
||||
// URL: http://localhost:3131
|
||||
// Login: admin:test
|
||||
await LocalMockApiServer(
|
||||
// RandomDelayGenerator(
|
||||
// const Duration(milliseconds: 100),
|
||||
// const Duration(milliseconds: 800),
|
||||
// ),
|
||||
)
|
||||
.start();
|
||||
}
|
||||
await _initHive();
|
||||
final widgetsBinding = WidgetsFlutterBinding.ensureInitialized();
|
||||
final globalSettingsBox = Hive.box<GlobalSettings>(HiveBoxes.globalSettings);
|
||||
final globalSettings = globalSettingsBox.getValue()!;
|
||||
runZonedGuarded(() async {
|
||||
Paint.enableDithering = true;
|
||||
if (kDebugMode) {
|
||||
// URL: http://localhost:3131
|
||||
// Login: admin:test
|
||||
await LocalMockApiServer(
|
||||
// RandomDelayGenerator(
|
||||
// const Duration(milliseconds: 100),
|
||||
// const Duration(milliseconds: 800),
|
||||
// ),
|
||||
)
|
||||
.start();
|
||||
}
|
||||
await _initHive();
|
||||
final widgetsBinding = WidgetsFlutterBinding.ensureInitialized();
|
||||
final globalSettingsBox =
|
||||
Hive.box<GlobalSettings>(HiveBoxes.globalSettings);
|
||||
final globalSettings = globalSettingsBox.getValue()!;
|
||||
|
||||
await findSystemLocale();
|
||||
packageInfo = await PackageInfo.fromPlatform();
|
||||
if (Platform.isAndroid) {
|
||||
androidInfo = await DeviceInfoPlugin().androidInfo;
|
||||
}
|
||||
if (Platform.isIOS) {
|
||||
iosInfo = await DeviceInfoPlugin().iosInfo;
|
||||
}
|
||||
await findSystemLocale();
|
||||
packageInfo = await PackageInfo.fromPlatform();
|
||||
if (Platform.isAndroid) {
|
||||
androidInfo = await DeviceInfoPlugin().androidInfo;
|
||||
}
|
||||
if (Platform.isIOS) {
|
||||
iosInfo = await DeviceInfoPlugin().iosInfo;
|
||||
}
|
||||
|
||||
final connectivity = Connectivity();
|
||||
final localAuthentication = LocalAuthentication();
|
||||
final connectivityStatusService = ConnectivityStatusServiceImpl(connectivity);
|
||||
final localAuthService = LocalAuthenticationService(localAuthentication);
|
||||
final connectivity = Connectivity();
|
||||
final localAuthentication = LocalAuthentication();
|
||||
final connectivityStatusService =
|
||||
ConnectivityStatusServiceImpl(connectivity);
|
||||
final localAuthService = LocalAuthenticationService(localAuthentication);
|
||||
|
||||
HydratedBloc.storage = await HydratedStorage.build(
|
||||
storageDirectory: await getApplicationDocumentsDirectory(),
|
||||
);
|
||||
HydratedBloc.storage = await HydratedStorage.build(
|
||||
storageDirectory: await getApplicationDocumentsDirectory(),
|
||||
);
|
||||
|
||||
FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);
|
||||
FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);
|
||||
|
||||
final languageHeaderInterceptor = LanguageHeaderInterceptor(
|
||||
globalSettings.preferredLocaleSubtag,
|
||||
);
|
||||
// Manages security context, required for self signed client certificates
|
||||
final sessionManager = SessionManager([
|
||||
DioHttpErrorInterceptor(),
|
||||
languageHeaderInterceptor,
|
||||
]);
|
||||
final languageHeaderInterceptor = LanguageHeaderInterceptor(
|
||||
globalSettings.preferredLocaleSubtag,
|
||||
);
|
||||
// Manages security context, required for self signed client certificates
|
||||
final sessionManager = SessionManager([
|
||||
languageHeaderInterceptor,
|
||||
]);
|
||||
|
||||
// Initialize Blocs/Cubits
|
||||
final connectivityCubit = ConnectivityCubit(connectivityStatusService);
|
||||
// Initialize Blocs/Cubits
|
||||
final connectivityCubit = ConnectivityCubit(connectivityStatusService);
|
||||
|
||||
// Load application settings and stored authentication data
|
||||
await connectivityCubit.initialize();
|
||||
// Load application settings and stored authentication data
|
||||
await connectivityCubit.initialize();
|
||||
|
||||
final localNotificationService = LocalNotificationService();
|
||||
await localNotificationService.initialize();
|
||||
final localNotificationService = LocalNotificationService();
|
||||
await localNotificationService.initialize();
|
||||
|
||||
//Update language header in interceptor on language change.
|
||||
globalSettingsBox.listenable().addListener(() {
|
||||
languageHeaderInterceptor.preferredLocaleSubtag =
|
||||
globalSettings.preferredLocaleSubtag;
|
||||
});
|
||||
//Update language header in interceptor on language change.
|
||||
globalSettingsBox.listenable().addListener(() {
|
||||
languageHeaderInterceptor.preferredLocaleSubtag =
|
||||
globalSettings.preferredLocaleSubtag;
|
||||
});
|
||||
|
||||
final apiFactory = PaperlessApiFactoryImpl(sessionManager);
|
||||
final apiFactory = PaperlessApiFactoryImpl(sessionManager);
|
||||
|
||||
runApp(
|
||||
MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProvider.value(value: sessionManager),
|
||||
Provider<LocalAuthenticationService>.value(value: localAuthService),
|
||||
Provider<Connectivity>.value(value: connectivity),
|
||||
Provider<ConnectivityStatusService>.value(
|
||||
value: connectivityStatusService),
|
||||
Provider<LocalNotificationService>.value(
|
||||
value: localNotificationService),
|
||||
Provider.value(value: DocumentChangedNotifier()),
|
||||
],
|
||||
child: MultiBlocProvider(
|
||||
runApp(
|
||||
MultiProvider(
|
||||
providers: [
|
||||
BlocProvider<ConnectivityCubit>.value(value: connectivityCubit),
|
||||
BlocProvider(
|
||||
create: (context) => AuthenticationCubit(
|
||||
localAuthService, apiFactory, sessionManager),
|
||||
)
|
||||
ChangeNotifierProvider.value(value: sessionManager),
|
||||
Provider<LocalAuthenticationService>.value(value: localAuthService),
|
||||
Provider<Connectivity>.value(value: connectivity),
|
||||
Provider<ConnectivityStatusService>.value(
|
||||
value: connectivityStatusService),
|
||||
Provider<LocalNotificationService>.value(
|
||||
value: localNotificationService),
|
||||
Provider.value(value: DocumentChangedNotifier()),
|
||||
],
|
||||
child: PaperlessMobileEntrypoint(
|
||||
paperlessProviderFactory: apiFactory,
|
||||
child: MultiBlocProvider(
|
||||
providers: [
|
||||
BlocProvider<ConnectivityCubit>.value(value: connectivityCubit),
|
||||
BlocProvider(
|
||||
create: (context) => AuthenticationCubit(
|
||||
localAuthService, apiFactory, sessionManager),
|
||||
),
|
||||
],
|
||||
child: PaperlessMobileEntrypoint(
|
||||
paperlessProviderFactory: apiFactory,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
);
|
||||
}, (error, stack) {
|
||||
String message = switch (error) {
|
||||
PaperlessServerException e => e.details ?? error.toString(),
|
||||
ServerMessageException e => e.message,
|
||||
_ => error.toString()
|
||||
};
|
||||
debugPrint("An unepxected exception has occured!");
|
||||
debugPrint(message);
|
||||
debugPrintStack(stackTrace: stack);
|
||||
// if (_rootScaffoldKey.currentContext != null) {
|
||||
// ScaffoldMessenger.maybeOf(_rootScaffoldKey.currentContext!)
|
||||
// ?..hideCurrentSnackBar()
|
||||
// ..showSnackBar(SnackBar(content: Text(message)));
|
||||
// }
|
||||
});
|
||||
}
|
||||
|
||||
class PaperlessMobileEntrypoint extends StatefulWidget {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:paperless_api/src/models/paperless_server_exception.dart';
|
||||
import 'package:paperless_api/src/modules/authentication_api/authentication_api.dart';
|
||||
|
||||
|
||||
Reference in New Issue
Block a user