add proper logging

This commit is contained in:
shenlong-tanwen
2024-08-21 23:43:48 +05:30
parent 1631df70e9
commit 75448ce56b
37 changed files with 923 additions and 224 deletions
@@ -0,0 +1,6 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:immich_mobile/domain/models/user.model.dart';
class CurrentUserCubit extends Cubit<User> {
CurrentUserCubit(super.initialState);
}
@@ -4,43 +4,51 @@ import 'package:flutter/material.dart';
class LoginPageState {
final bool isServerValidated;
final bool isValidationInProgress;
final bool isLoginSuccessful;
const LoginPageState({
required this.isServerValidated,
required this.isValidationInProgress,
required this.isLoginSuccessful,
});
factory LoginPageState.reset() {
return const LoginPageState(
isServerValidated: false,
isValidationInProgress: false,
isLoginSuccessful: false,
);
}
LoginPageState copyWith({
bool? isServerValidated,
bool? isValidationInProgress,
bool? isLoginSuccessful,
}) {
return LoginPageState(
isServerValidated: isServerValidated ?? this.isServerValidated,
isValidationInProgress:
isValidationInProgress ?? this.isValidationInProgress,
isLoginSuccessful: isLoginSuccessful ?? this.isLoginSuccessful,
);
}
@override
String toString() =>
'LoginPageState(isServerValidated: $isServerValidated, isValidationInProgress: $isValidationInProgress)';
'LoginPageState(isServerValidated: $isServerValidated, isValidationInProgress: $isValidationInProgress, isLoginSuccessful: $isLoginSuccessful)';
@override
bool operator ==(covariant LoginPageState other) {
if (identical(this, other)) return true;
return other.isServerValidated == isServerValidated &&
other.isValidationInProgress == isValidationInProgress;
other.isValidationInProgress == isValidationInProgress &&
other.isLoginSuccessful == isLoginSuccessful;
}
@override
int get hashCode =>
isServerValidated.hashCode ^ isValidationInProgress.hashCode;
isServerValidated.hashCode ^
isValidationInProgress.hashCode ^
isLoginSuccessful.hashCode;
}
@@ -152,13 +152,20 @@ class _LoginPageState extends State<LoginPage>
);
}
return Scaffold(
resizeToAvoidBottomInset: false,
appBar: appBar,
body: SafeArea(
child: ImAdaptiveScaffoldBody(
primaryBody: (_) => primaryBody,
secondaryBody: (_) => secondaryBody,
return BlocListener<LoginPageCubit, LoginPageState>(
listener: (_, loginState) {
if (loginState.isLoginSuccessful) {
context.replaceRoute(const TabControllerRoute());
}
},
child: Scaffold(
resizeToAvoidBottomInset: false,
appBar: appBar,
body: SafeArea(
child: ImAdaptiveScaffoldBody(
primaryBody: (_) => primaryBody,
secondaryBody: (_) => secondaryBody,
),
),
),
);
@@ -1,15 +1,20 @@
import 'dart:async';
import 'package:collection/collection.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:immich_mobile/domain/interfaces/store.interface.dart';
import 'package:immich_mobile/domain/interfaces/user.interface.dart';
import 'package:immich_mobile/domain/models/store.model.dart';
import 'package:immich_mobile/domain/services/login.service.dart';
import 'package:immich_mobile/domain/store_manager.dart';
import 'package:immich_mobile/domain/services/user.service.dart';
import 'package:immich_mobile/i18n/strings.g.dart';
import 'package:immich_mobile/presentation/modules/common/states/server_info/server_feature_config.state.dart';
import 'package:immich_mobile/presentation/modules/login/models/login_page.model.dart';
import 'package:immich_mobile/service_locator.dart';
import 'package:immich_mobile/utils/immich_auth_interceptor.dart';
import 'package:immich_mobile/utils/mixins/log_context.mixin.dart';
import 'package:immich_mobile/utils/snackbar_manager.dart';
import 'package:openapi/openapi.dart';
class LoginPageCubit extends Cubit<LoginPageState> with LogContext {
LoginPageCubit() : super(LoginPageState.reset());
@@ -60,8 +65,8 @@ class LoginPageCubit extends Cubit<LoginPageState> with LogContext {
// Check for /.well-known/immich
url = await loginService.resolveEndpoint(uri);
di<StoreManager>().put(StoreKey.serverEndpoint, url);
ServiceLocator.registerPostValidationServices(url);
di<IStoreRepository>().set(StoreKey.serverEndpoint, url);
await ServiceLocator.registerPostValidationServices(url);
// Fetch server features
await di<ServerFeatureConfigCubit>().getFeatures();
@@ -76,15 +81,64 @@ class LoginPageCubit extends Cubit<LoginPageState> with LogContext {
required String email,
required String password,
}) async {
emit(state.copyWith(isValidationInProgress: true));
try {
emit(state.copyWith(isValidationInProgress: true));
final accessToken =
await di<LoginService>().passwordLogin(email, password);
final url = di<StoreManager>().get(StoreKey.serverEndpoint);
if (accessToken == null) {
SnackbarManager.showError(t.login.error.error_login);
return;
}
await _postLogin(accessToken);
} finally {
emit(state.copyWith(isValidationInProgress: false));
}
}
Future<void> oAuthLogin() async {
emit(state.copyWith(isValidationInProgress: true));
try {
emit(state.copyWith(isValidationInProgress: true));
final url = di<StoreManager>().get(StoreKey.serverEndpoint);
final accessToken = await di<LoginService>().oAuthLogin();
if (accessToken == null) {
SnackbarManager.showError(t.login.error.error_login_oauth);
return;
}
await _postLogin(accessToken);
} finally {
emit(state.copyWith(isValidationInProgress: false));
}
}
Future<void> _postLogin(String accessToken) async {
await di<IStoreRepository>().set(StoreKey.accessToken, accessToken);
/// Set token to interceptor
final interceptor = di<Openapi>()
.dio
.interceptors
.firstWhereOrNull((i) => i is ImmichAuthInterceptor)
as ImmichAuthInterceptor?;
interceptor?.setAccessToken(accessToken);
final user = await di<UserService>().getMyUser();
if (user == null) {
SnackbarManager.showError(t.login.error.error_login);
return;
}
// Register user
ServiceLocator.registerCurrentUser(user);
await di<IUserRepository>().insertUser(user);
emit(state.copyWith(
isValidationInProgress: false,
isServerValidated: true,
));
}
void resetServerValidation() {
@@ -5,7 +5,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:immich_mobile/domain/models/server-info/server_feature_config.model.dart';
import 'package:immich_mobile/i18n/strings.g.dart';
import 'package:immich_mobile/presentation/components/common/gap.widget.dart';
import 'package:immich_mobile/presentation/components/common/loading_indaticator.widget.dart';
import 'package:immich_mobile/presentation/components/common/loading_indicator.widget.dart';
import 'package:immich_mobile/presentation/components/input/filled_button.widget.dart';
import 'package:immich_mobile/presentation/components/input/password_form_field.widget.dart';
import 'package:immich_mobile/presentation/components/input/text_button.widget.dart';
@@ -132,6 +132,7 @@ class _CredentialsPageState extends State<_CredentialsPage> {
children: [
if (state.features.hasPasswordLogin) ...[
ImTextFormField(
controller: widget.emailController,
label: context.t.login.label.email,
isDisabled: isValidationInProgress,
textInputAction: TextInputAction.next,
@@ -139,6 +140,7 @@ class _CredentialsPageState extends State<_CredentialsPage> {
),
const SizedGap.mh(),
ImPasswordFormField(
controller: widget.passwordController,
label: context.t.login.label.password,
focusNode: passwordFocusNode,
isDisabled: isValidationInProgress,
@@ -148,11 +150,12 @@ class _CredentialsPageState extends State<_CredentialsPage> {
ImFilledButton(
label: context.t.login.label.login_button,
icon: Symbols.login_rounded,
onPressed: () =>
context.read<LoginPageCubit>().passwordLogin(
email: widget.emailController.text,
password: widget.passwordController.text,
),
onPressed: () => unawaited(
context.read<LoginPageCubit>().passwordLogin(
email: widget.emailController.text,
password: widget.passwordController.text,
),
),
),
// Divider when both password and oAuth login is enabled
if (state.features.hasOAuthLogin) const Divider(),