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:flutter_svg/svg.dart';
|
||||||
import 'package:stackwallet/notifications/show_flush_bar.dart';
|
import 'package:stackwallet/notifications/show_flush_bar.dart';
|
||||||
import 'package:stackwallet/pages/buy_view/buy_in_wallet_view.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/exchange_view/wallet_initiated_exchange_view.dart';
|
||||||
import 'package:stackwallet/pages/home_view/home_view.dart';
|
import 'package:stackwallet/pages/home_view/home_view.dart';
|
||||||
import 'package:stackwallet/pages/notification_views/notifications_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/receive_view/receive_view.dart';
|
||||||
import 'package:stackwallet/pages/send_view/send_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_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/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/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/sub_widgets/wallet_summary.dart';
|
||||||
import 'package:stackwallet/pages/wallet_view/transaction_views/all_transactions_view.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/auto_swb_service_provider.dart';
|
||||||
|
import 'package:stackwallet/providers/global/paynym_api_provider.dart';
|
||||||
import 'package:stackwallet/providers/providers.dart';
|
import 'package:stackwallet/providers/providers.dart';
|
||||||
import 'package:stackwallet/providers/ui/transaction_filter_provider.dart';
|
import 'package:stackwallet/providers/ui/transaction_filter_provider.dart';
|
||||||
import 'package:stackwallet/providers/ui/unread_notifications_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/public_private_balance_state_provider.dart';
|
||||||
import 'package:stackwallet/providers/wallet/wallet_balance_toggle_state_provider.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/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/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/events/global/wallet_sync_status_changed_event.dart';
|
||||||
import 'package:stackwallet/services/event_bus/global_event_bus.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/assets.dart';
|
||||||
import 'package:stackwallet/utilities/constants.dart';
|
import 'package:stackwallet/utilities/constants.dart';
|
||||||
import 'package:stackwallet/utilities/enums/backup_frequency_type.dart';
|
import 'package:stackwallet/utilities/enums/backup_frequency_type.dart';
|
||||||
import 'package:stackwallet/utilities/enums/coin_enum.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/enums/wallet_balance_toggle_state.dart';
|
||||||
|
import 'package:stackwallet/utilities/logger.dart';
|
||||||
import 'package:stackwallet/utilities/text_styles.dart';
|
import 'package:stackwallet/utilities/text_styles.dart';
|
||||||
import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
||||||
import 'package:stackwallet/widgets/background.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/app_bar_icon_button.dart';
|
||||||
import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
|
import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
|
||||||
import 'package:stackwallet/widgets/custom_loading_overlay.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/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';
|
import 'package:tuple/tuple.dart';
|
||||||
|
|
||||||
/// [eventBus] should only be set during testing
|
/// [eventBus] should only be set during testing
|
||||||
|
@ -398,297 +414,303 @@ class _WalletViewState extends ConsumerState<WalletView> {
|
||||||
child: WillPopScope(
|
child: WillPopScope(
|
||||||
onWillPop: _onWillPop,
|
onWillPop: _onWillPop,
|
||||||
child: Background(
|
child: Background(
|
||||||
child: Scaffold(
|
child: Stack(
|
||||||
backgroundColor:
|
children: [
|
||||||
Theme.of(context).extension<StackColors>()!.background,
|
Scaffold(
|
||||||
appBar: AppBar(
|
backgroundColor:
|
||||||
leading: AppBarBackButton(
|
Theme.of(context).extension<StackColors>()!.background,
|
||||||
onPressed: () {
|
appBar: AppBar(
|
||||||
_logout();
|
leading: AppBarBackButton(
|
||||||
Navigator.of(context).pop();
|
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,
|
|
||||||
),
|
),
|
||||||
const SizedBox(
|
titleSpacing: 0,
|
||||||
width: 16,
|
title: Row(
|
||||||
),
|
children: [
|
||||||
Expanded(
|
SvgPicture.asset(
|
||||||
child: Text(
|
Assets.svg.iconFor(coin: coin),
|
||||||
ref.watch(
|
// color: Theme.of(context).extension<StackColors>()!.accentColorDark
|
||||||
managerProvider.select((value) => value.walletName)),
|
width: 24,
|
||||||
style: STextStyles.navBarTitle(context),
|
height: 24,
|
||||||
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,
|
|
||||||
),
|
),
|
||||||
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(
|
const SizedBox(
|
||||||
height: 10,
|
width: 16,
|
||||||
),
|
),
|
||||||
if (coin == Coin.firo)
|
Expanded(
|
||||||
Padding(
|
child: Text(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
ref.watch(managerProvider
|
||||||
child: Row(
|
.select((value) => value.walletName)),
|
||||||
children: [
|
style: STextStyles.navBarTitle(context),
|
||||||
Expanded(
|
overflow: TextOverflow.ellipsis,
|
||||||
child: TextButton(
|
),
|
||||||
style: Theme.of(context)
|
)
|
||||||
.extension<StackColors>()!
|
],
|
||||||
.getSecondaryEnabledButtonStyle(context),
|
),
|
||||||
onPressed: () async {
|
actions: [
|
||||||
await showDialog<void>(
|
Padding(
|
||||||
context: context,
|
padding: const EdgeInsets.only(
|
||||||
builder: (context) => StackDialog(
|
top: 10,
|
||||||
title: "Attention!",
|
bottom: 10,
|
||||||
message:
|
right: 10,
|
||||||
"You're about to anonymize all of your public funds.",
|
),
|
||||||
leftButton: TextButton(
|
child: AspectRatio(
|
||||||
onPressed: () {
|
aspectRatio: 1,
|
||||||
Navigator.of(context).pop();
|
child: AppBarIconButton(
|
||||||
},
|
key: const Key("walletViewRadioButton"),
|
||||||
child: Text(
|
size: 36,
|
||||||
"Cancel",
|
shadows: const [],
|
||||||
style: STextStyles.button(context)
|
color: Theme.of(context)
|
||||||
.copyWith(
|
.extension<StackColors>()!
|
||||||
color: Theme.of(context)
|
.background,
|
||||||
.extension<StackColors>()!
|
icon: _buildNetworkIcon(_currentSyncStatus),
|
||||||
.accentColorDark,
|
onPressed: () {
|
||||||
),
|
Navigator.of(context).pushNamed(
|
||||||
),
|
WalletNetworkSettingsView.routeName,
|
||||||
),
|
arguments: Tuple3(
|
||||||
rightButton: TextButton(
|
walletId,
|
||||||
onPressed: () async {
|
_currentSyncStatus,
|
||||||
Navigator.of(context).pop();
|
_currentNodeStatus,
|
||||||
|
|
||||||
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(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
padding: const EdgeInsets.only(
|
||||||
child: Row(
|
top: 10,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
bottom: 10,
|
||||||
children: [
|
right: 10,
|
||||||
Text(
|
),
|
||||||
"Transactions",
|
child: AspectRatio(
|
||||||
style: STextStyles.itemSubtitle(context).copyWith(
|
aspectRatio: 1,
|
||||||
color: Theme.of(context)
|
child: AppBarIconButton(
|
||||||
.extension<StackColors>()!
|
key: const Key("walletViewAlertsButton"),
|
||||||
.textDark3,
|
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(
|
onPressed: () {
|
||||||
text: "See all",
|
// reset unread state
|
||||||
onTap: () {
|
ref.refresh(unreadNotificationsStateProvider);
|
||||||
Navigator.of(context).pushNamed(
|
|
||||||
AllTransactionsView.routeName,
|
Navigator.of(context)
|
||||||
arguments: walletId,
|
.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(
|
Padding(
|
||||||
height: 12,
|
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(
|
||||||
|
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),
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
child: ClipRRect(
|
child: ClipRRect(
|
||||||
borderRadius: BorderRadius.vertical(
|
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