Compare commits
3 Commits
edf067369d
...
5387d7b7a6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5387d7b7a6 | ||
|
|
f138e1dcc9 | ||
|
|
e1bde24a83 |
36
lib/application/auth/logout_form/logout_form_bloc.dart
Normal file
36
lib/application/auth/logout_form/logout_form_bloc.dart
Normal file
@ -0,0 +1,36 @@
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:injectable/injectable.dart';
|
||||
|
||||
import '../../../domain/auth/auth.dart';
|
||||
|
||||
part 'logout_form_event.dart';
|
||||
part 'logout_form_state.dart';
|
||||
part 'logout_form_bloc.freezed.dart';
|
||||
|
||||
@injectable
|
||||
class LogoutFormBloc extends Bloc<LogoutFormEvent, LogoutFormState> {
|
||||
final IAuthRepository _repository;
|
||||
LogoutFormBloc(this._repository) : super(LogoutFormState.initial()) {
|
||||
on<LogoutFormEvent>(_onLogoutFormEvent);
|
||||
}
|
||||
|
||||
Future<void> _onLogoutFormEvent(
|
||||
LogoutFormEvent event,
|
||||
Emitter<LogoutFormState> emit,
|
||||
) {
|
||||
return event.map(
|
||||
submitted: (e) async {
|
||||
emit(state.copyWith(isSubmitting: true, failureOrAuthOption: none()));
|
||||
final failureOrAuth = await _repository.logout();
|
||||
emit(
|
||||
state.copyWith(
|
||||
isSubmitting: false,
|
||||
failureOrAuthOption: optionOf(failureOrAuth),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
335
lib/application/auth/logout_form/logout_form_bloc.freezed.dart
Normal file
335
lib/application/auth/logout_form/logout_form_bloc.freezed.dart
Normal file
@ -0,0 +1,335 @@
|
||||
// coverage:ignore-file
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of 'logout_form_bloc.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
final _privateConstructorUsedError = UnsupportedError(
|
||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models',
|
||||
);
|
||||
|
||||
/// @nodoc
|
||||
mixin _$LogoutFormEvent {
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() submitted,
|
||||
}) => throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>({
|
||||
TResult? Function()? submitted,
|
||||
}) => throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? submitted,
|
||||
required TResult orElse(),
|
||||
}) => throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(_Submitted value) submitted,
|
||||
}) => throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>({
|
||||
TResult? Function(_Submitted value)? submitted,
|
||||
}) => throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(_Submitted value)? submitted,
|
||||
required TResult orElse(),
|
||||
}) => throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $LogoutFormEventCopyWith<$Res> {
|
||||
factory $LogoutFormEventCopyWith(
|
||||
LogoutFormEvent value,
|
||||
$Res Function(LogoutFormEvent) then,
|
||||
) = _$LogoutFormEventCopyWithImpl<$Res, LogoutFormEvent>;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$LogoutFormEventCopyWithImpl<$Res, $Val extends LogoutFormEvent>
|
||||
implements $LogoutFormEventCopyWith<$Res> {
|
||||
_$LogoutFormEventCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
/// Create a copy of LogoutFormEvent
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$SubmittedImplCopyWith<$Res> {
|
||||
factory _$$SubmittedImplCopyWith(
|
||||
_$SubmittedImpl value,
|
||||
$Res Function(_$SubmittedImpl) then,
|
||||
) = __$$SubmittedImplCopyWithImpl<$Res>;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$SubmittedImplCopyWithImpl<$Res>
|
||||
extends _$LogoutFormEventCopyWithImpl<$Res, _$SubmittedImpl>
|
||||
implements _$$SubmittedImplCopyWith<$Res> {
|
||||
__$$SubmittedImplCopyWithImpl(
|
||||
_$SubmittedImpl _value,
|
||||
$Res Function(_$SubmittedImpl) _then,
|
||||
) : super(_value, _then);
|
||||
|
||||
/// Create a copy of LogoutFormEvent
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$SubmittedImpl implements _Submitted {
|
||||
const _$SubmittedImpl();
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'LogoutFormEvent.submitted()';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType && other is _$SubmittedImpl);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => runtimeType.hashCode;
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() submitted,
|
||||
}) {
|
||||
return submitted();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>({
|
||||
TResult? Function()? submitted,
|
||||
}) {
|
||||
return submitted?.call();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? submitted,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (submitted != null) {
|
||||
return submitted();
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(_Submitted value) submitted,
|
||||
}) {
|
||||
return submitted(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>({
|
||||
TResult? Function(_Submitted value)? submitted,
|
||||
}) {
|
||||
return submitted?.call(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(_Submitted value)? submitted,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (submitted != null) {
|
||||
return submitted(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _Submitted implements LogoutFormEvent {
|
||||
const factory _Submitted() = _$SubmittedImpl;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$LogoutFormState {
|
||||
Option<Either<AuthFailure, Unit>> get failureOrAuthOption =>
|
||||
throw _privateConstructorUsedError;
|
||||
bool get isSubmitting => throw _privateConstructorUsedError;
|
||||
|
||||
/// Create a copy of LogoutFormState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
$LogoutFormStateCopyWith<LogoutFormState> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $LogoutFormStateCopyWith<$Res> {
|
||||
factory $LogoutFormStateCopyWith(
|
||||
LogoutFormState value,
|
||||
$Res Function(LogoutFormState) then,
|
||||
) = _$LogoutFormStateCopyWithImpl<$Res, LogoutFormState>;
|
||||
@useResult
|
||||
$Res call({
|
||||
Option<Either<AuthFailure, Unit>> failureOrAuthOption,
|
||||
bool isSubmitting,
|
||||
});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$LogoutFormStateCopyWithImpl<$Res, $Val extends LogoutFormState>
|
||||
implements $LogoutFormStateCopyWith<$Res> {
|
||||
_$LogoutFormStateCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
/// Create a copy of LogoutFormState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({Object? failureOrAuthOption = null, Object? isSubmitting = null}) {
|
||||
return _then(
|
||||
_value.copyWith(
|
||||
failureOrAuthOption: null == failureOrAuthOption
|
||||
? _value.failureOrAuthOption
|
||||
: failureOrAuthOption // ignore: cast_nullable_to_non_nullable
|
||||
as Option<Either<AuthFailure, Unit>>,
|
||||
isSubmitting: null == isSubmitting
|
||||
? _value.isSubmitting
|
||||
: isSubmitting // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
)
|
||||
as $Val,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$LogoutFormStateImplCopyWith<$Res>
|
||||
implements $LogoutFormStateCopyWith<$Res> {
|
||||
factory _$$LogoutFormStateImplCopyWith(
|
||||
_$LogoutFormStateImpl value,
|
||||
$Res Function(_$LogoutFormStateImpl) then,
|
||||
) = __$$LogoutFormStateImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call({
|
||||
Option<Either<AuthFailure, Unit>> failureOrAuthOption,
|
||||
bool isSubmitting,
|
||||
});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$LogoutFormStateImplCopyWithImpl<$Res>
|
||||
extends _$LogoutFormStateCopyWithImpl<$Res, _$LogoutFormStateImpl>
|
||||
implements _$$LogoutFormStateImplCopyWith<$Res> {
|
||||
__$$LogoutFormStateImplCopyWithImpl(
|
||||
_$LogoutFormStateImpl _value,
|
||||
$Res Function(_$LogoutFormStateImpl) _then,
|
||||
) : super(_value, _then);
|
||||
|
||||
/// Create a copy of LogoutFormState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({Object? failureOrAuthOption = null, Object? isSubmitting = null}) {
|
||||
return _then(
|
||||
_$LogoutFormStateImpl(
|
||||
failureOrAuthOption: null == failureOrAuthOption
|
||||
? _value.failureOrAuthOption
|
||||
: failureOrAuthOption // ignore: cast_nullable_to_non_nullable
|
||||
as Option<Either<AuthFailure, Unit>>,
|
||||
isSubmitting: null == isSubmitting
|
||||
? _value.isSubmitting
|
||||
: isSubmitting // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$LogoutFormStateImpl implements _LogoutFormState {
|
||||
const _$LogoutFormStateImpl({
|
||||
required this.failureOrAuthOption,
|
||||
this.isSubmitting = false,
|
||||
});
|
||||
|
||||
@override
|
||||
final Option<Either<AuthFailure, Unit>> failureOrAuthOption;
|
||||
@override
|
||||
@JsonKey()
|
||||
final bool isSubmitting;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'LogoutFormState(failureOrAuthOption: $failureOrAuthOption, isSubmitting: $isSubmitting)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$LogoutFormStateImpl &&
|
||||
(identical(other.failureOrAuthOption, failureOrAuthOption) ||
|
||||
other.failureOrAuthOption == failureOrAuthOption) &&
|
||||
(identical(other.isSubmitting, isSubmitting) ||
|
||||
other.isSubmitting == isSubmitting));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
Object.hash(runtimeType, failureOrAuthOption, isSubmitting);
|
||||
|
||||
/// Create a copy of LogoutFormState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$LogoutFormStateImplCopyWith<_$LogoutFormStateImpl> get copyWith =>
|
||||
__$$LogoutFormStateImplCopyWithImpl<_$LogoutFormStateImpl>(
|
||||
this,
|
||||
_$identity,
|
||||
);
|
||||
}
|
||||
|
||||
abstract class _LogoutFormState implements LogoutFormState {
|
||||
const factory _LogoutFormState({
|
||||
required final Option<Either<AuthFailure, Unit>> failureOrAuthOption,
|
||||
final bool isSubmitting,
|
||||
}) = _$LogoutFormStateImpl;
|
||||
|
||||
@override
|
||||
Option<Either<AuthFailure, Unit>> get failureOrAuthOption;
|
||||
@override
|
||||
bool get isSubmitting;
|
||||
|
||||
/// Create a copy of LogoutFormState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
_$$LogoutFormStateImplCopyWith<_$LogoutFormStateImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
6
lib/application/auth/logout_form/logout_form_event.dart
Normal file
6
lib/application/auth/logout_form/logout_form_event.dart
Normal file
@ -0,0 +1,6 @@
|
||||
part of 'logout_form_bloc.dart';
|
||||
|
||||
@freezed
|
||||
class LogoutFormEvent with _$LogoutFormEvent {
|
||||
const factory LogoutFormEvent.submitted() = _Submitted;
|
||||
}
|
||||
12
lib/application/auth/logout_form/logout_form_state.dart
Normal file
12
lib/application/auth/logout_form/logout_form_state.dart
Normal file
@ -0,0 +1,12 @@
|
||||
part of 'logout_form_bloc.dart';
|
||||
|
||||
@freezed
|
||||
class LogoutFormState with _$LogoutFormState {
|
||||
const factory LogoutFormState({
|
||||
required Option<Either<AuthFailure, Unit>> failureOrAuthOption,
|
||||
@Default(false) bool isSubmitting,
|
||||
}) = _LogoutFormState;
|
||||
|
||||
factory LogoutFormState.initial() =>
|
||||
LogoutFormState(failureOrAuthOption: none(), isSubmitting: false);
|
||||
}
|
||||
@ -2,8 +2,10 @@ import 'package:awesome_dio_interceptor/awesome_dio_interceptor.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:injectable/injectable.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import '../../env.dart';
|
||||
import '../constant/local_storage_key.dart';
|
||||
import 'api_failure.dart';
|
||||
import 'errors/bad_network_error.dart';
|
||||
import 'errors/bad_request_error.dart';
|
||||
@ -22,11 +24,16 @@ import 'interceptors/unauthorized_interceptor.dart';
|
||||
class ApiClient {
|
||||
final Dio _dio;
|
||||
final Env _env;
|
||||
final SharedPreferences _preferences;
|
||||
|
||||
ApiClient(this._dio, this._env) {
|
||||
ApiClient(this._dio, this._env, this._preferences) {
|
||||
_dio.options.baseUrl = _env.baseUrl;
|
||||
_dio.options.validateStatus = (status) => status! < 500;
|
||||
_dio.options.connectTimeout = const Duration(seconds: 20);
|
||||
_dio.options.headers = {
|
||||
'authorization':
|
||||
'Bearer ${_preferences.getString(LocalStorageKey.token)}',
|
||||
};
|
||||
_dio.interceptors.add(BadNetworkErrorInterceptor());
|
||||
_dio.interceptors.add(BadRequestErrorInterceptor());
|
||||
_dio.interceptors.add(InternalServerErrorInterceptor());
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
class ApiPath {
|
||||
// Auth
|
||||
static const String login = '/api/v1/auth/login';
|
||||
static const String logout = '/api/v1/auth/logout';
|
||||
}
|
||||
|
||||
@ -7,4 +7,5 @@ abstract class IAuthRepository {
|
||||
});
|
||||
Future<bool> hasToken();
|
||||
Future<Either<AuthFailure, User>> currentUser();
|
||||
Future<Either<AuthFailure, Unit>> logout();
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:injectable/injectable.dart';
|
||||
import 'package:data_channel/data_channel.dart';
|
||||
|
||||
@ -41,4 +42,14 @@ class AuthRemoteDataProvider {
|
||||
return DC.error(AuthFailure.serverError(e));
|
||||
}
|
||||
}
|
||||
|
||||
Future<DC<AuthFailure, Unit>> logout() async {
|
||||
try {
|
||||
await _apiClient.post(ApiPath.logout);
|
||||
return DC.data(unit);
|
||||
} on ApiFailure catch (e, s) {
|
||||
log('login', name: _logName, error: e, stackTrace: s);
|
||||
return DC.error(AuthFailure.serverError(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,4 +58,20 @@ class AuthRepository implements IAuthRepository {
|
||||
Future<bool> hasToken() async {
|
||||
return await _localDataProvider.hasToken();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<AuthFailure, Unit>> logout() async {
|
||||
try {
|
||||
final result = await _remoteDataProvider.logout();
|
||||
if (result.hasError) {
|
||||
return left(result.error!);
|
||||
}
|
||||
|
||||
await _localDataProvider.deleteAllAuth();
|
||||
return right(unit);
|
||||
} catch (e, s) {
|
||||
log('logoutError', name: _logName, error: e, stackTrace: s);
|
||||
return left(const AuthFailure.unexpectedError());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,6 +12,8 @@
|
||||
import 'package:apskel_owner_flutter/application/auth/auth_bloc.dart' as _i945;
|
||||
import 'package:apskel_owner_flutter/application/auth/login_form/login_form_bloc.dart'
|
||||
as _i775;
|
||||
import 'package:apskel_owner_flutter/application/auth/logout_form/logout_form_bloc.dart'
|
||||
as _i574;
|
||||
import 'package:apskel_owner_flutter/application/language/language_bloc.dart'
|
||||
as _i455;
|
||||
import 'package:apskel_owner_flutter/common/api/api_client.dart' as _i115;
|
||||
@ -76,10 +78,14 @@ extension GetItInjectableX on _i174.GetIt {
|
||||
gh.factory<_i991.AuthLocalDataProvider>(
|
||||
() => _i991.AuthLocalDataProvider(gh<_i460.SharedPreferences>()),
|
||||
);
|
||||
gh.lazySingleton<_i115.ApiClient>(
|
||||
() => _i115.ApiClient(gh<_i361.Dio>(), gh<_i6.Env>()),
|
||||
);
|
||||
gh.factory<_i6.Env>(() => _i6.ProdEnv(), registerFor: {_prod});
|
||||
gh.lazySingleton<_i115.ApiClient>(
|
||||
() => _i115.ApiClient(
|
||||
gh<_i361.Dio>(),
|
||||
gh<_i6.Env>(),
|
||||
gh<_i460.SharedPreferences>(),
|
||||
),
|
||||
);
|
||||
gh.factory<_i17.AuthRemoteDataProvider>(
|
||||
() => _i17.AuthRemoteDataProvider(gh<_i115.ApiClient>()),
|
||||
);
|
||||
@ -95,6 +101,9 @@ extension GetItInjectableX on _i174.GetIt {
|
||||
gh.factory<_i945.AuthBloc>(
|
||||
() => _i945.AuthBloc(gh<_i49.IAuthRepository>()),
|
||||
);
|
||||
gh.factory<_i574.LogoutFormBloc>(
|
||||
() => _i574.LogoutFormBloc(gh<_i49.IAuthRepository>()),
|
||||
);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:loader_overlay/loader_overlay.dart';
|
||||
|
||||
import '../application/auth/auth_bloc.dart';
|
||||
import '../application/language/language_bloc.dart';
|
||||
@ -7,6 +8,7 @@ import '../common/theme/theme.dart';
|
||||
import '../common/constant/app_constant.dart';
|
||||
import '../injection.dart';
|
||||
import '../l10n/app_localizations.dart';
|
||||
import 'components/loading/loading_overlay.dart';
|
||||
import 'router/app_router.dart';
|
||||
import 'router/app_router_observer.dart';
|
||||
|
||||
@ -27,6 +29,10 @@ class _AppWidgetState extends State<AppWidget> {
|
||||
BlocProvider(create: (context) => getIt<LanguageBloc>()),
|
||||
BlocProvider(create: (context) => getIt<AuthBloc>()),
|
||||
],
|
||||
child: GlobalLoaderOverlay(
|
||||
useDefaultLoading: false,
|
||||
overlayWidgetBuilder: (progress) => LoadingOverlay(),
|
||||
overlayColor: AppColor.black.withOpacity(0.35),
|
||||
child: BlocBuilder<LanguageBloc, LanguageState>(
|
||||
builder: (context, state) {
|
||||
return MaterialApp.router(
|
||||
@ -37,11 +43,14 @@ class _AppWidgetState extends State<AppWidget> {
|
||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||
theme: ThemeApp.theme,
|
||||
routerConfig: _appRouter.config(
|
||||
navigatorObservers: () => <NavigatorObserver>[AppRouteObserver()],
|
||||
navigatorObservers: () => <NavigatorObserver>[
|
||||
AppRouteObserver(),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
23
lib/presentation/components/loading/loading_overlay.dart
Normal file
23
lib/presentation/components/loading/loading_overlay.dart
Normal file
@ -0,0 +1,23 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_spinkit/flutter_spinkit.dart';
|
||||
|
||||
import '../../../common/theme/theme.dart';
|
||||
|
||||
class LoadingOverlay extends StatelessWidget {
|
||||
const LoadingOverlay({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Center(
|
||||
child: Container(
|
||||
width: 64,
|
||||
height: 64,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.white,
|
||||
borderRadius: BorderRadius.circular(AppValue.radius),
|
||||
),
|
||||
child: SpinKitCircle(color: AppColor.primary, size: 32.0),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'dart:math' as math;
|
||||
|
||||
import '../../../../application/auth/auth_bloc.dart';
|
||||
import '../../../../application/auth/login_form/login_form_bloc.dart';
|
||||
import '../../../../common/extension/extension.dart';
|
||||
import '../../../../common/theme/theme.dart';
|
||||
@ -108,6 +109,7 @@ class _LoginPageState extends State<LoginPage> with TickerProviderStateMixin {
|
||||
(f) => AppFlushbar.showAuthFailureToast(context, f),
|
||||
(user) {
|
||||
if (context.mounted) {
|
||||
context.read<AuthBloc>().add(AuthEvent.fetchCurrentUser());
|
||||
context.router.replace(const MainRoute());
|
||||
}
|
||||
},
|
||||
|
||||
@ -1,10 +1,16 @@
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:line_icons/line_icons.dart';
|
||||
import 'package:loader_overlay/loader_overlay.dart';
|
||||
|
||||
import '../../../application/auth/logout_form/logout_form_bloc.dart';
|
||||
import '../../../common/theme/theme.dart';
|
||||
import '../../../injection.dart';
|
||||
import '../../components/button/button.dart';
|
||||
import '../../components/spacer/spacer.dart';
|
||||
import '../../components/toast/flushbar.dart';
|
||||
import '../../router/app_router.gr.dart';
|
||||
import 'widgets/account_info.dart';
|
||||
import 'widgets/app_setting.dart';
|
||||
import 'widgets/business_setting.dart';
|
||||
@ -13,17 +19,37 @@ import 'widgets/header.dart';
|
||||
import 'widgets/support.dart';
|
||||
|
||||
@RoutePage()
|
||||
class ProfilePage extends StatefulWidget {
|
||||
class ProfilePage extends StatelessWidget implements AutoRouteWrapper {
|
||||
const ProfilePage({super.key});
|
||||
|
||||
@override
|
||||
State<ProfilePage> createState() => _ProfilePageState();
|
||||
}
|
||||
|
||||
class _ProfilePageState extends State<ProfilePage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
return MultiBlocListener(
|
||||
listeners: [
|
||||
BlocListener<LogoutFormBloc, LogoutFormState>(
|
||||
listener: (context, state) {
|
||||
state.failureOrAuthOption.fold(
|
||||
() => null,
|
||||
(either) => either.fold(
|
||||
(f) => AppFlushbar.showAuthFailureToast(context, f),
|
||||
(_) => context.router.replace(const LoginRoute()),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
BlocListener<LogoutFormBloc, LogoutFormState>(
|
||||
listenWhen: (previous, current) =>
|
||||
previous.isSubmitting != current.isSubmitting,
|
||||
listener: (context, state) {
|
||||
if (state.isSubmitting) {
|
||||
context.loaderOverlay.show();
|
||||
} else {
|
||||
context.loaderOverlay.hide();
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
child: Scaffold(
|
||||
backgroundColor: AppColor.background,
|
||||
body: CustomScrollView(
|
||||
slivers: [
|
||||
@ -95,6 +121,11 @@ class _ProfilePageState extends State<ProfilePage> {
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget wrappedRoute(BuildContext context) =>
|
||||
BlocProvider(create: (_) => getIt<LogoutFormBloc>(), child: this);
|
||||
}
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
import '../../../../application/auth/logout_form/logout_form_bloc.dart';
|
||||
import '../../../../common/theme/theme.dart';
|
||||
import '../../../components/spacer/spacer.dart';
|
||||
import 'profile_tile.dart';
|
||||
@ -49,7 +51,9 @@ class ProfileDangerZone extends StatelessWidget {
|
||||
subtitle: 'Sign out from your account',
|
||||
iconColor: AppColor.error,
|
||||
textColor: AppColor.error,
|
||||
onTap: () {},
|
||||
onTap: () {
|
||||
context.read<LogoutFormBloc>().add(LogoutFormEvent.submitted());
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
16
pubspec.lock
16
pubspec.lock
@ -73,6 +73,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
back_button_interceptor:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: back_button_interceptor
|
||||
sha256: b85977faabf4aeb95164b3b8bf81784bed4c54ea1aef90a036ab6927ecf80c5a
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.0.4"
|
||||
bloc:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -741,6 +749,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.1.1"
|
||||
loader_overlay:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: loader_overlay
|
||||
sha256: "285c9ccab9a42a392ba948bd0b14376fd0ee9ddd7b63e3018bcd54460fd3e021"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.0.0"
|
||||
logging:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@ -39,6 +39,7 @@ dependencies:
|
||||
image_picker: ^1.1.2
|
||||
table_calendar: ^3.2.0
|
||||
package_info_plus: ^8.3.1
|
||||
loader_overlay: ^5.0.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user