basic coin control view

This commit is contained in:
julian 2023-03-06 12:11:13 -06:00
parent 7319f509f0
commit 456abf7ee4
5 changed files with 272 additions and 6 deletions

View file

@ -0,0 +1,129 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:isar/isar.dart';
import 'package:stackwallet/db/main_db.dart';
import 'package:stackwallet/models/isar/models/isar_models.dart';
import 'package:stackwallet/pages/coin_control/utxo_card.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/widgets/background.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart';
import 'package:stackwallet/widgets/toggle.dart';
class CoinControlView extends ConsumerStatefulWidget {
const CoinControlView({
Key? key,
required this.walletId,
}) : super(key: key);
static const routeName = "/coinControl";
final String walletId;
@override
ConsumerState<CoinControlView> createState() => _CoinControlViewState();
}
class _CoinControlViewState extends ConsumerState<CoinControlView> {
bool _showAvailable = false;
@override
Widget build(BuildContext context) {
debugPrint("BUILD: $runtimeType");
final ids = MainDB.instance
.getUTXOs(widget.walletId)
.filter()
.isBlockedEqualTo(_showAvailable)
.idProperty()
.findAllSync();
return Background(
child: Scaffold(
backgroundColor: Theme.of(context).extension<StackColors>()!.background,
appBar: AppBar(
leading: AppBarBackButton(
onPressed: () {
Navigator.of(context).pop();
},
),
title: Text(
"Coin control",
style: STextStyles.navBarTitle(context),
),
titleSpacing: 0,
),
body: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16,
),
child: Column(
children: [
const SizedBox(
height: 10,
),
RoundedWhiteContainer(
child: Text(
"This option allows you to control, freeze, and utilize outputs at your discretion. Tap the output circle to select.",
style: STextStyles.subtitle(context),
),
),
const SizedBox(
height: 10,
),
SizedBox(
height: 48,
child: Toggle(
key: UniqueKey(),
onColor: Theme.of(context).extension<StackColors>()!.popupBG,
onText: "Available outputs",
offColor: Theme.of(context)
.extension<StackColors>()!
.textFieldDefaultBG,
offText: "Frozen outputs",
isOn: _showAvailable,
onValueChanged: (value) {
setState(() {
_showAvailable = value;
});
},
decoration: BoxDecoration(
color: Colors.transparent,
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
),
),
),
const SizedBox(
height: 10,
),
Expanded(
child: ListView.separated(
itemCount: ids.length,
separatorBuilder: (context, _) => const SizedBox(
height: 10,
),
itemBuilder: (context, index) {
final utxo = MainDB.instance.isar.utxos
.where()
.idEqualTo(ids[index])
.findFirstSync()!;
return UtxoCard(
key: Key("${utxo.walletId}_${utxo.id}"),
walletId: widget.walletId,
utxo: utxo,
);
},
),
),
],
),
),
),
);
}
}

View file

@ -0,0 +1,120 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:isar/isar.dart';
import 'package:stackwallet/db/main_db.dart';
import 'package:stackwallet/models/isar/models/isar_models.dart';
import 'package:stackwallet/providers/global/wallets_provider.dart';
import 'package:stackwallet/utilities/assets.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/rounded_white_container.dart';
class UtxoCard extends ConsumerStatefulWidget {
const UtxoCard({
Key? key,
required this.utxo,
required this.walletId,
this.selectable = false,
}) : super(key: key);
final String walletId;
final UTXO utxo;
final bool selectable;
@override
ConsumerState<UtxoCard> createState() => _UtxoCardState();
}
class _UtxoCardState extends ConsumerState<UtxoCard> {
late final UTXO utxo;
bool _selected = false;
@override
void initState() {
utxo = widget.utxo;
super.initState();
}
@override
Widget build(BuildContext context) {
debugPrint("BUILD: $runtimeType");
final coin = ref.watch(walletsChangeNotifierProvider
.select((value) => value.getManager(widget.walletId).coin));
final addr = MainDB.instance.isar.transactions
.where()
.txidWalletIdEqualTo(
utxo.txid,
widget.walletId,
)
.findFirstSync()
?.address
.value
?.value;
String? label;
if (addr != null) {
label = MainDB.instance.isar.addressLabels
.where()
.addressStringWalletIdEqualTo(addr, widget.walletId)
.findFirstSync()
?.value;
}
return RoundedWhiteContainer(
child: Row(
children: [
SvgPicture.asset(
_selected
? Assets.svg.coinControl.selected
: utxo.isBlocked
? Assets.svg.coinControl.blocked
: Assets.svg.coinControl.unBlocked,
width: 32,
height: 32,
),
const SizedBox(
width: 10,
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
"${Format.satoshisToAmount(
utxo.value,
coin: coin,
).toStringAsFixed(coin.decimals)} ${coin.ticker}",
style: STextStyles.w600_14(context),
),
const SizedBox(
height: 2,
),
Row(
children: [
Flexible(
child: Text(
label ?? addr ?? utxo.txid,
style: STextStyles.w500_12(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textSubtitle1,
),
),
),
],
),
],
),
),
],
),
);
}
}

View file

@ -3,6 +3,7 @@ import 'dart:async';
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/flutter_svg.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_claim_view.dart';
import 'package:stackwallet/pages/paynym/paynym_home_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/paynym_api_provider.dart';
@ -112,10 +113,10 @@ class _WalletNavigationBarState extends ConsumerState<WalletNavigationBar> {
if (mounted) { if (mounted) {
Navigator.of(context).pop(); Navigator.of(context).pop();
// Navigator.of(context).pushNamed( Navigator.of(context).pushNamed(
// PaynymHomeView.routeName, CoinControlView.routeName,
// arguments: widget.walletId, arguments: widget.walletId,
// ); );
} }
}, },
child: Container( child: Container(

View file

@ -27,6 +27,7 @@ import 'package:stackwallet/pages/address_book_views/subviews/edit_contact_name_
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/buy_view/buy_quote_preview.dart'; import 'package:stackwallet/pages/buy_view/buy_quote_preview.dart';
import 'package:stackwallet/pages/buy_view/buy_view.dart'; import 'package:stackwallet/pages/buy_view/buy_view.dart';
import 'package:stackwallet/pages/coin_control/coin_control_view.dart';
import 'package:stackwallet/pages/exchange_view/choose_from_stack_view.dart'; import 'package:stackwallet/pages/exchange_view/choose_from_stack_view.dart';
import 'package:stackwallet/pages/exchange_view/edit_trade_note_view.dart'; import 'package:stackwallet/pages/exchange_view/edit_trade_note_view.dart';
import 'package:stackwallet/pages/exchange_view/exchange_step_views/step_1_view.dart'; import 'package:stackwallet/pages/exchange_view/exchange_step_views/step_1_view.dart';
@ -130,8 +131,6 @@ import 'package:stackwallet/utilities/enums/add_wallet_type_enum.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:tuple/tuple.dart'; import 'package:tuple/tuple.dart';
import 'models/isar/models/blockchain_data/transaction.dart';
class RouteGenerator { class RouteGenerator {
static const bool useMaterialPageRoute = true; static const bool useMaterialPageRoute = true;
@ -214,6 +213,20 @@ class RouteGenerator {
} }
return _routeError("${settings.name} invalid args: ${args.toString()}"); return _routeError("${settings.name} invalid args: ${args.toString()}");
case CoinControlView.routeName:
if (args is String) {
return getRoute(
shouldUseMaterialRoute: useMaterialPageRoute,
builder: (_) => CoinControlView(
walletId: args,
),
settings: RouteSettings(
name: settings.name,
),
);
}
return _routeError("${settings.name} invalid args: ${args.toString()}");
case PaynymHomeView.routeName: case PaynymHomeView.routeName:
if (args is String) { if (args is String) {
return getRoute( return getRoute(

View file

@ -14,6 +14,7 @@ import 'package:stackwallet/services/coins/namecoin/namecoin_wallet.dart'
import 'package:stackwallet/services/coins/particl/particl_wallet.dart' import 'package:stackwallet/services/coins/particl/particl_wallet.dart'
as particl; as particl;
import 'package:stackwallet/services/coins/wownero/wownero_wallet.dart' as wow; import 'package:stackwallet/services/coins/wownero/wownero_wallet.dart' as wow;
import 'package:stackwallet/utilities/constants.dart';
enum Coin { enum Coin {
bitcoin, bitcoin,
@ -232,6 +233,8 @@ extension CoinExt on Coin {
return nmc.MINIMUM_CONFIRMATIONS; return nmc.MINIMUM_CONFIRMATIONS;
} }
} }
int get decimals => Constants.decimalPlacesForCoin(this);
} }
Coin coinFromPrettyName(String name) { Coin coinFromPrettyName(String name) {