mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-11-17 09:47:37 +00:00
wallet navigation bar widget redesign
This commit is contained in:
parent
dea92f4adf
commit
244b4992ed
11 changed files with 965 additions and 959 deletions
|
@ -1,592 +0,0 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:stackwallet/pages/coin_control/coin_control_view.dart';
|
||||
import 'package:stackwallet/pages/paynym/paynym_claim_view.dart';
|
||||
import 'package:stackwallet/pages/paynym/paynym_home_view.dart';
|
||||
import 'package:stackwallet/providers/global/paynym_api_provider.dart';
|
||||
import 'package:stackwallet/providers/global/prefs_provider.dart';
|
||||
import 'package:stackwallet/providers/global/wallets_provider.dart';
|
||||
import 'package:stackwallet/providers/wallet/my_paynym_account_state_provider.dart';
|
||||
import 'package:stackwallet/services/mixins/paynym_wallet_interface.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart';
|
||||
import 'package:stackwallet/utilities/logger.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
||||
import 'package:stackwallet/widgets/loading_indicator.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
|
||||
class WalletNavigationBar extends ConsumerStatefulWidget {
|
||||
const WalletNavigationBar({
|
||||
Key? key,
|
||||
required this.onReceivePressed,
|
||||
required this.onSendPressed,
|
||||
required this.onExchangePressed,
|
||||
required this.onBuyPressed,
|
||||
required this.height,
|
||||
required this.enableExchange,
|
||||
required this.coin,
|
||||
required this.walletId,
|
||||
}) : super(key: key);
|
||||
|
||||
final VoidCallback onReceivePressed;
|
||||
final VoidCallback onSendPressed;
|
||||
final VoidCallback onExchangePressed;
|
||||
final VoidCallback onBuyPressed;
|
||||
final double height;
|
||||
final bool enableExchange;
|
||||
final Coin coin;
|
||||
final String walletId;
|
||||
|
||||
@override
|
||||
ConsumerState<WalletNavigationBar> createState() =>
|
||||
_WalletNavigationBarState();
|
||||
}
|
||||
|
||||
class _WalletNavigationBarState extends ConsumerState<WalletNavigationBar> {
|
||||
double scale = 0;
|
||||
final duration = const Duration(milliseconds: 200);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final showMore = ref.watch(
|
||||
walletsChangeNotifierProvider.select(
|
||||
(value) => value.getManager(widget.walletId).hasPaynymSupport,
|
||||
),
|
||||
) ||
|
||||
(ref.watch(
|
||||
walletsChangeNotifierProvider.select(
|
||||
(value) =>
|
||||
value.getManager(widget.walletId).hasCoinControlSupport,
|
||||
),
|
||||
) &&
|
||||
ref.watch(
|
||||
prefsChangeNotifierProvider.select(
|
||||
(value) => value.enableCoinControl,
|
||||
),
|
||||
));
|
||||
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
// const Spacer(),
|
||||
|
||||
AnimatedScale(
|
||||
scale: scale,
|
||||
duration: duration,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
// AnimatedOpacity(
|
||||
// opacity: scale,
|
||||
// duration: duration,
|
||||
// child: GestureDetector(
|
||||
// onTap: () {},
|
||||
// child: Container(
|
||||
// padding: const EdgeInsets.all(16),
|
||||
// width: 146,
|
||||
// decoration: BoxDecoration(
|
||||
// color:
|
||||
// Theme.of(context).extension<StackColors>()!.popupBG,
|
||||
// boxShadow: [
|
||||
// Theme.of(context)
|
||||
// .extension<StackColors>()!
|
||||
// .standardBoxShadow
|
||||
// ],
|
||||
// borderRadius: BorderRadius.circular(
|
||||
// widget.height / 2.0,
|
||||
// ),
|
||||
// ),
|
||||
// child: Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.center,
|
||||
// children: [
|
||||
// Text(
|
||||
// "Whirlpool",
|
||||
// style: STextStyles.w600_12(context),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// const SizedBox(
|
||||
// height: 8,
|
||||
// ),
|
||||
if (ref.watch(
|
||||
walletsChangeNotifierProvider.select(
|
||||
(value) => value
|
||||
.getManager(widget.walletId)
|
||||
.hasCoinControlSupport,
|
||||
),
|
||||
) &&
|
||||
ref.watch(
|
||||
prefsChangeNotifierProvider.select(
|
||||
(value) => value.enableCoinControl,
|
||||
),
|
||||
))
|
||||
AnimatedOpacity(
|
||||
opacity: scale,
|
||||
duration: duration,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
if (mounted) {
|
||||
// hide more context menu
|
||||
setState(() {
|
||||
scale = 0;
|
||||
});
|
||||
|
||||
Navigator.of(context).pushNamed(
|
||||
CoinControlView.routeName,
|
||||
arguments: Tuple2(
|
||||
widget.walletId,
|
||||
CoinControlViewType.manage,
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
width: 146,
|
||||
decoration: BoxDecoration(
|
||||
color:
|
||||
Theme.of(context).extension<StackColors>()!.popupBG,
|
||||
boxShadow: [
|
||||
Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.standardBoxShadow
|
||||
],
|
||||
borderRadius: BorderRadius.circular(
|
||||
widget.height / 2.0,
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
"Coin control",
|
||||
style: STextStyles.buttonSmall(context),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 16,
|
||||
),
|
||||
SvgPicture.asset(
|
||||
Assets.svg.coinControl.gamePad,
|
||||
height: 20,
|
||||
width: 20,
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.bottomNavIconIcon,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (ref.watch(
|
||||
walletsChangeNotifierProvider.select(
|
||||
(value) => value
|
||||
.getManager(widget.walletId)
|
||||
.hasCoinControlSupport,
|
||||
),
|
||||
) &&
|
||||
ref.watch(
|
||||
prefsChangeNotifierProvider.select(
|
||||
(value) => value.enableCoinControl,
|
||||
),
|
||||
) &&
|
||||
ref.watch(
|
||||
walletsChangeNotifierProvider.select(
|
||||
(value) =>
|
||||
value.getManager(widget.walletId).hasPaynymSupport,
|
||||
),
|
||||
))
|
||||
const SizedBox(
|
||||
height: 8,
|
||||
),
|
||||
if (ref.watch(walletsChangeNotifierProvider.select((value) =>
|
||||
value.getManager(widget.walletId).hasPaynymSupport)))
|
||||
AnimatedOpacity(
|
||||
opacity: scale,
|
||||
duration: duration,
|
||||
child: Consumer(builder: (context, ref, __) {
|
||||
return GestureDetector(
|
||||
onTap: () async {
|
||||
setState(() {
|
||||
scale = 0;
|
||||
});
|
||||
unawaited(
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => const LoadingIndicator(
|
||||
width: 100,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
final manager = ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(widget.walletId);
|
||||
|
||||
final paynymInterface =
|
||||
manager.wallet as PaynymWalletInterface;
|
||||
|
||||
final code = await paynymInterface.getPaymentCode(
|
||||
DerivePathTypeExt.primaryFor(manager.coin));
|
||||
|
||||
final account = await ref
|
||||
.read(paynymAPIProvider)
|
||||
.nym(code.toString());
|
||||
|
||||
Logging.instance.log(
|
||||
"my nym account: $account",
|
||||
level: LogLevel.Info,
|
||||
);
|
||||
|
||||
if (mounted) {
|
||||
Navigator.of(context).pop();
|
||||
|
||||
// check if account exists and for matching code to see if claimed
|
||||
if (account.value != null &&
|
||||
account.value!.codes.first.claimed) {
|
||||
ref.read(myPaynymAccountStateProvider.state).state =
|
||||
account.value!;
|
||||
|
||||
await Navigator.of(context).pushNamed(
|
||||
PaynymHomeView.routeName,
|
||||
arguments: widget.walletId,
|
||||
);
|
||||
} else {
|
||||
await Navigator.of(context).pushNamed(
|
||||
PaynymClaimView.routeName,
|
||||
arguments: widget.walletId,
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
width: 146,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.popupBG,
|
||||
boxShadow: [
|
||||
Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.standardBoxShadow
|
||||
],
|
||||
borderRadius: BorderRadius.circular(
|
||||
widget.height / 2.0,
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
"Paynym",
|
||||
style: STextStyles.buttonSmall(context),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 16,
|
||||
),
|
||||
SvgPicture.asset(
|
||||
Assets.svg.robotHead,
|
||||
height: 20,
|
||||
width: 20,
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.bottomNavIconIcon,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 8,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Container(
|
||||
height: widget.height,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).extension<StackColors>()!.bottomNavBack,
|
||||
boxShadow: [
|
||||
Theme.of(context).extension<StackColors>()!.standardBoxShadow
|
||||
],
|
||||
borderRadius: BorderRadius.circular(
|
||||
widget.height / 2.0,
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 6,
|
||||
vertical: 4,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
const SizedBox(
|
||||
width: 12,
|
||||
),
|
||||
RawMaterialButton(
|
||||
constraints: const BoxConstraints(
|
||||
minWidth: 66,
|
||||
),
|
||||
onPressed: widget.onReceivePressed,
|
||||
splashColor:
|
||||
Theme.of(context).extension<StackColors>()!.highlight,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(
|
||||
widget.height / 2.0,
|
||||
),
|
||||
),
|
||||
child: Container(
|
||||
color: Colors.transparent,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 2.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const Spacer(),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.accentColorDark
|
||||
.withOpacity(0.4),
|
||||
borderRadius: BorderRadius.circular(
|
||||
24,
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(6.0),
|
||||
child: SvgPicture.asset(
|
||||
Assets.svg.arrowDownLeft,
|
||||
width: 12,
|
||||
height: 12,
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.accentColorDark,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 4,
|
||||
),
|
||||
Text(
|
||||
"Receive",
|
||||
style: STextStyles.buttonSmall(context),
|
||||
),
|
||||
const Spacer(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
RawMaterialButton(
|
||||
constraints: const BoxConstraints(
|
||||
minWidth: 66,
|
||||
),
|
||||
onPressed: widget.onSendPressed,
|
||||
splashColor:
|
||||
Theme.of(context).extension<StackColors>()!.highlight,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(
|
||||
widget.height / 2.0,
|
||||
),
|
||||
),
|
||||
child: Container(
|
||||
color: Colors.transparent,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 2.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const Spacer(),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.accentColorDark
|
||||
.withOpacity(0.4),
|
||||
borderRadius: BorderRadius.circular(
|
||||
24,
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(6.0),
|
||||
child: SvgPicture.asset(
|
||||
Assets.svg.arrowUpRight,
|
||||
width: 12,
|
||||
height: 12,
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.accentColorDark,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 4,
|
||||
),
|
||||
Text(
|
||||
"Send",
|
||||
style: STextStyles.buttonSmall(context),
|
||||
),
|
||||
const Spacer(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (widget.enableExchange)
|
||||
RawMaterialButton(
|
||||
constraints: const BoxConstraints(
|
||||
minWidth: 66,
|
||||
),
|
||||
onPressed: widget.onExchangePressed,
|
||||
splashColor:
|
||||
Theme.of(context).extension<StackColors>()!.highlight,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(
|
||||
widget.height / 2.0,
|
||||
),
|
||||
),
|
||||
child: Container(
|
||||
color: Colors.transparent,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 2.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const Spacer(),
|
||||
SvgPicture.asset(
|
||||
Assets.svg.exchange(context),
|
||||
width: 24,
|
||||
height: 24,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 4,
|
||||
),
|
||||
Text(
|
||||
"Exchange",
|
||||
style: STextStyles.buttonSmall(context),
|
||||
),
|
||||
const Spacer(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (widget.coin.hasBuySupport)
|
||||
RawMaterialButton(
|
||||
constraints: const BoxConstraints(
|
||||
minWidth: 66,
|
||||
),
|
||||
onPressed: widget.onBuyPressed,
|
||||
splashColor:
|
||||
Theme.of(context).extension<StackColors>()!.highlight,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(
|
||||
widget.height / 2.0,
|
||||
),
|
||||
),
|
||||
child: Container(
|
||||
color: Colors.transparent,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 2.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const Spacer(),
|
||||
SvgPicture.asset(
|
||||
Assets.svg.buy(context),
|
||||
width: 24,
|
||||
height: 24,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 4,
|
||||
),
|
||||
Text(
|
||||
"Buy",
|
||||
style: STextStyles.buttonSmall(context),
|
||||
),
|
||||
const Spacer(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (showMore)
|
||||
RawMaterialButton(
|
||||
constraints: const BoxConstraints(
|
||||
minWidth: 66,
|
||||
),
|
||||
onPressed: () {
|
||||
if (scale == 0) {
|
||||
setState(() {
|
||||
scale = 1;
|
||||
});
|
||||
} else if (scale == 1) {
|
||||
setState(() {
|
||||
scale = 0;
|
||||
});
|
||||
}
|
||||
},
|
||||
splashColor:
|
||||
Theme.of(context).extension<StackColors>()!.highlight,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(
|
||||
widget.height / 2.0,
|
||||
),
|
||||
),
|
||||
child: Container(
|
||||
color: Colors.transparent,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 2.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const Spacer(),
|
||||
const SizedBox(
|
||||
height: 2,
|
||||
),
|
||||
SvgPicture.asset(
|
||||
Assets.svg.bars,
|
||||
width: 20,
|
||||
height: 20,
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.bottomNavIconIcon,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 6,
|
||||
),
|
||||
Text(
|
||||
"More",
|
||||
style: STextStyles.buttonSmall(context),
|
||||
),
|
||||
const Spacer(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 12,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
|
@ -7,21 +7,25 @@ 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/buy_view/buy_in_wallet_view.dart';
|
||||
import 'package:stackwallet/pages/coin_control/coin_control_view.dart';
|
||||
import 'package:stackwallet/pages/exchange_view/wallet_initiated_exchange_view.dart';
|
||||
import 'package:stackwallet/pages/home_view/home_view.dart';
|
||||
import 'package:stackwallet/pages/notification_views/notifications_view.dart';
|
||||
import 'package:stackwallet/pages/paynym/paynym_claim_view.dart';
|
||||
import 'package:stackwallet/pages/paynym/paynym_home_view.dart';
|
||||
import 'package:stackwallet/pages/receive_view/receive_view.dart';
|
||||
import 'package:stackwallet/pages/send_view/send_view.dart';
|
||||
import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart';
|
||||
import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_settings_view.dart';
|
||||
import 'package:stackwallet/pages/wallet_view/sub_widgets/transactions_list.dart';
|
||||
import 'package:stackwallet/pages/wallet_view/sub_widgets/wallet_navigation_bar.dart';
|
||||
import 'package:stackwallet/pages/wallet_view/sub_widgets/wallet_summary.dart';
|
||||
import 'package:stackwallet/pages/wallet_view/transaction_views/all_transactions_view.dart';
|
||||
import 'package:stackwallet/providers/global/auto_swb_service_provider.dart';
|
||||
import 'package:stackwallet/providers/global/paynym_api_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/providers/wallet/my_paynym_account_state_provider.dart';
|
||||
import 'package:stackwallet/providers/wallet/public_private_balance_state_provider.dart';
|
||||
import 'package:stackwallet/providers/wallet/wallet_balance_toggle_state_provider.dart';
|
||||
import 'package:stackwallet/services/coins/firo/firo_wallet.dart';
|
||||
|
@ -29,11 +33,14 @@ 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';
|
||||
import 'package:stackwallet/services/event_bus/global_event_bus.dart';
|
||||
import 'package:stackwallet/services/mixins/paynym_wallet_interface.dart';
|
||||
import 'package:stackwallet/utilities/assets.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/derive_path_type_enum.dart';
|
||||
import 'package:stackwallet/utilities/enums/wallet_balance_toggle_state.dart';
|
||||
import 'package:stackwallet/utilities/logger.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
||||
import 'package:stackwallet/widgets/background.dart';
|
||||
|
@ -41,7 +48,16 @@ import 'package:stackwallet/widgets/conditional_parent.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/loading_indicator.dart';
|
||||
import 'package:stackwallet/widgets/stack_dialog.dart';
|
||||
import 'package:stackwallet/widgets/wallet_navigation_bar/components/icons/buy_nav_icon.dart';
|
||||
import 'package:stackwallet/widgets/wallet_navigation_bar/components/icons/coin_control_nav_icon.dart';
|
||||
import 'package:stackwallet/widgets/wallet_navigation_bar/components/icons/exchange_nav_icon.dart';
|
||||
import 'package:stackwallet/widgets/wallet_navigation_bar/components/icons/paynym_nav_icon.dart';
|
||||
import 'package:stackwallet/widgets/wallet_navigation_bar/components/icons/receive_nav_icon.dart';
|
||||
import 'package:stackwallet/widgets/wallet_navigation_bar/components/icons/send_nav_icon.dart';
|
||||
import 'package:stackwallet/widgets/wallet_navigation_bar/components/wallet_navigation_bar_item.dart';
|
||||
import 'package:stackwallet/widgets/wallet_navigation_bar/wallet_navigation_bar.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
|
||||
/// [eventBus] should only be set during testing
|
||||
|
@ -398,297 +414,303 @@ class _WalletViewState extends ConsumerState<WalletView> {
|
|||
child: WillPopScope(
|
||||
onWillPop: _onWillPop,
|
||||
child: Background(
|
||||
child: Scaffold(
|
||||
backgroundColor:
|
||||
Theme.of(context).extension<StackColors>()!.background,
|
||||
appBar: AppBar(
|
||||
leading: AppBarBackButton(
|
||||
onPressed: () {
|
||||
_logout();
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
titleSpacing: 0,
|
||||
title: Row(
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
Assets.svg.iconFor(coin: coin),
|
||||
// color: Theme.of(context).extension<StackColors>()!.accentColorDark
|
||||
width: 24,
|
||||
height: 24,
|
||||
child: Stack(
|
||||
children: [
|
||||
Scaffold(
|
||||
backgroundColor:
|
||||
Theme.of(context).extension<StackColors>()!.background,
|
||||
appBar: AppBar(
|
||||
leading: AppBarBackButton(
|
||||
onPressed: () {
|
||||
_logout();
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
width: 16,
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
ref.watch(
|
||||
managerProvider.select((value) => value.walletName)),
|
||||
style: STextStyles.navBarTitle(context),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 10,
|
||||
bottom: 10,
|
||||
right: 10,
|
||||
),
|
||||
child: AspectRatio(
|
||||
aspectRatio: 1,
|
||||
child: AppBarIconButton(
|
||||
key: const Key("walletViewRadioButton"),
|
||||
size: 36,
|
||||
shadows: const [],
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.background,
|
||||
icon: _buildNetworkIcon(_currentSyncStatus),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pushNamed(
|
||||
WalletNetworkSettingsView.routeName,
|
||||
arguments: Tuple3(
|
||||
walletId,
|
||||
_currentSyncStatus,
|
||||
_currentNodeStatus,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 10,
|
||||
bottom: 10,
|
||||
right: 10,
|
||||
),
|
||||
child: AspectRatio(
|
||||
aspectRatio: 1,
|
||||
child: AppBarIconButton(
|
||||
key: const Key("walletViewAlertsButton"),
|
||||
size: 36,
|
||||
shadows: const [],
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.background,
|
||||
icon: SvgPicture.asset(
|
||||
ref.watch(notificationsProvider.select((value) =>
|
||||
value.hasUnreadNotificationsFor(walletId)))
|
||||
? Assets.svg.bellNew(context)
|
||||
: Assets.svg.bell,
|
||||
width: 20,
|
||||
height: 20,
|
||||
color: ref.watch(notificationsProvider.select((value) =>
|
||||
value.hasUnreadNotificationsFor(walletId)))
|
||||
? null
|
||||
: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.topNavIconPrimary,
|
||||
titleSpacing: 0,
|
||||
title: Row(
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
Assets.svg.iconFor(coin: coin),
|
||||
// color: Theme.of(context).extension<StackColors>()!.accentColorDark
|
||||
width: 24,
|
||||
height: 24,
|
||||
),
|
||||
onPressed: () {
|
||||
// reset unread state
|
||||
ref.refresh(unreadNotificationsStateProvider);
|
||||
|
||||
Navigator.of(context)
|
||||
.pushNamed(
|
||||
NotificationsView.routeName,
|
||||
arguments: walletId,
|
||||
)
|
||||
.then((_) {
|
||||
final Set<int> unreadNotificationIds = ref
|
||||
.read(unreadNotificationsStateProvider.state)
|
||||
.state;
|
||||
if (unreadNotificationIds.isEmpty) return;
|
||||
|
||||
List<Future<dynamic>> futures = [];
|
||||
for (int i = 0;
|
||||
i < unreadNotificationIds.length - 1;
|
||||
i++) {
|
||||
futures.add(ref
|
||||
.read(notificationsProvider)
|
||||
.markAsRead(
|
||||
unreadNotificationIds.elementAt(i), false));
|
||||
}
|
||||
|
||||
// wait for multiple to update if any
|
||||
Future.wait(futures).then((_) {
|
||||
// only notify listeners once
|
||||
ref
|
||||
.read(notificationsProvider)
|
||||
.markAsRead(unreadNotificationIds.last, true);
|
||||
});
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 10,
|
||||
bottom: 10,
|
||||
right: 10,
|
||||
),
|
||||
child: AspectRatio(
|
||||
aspectRatio: 1,
|
||||
child: AppBarIconButton(
|
||||
key: const Key("walletViewSettingsButton"),
|
||||
size: 36,
|
||||
shadows: const [],
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.background,
|
||||
icon: SvgPicture.asset(
|
||||
Assets.svg.bars,
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.accentColorDark,
|
||||
width: 20,
|
||||
height: 20,
|
||||
),
|
||||
onPressed: () {
|
||||
//todo: check if print needed
|
||||
// debugPrint("wallet view settings tapped");
|
||||
Navigator.of(context).pushNamed(
|
||||
WalletSettingsView.routeName,
|
||||
arguments: Tuple4(
|
||||
walletId,
|
||||
ref.read(managerProvider).coin,
|
||||
_currentSyncStatus,
|
||||
_currentNodeStatus,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
body: SafeArea(
|
||||
child: Container(
|
||||
color: Theme.of(context).extension<StackColors>()!.background,
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: WalletSummary(
|
||||
walletId: walletId,
|
||||
managerProvider: managerProvider,
|
||||
initialSyncStatus: ref.watch(managerProvider
|
||||
.select((value) => value.isRefreshing))
|
||||
? WalletSyncStatus.syncing
|
||||
: WalletSyncStatus.synced,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (coin == Coin.firo)
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
width: 16,
|
||||
),
|
||||
if (coin == Coin.firo)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextButton(
|
||||
style: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.getSecondaryEnabledButtonStyle(context),
|
||||
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(context)
|
||||
.copyWith(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.accentColorDark,
|
||||
),
|
||||
),
|
||||
),
|
||||
rightButton: TextButton(
|
||||
onPressed: () async {
|
||||
Navigator.of(context).pop();
|
||||
|
||||
unawaited(attemptAnonymize());
|
||||
},
|
||||
style: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.getPrimaryEnabledButtonStyle(
|
||||
context),
|
||||
child: Text(
|
||||
"Continue",
|
||||
style: STextStyles.button(context),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
child: Text(
|
||||
"Anonymize funds",
|
||||
style: STextStyles.button(context).copyWith(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.buttonTextSecondary,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
ref.watch(managerProvider
|
||||
.select((value) => value.walletName)),
|
||||
style: STextStyles.navBarTitle(context),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 10,
|
||||
bottom: 10,
|
||||
right: 10,
|
||||
),
|
||||
child: AspectRatio(
|
||||
aspectRatio: 1,
|
||||
child: AppBarIconButton(
|
||||
key: const Key("walletViewRadioButton"),
|
||||
size: 36,
|
||||
shadows: const [],
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.background,
|
||||
icon: _buildNetworkIcon(_currentSyncStatus),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pushNamed(
|
||||
WalletNetworkSettingsView.routeName,
|
||||
arguments: Tuple3(
|
||||
walletId,
|
||||
_currentSyncStatus,
|
||||
_currentNodeStatus,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"Transactions",
|
||||
style: STextStyles.itemSubtitle(context).copyWith(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.textDark3,
|
||||
),
|
||||
padding: const EdgeInsets.only(
|
||||
top: 10,
|
||||
bottom: 10,
|
||||
right: 10,
|
||||
),
|
||||
child: AspectRatio(
|
||||
aspectRatio: 1,
|
||||
child: AppBarIconButton(
|
||||
key: const Key("walletViewAlertsButton"),
|
||||
size: 36,
|
||||
shadows: const [],
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.background,
|
||||
icon: SvgPicture.asset(
|
||||
ref.watch(notificationsProvider.select((value) =>
|
||||
value.hasUnreadNotificationsFor(walletId)))
|
||||
? Assets.svg.bellNew(context)
|
||||
: Assets.svg.bell,
|
||||
width: 20,
|
||||
height: 20,
|
||||
color: ref.watch(notificationsProvider.select(
|
||||
(value) => value
|
||||
.hasUnreadNotificationsFor(walletId)))
|
||||
? null
|
||||
: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.topNavIconPrimary,
|
||||
),
|
||||
CustomTextButton(
|
||||
text: "See all",
|
||||
onTap: () {
|
||||
Navigator.of(context).pushNamed(
|
||||
AllTransactionsView.routeName,
|
||||
arguments: walletId,
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
onPressed: () {
|
||||
// reset unread state
|
||||
ref.refresh(unreadNotificationsStateProvider);
|
||||
|
||||
Navigator.of(context)
|
||||
.pushNamed(
|
||||
NotificationsView.routeName,
|
||||
arguments: walletId,
|
||||
)
|
||||
.then((_) {
|
||||
final Set<int> unreadNotificationIds = ref
|
||||
.read(unreadNotificationsStateProvider.state)
|
||||
.state;
|
||||
if (unreadNotificationIds.isEmpty) return;
|
||||
|
||||
List<Future<dynamic>> futures = [];
|
||||
for (int i = 0;
|
||||
i < unreadNotificationIds.length - 1;
|
||||
i++) {
|
||||
futures.add(ref
|
||||
.read(notificationsProvider)
|
||||
.markAsRead(
|
||||
unreadNotificationIds.elementAt(i),
|
||||
false));
|
||||
}
|
||||
|
||||
// wait for multiple to update if any
|
||||
Future.wait(futures).then((_) {
|
||||
// only notify listeners once
|
||||
ref.read(notificationsProvider).markAsRead(
|
||||
unreadNotificationIds.last, true);
|
||||
});
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 12,
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 10,
|
||||
bottom: 10,
|
||||
right: 10,
|
||||
),
|
||||
child: AspectRatio(
|
||||
aspectRatio: 1,
|
||||
child: AppBarIconButton(
|
||||
key: const Key("walletViewSettingsButton"),
|
||||
size: 36,
|
||||
shadows: const [],
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.background,
|
||||
icon: SvgPicture.asset(
|
||||
Assets.svg.bars,
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.accentColorDark,
|
||||
width: 20,
|
||||
height: 20,
|
||||
),
|
||||
onPressed: () {
|
||||
//todo: check if print needed
|
||||
// debugPrint("wallet view settings tapped");
|
||||
Navigator.of(context).pushNamed(
|
||||
WalletSettingsView.routeName,
|
||||
arguments: Tuple4(
|
||||
walletId,
|
||||
ref.read(managerProvider).coin,
|
||||
_currentSyncStatus,
|
||||
_currentNodeStatus,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Stack(
|
||||
children: [
|
||||
],
|
||||
),
|
||||
body: SafeArea(
|
||||
child: Container(
|
||||
color:
|
||||
Theme.of(context).extension<StackColors>()!.background,
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: WalletSummary(
|
||||
walletId: walletId,
|
||||
managerProvider: managerProvider,
|
||||
initialSyncStatus: ref.watch(managerProvider
|
||||
.select((value) => value.isRefreshing))
|
||||
? WalletSyncStatus.syncing
|
||||
: WalletSyncStatus.synced,
|
||||
),
|
||||
),
|
||||
),
|
||||
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(
|
||||
style: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.getSecondaryEnabledButtonStyle(
|
||||
context),
|
||||
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(context)
|
||||
.copyWith(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.accentColorDark,
|
||||
),
|
||||
),
|
||||
),
|
||||
rightButton: TextButton(
|
||||
onPressed: () async {
|
||||
Navigator.of(context).pop();
|
||||
|
||||
unawaited(attemptAnonymize());
|
||||
},
|
||||
style: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.getPrimaryEnabledButtonStyle(
|
||||
context),
|
||||
child: Text(
|
||||
"Continue",
|
||||
style:
|
||||
STextStyles.button(context),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
child: Text(
|
||||
"Anonymize funds",
|
||||
style:
|
||||
STextStyles.button(context).copyWith(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.buttonTextSecondary,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"Transactions",
|
||||
style:
|
||||
STextStyles.itemSubtitle(context).copyWith(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.textDark3,
|
||||
),
|
||||
),
|
||||
CustomTextButton(
|
||||
text: "See all",
|
||||
onTap: () {
|
||||
Navigator.of(context).pushNamed(
|
||||
AllTransactionsView.routeName,
|
||||
arguments: walletId,
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.vertical(
|
||||
|
@ -741,98 +763,162 @@ class _WalletViewState extends ConsumerState<WalletView> {
|
|||
),
|
||||
),
|
||||
),
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
bottom: 14,
|
||||
left: 16,
|
||||
right: 16,
|
||||
),
|
||||
child: WalletNavigationBar(
|
||||
walletId: widget.walletId,
|
||||
coin: ref.watch(managerProvider
|
||||
.select((value) => value.coin)),
|
||||
enableExchange:
|
||||
Constants.enableExchange &&
|
||||
ref.watch(managerProvider.select(
|
||||
(value) => value.coin)) !=
|
||||
Coin.epicCash,
|
||||
height: WalletView.navBarHeight,
|
||||
onExchangePressed: () =>
|
||||
_onExchangePressed(context),
|
||||
onReceivePressed: () async {
|
||||
final coin =
|
||||
ref.read(managerProvider).coin;
|
||||
if (mounted) {
|
||||
unawaited(
|
||||
Navigator.of(context).pushNamed(
|
||||
ReceiveView.routeName,
|
||||
arguments: Tuple2(
|
||||
walletId,
|
||||
coin,
|
||||
),
|
||||
));
|
||||
}
|
||||
},
|
||||
onSendPressed: () {
|
||||
final walletId =
|
||||
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(
|
||||
walletId,
|
||||
coin,
|
||||
),
|
||||
);
|
||||
},
|
||||
onBuyPressed: () {
|
||||
unawaited(
|
||||
Navigator.of(context).pushNamed(
|
||||
BuyInWalletView.routeName,
|
||||
arguments: coin,
|
||||
));
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
WalletNavigationBar(
|
||||
items: [
|
||||
WalletNavigationBarItemData(
|
||||
label: "Receive",
|
||||
icon: const ReceiveNavIcon(),
|
||||
onTap: () {
|
||||
final coin = ref.read(managerProvider).coin;
|
||||
if (mounted) {
|
||||
unawaited(
|
||||
Navigator.of(context).pushNamed(
|
||||
ReceiveView.routeName,
|
||||
arguments: Tuple2(
|
||||
walletId,
|
||||
coin,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
WalletNavigationBarItemData(
|
||||
label: "Send",
|
||||
icon: const SendNavIcon(),
|
||||
onTap: () {
|
||||
final walletId = 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(
|
||||
walletId,
|
||||
coin,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
WalletNavigationBarItemData(
|
||||
label: "Exchange",
|
||||
icon: const ExchangeNavIcon(),
|
||||
onTap: () => _onExchangePressed(context),
|
||||
),
|
||||
WalletNavigationBarItemData(
|
||||
label: "Buy",
|
||||
icon: const BuyNavIcon(),
|
||||
onTap: () {
|
||||
unawaited(
|
||||
Navigator.of(context).pushNamed(
|
||||
BuyInWalletView.routeName,
|
||||
arguments: coin,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
if (ref.watch(
|
||||
walletsChangeNotifierProvider.select(
|
||||
(value) => value
|
||||
.getManager(widget.walletId)
|
||||
.hasCoinControlSupport,
|
||||
),
|
||||
) &&
|
||||
ref.watch(
|
||||
prefsChangeNotifierProvider.select(
|
||||
(value) => value.enableCoinControl,
|
||||
),
|
||||
))
|
||||
WalletNavigationBarItemData(
|
||||
label: "Coin control",
|
||||
icon: const CoinControlNavIcon(),
|
||||
onTap: () {
|
||||
Navigator.of(context).pushNamed(
|
||||
CoinControlView.routeName,
|
||||
arguments: Tuple2(
|
||||
widget.walletId,
|
||||
CoinControlViewType.manage,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
if (ref.watch(walletsChangeNotifierProvider.select((value) =>
|
||||
value.getManager(widget.walletId).hasPaynymSupport)))
|
||||
WalletNavigationBarItemData(
|
||||
label: "PayNym",
|
||||
icon: const PaynymNavIcon(),
|
||||
onTap: () async {
|
||||
unawaited(
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => const LoadingIndicator(
|
||||
width: 100,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
final manager = ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(widget.walletId);
|
||||
|
||||
final paynymInterface =
|
||||
manager.wallet as PaynymWalletInterface;
|
||||
|
||||
final code = await paynymInterface.getPaymentCode(
|
||||
DerivePathTypeExt.primaryFor(manager.coin));
|
||||
|
||||
final account = await ref
|
||||
.read(paynymAPIProvider)
|
||||
.nym(code.toString());
|
||||
|
||||
Logging.instance.log(
|
||||
"my nym account: $account",
|
||||
level: LogLevel.Info,
|
||||
);
|
||||
|
||||
if (mounted) {
|
||||
Navigator.of(context).pop();
|
||||
|
||||
// check if account exists and for matching code to see if claimed
|
||||
if (account.value != null &&
|
||||
account.value!.codes.first.claimed) {
|
||||
ref.read(myPaynymAccountStateProvider.state).state =
|
||||
account.value!;
|
||||
|
||||
await Navigator.of(context).pushNamed(
|
||||
PaynymHomeView.routeName,
|
||||
arguments: widget.walletId,
|
||||
);
|
||||
} else {
|
||||
await Navigator.of(context).pushNamed(
|
||||
PaynymClaimView.routeName,
|
||||
arguments: widget.walletId,
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
|
||||
class BuyNavIcon extends StatelessWidget {
|
||||
const BuyNavIcon({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SvgPicture.asset(
|
||||
Assets.svg.buy(context),
|
||||
width: 24,
|
||||
height: 24,
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
||||
|
||||
class CoinControlNavIcon extends StatelessWidget {
|
||||
const CoinControlNavIcon({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SvgPicture.asset(
|
||||
Assets.svg.coinControl.gamePad,
|
||||
height: 20,
|
||||
width: 20,
|
||||
color: Theme.of(context).extension<StackColors>()!.bottomNavIconIcon,
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
|
||||
class ExchangeNavIcon extends StatelessWidget {
|
||||
const ExchangeNavIcon({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SvgPicture.asset(
|
||||
Assets.svg.exchange(context),
|
||||
width: 24,
|
||||
height: 24,
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
||||
|
||||
class PaynymNavIcon extends StatelessWidget {
|
||||
const PaynymNavIcon({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SvgPicture.asset(
|
||||
Assets.svg.robotHead,
|
||||
height: 20,
|
||||
width: 20,
|
||||
color: Theme.of(context).extension<StackColors>()!.bottomNavIconIcon,
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
||||
|
||||
class ReceiveNavIcon extends StatelessWidget {
|
||||
const ReceiveNavIcon({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.accentColorDark
|
||||
.withOpacity(0.4),
|
||||
borderRadius: BorderRadius.circular(
|
||||
24,
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(6.0),
|
||||
child: SvgPicture.asset(
|
||||
Assets.svg.arrowDownLeft,
|
||||
width: 12,
|
||||
height: 12,
|
||||
color: Theme.of(context).extension<StackColors>()!.accentColorDark,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
||||
|
||||
class SendNavIcon extends StatelessWidget {
|
||||
const SendNavIcon({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.accentColorDark
|
||||
.withOpacity(0.4),
|
||||
borderRadius: BorderRadius.circular(
|
||||
24,
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(6.0),
|
||||
child: SvgPicture.asset(
|
||||
Assets.svg.arrowUpRight,
|
||||
width: 12,
|
||||
height: 12,
|
||||
color: Theme.of(context).extension<StackColors>()!.accentColorDark,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
||||
|
||||
class WhirlpoolNavIcon extends StatelessWidget {
|
||||
const WhirlpoolNavIcon({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SvgPicture.asset(
|
||||
Assets.svg.whirlPool,
|
||||
height: 20,
|
||||
width: 20,
|
||||
color: Theme.of(context).extension<StackColors>()!.bottomNavIconIcon,
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
||||
import 'package:stackwallet/widgets/rounded_container.dart';
|
||||
import 'package:stackwallet/widgets/wallet_navigation_bar/wallet_navigation_bar.dart';
|
||||
|
||||
class WalletNavigationBarItemData {
|
||||
WalletNavigationBarItemData({
|
||||
required this.icon,
|
||||
required this.label,
|
||||
required this.onTap,
|
||||
this.isMore = false,
|
||||
this.overrideText,
|
||||
});
|
||||
|
||||
final Widget icon;
|
||||
final String? label;
|
||||
final VoidCallback? onTap;
|
||||
final bool isMore;
|
||||
final Widget? overrideText;
|
||||
}
|
||||
|
||||
class WalletNavigationBarItem extends ConsumerWidget {
|
||||
const WalletNavigationBarItem({
|
||||
Key? key,
|
||||
required this.data,
|
||||
required this.disableDuration,
|
||||
}) : super(key: key);
|
||||
|
||||
final WalletNavigationBarItemData data;
|
||||
final Duration disableDuration;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
return GestureDetector(
|
||||
onTap: data.isMore || !ref.watch(walletNavBarMore.state).state
|
||||
? data.onTap
|
||||
: null,
|
||||
child: RoundedContainer(
|
||||
color: Colors.transparent,
|
||||
padding: const EdgeInsets.all(0),
|
||||
radiusMultiplier: 2,
|
||||
child: AnimatedOpacity(
|
||||
opacity:
|
||||
data.isMore || !ref.watch(walletNavBarMore.state).state ? 1 : 0.2,
|
||||
duration: disableDuration,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||
child: ConstrainedBox(
|
||||
constraints: const BoxConstraints(
|
||||
maxHeight: 45,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 24,
|
||||
height: 24,
|
||||
child: Center(
|
||||
child: data.icon,
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
data.overrideText ??
|
||||
Text(
|
||||
data.label ?? "",
|
||||
style: STextStyles.buttonSmall(context),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class WalletNavigationBarMoreItem extends ConsumerWidget {
|
||||
const WalletNavigationBarMoreItem({
|
||||
Key? key,
|
||||
required this.data,
|
||||
}) : super(key: key);
|
||||
|
||||
final WalletNavigationBarItemData data;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
data.onTap?.call();
|
||||
ref.read(walletNavBarMore.state).state = false;
|
||||
},
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: RoundedContainer(
|
||||
color: Theme.of(context).extension<StackColors>()!.bottomNavBack,
|
||||
radiusMultiplier: 100,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 16,
|
||||
horizontal: 30,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
data.label ?? "",
|
||||
textAlign: TextAlign.center,
|
||||
style: STextStyles.buttonSmall(context),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
data.icon,
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
237
lib/widgets/wallet_navigation_bar/wallet_navigation_bar.dart
Normal file
237
lib/widgets/wallet_navigation_bar/wallet_navigation_bar.dart
Normal file
|
@ -0,0 +1,237 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
||||
import 'package:stackwallet/widgets/wallet_navigation_bar/components/wallet_navigation_bar_item.dart';
|
||||
|
||||
const _kMaxItems = 5;
|
||||
|
||||
final walletNavBarMore = StateProvider.autoDispose((ref) => false);
|
||||
|
||||
class WalletNavigationBar extends ConsumerStatefulWidget {
|
||||
const WalletNavigationBar({
|
||||
Key? key,
|
||||
required this.items,
|
||||
}) : super(key: key);
|
||||
|
||||
final List<WalletNavigationBarItemData> items;
|
||||
|
||||
@override
|
||||
ConsumerState<WalletNavigationBar> createState() =>
|
||||
_WalletNavigationBarState();
|
||||
}
|
||||
|
||||
class _WalletNavigationBarState extends ConsumerState<WalletNavigationBar> {
|
||||
static const double horizontalPadding = 16;
|
||||
|
||||
final _moreDuration = const Duration(milliseconds: 200);
|
||||
|
||||
late final bool hasMore;
|
||||
|
||||
double _moreScale = 0;
|
||||
|
||||
void _onMorePressed() {
|
||||
ref.read(walletNavBarMore.state).state =
|
||||
!ref.read(walletNavBarMore.state).state;
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
hasMore = widget.items.length > _kMaxItems;
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(
|
||||
alignment: Alignment.bottomCenter,
|
||||
children: [
|
||||
IgnorePointer(
|
||||
ignoring: !ref.read(walletNavBarMore.state).state,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
if (ref.read(walletNavBarMore.state).state) {
|
||||
ref.read(walletNavBarMore.state).state = false;
|
||||
}
|
||||
},
|
||||
child: AnimatedOpacity(
|
||||
opacity: ref.watch(walletNavBarMore.state).state ? 1 : 0,
|
||||
duration: _moreDuration,
|
||||
child: Container(
|
||||
color: Colors.black.withOpacity(0.7),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
left: horizontalPadding,
|
||||
right: horizontalPadding,
|
||||
bottom: horizontalPadding,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
AnimatedScale(
|
||||
scale: ref.watch(walletNavBarMore.state).state ? 1 : 0,
|
||||
duration: _moreDuration,
|
||||
alignment: const Alignment(
|
||||
0.5,
|
||||
1.0,
|
||||
),
|
||||
child: AnimatedOpacity(
|
||||
opacity: ref.watch(walletNavBarMore.state).state ? 1 : 0,
|
||||
duration: _moreDuration,
|
||||
child: IntrinsicWidth(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
...widget.items.sublist(_kMaxItems - 1).map(
|
||||
(e) {
|
||||
return Column(
|
||||
children: [
|
||||
WalletNavigationBarMoreItem(data: e),
|
||||
const SizedBox(
|
||||
height: 8,
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Material(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(
|
||||
1000,
|
||||
),
|
||||
),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.bottomNavBack,
|
||||
boxShadow: [
|
||||
Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.standardBoxShadow
|
||||
],
|
||||
borderRadius: BorderRadius.circular(
|
||||
1000,
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 6,
|
||||
horizontal: 12,
|
||||
),
|
||||
child: IntrinsicWidth(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Spacer(),
|
||||
if (!hasMore)
|
||||
...widget.items.map(
|
||||
(e) => Flexible(
|
||||
flex: 10000,
|
||||
child: WalletNavigationBarItem(
|
||||
data: e,
|
||||
disableDuration: _moreDuration,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (hasMore)
|
||||
...widget.items.sublist(0, _kMaxItems - 1).map(
|
||||
(e) => Flexible(
|
||||
flex: 10000,
|
||||
child: WalletNavigationBarItem(
|
||||
data: e,
|
||||
disableDuration: _moreDuration,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (hasMore)
|
||||
Flexible(
|
||||
flex: 10000,
|
||||
child: WalletNavigationBarItem(
|
||||
data: WalletNavigationBarItemData(
|
||||
icon: AnimatedCrossFade(
|
||||
firstChild: SvgPicture.asset(
|
||||
Assets.svg.bars,
|
||||
width: 20,
|
||||
height: 20,
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.bottomNavIconIcon,
|
||||
),
|
||||
secondChild: SvgPicture.asset(
|
||||
Assets.svg.bars,
|
||||
width: 20,
|
||||
height: 20,
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.infoItemIcons,
|
||||
),
|
||||
crossFadeState: ref
|
||||
.watch(walletNavBarMore.state)
|
||||
.state
|
||||
? CrossFadeState.showSecond
|
||||
: CrossFadeState.showFirst,
|
||||
duration: _moreDuration,
|
||||
),
|
||||
overrideText: AnimatedCrossFade(
|
||||
firstChild: Text(
|
||||
"More",
|
||||
style:
|
||||
STextStyles.buttonSmall(context),
|
||||
),
|
||||
secondChild: Text(
|
||||
"More",
|
||||
style:
|
||||
STextStyles.buttonSmall(context)
|
||||
.copyWith(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.infoItemIcons,
|
||||
),
|
||||
),
|
||||
crossFadeState: ref
|
||||
.watch(walletNavBarMore.state)
|
||||
.state
|
||||
? CrossFadeState.showSecond
|
||||
: CrossFadeState.showFirst,
|
||||
duration: _moreDuration,
|
||||
),
|
||||
label: null,
|
||||
isMore: true,
|
||||
onTap: _onMorePressed,
|
||||
),
|
||||
disableDuration: _moreDuration,
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue