mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-12-23 11:59:30 +00:00
basic coin control view
This commit is contained in:
parent
7319f509f0
commit
456abf7ee4
5 changed files with 272 additions and 6 deletions
129
lib/pages/coin_control/coin_control_view.dart
Normal file
129
lib/pages/coin_control/coin_control_view.dart
Normal 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,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
120
lib/pages/coin_control/utxo_card.dart
Normal file
120
lib/pages/coin_control/utxo_card.dart
Normal 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,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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(
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in a new issue