WIP boost fee slider

This commit is contained in:
sneurlax 2024-06-12 14:23:04 -05:00 committed by julian
parent 6fa1bc75af
commit f2ca700a9f
2 changed files with 322 additions and 179 deletions

View file

@ -15,7 +15,6 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:isar/isar.dart'; import 'package:isar/isar.dart';
import 'package:url_launcher/url_launcher.dart';
import '../../../../models/isar/models/blockchain_data/transaction.dart'; import '../../../../models/isar/models/blockchain_data/transaction.dart';
import '../../../../models/isar/models/blockchain_data/v2/transaction_v2.dart'; import '../../../../models/isar/models/blockchain_data/v2/transaction_v2.dart';
@ -27,7 +26,6 @@ import '../../../../providers/providers.dart';
import '../../../../themes/stack_colors.dart'; import '../../../../themes/stack_colors.dart';
import '../../../../utilities/amount/amount.dart'; import '../../../../utilities/amount/amount.dart';
import '../../../../utilities/amount/amount_formatter.dart'; import '../../../../utilities/amount/amount_formatter.dart';
import '../../../../utilities/block_explorers.dart';
import '../../../../utilities/constants.dart'; import '../../../../utilities/constants.dart';
import '../../../../utilities/logger.dart'; import '../../../../utilities/logger.dart';
import '../../../../utilities/text_styles.dart'; import '../../../../utilities/text_styles.dart';
@ -39,9 +37,9 @@ import '../../../../wallets/isar/providers/wallet_info_provider.dart';
import '../../../../wallets/wallet/impl/epiccash_wallet.dart'; import '../../../../wallets/wallet/impl/epiccash_wallet.dart';
import '../../../../wallets/wallet/wallet_mixin_interfaces/spark_interface.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/spark_interface.dart';
import '../../../../widgets/background.dart'; import '../../../../widgets/background.dart';
import '../../../../widgets/boost_fee_slider.dart';
import '../../../../widgets/conditional_parent.dart'; import '../../../../widgets/conditional_parent.dart';
import '../../../../widgets/custom_buttons/app_bar_icon_button.dart'; import '../../../../widgets/custom_buttons/app_bar_icon_button.dart';
import '../../../../widgets/custom_buttons/blue_text_button.dart';
import '../../../../widgets/desktop/desktop_dialog.dart'; import '../../../../widgets/desktop/desktop_dialog.dart';
import '../../../../widgets/desktop/desktop_dialog_close_button.dart'; import '../../../../widgets/desktop/desktop_dialog_close_button.dart';
import '../../../../widgets/desktop/primary_button.dart'; import '../../../../widgets/desktop/primary_button.dart';
@ -94,6 +92,8 @@ class _BoostTransactionViewState extends ConsumerState<BoostTransactionView> {
String? _sparkMemo; String? _sparkMemo;
BigInt customFee = BigInt.one;
@override @override
void initState() { void initState() {
isDesktop = Util.isDesktop; isDesktop = Util.isDesktop;
@ -1282,7 +1282,9 @@ class _BoostTransactionViewState extends ConsumerState<BoostTransactionView> {
fee, fee,
); );
return Row( return Column(
children: [
Row(
mainAxisAlignment: mainAxisAlignment:
MainAxisAlignment.spaceBetween, MainAxisAlignment.spaceBetween,
crossAxisAlignment: crossAxisAlignment:
@ -1299,7 +1301,8 @@ class _BoostTransactionViewState extends ConsumerState<BoostTransactionView> {
.desktopTextExtraExtraSmall( .desktopTextExtraExtraSmall(
context, context,
) )
: STextStyles.itemSubtitle( : STextStyles
.itemSubtitle(
context, context,
), ),
), ),
@ -1308,6 +1311,27 @@ class _BoostTransactionViewState extends ConsumerState<BoostTransactionView> {
height: 2, height: 2,
), ),
if (isDesktop) if (isDesktop)
SelectableText(
feeString,
style: isDesktop
? STextStyles
.desktopTextExtraExtraSmall(
context,
).copyWith(
color: Theme.of(
context)
.extension<
StackColors>()!
.textDark,
)
: STextStyles
.itemSubtitle12(
context,
),
),
],
),
if (!isDesktop)
SelectableText( SelectableText(
feeString, feeString,
style: isDesktop style: isDesktop
@ -1325,28 +1349,25 @@ class _BoostTransactionViewState extends ConsumerState<BoostTransactionView> {
context, context,
), ),
), ),
// TODO [prio=high]: Boost tx fee UI. // if (isDesktop)
// IconCopyButton(data: feeString),
], ],
), ),
if (!isDesktop) Padding(
SelectableText( padding: const EdgeInsets.only(
feeString, bottom: 12,
style: isDesktop top: 16,
? STextStyles ),
.desktopTextExtraExtraSmall( child: BoostFeeSlider(
context, coin: coin,
).copyWith( onFeeChanged: (fee) {
color: Theme.of(context) customFee = fee;
.extension< },
StackColors>()! min: fee.raw,
.textDark, max: fee.raw * BigInt.from(4),
// TODO [prio=med]: The max fee should be set to an absurd fee.
),
) )
: STextStyles.itemSubtitle12(
context,
),
),
if (isDesktop)
IconCopyButton(data: feeString),
], ],
); );
}, },
@ -1493,142 +1514,142 @@ class _BoostTransactionViewState extends ConsumerState<BoostTransactionView> {
// ], // ],
// ), // ),
// ), // ),
isDesktop // isDesktop
? const _Divider() // ? const _Divider()
: const SizedBox( // : const SizedBox(
height: 12, // height: 12,
), // ),
RoundedWhiteContainer( // RoundedWhiteContainer(
padding: isDesktop // padding: isDesktop
? const EdgeInsets.all(16) // ? const EdgeInsets.all(16)
: const EdgeInsets.all(12), // : const EdgeInsets.all(12),
child: Row( // child: Row(
crossAxisAlignment: CrossAxisAlignment.start, // crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: // mainAxisAlignment:
MainAxisAlignment.spaceBetween, // MainAxisAlignment.spaceBetween,
children: [ // children: [
Expanded( // Expanded(
child: Column( // child: Column(
crossAxisAlignment: // crossAxisAlignment:
CrossAxisAlignment.start, // CrossAxisAlignment.start,
children: [ // children: [
Text( // Text(
"Transaction ID", // "Transaction ID",
style: isDesktop // style: isDesktop
? STextStyles // ? STextStyles
.desktopTextExtraExtraSmall( // .desktopTextExtraExtraSmall(
context, // context,
) // )
: STextStyles.itemSubtitle( // : STextStyles.itemSubtitle(
context, // context,
), // ),
), // ),
const SizedBox( // const SizedBox(
height: 8, // height: 8,
), // ),
// Flexible( // // Flexible(
// child: FittedBox( // // child: FittedBox(
// fit: BoxFit.scaleDown, // // fit: BoxFit.scaleDown,
// child: // // child:
SelectableText( // SelectableText(
_transaction.txid, // _transaction.txid,
style: isDesktop // style: isDesktop
? STextStyles // ? STextStyles
.desktopTextExtraExtraSmall( // .desktopTextExtraExtraSmall(
context, // context,
).copyWith( // ).copyWith(
color: Theme.of(context) // color: Theme.of(context)
.extension<StackColors>()! // .extension<StackColors>()!
.textDark, // .textDark,
) // )
: STextStyles.itemSubtitle12( // : STextStyles.itemSubtitle12(
context, // context,
), // ),
), // ),
if (coin is! Epiccash) // if (coin is! Epiccash)
const SizedBox( // const SizedBox(
height: 8, // height: 8,
), // ),
if (coin is! Epiccash) // if (coin is! Epiccash)
CustomTextButton( // CustomTextButton(
text: "Open in block explorer", // text: "Open in block explorer",
onTap: () async { // onTap: () async {
final uri = // final uri =
getBlockExplorerTransactionUrlFor( // getBlockExplorerTransactionUrlFor(
coin: coin, // coin: coin,
txid: _transaction.txid, // txid: _transaction.txid,
);
if (ref
.read(
prefsChangeNotifierProvider,
)
.hideBlockExplorerWarning ==
false) {
final shouldContinue =
await showExplorerWarning(
"${uri.scheme}://${uri.host}",
);
if (!shouldContinue) {
return;
}
}
// ref
// .read(
// shouldShowLockscreenOnResumeStateProvider
// .state)
// .state = false;
try {
await launchUrl(
uri,
mode: LaunchMode
.externalApplication,
);
} catch (_) {
if (mounted) {
unawaited(
showDialog<void>(
context: context,
builder: (_) =>
StackOkDialog(
title:
"Could not open in block explorer",
message:
"Failed to open \"${uri.toString()}\"",
),
),
);
}
} finally {
// Future<void>.delayed(
// const Duration(seconds: 1),
// () => ref
// .read(
// shouldShowLockscreenOnResumeStateProvider
// .state)
// .state = true,
// ); // );
} //
}, // if (ref
), // .read(
// prefsChangeNotifierProvider,
// )
// .hideBlockExplorerWarning ==
// false) {
// final shouldContinue =
// await showExplorerWarning(
// "${uri.scheme}://${uri.host}",
// );
//
// if (!shouldContinue) {
// return;
// }
// }
//
// // ref
// // .read(
// // shouldShowLockscreenOnResumeStateProvider
// // .state)
// // .state = false;
// try {
// await launchUrl(
// uri,
// mode: LaunchMode
// .externalApplication,
// );
// } catch (_) {
// if (mounted) {
// unawaited(
// showDialog<void>(
// context: context,
// builder: (_) =>
// StackOkDialog(
// title:
// "Could not open in block explorer",
// message:
// "Failed to open \"${uri.toString()}\"",
// ),
// ),
// );
// }
// } finally {
// // Future<void>.delayed(
// // const Duration(seconds: 1),
// // () => ref
// // .read(
// // shouldShowLockscreenOnResumeStateProvider
// // .state)
// // .state = true,
// // );
// }
// },
// ),
// // ),
// // ),
// ],
// ),
// ),
// if (isDesktop)
// const SizedBox(
// width: 12,
// ),
// if (isDesktop)
// IconCopyButton(
// data: _transaction.txid,
// ),
// ],
// ), // ),
// ), // ),
],
),
),
if (isDesktop)
const SizedBox(
width: 12,
),
if (isDesktop)
IconCopyButton(
data: _transaction.txid,
),
],
),
),
// if ((coin is FiroTestNet || coin is Firo) && // if ((coin is FiroTestNet || coin is Firo) &&
// _transaction.subType == "mint") // _transaction.subType == "mint")
// const SizedBox( // const SizedBox(

View file

@ -0,0 +1,122 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../utilities/amount/amount.dart';
import '../utilities/amount/amount_formatter.dart';
import '../wallets/crypto_currency/crypto_currency.dart'; // Update with your actual path
class BoostFeeSlider extends ConsumerStatefulWidget {
final CryptoCurrency coin;
final Function(BigInt) onFeeChanged;
final BigInt min;
final BigInt max;
BoostFeeSlider({
required this.coin,
required this.onFeeChanged,
required this.min,
required this.max,
});
@override
_BoostFeeSliderState createState() => _BoostFeeSliderState();
}
class _BoostFeeSliderState extends ConsumerState<BoostFeeSlider> {
double _currentSliderValue = 0;
late TextEditingController _textEditingController;
@override
void initState() {
super.initState();
_currentSliderValue = widget.min.toDouble();
_textEditingController = TextEditingController(
text: ref.read(pAmountFormatter(widget.coin)).format(
Amount(
rawValue: BigInt.from(_currentSliderValue),
fractionDigits: widget.coin.fractionDigits),
withUnitName: false,
),
);
_textEditingController.addListener(() {
BigInt? value =
BigInt.tryParse(_textEditingController.text.replaceAll(',', ''));
if (value != null && value >= widget.min && value <= widget.max) {
setState(() {
_currentSliderValue = value.toDouble();
widget.onFeeChanged(value);
});
}
});
}
@override
void dispose() {
_textEditingController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: <Widget>[
Row(
children: [
Expanded(
child: Slider(
value: _currentSliderValue,
min: widget.min.toDouble(),
max: widget.max.toDouble(),
divisions: (widget.max - widget.min).toInt(),
label: ref.read(pAmountFormatter(widget.coin)).format(Amount(
rawValue: BigInt.from(_currentSliderValue),
fractionDigits: widget.coin.fractionDigits)),
onChanged: (value) {
setState(() {
_currentSliderValue = value;
_textEditingController.text = ref
.read(pAmountFormatter(widget.coin))
.format(Amount(
rawValue: BigInt.from(_currentSliderValue),
fractionDigits: widget.coin.fractionDigits));
widget.onFeeChanged(BigInt.from(_currentSliderValue));
});
},
),
),
SizedBox(width: 16),
Container(
width: 122,
child: TextField(
controller: _textEditingController,
keyboardType: TextInputType.number,
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
],
decoration: InputDecoration(
border: OutlineInputBorder(),
),
onChanged: (value) {
BigInt? newValue =
BigInt.tryParse(value.replaceAll(',', ''));
if (newValue != null &&
newValue >= widget.min &&
newValue <= widget.max) {
setState(() {
_currentSliderValue = newValue.toDouble();
widget.onFeeChanged(newValue);
});
}
},
),
),
],
),
],
),
);
}
}