diff --git a/lib/app.dart b/lib/app.dart index 1fb236e1..2b3da449 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -15,6 +15,7 @@ import 'package:hypha_wallet/ui/blocs/authentication/authentication_bloc.dart'; import 'package:hypha_wallet/ui/blocs/deeplink/deeplink_bloc.dart'; import 'package:hypha_wallet/ui/blocs/error_handler/error_handler_bloc.dart'; import 'package:hypha_wallet/ui/blocs/push_notifications/push_notifications_bloc.dart'; +import 'package:hypha_wallet/ui/onboarding/join_dao/join_dao_rationale_bottom_sheet.dart'; import 'package:hypha_wallet/ui/onboarding/onboarding_page_with_link.dart'; import 'package:hypha_wallet/ui/settings/hypha_confirmation_page.dart'; import 'package:hypha_wallet/ui/settings/interactor/settings_bloc.dart'; @@ -60,8 +61,9 @@ class HyphaAppView extends StatelessWidget { }, listener: (context, state) { LogHelper.d('Auth Bloc Listener FIRED'); + /// If we are handling a deeplink. Do not listen to navigation. - if(context.read().state.inviteLinkData != null) { + if (context.read().state.inviteLinkData != null) { LogHelper.d('There is Invite Link data. Ignore this command.'); return; } @@ -90,10 +92,14 @@ class HyphaAppView extends StatelessWidget { listenWhen: (previous, current) => previous.command != current.command, listener: (context, state) { state.command?.when( - navigateToCreateAccount: () => Get.Get.offAll(() => const OnboardingPageWithLink()), - navigateToSignTransaction: (ScanQrCodeResultData data) { - _showSignTransactionBottomSheet(data); - }); + navigateToCreateAccount: () => Get.Get.offAll(() => const OnboardingPageWithLink()), + navigateToSignTransaction: (ScanQrCodeResultData data) { + _showSignTransactionBottomSheet(data); + }, + showJoinDaoRationale: (daoName, secret) { + _showJoinDaoRationale(daoName, secret, context); + }, + ); context.read().add(const DeeplinkEvent.clearPageCommand()); }, ), @@ -219,4 +225,18 @@ class HyphaAppView extends StatelessWidget { ), ); } + + void _showJoinDaoRationale(String daoName, String secret, BuildContext context) { + showModalBottomSheet( + useSafeArea: true, + isScrollControlled: true, + builder: (context) { + return JoinDaoRationaleBottomSheet(daoName: daoName, secret: secret); + }, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical(top: Radius.circular(30)), + ), + context: context, + ); + } } diff --git a/lib/core/di/bloc_module.dart b/lib/core/di/bloc_module.dart index 9a7c9a66..2da41ff5 100644 --- a/lib/core/di/bloc_module.dart +++ b/lib/core/di/bloc_module.dart @@ -107,6 +107,15 @@ void _registerBlocsModule() { ), ); + _registerFactoryWithParams( + (secret, _) => JoinDaoBloc( + _getIt(), + _getIt(), + _getIt(), + secret, + ), + ); + _registerFactoryWithParams( (tokenData, _) => ReceiveBloc(tokenData, _getIt()), ); diff --git a/lib/core/di/di_setup.dart b/lib/core/di/di_setup.dart index 3ad00629..05b6e44e 100644 --- a/lib/core/di/di_setup.dart +++ b/lib/core/di/di_setup.dart @@ -54,6 +54,7 @@ import 'package:hypha_wallet/ui/onboarding/import_account/usecases/find_account_ import 'package:hypha_wallet/ui/onboarding/import_account/usecases/generate_key_from_recovery_words_use_case.dart'; import 'package:hypha_wallet/ui/onboarding/import_account/usecases/generate_key_from_seeds_passport_words_use_case.dart'; import 'package:hypha_wallet/ui/onboarding/import_account/usecases/validate_key_use_case.dart'; +import 'package:hypha_wallet/ui/onboarding/join_dao/interactor/join_dao_bloc.dart'; import 'package:hypha_wallet/ui/onboarding/usecases/check_account_availability_use_case.dart'; import 'package:hypha_wallet/ui/onboarding/usecases/create_account_use_case.dart'; import 'package:hypha_wallet/ui/onboarding/usecases/find_available_account_use_case.dart'; diff --git a/lib/ui/blocs/deeplink/deeplink_bloc.dart b/lib/ui/blocs/deeplink/deeplink_bloc.dart index a2c53901..fa8c0a34 100644 --- a/lib/ui/blocs/deeplink/deeplink_bloc.dart +++ b/lib/ui/blocs/deeplink/deeplink_bloc.dart @@ -98,7 +98,14 @@ class DeeplinkBloc extends Bloc { final chain = queryParams['chain']!; final dao = queryParams['dao']!; - final String? enrollSecret = queryParams['enroll_secret']; + final String enrollSecret = queryParams['enroll_secret']!; + + final PageCommand command; + if(_authRepository.currentAuthStatus is Authenticated) { + command = PageCommand.showJoinDaoRationale(dao, enrollSecret); + } else { + command = const PageCommand.navigateToCreateAccount(); + } /// Emit new state with data from link emit( @@ -109,7 +116,7 @@ class DeeplinkBloc extends Bloc { dao: dao, enrollSecret: enrollSecret, ), - command: const PageCommand.navigateToCreateAccount(), + command: command, ), ); } diff --git a/lib/ui/blocs/deeplink/deeplink_bloc.freezed.dart b/lib/ui/blocs/deeplink/deeplink_bloc.freezed.dart index 14322621..1a97a8f2 100644 --- a/lib/ui/blocs/deeplink/deeplink_bloc.freezed.dart +++ b/lib/ui/blocs/deeplink/deeplink_bloc.freezed.dart @@ -775,6 +775,8 @@ mixin _$PageCommand { @optionalTypeArgs TResult when({ required TResult Function() navigateToCreateAccount, + required TResult Function(String daoName, String secret) + showJoinDaoRationale, required TResult Function(ScanQrCodeResultData data) navigateToSignTransaction, }) => @@ -782,12 +784,14 @@ mixin _$PageCommand { @optionalTypeArgs TResult? whenOrNull({ TResult? Function()? navigateToCreateAccount, + TResult? Function(String daoName, String secret)? showJoinDaoRationale, TResult? Function(ScanQrCodeResultData data)? navigateToSignTransaction, }) => throw _privateConstructorUsedError; @optionalTypeArgs TResult maybeWhen({ TResult Function()? navigateToCreateAccount, + TResult Function(String daoName, String secret)? showJoinDaoRationale, TResult Function(ScanQrCodeResultData data)? navigateToSignTransaction, required TResult orElse(), }) => @@ -796,6 +800,7 @@ mixin _$PageCommand { TResult map({ required TResult Function(_NavigateToCreateAccount value) navigateToCreateAccount, + required TResult Function(_ShowJoinDaoRationale value) showJoinDaoRationale, required TResult Function(_ESRLinkNavigateToSignTransaction value) navigateToSignTransaction, }) => @@ -803,6 +808,7 @@ mixin _$PageCommand { @optionalTypeArgs TResult? mapOrNull({ TResult? Function(_NavigateToCreateAccount value)? navigateToCreateAccount, + TResult? Function(_ShowJoinDaoRationale value)? showJoinDaoRationale, TResult? Function(_ESRLinkNavigateToSignTransaction value)? navigateToSignTransaction, }) => @@ -810,6 +816,7 @@ mixin _$PageCommand { @optionalTypeArgs TResult maybeMap({ TResult Function(_NavigateToCreateAccount value)? navigateToCreateAccount, + TResult Function(_ShowJoinDaoRationale value)? showJoinDaoRationale, TResult Function(_ESRLinkNavigateToSignTransaction value)? navigateToSignTransaction, required TResult orElse(), @@ -875,6 +882,8 @@ class _$_NavigateToCreateAccount implements _NavigateToCreateAccount { @optionalTypeArgs TResult when({ required TResult Function() navigateToCreateAccount, + required TResult Function(String daoName, String secret) + showJoinDaoRationale, required TResult Function(ScanQrCodeResultData data) navigateToSignTransaction, }) { @@ -885,6 +894,7 @@ class _$_NavigateToCreateAccount implements _NavigateToCreateAccount { @optionalTypeArgs TResult? whenOrNull({ TResult? Function()? navigateToCreateAccount, + TResult? Function(String daoName, String secret)? showJoinDaoRationale, TResult? Function(ScanQrCodeResultData data)? navigateToSignTransaction, }) { return navigateToCreateAccount?.call(); @@ -894,6 +904,7 @@ class _$_NavigateToCreateAccount implements _NavigateToCreateAccount { @optionalTypeArgs TResult maybeWhen({ TResult Function()? navigateToCreateAccount, + TResult Function(String daoName, String secret)? showJoinDaoRationale, TResult Function(ScanQrCodeResultData data)? navigateToSignTransaction, required TResult orElse(), }) { @@ -908,6 +919,7 @@ class _$_NavigateToCreateAccount implements _NavigateToCreateAccount { TResult map({ required TResult Function(_NavigateToCreateAccount value) navigateToCreateAccount, + required TResult Function(_ShowJoinDaoRationale value) showJoinDaoRationale, required TResult Function(_ESRLinkNavigateToSignTransaction value) navigateToSignTransaction, }) { @@ -918,6 +930,7 @@ class _$_NavigateToCreateAccount implements _NavigateToCreateAccount { @optionalTypeArgs TResult? mapOrNull({ TResult? Function(_NavigateToCreateAccount value)? navigateToCreateAccount, + TResult? Function(_ShowJoinDaoRationale value)? showJoinDaoRationale, TResult? Function(_ESRLinkNavigateToSignTransaction value)? navigateToSignTransaction, }) { @@ -928,6 +941,7 @@ class _$_NavigateToCreateAccount implements _NavigateToCreateAccount { @optionalTypeArgs TResult maybeMap({ TResult Function(_NavigateToCreateAccount value)? navigateToCreateAccount, + TResult Function(_ShowJoinDaoRationale value)? showJoinDaoRationale, TResult Function(_ESRLinkNavigateToSignTransaction value)? navigateToSignTransaction, required TResult orElse(), @@ -943,6 +957,162 @@ abstract class _NavigateToCreateAccount implements PageCommand { const factory _NavigateToCreateAccount() = _$_NavigateToCreateAccount; } +/// @nodoc +abstract class _$$_ShowJoinDaoRationaleCopyWith<$Res> { + factory _$$_ShowJoinDaoRationaleCopyWith(_$_ShowJoinDaoRationale value, + $Res Function(_$_ShowJoinDaoRationale) then) = + __$$_ShowJoinDaoRationaleCopyWithImpl<$Res>; + @useResult + $Res call({String daoName, String secret}); +} + +/// @nodoc +class __$$_ShowJoinDaoRationaleCopyWithImpl<$Res> + extends _$PageCommandCopyWithImpl<$Res, _$_ShowJoinDaoRationale> + implements _$$_ShowJoinDaoRationaleCopyWith<$Res> { + __$$_ShowJoinDaoRationaleCopyWithImpl(_$_ShowJoinDaoRationale _value, + $Res Function(_$_ShowJoinDaoRationale) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? daoName = null, + Object? secret = null, + }) { + return _then(_$_ShowJoinDaoRationale( + null == daoName + ? _value.daoName + : daoName // ignore: cast_nullable_to_non_nullable + as String, + null == secret + ? _value.secret + : secret // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// @nodoc + +class _$_ShowJoinDaoRationale implements _ShowJoinDaoRationale { + const _$_ShowJoinDaoRationale(this.daoName, this.secret); + + @override + final String daoName; + @override + final String secret; + + @override + String toString() { + return 'PageCommand.showJoinDaoRationale(daoName: $daoName, secret: $secret)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$_ShowJoinDaoRationale && + (identical(other.daoName, daoName) || other.daoName == daoName) && + (identical(other.secret, secret) || other.secret == secret)); + } + + @override + int get hashCode => Object.hash(runtimeType, daoName, secret); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$_ShowJoinDaoRationaleCopyWith<_$_ShowJoinDaoRationale> get copyWith => + __$$_ShowJoinDaoRationaleCopyWithImpl<_$_ShowJoinDaoRationale>( + this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() navigateToCreateAccount, + required TResult Function(String daoName, String secret) + showJoinDaoRationale, + required TResult Function(ScanQrCodeResultData data) + navigateToSignTransaction, + }) { + return showJoinDaoRationale(daoName, secret); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? navigateToCreateAccount, + TResult? Function(String daoName, String secret)? showJoinDaoRationale, + TResult? Function(ScanQrCodeResultData data)? navigateToSignTransaction, + }) { + return showJoinDaoRationale?.call(daoName, secret); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? navigateToCreateAccount, + TResult Function(String daoName, String secret)? showJoinDaoRationale, + TResult Function(ScanQrCodeResultData data)? navigateToSignTransaction, + required TResult orElse(), + }) { + if (showJoinDaoRationale != null) { + return showJoinDaoRationale(daoName, secret); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_NavigateToCreateAccount value) + navigateToCreateAccount, + required TResult Function(_ShowJoinDaoRationale value) showJoinDaoRationale, + required TResult Function(_ESRLinkNavigateToSignTransaction value) + navigateToSignTransaction, + }) { + return showJoinDaoRationale(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_NavigateToCreateAccount value)? navigateToCreateAccount, + TResult? Function(_ShowJoinDaoRationale value)? showJoinDaoRationale, + TResult? Function(_ESRLinkNavigateToSignTransaction value)? + navigateToSignTransaction, + }) { + return showJoinDaoRationale?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_NavigateToCreateAccount value)? navigateToCreateAccount, + TResult Function(_ShowJoinDaoRationale value)? showJoinDaoRationale, + TResult Function(_ESRLinkNavigateToSignTransaction value)? + navigateToSignTransaction, + required TResult orElse(), + }) { + if (showJoinDaoRationale != null) { + return showJoinDaoRationale(this); + } + return orElse(); + } +} + +abstract class _ShowJoinDaoRationale implements PageCommand { + const factory _ShowJoinDaoRationale( + final String daoName, final String secret) = _$_ShowJoinDaoRationale; + + String get daoName; + String get secret; + @JsonKey(ignore: true) + _$$_ShowJoinDaoRationaleCopyWith<_$_ShowJoinDaoRationale> get copyWith => + throw _privateConstructorUsedError; +} + /// @nodoc abstract class _$$_ESRLinkNavigateToSignTransactionCopyWith<$Res> { factory _$$_ESRLinkNavigateToSignTransactionCopyWith( @@ -1013,6 +1183,8 @@ class _$_ESRLinkNavigateToSignTransaction @optionalTypeArgs TResult when({ required TResult Function() navigateToCreateAccount, + required TResult Function(String daoName, String secret) + showJoinDaoRationale, required TResult Function(ScanQrCodeResultData data) navigateToSignTransaction, }) { @@ -1023,6 +1195,7 @@ class _$_ESRLinkNavigateToSignTransaction @optionalTypeArgs TResult? whenOrNull({ TResult? Function()? navigateToCreateAccount, + TResult? Function(String daoName, String secret)? showJoinDaoRationale, TResult? Function(ScanQrCodeResultData data)? navigateToSignTransaction, }) { return navigateToSignTransaction?.call(data); @@ -1032,6 +1205,7 @@ class _$_ESRLinkNavigateToSignTransaction @optionalTypeArgs TResult maybeWhen({ TResult Function()? navigateToCreateAccount, + TResult Function(String daoName, String secret)? showJoinDaoRationale, TResult Function(ScanQrCodeResultData data)? navigateToSignTransaction, required TResult orElse(), }) { @@ -1046,6 +1220,7 @@ class _$_ESRLinkNavigateToSignTransaction TResult map({ required TResult Function(_NavigateToCreateAccount value) navigateToCreateAccount, + required TResult Function(_ShowJoinDaoRationale value) showJoinDaoRationale, required TResult Function(_ESRLinkNavigateToSignTransaction value) navigateToSignTransaction, }) { @@ -1056,6 +1231,7 @@ class _$_ESRLinkNavigateToSignTransaction @optionalTypeArgs TResult? mapOrNull({ TResult? Function(_NavigateToCreateAccount value)? navigateToCreateAccount, + TResult? Function(_ShowJoinDaoRationale value)? showJoinDaoRationale, TResult? Function(_ESRLinkNavigateToSignTransaction value)? navigateToSignTransaction, }) { @@ -1066,6 +1242,7 @@ class _$_ESRLinkNavigateToSignTransaction @optionalTypeArgs TResult maybeMap({ TResult Function(_NavigateToCreateAccount value)? navigateToCreateAccount, + TResult Function(_ShowJoinDaoRationale value)? showJoinDaoRationale, TResult Function(_ESRLinkNavigateToSignTransaction value)? navigateToSignTransaction, required TResult orElse(), diff --git a/lib/ui/blocs/deeplink/page_command.dart b/lib/ui/blocs/deeplink/page_command.dart index 294f2cfa..14a14464 100644 --- a/lib/ui/blocs/deeplink/page_command.dart +++ b/lib/ui/blocs/deeplink/page_command.dart @@ -3,5 +3,6 @@ part of 'deeplink_bloc.dart'; @freezed class PageCommand with _$PageCommand { const factory PageCommand.navigateToCreateAccount() = _NavigateToCreateAccount; + const factory PageCommand.showJoinDaoRationale(String daoName, String secret) = _ShowJoinDaoRationale; const factory PageCommand.navigateToSignTransaction(ScanQrCodeResultData data) = _ESRLinkNavigateToSignTransaction; } diff --git a/lib/ui/onboarding/join_dao/interactor/join_dao_bloc.dart b/lib/ui/onboarding/join_dao/interactor/join_dao_bloc.dart new file mode 100644 index 00000000..e4448703 --- /dev/null +++ b/lib/ui/onboarding/join_dao/interactor/join_dao_bloc.dart @@ -0,0 +1,52 @@ +import 'dart:async'; + +import 'package:bloc/bloc.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:get/get.dart'; +import 'package:hypha_wallet/core/error_handler/error_handler_manager.dart'; +import 'package:hypha_wallet/core/network/api/services/invite_service.dart'; +import 'package:hypha_wallet/core/network/repository/auth_repository.dart'; +import 'package:hypha_wallet/ui/architecture/interactor/page_states.dart'; + +part 'join_dao_bloc.freezed.dart'; + +part 'join_dao_event.dart'; + +part 'join_dao_state.dart'; + +class JoinDaoBloc extends Bloc { + final AuthRepository _authRepository; + final InviteService _inviteService; + final ErrorHandlerManager _errorHandlerManager; + final String secret; + + JoinDaoBloc( + this._authRepository, + this._inviteService, + this._errorHandlerManager, + this.secret, + ) : super(const JoinDaoState()) { + on<_Initial>(_initial); + on<_OnYesTapped>(_onYesTapped); + } + + Future _initial(_Initial event, Emitter emit) async { + emit(state.copyWith(pageState: PageState.success)); + } + + FutureOr _onYesTapped(_OnYesTapped event, Emitter emit) async { + emit(state.copyWith(isButtonLoading: true)); + final result = await _inviteService.redeemInvite( + user: _authRepository.authDataOrCrash.userProfileData, + secret: secret, + ); + + if(result.isValue) { + emit(state.copyWith(isButtonLoading: false)); + Get.back(); + } else { + emit(state.copyWith(isButtonLoading: false)); + unawaited(_errorHandlerManager.handlerError(result.asError!.error)); + } + } +} diff --git a/lib/ui/onboarding/join_dao/interactor/join_dao_bloc.freezed.dart b/lib/ui/onboarding/join_dao/interactor/join_dao_bloc.freezed.dart new file mode 100644 index 00000000..1d185ca6 --- /dev/null +++ b/lib/ui/onboarding/join_dao/interactor/join_dao_bloc.freezed.dart @@ -0,0 +1,420 @@ +// 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 'join_dao_bloc.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(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#custom-getters-and-methods'); + +/// @nodoc +mixin _$JoinDaoEvent { + @optionalTypeArgs + TResult when({ + required TResult Function() initial, + required TResult Function() onYesTapped, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? initial, + TResult? Function()? onYesTapped, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? initial, + TResult Function()? onYesTapped, + required TResult orElse(), + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(_Initial value) initial, + required TResult Function(_OnYesTapped value) onYesTapped, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_Initial value)? initial, + TResult? Function(_OnYesTapped value)? onYesTapped, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_Initial value)? initial, + TResult Function(_OnYesTapped value)? onYesTapped, + required TResult orElse(), + }) => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $JoinDaoEventCopyWith<$Res> { + factory $JoinDaoEventCopyWith( + JoinDaoEvent value, $Res Function(JoinDaoEvent) then) = + _$JoinDaoEventCopyWithImpl<$Res, JoinDaoEvent>; +} + +/// @nodoc +class _$JoinDaoEventCopyWithImpl<$Res, $Val extends JoinDaoEvent> + implements $JoinDaoEventCopyWith<$Res> { + _$JoinDaoEventCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; +} + +/// @nodoc +abstract class _$$_InitialCopyWith<$Res> { + factory _$$_InitialCopyWith( + _$_Initial value, $Res Function(_$_Initial) then) = + __$$_InitialCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$_InitialCopyWithImpl<$Res> + extends _$JoinDaoEventCopyWithImpl<$Res, _$_Initial> + implements _$$_InitialCopyWith<$Res> { + __$$_InitialCopyWithImpl(_$_Initial _value, $Res Function(_$_Initial) _then) + : super(_value, _then); +} + +/// @nodoc + +class _$_Initial implements _Initial { + const _$_Initial(); + + @override + String toString() { + return 'JoinDaoEvent.initial()'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$_Initial); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() initial, + required TResult Function() onYesTapped, + }) { + return initial(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? initial, + TResult? Function()? onYesTapped, + }) { + return initial?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? initial, + TResult Function()? onYesTapped, + required TResult orElse(), + }) { + if (initial != null) { + return initial(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_Initial value) initial, + required TResult Function(_OnYesTapped value) onYesTapped, + }) { + return initial(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_Initial value)? initial, + TResult? Function(_OnYesTapped value)? onYesTapped, + }) { + return initial?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_Initial value)? initial, + TResult Function(_OnYesTapped value)? onYesTapped, + required TResult orElse(), + }) { + if (initial != null) { + return initial(this); + } + return orElse(); + } +} + +abstract class _Initial implements JoinDaoEvent { + const factory _Initial() = _$_Initial; +} + +/// @nodoc +abstract class _$$_OnYesTappedCopyWith<$Res> { + factory _$$_OnYesTappedCopyWith( + _$_OnYesTapped value, $Res Function(_$_OnYesTapped) then) = + __$$_OnYesTappedCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$_OnYesTappedCopyWithImpl<$Res> + extends _$JoinDaoEventCopyWithImpl<$Res, _$_OnYesTapped> + implements _$$_OnYesTappedCopyWith<$Res> { + __$$_OnYesTappedCopyWithImpl( + _$_OnYesTapped _value, $Res Function(_$_OnYesTapped) _then) + : super(_value, _then); +} + +/// @nodoc + +class _$_OnYesTapped implements _OnYesTapped { + const _$_OnYesTapped(); + + @override + String toString() { + return 'JoinDaoEvent.onYesTapped()'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$_OnYesTapped); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() initial, + required TResult Function() onYesTapped, + }) { + return onYesTapped(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? initial, + TResult? Function()? onYesTapped, + }) { + return onYesTapped?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? initial, + TResult Function()? onYesTapped, + required TResult orElse(), + }) { + if (onYesTapped != null) { + return onYesTapped(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_Initial value) initial, + required TResult Function(_OnYesTapped value) onYesTapped, + }) { + return onYesTapped(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_Initial value)? initial, + TResult? Function(_OnYesTapped value)? onYesTapped, + }) { + return onYesTapped?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_Initial value)? initial, + TResult Function(_OnYesTapped value)? onYesTapped, + required TResult orElse(), + }) { + if (onYesTapped != null) { + return onYesTapped(this); + } + return orElse(); + } +} + +abstract class _OnYesTapped implements JoinDaoEvent { + const factory _OnYesTapped() = _$_OnYesTapped; +} + +/// @nodoc +mixin _$JoinDaoState { + PageState get pageState => throw _privateConstructorUsedError; + bool get isButtonLoading => throw _privateConstructorUsedError; + + @JsonKey(ignore: true) + $JoinDaoStateCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $JoinDaoStateCopyWith<$Res> { + factory $JoinDaoStateCopyWith( + JoinDaoState value, $Res Function(JoinDaoState) then) = + _$JoinDaoStateCopyWithImpl<$Res, JoinDaoState>; + @useResult + $Res call({PageState pageState, bool isButtonLoading}); +} + +/// @nodoc +class _$JoinDaoStateCopyWithImpl<$Res, $Val extends JoinDaoState> + implements $JoinDaoStateCopyWith<$Res> { + _$JoinDaoStateCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? pageState = null, + Object? isButtonLoading = null, + }) { + return _then(_value.copyWith( + pageState: null == pageState + ? _value.pageState + : pageState // ignore: cast_nullable_to_non_nullable + as PageState, + isButtonLoading: null == isButtonLoading + ? _value.isButtonLoading + : isButtonLoading // ignore: cast_nullable_to_non_nullable + as bool, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$_JoinDaoStateCopyWith<$Res> + implements $JoinDaoStateCopyWith<$Res> { + factory _$$_JoinDaoStateCopyWith( + _$_JoinDaoState value, $Res Function(_$_JoinDaoState) then) = + __$$_JoinDaoStateCopyWithImpl<$Res>; + @override + @useResult + $Res call({PageState pageState, bool isButtonLoading}); +} + +/// @nodoc +class __$$_JoinDaoStateCopyWithImpl<$Res> + extends _$JoinDaoStateCopyWithImpl<$Res, _$_JoinDaoState> + implements _$$_JoinDaoStateCopyWith<$Res> { + __$$_JoinDaoStateCopyWithImpl( + _$_JoinDaoState _value, $Res Function(_$_JoinDaoState) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? pageState = null, + Object? isButtonLoading = null, + }) { + return _then(_$_JoinDaoState( + pageState: null == pageState + ? _value.pageState + : pageState // ignore: cast_nullable_to_non_nullable + as PageState, + isButtonLoading: null == isButtonLoading + ? _value.isButtonLoading + : isButtonLoading // ignore: cast_nullable_to_non_nullable + as bool, + )); + } +} + +/// @nodoc + +class _$_JoinDaoState extends _JoinDaoState { + const _$_JoinDaoState( + {this.pageState = PageState.initial, this.isButtonLoading = false}) + : super._(); + + @override + @JsonKey() + final PageState pageState; + @override + @JsonKey() + final bool isButtonLoading; + + @override + String toString() { + return 'JoinDaoState(pageState: $pageState, isButtonLoading: $isButtonLoading)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$_JoinDaoState && + (identical(other.pageState, pageState) || + other.pageState == pageState) && + (identical(other.isButtonLoading, isButtonLoading) || + other.isButtonLoading == isButtonLoading)); + } + + @override + int get hashCode => Object.hash(runtimeType, pageState, isButtonLoading); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$_JoinDaoStateCopyWith<_$_JoinDaoState> get copyWith => + __$$_JoinDaoStateCopyWithImpl<_$_JoinDaoState>(this, _$identity); +} + +abstract class _JoinDaoState extends JoinDaoState { + const factory _JoinDaoState( + {final PageState pageState, + final bool isButtonLoading}) = _$_JoinDaoState; + const _JoinDaoState._() : super._(); + + @override + PageState get pageState; + @override + bool get isButtonLoading; + @override + @JsonKey(ignore: true) + _$$_JoinDaoStateCopyWith<_$_JoinDaoState> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/ui/onboarding/join_dao/interactor/join_dao_event.dart b/lib/ui/onboarding/join_dao/interactor/join_dao_event.dart new file mode 100644 index 00000000..cd8f2f38 --- /dev/null +++ b/lib/ui/onboarding/join_dao/interactor/join_dao_event.dart @@ -0,0 +1,7 @@ +part of 'join_dao_bloc.dart'; + +@freezed +class JoinDaoEvent with _$JoinDaoEvent { + const factory JoinDaoEvent.initial() = _Initial; + const factory JoinDaoEvent.onYesTapped() = _OnYesTapped; +} diff --git a/lib/ui/onboarding/join_dao/interactor/join_dao_state.dart b/lib/ui/onboarding/join_dao/interactor/join_dao_state.dart new file mode 100644 index 00000000..60157849 --- /dev/null +++ b/lib/ui/onboarding/join_dao/interactor/join_dao_state.dart @@ -0,0 +1,12 @@ +part of 'join_dao_bloc.dart'; + +@freezed +class JoinDaoState with _$JoinDaoState { + const JoinDaoState._(); + + const factory JoinDaoState({ + @Default(PageState.initial) PageState pageState, + @Default(false) bool isButtonLoading, + }) = _JoinDaoState; + +} diff --git a/lib/ui/onboarding/join_dao/join_dao_rationale_bottom_sheet.dart b/lib/ui/onboarding/join_dao/join_dao_rationale_bottom_sheet.dart new file mode 100644 index 00000000..a1a524fd --- /dev/null +++ b/lib/ui/onboarding/join_dao/join_dao_rationale_bottom_sheet.dart @@ -0,0 +1,58 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:get/get.dart'; +import 'package:get_it/get_it.dart'; +import 'package:hypha_wallet/design/buttons/button_type.dart'; +import 'package:hypha_wallet/design/buttons/hypha_app_button.dart'; +import 'package:hypha_wallet/design/hypha_colors.dart'; +import 'package:hypha_wallet/design/themes/extensions/theme_extension_provider.dart'; +import 'package:hypha_wallet/ui/onboarding/join_dao/interactor/join_dao_bloc.dart'; + +class JoinDaoRationaleBottomSheet extends StatelessWidget { + final String daoName; + final String secret; + + const JoinDaoRationaleBottomSheet({super.key, required this.daoName, required this.secret}); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => GetIt.I.get(param1: secret)..add(const JoinDaoEvent.initial()), + child: DecoratedBox( + decoration: BoxDecoration( + gradient: context.isDarkTheme ? HyphaColors.gradientBlack : HyphaColors.gradientWhite, + borderRadius: const BorderRadius.only(topLeft: Radius.circular(30), topRight: Radius.circular(30)), + ), + child: Padding( + padding: const EdgeInsets.all(24), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text('Do you want to join DAO "$daoName"?', style: context.textTheme.titleSmall), + const SizedBox(height: 24), + BlocBuilder( + builder: (context, state) { + return HyphaAppButton( + title: 'Yes', + isLoading: state.isButtonLoading, + onPressed: () { + context.read().add(const JoinDaoEvent.onYesTapped()); + }, + ); + }, + ), + const SizedBox(height: 8), + HyphaAppButton( + title: 'Cancel', + buttonType: ButtonType.secondary, + onPressed: () { + Get.back(); + }, + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/ui/transfer_tokens/receive/interactor/receive_bloc.freezed.dart b/lib/ui/transfer_tokens/receive/interactor/receive_bloc.freezed.dart index bb8a8e6c..43a8fcee 100644 --- a/lib/ui/transfer_tokens/receive/interactor/receive_bloc.freezed.dart +++ b/lib/ui/transfer_tokens/receive/interactor/receive_bloc.freezed.dart @@ -681,10 +681,10 @@ class __$$_OnKeypadTappedCopyWithImpl<$Res> @pragma('vm:prefer-inline') @override $Res call({ - Object? tappedKey = freezed, + Object? tappedKey = null, }) { return _then(_$_OnKeypadTapped( - freezed == tappedKey + null == tappedKey ? _value.tappedKey : tappedKey // ignore: cast_nullable_to_non_nullable as KeypadKey, @@ -710,12 +710,12 @@ class _$_OnKeypadTapped implements _OnKeypadTapped { return identical(this, other) || (other.runtimeType == runtimeType && other is _$_OnKeypadTapped && - const DeepCollectionEquality().equals(other.tappedKey, tappedKey)); + (identical(other.tappedKey, tappedKey) || + other.tappedKey == tappedKey)); } @override - int get hashCode => - Object.hash(runtimeType, const DeepCollectionEquality().hash(tappedKey)); + int get hashCode => Object.hash(runtimeType, tappedKey); @JsonKey(ignore: true) @override diff --git a/lib/ui/transfer_tokens/send/interactor/send_bloc.freezed.dart b/lib/ui/transfer_tokens/send/interactor/send_bloc.freezed.dart index e899557a..7a2f09fd 100644 --- a/lib/ui/transfer_tokens/send/interactor/send_bloc.freezed.dart +++ b/lib/ui/transfer_tokens/send/interactor/send_bloc.freezed.dart @@ -732,10 +732,10 @@ class __$$_OnPercentageTappedCopyWithImpl<$Res> @pragma('vm:prefer-inline') @override $Res call({ - Object? amountPercentage = freezed, + Object? amountPercentage = null, }) { return _then(_$_OnPercentageTapped( - freezed == amountPercentage + null == amountPercentage ? _value.amountPercentage : amountPercentage // ignore: cast_nullable_to_non_nullable as AmountPercentage, @@ -761,13 +761,12 @@ class _$_OnPercentageTapped implements _OnPercentageTapped { return identical(this, other) || (other.runtimeType == runtimeType && other is _$_OnPercentageTapped && - const DeepCollectionEquality() - .equals(other.amountPercentage, amountPercentage)); + (identical(other.amountPercentage, amountPercentage) || + other.amountPercentage == amountPercentage)); } @override - int get hashCode => Object.hash( - runtimeType, const DeepCollectionEquality().hash(amountPercentage)); + int get hashCode => Object.hash(runtimeType, amountPercentage); @JsonKey(ignore: true) @override @@ -900,10 +899,10 @@ class __$$_OnKeypadTappedCopyWithImpl<$Res> @pragma('vm:prefer-inline') @override $Res call({ - Object? tappedKey = freezed, + Object? tappedKey = null, }) { return _then(_$_OnKeypadTapped( - freezed == tappedKey + null == tappedKey ? _value.tappedKey : tappedKey // ignore: cast_nullable_to_non_nullable as KeypadKey, @@ -929,12 +928,12 @@ class _$_OnKeypadTapped implements _OnKeypadTapped { return identical(this, other) || (other.runtimeType == runtimeType && other is _$_OnKeypadTapped && - const DeepCollectionEquality().equals(other.tappedKey, tappedKey)); + (identical(other.tappedKey, tappedKey) || + other.tappedKey == tappedKey)); } @override - int get hashCode => - Object.hash(runtimeType, const DeepCollectionEquality().hash(tappedKey)); + int get hashCode => Object.hash(runtimeType, tappedKey); @JsonKey(ignore: true) @override