refactor(legacy-account): migrate account_settings to AsyncNotifier
This commit is contained in:
@@ -1,12 +1,13 @@
|
|||||||
import 'package:account/src/features/account_settings/presentation/state/account_settings_view_model.dart';
|
import 'package:account/src/features/account_settings/presentation/providers/account_settings_controller.dart';
|
||||||
import 'package:legacy_theme/legacy_theme.dart';
|
|
||||||
import 'package:design_system/design_system.dart';
|
import 'package:design_system/design_system.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:legacy_theme/legacy_theme.dart';
|
||||||
import 'package:legacy_ui/legacy_ui.dart';
|
import 'package:legacy_ui/legacy_ui.dart';
|
||||||
import 'package:sf_shared/sf_shared.dart';
|
|
||||||
import 'package:navigation/navigation.dart';
|
import 'package:navigation/navigation.dart';
|
||||||
|
import 'package:sf_infrastructure/sf_infrastructure.dart';
|
||||||
import 'package:sf_localizations/sf_localizations.dart';
|
import 'package:sf_localizations/sf_localizations.dart';
|
||||||
|
import 'package:sf_shared/sf_shared.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
import 'package:utils/utils.dart';
|
import 'package:utils/utils.dart';
|
||||||
|
|
||||||
@@ -14,7 +15,7 @@ import 'widgets/reg_code_dialog.dart';
|
|||||||
|
|
||||||
class AccountSettingsScreen extends ConsumerWidget {
|
class AccountSettingsScreen extends ConsumerWidget {
|
||||||
final NavigationContract navigationContract;
|
final NavigationContract navigationContract;
|
||||||
static final _privacyUrl =
|
static const _privacyUrl =
|
||||||
'https://savefamilygps.com/pages/politica-de-privacidad-reloj-gps-infantil-localizador-savefamily';
|
'https://savefamilygps.com/pages/politica-de-privacidad-reloj-gps-infantil-localizador-savefamily';
|
||||||
|
|
||||||
const AccountSettingsScreen({super.key, required this.navigationContract});
|
const AccountSettingsScreen({super.key, required this.navigationContract});
|
||||||
@@ -24,15 +25,15 @@ class AccountSettingsScreen extends ConsumerWidget {
|
|||||||
final color = context.sfColors.legacyPrimary;
|
final color = context.sfColors.legacyPrimary;
|
||||||
final selectedDevice = ref.watch(selectedDeviceProvider).value;
|
final selectedDevice = ref.watch(selectedDeviceProvider).value;
|
||||||
final isLoggingOut = ref.watch(
|
final isLoggingOut = ref.watch(
|
||||||
accountSettingsViewModelProvider.select((s) => s.isLoggingOut),
|
accountSettingsControllerProvider.select((s) => s.isLoading),
|
||||||
);
|
);
|
||||||
|
|
||||||
ref.listen(accountSettingsViewModelProvider.select((s) => s.isLoggingOut), (
|
ref.listen(accountSettingsControllerProvider, (prev, next) async {
|
||||||
prev,
|
if (prev != null && prev.isLoading && !next.isLoading) {
|
||||||
isLoggingOut,
|
await clearSessionData();
|
||||||
) {
|
ref.invalidate(legacyDevicesProvider);
|
||||||
if (prev == true && !isLoggingOut) {
|
ref.invalidate(selectedDeviceProvider);
|
||||||
navigationContract.goTo(AppRoutes.legacyLogin);
|
if (context.mounted) navigationContract.goTo(AppRoutes.legacyLogin);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -41,8 +42,8 @@ class AccountSettingsScreen extends ConsumerWidget {
|
|||||||
body: SingleChildScrollView(
|
body: SingleChildScrollView(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: SizeUtils.getByScreen(
|
padding: SizeUtils.getByScreen(
|
||||||
small: EdgeInsets.symmetric(horizontal: 22, vertical: 10),
|
small: const EdgeInsets.symmetric(horizontal: 22, vertical: 10),
|
||||||
big: EdgeInsets.symmetric(horizontal: 21, vertical: 8),
|
big: const EdgeInsets.symmetric(horizontal: 21, vertical: 8),
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
@@ -101,9 +102,9 @@ class AccountSettingsScreen extends ConsumerWidget {
|
|||||||
_item(
|
_item(
|
||||||
context,
|
context,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
showDialog(
|
showDialog<void>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => Dialog(
|
builder: (_) => Dialog(
|
||||||
backgroundColor: Colors.transparent,
|
backgroundColor: Colors.transparent,
|
||||||
child: RegCodeDialog(
|
child: RegCodeDialog(
|
||||||
regCode: selectedDevice?.id ?? '',
|
regCode: selectedDevice?.id ?? '',
|
||||||
@@ -131,8 +132,8 @@ class AccountSettingsScreen extends ConsumerWidget {
|
|||||||
),
|
),
|
||||||
footer: Container(
|
footer: Container(
|
||||||
padding: SizeUtils.getByScreen(
|
padding: SizeUtils.getByScreen(
|
||||||
small: EdgeInsets.symmetric(vertical: 12, horizontal: 30),
|
small: const EdgeInsets.symmetric(vertical: 12, horizontal: 30),
|
||||||
big: EdgeInsets.symmetric(vertical: 10, horizontal: 28),
|
big: const EdgeInsets.symmetric(vertical: 10, horizontal: 28),
|
||||||
),
|
),
|
||||||
child: PrimaryButton(
|
child: PrimaryButton(
|
||||||
text: context.translate(I18n.logOut),
|
text: context.translate(I18n.logOut),
|
||||||
@@ -149,7 +150,7 @@ class AccountSettingsScreen extends ConsumerWidget {
|
|||||||
: null,
|
: null,
|
||||||
onPressed: isLoggingOut
|
onPressed: isLoggingOut
|
||||||
? () {}
|
? () {}
|
||||||
: ref.read(accountSettingsViewModelProvider.notifier).logout,
|
: ref.read(accountSettingsControllerProvider.notifier).logout,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:legacy_auth/legacy_auth.dart';
|
||||||
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
import 'package:sf_tracking/sf_tracking.dart';
|
||||||
|
|
||||||
|
part 'account_settings_controller.g.dart';
|
||||||
|
|
||||||
|
@riverpod
|
||||||
|
class AccountSettingsController extends _$AccountSettingsController {
|
||||||
|
@override
|
||||||
|
FutureOr<void> build() {}
|
||||||
|
|
||||||
|
Future<void> logout() async {
|
||||||
|
state = const AsyncLoading();
|
||||||
|
try {
|
||||||
|
await ref.read(legacyAuthRepositoryProvider).logout();
|
||||||
|
} catch (_) {}
|
||||||
|
unawaited(ref.read(sfTrackingProvider).legacyAuthLogout());
|
||||||
|
state = const AsyncData(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'account_settings_controller.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// RiverpodGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// ignore_for_file: type=lint, type=warning
|
||||||
|
|
||||||
|
@ProviderFor(AccountSettingsController)
|
||||||
|
const accountSettingsControllerProvider = AccountSettingsControllerProvider._();
|
||||||
|
|
||||||
|
final class AccountSettingsControllerProvider
|
||||||
|
extends $AsyncNotifierProvider<AccountSettingsController, void> {
|
||||||
|
const AccountSettingsControllerProvider._()
|
||||||
|
: super(
|
||||||
|
from: null,
|
||||||
|
argument: null,
|
||||||
|
retry: null,
|
||||||
|
name: r'accountSettingsControllerProvider',
|
||||||
|
isAutoDispose: true,
|
||||||
|
dependencies: null,
|
||||||
|
$allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String debugGetCreateSourceHash() => _$accountSettingsControllerHash();
|
||||||
|
|
||||||
|
@$internal
|
||||||
|
@override
|
||||||
|
AccountSettingsController create() => AccountSettingsController();
|
||||||
|
}
|
||||||
|
|
||||||
|
String _$accountSettingsControllerHash() =>
|
||||||
|
r'8ca0c05ca6f2d5696126f5ab7ade83419c544afe';
|
||||||
|
|
||||||
|
abstract class _$AccountSettingsController extends $AsyncNotifier<void> {
|
||||||
|
FutureOr<void> build();
|
||||||
|
@$mustCallSuper
|
||||||
|
@override
|
||||||
|
void runBuild() {
|
||||||
|
build();
|
||||||
|
final ref = this.ref as $Ref<AsyncValue<void>, void>;
|
||||||
|
final element =
|
||||||
|
ref.element
|
||||||
|
as $ClassProviderElement<
|
||||||
|
AnyNotifier<AsyncValue<void>, void>,
|
||||||
|
AsyncValue<void>,
|
||||||
|
Object?,
|
||||||
|
Object?
|
||||||
|
>;
|
||||||
|
element.handleValue(ref, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
import 'dart:async';
|
|
||||||
|
|
||||||
import 'package:account/src/features/account_settings/presentation/state/account_settings_view_state.dart';
|
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
||||||
import 'package:legacy_auth/legacy_auth.dart';
|
|
||||||
import 'package:sf_shared/sf_shared.dart';
|
|
||||||
import 'package:sf_infrastructure/sf_infrastructure.dart';
|
|
||||||
import 'package:sf_tracking/sf_tracking.dart';
|
|
||||||
|
|
||||||
final accountSettingsViewModelProvider =
|
|
||||||
NotifierProvider.autoDispose<
|
|
||||||
AccountSettingsViewModel,
|
|
||||||
AccountSettingsViewState
|
|
||||||
>(AccountSettingsViewModel.new);
|
|
||||||
|
|
||||||
class AccountSettingsViewModel extends Notifier<AccountSettingsViewState> {
|
|
||||||
late final SfTrackingRepository _tracking;
|
|
||||||
|
|
||||||
@override
|
|
||||||
AccountSettingsViewState build() {
|
|
||||||
_tracking = ref.read(sfTrackingProvider);
|
|
||||||
return const AccountSettingsViewState();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> logout() async {
|
|
||||||
if (state.isLoggingOut) return;
|
|
||||||
|
|
||||||
state = state.copyWith(isLoggingOut: true, errorMessage: '');
|
|
||||||
|
|
||||||
try {
|
|
||||||
await ref.read(legacyAuthRepositoryProvider).logout();
|
|
||||||
} catch (_) {}
|
|
||||||
|
|
||||||
await clearSessionData();
|
|
||||||
ref.invalidate(legacyDevicesProvider);
|
|
||||||
ref.invalidate(selectedDeviceProvider);
|
|
||||||
|
|
||||||
unawaited(_tracking.legacyAuthLogout());
|
|
||||||
|
|
||||||
state = state.copyWith(isLoggingOut: false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
|
||||||
|
|
||||||
part 'account_settings_view_state.freezed.dart';
|
|
||||||
|
|
||||||
@freezed
|
|
||||||
abstract class AccountSettingsViewState with _$AccountSettingsViewState {
|
|
||||||
const factory AccountSettingsViewState({
|
|
||||||
@Default(false) bool isLoggingOut,
|
|
||||||
@Default('') String errorMessage,
|
|
||||||
}) = _AccountSettingsViewState;
|
|
||||||
}
|
|
||||||
@@ -1,274 +0,0 @@
|
|||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
|
||||||
// coverage:ignore-file
|
|
||||||
// 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 'account_settings_view_state.dart';
|
|
||||||
|
|
||||||
// **************************************************************************
|
|
||||||
// FreezedGenerator
|
|
||||||
// **************************************************************************
|
|
||||||
|
|
||||||
// dart format off
|
|
||||||
T _$identity<T>(T value) => value;
|
|
||||||
/// @nodoc
|
|
||||||
mixin _$AccountSettingsViewState {
|
|
||||||
|
|
||||||
bool get isLoggingOut; String get errorMessage;
|
|
||||||
/// Create a copy of AccountSettingsViewState
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
@pragma('vm:prefer-inline')
|
|
||||||
$AccountSettingsViewStateCopyWith<AccountSettingsViewState> get copyWith => _$AccountSettingsViewStateCopyWithImpl<AccountSettingsViewState>(this as AccountSettingsViewState, _$identity);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool operator ==(Object other) {
|
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is AccountSettingsViewState&&(identical(other.isLoggingOut, isLoggingOut) || other.isLoggingOut == isLoggingOut)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@override
|
|
||||||
int get hashCode => Object.hash(runtimeType,isLoggingOut,errorMessage);
|
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() {
|
|
||||||
return 'AccountSettingsViewState(isLoggingOut: $isLoggingOut, errorMessage: $errorMessage)';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
abstract mixin class $AccountSettingsViewStateCopyWith<$Res> {
|
|
||||||
factory $AccountSettingsViewStateCopyWith(AccountSettingsViewState value, $Res Function(AccountSettingsViewState) _then) = _$AccountSettingsViewStateCopyWithImpl;
|
|
||||||
@useResult
|
|
||||||
$Res call({
|
|
||||||
bool isLoggingOut, String errorMessage
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
/// @nodoc
|
|
||||||
class _$AccountSettingsViewStateCopyWithImpl<$Res>
|
|
||||||
implements $AccountSettingsViewStateCopyWith<$Res> {
|
|
||||||
_$AccountSettingsViewStateCopyWithImpl(this._self, this._then);
|
|
||||||
|
|
||||||
final AccountSettingsViewState _self;
|
|
||||||
final $Res Function(AccountSettingsViewState) _then;
|
|
||||||
|
|
||||||
/// Create a copy of AccountSettingsViewState
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@pragma('vm:prefer-inline') @override $Res call({Object? isLoggingOut = null,Object? errorMessage = null,}) {
|
|
||||||
return _then(_self.copyWith(
|
|
||||||
isLoggingOut: null == isLoggingOut ? _self.isLoggingOut : isLoggingOut // ignore: cast_nullable_to_non_nullable
|
|
||||||
as bool,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Adds pattern-matching-related methods to [AccountSettingsViewState].
|
|
||||||
extension AccountSettingsViewStatePatterns on AccountSettingsViewState {
|
|
||||||
/// A variant of `map` that fallback to returning `orElse`.
|
|
||||||
///
|
|
||||||
/// It is equivalent to doing:
|
|
||||||
/// ```dart
|
|
||||||
/// switch (sealedClass) {
|
|
||||||
/// case final Subclass value:
|
|
||||||
/// return ...;
|
|
||||||
/// case _:
|
|
||||||
/// return orElse();
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
|
|
||||||
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _AccountSettingsViewState value)? $default,{required TResult orElse(),}){
|
|
||||||
final _that = this;
|
|
||||||
switch (_that) {
|
|
||||||
case _AccountSettingsViewState() when $default != null:
|
|
||||||
return $default(_that);case _:
|
|
||||||
return orElse();
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// A `switch`-like method, using callbacks.
|
|
||||||
///
|
|
||||||
/// Callbacks receives the raw object, upcasted.
|
|
||||||
/// It is equivalent to doing:
|
|
||||||
/// ```dart
|
|
||||||
/// switch (sealedClass) {
|
|
||||||
/// case final Subclass value:
|
|
||||||
/// return ...;
|
|
||||||
/// case final Subclass2 value:
|
|
||||||
/// return ...;
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
|
|
||||||
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _AccountSettingsViewState value) $default,){
|
|
||||||
final _that = this;
|
|
||||||
switch (_that) {
|
|
||||||
case _AccountSettingsViewState():
|
|
||||||
return $default(_that);case _:
|
|
||||||
throw StateError('Unexpected subclass');
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// A variant of `map` that fallback to returning `null`.
|
|
||||||
///
|
|
||||||
/// It is equivalent to doing:
|
|
||||||
/// ```dart
|
|
||||||
/// switch (sealedClass) {
|
|
||||||
/// case final Subclass value:
|
|
||||||
/// return ...;
|
|
||||||
/// case _:
|
|
||||||
/// return null;
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
|
|
||||||
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _AccountSettingsViewState value)? $default,){
|
|
||||||
final _that = this;
|
|
||||||
switch (_that) {
|
|
||||||
case _AccountSettingsViewState() when $default != null:
|
|
||||||
return $default(_that);case _:
|
|
||||||
return null;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// A variant of `when` that fallback to an `orElse` callback.
|
|
||||||
///
|
|
||||||
/// It is equivalent to doing:
|
|
||||||
/// ```dart
|
|
||||||
/// switch (sealedClass) {
|
|
||||||
/// case Subclass(:final field):
|
|
||||||
/// return ...;
|
|
||||||
/// case _:
|
|
||||||
/// return orElse();
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
|
|
||||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( bool isLoggingOut, String errorMessage)? $default,{required TResult orElse(),}) {final _that = this;
|
|
||||||
switch (_that) {
|
|
||||||
case _AccountSettingsViewState() when $default != null:
|
|
||||||
return $default(_that.isLoggingOut,_that.errorMessage);case _:
|
|
||||||
return orElse();
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// A `switch`-like method, using callbacks.
|
|
||||||
///
|
|
||||||
/// As opposed to `map`, this offers destructuring.
|
|
||||||
/// It is equivalent to doing:
|
|
||||||
/// ```dart
|
|
||||||
/// switch (sealedClass) {
|
|
||||||
/// case Subclass(:final field):
|
|
||||||
/// return ...;
|
|
||||||
/// case Subclass2(:final field2):
|
|
||||||
/// return ...;
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
|
|
||||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( bool isLoggingOut, String errorMessage) $default,) {final _that = this;
|
|
||||||
switch (_that) {
|
|
||||||
case _AccountSettingsViewState():
|
|
||||||
return $default(_that.isLoggingOut,_that.errorMessage);case _:
|
|
||||||
throw StateError('Unexpected subclass');
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// A variant of `when` that fallback to returning `null`
|
|
||||||
///
|
|
||||||
/// It is equivalent to doing:
|
|
||||||
/// ```dart
|
|
||||||
/// switch (sealedClass) {
|
|
||||||
/// case Subclass(:final field):
|
|
||||||
/// return ...;
|
|
||||||
/// case _:
|
|
||||||
/// return null;
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
|
|
||||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( bool isLoggingOut, String errorMessage)? $default,) {final _that = this;
|
|
||||||
switch (_that) {
|
|
||||||
case _AccountSettingsViewState() when $default != null:
|
|
||||||
return $default(_that.isLoggingOut,_that.errorMessage);case _:
|
|
||||||
return null;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
|
|
||||||
|
|
||||||
class _AccountSettingsViewState implements AccountSettingsViewState {
|
|
||||||
const _AccountSettingsViewState({this.isLoggingOut = false, this.errorMessage = ''});
|
|
||||||
|
|
||||||
|
|
||||||
@override@JsonKey() final bool isLoggingOut;
|
|
||||||
@override@JsonKey() final String errorMessage;
|
|
||||||
|
|
||||||
/// Create a copy of AccountSettingsViewState
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
@pragma('vm:prefer-inline')
|
|
||||||
_$AccountSettingsViewStateCopyWith<_AccountSettingsViewState> get copyWith => __$AccountSettingsViewStateCopyWithImpl<_AccountSettingsViewState>(this, _$identity);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool operator ==(Object other) {
|
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _AccountSettingsViewState&&(identical(other.isLoggingOut, isLoggingOut) || other.isLoggingOut == isLoggingOut)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@override
|
|
||||||
int get hashCode => Object.hash(runtimeType,isLoggingOut,errorMessage);
|
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() {
|
|
||||||
return 'AccountSettingsViewState(isLoggingOut: $isLoggingOut, errorMessage: $errorMessage)';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
abstract mixin class _$AccountSettingsViewStateCopyWith<$Res> implements $AccountSettingsViewStateCopyWith<$Res> {
|
|
||||||
factory _$AccountSettingsViewStateCopyWith(_AccountSettingsViewState value, $Res Function(_AccountSettingsViewState) _then) = __$AccountSettingsViewStateCopyWithImpl;
|
|
||||||
@override @useResult
|
|
||||||
$Res call({
|
|
||||||
bool isLoggingOut, String errorMessage
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
/// @nodoc
|
|
||||||
class __$AccountSettingsViewStateCopyWithImpl<$Res>
|
|
||||||
implements _$AccountSettingsViewStateCopyWith<$Res> {
|
|
||||||
__$AccountSettingsViewStateCopyWithImpl(this._self, this._then);
|
|
||||||
|
|
||||||
final _AccountSettingsViewState _self;
|
|
||||||
final $Res Function(_AccountSettingsViewState) _then;
|
|
||||||
|
|
||||||
/// Create a copy of AccountSettingsViewState
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@override @pragma('vm:prefer-inline') $Res call({Object? isLoggingOut = null,Object? errorMessage = null,}) {
|
|
||||||
return _then(_AccountSettingsViewState(
|
|
||||||
isLoggingOut: null == isLoggingOut ? _self.isLoggingOut : isLoggingOut // ignore: cast_nullable_to_non_nullable
|
|
||||||
as bool,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// dart format on
|
|
||||||
@@ -34,7 +34,7 @@ final class DeleteAccountControllerProvider
|
|||||||
}
|
}
|
||||||
|
|
||||||
String _$deleteAccountControllerHash() =>
|
String _$deleteAccountControllerHash() =>
|
||||||
r'fec69b905e8020c9357500bdd4c75e70b2b0797d';
|
r'293d3eacd0a4189e8849dd9f825a0a04c80cb0ff';
|
||||||
|
|
||||||
abstract class _$DeleteAccountController extends $AsyncNotifier<void> {
|
abstract class _$DeleteAccountController extends $AsyncNotifier<void> {
|
||||||
FutureOr<void> build();
|
FutureOr<void> build();
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
import 'package:account/src/features/account_settings/presentation/providers/account_settings_controller.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:legacy_auth/legacy_auth.dart';
|
||||||
|
import 'package:legacy_auth/src/core/domain/repositories/auth_repository.dart';
|
||||||
|
import 'package:mocktail/mocktail.dart';
|
||||||
|
import 'package:sf_shared/testing.dart';
|
||||||
|
import 'package:sf_tracking/sf_tracking.dart';
|
||||||
|
|
||||||
|
class MockLegacyAuthRepository extends Mock implements LegacyAuthRepository {}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
ProviderContainer buildContainer(LegacyAuthRepository authRepo) {
|
||||||
|
return makeContainer(
|
||||||
|
overrides: [
|
||||||
|
legacyAuthRepositoryProvider.overrideWithValue(authRepo),
|
||||||
|
sfTrackingProvider.overrideWithValue(
|
||||||
|
SfTrackingRepository(clients: const []),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
group('AccountSettingsController.logout', () {
|
||||||
|
test('transitions to AsyncData when backend logout succeeds', () async {
|
||||||
|
final auth = MockLegacyAuthRepository();
|
||||||
|
when(() => auth.logout()).thenAnswer((_) async {});
|
||||||
|
|
||||||
|
final container = buildContainer(auth);
|
||||||
|
addTearDown(container.dispose);
|
||||||
|
|
||||||
|
await container.read(accountSettingsControllerProvider.notifier).logout();
|
||||||
|
|
||||||
|
final state = container.read(accountSettingsControllerProvider);
|
||||||
|
expect(state, isA<AsyncData<void>>());
|
||||||
|
expect(state.isLoading, isFalse);
|
||||||
|
|
||||||
|
verify(() => auth.logout()).called(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('still completes when backend logout throws', () async {
|
||||||
|
final auth = MockLegacyAuthRepository();
|
||||||
|
when(() => auth.logout()).thenThrow(Exception('server down'));
|
||||||
|
|
||||||
|
final container = buildContainer(auth);
|
||||||
|
addTearDown(container.dispose);
|
||||||
|
|
||||||
|
await container.read(accountSettingsControllerProvider.notifier).logout();
|
||||||
|
|
||||||
|
final state = container.read(accountSettingsControllerProvider);
|
||||||
|
expect(state, isA<AsyncData<void>>());
|
||||||
|
expect(state.isLoading, isFalse);
|
||||||
|
|
||||||
|
verify(() => auth.logout()).called(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user