WIP firo redesign

This commit is contained in:
julian 2022-09-06 17:27:14 -06:00
parent 94941dfb94
commit fbc398bc14
9 changed files with 938 additions and 159 deletions

View file

@ -13,7 +13,9 @@ import 'package:stackwallet/pages/send_view/sub_widgets/transaction_fee_selectio
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/providers/ui/fee_rate_type_state_provider.dart';
import 'package:stackwallet/providers/ui/preview_tx_button_state_provider.dart';
import 'package:stackwallet/providers/wallet/public_private_balance_state_provider.dart';
import 'package:stackwallet/route_generator.dart';
import 'package:stackwallet/services/coins/firo/firo_wallet.dart';
import 'package:stackwallet/services/coins/manager.dart';
import 'package:stackwallet/utilities/address_utils.dart';
import 'package:stackwallet/utilities/assets.dart';
@ -37,6 +39,8 @@ import 'package:stackwallet/widgets/stack_dialog.dart';
import 'package:stackwallet/widgets/stack_text_field.dart';
import 'package:stackwallet/widgets/textfield_icon_button.dart';
import 'sub_widgets/firo_balance_selection_sheet.dart';
class SendView extends ConsumerStatefulWidget {
const SendView({
Key? key,
@ -82,6 +86,9 @@ class _SendViewState extends ConsumerState<SendView> {
Decimal? _cachedAmountToSend;
String? _address;
String? _privateBalanceString;
String? _publicBalanceString;
bool _addressToggleFlag = false;
bool _cryptoAmountChangeLock = false;
@ -196,6 +203,26 @@ class _SendViewState extends ConsumerState<SendView> {
return cachedFees[amount]!;
}
Future<String?> _firoBalanceFuture(
ChangeNotifierProvider<Manager> provider, String locale) async {
final wallet = ref.read(provider).wallet as FiroWallet?;
if (wallet != null) {
Decimal? balance;
if (ref.read(publicPrivateBalanceStateProvider.state).state ==
"Private") {
balance = await wallet.availablePrivateBalance();
} else {
balance = await wallet.availablePublicBalance();
}
return Format.localizedStringAsFixed(
value: balance, locale: locale, decimalPlaces: 8);
}
return null;
}
@override
void initState() {
ref.refresh(feeSheetSessionCacheProvider);
@ -334,21 +361,59 @@ class _SendViewState extends ConsumerState<SendView> {
children: [
SvgPicture.asset(
Assets.svg.iconFor(coin: coin),
width: 18,
height: 18,
width: 22,
height: 22,
),
const SizedBox(
width: 6,
),
Text(
ref.watch(provider
.select((value) => value.walletName)),
style: STextStyles.titleBold12,
),
if (coin != Coin.firo &&
coin != Coin.firoTestNet)
Text(
ref.watch(provider
.select((value) => value.walletName)),
style: STextStyles.titleBold12,
),
if (coin == Coin.firo ||
coin == Coin.firoTestNet)
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
ref.watch(provider.select(
(value) => value.walletName)),
style: STextStyles.titleBold12
.copyWith(fontSize: 14),
),
// const SizedBox(
// height: 2,
// ),
Text(
"${ref.watch(publicPrivateBalanceStateProvider.state).state} balance",
style: STextStyles.label
.copyWith(fontSize: 10),
),
],
),
const Spacer(),
FutureBuilder(
future: ref.watch(provider.select(
(value) => value.availableBalance)),
future: (coin != Coin.firo &&
coin != Coin.firoTestNet)
? ref.watch(provider.select(
(value) => value.availableBalance))
: ref
.watch(
publicPrivateBalanceStateProvider
.state)
.state ==
"Private"
? (ref.watch(provider).wallet
as FiroWallet)
.availablePrivateBalance()
: (ref.watch(provider).wallet
as FiroWallet)
.availablePublicBalance(),
builder:
(_, AsyncSnapshot<Decimal> snapshot) {
if (snapshot.connectionState ==
@ -423,6 +488,9 @@ class _SendViewState extends ConsumerState<SendView> {
fontSize: 10,
),
),
const SizedBox(
height: 2,
),
AnimatedText(
stringsToLoopThrough: const [
"Loading balance ",
@ -730,6 +798,141 @@ class _SendViewState extends ConsumerState<SendView> {
}
},
),
if (coin == Coin.firo)
const SizedBox(
height: 12,
),
if (coin == Coin.firo)
Text(
"Send from",
style: STextStyles.smallMed12,
textAlign: TextAlign.left,
),
if (coin == Coin.firo)
const SizedBox(
height: 8,
),
if (coin == Coin.firo)
Stack(
children: [
const TextField(
readOnly: true,
textInputAction: TextInputAction.none,
),
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 12,
),
child: RawMaterialButton(
splashColor: CFColors.splashLight,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
),
onPressed: () {
showModalBottomSheet<dynamic>(
backgroundColor: Colors.transparent,
context: context,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
top: Radius.circular(20),
),
),
builder: (_) => FiroBalanceSelectionSheet(
walletId: walletId,
),
);
},
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Text(
"${ref.watch(publicPrivateBalanceStateProvider.state).state} balance",
style: STextStyles.itemSubtitle12,
),
const SizedBox(
width: 10,
),
FutureBuilder(
future: _firoBalanceFuture(
provider, locale),
builder: (context,
AsyncSnapshot<String?>
snapshot) {
if (snapshot.connectionState ==
ConnectionState.done &&
snapshot.hasData) {
if (ref
.read(
publicPrivateBalanceStateProvider
.state)
.state ==
"Private") {
_privateBalanceString =
snapshot.data!;
} else {
_publicBalanceString =
snapshot.data!;
}
}
if (ref
.read(
publicPrivateBalanceStateProvider
.state)
.state ==
"Private" &&
_privateBalanceString !=
null) {
return Text(
"$_privateBalanceString ${coin.ticker}",
style:
STextStyles.itemSubtitle,
);
} else if (ref
.read(
publicPrivateBalanceStateProvider
.state)
.state ==
"Public" &&
_publicBalanceString !=
null) {
return Text(
"$_publicBalanceString ${coin.ticker}",
style:
STextStyles.itemSubtitle,
);
} else {
return AnimatedText(
stringsToLoopThrough: const [
"Loading balance",
"Loading balance.",
"Loading balance..",
"Loading balance...",
],
style:
STextStyles.itemSubtitle,
);
}
},
),
],
),
SvgPicture.asset(
Assets.svg.chevronDown,
width: 8,
height: 4,
color: CFColors.gray3,
),
],
),
),
)
],
),
const SizedBox(
height: 12,
),
@ -744,10 +947,34 @@ class _SendViewState extends ConsumerState<SendView> {
BlueTextButton(
text: "Send all ${coin.ticker}",
onTap: () async {
cryptoAmountController.text = (await ref
.read(provider)
.availableBalance)
.toStringAsFixed(Constants.decimalPlaces);
if (coin == Coin.firo ||
coin == Coin.firoTestNet) {
final firoWallet =
ref.read(provider).wallet as FiroWallet;
if (ref
.read(
publicPrivateBalanceStateProvider
.state)
.state ==
"Private") {
cryptoAmountController.text =
(await firoWallet
.availablePrivateBalance())
.toStringAsFixed(
Constants.decimalPlaces);
} else {
cryptoAmountController.text =
(await firoWallet
.availablePublicBalance())
.toStringAsFixed(
Constants.decimalPlaces);
}
} else {
cryptoAmountController.text = (await ref
.read(provider)
.availableBalance)
.toStringAsFixed(Constants.decimalPlaces);
}
},
),
],

View file

@ -0,0 +1,287 @@
import 'package:decimal/decimal.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/providers/wallet/public_private_balance_state_provider.dart';
import 'package:stackwallet/services/coins/firo/firo_wallet.dart';
import 'package:stackwallet/utilities/cfcolors.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/widgets/animated_text.dart';
class FiroBalanceSelectionSheet extends ConsumerStatefulWidget {
const FiroBalanceSelectionSheet({
Key? key,
required this.walletId,
}) : super(key: key);
final String walletId;
@override
ConsumerState<FiroBalanceSelectionSheet> createState() =>
_FiroBalanceSelectionSheetState();
}
class _FiroBalanceSelectionSheetState
extends ConsumerState<FiroBalanceSelectionSheet> {
late final String walletId;
final stringsToLoopThrough = [
"Loading balance",
"Loading balance.",
"Loading balance..",
"Loading balance...",
];
@override
void initState() {
walletId = widget.walletId;
super.initState();
}
@override
Widget build(BuildContext context) {
debugPrint("BUILD: $runtimeType");
final manager = ref.watch(walletsChangeNotifierProvider
.select((value) => value.getManager(walletId)));
final firoWallet = manager.wallet as FiroWallet;
return Container(
decoration: const BoxDecoration(
color: CFColors.white,
borderRadius: BorderRadius.vertical(
top: Radius.circular(20),
),
),
child: Padding(
padding: const EdgeInsets.only(
left: 24,
right: 24,
top: 10,
bottom: 0,
),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Center(
child: Container(
decoration: BoxDecoration(
color: CFColors.fieldGray,
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
),
width: 60,
height: 4,
),
),
const SizedBox(
height: 36,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Select balance",
style: STextStyles.pageTitleH2,
textAlign: TextAlign.left,
),
const SizedBox(
height: 16,
),
GestureDetector(
onTap: () {
final state =
ref.read(publicPrivateBalanceStateProvider.state).state;
if (state != "Private") {
ref.read(publicPrivateBalanceStateProvider.state).state =
"Private";
}
Navigator.of(context).pop();
},
child: Container(
color: Colors.transparent,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
SizedBox(
width: 20,
height: 20,
child: Radio(
activeColor: CFColors.link2,
value: "Private",
groupValue: ref
.watch(
publicPrivateBalanceStateProvider.state)
.state,
onChanged: (x) {
ref
.read(publicPrivateBalanceStateProvider
.state)
.state = "Private";
Navigator.of(context).pop();
},
),
),
],
),
const SizedBox(
width: 12,
),
Flexible(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Row(
// children: [
Text(
"Private balance",
style: STextStyles.titleBold12.copyWith(
color: const Color(0xFF44464E),
),
textAlign: TextAlign.left,
),
const SizedBox(
width: 2,
),
FutureBuilder(
future: firoWallet.availablePrivateBalance(),
builder:
(context, AsyncSnapshot<Decimal> snapshot) {
if (snapshot.connectionState ==
ConnectionState.done &&
snapshot.hasData) {
return Text(
"${snapshot.data!} ${manager.coin.ticker}",
style: STextStyles.itemSubtitle,
textAlign: TextAlign.left,
);
} else {
return AnimatedText(
stringsToLoopThrough:
stringsToLoopThrough,
style: STextStyles.itemSubtitle,
);
}
},
)
],
),
// ],
// ),
)
],
),
),
),
const SizedBox(
height: 16,
),
GestureDetector(
onTap: () {
final state =
ref.read(publicPrivateBalanceStateProvider.state).state;
if (state != "Public") {
ref.read(publicPrivateBalanceStateProvider.state).state =
"Public";
}
Navigator.of(context).pop();
},
child: Container(
color: Colors.transparent,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
children: [
SizedBox(
width: 20,
height: 20,
child: Radio(
activeColor: CFColors.link2,
value: "Public",
groupValue: ref
.watch(
publicPrivateBalanceStateProvider.state)
.state,
onChanged: (x) {
ref
.read(publicPrivateBalanceStateProvider
.state)
.state = "Public";
Navigator.of(context).pop();
},
),
),
],
),
const SizedBox(
width: 12,
),
Flexible(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Row(
// children: [
Text(
"Public balance",
style: STextStyles.titleBold12.copyWith(
color: const Color(0xFF44464E),
),
textAlign: TextAlign.left,
),
const SizedBox(
width: 2,
),
FutureBuilder(
future: firoWallet.availablePublicBalance(),
builder:
(context, AsyncSnapshot<Decimal> snapshot) {
if (snapshot.connectionState ==
ConnectionState.done &&
snapshot.hasData) {
return Text(
"${snapshot.data!} ${manager.coin.ticker}",
style: STextStyles.itemSubtitle,
textAlign: TextAlign.left,
);
} else {
return AnimatedText(
stringsToLoopThrough:
stringsToLoopThrough,
style: STextStyles.itemSubtitle,
);
}
},
)
// ],
// ),
],
),
),
],
),
),
),
const SizedBox(
height: 16,
),
const SizedBox(
height: 24,
),
],
),
],
),
),
);
}
}

View file

@ -1,8 +1,10 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/providers/wallet/wallet_balance_toggle_state_provider.dart';
import 'package:stackwallet/utilities/cfcolors.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/wallet_balance_toggle_state.dart';
import 'package:stackwallet/utilities/text_styles.dart';
@ -18,6 +20,9 @@ class WalletBalanceToggleSheet extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final maxHeight = MediaQuery.of(context).size.height * 0.60;
final coin = ref.watch(walletsChangeNotifierProvider
.select((value) => value.getManager(walletId).coin));
return Container(
decoration: const BoxDecoration(
color: CFColors.white,
@ -105,25 +110,44 @@ class WalletBalanceToggleSheet extends ConsumerWidget {
const SizedBox(
width: 12,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Available balance",
style: STextStyles.titleBold12,
),
const SizedBox(
height: 2,
),
// TODO need text from design
Text(
"Current spendable (unlocked) balance",
style: STextStyles.itemSubtitle12.copyWith(
color: CFColors.neutral60,
if (coin != Coin.firo && coin != Coin.firoTestNet)
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Available balance",
style: STextStyles.titleBold12,
),
),
],
),
const SizedBox(
height: 2,
),
Text(
"Current spendable (unlocked) balance",
style: STextStyles.itemSubtitle12.copyWith(
color: CFColors.neutral60,
),
),
],
),
if (coin == Coin.firo || coin == Coin.firoTestNet)
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Private balance",
style: STextStyles.titleBold12,
),
const SizedBox(
height: 2,
),
Text(
"Current private spendable (unlocked) balance",
style: STextStyles.itemSubtitle12.copyWith(
color: CFColors.neutral60,
),
),
],
),
],
),
),
@ -172,25 +196,44 @@ class WalletBalanceToggleSheet extends ConsumerWidget {
const SizedBox(
width: 12,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Full balance",
style: STextStyles.titleBold12,
),
const SizedBox(
height: 2,
),
// TODO need text from design
Text(
"Total wallet balance",
style: STextStyles.itemSubtitle12.copyWith(
color: CFColors.neutral60,
if (coin != Coin.firo && coin != Coin.firoTestNet)
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Full balance",
style: STextStyles.titleBold12,
),
),
],
),
const SizedBox(
height: 2,
),
Text(
"Total wallet balance",
style: STextStyles.itemSubtitle12.copyWith(
color: CFColors.neutral60,
),
),
],
),
if (coin == Coin.firo || coin == Coin.firoTestNet)
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Public balance",
style: STextStyles.titleBold12,
),
const SizedBox(
height: 2,
),
Text(
"Current public spendable (unlocked) balance",
style: STextStyles.itemSubtitle12.copyWith(
color: CFColors.neutral60,
),
),
],
),
],
),
),

View file

@ -6,6 +6,7 @@ import 'package:stackwallet/pages/wallet_view/sub_widgets/wallet_balance_toggle_
import 'package:stackwallet/pages/wallet_view/sub_widgets/wallet_refresh_button.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/providers/wallet/wallet_balance_toggle_state_provider.dart';
import 'package:stackwallet/services/coins/firo/firo_wallet.dart';
import 'package:stackwallet/services/coins/manager.dart';
import 'package:stackwallet/services/event_bus/events/global/wallet_sync_status_changed_event.dart';
import 'package:stackwallet/utilities/assets.dart';
@ -67,15 +68,25 @@ class _WalletSummaryInfoState extends State<WalletSummaryInfo> {
Expanded(
child: Consumer(
builder: (_, ref, __) {
final totalBalanceFuture = ref
.watch(managerProvider.select((value) => value.totalBalance));
final availableBalanceFuture = ref.watch(
managerProvider.select((value) => value.availableBalance));
final Coin coin =
ref.watch(managerProvider.select((value) => value.coin));
Future<Decimal>? totalBalanceFuture;
Future<Decimal>? availableBalanceFuture;
if (coin == Coin.firo || coin == Coin.firoTestNet) {
final firoWallet =
ref.watch(managerProvider.select((value) => value.wallet))
as FiroWallet;
totalBalanceFuture = firoWallet.availablePublicBalance();
availableBalanceFuture = firoWallet.availablePrivateBalance();
} else {
totalBalanceFuture = ref.watch(
managerProvider.select((value) => value.totalBalance));
availableBalanceFuture = ref.watch(
managerProvider.select((value) => value.availableBalance));
}
final locale = ref.watch(localeServiceChangeNotifierProvider
.select((value) => value.locale));
@ -114,12 +125,20 @@ class _WalletSummaryInfoState extends State<WalletSummaryInfo> {
onTap: showSheet,
child: Row(
children: [
Text(
"${_showAvailable ? "Available" : "Full"} Balance",
style: STextStyles.subtitle.copyWith(
fontWeight: FontWeight.w500,
if (coin == Coin.firo || coin == Coin.firoTestNet)
Text(
"${_showAvailable ? "Private" : "Public"} Balance",
style: STextStyles.subtitle.copyWith(
fontWeight: FontWeight.w500,
),
),
if (coin != Coin.firo && coin != Coin.firoTestNet)
Text(
"${_showAvailable ? "Available" : "Full"} Balance",
style: STextStyles.subtitle.copyWith(
fontWeight: FontWeight.w500,
),
),
),
const SizedBox(
width: 4,
),
@ -166,12 +185,20 @@ class _WalletSummaryInfoState extends State<WalletSummaryInfo> {
onTap: showSheet,
child: Row(
children: [
Text(
"${_showAvailable ? "Available" : "Full"} Balance",
style: STextStyles.subtitle.copyWith(
fontWeight: FontWeight.w500,
if (coin == Coin.firo || coin == Coin.firoTestNet)
Text(
"${_showAvailable ? "Private" : "Public"} Balance",
style: STextStyles.subtitle.copyWith(
fontWeight: FontWeight.w500,
),
),
if (coin != Coin.firo && coin != Coin.firoTestNet)
Text(
"${_showAvailable ? "Available" : "Full"} Balance",
style: STextStyles.subtitle.copyWith(
fontWeight: FontWeight.w500,
),
),
),
const SizedBox(
width: 4,
),

View file

@ -71,11 +71,11 @@ class _TransactionDetailsViewState
fee = Format.satoshisToAmount(_transaction.fees);
amountPrefix = _transaction.txType.toLowerCase() == "sent" ? "- " : "+ ";
if (coin == Coin.firo || coin == Coin.firoTestNet) {
showFeePending = true;
} else {
showFeePending = false;
}
// if (coin == Coin.firo || coin == Coin.firoTestNet) {
// showFeePending = true;
// } else {
// showFeePending = false;
// }
super.initState();
}
@ -86,9 +86,10 @@ class _TransactionDetailsViewState
String whatIsIt(String type) {
if (type == "Received") {
if (_transaction.isMinting) {
return "Minting";
} else if (_transaction.confirmedStatus) {
// if (_transaction.isMinting) {
// return "Minting";
// } else
if (_transaction.confirmedStatus) {
return "Received";
} else {
return "Receiving";
@ -507,83 +508,83 @@ class _TransactionDetailsViewState
],
),
),
if ((coin == Coin.firoTestNet || coin == Coin.firo) &&
_transaction.subType == "mint")
const SizedBox(
height: 12,
),
if ((coin == Coin.firoTestNet || coin == Coin.firo) &&
_transaction.subType == "mint")
RoundedWhiteContainer(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Mint Transaction ID",
style: STextStyles.itemSubtitle,
),
],
),
const SizedBox(
height: 8,
),
// Flexible(
// child: FittedBox(
// fit: BoxFit.scaleDown,
// child:
SelectableText(
_transaction.otherData ?? "Unknown",
style: STextStyles.itemSubtitle12,
),
// ),
// ),
const SizedBox(
height: 8,
),
BlueTextButton(
text: "Open in block explorer",
onTap: () async {
final uri = getBlockExplorerTransactionUrlFor(
coin: coin,
txid: _transaction.otherData ?? "Unknown",
);
// ref
// .read(
// shouldShowLockscreenOnResumeStateProvider
// .state)
// .state = false;
try {
await launchUrl(
uri,
mode: LaunchMode.externalApplication,
);
} catch (_) {
showDialog<void>(
context: context,
builder: (_) => StackOkDialog(
title: "Could not open in block explorer",
message:
"Failed to open \"${uri.toString()}\"",
),
);
} finally {
// Future<void>.delayed(
// const Duration(seconds: 1),
// () => ref
// .read(
// shouldShowLockscreenOnResumeStateProvider
// .state)
// .state = true,
// );
}
},
),
],
),
),
// if ((coin == Coin.firoTestNet || coin == Coin.firo) &&
// _transaction.subType == "mint")
// const SizedBox(
// height: 12,
// ),
// if ((coin == Coin.firoTestNet || coin == Coin.firo) &&
// _transaction.subType == "mint")
// RoundedWhiteContainer(
// child: Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children: [
// Text(
// "Mint Transaction ID",
// style: STextStyles.itemSubtitle,
// ),
// ],
// ),
// const SizedBox(
// height: 8,
// ),
// // Flexible(
// // child: FittedBox(
// // fit: BoxFit.scaleDown,
// // child:
// SelectableText(
// _transaction.otherData ?? "Unknown",
// style: STextStyles.itemSubtitle12,
// ),
// // ),
// // ),
// const SizedBox(
// height: 8,
// ),
// BlueTextButton(
// text: "Open in block explorer",
// onTap: () async {
// final uri = getBlockExplorerTransactionUrlFor(
// coin: coin,
// txid: _transaction.otherData ?? "Unknown",
// );
// // ref
// // .read(
// // shouldShowLockscreenOnResumeStateProvider
// // .state)
// // .state = false;
// try {
// await launchUrl(
// uri,
// mode: LaunchMode.externalApplication,
// );
// } catch (_) {
// unawaited(showDialog<void>(
// context: context,
// builder: (_) => StackOkDialog(
// title: "Could not open in block explorer",
// message:
// "Failed to open \"${uri.toString()}\"",
// ),
// ));
// } finally {
// // Future<void>.delayed(
// // const Duration(seconds: 1),
// // () => ref
// // .read(
// // shouldShowLockscreenOnResumeStateProvider
// // .state)
// // .state = true,
// // );
// }
// },
// ),
// ],
// ),
// ),
if (coin == Coin.epicCash)
const SizedBox(
height: 12,

View file

@ -1,9 +1,11 @@
import 'dart:async';
import 'package:decimal/decimal.dart';
import 'package:event_bus/event_bus.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/notifications/show_flush_bar.dart';
import 'package:stackwallet/pages/exchange_view/sub_widgets/exchange_rate_sheet.dart';
import 'package:stackwallet/pages/exchange_view/wallet_initiated_exchange_view.dart';
import 'package:stackwallet/pages/home_view/home_view.dart';
@ -22,6 +24,7 @@ import 'package:stackwallet/providers/global/auto_swb_service_provider.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/providers/ui/transaction_filter_provider.dart';
import 'package:stackwallet/providers/ui/unread_notifications_provider.dart';
import 'package:stackwallet/services/coins/firo/firo_wallet.dart';
import 'package:stackwallet/services/coins/manager.dart';
import 'package:stackwallet/services/event_bus/events/global/node_connection_status_changed_event.dart';
import 'package:stackwallet/services/event_bus/events/global/wallet_sync_status_changed_event.dart';
@ -31,12 +34,18 @@ import 'package:stackwallet/utilities/cfcolors.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/backup_frequency_type.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/flush_bar_type.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
import 'package:stackwallet/widgets/custom_loading_overlay.dart';
import 'package:stackwallet/widgets/stack_dialog.dart';
import 'package:tuple/tuple.dart';
import '../../providers/wallet/public_private_balance_state_provider.dart';
import '../../providers/wallet/wallet_balance_toggle_state_provider.dart';
import '../../utilities/enums/wallet_balance_toggle_state.dart';
/// [eventBus] should only be set during testing
class WalletView extends ConsumerStatefulWidget {
const WalletView({
@ -271,10 +280,78 @@ class _WalletViewState extends ConsumerState<WalletView> {
}
}
Future<void> attemptAnonymize() async {
bool shouldPop = false;
unawaited(
showDialog(
context: context,
builder: (context) => WillPopScope(
child: const CustomLoadingOverlay(
message: "Anonymizing balance",
eventBus: null,
),
onWillPop: () async => shouldPop,
),
),
);
final firoWallet = ref.read(managerProvider).wallet as FiroWallet;
final publicBalance = await firoWallet.availablePublicBalance();
if (publicBalance <= Decimal.zero) {
shouldPop = true;
if (mounted) {
Navigator.of(context).popUntil(
ModalRoute.withName(WalletView.routeName),
);
unawaited(
showFloatingFlushBar(
type: FlushBarType.info,
message: "No funds available to anonymize!",
context: context,
),
);
}
return;
}
try {
await firoWallet.anonymizeAllPublicFunds();
shouldPop = true;
if (mounted) {
Navigator.of(context).popUntil(
ModalRoute.withName(WalletView.routeName),
);
unawaited(
showFloatingFlushBar(
type: FlushBarType.success,
message: "Anonymize transaction submitted",
context: context,
),
);
}
} catch (e) {
shouldPop = true;
if (mounted) {
Navigator.of(context).popUntil(
ModalRoute.withName(WalletView.routeName),
);
await showDialog<dynamic>(
context: context,
builder: (_) => StackOkDialog(
title: "Anonymize all failed",
message: "Reason: $e",
),
);
}
}
}
@override
Widget build(BuildContext context) {
debugPrint("BUILD: $runtimeType");
final coin = ref.watch(managerProvider.select((value) => value.coin));
return WillPopScope(
onWillPop: _onWillPop,
child: Scaffold(
@ -283,9 +360,7 @@ class _WalletViewState extends ConsumerState<WalletView> {
title: Row(
children: [
SvgPicture.asset(
Assets.svg.iconFor(
coin: ref
.watch(managerProvider.select((value) => value.coin))),
Assets.svg.iconFor(coin: coin),
// color: CFColors.stackAccent,
width: 24,
height: 24,
@ -440,6 +515,69 @@ class _WalletViewState extends ConsumerState<WalletView> {
),
),
),
if (coin == Coin.firo)
const SizedBox(
height: 10,
),
if (coin == Coin.firo)
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Row(
children: [
Expanded(
child: TextButton(
onPressed: () async {
await showDialog<void>(
context: context,
builder: (context) => StackDialog(
title: "Attention!",
message:
"You're about to anonymize all of your public funds.",
leftButton: TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text(
"Cancel",
style: STextStyles.button.copyWith(
color: CFColors.stackAccent,
),
),
),
rightButton: TextButton(
onPressed: () async {
Navigator.of(context).pop();
unawaited(attemptAnonymize());
},
style: Theme.of(context)
.textButtonTheme
.style
?.copyWith(
backgroundColor:
MaterialStateProperty.all<Color>(
CFColors.stackAccent,
),
),
child: Text(
"Continue",
style: STextStyles.button,
),
),
),
);
},
child: Text(
"Anonymize funds",
style: STextStyles.button.copyWith(
color: CFColors.stackAccent,
),
),
),
),
],
),
),
const SizedBox(
height: 20,
),
@ -550,6 +688,25 @@ class _WalletViewState extends ConsumerState<WalletView> {
ref.read(managerProvider).walletId;
final coin =
ref.read(managerProvider).coin;
switch (ref
.read(walletBalanceToggleStateProvider
.state)
.state) {
case WalletBalanceToggleState.full:
ref
.read(
publicPrivateBalanceStateProvider
.state)
.state = "Public";
break;
case WalletBalanceToggleState.available:
ref
.read(
publicPrivateBalanceStateProvider
.state)
.state = "Private";
break;
}
Navigator.of(context).pushNamed(
SendView.routeName,
arguments: Tuple2(

View file

@ -0,0 +1,4 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
final publicPrivateBalanceStateProvider =
StateProvider<String>((_) => "Private");

View file

@ -1761,7 +1761,12 @@ class FiroWallet extends CoinServiceAPI {
balances.add(
(lelantusBalance + utxosValue + _unconfirmedLelantusBalance) * price);
balances.add(utxosValue);
int availableSats =
utxos.satoshiBalance - utxos.satoshiBalanceUnconfirmed;
if (availableSats < 0) {
availableSats = 0;
}
balances.add(Format.satoshisToAmount(availableSats));
Logging.instance.log("balances $balances", level: LogLevel.Info);
await DB.instance.put<dynamic>(
@ -2782,6 +2787,7 @@ class FiroWallet extends CoinServiceAPI {
Decimal currentPrice = await firoPrice;
final List<Map<String, dynamic>> outputArray = [];
int satoshiBalance = 0;
int satoshiBalancePending = 0;
for (int i = 0; i < utxoData.length; i++) {
for (int j = 0; j < utxoData[i].length; j++) {
@ -2795,16 +2801,22 @@ class FiroWallet extends CoinServiceAPI {
);
final Map<String, dynamic> tx = {};
final int confirmations = txn["confirmations"] as int? ?? 0;
final bool confirmed = confirmations >= MINIMUM_CONFIRMATIONS;
if (!confirmed) {
satoshiBalancePending += value;
}
tx["txid"] = txn["txid"];
tx["vout"] = utxoData[i][j]["tx_pos"];
tx["value"] = value;
tx["status"] = <String, dynamic>{};
tx["status"]["confirmed"] = confirmed;
tx["status"]["confirmations"] = confirmations;
tx["status"]["confirmed"] =
txn["confirmations"] == null ? false : txn["confirmations"] > 0;
tx["status"]["confirmations"] =
txn["confirmations"] == null ? 0 : txn["confirmations"]!;
tx["status"]["block_height"] = txn["height"];
tx["status"]["block_hash"] = txn["blockhash"];
tx["status"]["block_time"] = txn["blocktime"];
@ -2832,6 +2844,7 @@ class FiroWallet extends CoinServiceAPI {
.toDecimal(scaleOnInfinitePrecision: Constants.decimalPlaces)
.toString(),
"outputArray": outputArray,
"unconfirmed": satoshiBalancePending,
};
final dataModel = UtxoData.fromJson(result);

View file

@ -37,10 +37,30 @@ class _TransactionCardState extends ConsumerState<TransactionCard> {
if (coin == Coin.epicCash && _transaction.slateId == null) {
return "Restored Funds";
}
if (_transaction.subType == "mint") {
// if (type == "Received") {
if (_transaction.confirmedStatus) {
return "Anonymized";
} else {
return "Anonymizing";
}
// } else if (type == "Sent") {
// if (_transaction.confirmedStatus) {
// return "Sent MINT";
// } else {
// return "Sending MINT";
// }
// } else {
// return type;
// }
}
if (type == "Received") {
if (_transaction.isMinting) {
return "Minting";
} else if (_transaction.confirmedStatus) {
// if (_transaction.isMinting) {
// return "Minting";
// } else
if (_transaction.confirmedStatus) {
return "Received";
} else {
return "Receiving";