Before Width: | Height: | Size: 677 KiB |
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 68 KiB |
Before Width: | Height: | Size: 677 KiB |
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 68 KiB |
Before Width: | Height: | Size: 677 KiB |
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 68 KiB |
|
@ -2,6 +2,8 @@
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
|
<key>ITSAppUsesNonExemptEncryption</key>
|
||||||
|
<false/>
|
||||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
@ -29,7 +31,7 @@
|
||||||
<key>LSSupportsOpeningDocumentsInPlace</key>
|
<key>LSSupportsOpeningDocumentsInPlace</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>NSCameraUsageDescription</key>
|
<key>NSCameraUsageDescription</key>
|
||||||
<string>App requires access to the Camera to scan QR codes from other people's installed app in order to coordinate sending Firo.</string>
|
<string>App requires access to the Camera to scan QR codes from other people's installed app in order to coordinate sending.</string>
|
||||||
<key>NSFaceIDUsageDescription</key>
|
<key>NSFaceIDUsageDescription</key>
|
||||||
<string>This app requires Face ID permissions so that the user can securely lock their wallet if their device uses Face ID. It will be useful feature for all users, and especially those prone to forget their login pin on iPhones where Touch ID is not available.</string>
|
<string>This app requires Face ID permissions so that the user can securely lock their wallet if their device uses Face ID. It will be useful feature for all users, and especially those prone to forget their login pin on iPhones where Touch ID is not available.</string>
|
||||||
<key>NSPhotoLibraryUsageDescription</key>
|
<key>NSPhotoLibraryUsageDescription</key>
|
||||||
|
|
|
@ -28,8 +28,6 @@ class AddWalletNextButton extends ConsumerWidget {
|
||||||
final selectedCoin =
|
final selectedCoin =
|
||||||
ref.read(addWalletSelectedCoinStateProvider.state).state;
|
ref.read(addWalletSelectedCoinStateProvider.state).state;
|
||||||
|
|
||||||
//todo: check if print needed
|
|
||||||
// debugPrint("Next pressed with ${selectedCoin!.name} selected!");
|
|
||||||
Navigator.of(context).pushNamed(
|
Navigator.of(context).pushNamed(
|
||||||
CreateOrRestoreWalletView.routeName,
|
CreateOrRestoreWalletView.routeName,
|
||||||
arguments: selectedCoin,
|
arguments: selectedCoin,
|
||||||
|
|
|
@ -89,20 +89,18 @@ class CreateOrRestoreWalletView extends StatelessWidget {
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
body: Container(
|
body: SafeArea(
|
||||||
|
child: Container(
|
||||||
color: Theme.of(context).extension<StackColors>()!.background,
|
color: Theme.of(context).extension<StackColors>()!.background,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
CoinImage(
|
||||||
padding: const EdgeInsets.all(31),
|
|
||||||
child: CoinImage(
|
|
||||||
coin: coin,
|
coin: coin,
|
||||||
isDesktop: isDesktop,
|
isDesktop: isDesktop,
|
||||||
),
|
),
|
||||||
),
|
|
||||||
const Spacer(
|
const Spacer(
|
||||||
flex: 2,
|
flex: 2,
|
||||||
),
|
),
|
||||||
|
@ -128,6 +126,7 @@ class CreateOrRestoreWalletView extends StatelessWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ class CoinImage extends ConsumerWidget {
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
return SvgPicture.asset(
|
return SvgPicture.asset(
|
||||||
Assets.svg.imageFor(coin: coin, context: context),
|
Assets.svg.imageFor(coin: coin, context: context),
|
||||||
width: isDesktop ? 324 : MediaQuery.of(context).size.width,
|
width: isDesktop ? 324 : MediaQuery.of(context).size.width / 1.6,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,7 +76,7 @@ class _FiatSelectionViewState extends State<FiatSelectionView> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
Locale locale = Localizations.localeOf(context);
|
Locale locale = Localizations.localeOf(context);
|
||||||
var format = NumberFormat.simpleCurrency(locale: locale.toString());
|
final format = NumberFormat.simpleCurrency(locale: locale.toString());
|
||||||
// See https://stackoverflow.com/a/67055685
|
// See https://stackoverflow.com/a/67055685
|
||||||
|
|
||||||
final isDesktop = Util.isDesktop;
|
final isDesktop = Util.isDesktop;
|
||||||
|
@ -186,21 +186,33 @@ class _FiatSelectionViewState extends State<FiatSelectionView> {
|
||||||
height: 12,
|
height: 12,
|
||||||
),
|
),
|
||||||
Flexible(
|
Flexible(
|
||||||
|
child: SingleChildScrollView(
|
||||||
child: RoundedWhiteContainer(
|
child: RoundedWhiteContainer(
|
||||||
padding: const EdgeInsets.all(0),
|
padding: const EdgeInsets.all(0),
|
||||||
child: ListView.builder(
|
child: Table(
|
||||||
shrinkWrap: true,
|
columnWidths: const {
|
||||||
primary: isDesktop ? false : null,
|
0: IntrinsicColumnWidth(),
|
||||||
itemCount: _fiats.length,
|
1: FlexColumnWidth(),
|
||||||
itemBuilder: (builderContext, index) {
|
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 4),
|
|
||||||
child: GestureDetector(
|
|
||||||
onTap: () {
|
|
||||||
Navigator.of(context).pop(_fiats[index]);
|
|
||||||
},
|
},
|
||||||
child: RoundedWhiteContainer(
|
defaultVerticalAlignment: TableCellVerticalAlignment.middle,
|
||||||
child: Row(
|
children: [
|
||||||
|
..._fiats.map(
|
||||||
|
(e) {
|
||||||
|
return TableRow(
|
||||||
|
children: [
|
||||||
|
TableCell(
|
||||||
|
verticalAlignment:
|
||||||
|
TableCellVerticalAlignment.fill,
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () => Navigator.of(context).pop(e),
|
||||||
|
child: Container(
|
||||||
|
color: Colors.transparent,
|
||||||
|
padding: const EdgeInsets.only(left: 12),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.stretch,
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.all(7.5),
|
padding: const EdgeInsets.all(7.5),
|
||||||
|
@ -208,42 +220,52 @@ class _FiatSelectionViewState extends State<FiatSelectionView> {
|
||||||
color: Theme.of(context)
|
color: Theme.of(context)
|
||||||
.extension<StackColors>()!
|
.extension<StackColors>()!
|
||||||
.currencyListItemBG,
|
.currencyListItemBG,
|
||||||
borderRadius: BorderRadius.circular(4),
|
borderRadius:
|
||||||
|
BorderRadius.circular(4),
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
format.simpleCurrencySymbol(
|
format.simpleCurrencySymbol(
|
||||||
_fiats[index].ticker.toUpperCase()),
|
e.ticker.toUpperCase()),
|
||||||
style: STextStyles.subtitle(context).apply(
|
style: STextStyles.subtitle(context)
|
||||||
|
.apply(
|
||||||
fontSizeFactor: (1 /
|
fontSizeFactor: (1 /
|
||||||
format
|
format
|
||||||
.simpleCurrencySymbol(_fiats[index]
|
.simpleCurrencySymbol(
|
||||||
.ticker
|
e.ticker.toUpperCase())
|
||||||
.toUpperCase())
|
|
||||||
.length * // Couldn't get pow() working here
|
.length * // Couldn't get pow() working here
|
||||||
format
|
format
|
||||||
.simpleCurrencySymbol(_fiats[index]
|
.simpleCurrencySymbol(
|
||||||
.ticker
|
e.ticker.toUpperCase())
|
||||||
.toUpperCase())
|
.length),
|
||||||
.length)),
|
),
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(
|
],
|
||||||
width: 10,
|
|
||||||
),
|
),
|
||||||
Expanded(
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () => Navigator.of(context).pop(e),
|
||||||
|
child: Container(
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(12),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
_fiats[index].name,
|
e.name,
|
||||||
style: STextStyles.largeMedium14(context),
|
style:
|
||||||
|
STextStyles.largeMedium14(context),
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 2,
|
height: 2,
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
_fiats[index].ticker.toUpperCase(),
|
e.ticker.toUpperCase(),
|
||||||
style: STextStyles.smallMed12(context)
|
style: STextStyles.smallMed12(context)
|
||||||
.copyWith(
|
.copyWith(
|
||||||
color: Theme.of(context)
|
color: Theme.of(context)
|
||||||
|
@ -254,13 +276,89 @@ class _FiatSelectionViewState extends State<FiatSelectionView> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
// child: ListView.builder(
|
||||||
|
// shrinkWrap: true,
|
||||||
|
// primary: isDesktop ? false : null,
|
||||||
|
// itemCount: _fiats.length,
|
||||||
|
// itemBuilder: (builderContext, index) {
|
||||||
|
// return Padding(
|
||||||
|
// padding: const EdgeInsets.symmetric(vertical: 4),
|
||||||
|
// child: GestureDetector(
|
||||||
|
// onTap: () {
|
||||||
|
// Navigator.of(context).pop(_fiats[index]);
|
||||||
|
// },
|
||||||
|
// child: RoundedWhiteContainer(
|
||||||
|
// child: Row(
|
||||||
|
// children: [
|
||||||
|
// Container(
|
||||||
|
// padding: const EdgeInsets.all(7.5),
|
||||||
|
// decoration: BoxDecoration(
|
||||||
|
// color: Theme.of(context)
|
||||||
|
// .extension<StackColors>()!
|
||||||
|
// .currencyListItemBG,
|
||||||
|
// borderRadius: BorderRadius.circular(4),
|
||||||
|
// ),
|
||||||
|
// child: Text(
|
||||||
|
// format.simpleCurrencySymbol(
|
||||||
|
// _fiats[index].ticker.toUpperCase()),
|
||||||
|
// style: STextStyles.subtitle(context).apply(
|
||||||
|
// fontSizeFactor: (1 /
|
||||||
|
// format
|
||||||
|
// .simpleCurrencySymbol(_fiats[index]
|
||||||
|
// .ticker
|
||||||
|
// .toUpperCase())
|
||||||
|
// .length * // Couldn't get pow() working here
|
||||||
|
// format
|
||||||
|
// .simpleCurrencySymbol(_fiats[index]
|
||||||
|
// .ticker
|
||||||
|
// .toUpperCase())
|
||||||
|
// .length)),
|
||||||
|
// textAlign: TextAlign.center,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// const SizedBox(
|
||||||
|
// width: 10,
|
||||||
|
// ),
|
||||||
|
// Expanded(
|
||||||
|
// child: Column(
|
||||||
|
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
// children: [
|
||||||
|
// Text(
|
||||||
|
// _fiats[index].name,
|
||||||
|
// style: STextStyles.largeMedium14(context),
|
||||||
|
// ),
|
||||||
|
// const SizedBox(
|
||||||
|
// height: 2,
|
||||||
|
// ),
|
||||||
|
// Text(
|
||||||
|
// _fiats[index].ticker.toUpperCase(),
|
||||||
|
// style: STextStyles.smallMed12(context)
|
||||||
|
// .copyWith(
|
||||||
|
// color: Theme.of(context)
|
||||||
|
// .extension<StackColors>()!
|
||||||
|
// .textSubtitle1,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
// },
|
||||||
|
// ),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:isar/isar.dart';
|
|
||||||
import 'package:stackwallet/db/main_db.dart';
|
import 'package:stackwallet/db/main_db.dart';
|
||||||
import 'package:stackwallet/models/isar/models/isar_models.dart';
|
import 'package:stackwallet/models/isar/models/isar_models.dart';
|
||||||
import 'package:stackwallet/providers/global/wallets_provider.dart';
|
import 'package:stackwallet/providers/global/wallets_provider.dart';
|
||||||
|
@ -36,7 +35,8 @@ class UtxoCard extends ConsumerStatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _UtxoCardState extends ConsumerState<UtxoCard> {
|
class _UtxoCardState extends ConsumerState<UtxoCard> {
|
||||||
late final UTXO utxo;
|
late Stream<UTXO?> stream;
|
||||||
|
late UTXO utxo;
|
||||||
|
|
||||||
late bool _selected;
|
late bool _selected;
|
||||||
|
|
||||||
|
@ -44,6 +44,8 @@ class _UtxoCardState extends ConsumerState<UtxoCard> {
|
||||||
void initState() {
|
void initState() {
|
||||||
_selected = widget.initialSelectedState;
|
_selected = widget.initialSelectedState;
|
||||||
utxo = widget.utxo;
|
utxo = widget.utxo;
|
||||||
|
|
||||||
|
stream = MainDB.instance.watchUTXO(id: utxo.id);
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,19 +59,6 @@ class _UtxoCardState extends ConsumerState<UtxoCard> {
|
||||||
final currentChainHeight = ref.watch(walletsChangeNotifierProvider
|
final currentChainHeight = ref.watch(walletsChangeNotifierProvider
|
||||||
.select((value) => value.getManager(widget.walletId).currentHeight));
|
.select((value) => value.getManager(widget.walletId).currentHeight));
|
||||||
|
|
||||||
String? label;
|
|
||||||
if (utxo.address != null) {
|
|
||||||
label = MainDB.instance.isar.addressLabels
|
|
||||||
.where()
|
|
||||||
.addressStringWalletIdEqualTo(utxo.address!, widget.walletId)
|
|
||||||
.findFirstSync()
|
|
||||||
?.value;
|
|
||||||
|
|
||||||
if (label != null && label.isEmpty) {
|
|
||||||
label = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ConditionalParent(
|
return ConditionalParent(
|
||||||
condition: widget.onPressed != null,
|
condition: widget.onPressed != null,
|
||||||
builder: (child) => MaterialButton(
|
builder: (child) => MaterialButton(
|
||||||
|
@ -92,7 +81,13 @@ class _UtxoCardState extends ConsumerState<UtxoCard> {
|
||||||
color: widget.onPressed == null
|
color: widget.onPressed == null
|
||||||
? Theme.of(context).extension<StackColors>()!.popupBG
|
? Theme.of(context).extension<StackColors>()!.popupBG
|
||||||
: Colors.transparent,
|
: Colors.transparent,
|
||||||
child: Row(
|
child: StreamBuilder<UTXO?>(
|
||||||
|
stream: stream,
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.hasData) {
|
||||||
|
utxo = snapshot.data!;
|
||||||
|
}
|
||||||
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
ConditionalParent(
|
ConditionalParent(
|
||||||
condition: widget.canSelect,
|
condition: widget.canSelect,
|
||||||
|
@ -112,7 +107,8 @@ class _UtxoCardState extends ConsumerState<UtxoCard> {
|
||||||
)
|
)
|
||||||
? UTXOStatusIconStatus.confirmed
|
? UTXOStatusIconStatus.confirmed
|
||||||
: UTXOStatusIconStatus.unconfirmed,
|
: UTXOStatusIconStatus.unconfirmed,
|
||||||
background: Theme.of(context).extension<StackColors>()!.popupBG,
|
background:
|
||||||
|
Theme.of(context).extension<StackColors>()!.popupBG,
|
||||||
selected: _selected,
|
selected: _selected,
|
||||||
width: 32,
|
width: 32,
|
||||||
height: 32,
|
height: 32,
|
||||||
|
@ -140,7 +136,9 @@ class _UtxoCardState extends ConsumerState<UtxoCard> {
|
||||||
children: [
|
children: [
|
||||||
Flexible(
|
Flexible(
|
||||||
child: Text(
|
child: Text(
|
||||||
label ?? utxo.address ?? utxo.txid,
|
utxo.name.isNotEmpty
|
||||||
|
? utxo.name
|
||||||
|
: utxo.address ?? utxo.txid,
|
||||||
style: STextStyles.w500_12(context).copyWith(
|
style: STextStyles.w500_12(context).copyWith(
|
||||||
color: Theme.of(context)
|
color: Theme.of(context)
|
||||||
.extension<StackColors>()!
|
.extension<StackColors>()!
|
||||||
|
@ -154,7 +152,8 @@ class _UtxoCardState extends ConsumerState<UtxoCard> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
);
|
||||||
|
}),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -176,11 +176,9 @@ class _UtxoDetailsViewState extends ConsumerState<UtxoDetailsView> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (label != null && label!.value.isNotEmpty)
|
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: _spacing,
|
height: _spacing,
|
||||||
),
|
),
|
||||||
if (label != null && label!.value.isNotEmpty)
|
|
||||||
RoundedWhiteContainer(
|
RoundedWhiteContainer(
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
@ -190,15 +188,23 @@ class _UtxoDetailsViewState extends ConsumerState<UtxoDetailsView> {
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Address label",
|
"Label",
|
||||||
style: STextStyles.w500_14(context).copyWith(
|
style: STextStyles.w500_14(context).copyWith(
|
||||||
color: Theme.of(context)
|
color: Theme.of(context)
|
||||||
.extension<StackColors>()!
|
.extension<StackColors>()!
|
||||||
.textSubtitle1,
|
.textSubtitle1,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SimpleCopyButton(
|
SimpleEditButton(
|
||||||
data: label!.value,
|
editValue: utxo!.name,
|
||||||
|
editLabel: "label",
|
||||||
|
onValueChanged: (newName) {
|
||||||
|
MainDB.instance.putUTXO(
|
||||||
|
utxo!.copyWith(
|
||||||
|
name: newName,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -206,7 +212,7 @@ class _UtxoDetailsViewState extends ConsumerState<UtxoDetailsView> {
|
||||||
height: 4,
|
height: 4,
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
label!.value,
|
utxo!.name,
|
||||||
style: STextStyles.w500_14(context),
|
style: STextStyles.w500_14(context),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -246,6 +252,42 @@ class _UtxoDetailsViewState extends ConsumerState<UtxoDetailsView> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
if (label != null && label!.value.isNotEmpty)
|
||||||
|
const SizedBox(
|
||||||
|
height: _spacing,
|
||||||
|
),
|
||||||
|
if (label != null && label!.value.isNotEmpty)
|
||||||
|
RoundedWhiteContainer(
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Address label",
|
||||||
|
style: STextStyles.w500_14(context).copyWith(
|
||||||
|
color: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.textSubtitle1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SimpleCopyButton(
|
||||||
|
data: label!.value,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 4,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
label!.value,
|
||||||
|
style: STextStyles.w500_14(context),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: _spacing,
|
height: _spacing,
|
||||||
),
|
),
|
||||||
|
@ -309,48 +351,6 @@ class _UtxoDetailsViewState extends ConsumerState<UtxoDetailsView> {
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: _spacing,
|
height: _spacing,
|
||||||
),
|
),
|
||||||
RoundedWhiteContainer(
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
"Note",
|
|
||||||
style: STextStyles.w500_14(context).copyWith(
|
|
||||||
color: Theme.of(context)
|
|
||||||
.extension<StackColors>()!
|
|
||||||
.textSubtitle1,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SimpleEditButton(
|
|
||||||
editValue: utxo!.name,
|
|
||||||
editLabel: "note",
|
|
||||||
onValueChanged: (newName) {
|
|
||||||
MainDB.instance.putUTXO(
|
|
||||||
utxo!.copyWith(
|
|
||||||
name: newName,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
height: 4,
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
utxo!.name,
|
|
||||||
style: STextStyles.w500_14(context),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
height: _spacing,
|
|
||||||
),
|
|
||||||
if (utxo!.isBlocked)
|
if (utxo!.isBlocked)
|
||||||
Column(
|
Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
|
|
@ -618,6 +618,16 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
|
||||||
if (walletInitiated) {
|
if (walletInitiated) {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||||
ref.read(exchangeFormStateProvider).reset(shouldNotifyListeners: true);
|
ref.read(exchangeFormStateProvider).reset(shouldNotifyListeners: true);
|
||||||
|
ExchangeDataLoadingService.instance
|
||||||
|
.getAggregateCurrency(
|
||||||
|
coin!.ticker,
|
||||||
|
ExchangeRateType.estimated,
|
||||||
|
)
|
||||||
|
.then((value) {
|
||||||
|
if (value != null) {
|
||||||
|
ref.read(exchangeFormStateProvider).updateSendCurrency(value, true);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
_sendController.text =
|
_sendController.text =
|
||||||
|
@ -848,7 +858,7 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
|
||||||
enabled: ref.watch(
|
enabled: ref.watch(
|
||||||
exchangeFormStateProvider.select((value) => value.canExchange)),
|
exchangeFormStateProvider.select((value) => value.canExchange)),
|
||||||
onPressed: onExchangePressed,
|
onPressed: onExchangePressed,
|
||||||
label: "Exchange",
|
label: "Swap",
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
|
@ -56,7 +56,7 @@ class _Step1ViewState extends State<Step1View> {
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
title: Text(
|
title: Text(
|
||||||
"Exchange",
|
"Swap",
|
||||||
style: STextStyles.navBarTitle(context),
|
style: STextStyles.navBarTitle(context),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -144,7 +144,7 @@ class _Step2ViewState extends ConsumerState<Step2View> {
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
title: Text(
|
title: Text(
|
||||||
"Exchange",
|
"Swap",
|
||||||
style: STextStyles.navBarTitle(context),
|
style: STextStyles.navBarTitle(context),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -72,7 +72,7 @@ class _Step3ViewState extends ConsumerState<Step3View> {
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
title: Text(
|
title: Text(
|
||||||
"Exchange",
|
"Swap",
|
||||||
style: STextStyles.navBarTitle(context),
|
style: STextStyles.navBarTitle(context),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -152,7 +152,7 @@ class _Step4ViewState extends ConsumerState<Step4View> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
title: Text(
|
title: Text(
|
||||||
"Exchange",
|
"Swap",
|
||||||
style: STextStyles.navBarTitle(context),
|
style: STextStyles.navBarTitle(context),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -322,7 +322,7 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
|
||||||
width: 16,
|
width: 16,
|
||||||
),
|
),
|
||||||
SelectableText(
|
SelectableText(
|
||||||
"Exchange",
|
"Swap service",
|
||||||
style: STextStyles.desktopTextMedium(context),
|
style: STextStyles.desktopTextMedium(context),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -1052,7 +1052,7 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Exchange",
|
"Swap service",
|
||||||
style: STextStyles.itemSubtitle(context),
|
style: STextStyles.itemSubtitle(context),
|
||||||
),
|
),
|
||||||
if (isDesktop)
|
if (isDesktop)
|
||||||
|
|
|
@ -127,7 +127,7 @@ class _WalletInitiatedExchangeViewState
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
title: Text(
|
title: Text(
|
||||||
"Exchange",
|
"Swap",
|
||||||
style: STextStyles.navBarTitle(context),
|
style: STextStyles.navBarTitle(context),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -107,23 +107,8 @@ class _HomeViewState extends ConsumerState<HomeView> {
|
||||||
_rotateIconController = RotateIconController();
|
_rotateIconController = RotateIconController();
|
||||||
_children = [
|
_children = [
|
||||||
const WalletsView(),
|
const WalletsView(),
|
||||||
if (Constants.enableExchange)
|
if (Constants.enableExchange) const ExchangeView(),
|
||||||
Stack(
|
if (Constants.enableExchange) const BuyView(),
|
||||||
children: [
|
|
||||||
const ExchangeView(),
|
|
||||||
// ExchangeLoadingOverlayView(
|
|
||||||
// unawaitedLoad: _loadCNData,
|
|
||||||
// ),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
if (Constants.enableBuy)
|
|
||||||
// Stack(
|
|
||||||
// children: [
|
|
||||||
const BuyView(),
|
|
||||||
// BuyLoadingOverlayView(
|
|
||||||
// unawaitedLoad: _loadSimplexData,
|
|
||||||
// ),
|
|
||||||
// ],
|
|
||||||
];
|
];
|
||||||
|
|
||||||
ref.read(notificationsProvider).startCheckingWatchedNotifications();
|
ref.read(notificationsProvider).startCheckingWatchedNotifications();
|
||||||
|
|
|
@ -111,7 +111,7 @@ class _HomeViewButtonBarState extends ConsumerState<HomeViewButtonBar> {
|
||||||
// }
|
// }
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
"Exchange",
|
"Swap",
|
||||||
style: STextStyles.button(context).copyWith(
|
style: STextStyles.button(context).copyWith(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: selectedIndex == 1
|
color: selectedIndex == 1
|
||||||
|
|
|
@ -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,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,23 +5,29 @@ import 'package:event_bus/event_bus.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
|
import 'package:isar/isar.dart';
|
||||||
|
import 'package:stackwallet/models/isar/exchange_cache/currency.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 +35,15 @@ 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/exchange/exchange_data_loading_service.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 +51,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
|
||||||
|
@ -239,19 +258,14 @@ class _WalletViewState extends ConsumerState<WalletView> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onExchangePressed(BuildContext context) async {
|
void _onExchangePressed(BuildContext context) async {
|
||||||
// too expensive
|
|
||||||
// unawaited(ExchangeDataLoadingService.instance.loadAll(ref));
|
|
||||||
|
|
||||||
final coin = ref.read(managerProvider).coin;
|
final coin = ref.read(managerProvider).coin;
|
||||||
|
|
||||||
if (coin == Coin.epicCash) {
|
final currency = ExchangeDataLoadingService.instance.isar.currencies
|
||||||
await showDialog<void>(
|
.where()
|
||||||
context: context,
|
.tickerEqualToAnyExchangeNameName(coin.ticker)
|
||||||
builder: (_) => const StackOkDialog(
|
.findFirstSync();
|
||||||
title: "Exchange not available for Epic Cash",
|
|
||||||
),
|
if (coin.isTestNet) {
|
||||||
);
|
|
||||||
} else if (coin.name.endsWith("TestNet")) {
|
|
||||||
await showDialog<void>(
|
await showDialog<void>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (_) => const StackOkDialog(
|
builder: (_) => const StackOkDialog(
|
||||||
|
@ -259,41 +273,13 @@ class _WalletViewState extends ConsumerState<WalletView> {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// ref.read(currentExchangeNameStateProvider.state).state =
|
|
||||||
// ChangeNowExchange.exchangeName;
|
|
||||||
// final walletId = ref.read(managerProvider).walletId;
|
|
||||||
// ref.read(prefsChangeNotifierProvider).exchangeRateType =
|
|
||||||
// ExchangeRateType.estimated;
|
|
||||||
//
|
|
||||||
// final currencies = ref
|
|
||||||
// .read(availableChangeNowCurrenciesProvider)
|
|
||||||
// .currencies
|
|
||||||
// .where((element) =>
|
|
||||||
// element.ticker.toLowerCase() == coin.ticker.toLowerCase());
|
|
||||||
//
|
|
||||||
// if (currencies.isNotEmpty) {
|
|
||||||
// ref
|
|
||||||
// .read(exchangeFormStateProvider(ExchangeRateType.estimated))
|
|
||||||
// .setCurrencies(
|
|
||||||
// currencies.first,
|
|
||||||
// ref
|
|
||||||
// .read(availableChangeNowCurrenciesProvider)
|
|
||||||
// .currencies
|
|
||||||
// .firstWhere(
|
|
||||||
// (element) =>
|
|
||||||
// element.ticker.toLowerCase() !=
|
|
||||||
// coin.ticker.toLowerCase(),
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
unawaited(
|
unawaited(
|
||||||
Navigator.of(context).pushNamed(
|
Navigator.of(context).pushNamed(
|
||||||
WalletInitiatedExchangeView.routeName,
|
WalletInitiatedExchangeView.routeName,
|
||||||
arguments: Tuple2(
|
arguments: Tuple2(
|
||||||
walletId,
|
walletId,
|
||||||
coin,
|
currency == null ? Coin.bitcoin : coin,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -301,6 +287,28 @@ class _WalletViewState extends ConsumerState<WalletView> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _onBuyPressed(BuildContext context) async {
|
||||||
|
final coin = ref.read(managerProvider).coin;
|
||||||
|
|
||||||
|
if (coin.isTestNet) {
|
||||||
|
await showDialog<void>(
|
||||||
|
context: context,
|
||||||
|
builder: (_) => const StackOkDialog(
|
||||||
|
title: "Buy not available for test net coins",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
if (mounted) {
|
||||||
|
unawaited(
|
||||||
|
Navigator.of(context).pushNamed(
|
||||||
|
BuyInWalletView.routeName,
|
||||||
|
arguments: coin.hasBuySupport ? coin : Coin.bitcoin,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> attemptAnonymize() async {
|
Future<void> attemptAnonymize() async {
|
||||||
bool shouldPop = false;
|
bool shouldPop = false;
|
||||||
unawaited(
|
unawaited(
|
||||||
|
@ -398,7 +406,9 @@ class _WalletViewState extends ConsumerState<WalletView> {
|
||||||
child: WillPopScope(
|
child: WillPopScope(
|
||||||
onWillPop: _onWillPop,
|
onWillPop: _onWillPop,
|
||||||
child: Background(
|
child: Background(
|
||||||
child: Scaffold(
|
child: Stack(
|
||||||
|
children: [
|
||||||
|
Scaffold(
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
Theme.of(context).extension<StackColors>()!.background,
|
Theme.of(context).extension<StackColors>()!.background,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
|
@ -422,8 +432,8 @@ class _WalletViewState extends ConsumerState<WalletView> {
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text(
|
child: Text(
|
||||||
ref.watch(
|
ref.watch(managerProvider
|
||||||
managerProvider.select((value) => value.walletName)),
|
.select((value) => value.walletName)),
|
||||||
style: STextStyles.navBarTitle(context),
|
style: STextStyles.navBarTitle(context),
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
|
@ -482,8 +492,9 @@ class _WalletViewState extends ConsumerState<WalletView> {
|
||||||
: Assets.svg.bell,
|
: Assets.svg.bell,
|
||||||
width: 20,
|
width: 20,
|
||||||
height: 20,
|
height: 20,
|
||||||
color: ref.watch(notificationsProvider.select((value) =>
|
color: ref.watch(notificationsProvider.select(
|
||||||
value.hasUnreadNotificationsFor(walletId)))
|
(value) => value
|
||||||
|
.hasUnreadNotificationsFor(walletId)))
|
||||||
? null
|
? null
|
||||||
: Theme.of(context)
|
: Theme.of(context)
|
||||||
.extension<StackColors>()!
|
.extension<StackColors>()!
|
||||||
|
@ -511,15 +522,15 @@ class _WalletViewState extends ConsumerState<WalletView> {
|
||||||
futures.add(ref
|
futures.add(ref
|
||||||
.read(notificationsProvider)
|
.read(notificationsProvider)
|
||||||
.markAsRead(
|
.markAsRead(
|
||||||
unreadNotificationIds.elementAt(i), false));
|
unreadNotificationIds.elementAt(i),
|
||||||
|
false));
|
||||||
}
|
}
|
||||||
|
|
||||||
// wait for multiple to update if any
|
// wait for multiple to update if any
|
||||||
Future.wait(futures).then((_) {
|
Future.wait(futures).then((_) {
|
||||||
// only notify listeners once
|
// only notify listeners once
|
||||||
ref
|
ref.read(notificationsProvider).markAsRead(
|
||||||
.read(notificationsProvider)
|
unreadNotificationIds.last, true);
|
||||||
.markAsRead(unreadNotificationIds.last, true);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -569,7 +580,8 @@ class _WalletViewState extends ConsumerState<WalletView> {
|
||||||
),
|
),
|
||||||
body: SafeArea(
|
body: SafeArea(
|
||||||
child: Container(
|
child: Container(
|
||||||
color: Theme.of(context).extension<StackColors>()!.background,
|
color:
|
||||||
|
Theme.of(context).extension<StackColors>()!.background,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
|
@ -601,7 +613,8 @@ class _WalletViewState extends ConsumerState<WalletView> {
|
||||||
child: TextButton(
|
child: TextButton(
|
||||||
style: Theme.of(context)
|
style: Theme.of(context)
|
||||||
.extension<StackColors>()!
|
.extension<StackColors>()!
|
||||||
.getSecondaryEnabledButtonStyle(context),
|
.getSecondaryEnabledButtonStyle(
|
||||||
|
context),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
await showDialog<void>(
|
await showDialog<void>(
|
||||||
context: context,
|
context: context,
|
||||||
|
@ -635,7 +648,8 @@ class _WalletViewState extends ConsumerState<WalletView> {
|
||||||
context),
|
context),
|
||||||
child: Text(
|
child: Text(
|
||||||
"Continue",
|
"Continue",
|
||||||
style: STextStyles.button(context),
|
style:
|
||||||
|
STextStyles.button(context),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -643,7 +657,8 @@ class _WalletViewState extends ConsumerState<WalletView> {
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
"Anonymize funds",
|
"Anonymize funds",
|
||||||
style: STextStyles.button(context).copyWith(
|
style:
|
||||||
|
STextStyles.button(context).copyWith(
|
||||||
color: Theme.of(context)
|
color: Theme.of(context)
|
||||||
.extension<StackColors>()!
|
.extension<StackColors>()!
|
||||||
.buttonTextSecondary,
|
.buttonTextSecondary,
|
||||||
|
@ -664,7 +679,8 @@ class _WalletViewState extends ConsumerState<WalletView> {
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Transactions",
|
"Transactions",
|
||||||
style: STextStyles.itemSubtitle(context).copyWith(
|
style:
|
||||||
|
STextStyles.itemSubtitle(context).copyWith(
|
||||||
color: Theme.of(context)
|
color: Theme.of(context)
|
||||||
.extension<StackColors>()!
|
.extension<StackColors>()!
|
||||||
.textDark3,
|
.textDark3,
|
||||||
|
@ -686,9 +702,7 @@ class _WalletViewState extends ConsumerState<WalletView> {
|
||||||
height: 12,
|
height: 12,
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Stack(
|
child: Padding(
|
||||||
children: [
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
child: ClipRRect(
|
child: ClipRRect(
|
||||||
borderRadius: BorderRadius.vertical(
|
borderRadius: BorderRadius.vertical(
|
||||||
|
@ -741,33 +755,19 @@ 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 &&
|
WalletNavigationBar(
|
||||||
ref.watch(managerProvider.select(
|
items: [
|
||||||
(value) => value.coin)) !=
|
WalletNavigationBarItemData(
|
||||||
Coin.epicCash,
|
label: "Receive",
|
||||||
height: WalletView.navBarHeight,
|
icon: const ReceiveNavIcon(),
|
||||||
onExchangePressed: () =>
|
onTap: () {
|
||||||
_onExchangePressed(context),
|
final coin = ref.read(managerProvider).coin;
|
||||||
onReceivePressed: () async {
|
|
||||||
final coin =
|
|
||||||
ref.read(managerProvider).coin;
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
unawaited(
|
unawaited(
|
||||||
Navigator.of(context).pushNamed(
|
Navigator.of(context).pushNamed(
|
||||||
|
@ -776,32 +776,28 @@ class _WalletViewState extends ConsumerState<WalletView> {
|
||||||
walletId,
|
walletId,
|
||||||
coin,
|
coin,
|
||||||
),
|
),
|
||||||
));
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onSendPressed: () {
|
),
|
||||||
final walletId =
|
WalletNavigationBarItemData(
|
||||||
ref.read(managerProvider).walletId;
|
label: "Send",
|
||||||
final coin =
|
icon: const SendNavIcon(),
|
||||||
ref.read(managerProvider).coin;
|
onTap: () {
|
||||||
|
final walletId = ref.read(managerProvider).walletId;
|
||||||
|
final coin = ref.read(managerProvider).coin;
|
||||||
switch (ref
|
switch (ref
|
||||||
.read(
|
.read(walletBalanceToggleStateProvider.state)
|
||||||
walletBalanceToggleStateProvider
|
|
||||||
.state)
|
|
||||||
.state) {
|
.state) {
|
||||||
case WalletBalanceToggleState.full:
|
case WalletBalanceToggleState.full:
|
||||||
ref
|
ref
|
||||||
.read(
|
.read(publicPrivateBalanceStateProvider.state)
|
||||||
publicPrivateBalanceStateProvider
|
|
||||||
.state)
|
|
||||||
.state = "Public";
|
.state = "Public";
|
||||||
break;
|
break;
|
||||||
case WalletBalanceToggleState
|
case WalletBalanceToggleState.available:
|
||||||
.available:
|
|
||||||
ref
|
ref
|
||||||
.read(
|
.read(publicPrivateBalanceStateProvider.state)
|
||||||
publicPrivateBalanceStateProvider
|
|
||||||
.state)
|
|
||||||
.state = "Private";
|
.state = "Private";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -813,26 +809,105 @@ class _WalletViewState extends ConsumerState<WalletView> {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
onBuyPressed: () {
|
),
|
||||||
unawaited(
|
if (Constants.enableExchange)
|
||||||
|
WalletNavigationBarItemData(
|
||||||
|
label: "Swap",
|
||||||
|
icon: const ExchangeNavIcon(),
|
||||||
|
onTap: () => _onExchangePressed(context),
|
||||||
|
),
|
||||||
|
if (Constants.enableExchange)
|
||||||
|
WalletNavigationBarItemData(
|
||||||
|
label: "Buy",
|
||||||
|
icon: const BuyNavIcon(),
|
||||||
|
onTap: () => _onBuyPressed(context),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
moreItems: [
|
||||||
|
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(
|
Navigator.of(context).pushNamed(
|
||||||
BuyInWalletView.routeName,
|
CoinControlView.routeName,
|
||||||
arguments: coin,
|
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,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -38,20 +38,9 @@ class EmptyWallets extends ConsumerWidget {
|
||||||
const Spacer(
|
const Spacer(
|
||||||
flex: 2,
|
flex: 2,
|
||||||
),
|
),
|
||||||
(isSorbet || isForest || isOcean)
|
SvgPicture.asset(
|
||||||
? SvgPicture.asset(
|
|
||||||
Assets.svg.stack(context),
|
Assets.svg.stack(context),
|
||||||
width: isDesktop
|
width: isDesktop ? 324 : MediaQuery.of(context).size.width / 3,
|
||||||
? 324
|
|
||||||
: MediaQuery.of(context).size.width / 3,
|
|
||||||
)
|
|
||||||
: Image(
|
|
||||||
image: AssetImage(
|
|
||||||
Assets.png.stack(context),
|
|
||||||
),
|
|
||||||
width: isDesktop
|
|
||||||
? 324
|
|
||||||
: MediaQuery.of(context).size.width / 3,
|
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: isDesktop ? 30 : 16,
|
height: isDesktop ? 30 : 16,
|
||||||
|
|
|
@ -95,7 +95,7 @@ class _DesktopExchangeViewState extends ConsumerState<DesktopExchangeView> {
|
||||||
left: 24,
|
left: 24,
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
"Exchange",
|
"Swap",
|
||||||
style: STextStyles.desktopH3(context),
|
style: STextStyles.desktopH3(context),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -37,7 +37,7 @@ class DesktopStep1 extends ConsumerWidget {
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
DesktopStepItem(
|
DesktopStepItem(
|
||||||
label: "Exchange",
|
label: "Swap",
|
||||||
value: ref.watch(exchangeFormStateProvider
|
value: ref.watch(exchangeFormStateProvider
|
||||||
.select((value) => value.exchange.name)),
|
.select((value) => value.exchange.name)),
|
||||||
),
|
),
|
||||||
|
|
|
@ -35,7 +35,7 @@ class _DesktopStep3State extends ConsumerState<DesktopStep3> {
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
DesktopStepItem(
|
DesktopStepItem(
|
||||||
label: "Exchange",
|
label: "Swap",
|
||||||
value: ref.watch(exchangeFormStateProvider
|
value: ref.watch(exchangeFormStateProvider
|
||||||
.select((value) => value.exchange.name)),
|
.select((value) => value.exchange.name)),
|
||||||
),
|
),
|
||||||
|
|
|
@ -153,7 +153,7 @@ class _DesktopMenuState extends ConsumerState<DesktopMenu> {
|
||||||
DesktopMenuItem(
|
DesktopMenuItem(
|
||||||
duration: duration,
|
duration: duration,
|
||||||
icon: const DesktopExchangeIcon(),
|
icon: const DesktopExchangeIcon(),
|
||||||
label: "Exchange",
|
label: "Swap",
|
||||||
value: DesktopMenuItemId.exchange,
|
value: DesktopMenuItemId.exchange,
|
||||||
onChanged: updateSelectedMenuItem,
|
onChanged: updateSelectedMenuItem,
|
||||||
controller: controllers[1],
|
controller: controllers[1],
|
||||||
|
|
|
@ -504,7 +504,7 @@ class _DesktopWalletViewState extends ConsumerState<DesktopWalletView> {
|
||||||
// onPressed: () {
|
// onPressed: () {
|
||||||
// _onExchangePressed(context);
|
// _onExchangePressed(context);
|
||||||
// },
|
// },
|
||||||
// label: "Exchange",
|
// label: "Swap",
|
||||||
// icon: Container(
|
// icon: Container(
|
||||||
// width: 24,
|
// width: 24,
|
||||||
// height: 24,
|
// height: 24,
|
||||||
|
|
|
@ -21,8 +21,9 @@ abstract class Constants {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool enableExchange = Util.isDesktop || !Platform.isIOS;
|
static bool enableExchange = Util.isDesktop || !Platform.isIOS;
|
||||||
static bool enableBuy =
|
// just use enable exchange flag
|
||||||
true; // true for development, TODO change to "Util.isDesktop || !Platform.isIOS;" as above or even just = enableExchange
|
// static bool enableBuy = enableExchange;
|
||||||
|
// // true; // true for development,
|
||||||
|
|
||||||
//TODO: correct for monero?
|
//TODO: correct for monero?
|
||||||
static const int _satsPerCoinMonero = 1000000000000;
|
static const int _satsPerCoinMonero = 1000000000000;
|
||||||
|
|
|
@ -195,6 +195,29 @@ extension CoinExt on Coin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool get isTestNet {
|
||||||
|
switch (this) {
|
||||||
|
case Coin.bitcoin:
|
||||||
|
case Coin.litecoin:
|
||||||
|
case Coin.bitcoincash:
|
||||||
|
case Coin.dogecoin:
|
||||||
|
case Coin.firo:
|
||||||
|
case Coin.namecoin:
|
||||||
|
case Coin.particl:
|
||||||
|
case Coin.epicCash:
|
||||||
|
case Coin.monero:
|
||||||
|
case Coin.wownero:
|
||||||
|
return false;
|
||||||
|
|
||||||
|
case Coin.dogecoinTestNet:
|
||||||
|
case Coin.bitcoinTestNet:
|
||||||
|
case Coin.litecoinTestNet:
|
||||||
|
case Coin.bitcoincashTestnet:
|
||||||
|
case Coin.firoTestNet:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int get requiredConfirmations {
|
int get requiredConfirmations {
|
||||||
switch (this) {
|
switch (this) {
|
||||||
case Coin.bitcoin:
|
case Coin.bitcoin:
|
||||||
|
|
|
@ -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,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
231
lib/widgets/wallet_navigation_bar/wallet_navigation_bar.dart
Normal file
|
@ -0,0 +1,231 @@
|
||||||
|
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/conditional_parent.dart';
|
||||||
|
import 'package:stackwallet/widgets/wallet_navigation_bar/components/wallet_navigation_bar_item.dart';
|
||||||
|
|
||||||
|
final walletNavBarMore = StateProvider.autoDispose((ref) => false);
|
||||||
|
|
||||||
|
class WalletNavigationBar extends ConsumerStatefulWidget {
|
||||||
|
const WalletNavigationBar({
|
||||||
|
Key? key,
|
||||||
|
required this.items,
|
||||||
|
required this.moreItems,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
final List<WalletNavigationBarItemData> items;
|
||||||
|
final List<WalletNavigationBarItemData> moreItems;
|
||||||
|
|
||||||
|
@override
|
||||||
|
ConsumerState<WalletNavigationBar> createState() =>
|
||||||
|
_WalletNavigationBarState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _WalletNavigationBarState extends ConsumerState<WalletNavigationBar> {
|
||||||
|
static const double horizontalPadding = 16;
|
||||||
|
|
||||||
|
final _moreDuration = const Duration(milliseconds: 200);
|
||||||
|
|
||||||
|
void _onMorePressed() {
|
||||||
|
ref.read(walletNavBarMore.state).state =
|
||||||
|
!ref.read(walletNavBarMore.state).state;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final width = MediaQuery.of(context).size.width - 40;
|
||||||
|
|
||||||
|
final hasMore = widget.moreItems.isNotEmpty;
|
||||||
|
final buttonCount = widget.items.length + (hasMore ? 1 : 0);
|
||||||
|
|
||||||
|
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.moreItems.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: 20,
|
||||||
|
),
|
||||||
|
// child: IntrinsicWidth(
|
||||||
|
child: ConditionalParent(
|
||||||
|
condition: buttonCount > 4,
|
||||||
|
builder: (child) => SizedBox(
|
||||||
|
width: width * 0.9,
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
|
child: ConditionalParent(
|
||||||
|
condition: buttonCount <= 4,
|
||||||
|
builder: (child) => SizedBox(
|
||||||
|
width: width * 0.2 * buttonCount,
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
...widget.items.map(
|
||||||
|
(e) => Expanded(
|
||||||
|
child: WalletNavigationBarItem(
|
||||||
|
data: e,
|
||||||
|
disableDuration: _moreDuration,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (hasMore)
|
||||||
|
Expanded(
|
||||||
|
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,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|