Skip to content

Commit

Permalink
feat: show snackbar when explorer call error
Browse files Browse the repository at this point in the history
  • Loading branch information
gabaldon committed May 23, 2023
1 parent 29e692a commit 3c20b3b
Show file tree
Hide file tree
Showing 7 changed files with 198 additions and 72 deletions.
12 changes: 8 additions & 4 deletions lib/bloc/explorer/api_explorer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,14 @@ class ApiExplorer {
}
}

Future<PrioritiesEstimate> priority() async {
try {
return await client.valueTransferPriority();
} catch (e) {
rethrow;
}
}

Future<void> delay() async {
await Future.delayed(Duration(milliseconds: EXPLORER_DELAY_MS));
}
Expand All @@ -225,8 +233,4 @@ class ApiExplorer {
var result = await hash(transactionId);
return result as ValueTransferInfo;
}

Future<PrioritiesEstimate> priority() async {
return await client.valueTransferPriority();
}
}
107 changes: 76 additions & 31 deletions lib/bloc/explorer/explorer_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,60 +32,95 @@ class ExplorerBloc extends Bloc<ExplorerEvent, ExplorerState> {

Future<void> _hashQueryEvent(
HashQueryEvent event, Emitter<ExplorerState> emit) async {
var resp = await Locator.instance
.get<ApiExplorer>()
.hash(event.value, event.utxos);
return emit(
ExplorerState.dataLoaded(data: resp, query: ExplorerQuery.hash));
emit(ExplorerState.unknown());
try {
var resp = await Locator.instance
.get<ApiExplorer>()
.hash(event.value, event.utxos);
emit(ExplorerState.dataLoaded(data: resp, query: ExplorerQuery.hash));
} catch (err) {
emit(ExplorerState.error());
rethrow;
}
}

Future<void> _statusQueryEvent(
StatusQueryEvent event, Emitter<ExplorerState> emit) async {
var resp = await Locator.instance.get<ApiExplorer>().getStatus();
return emit(ExplorerState.dataLoaded(
data: resp.jsonMap(), query: ExplorerQuery.status));
Status resp = await Locator.instance.get<ApiExplorer>().getStatus();
emit(ExplorerState.unknown());
try {
// TODO: fix type error in witnet.dart to get status
if (resp.databaseMessage == 'Explorer backend seems healthy') {
emit(ExplorerState.dataLoaded(
data: resp.jsonMap(), query: ExplorerQuery.status));
} else {
emit(ExplorerState.error());
}
} catch (err) {
emit(ExplorerState.error());
rethrow;
}
}

Future<void> _addressQueryEvent(
AddressQueryEvent event, Emitter<ExplorerState> emit) async {
var resp = await Locator.instance
.get<ApiExplorer>()
.address(value: event.address, tab: event.tab);
return emit(ExplorerState.dataLoaded(
data: resp.jsonMap(), query: ExplorerQuery.address));
emit(ExplorerState.unknown());
try {
var resp = await Locator.instance
.get<ApiExplorer>()
.address(value: event.address, tab: event.tab);
emit(ExplorerState.dataLoaded(
data: resp.jsonMap(), query: ExplorerQuery.address));
} catch (err) {
emit(ExplorerState.error());
rethrow;
}
}

Future<void> _vtTransactionPostEvent(
VTTransactionPostEvent event, Emitter<ExplorerState> emit) async {
var resp = await Locator.instance
.get<ApiExplorer>()
.sendVtTransaction(event.vtTransaction);
emit(ExplorerState.unknown());
try {
var resp = await Locator.instance
.get<ApiExplorer>()
.sendVtTransaction(event.vtTransaction);

return emit(
ExplorerState.dataLoaded(query: ExplorerQuery.sendVtt, data: resp));
emit(ExplorerState.dataLoaded(query: ExplorerQuery.sendVtt, data: resp));
} catch (err) {
emit(ExplorerState.error());
rethrow;
}
}

Future<void> _utxoQueryEvent(
UtxoQueryEvent event, Emitter<ExplorerState> emit) async {
var resp = await Locator.instance
.get<ApiExplorer>()
.utxos(address: event.account.address);
var utxoList = {};
resp.forEach((element) {
utxoList[element.outputPointer.transactionId] = element;
});
emit(ExplorerState.unknown());
try {
var resp = await Locator.instance
.get<ApiExplorer>()
.utxos(address: event.account.address);
var utxoList = {};
resp.forEach((element) {
utxoList[element.outputPointer.transactionId] = element;
});

return emit(ExplorerState.dataLoaded(
query: ExplorerQuery.utxos, data: {'utxos': utxoList}));
emit(ExplorerState.dataLoaded(
query: ExplorerQuery.utxos, data: {'utxos': utxoList}));
} catch (e) {
print('Error loading utxos $e');
emit(ExplorerState.error());
rethrow;
}
}

Future<void> _syncWalletEvent(
SyncWalletEvent event, Emitter<ExplorerState> emit) async {
emit(ExplorerState.unknown());
try {
// TODO: check if the explorer is up
await syncWalletRoutine(event, emit);
} catch (e) {
print('Error syncing the Wallet $e');
print('Error syncing wallet $e');
emit(ExplorerState.error());
rethrow;
}
}
Expand Down Expand Up @@ -138,7 +173,13 @@ class ExplorerBloc extends Bloc<ExplorerEvent, ExplorerState> {
if (!isTheSameList(account, utxoList)) {
if (utxoList.isNotEmpty) {
account.utxos = utxoList;
account = await updateAccountVttsAndBalance(account);
try {
account = await updateAccountVttsAndBalance(account);
} catch (e) {
print('Error updateAccountVttsAndBalance $e');
emit(ExplorerState.error());
rethrow;
}
} else {
account.utxos.clear();
}
Expand All @@ -158,7 +199,10 @@ class ExplorerBloc extends Bloc<ExplorerEvent, ExplorerState> {
if (_vtt.status != vtt.status) {
await database.updateVtt(wallet.id, vtt);
}
} catch (e) {}
} catch (e) {
print('Error getting vtt: ${_vtt.txnHash} :: $e');
emit(ExplorerState.error());
}
}
String currentAddress = database.walletStorage.currentAccount.address;
Map<String, String>? _addressList =
Expand Down Expand Up @@ -222,6 +266,7 @@ class ExplorerBloc extends Bloc<ExplorerEvent, ExplorerState> {
database.walletStorage.wallets[account.walletId]!.setAccount(account);
} catch (e) {
print('Error updating account vtts and balance $e');
rethrow;
}
return account;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:fixnum/fixnum.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:my_wit_wallet/constants.dart';
import 'package:witnet/constants.dart';
import 'package:witnet/data_structures.dart';
Expand Down Expand Up @@ -103,6 +104,7 @@ class VTTCreateBloc extends Bloc<VTTCreateEvent, VTTCreateState> {
prioritiesEstimate = await Locator.instance.get<ApiExplorer>().priority();
} catch (e) {
print('Error getting priority estimations $e');
rethrow;
}
}

Expand Down Expand Up @@ -616,9 +618,15 @@ class VTTCreateBloc extends Bloc<VTTCreateEvent, VTTCreateState> {
Future<void> _addSourceWalletsEvent(
AddSourceWalletsEvent event, Emitter<VTTCreateState> emit) async {
await setWallet(event.currentWallet);
await setEstimatedPriorities();
emit(state.copyWith(
inputs: inputs, outputs: outputs, status: VTTCreateStatus.building));
try {
await setEstimatedPriorities();
} catch (err) {
print('Error setting estimated priorities $err');
emit(state.copyWith(status: VTTCreateStatus.exception));
rethrow;
}
}

void _resetTransactionEvent(
Expand Down
24 changes: 4 additions & 20 deletions lib/screens/dashboard/view/dashboard_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -123,26 +123,10 @@ class DashboardScreenState extends State<DashboardScreen>
actions: [],
);
}, listener: (context, state) {
switch (state.status) {
case ExplorerStatus.unknown:
// TODO: Handle this case.
break;
case ExplorerStatus.dataloading:
// TODO: Handle this case.
break;
case ExplorerStatus.dataloaded:
{
setState(() {
_getVtts();
});
}
break;
case ExplorerStatus.error:
// TODO: Handle this case.
break;
case ExplorerStatus.ready:
// TODO: Handle this case.
break;
if (state.status == ExplorerStatus.dataloaded) {
setState(() {
_getVtts();
});
}
});
}
Expand Down
89 changes: 86 additions & 3 deletions lib/widgets/layouts/dashboard_layout.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:my_wit_wallet/bloc/explorer/explorer_bloc.dart';
import 'package:my_wit_wallet/bloc/transactions/value_transfer/vtt_create/vtt_create_bloc.dart';
import 'package:my_wit_wallet/constants.dart';
import 'package:my_wit_wallet/screens/dashboard/view/dashboard_screen.dart';
Expand Down Expand Up @@ -44,6 +47,9 @@ class DashboardLayout extends StatefulWidget {
class DashboardLayoutState extends State<DashboardLayout>
with TickerProviderStateMixin {
Wallet? walletStorage;
late Timer explorerTimer;
final GlobalKey<ScaffoldMessengerState> scaffoldMessengerKey =
GlobalKey<ScaffoldMessengerState>();

@override
void initState() {
Expand Down Expand Up @@ -203,6 +209,82 @@ class DashboardLayoutState extends State<DashboardLayout>
];
}

SnackBar buildSnackbar(String text, Color? color, [Function? action]) {
final theme = Theme.of(context);
return SnackBar(
clipBehavior: Clip.none,
action: action != null
? SnackBarAction(
label: 'Dismiss',
onPressed: () => action(),
textColor: Colors.white,
)
: null,
content: Text(text,
textAlign: TextAlign.left,
style: theme.textTheme.bodyMedium!.copyWith(color: Colors.white)),
duration: Duration(hours: 1),
behavior: SnackBarBehavior.floating,
backgroundColor: color,
elevation: 0,
);
}

BlocListener<VTTCreateBloc, VTTCreateState> _vttListener(Widget child) {
final theme = Theme.of(context);
final extendedTheme = theme.extension<ExtendedTheme>()!;
return BlocListener<VTTCreateBloc, VTTCreateState>(
listenWhen: (previousState, currentState) {
if (previousState.vttCreateStatus == VTTCreateStatus.exception &&
currentState.vttCreateStatus != VTTCreateStatus.exception) {
scaffoldMessengerKey.currentState!.showSnackBar(buildSnackbar(
'Connection reestablished!',
extendedTheme.txValuePositiveColor,
() =>
scaffoldMessengerKey.currentState!.hideCurrentMaterialBanner(),
));
}
return true;
},
listener: (context, state) {
if (state.vttCreateStatus == VTTCreateStatus.exception) {
scaffoldMessengerKey.currentState!.showSnackBar(buildSnackbar(
'myWitWallet is experiencing connection problems',
theme.colorScheme.error));
}
},
child: child,
);
}

BlocListener<ExplorerBloc, ExplorerState> _explorerListerner(Widget child) {
final theme = Theme.of(context);
final extendedTheme = theme.extension<ExtendedTheme>()!;
return BlocListener<ExplorerBloc, ExplorerState>(
listenWhen: (previousState, currentState) {
if (previousState.status == ExplorerStatus.error &&
currentState.status != ExplorerStatus.error &&
currentState.status != ExplorerStatus.unknown) {
scaffoldMessengerKey.currentState!.showSnackBar(buildSnackbar(
'Connection reestablished!',
extendedTheme.txValuePositiveColor,
() =>
scaffoldMessengerKey.currentState!.hideCurrentMaterialBanner(),
));
}
return true;
},
listener: (context, state) {
if (state.status == ExplorerStatus.error) {
scaffoldMessengerKey.currentState!.showSnackBar(buildSnackbar(
'myWitWallet is experiencing connection problems',
theme.colorScheme.error));
}
},
child: child,
);
}

Widget _authBuilder() {
final theme = Theme.of(context);
return BlocListener<LoginBloc, LoginState>(
Expand All @@ -228,14 +310,14 @@ class DashboardLayoutState extends State<DashboardLayout>
break;
case LoginStatus.LoginSuccess:
_walletList = WalletList();
_body = Column(
_body = _vttListener(_explorerListerner(Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
child: widget.dashboardChild,
),
],
);
)));
break;
default:
_body = Column(
Expand Down Expand Up @@ -264,7 +346,8 @@ class DashboardLayoutState extends State<DashboardLayout>
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async => false,
child: _authBuilder(),
child:
ScaffoldMessenger(key: scaffoldMessengerKey, child: _authBuilder()),
);
}
}
4 changes: 2 additions & 2 deletions macos/Flutter/GeneratedPluginRegistrant.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import Foundation

import mobile_scanner
import package_info_plus
import path_provider_macos
import path_provider_foundation
import screen_retriever
import shared_preferences_macos
import shared_preferences_foundation
import url_launcher_macos
import window_manager

Expand Down
Loading

0 comments on commit 3c20b3b

Please sign in to comment.