Skip to content

Commit

Permalink
Merge pull request #1824 from ardriveapp/PE-6623-navigate-to-drive-ex…
Browse files Browse the repository at this point in the history
…plorer-before-wallet-balance-and-io-tokens-fetch-completion

PE-6709: navigate to drive explorer before wallet balance and io tokens fetch completion
  • Loading branch information
thiagocarvalhodev authored Sep 11, 2024
2 parents 60f3544 + 629ca5b commit 27289ef
Show file tree
Hide file tree
Showing 22 changed files with 473 additions and 55 deletions.
32 changes: 29 additions & 3 deletions lib/authentication/ardrive_auth.dart
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@ class ArDriveAuthImpl implements ArDriveAuth {

currentUser = await _userRepository.getUser(password);

_updateBalance();

if (await _biometricAuthentication.isEnabled()) {
logger.i('Saving password in secure storage');

Expand Down Expand Up @@ -308,11 +310,33 @@ class ArDriveAuthImpl implements ArDriveAuth {

currentUser = await _userRepository.getUser(password);

_updateBalance();

_userStreamController.add(_currentUser);

return currentUser;
}

void _updateBalance() {
_userRepository.getIOTokens(currentUser.wallet).then((value) {
_currentUser = _currentUser!.copyWith(
ioTokens: value,
errorFetchingIOTokens: false,
);
_userStreamController.add(_currentUser);
}).catchError((e) {
_currentUser = _currentUser!.copyWith(
errorFetchingIOTokens: true,
);
_userStreamController.add(_currentUser);
return Future.value(null);
});
_userRepository.getBalance(currentUser.wallet).then((value) {
_currentUser = _currentUser!.copyWith(walletBalance: value);
_userStreamController.add(_currentUser);
});
}

Future<void> _saveUser(
String password,
ProfileType profileType,
Expand Down Expand Up @@ -364,11 +388,13 @@ class ArDriveAuthImpl implements ArDriveAuth {

@override
Future<void> refreshBalance() async {
final balance = await _userRepository.getBalance(currentUser.wallet);

currentUser = currentUser.copyWith(walletBalance: balance);
_currentUser = _currentUser!.copyWith(
errorFetchingIOTokens: false,
);

_userStreamController.add(_currentUser);

_updateBalance();
}
}

Expand Down
7 changes: 7 additions & 0 deletions lib/blocs/profile/profile_cubit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ class ProfileCubit extends Cubit<ProfileState> {
_arDriveAuth = arDriveAuth,
super(ProfileCheckingAvailability()) {
promptToAuthenticate();

_arDriveAuth.onAuthStateChanged().listen((user) {
if (user != null) {
emit(ProfileLoggedIn(
user: user, useTurbo: _turboUploadService.useTurboUpload));
}
});
}

Future<bool> isCurrentProfileArConnect() async {
Expand Down
2 changes: 1 addition & 1 deletion lib/blocs/profile/profile_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class ProfileLoggedIn extends ProfileAvailable {
useTurbo;

@override
List<Object?> get props => [user];
List<Object?> get props => [user, useTurbo];
}

class ProfilePromptAdd extends ProfileUnavailable {}
Expand Down
93 changes: 64 additions & 29 deletions lib/components/profile_card.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import 'package:ardrive/services/config/config.dart';
import 'package:ardrive/turbo/services/payment_service.dart';
import 'package:ardrive/turbo/topup/components/turbo_balance_widget.dart';
import 'package:ardrive/turbo/utils/utils.dart';
import 'package:ardrive/user/balance/user_balance_bloc.dart';
import 'package:ardrive/user/download_wallet/download_wallet_modal.dart';
import 'package:ardrive/utils/app_localizations_wrapper.dart';
import 'package:ardrive/utils/open_url.dart';
Expand Down Expand Up @@ -477,36 +478,70 @@ class _ProfileCardState extends State<ProfileCard> {

final ioTokens = state.user.ioTokens;

return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'tIO Tokens',
style: typography.paragraphNormal(
fontWeight: ArFontWeight.semiBold,
color: colorTokens.textHigh,
),
),
if (ioTokens != null)
Text(
ioTokens,
style: typography.paragraphNormal(
color: colorTokens.textLow,
fontWeight: ArFontWeight.semiBold,
),
),
if (ioTokens == null)
Text(
'An error occurred while fetching IO tokens',
style: typography.paragraphNormal(
color: colorTokens.textLow,
fontWeight: ArFontWeight.semiBold,
return BlocProvider(
create: (context) => UserBalanceBloc(auth: context.read<ArDriveAuth>())
..add(GetUserBalance()),
child: BlocBuilder<UserBalanceBloc, UserBalanceState>(
builder: (context, state) {
if (state is UserBalanceLoaded) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'tIO Tokens',
style: typography.paragraphNormal(
fontWeight: ArFontWeight.semiBold,
color: colorTokens.textHigh,
),
),
if (state is UserBalanceLoadingIOTokens &&
!state.errorFetchingIOTokens)
const Padding(
padding: EdgeInsets.only(top: 8),
child: LinearProgressIndicator(),
),
if (ioTokens != null)
Text(
ioTokens,
style: typography.paragraphNormal(
color: colorTokens.textLow,
fontWeight: ArFontWeight.semiBold,
),
),
if (state.errorFetchingIOTokens) ...[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Error fetching tIO balance',
style: typography.paragraphNormal(
fontWeight: ArFontWeight.semiBold,
color: ArDriveTheme.of(context)
.themeData
.colors
.themeErrorDefault,
),
),
ArDriveIconButton(
icon: ArDriveIcons.refresh(),
onPressed: () {
context
.read<UserBalanceBloc>()
.add(RefreshUserBalance());
},
)
],
),
]
],
),
),
],
);
}
return const SizedBox.shrink();
},
),
);
}
Expand Down
1 change: 1 addition & 0 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,7 @@ class AppState extends State<App> {
create: (context) => UserRepository(
context.read<ProfileDao>(),
context.read<ArweaveService>(),
ArioSDKFactory().create(),
),
),
RepositoryProvider(
Expand Down
93 changes: 93 additions & 0 deletions lib/user/balance/user_balance_bloc.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import 'dart:async';

import 'package:ardrive/authentication/ardrive_auth.dart';
import 'package:ardrive/user/user.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

part 'user_balance_event.dart';
part 'user_balance_state.dart';

class UserBalanceBloc extends Bloc<UserBalanceEvent, UserBalanceState> {
final ArDriveAuth _auth;
StreamSubscription<User?>? _userSubscription;

UserBalanceBloc({required ArDriveAuth auth})
: _auth = auth,
super(UserBalanceInitial()) {
on<GetUserBalance>(_onGetUserBalance);
on<RefreshUserBalance>(_onRefreshUserBalance);
}

Future<void> _onGetUserBalance(
GetUserBalance event, Emitter<UserBalanceState> emit) async {
await _cancelSubscription();

final user = _auth.currentUser;
_emitUserBalanceState(user, emit);

_userSubscription = _auth.onAuthStateChanged().listen((user) {
if (isClosed) return;
_emitUserBalanceState(user, emit);
if (user?.ioTokens != null) {
_cancelSubscription();
}
});

await _userSubscription?.asFuture();
}

Future<void> _onRefreshUserBalance(
RefreshUserBalance event, Emitter<UserBalanceState> emit) async {
if (isClosed) return;

await _cancelSubscription();

emit(UserBalanceLoadingIOTokens(
arBalance: _auth.currentUser.walletBalance,
errorFetchingIOTokens: false,
));

_auth.refreshBalance();

_userSubscription = _auth.onAuthStateChanged().listen((user) {
if (isClosed) return;
_emitUserBalanceState(user, emit);
if (user?.ioTokens != null) {
_cancelSubscription();
}
});

await _userSubscription?.asFuture();
}

Future<void> _cancelSubscription() async {
if (_userSubscription != null) {
await _userSubscription!.cancel();
_userSubscription = null;
}
}

void _emitUserBalanceState(User? user, Emitter<UserBalanceState> emit) {
if (user == null) return;

if (user.ioTokens == null && !user.errorFetchingIOTokens) {
emit(UserBalanceLoadingIOTokens(
arBalance: user.walletBalance,
errorFetchingIOTokens: user.errorFetchingIOTokens,
));
} else {
emit(UserBalanceLoaded(
arBalance: user.walletBalance,
ioTokens: user.ioTokens,
errorFetchingIOTokens: user.errorFetchingIOTokens,
));
}
}

@override
Future<void> close() async {
await _cancelSubscription();
return super.close();
}
}
12 changes: 12 additions & 0 deletions lib/user/balance/user_balance_event.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
part of 'user_balance_bloc.dart';

sealed class UserBalanceEvent extends Equatable {
const UserBalanceEvent();

@override
List<Object> get props => [];
}

final class GetUserBalance extends UserBalanceEvent {}

final class RefreshUserBalance extends UserBalanceEvent {}
30 changes: 30 additions & 0 deletions lib/user/balance/user_balance_state.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
part of 'user_balance_bloc.dart';

sealed class UserBalanceState extends Equatable {
const UserBalanceState();

@override
List<Object> get props => [];
}

final class UserBalanceInitial extends UserBalanceState {}

final class UserBalanceLoaded extends UserBalanceState {
final BigInt arBalance;
final String? ioTokens;
final bool errorFetchingIOTokens;

const UserBalanceLoaded({
required this.arBalance,
required this.ioTokens,
required this.errorFetchingIOTokens,
});
}

final class UserBalanceLoadingIOTokens extends UserBalanceLoaded {
const UserBalanceLoadingIOTokens({
required super.arBalance,
super.ioTokens,
super.errorFetchingIOTokens = false,
});
}
Loading

0 comments on commit 27289ef

Please sign in to comment.