mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-12-23 11:59:30 +00:00
Merge branch 'staging' into ui-fixes
This commit is contained in:
commit
54dba90825
18 changed files with 733 additions and 533 deletions
|
@ -295,6 +295,9 @@ class _MaterialAppWithThemeState extends ConsumerState<MaterialAppWithTheme>
|
||||||
await ref.read(prefsChangeNotifierProvider).isExternalCallsSet()) {
|
await ref.read(prefsChangeNotifierProvider).isExternalCallsSet()) {
|
||||||
if (Constants.enableExchange) {
|
if (Constants.enableExchange) {
|
||||||
await ExchangeDataLoadingService.instance.init();
|
await ExchangeDataLoadingService.instance.init();
|
||||||
|
await ExchangeDataLoadingService.instance.setCurrenciesIfEmpty(
|
||||||
|
ref.read(exchangeFormStateProvider),
|
||||||
|
);
|
||||||
unawaited(ExchangeDataLoadingService.instance.loadAll());
|
unawaited(ExchangeDataLoadingService.instance.loadAll());
|
||||||
}
|
}
|
||||||
// if (Constants.enableBuy) {
|
// if (Constants.enableBuy) {
|
||||||
|
|
|
@ -163,7 +163,7 @@ class ExchangeFormState extends ChangeNotifier {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setCurrencies(AggregateCurrency from, AggregateCurrency to) {
|
void setCurrencies(AggregateCurrency? from, AggregateCurrency? to) {
|
||||||
_sendCurrency = from;
|
_sendCurrency = from;
|
||||||
_receiveCurrency = to;
|
_receiveCurrency = to;
|
||||||
}
|
}
|
||||||
|
|
|
@ -468,9 +468,10 @@ class _RestoreOptionsViewState extends ConsumerState<RestoreOptionsView> {
|
||||||
header: Container(
|
header: Container(
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.only(
|
||||||
vertical: 8.0,
|
top: 8.0,
|
||||||
horizontal: 16,
|
bottom: 8.0,
|
||||||
|
right: 10,
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
@ -504,67 +505,90 @@ class _RestoreOptionsViewState extends ConsumerState<RestoreOptionsView> {
|
||||||
),
|
),
|
||||||
body: Container(
|
body: Container(
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
child: ClipRRect(
|
child: Column(
|
||||||
borderRadius: BorderRadius.circular(
|
children: [
|
||||||
Constants.size.circularBorderRadius,
|
ClipRRect(
|
||||||
),
|
borderRadius: BorderRadius.circular(
|
||||||
child: TextField(
|
Constants.size.circularBorderRadius,
|
||||||
key: const Key("mnemonicPassphraseFieldKey1"),
|
),
|
||||||
focusNode: passwordFocusNode,
|
child: TextField(
|
||||||
controller: passwordController,
|
key: const Key("mnemonicPassphraseFieldKey1"),
|
||||||
style: isDesktop
|
focusNode: passwordFocusNode,
|
||||||
? STextStyles.desktopTextMedium(context).copyWith(
|
controller: passwordController,
|
||||||
height: 2,
|
style: isDesktop
|
||||||
)
|
? STextStyles.desktopTextMedium(context)
|
||||||
: STextStyles.field(context),
|
.copyWith(
|
||||||
obscureText: hidePassword,
|
height: 2,
|
||||||
enableSuggestions: false,
|
)
|
||||||
autocorrect: false,
|
: STextStyles.field(context),
|
||||||
decoration: standardInputDecoration(
|
obscureText: hidePassword,
|
||||||
"Recovery phrase password",
|
enableSuggestions: false,
|
||||||
passwordFocusNode,
|
autocorrect: false,
|
||||||
context,
|
decoration: standardInputDecoration(
|
||||||
).copyWith(
|
"Recovery phrase password",
|
||||||
suffixIcon: UnconstrainedBox(
|
passwordFocusNode,
|
||||||
child: ConditionalParent(
|
context,
|
||||||
condition: isDesktop,
|
).copyWith(
|
||||||
builder: (child) => SizedBox(
|
suffixIcon: UnconstrainedBox(
|
||||||
height: 70,
|
child: ConditionalParent(
|
||||||
child: child,
|
condition: isDesktop,
|
||||||
),
|
builder: (child) => SizedBox(
|
||||||
child: Row(
|
height: 70,
|
||||||
children: [
|
child: child,
|
||||||
SizedBox(
|
|
||||||
width: isDesktop ? 24 : 16,
|
|
||||||
),
|
),
|
||||||
GestureDetector(
|
child: Row(
|
||||||
key: const Key(
|
children: [
|
||||||
"mnemonicPassphraseFieldShowPasswordButtonKey"),
|
SizedBox(
|
||||||
onTap: () async {
|
width: isDesktop ? 24 : 16,
|
||||||
setState(() {
|
),
|
||||||
hidePassword = !hidePassword;
|
GestureDetector(
|
||||||
});
|
key: const Key(
|
||||||
},
|
"mnemonicPassphraseFieldShowPasswordButtonKey"),
|
||||||
child: SvgPicture.asset(
|
onTap: () async {
|
||||||
hidePassword
|
setState(() {
|
||||||
? Assets.svg.eye
|
hidePassword = !hidePassword;
|
||||||
: Assets.svg.eyeSlash,
|
});
|
||||||
color: Theme.of(context)
|
},
|
||||||
.extension<StackColors>()!
|
child: SvgPicture.asset(
|
||||||
.textDark3,
|
hidePassword
|
||||||
width: isDesktop ? 24 : 16,
|
? Assets.svg.eye
|
||||||
height: isDesktop ? 24 : 16,
|
: Assets.svg.eyeSlash,
|
||||||
),
|
color: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.textDark3,
|
||||||
|
width: isDesktop ? 24 : 16,
|
||||||
|
height: isDesktop ? 24 : 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 12,
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(
|
),
|
||||||
width: 12,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(
|
||||||
|
height: 8,
|
||||||
|
),
|
||||||
|
RoundedWhiteContainer(
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
"If the recovery phrase you are about to restore was created with an optional passphrase you can enter it here.",
|
||||||
|
style: isDesktop
|
||||||
|
? STextStyles.desktopTextExtraSmall(context)
|
||||||
|
.copyWith(
|
||||||
|
color: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.textSubtitle1,
|
||||||
|
)
|
||||||
|
: STextStyles.itemSubtitle(context),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -108,6 +108,8 @@ class _ExchangeCurrencySelectionViewState
|
||||||
return ExchangeDataLoadingService.instance.isar.currencies
|
return ExchangeDataLoadingService.instance.isar.currencies
|
||||||
.where()
|
.where()
|
||||||
.filter()
|
.filter()
|
||||||
|
.isFiatEqualTo(false)
|
||||||
|
.and()
|
||||||
.tickerEqualTo(ticker, caseSensitive: false)
|
.tickerEqualTo(ticker, caseSensitive: false)
|
||||||
.group((q) => widget.isFixedRate
|
.group((q) => widget.isFixedRate
|
||||||
? q
|
? q
|
||||||
|
@ -150,6 +152,8 @@ class _ExchangeCurrencySelectionViewState
|
||||||
return ExchangeDataLoadingService.instance.isar.currencies
|
return ExchangeDataLoadingService.instance.isar.currencies
|
||||||
.where()
|
.where()
|
||||||
.filter()
|
.filter()
|
||||||
|
.isFiatEqualTo(false)
|
||||||
|
.and()
|
||||||
.group((q) => widget.isFixedRate
|
.group((q) => widget.isFixedRate
|
||||||
? q
|
? q
|
||||||
.rateTypeEqualTo(SupportedRateType.both)
|
.rateTypeEqualTo(SupportedRateType.both)
|
||||||
|
|
|
@ -36,7 +36,10 @@ class _ExchangeViewState extends ConsumerState<ExchangeView> {
|
||||||
ExchangeDataLoadingService.cacheVersion) {
|
ExchangeDataLoadingService.cacheVersion) {
|
||||||
_initialCachePopulationUnderway = true;
|
_initialCachePopulationUnderway = true;
|
||||||
ExchangeDataLoadingService.instance.onLoadingComplete = () {
|
ExchangeDataLoadingService.instance.onLoadingComplete = () {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
||||||
|
await ExchangeDataLoadingService.instance.setCurrenciesIfEmpty(
|
||||||
|
ref.read(exchangeFormStateProvider),
|
||||||
|
);
|
||||||
setState(() {
|
setState(() {
|
||||||
_initialCachePopulationUnderway = false;
|
_initialCachePopulationUnderway = false;
|
||||||
});
|
});
|
||||||
|
@ -51,7 +54,10 @@ class _ExchangeViewState extends ConsumerState<ExchangeView> {
|
||||||
ExchangeDataLoadingService.cacheVersion) {
|
ExchangeDataLoadingService.cacheVersion) {
|
||||||
_initialCachePopulationUnderway = true;
|
_initialCachePopulationUnderway = true;
|
||||||
ExchangeDataLoadingService.instance.onLoadingComplete = () {
|
ExchangeDataLoadingService.instance.onLoadingComplete = () {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
||||||
|
await ExchangeDataLoadingService.instance.setCurrenciesIfEmpty(
|
||||||
|
ref.read(exchangeFormStateProvider),
|
||||||
|
);
|
||||||
setState(() {
|
setState(() {
|
||||||
_initialCachePopulationUnderway = false;
|
_initialCachePopulationUnderway = false;
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:stackwallet/pages/exchange_view/exchange_form.dart';
|
import 'package:stackwallet/pages/exchange_view/exchange_form.dart';
|
||||||
import 'package:stackwallet/pages/exchange_view/sub_widgets/step_row.dart';
|
import 'package:stackwallet/pages/exchange_view/sub_widgets/step_row.dart';
|
||||||
|
import 'package:stackwallet/providers/exchange/exchange_form_state_provider.dart';
|
||||||
import 'package:stackwallet/providers/global/prefs_provider.dart';
|
import 'package:stackwallet/providers/global/prefs_provider.dart';
|
||||||
import 'package:stackwallet/services/exchange/exchange_data_loading_service.dart';
|
import 'package:stackwallet/services/exchange/exchange_data_loading_service.dart';
|
||||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||||
|
@ -48,7 +49,10 @@ class _WalletInitiatedExchangeViewState
|
||||||
ExchangeDataLoadingService.cacheVersion) {
|
ExchangeDataLoadingService.cacheVersion) {
|
||||||
_initialCachePopulationUnderway = true;
|
_initialCachePopulationUnderway = true;
|
||||||
ExchangeDataLoadingService.instance.onLoadingComplete = () {
|
ExchangeDataLoadingService.instance.onLoadingComplete = () {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
||||||
|
await ExchangeDataLoadingService.instance.setCurrenciesIfEmpty(
|
||||||
|
ref.read(exchangeFormStateProvider),
|
||||||
|
);
|
||||||
setState(() {
|
setState(() {
|
||||||
_initialCachePopulationUnderway = false;
|
_initialCachePopulationUnderway = false;
|
||||||
});
|
});
|
||||||
|
@ -63,7 +67,10 @@ class _WalletInitiatedExchangeViewState
|
||||||
ExchangeDataLoadingService.cacheVersion) {
|
ExchangeDataLoadingService.cacheVersion) {
|
||||||
_initialCachePopulationUnderway = true;
|
_initialCachePopulationUnderway = true;
|
||||||
ExchangeDataLoadingService.instance.onLoadingComplete = () {
|
ExchangeDataLoadingService.instance.onLoadingComplete = () {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
||||||
|
await ExchangeDataLoadingService.instance.setCurrenciesIfEmpty(
|
||||||
|
ref.read(exchangeFormStateProvider),
|
||||||
|
);
|
||||||
setState(() {
|
setState(() {
|
||||||
_initialCachePopulationUnderway = false;
|
_initialCachePopulationUnderway = false;
|
||||||
});
|
});
|
||||||
|
|
|
@ -559,6 +559,7 @@ class _PaynymHomeViewState extends ConsumerState<PaynymHomeView> {
|
||||||
height: isDesktop ? 56 : 48,
|
height: isDesktop ? 56 : 48,
|
||||||
width: isDesktop ? 490 : null,
|
width: isDesktop ? 490 : null,
|
||||||
child: Toggle(
|
child: Toggle(
|
||||||
|
key: UniqueKey(),
|
||||||
onColor: Theme.of(context).extension<StackColors>()!.popupBG,
|
onColor: Theme.of(context).extension<StackColors>()!.popupBG,
|
||||||
onText:
|
onText:
|
||||||
"Following (${ref.watch(myPaynymAccountStateProvider.state).state?.following.length ?? 0})",
|
"Following (${ref.watch(myPaynymAccountStateProvider.state).state?.following.length ?? 0})",
|
||||||
|
|
|
@ -11,6 +11,7 @@ import 'package:stackwallet/notifications/show_flush_bar.dart';
|
||||||
import 'package:stackwallet/pages/paynym/dialogs/confirm_paynym_connect_dialog.dart';
|
import 'package:stackwallet/pages/paynym/dialogs/confirm_paynym_connect_dialog.dart';
|
||||||
import 'package:stackwallet/pages/paynym/subwidgets/paynym_bot.dart';
|
import 'package:stackwallet/pages/paynym/subwidgets/paynym_bot.dart';
|
||||||
import 'package:stackwallet/pages/send_view/confirm_transaction_view.dart';
|
import 'package:stackwallet/pages/send_view/confirm_transaction_view.dart';
|
||||||
|
import 'package:stackwallet/pages_desktop_specific/my_stack_view/paynym/desktop_paynym_send_dialog.dart';
|
||||||
import 'package:stackwallet/providers/global/wallets_provider.dart';
|
import 'package:stackwallet/providers/global/wallets_provider.dart';
|
||||||
import 'package:stackwallet/services/mixins/paynym_wallet_interface.dart';
|
import 'package:stackwallet/services/mixins/paynym_wallet_interface.dart';
|
||||||
import 'package:stackwallet/utilities/assets.dart';
|
import 'package:stackwallet/utilities/assets.dart';
|
||||||
|
@ -102,8 +103,6 @@ class _PaynymDetailsPopupState extends ConsumerState<DesktopPaynymDetails> {
|
||||||
builder: (context) => ConfirmPaynymConnectDialog(
|
builder: (context) => ConfirmPaynymConnectDialog(
|
||||||
nymName: widget.accountLite.nymName,
|
nymName: widget.accountLite.nymName,
|
||||||
onConfirmPressed: () {
|
onConfirmPressed: () {
|
||||||
//
|
|
||||||
print("CONFIRM NOTIF TX: $preparedTx");
|
|
||||||
Navigator.of(context, rootNavigator: true).pop();
|
Navigator.of(context, rootNavigator: true).pop();
|
||||||
unawaited(
|
unawaited(
|
||||||
showDialog(
|
showDialog(
|
||||||
|
@ -148,7 +147,13 @@ class _PaynymDetailsPopupState extends ConsumerState<DesktopPaynymDetails> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onSend() async {
|
Future<void> _onSend() async {
|
||||||
print("sned");
|
await showDialog<void>(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => DesktopPaynymSendDialog(
|
||||||
|
walletId: widget.walletId,
|
||||||
|
accountLite: widget.accountLite,
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
@ -586,7 +586,9 @@ class _ConfirmTransactionViewState
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Send to",
|
widget.isPaynymTransaction
|
||||||
|
? "PayNym recipient"
|
||||||
|
: "Send to",
|
||||||
style: STextStyles.desktopTextExtraExtraSmall(
|
style: STextStyles.desktopTextExtraExtraSmall(
|
||||||
context),
|
context),
|
||||||
),
|
),
|
||||||
|
@ -594,7 +596,11 @@ class _ConfirmTransactionViewState
|
||||||
height: 2,
|
height: 2,
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
"${transactionInfo["address"] ?? "ERROR"}",
|
widget.isPaynymTransaction
|
||||||
|
? (transactionInfo["paynymAccountLite"]
|
||||||
|
as PaynymAccountLite)
|
||||||
|
.nymName
|
||||||
|
: "${transactionInfo["address"] ?? "ERROR"}",
|
||||||
style: STextStyles.desktopTextExtraExtraSmall(
|
style: STextStyles.desktopTextExtraExtraSmall(
|
||||||
context)
|
context)
|
||||||
.copyWith(
|
.copyWith(
|
||||||
|
@ -606,6 +612,64 @@ class _ConfirmTransactionViewState
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
if (widget.isPaynymTransaction)
|
||||||
|
Container(
|
||||||
|
height: 1,
|
||||||
|
color: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.background,
|
||||||
|
),
|
||||||
|
if (widget.isPaynymTransaction)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(12),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Transaction fee",
|
||||||
|
style: STextStyles.desktopTextExtraExtraSmall(
|
||||||
|
context),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 2,
|
||||||
|
),
|
||||||
|
Builder(
|
||||||
|
builder: (context) {
|
||||||
|
final coin = ref
|
||||||
|
.watch(walletsChangeNotifierProvider
|
||||||
|
.select((value) =>
|
||||||
|
value.getManager(walletId)))
|
||||||
|
.coin;
|
||||||
|
|
||||||
|
final fee = Format.satoshisToAmount(
|
||||||
|
transactionInfo["fee"] as int,
|
||||||
|
coin: coin,
|
||||||
|
);
|
||||||
|
|
||||||
|
return Text(
|
||||||
|
"${Format.localizedStringAsFixed(
|
||||||
|
value: fee,
|
||||||
|
locale: ref.watch(
|
||||||
|
localeServiceChangeNotifierProvider
|
||||||
|
.select((value) => value.locale)),
|
||||||
|
decimalPlaces:
|
||||||
|
Constants.decimalPlacesForCoin(coin),
|
||||||
|
)} ${coin.ticker}",
|
||||||
|
style:
|
||||||
|
STextStyles.desktopTextExtraExtraSmall(
|
||||||
|
context)
|
||||||
|
.copyWith(
|
||||||
|
color: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.textDark,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
// Container(
|
// Container(
|
||||||
// height: 1,
|
// height: 1,
|
||||||
// color: Theme.of(context)
|
// color: Theme.of(context)
|
||||||
|
@ -725,7 +789,7 @@ class _ConfirmTransactionViewState
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (isDesktop)
|
if (isDesktop && !widget.isPaynymTransaction)
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.only(
|
||||||
left: 32,
|
left: 32,
|
||||||
|
@ -735,22 +799,23 @@ class _ConfirmTransactionViewState
|
||||||
style: STextStyles.desktopTextExtraExtraSmall(context),
|
style: STextStyles.desktopTextExtraExtraSmall(context),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (isDesktop)
|
if (isDesktop && !widget.isPaynymTransaction)
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.only(
|
||||||
top: 10,
|
top: 10,
|
||||||
left: 32,
|
left: 32,
|
||||||
right: 32,
|
right: 32,
|
||||||
|
),
|
||||||
|
child: RoundedContainer(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 16,
|
||||||
|
vertical: 18,
|
||||||
),
|
),
|
||||||
child: RoundedContainer(
|
color: Theme.of(context)
|
||||||
padding: const EdgeInsets.symmetric(
|
.extension<StackColors>()!
|
||||||
horizontal: 16,
|
.textFieldDefaultBG,
|
||||||
vertical: 18,
|
child: Builder(
|
||||||
),
|
builder: (context) {
|
||||||
color: Theme.of(context)
|
|
||||||
.extension<StackColors>()!
|
|
||||||
.textFieldDefaultBG,
|
|
||||||
child: Builder(builder: (context) {
|
|
||||||
final coin = ref
|
final coin = ref
|
||||||
.watch(walletsChangeNotifierProvider
|
.watch(walletsChangeNotifierProvider
|
||||||
.select((value) => value.getManager(walletId)))
|
.select((value) => value.getManager(walletId)))
|
||||||
|
@ -770,64 +835,10 @@ class _ConfirmTransactionViewState
|
||||||
)} ${coin.ticker}",
|
)} ${coin.ticker}",
|
||||||
style: STextStyles.itemSubtitle(context),
|
style: STextStyles.itemSubtitle(context),
|
||||||
);
|
);
|
||||||
}),
|
},
|
||||||
)
|
|
||||||
// DropdownButtonHideUnderline(
|
|
||||||
// child: DropdownButton2(
|
|
||||||
// offset: const Offset(0, -10),
|
|
||||||
// isExpanded: true,
|
|
||||||
//
|
|
||||||
// dropdownElevation: 0,
|
|
||||||
// value: _fee,
|
|
||||||
// items: [
|
|
||||||
// ..._dropDownItems.map(
|
|
||||||
// (e) {
|
|
||||||
// String message = _fee.toString();
|
|
||||||
//
|
|
||||||
// return DropdownMenuItem(
|
|
||||||
// value: e,
|
|
||||||
// child: Text(message),
|
|
||||||
// );
|
|
||||||
// },
|
|
||||||
// ),
|
|
||||||
// ],
|
|
||||||
// onChanged: (value) {
|
|
||||||
// if (value is int) {
|
|
||||||
// setState(() {
|
|
||||||
// _fee = value;
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// icon: SvgPicture.asset(
|
|
||||||
// Assets.svg.chevronDown,
|
|
||||||
// width: 12,
|
|
||||||
// height: 6,
|
|
||||||
// color:
|
|
||||||
// Theme.of(context).extension<StackColors>()!.textDark3,
|
|
||||||
// ),
|
|
||||||
// buttonPadding: const EdgeInsets.symmetric(
|
|
||||||
// horizontal: 16,
|
|
||||||
// vertical: 8,
|
|
||||||
// ),
|
|
||||||
// buttonDecoration: BoxDecoration(
|
|
||||||
// color: Theme.of(context)
|
|
||||||
// .extension<StackColors>()!
|
|
||||||
// .textFieldDefaultBG,
|
|
||||||
// borderRadius: BorderRadius.circular(
|
|
||||||
// Constants.size.circularBorderRadius,
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// dropdownDecoration: BoxDecoration(
|
|
||||||
// color: Theme.of(context)
|
|
||||||
// .extension<StackColors>()!
|
|
||||||
// .textFieldDefaultBG,
|
|
||||||
// borderRadius: BorderRadius.circular(
|
|
||||||
// Constants.size.circularBorderRadius,
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
if (!isDesktop) const Spacer(),
|
if (!isDesktop) const Spacer(),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: isDesktop ? 23 : 12,
|
height: isDesktop ? 23 : 12,
|
||||||
|
|
|
@ -297,44 +297,6 @@ class _SendViewState extends ConsumerState<SendView> {
|
||||||
final manager =
|
final manager =
|
||||||
ref.read(walletsChangeNotifierProvider).getManager(walletId);
|
ref.read(walletsChangeNotifierProvider).getManager(walletId);
|
||||||
|
|
||||||
// // TODO: remove the need for this!!
|
|
||||||
// final bool isOwnAddress =
|
|
||||||
// await manager.isOwnAddress(_address!);
|
|
||||||
// if (isOwnAddress && coin != Coin.dogecoinTestNet) {
|
|
||||||
// await showDialog<dynamic>(
|
|
||||||
// context: context,
|
|
||||||
// useSafeArea: false,
|
|
||||||
// barrierDismissible: true,
|
|
||||||
// builder: (context) {
|
|
||||||
// return StackDialog(
|
|
||||||
// title: "Transaction failed",
|
|
||||||
// message:
|
|
||||||
// "Sending to self is currently disabled",
|
|
||||||
// rightButton: TextButton(
|
|
||||||
// style: Theme.of(context)
|
|
||||||
// .extension<StackColors>()!
|
|
||||||
// .getSecondaryEnabledButtonColor(
|
|
||||||
// context),
|
|
||||||
// child: Text(
|
|
||||||
// "Ok",
|
|
||||||
// style: STextStyles.button(
|
|
||||||
// context)
|
|
||||||
// .copyWith(
|
|
||||||
// color: Theme.of(context)
|
|
||||||
// .extension<
|
|
||||||
// StackColors>()!
|
|
||||||
// .accentColorDark),
|
|
||||||
// ),
|
|
||||||
// onPressed: () {
|
|
||||||
// Navigator.of(context).pop();
|
|
||||||
// },
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
// },
|
|
||||||
// );
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
final amount = Format.decimalAmountToSatoshis(_amountToSend!, coin);
|
final amount = Format.decimalAmountToSatoshis(_amountToSend!, coin);
|
||||||
int availableBalance;
|
int availableBalance;
|
||||||
if ((coin == Coin.firo || coin == Coin.firoTestNet)) {
|
if ((coin == Coin.firo || coin == Coin.firoTestNet)) {
|
||||||
|
|
|
@ -21,7 +21,7 @@ class AllWallets extends StatelessWidget {
|
||||||
Text(
|
Text(
|
||||||
"All wallets",
|
"All wallets",
|
||||||
style: STextStyles.itemSubtitle(context).copyWith(
|
style: STextStyles.itemSubtitle(context).copyWith(
|
||||||
color: Theme.of(context).extension<StackColors>()!.textDark,
|
color: Theme.of(context).extension<StackColors>()!.textDark3,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
CustomTextButton(
|
CustomTextButton(
|
||||||
|
|
|
@ -106,12 +106,12 @@ class _FavoriteWalletsState extends ConsumerState<FavoriteWallets> {
|
||||||
ManageFavoritesView.routeName,
|
ManageFavoritesView.routeName,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 12,
|
height: 20,
|
||||||
),
|
),
|
||||||
!hasFavorites
|
!hasFavorites
|
||||||
? Padding(
|
? Padding(
|
||||||
|
|
|
@ -5,6 +5,8 @@ import 'package:stackwallet/pages/wallets_view/sub_widgets/all_wallets.dart';
|
||||||
import 'package:stackwallet/pages/wallets_view/sub_widgets/empty_wallets.dart';
|
import 'package:stackwallet/pages/wallets_view/sub_widgets/empty_wallets.dart';
|
||||||
import 'package:stackwallet/pages/wallets_view/sub_widgets/favorite_wallets.dart';
|
import 'package:stackwallet/pages/wallets_view/sub_widgets/favorite_wallets.dart';
|
||||||
import 'package:stackwallet/providers/providers.dart';
|
import 'package:stackwallet/providers/providers.dart';
|
||||||
|
import 'package:stackwallet/providers/ui/color_theme_provider.dart';
|
||||||
|
import 'package:stackwallet/utilities/theme/color_theme.dart';
|
||||||
|
|
||||||
class WalletsView extends ConsumerWidget {
|
class WalletsView extends ConsumerWidget {
|
||||||
const WalletsView({Key? key}) : super(key: key);
|
const WalletsView({Key? key}) : super(key: key);
|
||||||
|
@ -22,8 +24,11 @@ class WalletsView extends ConsumerWidget {
|
||||||
return SafeArea(
|
return SafeArea(
|
||||||
child: hasWallets
|
child: hasWallets
|
||||||
? Padding(
|
? Padding(
|
||||||
padding: const EdgeInsets.only(
|
padding: EdgeInsets.only(
|
||||||
top: 20,
|
top: ref.watch(colorThemeProvider).themeType ==
|
||||||
|
ThemeType.fruitSorbet
|
||||||
|
? 6
|
||||||
|
: 20,
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
|
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:stackwallet/pages/exchange_view/exchange_form.dart';
|
import 'package:stackwallet/pages/exchange_view/exchange_form.dart';
|
||||||
import 'package:stackwallet/pages_desktop_specific/desktop_exchange/subwidgets/desktop_trade_history.dart';
|
import 'package:stackwallet/pages_desktop_specific/desktop_exchange/subwidgets/desktop_trade_history.dart';
|
||||||
|
import 'package:stackwallet/providers/exchange/exchange_form_state_provider.dart';
|
||||||
import 'package:stackwallet/providers/global/prefs_provider.dart';
|
import 'package:stackwallet/providers/global/prefs_provider.dart';
|
||||||
import 'package:stackwallet/services/exchange/exchange_data_loading_service.dart';
|
import 'package:stackwallet/services/exchange/exchange_data_loading_service.dart';
|
||||||
import 'package:stackwallet/utilities/text_styles.dart';
|
import 'package:stackwallet/utilities/text_styles.dart';
|
||||||
|
@ -32,7 +33,10 @@ class _DesktopExchangeViewState extends ConsumerState<DesktopExchangeView> {
|
||||||
ExchangeDataLoadingService.cacheVersion) {
|
ExchangeDataLoadingService.cacheVersion) {
|
||||||
_initialCachePopulationUnderway = true;
|
_initialCachePopulationUnderway = true;
|
||||||
ExchangeDataLoadingService.instance.onLoadingComplete = () {
|
ExchangeDataLoadingService.instance.onLoadingComplete = () {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
||||||
|
await ExchangeDataLoadingService.instance.setCurrenciesIfEmpty(
|
||||||
|
ref.read(exchangeFormStateProvider),
|
||||||
|
);
|
||||||
setState(() {
|
setState(() {
|
||||||
_initialCachePopulationUnderway = false;
|
_initialCachePopulationUnderway = false;
|
||||||
});
|
});
|
||||||
|
@ -47,7 +51,10 @@ class _DesktopExchangeViewState extends ConsumerState<DesktopExchangeView> {
|
||||||
ExchangeDataLoadingService.cacheVersion) {
|
ExchangeDataLoadingService.cacheVersion) {
|
||||||
_initialCachePopulationUnderway = true;
|
_initialCachePopulationUnderway = true;
|
||||||
ExchangeDataLoadingService.instance.onLoadingComplete = () {
|
ExchangeDataLoadingService.instance.onLoadingComplete = () {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
||||||
|
await ExchangeDataLoadingService.instance.setCurrenciesIfEmpty(
|
||||||
|
ref.read(exchangeFormStateProvider),
|
||||||
|
);
|
||||||
setState(() {
|
setState(() {
|
||||||
_initialCachePopulationUnderway = false;
|
_initialCachePopulationUnderway = false;
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,197 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:flutter_svg/svg.dart';
|
||||||
|
import 'package:stackwallet/models/paynym/paynym_account_lite.dart';
|
||||||
|
import 'package:stackwallet/models/send_view_auto_fill_data.dart';
|
||||||
|
import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart';
|
||||||
|
import 'package:stackwallet/providers/global/locale_provider.dart';
|
||||||
|
import 'package:stackwallet/providers/global/prefs_provider.dart';
|
||||||
|
import 'package:stackwallet/providers/global/price_provider.dart';
|
||||||
|
import 'package:stackwallet/providers/global/wallets_provider.dart';
|
||||||
|
import 'package:stackwallet/providers/wallet/public_private_balance_state_provider.dart';
|
||||||
|
import 'package:stackwallet/services/coins/firo/firo_wallet.dart';
|
||||||
|
import 'package:stackwallet/utilities/assets.dart';
|
||||||
|
import 'package:stackwallet/utilities/barcode_scanner_interface.dart';
|
||||||
|
import 'package:stackwallet/utilities/clipboard_interface.dart';
|
||||||
|
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||||
|
import 'package:stackwallet/utilities/format.dart';
|
||||||
|
import 'package:stackwallet/utilities/text_styles.dart';
|
||||||
|
import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
||||||
|
import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
|
||||||
|
import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
|
||||||
|
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||||
|
|
||||||
|
class DesktopPaynymSendDialog extends ConsumerStatefulWidget {
|
||||||
|
const DesktopPaynymSendDialog({
|
||||||
|
Key? key,
|
||||||
|
required this.walletId,
|
||||||
|
this.autoFillData,
|
||||||
|
this.clipboard = const ClipboardWrapper(),
|
||||||
|
this.barcodeScanner = const BarcodeScannerWrapper(),
|
||||||
|
this.accountLite,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
final String walletId;
|
||||||
|
final SendViewAutoFillData? autoFillData;
|
||||||
|
final ClipboardInterface clipboard;
|
||||||
|
final BarcodeScannerInterface barcodeScanner;
|
||||||
|
final PaynymAccountLite? accountLite;
|
||||||
|
|
||||||
|
@override
|
||||||
|
ConsumerState<DesktopPaynymSendDialog> createState() =>
|
||||||
|
_DesktopPaynymSendDialogState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DesktopPaynymSendDialogState
|
||||||
|
extends ConsumerState<DesktopPaynymSendDialog> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final manager = ref.watch(walletsChangeNotifierProvider
|
||||||
|
.select((value) => value.getManager(widget.walletId)));
|
||||||
|
final String locale = ref.watch(
|
||||||
|
localeServiceChangeNotifierProvider.select((value) => value.locale));
|
||||||
|
|
||||||
|
final coin = manager.coin;
|
||||||
|
|
||||||
|
final isFiro = coin == Coin.firo || coin == Coin.firoTestNet;
|
||||||
|
|
||||||
|
return DesktopDialog(
|
||||||
|
maxHeight: double.infinity,
|
||||||
|
maxWidth: 580,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 32),
|
||||||
|
child: Text(
|
||||||
|
"Send ${manager.coin.ticker.toUpperCase()}",
|
||||||
|
style: STextStyles.desktopH3(context),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const DesktopDialogCloseButton(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 32),
|
||||||
|
child: RoundedWhiteContainer(
|
||||||
|
borderColor:
|
||||||
|
Theme.of(context).extension<StackColors>()!.background,
|
||||||
|
// Theme.of(context).extension<StackColors>()!.textSubtitle4,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
SvgPicture.asset(
|
||||||
|
Assets.svg.iconFor(coin: coin),
|
||||||
|
width: 36,
|
||||||
|
height: 36,
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 12,
|
||||||
|
),
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
manager.walletName,
|
||||||
|
style: STextStyles.titleBold12(context),
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
maxLines: 1,
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 2,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
isFiro
|
||||||
|
? "${ref.watch(publicPrivateBalanceStateProvider.state).state} balance"
|
||||||
|
: "Available balance",
|
||||||
|
style: STextStyles.baseXS(context).copyWith(
|
||||||
|
color: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.textSubtitle1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
|
Container(
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"${Format.localizedStringAsFixed(
|
||||||
|
value: !isFiro
|
||||||
|
? manager.balance.getSpendable()
|
||||||
|
: ref
|
||||||
|
.watch(
|
||||||
|
publicPrivateBalanceStateProvider
|
||||||
|
.state)
|
||||||
|
.state ==
|
||||||
|
"Private"
|
||||||
|
? (manager.wallet as FiroWallet)
|
||||||
|
.availablePrivateBalance()
|
||||||
|
: (manager.wallet as FiroWallet)
|
||||||
|
.availablePublicBalance(),
|
||||||
|
locale: locale,
|
||||||
|
decimalPlaces: 8,
|
||||||
|
)} ${coin.ticker}",
|
||||||
|
style: STextStyles.titleBold12(context),
|
||||||
|
textAlign: TextAlign.right,
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 2,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
"${Format.localizedStringAsFixed(
|
||||||
|
value: (!isFiro
|
||||||
|
? manager.balance.getSpendable()
|
||||||
|
: ref
|
||||||
|
.watch(
|
||||||
|
publicPrivateBalanceStateProvider
|
||||||
|
.state)
|
||||||
|
.state ==
|
||||||
|
"Private"
|
||||||
|
? (manager.wallet as FiroWallet)
|
||||||
|
.availablePrivateBalance()
|
||||||
|
: (manager.wallet as FiroWallet)
|
||||||
|
.availablePublicBalance()) *
|
||||||
|
ref.watch(
|
||||||
|
priceAnd24hChangeNotifierProvider.select(
|
||||||
|
(value) => value.getPrice(coin).item1)),
|
||||||
|
locale: locale,
|
||||||
|
decimalPlaces: 2,
|
||||||
|
)} ${ref.watch(prefsChangeNotifierProvider.select((value) => value.currency))}",
|
||||||
|
style: STextStyles.baseXS(context).copyWith(
|
||||||
|
color: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.textSubtitle1,
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.right,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 20,
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
left: 32,
|
||||||
|
right: 32,
|
||||||
|
bottom: 32,
|
||||||
|
),
|
||||||
|
child: DesktopSend(
|
||||||
|
walletId: manager.walletId,
|
||||||
|
accountLite: widget.accountLite,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:bip47/bip47.dart';
|
||||||
import 'package:decimal/decimal.dart';
|
import 'package:decimal/decimal.dart';
|
||||||
import 'package:dropdown_button2/dropdown_button2.dart';
|
import 'package:dropdown_button2/dropdown_button2.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
@ -7,6 +8,7 @@ import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:stackwallet/models/contact_address_entry.dart';
|
import 'package:stackwallet/models/contact_address_entry.dart';
|
||||||
|
import 'package:stackwallet/models/paynym/paynym_account_lite.dart';
|
||||||
import 'package:stackwallet/models/send_view_auto_fill_data.dart';
|
import 'package:stackwallet/models/send_view_auto_fill_data.dart';
|
||||||
import 'package:stackwallet/pages/send_view/confirm_transaction_view.dart';
|
import 'package:stackwallet/pages/send_view/confirm_transaction_view.dart';
|
||||||
import 'package:stackwallet/pages/send_view/sub_widgets/building_transaction_dialog.dart';
|
import 'package:stackwallet/pages/send_view/sub_widgets/building_transaction_dialog.dart';
|
||||||
|
@ -20,6 +22,7 @@ import 'package:stackwallet/providers/ui/preview_tx_button_state_provider.dart';
|
||||||
import 'package:stackwallet/providers/wallet/public_private_balance_state_provider.dart';
|
import 'package:stackwallet/providers/wallet/public_private_balance_state_provider.dart';
|
||||||
import 'package:stackwallet/services/coins/firo/firo_wallet.dart';
|
import 'package:stackwallet/services/coins/firo/firo_wallet.dart';
|
||||||
import 'package:stackwallet/services/coins/manager.dart';
|
import 'package:stackwallet/services/coins/manager.dart';
|
||||||
|
import 'package:stackwallet/services/mixins/paynym_wallet_interface.dart';
|
||||||
import 'package:stackwallet/utilities/address_utils.dart';
|
import 'package:stackwallet/utilities/address_utils.dart';
|
||||||
import 'package:stackwallet/utilities/assets.dart';
|
import 'package:stackwallet/utilities/assets.dart';
|
||||||
import 'package:stackwallet/utilities/barcode_scanner_interface.dart';
|
import 'package:stackwallet/utilities/barcode_scanner_interface.dart';
|
||||||
|
@ -51,12 +54,14 @@ class DesktopSend extends ConsumerStatefulWidget {
|
||||||
this.autoFillData,
|
this.autoFillData,
|
||||||
this.clipboard = const ClipboardWrapper(),
|
this.clipboard = const ClipboardWrapper(),
|
||||||
this.barcodeScanner = const BarcodeScannerWrapper(),
|
this.barcodeScanner = const BarcodeScannerWrapper(),
|
||||||
|
this.accountLite,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
final String walletId;
|
final String walletId;
|
||||||
final SendViewAutoFillData? autoFillData;
|
final SendViewAutoFillData? autoFillData;
|
||||||
final ClipboardInterface clipboard;
|
final ClipboardInterface clipboard;
|
||||||
final BarcodeScannerInterface barcodeScanner;
|
final BarcodeScannerInterface barcodeScanner;
|
||||||
|
final PaynymAccountLite? accountLite;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ConsumerState<DesktopSend> createState() => _DesktopSendState();
|
ConsumerState<DesktopSend> createState() => _DesktopSendState();
|
||||||
|
@ -93,78 +98,12 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
|
||||||
bool _cryptoAmountChangeLock = false;
|
bool _cryptoAmountChangeLock = false;
|
||||||
late VoidCallback onCryptoAmountChanged;
|
late VoidCallback onCryptoAmountChanged;
|
||||||
|
|
||||||
|
bool get isPaynymSend => widget.accountLite != null;
|
||||||
|
|
||||||
Future<void> previewSend() async {
|
Future<void> previewSend() async {
|
||||||
final manager =
|
final manager =
|
||||||
ref.read(walletsChangeNotifierProvider).getManager(walletId);
|
ref.read(walletsChangeNotifierProvider).getManager(walletId);
|
||||||
|
|
||||||
// // TODO: remove the need for this!!
|
|
||||||
// final bool isOwnAddress = await manager.isOwnAddress(_address!);
|
|
||||||
// if (isOwnAddress) {
|
|
||||||
// await showDialog<dynamic>(
|
|
||||||
// context: context,
|
|
||||||
// useSafeArea: false,
|
|
||||||
// barrierDismissible: true,
|
|
||||||
// builder: (context) {
|
|
||||||
// return DesktopDialog(
|
|
||||||
// maxWidth: 400,
|
|
||||||
// maxHeight: double.infinity,
|
|
||||||
// child: Padding(
|
|
||||||
// padding: const EdgeInsets.only(
|
|
||||||
// left: 32,
|
|
||||||
// bottom: 32,
|
|
||||||
// ),
|
|
||||||
// child: Column(
|
|
||||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
// children: [
|
|
||||||
// Row(
|
|
||||||
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
// children: [
|
|
||||||
// Text(
|
|
||||||
// "Transaction failed",
|
|
||||||
// style: STextStyles.desktopH3(context),
|
|
||||||
// ),
|
|
||||||
// const DesktopDialogCloseButton(),
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
// const SizedBox(
|
|
||||||
// height: 12,
|
|
||||||
// ),
|
|
||||||
// Text(
|
|
||||||
// "Sending to self is currently disabled",
|
|
||||||
// textAlign: TextAlign.left,
|
|
||||||
// style: STextStyles.desktopTextExtraExtraSmall(context)
|
|
||||||
// .copyWith(
|
|
||||||
// fontSize: 18,
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// const SizedBox(
|
|
||||||
// height: 40,
|
|
||||||
// ),
|
|
||||||
// Row(
|
|
||||||
// children: [
|
|
||||||
// Expanded(
|
|
||||||
// child: SecondaryButton(
|
|
||||||
// buttonHeight: ButtonHeight.l,
|
|
||||||
// label: "Ok",
|
|
||||||
// onPressed: () {
|
|
||||||
// Navigator.of(context).pop();
|
|
||||||
// },
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// const SizedBox(
|
|
||||||
// width: 32,
|
|
||||||
// ),
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
// },
|
|
||||||
// );
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
final amount = Format.decimalAmountToSatoshis(_amountToSend!, coin);
|
final amount = Format.decimalAmountToSatoshis(_amountToSend!, coin);
|
||||||
int availableBalance;
|
int availableBalance;
|
||||||
if ((coin == Coin.firo || coin == Coin.firoTestNet)) {
|
if ((coin == Coin.firo || coin == Coin.firoTestNet)) {
|
||||||
|
@ -304,7 +243,19 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
|
||||||
|
|
||||||
Map<String, dynamic> txData;
|
Map<String, dynamic> txData;
|
||||||
|
|
||||||
if ((coin == Coin.firo || coin == Coin.firoTestNet) &&
|
if (isPaynymSend) {
|
||||||
|
final wallet = manager.wallet as PaynymWalletInterface;
|
||||||
|
final paymentCode = PaymentCode.fromPaymentCode(
|
||||||
|
widget.accountLite!.code,
|
||||||
|
wallet.networkType,
|
||||||
|
);
|
||||||
|
final feeRate = ref.read(feeRateTypeStateProvider);
|
||||||
|
txData = await wallet.preparePaymentCodeSend(
|
||||||
|
paymentCode: paymentCode,
|
||||||
|
satoshiAmount: amount,
|
||||||
|
args: {"feeRate": feeRate},
|
||||||
|
);
|
||||||
|
} else if ((coin == Coin.firo || coin == Coin.firoTestNet) &&
|
||||||
ref.read(publicPrivateBalanceStateProvider.state).state !=
|
ref.read(publicPrivateBalanceStateProvider.state).state !=
|
||||||
"Private") {
|
"Private") {
|
||||||
txData = await (manager.wallet as FiroWallet).prepareSendPublic(
|
txData = await (manager.wallet as FiroWallet).prepareSendPublic(
|
||||||
|
@ -321,8 +272,13 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!wasCancelled && mounted) {
|
if (!wasCancelled && mounted) {
|
||||||
txData["note"] = _note ?? "";
|
if (isPaynymSend) {
|
||||||
txData["address"] = _address;
|
txData["paynymAccountLite"] = widget.accountLite!;
|
||||||
|
txData["note"] = _note ?? "PayNym send";
|
||||||
|
} else {
|
||||||
|
txData["address"] = _address;
|
||||||
|
txData["note"] = _note ?? "";
|
||||||
|
}
|
||||||
// pop building dialog
|
// pop building dialog
|
||||||
Navigator.of(
|
Navigator.of(
|
||||||
context,
|
context,
|
||||||
|
@ -338,6 +294,7 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
|
||||||
child: ConfirmTransactionView(
|
child: ConfirmTransactionView(
|
||||||
transactionInfo: txData,
|
transactionInfo: txData,
|
||||||
walletId: walletId,
|
walletId: walletId,
|
||||||
|
isPaynymTransaction: isPaynymSend,
|
||||||
routeOnSuccessName: DesktopHomeView.routeName,
|
routeOnSuccessName: DesktopHomeView.routeName,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -439,9 +396,9 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
|
||||||
_cachedAmountToSend == _amountToSend) {
|
_cachedAmountToSend == _amountToSend) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_cachedAmountToSend = _amountToSend;
|
|
||||||
Logging.instance.log("it changed $_amountToSend $_cachedAmountToSend",
|
Logging.instance.log("it changed $_amountToSend $_cachedAmountToSend",
|
||||||
level: LogLevel.Info);
|
level: LogLevel.Info);
|
||||||
|
_cachedAmountToSend = _amountToSend;
|
||||||
|
|
||||||
final price =
|
final price =
|
||||||
ref.read(priceAnd24hChangeNotifierProvider).getPrice(coin).item1;
|
ref.read(priceAnd24hChangeNotifierProvider).getPrice(coin).item1;
|
||||||
|
@ -457,6 +414,7 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_amountToSend = null;
|
_amountToSend = null;
|
||||||
|
_cachedAmountToSend = null;
|
||||||
baseAmountController.text = "";
|
baseAmountController.text = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -475,87 +433,19 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void _updatePreviewButtonState(String? address, Decimal? amount) {
|
void _updatePreviewButtonState(String? address, Decimal? amount) {
|
||||||
final isValidAddress = ref
|
if (isPaynymSend) {
|
||||||
.read(walletsChangeNotifierProvider)
|
ref.read(previewTxButtonStateProvider.state).state =
|
||||||
.getManager(walletId)
|
(amount != null && amount > Decimal.zero);
|
||||||
.validateAddress(address ?? "");
|
} else {
|
||||||
ref.read(previewTxButtonStateProvider.state).state =
|
final isValidAddress = ref
|
||||||
(isValidAddress && amount != null && amount > Decimal.zero);
|
.read(walletsChangeNotifierProvider)
|
||||||
|
.getManager(walletId)
|
||||||
|
.validateAddress(address ?? "");
|
||||||
|
ref.read(previewTxButtonStateProvider.state).state =
|
||||||
|
(isValidAddress && amount != null && amount > Decimal.zero);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// late Future<String> _calculateFeesFuture;
|
|
||||||
|
|
||||||
// Map<int, String> cachedFees = {};
|
|
||||||
// Map<int, String> cachedFiroPrivateFees = {};
|
|
||||||
// Map<int, String> cachedFiroPublicFees = {};
|
|
||||||
|
|
||||||
// Future<String> calculateFees(int amount) async {
|
|
||||||
// if (amount <= 0) {
|
|
||||||
// return "0";
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (coin == Coin.firo || coin == Coin.firoTestNet) {
|
|
||||||
// if (ref.read(publicPrivateBalanceStateProvider.state).state ==
|
|
||||||
// "Private") {
|
|
||||||
// if (cachedFiroPrivateFees[amount] != null) {
|
|
||||||
// return cachedFiroPrivateFees[amount]!;
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// if (cachedFiroPublicFees[amount] != null) {
|
|
||||||
// return cachedFiroPublicFees[amount]!;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// } else if (cachedFees[amount] != null) {
|
|
||||||
// return cachedFees[amount]!;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// final manager =
|
|
||||||
// ref.read(walletsChangeNotifierProvider).getManager(walletId);
|
|
||||||
// final feeObject = await manager.fees;
|
|
||||||
//
|
|
||||||
// late final int feeRate;
|
|
||||||
//
|
|
||||||
// switch (ref.read(feeRateTypeStateProvider.state).state) {
|
|
||||||
// case FeeRateType.fast:
|
|
||||||
// feeRate = feeObject.fast;
|
|
||||||
// break;
|
|
||||||
// case FeeRateType.average:
|
|
||||||
// feeRate = feeObject.medium;
|
|
||||||
// break;
|
|
||||||
// case FeeRateType.slow:
|
|
||||||
// feeRate = feeObject.slow;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// int fee;
|
|
||||||
//
|
|
||||||
// if (coin == Coin.firo || coin == Coin.firoTestNet) {
|
|
||||||
// if (ref.read(publicPrivateBalanceStateProvider.state).state ==
|
|
||||||
// "Private") {
|
|
||||||
// fee = await manager.estimateFeeFor(amount, feeRate);
|
|
||||||
//
|
|
||||||
// cachedFiroPrivateFees[amount] = Format.satoshisToAmount(fee)
|
|
||||||
// .toStringAsFixed(Constants.decimalPlaces);
|
|
||||||
//
|
|
||||||
// return cachedFiroPrivateFees[amount]!;
|
|
||||||
// } else {
|
|
||||||
// fee = await (manager.wallet as FiroWallet)
|
|
||||||
// .estimateFeeForPublic(amount, feeRate);
|
|
||||||
//
|
|
||||||
// cachedFiroPublicFees[amount] = Format.satoshisToAmount(fee)
|
|
||||||
// .toStringAsFixed(Constants.decimalPlaces);
|
|
||||||
//
|
|
||||||
// return cachedFiroPublicFees[amount]!;
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// fee = await manager.estimateFeeFor(amount, feeRate);
|
|
||||||
// cachedFees[amount] =
|
|
||||||
// Format.satoshisToAmount(fee).toStringAsFixed(Constants.decimalPlaces);
|
|
||||||
//
|
|
||||||
// return cachedFees[amount]!;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
Future<String?> _firoBalanceFuture(
|
Future<String?> _firoBalanceFuture(
|
||||||
ChangeNotifierProvider<Manager> provider,
|
ChangeNotifierProvider<Manager> provider,
|
||||||
String locale,
|
String locale,
|
||||||
|
@ -773,7 +663,10 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
ref.refresh(feeSheetSessionCacheProvider);
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
ref.refresh(feeSheetSessionCacheProvider);
|
||||||
|
ref.read(previewTxButtonStateProvider.state).state = false;
|
||||||
|
});
|
||||||
|
|
||||||
// _calculateFeesFuture = calculateFees(0);
|
// _calculateFeesFuture = calculateFees(0);
|
||||||
_data = widget.autoFillData;
|
_data = widget.autoFillData;
|
||||||
|
@ -799,6 +692,10 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
|
||||||
_addressToggleFlag = true;
|
_addressToggleFlag = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isPaynymSend) {
|
||||||
|
sendToController.text = widget.accountLite!.nymName;
|
||||||
|
}
|
||||||
|
|
||||||
_cryptoFocus.addListener(() {
|
_cryptoFocus.addListener(() {
|
||||||
if (!_cryptoFocus.hasFocus && !_baseFocus.hasFocus) {
|
if (!_cryptoFocus.hasFocus && !_baseFocus.hasFocus) {
|
||||||
if (_amountToSend == null) {
|
if (_amountToSend == null) {
|
||||||
|
@ -845,21 +742,6 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
|
||||||
final String locale = ref.watch(
|
final String locale = ref.watch(
|
||||||
localeServiceChangeNotifierProvider.select((value) => value.locale));
|
localeServiceChangeNotifierProvider.select((value) => value.locale));
|
||||||
|
|
||||||
// if (coin == Coin.firo || coin == Coin.firoTestNet) {
|
|
||||||
// ref.listen(publicPrivateBalanceStateProvider, (previous, next) {
|
|
||||||
// if (_amountToSend == null) {
|
|
||||||
// setState(() {
|
|
||||||
// _calculateFeesFuture = calculateFees(0);
|
|
||||||
// });
|
|
||||||
// } else {
|
|
||||||
// setState(() {
|
|
||||||
// _calculateFeesFuture =
|
|
||||||
// calculateFees(Format.decimalAmountToSatoshis(_amountToSend!));
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
|
@ -975,6 +857,36 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 20,
|
height: 20,
|
||||||
),
|
),
|
||||||
|
if (isPaynymSend)
|
||||||
|
Text(
|
||||||
|
"Send to PayNym address",
|
||||||
|
style: STextStyles.smallMed12(context),
|
||||||
|
textAlign: TextAlign.left,
|
||||||
|
),
|
||||||
|
if (isPaynymSend)
|
||||||
|
const SizedBox(
|
||||||
|
height: 10,
|
||||||
|
),
|
||||||
|
if (isPaynymSend)
|
||||||
|
TextField(
|
||||||
|
key: const Key("sendViewPaynymAddressFieldKey"),
|
||||||
|
controller: sendToController,
|
||||||
|
enabled: false,
|
||||||
|
readOnly: true,
|
||||||
|
style: STextStyles.desktopTextFieldLabel(context).copyWith(
|
||||||
|
fontSize: 16,
|
||||||
|
),
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
contentPadding: EdgeInsets.symmetric(
|
||||||
|
vertical: 18,
|
||||||
|
horizontal: 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (isPaynymSend)
|
||||||
|
const SizedBox(
|
||||||
|
height: 20,
|
||||||
|
),
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
|
@ -1020,6 +932,7 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
|
||||||
? newValue
|
? newValue
|
||||||
: oldValue),
|
: oldValue),
|
||||||
],
|
],
|
||||||
|
onChanged: (newValue) {},
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
contentPadding: const EdgeInsets.only(
|
contentPadding: const EdgeInsets.only(
|
||||||
top: 22,
|
top: 22,
|
||||||
|
@ -1108,199 +1021,204 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 20,
|
height: 20,
|
||||||
),
|
),
|
||||||
Text(
|
if (!isPaynymSend)
|
||||||
"Send to",
|
Text(
|
||||||
style: STextStyles.desktopTextExtraSmall(context).copyWith(
|
"Send to",
|
||||||
color: Theme.of(context)
|
|
||||||
.extension<StackColors>()!
|
|
||||||
.textFieldActiveSearchIconRight,
|
|
||||||
),
|
|
||||||
textAlign: TextAlign.left,
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
height: 10,
|
|
||||||
),
|
|
||||||
ClipRRect(
|
|
||||||
borderRadius: BorderRadius.circular(
|
|
||||||
Constants.size.circularBorderRadius,
|
|
||||||
),
|
|
||||||
child: TextField(
|
|
||||||
minLines: 1,
|
|
||||||
maxLines: 5,
|
|
||||||
key: const Key("sendViewAddressFieldKey"),
|
|
||||||
controller: sendToController,
|
|
||||||
readOnly: false,
|
|
||||||
autocorrect: false,
|
|
||||||
enableSuggestions: false,
|
|
||||||
// inputFormatters: <TextInputFormatter>[
|
|
||||||
// FilteringTextInputFormatter.allow(
|
|
||||||
// RegExp("[a-zA-Z0-9]{34}")),
|
|
||||||
// ],
|
|
||||||
toolbarOptions: const ToolbarOptions(
|
|
||||||
copy: false,
|
|
||||||
cut: false,
|
|
||||||
paste: true,
|
|
||||||
selectAll: false,
|
|
||||||
),
|
|
||||||
onChanged: (newValue) {
|
|
||||||
_address = newValue;
|
|
||||||
_updatePreviewButtonState(_address, _amountToSend);
|
|
||||||
|
|
||||||
setState(() {
|
|
||||||
_addressToggleFlag = newValue.isNotEmpty;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
focusNode: _addressFocusNode,
|
|
||||||
style: STextStyles.desktopTextExtraSmall(context).copyWith(
|
style: STextStyles.desktopTextExtraSmall(context).copyWith(
|
||||||
color: Theme.of(context)
|
color: Theme.of(context)
|
||||||
.extension<StackColors>()!
|
.extension<StackColors>()!
|
||||||
.textFieldActiveText,
|
.textFieldActiveSearchIconRight,
|
||||||
height: 1.8,
|
|
||||||
),
|
),
|
||||||
decoration: standardInputDecoration(
|
textAlign: TextAlign.left,
|
||||||
"Enter ${coin.ticker} address",
|
),
|
||||||
_addressFocusNode,
|
if (!isPaynymSend)
|
||||||
context,
|
const SizedBox(
|
||||||
desktopMed: true,
|
height: 10,
|
||||||
).copyWith(
|
),
|
||||||
contentPadding: const EdgeInsets.only(
|
if (!isPaynymSend)
|
||||||
left: 16,
|
ClipRRect(
|
||||||
top: 11,
|
borderRadius: BorderRadius.circular(
|
||||||
bottom: 12,
|
Constants.size.circularBorderRadius,
|
||||||
right: 5,
|
),
|
||||||
|
child: TextField(
|
||||||
|
minLines: 1,
|
||||||
|
maxLines: 5,
|
||||||
|
key: const Key("sendViewAddressFieldKey"),
|
||||||
|
controller: sendToController,
|
||||||
|
readOnly: false,
|
||||||
|
autocorrect: false,
|
||||||
|
enableSuggestions: false,
|
||||||
|
// inputFormatters: <TextInputFormatter>[
|
||||||
|
// FilteringTextInputFormatter.allow(
|
||||||
|
// RegExp("[a-zA-Z0-9]{34}")),
|
||||||
|
// ],
|
||||||
|
toolbarOptions: const ToolbarOptions(
|
||||||
|
copy: false,
|
||||||
|
cut: false,
|
||||||
|
paste: true,
|
||||||
|
selectAll: false,
|
||||||
),
|
),
|
||||||
suffixIcon: Padding(
|
onChanged: (newValue) {
|
||||||
padding: sendToController.text.isEmpty
|
_address = newValue;
|
||||||
? const EdgeInsets.only(right: 8)
|
_updatePreviewButtonState(_address, _amountToSend);
|
||||||
: const EdgeInsets.only(right: 0),
|
|
||||||
child: UnconstrainedBox(
|
setState(() {
|
||||||
child: Row(
|
_addressToggleFlag = newValue.isNotEmpty;
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
});
|
||||||
children: [
|
},
|
||||||
_addressToggleFlag
|
focusNode: _addressFocusNode,
|
||||||
? TextFieldIconButton(
|
style: STextStyles.desktopTextExtraSmall(context).copyWith(
|
||||||
key: const Key(
|
color: Theme.of(context)
|
||||||
"sendViewClearAddressFieldButtonKey"),
|
.extension<StackColors>()!
|
||||||
onTap: () {
|
.textFieldActiveText,
|
||||||
sendToController.text = "";
|
height: 1.8,
|
||||||
_address = "";
|
),
|
||||||
_updatePreviewButtonState(
|
decoration: standardInputDecoration(
|
||||||
_address, _amountToSend);
|
"Enter ${coin.ticker} address",
|
||||||
setState(() {
|
_addressFocusNode,
|
||||||
_addressToggleFlag = false;
|
context,
|
||||||
});
|
desktopMed: true,
|
||||||
},
|
).copyWith(
|
||||||
child: const XIcon(),
|
contentPadding: const EdgeInsets.only(
|
||||||
)
|
left: 16,
|
||||||
: TextFieldIconButton(
|
top: 11,
|
||||||
key: const Key(
|
bottom: 12,
|
||||||
"sendViewPasteAddressFieldButtonKey"),
|
right: 5,
|
||||||
onTap: pasteAddress,
|
),
|
||||||
child: sendToController.text.isEmpty
|
suffixIcon: Padding(
|
||||||
? const ClipboardIcon()
|
padding: sendToController.text.isEmpty
|
||||||
: const XIcon(),
|
? const EdgeInsets.only(right: 8)
|
||||||
),
|
: const EdgeInsets.only(right: 0),
|
||||||
if (sendToController.text.isEmpty)
|
child: UnconstrainedBox(
|
||||||
TextFieldIconButton(
|
child: Row(
|
||||||
key: const Key("sendViewAddressBookButtonKey"),
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
onTap: () async {
|
children: [
|
||||||
final entry =
|
_addressToggleFlag
|
||||||
await showDialog<ContactAddressEntry?>(
|
? TextFieldIconButton(
|
||||||
context: context,
|
key: const Key(
|
||||||
builder: (context) => DesktopDialog(
|
"sendViewClearAddressFieldButtonKey"),
|
||||||
maxWidth: 696,
|
onTap: () {
|
||||||
maxHeight: 600,
|
sendToController.text = "";
|
||||||
child: Column(
|
_address = "";
|
||||||
mainAxisSize: MainAxisSize.min,
|
_updatePreviewButtonState(
|
||||||
children: [
|
_address, _amountToSend);
|
||||||
Row(
|
setState(() {
|
||||||
mainAxisAlignment:
|
_addressToggleFlag = false;
|
||||||
MainAxisAlignment.spaceBetween,
|
});
|
||||||
children: [
|
},
|
||||||
Padding(
|
child: const XIcon(),
|
||||||
padding: const EdgeInsets.only(
|
)
|
||||||
left: 32,
|
: TextFieldIconButton(
|
||||||
),
|
key: const Key(
|
||||||
child: Text(
|
"sendViewPasteAddressFieldButtonKey"),
|
||||||
"Address book",
|
onTap: pasteAddress,
|
||||||
style:
|
child: sendToController.text.isEmpty
|
||||||
STextStyles.desktopH3(context),
|
? const ClipboardIcon()
|
||||||
),
|
: const XIcon(),
|
||||||
),
|
|
||||||
const DesktopDialogCloseButton(),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: AddressBookAddressChooser(
|
|
||||||
coin: coin,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
if (sendToController.text.isEmpty)
|
||||||
|
TextFieldIconButton(
|
||||||
if (entry != null) {
|
key: const Key("sendViewAddressBookButtonKey"),
|
||||||
sendToController.text =
|
onTap: () async {
|
||||||
entry.other ?? entry.label;
|
final entry =
|
||||||
|
await showDialog<ContactAddressEntry?>(
|
||||||
_address = entry.address;
|
context: context,
|
||||||
|
builder: (context) => DesktopDialog(
|
||||||
_updatePreviewButtonState(
|
maxWidth: 696,
|
||||||
_address,
|
maxHeight: 600,
|
||||||
_amountToSend,
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
left: 32,
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
"Address book",
|
||||||
|
style: STextStyles.desktopH3(
|
||||||
|
context),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const DesktopDialogCloseButton(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: AddressBookAddressChooser(
|
||||||
|
coin: coin,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
setState(() {
|
if (entry != null) {
|
||||||
_addressToggleFlag = true;
|
sendToController.text =
|
||||||
});
|
entry.other ?? entry.label;
|
||||||
}
|
|
||||||
},
|
_address = entry.address;
|
||||||
child: const AddressBookIcon(),
|
|
||||||
),
|
_updatePreviewButtonState(
|
||||||
// if (sendToController.text.isEmpty)
|
_address,
|
||||||
// TextFieldIconButton(
|
_amountToSend,
|
||||||
// key: const Key("sendViewScanQrButtonKey"),
|
);
|
||||||
// onTap: scanQr,
|
|
||||||
// child: const QrCodeIcon(),
|
setState(() {
|
||||||
// )
|
_addressToggleFlag = true;
|
||||||
],
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: const AddressBookIcon(),
|
||||||
|
),
|
||||||
|
// if (sendToController.text.isEmpty)
|
||||||
|
// TextFieldIconButton(
|
||||||
|
// key: const Key("sendViewScanQrButtonKey"),
|
||||||
|
// onTap: scanQr,
|
||||||
|
// child: const QrCodeIcon(),
|
||||||
|
// )
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
if (!isPaynymSend)
|
||||||
Builder(
|
Builder(
|
||||||
builder: (_) {
|
builder: (_) {
|
||||||
final error = _updateInvalidAddressText(
|
final error = _updateInvalidAddressText(
|
||||||
_address ?? "",
|
_address ?? "",
|
||||||
ref.read(walletsChangeNotifierProvider).getManager(walletId),
|
ref.read(walletsChangeNotifierProvider).getManager(walletId),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (error == null || error.isEmpty) {
|
if (error == null || error.isEmpty) {
|
||||||
return Container();
|
return Container();
|
||||||
} else {
|
} else {
|
||||||
return Align(
|
return Align(
|
||||||
alignment: Alignment.topLeft,
|
alignment: Alignment.topLeft,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.only(
|
||||||
left: 12.0,
|
left: 12.0,
|
||||||
top: 4.0,
|
top: 4.0,
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
error,
|
error,
|
||||||
textAlign: TextAlign.left,
|
textAlign: TextAlign.left,
|
||||||
style: STextStyles.label(context).copyWith(
|
style: STextStyles.label(context).copyWith(
|
||||||
color:
|
color: Theme.of(context)
|
||||||
Theme.of(context).extension<StackColors>()!.textError,
|
.extension<StackColors>()!
|
||||||
|
.textError,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
);
|
}
|
||||||
}
|
},
|
||||||
},
|
),
|
||||||
),
|
|
||||||
// const SizedBox(
|
// const SizedBox(
|
||||||
// height: 20,
|
// height: 20,
|
||||||
// ),
|
// ),
|
||||||
|
@ -1368,9 +1286,10 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
|
||||||
// ),
|
// ),
|
||||||
// ),
|
// ),
|
||||||
// ),
|
// ),
|
||||||
const SizedBox(
|
if (!isPaynymSend)
|
||||||
height: 20,
|
const SizedBox(
|
||||||
),
|
height: 20,
|
||||||
|
),
|
||||||
if (coin != Coin.epicCash)
|
if (coin != Coin.epicCash)
|
||||||
Text(
|
Text(
|
||||||
"Transaction fee (estimated)",
|
"Transaction fee (estimated)",
|
||||||
|
|
|
@ -1,12 +1,16 @@
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:isar/isar.dart';
|
import 'package:isar/isar.dart';
|
||||||
import 'package:stackwallet/hive/db.dart';
|
import 'package:stackwallet/hive/db.dart';
|
||||||
|
import 'package:stackwallet/models/exchange/aggregate_currency.dart';
|
||||||
|
import 'package:stackwallet/models/exchange/exchange_form_state.dart';
|
||||||
import 'package:stackwallet/models/isar/exchange_cache/currency.dart';
|
import 'package:stackwallet/models/isar/exchange_cache/currency.dart';
|
||||||
import 'package:stackwallet/models/isar/exchange_cache/pair.dart';
|
import 'package:stackwallet/models/isar/exchange_cache/pair.dart';
|
||||||
import 'package:stackwallet/services/exchange/change_now/change_now_exchange.dart';
|
import 'package:stackwallet/services/exchange/change_now/change_now_exchange.dart';
|
||||||
import 'package:stackwallet/services/exchange/majestic_bank/majestic_bank_exchange.dart';
|
import 'package:stackwallet/services/exchange/majestic_bank/majestic_bank_exchange.dart';
|
||||||
|
import 'package:stackwallet/utilities/enums/exchange_rate_type_enum.dart';
|
||||||
import 'package:stackwallet/utilities/logger.dart';
|
import 'package:stackwallet/utilities/logger.dart';
|
||||||
import 'package:stackwallet/utilities/stack_file_system.dart';
|
import 'package:stackwallet/utilities/stack_file_system.dart';
|
||||||
|
import 'package:tuple/tuple.dart';
|
||||||
|
|
||||||
class ExchangeDataLoadingService {
|
class ExchangeDataLoadingService {
|
||||||
ExchangeDataLoadingService._();
|
ExchangeDataLoadingService._();
|
||||||
|
@ -50,6 +54,51 @@ class ExchangeDataLoadingService {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> setCurrenciesIfEmpty(ExchangeFormState state) async {
|
||||||
|
if (state.sendCurrency == null && state.receiveCurrency == null) {
|
||||||
|
if (await isar.currencies.count() > 0) {
|
||||||
|
final sendCurrency = await getAggregateCurrency(
|
||||||
|
"BTC",
|
||||||
|
state.exchangeRateType,
|
||||||
|
);
|
||||||
|
final receiveCurrency = await getAggregateCurrency(
|
||||||
|
"XMR",
|
||||||
|
state.exchangeRateType,
|
||||||
|
);
|
||||||
|
state.setCurrencies(sendCurrency, receiveCurrency);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<AggregateCurrency?> getAggregateCurrency(
|
||||||
|
String ticker, ExchangeRateType rateType) async {
|
||||||
|
final currencies = await ExchangeDataLoadingService.instance.isar.currencies
|
||||||
|
.filter()
|
||||||
|
.group((q) => rateType == ExchangeRateType.fixed
|
||||||
|
? q
|
||||||
|
.rateTypeEqualTo(SupportedRateType.both)
|
||||||
|
.or()
|
||||||
|
.rateTypeEqualTo(SupportedRateType.fixed)
|
||||||
|
: q
|
||||||
|
.rateTypeEqualTo(SupportedRateType.both)
|
||||||
|
.or()
|
||||||
|
.rateTypeEqualTo(SupportedRateType.estimated))
|
||||||
|
.and()
|
||||||
|
.tickerEqualTo(
|
||||||
|
ticker,
|
||||||
|
caseSensitive: false,
|
||||||
|
)
|
||||||
|
.findAll();
|
||||||
|
|
||||||
|
final items = currencies
|
||||||
|
.map((e) => Tuple2(e.exchangeName, e))
|
||||||
|
.toList(growable: false);
|
||||||
|
|
||||||
|
return items.isNotEmpty
|
||||||
|
? AggregateCurrency(exchangeCurrencyPairs: items)
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
bool get isLoading => _locked;
|
bool get isLoading => _locked;
|
||||||
|
|
||||||
bool _locked = false;
|
bool _locked = false;
|
||||||
|
|
|
@ -306,7 +306,7 @@ mixin PaynymWalletInterface {
|
||||||
{required PaymentCode paymentCode,
|
{required PaymentCode paymentCode,
|
||||||
required int satoshiAmount,
|
required int satoshiAmount,
|
||||||
Map<String, dynamic>? args}) async {
|
Map<String, dynamic>? args}) async {
|
||||||
if (!(await hasConnected(paymentCode.notificationAddressP2PKH()))) {
|
if (!(await hasConnected(paymentCode.toString()))) {
|
||||||
throw PaynymSendException(
|
throw PaynymSendException(
|
||||||
"No notification transaction sent to $paymentCode");
|
"No notification transaction sent to $paymentCode");
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in a new issue