mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-11-17 09:47:37 +00:00
Merge pull request #454 from cypherstack/ui-fixes
Desktop address list gui
This commit is contained in:
commit
a715c20236
13 changed files with 1132 additions and 411 deletions
|
@ -9,6 +9,7 @@ import 'package:stackwallet/widgets/conditional_parent.dart';
|
|||
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||
import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
|
||||
import 'package:stackwallet/widgets/desktop/primary_button.dart';
|
||||
import 'package:stackwallet/widgets/desktop/secondary_button.dart';
|
||||
import 'package:stackwallet/widgets/icon_widgets/x_icon.dart';
|
||||
import 'package:stackwallet/widgets/stack_text_field.dart';
|
||||
import 'package:stackwallet/widgets/textfield_icon_button.dart';
|
||||
|
@ -186,10 +187,31 @@ class _SingleFieldEditViewState extends State<SingleFieldEditView> {
|
|||
condition: isDesktop,
|
||||
builder: (child) => Padding(
|
||||
padding: const EdgeInsets.all(32),
|
||||
child: child,
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: SecondaryButton(
|
||||
label: "Cancel",
|
||||
buttonHeight: ButtonHeight.l,
|
||||
onPressed: () {
|
||||
if (mounted) {
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 16,
|
||||
),
|
||||
Expanded(
|
||||
child: child,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
child: PrimaryButton(
|
||||
label: "Save",
|
||||
buttonHeight: isDesktop ? ButtonHeight.l : null,
|
||||
onPressed: () {
|
||||
if (mounted) {
|
||||
Navigator.of(context).pop(_textController.text);
|
||||
|
|
|
@ -1,13 +1,17 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.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/pages/receive_view/addresses/address_tag.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/clipboard_interface.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/util.dart';
|
||||
import 'package:stackwallet/widgets/conditional_parent.dart';
|
||||
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||
|
||||
class AddressCard extends StatefulWidget {
|
||||
|
@ -31,6 +35,8 @@ class AddressCard extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _AddressCardState extends State<AddressCard> {
|
||||
final isDesktop = Util.isDesktop;
|
||||
|
||||
late Stream<AddressLabel?> stream;
|
||||
late final Address address;
|
||||
|
||||
|
@ -74,115 +80,64 @@ class _AddressCardState extends State<AddressCard> {
|
|||
label = snapshot.data!;
|
||||
}
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (label!.value.isNotEmpty)
|
||||
Text(
|
||||
label!.value,
|
||||
style: STextStyles.itemSubtitle(context),
|
||||
textAlign: TextAlign.left,
|
||||
return ConditionalParent(
|
||||
condition: isDesktop,
|
||||
builder: (child) => Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
Assets.svg.iconFor(coin: widget.coin),
|
||||
width: 32,
|
||||
height: 32,
|
||||
),
|
||||
// Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
// children: [
|
||||
//
|
||||
// CustomTextButton(
|
||||
// text: "Edit label",
|
||||
// textSize: 14,
|
||||
// onTap: () {
|
||||
// Navigator.of(context).pushNamed(
|
||||
// EditAddressLabelView.routeName,
|
||||
// arguments: label!.id,
|
||||
// );
|
||||
// },
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
if (label!.value.isNotEmpty)
|
||||
const SizedBox(
|
||||
height: 8,
|
||||
width: 12,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
address.value,
|
||||
style: STextStyles.itemSubtitle12(context),
|
||||
),
|
||||
Expanded(
|
||||
child: child,
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (label!.value.isNotEmpty)
|
||||
Text(
|
||||
label!.value,
|
||||
style: STextStyles.itemSubtitle(context),
|
||||
textAlign: TextAlign.left,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
|
||||
if (label!.tags != null && label!.tags!.isNotEmpty)
|
||||
Wrap(
|
||||
spacing: 10,
|
||||
runSpacing: 10,
|
||||
children: label!.tags!
|
||||
.map(
|
||||
(e) => AddressTag(
|
||||
tag: e,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
if (label!.value.isNotEmpty)
|
||||
SizedBox(
|
||||
height: isDesktop ? 2 : 8,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
address.value,
|
||||
style: STextStyles.itemSubtitle12(context),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
// Row(
|
||||
// children: [
|
||||
// Expanded(
|
||||
// child: SecondaryButton(
|
||||
// label: "Copy address",
|
||||
// icon: CopyIcon(
|
||||
// color: Theme.of(context)
|
||||
// .extension<StackColors>()!
|
||||
// .buttonTextSecondary,
|
||||
// ),
|
||||
// onPressed: () async {
|
||||
// await widget.clipboard.setData(
|
||||
// ClipboardData(
|
||||
// text: address.value,
|
||||
// ),
|
||||
// );
|
||||
// if (mounted) {
|
||||
// unawaited(
|
||||
// showFloatingFlushBar(
|
||||
// type: FlushBarType.info,
|
||||
// message: "Copied to clipboard",
|
||||
// context: context,
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
// },
|
||||
// ),
|
||||
// ),
|
||||
// const SizedBox(
|
||||
// width: 12,
|
||||
// ),
|
||||
// Expanded(
|
||||
// child: SecondaryButton(
|
||||
// label: "Show QR Code",
|
||||
// icon: QrCodeIcon(
|
||||
// color: Theme.of(context)
|
||||
// .extension<StackColors>()!
|
||||
// .buttonTextSecondary,
|
||||
// ),
|
||||
// onPressed: () {
|
||||
// showDialog<void>(
|
||||
// context: context,
|
||||
// builder: (context) => AddressQrPopup(
|
||||
// addressString: address.value,
|
||||
// coin: widget.coin,
|
||||
// clipboard: widget.clipboard,
|
||||
// ),
|
||||
// );
|
||||
// },
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// )
|
||||
],
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
if (label!.tags != null && label!.tags!.isNotEmpty)
|
||||
Wrap(
|
||||
spacing: 10,
|
||||
runSpacing: 10,
|
||||
children: label!.tags!
|
||||
.map(
|
||||
(e) => AddressTag(
|
||||
tag: e,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
|
|
@ -6,6 +6,7 @@ import 'package:stackwallet/db/main_db.dart';
|
|||
import 'package:stackwallet/models/isar/models/isar_models.dart';
|
||||
import 'package:stackwallet/pages/receive_view/addresses/address_tag.dart';
|
||||
import 'package:stackwallet/pages/wallet_view/sub_widgets/no_transactions_found.dart';
|
||||
import 'package:stackwallet/pages/wallet_view/transaction_views/transaction_details_view.dart';
|
||||
import 'package:stackwallet/providers/global/wallets_provider.dart';
|
||||
import 'package:stackwallet/utilities/address_utils.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
|
@ -14,8 +15,11 @@ import 'package:stackwallet/utilities/util.dart';
|
|||
import 'package:stackwallet/widgets/background.dart';
|
||||
import 'package:stackwallet/widgets/conditional_parent.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/simple_copy_button.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/simple_edit_button.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';
|
||||
import 'package:stackwallet/widgets/transaction_card.dart';
|
||||
|
||||
|
@ -44,6 +48,64 @@ class _AddressDetailsViewState extends ConsumerState<AddressDetailsView> {
|
|||
|
||||
AddressLabel? label;
|
||||
|
||||
void _showDesktopAddressQrCode() {
|
||||
showDialog<void>(
|
||||
context: context,
|
||||
builder: (context) => DesktopDialog(
|
||||
maxWidth: 480,
|
||||
maxHeight: 400,
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 32),
|
||||
child: Text(
|
||||
"Address QR code",
|
||||
style: STextStyles.desktopH3(context),
|
||||
),
|
||||
),
|
||||
const DesktopDialogCloseButton(),
|
||||
],
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Center(
|
||||
child: RepaintBoundary(
|
||||
key: _qrKey,
|
||||
child: QrImage(
|
||||
data: AddressUtils.buildUriString(
|
||||
ref.watch(walletsChangeNotifierProvider.select(
|
||||
(value) =>
|
||||
value.getManager(widget.walletId).coin)),
|
||||
address.value,
|
||||
{},
|
||||
),
|
||||
size: 220,
|
||||
backgroundColor:
|
||||
Theme.of(context).extension<StackColors>()!.popupBG,
|
||||
foregroundColor: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.accentColorDark,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 32,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
address = MainDB.instance.isar.addresses
|
||||
|
@ -73,13 +135,6 @@ class _AddressDetailsViewState extends ConsumerState<AddressDetailsView> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final coin = ref.watch(walletsChangeNotifierProvider
|
||||
.select((value) => value.getManager(widget.walletId).coin));
|
||||
final query = MainDB.instance
|
||||
.getTransactions(widget.walletId)
|
||||
.filter()
|
||||
.address((q) => q.valueEqualTo(address.value));
|
||||
|
||||
return ConditionalParent(
|
||||
condition: !isDesktop,
|
||||
builder: (child) => Background(
|
||||
|
@ -96,7 +151,7 @@ class _AddressDetailsViewState extends ConsumerState<AddressDetailsView> {
|
|||
),
|
||||
titleSpacing: 0,
|
||||
title: Text(
|
||||
"Wallet addresses",
|
||||
"Address details",
|
||||
style: STextStyles.navBarTitle(context),
|
||||
),
|
||||
),
|
||||
|
@ -126,114 +181,198 @@ class _AddressDetailsViewState extends ConsumerState<AddressDetailsView> {
|
|||
label = snapshot.data!;
|
||||
}
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Center(
|
||||
child: RepaintBoundary(
|
||||
key: _qrKey,
|
||||
child: QrImage(
|
||||
data: AddressUtils.buildUriString(
|
||||
coin,
|
||||
address.value,
|
||||
{},
|
||||
),
|
||||
size: 220,
|
||||
backgroundColor:
|
||||
Theme.of(context).extension<StackColors>()!.background,
|
||||
foregroundColor: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.accentColorDark,
|
||||
return ConditionalParent(
|
||||
condition: isDesktop,
|
||||
builder: (child) {
|
||||
return Column(
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 16,
|
||||
),
|
||||
_Item(
|
||||
title: "Address",
|
||||
data: address.value,
|
||||
button: SimpleCopyButton(
|
||||
data: address.value,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
_Item(
|
||||
title: "Label",
|
||||
data: label!.value,
|
||||
button: SimpleEditButton(
|
||||
editValue: label!.value,
|
||||
editLabel: 'label',
|
||||
onValueChanged: (value) {
|
||||
MainDB.instance.putAddressLabel(
|
||||
label!.copyWith(
|
||||
label: value,
|
||||
RoundedWhiteContainer(
|
||||
padding: const EdgeInsets.all(24),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"Address details",
|
||||
style: STextStyles.desktopTextExtraExtraSmall(
|
||||
context)
|
||||
.copyWith(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.textSubtitle1,
|
||||
),
|
||||
),
|
||||
CustomTextButton(
|
||||
text: "View QR code",
|
||||
onTap: _showDesktopAddressQrCode,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 4,
|
||||
),
|
||||
RoundedWhiteContainer(
|
||||
padding: EdgeInsets.zero,
|
||||
borderColor: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.backgroundAppBar,
|
||||
child: child,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 16,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"Transaction history",
|
||||
style: STextStyles.desktopTextExtraExtraSmall(
|
||||
context)
|
||||
.copyWith(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.textSubtitle1,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 8,
|
||||
),
|
||||
RoundedWhiteContainer(
|
||||
padding: EdgeInsets.zero,
|
||||
borderColor: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.backgroundAppBar,
|
||||
child: _AddressDetailsTxList(
|
||||
walletId: widget.walletId,
|
||||
address: address,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
if (!isDesktop)
|
||||
Center(
|
||||
child: RepaintBoundary(
|
||||
key: _qrKey,
|
||||
child: QrImage(
|
||||
data: AddressUtils.buildUriString(
|
||||
ref.watch(walletsChangeNotifierProvider.select(
|
||||
(value) =>
|
||||
value.getManager(widget.walletId).coin)),
|
||||
address.value,
|
||||
{},
|
||||
),
|
||||
size: 220,
|
||||
backgroundColor: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.background,
|
||||
foregroundColor: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.accentColorDark,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
if (!isDesktop)
|
||||
const SizedBox(
|
||||
height: 16,
|
||||
),
|
||||
_Item(
|
||||
title: "Address",
|
||||
data: address.value,
|
||||
button: isDesktop
|
||||
? IconCopyButton(
|
||||
data: address.value,
|
||||
)
|
||||
: SimpleCopyButton(
|
||||
data: address.value,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
_Tags(
|
||||
tags: label!.tags,
|
||||
),
|
||||
if (address.derivationPath != null)
|
||||
const SizedBox(
|
||||
const _Div(
|
||||
height: 12,
|
||||
),
|
||||
if (address.derivationPath != null)
|
||||
_Item(
|
||||
title: "Derivation path",
|
||||
data: address.derivationPath!.value,
|
||||
button: Container(),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
_Item(
|
||||
title: "Type",
|
||||
data: address.type.readableName,
|
||||
button: Container(),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
_Item(
|
||||
title: "Sub type",
|
||||
data: address.subType.prettyName,
|
||||
button: Container(),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
Text(
|
||||
"Transactions",
|
||||
textAlign: TextAlign.left,
|
||||
style: STextStyles.itemSubtitle(context).copyWith(
|
||||
color: Theme.of(context).extension<StackColors>()!.textDark3,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
if (query.countSync() == 0) const NoTransActionsFound(),
|
||||
if (query.countSync() > 0)
|
||||
RoundedWhiteContainer(
|
||||
padding: EdgeInsets.zero,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: query
|
||||
.findAllSync()
|
||||
.map((e) => TransactionCard(
|
||||
transaction: e, walletId: widget.walletId))
|
||||
.toList(),
|
||||
title: "Label",
|
||||
data: label!.value,
|
||||
button: SimpleEditButton(
|
||||
editValue: label!.value,
|
||||
editLabel: 'label',
|
||||
onValueChanged: (value) {
|
||||
MainDB.instance.putAddressLabel(
|
||||
label!.copyWith(
|
||||
label: value,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
const _Div(
|
||||
height: 12,
|
||||
),
|
||||
_Tags(
|
||||
tags: label!.tags,
|
||||
),
|
||||
if (address.derivationPath != null)
|
||||
const _Div(
|
||||
height: 12,
|
||||
),
|
||||
if (address.derivationPath != null)
|
||||
_Item(
|
||||
title: "Derivation path",
|
||||
data: address.derivationPath!.value,
|
||||
button: Container(),
|
||||
),
|
||||
const _Div(
|
||||
height: 12,
|
||||
),
|
||||
_Item(
|
||||
title: "Type",
|
||||
data: address.type.readableName,
|
||||
button: Container(),
|
||||
),
|
||||
const _Div(
|
||||
height: 12,
|
||||
),
|
||||
_Item(
|
||||
title: "Sub type",
|
||||
data: address.subType.prettyName,
|
||||
button: Container(),
|
||||
),
|
||||
if (!isDesktop)
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
if (!isDesktop)
|
||||
Text(
|
||||
"Transactions",
|
||||
textAlign: TextAlign.left,
|
||||
style: STextStyles.itemSubtitle(context).copyWith(
|
||||
color:
|
||||
Theme.of(context).extension<StackColors>()!.textDark3,
|
||||
),
|
||||
),
|
||||
if (!isDesktop)
|
||||
const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
if (!isDesktop)
|
||||
_AddressDetailsTxList(
|
||||
walletId: widget.walletId,
|
||||
address: address,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
@ -241,6 +380,85 @@ class _AddressDetailsViewState extends ConsumerState<AddressDetailsView> {
|
|||
}
|
||||
}
|
||||
|
||||
class _AddressDetailsTxList extends StatelessWidget {
|
||||
const _AddressDetailsTxList({
|
||||
Key? key,
|
||||
required this.walletId,
|
||||
required this.address,
|
||||
}) : super(key: key);
|
||||
|
||||
final String walletId;
|
||||
final Address address;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final query = MainDB.instance
|
||||
.getTransactions(walletId)
|
||||
.filter()
|
||||
.address((q) => q.valueEqualTo(address.value));
|
||||
|
||||
final count = query.countSync();
|
||||
|
||||
if (count > 0) {
|
||||
if (Util.isDesktop) {
|
||||
final txns = query.findAllSync();
|
||||
return ListView.separated(
|
||||
shrinkWrap: true,
|
||||
primary: false,
|
||||
itemBuilder: (_, index) => TransactionCard(
|
||||
transaction: txns[index],
|
||||
walletId: walletId,
|
||||
),
|
||||
separatorBuilder: (_, __) => const _Div(height: 1),
|
||||
itemCount: count,
|
||||
);
|
||||
} else {
|
||||
return RoundedWhiteContainer(
|
||||
padding: EdgeInsets.zero,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: query
|
||||
.findAllSync()
|
||||
.map(
|
||||
(e) => TransactionCard(
|
||||
transaction: e,
|
||||
walletId: walletId,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
return const NoTransActionsFound();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class _Div extends StatelessWidget {
|
||||
const _Div({
|
||||
Key? key,
|
||||
required this.height,
|
||||
}) : super(key: key);
|
||||
|
||||
final double height;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (Util.isDesktop) {
|
||||
return Container(
|
||||
color: Theme.of(context).extension<StackColors>()!.backgroundAppBar,
|
||||
height: 1,
|
||||
width: double.infinity,
|
||||
);
|
||||
} else {
|
||||
return SizedBox(
|
||||
height: height,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class _Tags extends StatelessWidget {
|
||||
const _Tags({
|
||||
Key? key,
|
||||
|
@ -313,37 +531,48 @@ class _Item extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return RoundedWhiteContainer(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
title,
|
||||
style: STextStyles.itemSubtitle(context),
|
||||
),
|
||||
button,
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
data.isNotEmpty
|
||||
? SelectableText(
|
||||
data,
|
||||
style: STextStyles.w500_14(context),
|
||||
)
|
||||
: Text(
|
||||
"$title will appear here",
|
||||
style: STextStyles.w500_14(context).copyWith(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.textSubtitle3,
|
||||
),
|
||||
return ConditionalParent(
|
||||
condition: !Util.isDesktop,
|
||||
builder: (child) => RoundedWhiteContainer(
|
||||
child: child,
|
||||
),
|
||||
child: ConditionalParent(
|
||||
condition: Util.isDesktop,
|
||||
builder: (child) => Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: child,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
title,
|
||||
style: STextStyles.itemSubtitle(context),
|
||||
),
|
||||
],
|
||||
button,
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
data.isNotEmpty
|
||||
? SelectableText(
|
||||
data,
|
||||
style: STextStyles.w500_14(context),
|
||||
)
|
||||
: Text(
|
||||
"$title will appear here",
|
||||
style: STextStyles.w500_14(context).copyWith(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.textSubtitle3,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/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/pages/receive_view/addresses/address_details_view.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/addresses/sub_widgets/desktop_address_list.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||
import 'package:stackwallet/widgets/desktop/desktop_app_bar.dart';
|
||||
import 'package:stackwallet/widgets/desktop/desktop_scaffold.dart';
|
||||
|
||||
final desktopSelectedAddressId = StateProvider.autoDispose<Id?>((ref) => null);
|
||||
|
||||
class DesktopWalletAddressesView extends ConsumerStatefulWidget {
|
||||
const DesktopWalletAddressesView({
|
||||
Key? key,
|
||||
required this.walletId,
|
||||
}) : super(key: key);
|
||||
|
||||
static const String routeName = "/desktopWalletAddressesView";
|
||||
|
||||
final String walletId;
|
||||
|
||||
@override
|
||||
ConsumerState<DesktopWalletAddressesView> createState() =>
|
||||
_DesktopWalletAddressesViewState();
|
||||
}
|
||||
|
||||
class _DesktopWalletAddressesViewState
|
||||
extends ConsumerState<DesktopWalletAddressesView> {
|
||||
static const _headerHeight = 70.0;
|
||||
static const _columnWidth0 = 489.0;
|
||||
|
||||
late final Stream<void> addressCollectionWatcher;
|
||||
|
||||
void _onAddressCollectionWatcherEvent() {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
setState(() {});
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
addressCollectionWatcher =
|
||||
MainDB.instance.isar.addresses.watchLazy(fireImmediately: true);
|
||||
addressCollectionWatcher.listen((_) => _onAddressCollectionWatcherEvent());
|
||||
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DesktopScaffold(
|
||||
appBar: DesktopAppBar(
|
||||
background: Theme.of(context).extension<StackColors>()!.popupBG,
|
||||
leading: Expanded(
|
||||
child: Row(
|
||||
children: [
|
||||
const SizedBox(
|
||||
width: 32,
|
||||
),
|
||||
AppBarIconButton(
|
||||
size: 32,
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.textFieldDefaultBG,
|
||||
shadows: const [],
|
||||
icon: SvgPicture.asset(
|
||||
Assets.svg.arrowLeft,
|
||||
width: 18,
|
||||
height: 18,
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.topNavIconPrimary,
|
||||
),
|
||||
onPressed: Navigator.of(context).pop,
|
||||
),
|
||||
const SizedBox(
|
||||
width: 12,
|
||||
),
|
||||
Text(
|
||||
"Address list",
|
||||
style: STextStyles.desktopH3(context),
|
||||
),
|
||||
const Spacer(),
|
||||
],
|
||||
),
|
||||
),
|
||||
useSpacers: false,
|
||||
isCompactHeight: true,
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(24),
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: _columnWidth0,
|
||||
child: DesktopAddressList(
|
||||
searchHeight: _headerHeight,
|
||||
walletId: widget.walletId,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 16,
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: _headerHeight,
|
||||
),
|
||||
if (ref.watch(desktopSelectedAddressId.state).state !=
|
||||
null)
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
child: AddressDetailsView(
|
||||
key: Key(
|
||||
"currentDesktopAddressDetails_key_${ref.watch(desktopSelectedAddressId.state).state}"),
|
||||
walletId: widget.walletId,
|
||||
addressId: ref
|
||||
.watch(desktopSelectedAddressId.state)
|
||||
.state!,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,232 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/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/pages/receive_view/addresses/address_card.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/addresses/desktop_wallet_addresses_view.dart';
|
||||
import 'package:stackwallet/providers/global/wallets_provider.dart';
|
||||
import 'package:stackwallet/utilities/assets.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/utilities/util.dart';
|
||||
import 'package:stackwallet/widgets/icon_widgets/x_icon.dart';
|
||||
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||
import 'package:stackwallet/widgets/stack_text_field.dart';
|
||||
import 'package:stackwallet/widgets/textfield_icon_button.dart';
|
||||
|
||||
class DesktopAddressList extends ConsumerStatefulWidget {
|
||||
const DesktopAddressList({
|
||||
Key? key,
|
||||
required this.walletId,
|
||||
this.searchHeight,
|
||||
}) : super(key: key);
|
||||
|
||||
final String walletId;
|
||||
final double? searchHeight;
|
||||
|
||||
@override
|
||||
ConsumerState<DesktopAddressList> createState() => _DesktopAddressListState();
|
||||
}
|
||||
|
||||
class _DesktopAddressListState extends ConsumerState<DesktopAddressList> {
|
||||
final bool isDesktop = Util.isDesktop;
|
||||
|
||||
String _searchString = "";
|
||||
|
||||
late final TextEditingController _searchController;
|
||||
final searchFieldFocusNode = FocusNode();
|
||||
|
||||
List<Id> _search(String term) {
|
||||
if (term.isEmpty) {
|
||||
return MainDB.instance
|
||||
.getAddresses(widget.walletId)
|
||||
.filter()
|
||||
.group((q) => q
|
||||
.subTypeEqualTo(AddressSubType.change)
|
||||
.or()
|
||||
.subTypeEqualTo(AddressSubType.receiving)
|
||||
.or()
|
||||
.subTypeEqualTo(AddressSubType.paynymReceive)
|
||||
.or()
|
||||
.subTypeEqualTo(AddressSubType.paynymNotification))
|
||||
.and()
|
||||
.not()
|
||||
.typeEqualTo(AddressType.nonWallet)
|
||||
.sortByDerivationIndex()
|
||||
.idProperty()
|
||||
.findAllSync();
|
||||
}
|
||||
|
||||
final labels = MainDB.instance
|
||||
.getAddressLabels(widget.walletId)
|
||||
.filter()
|
||||
.group(
|
||||
(q) => q
|
||||
.valueContains(term, caseSensitive: false)
|
||||
.or()
|
||||
.addressStringContains(term, caseSensitive: false)
|
||||
.or()
|
||||
.group(
|
||||
(q) => q
|
||||
.tagsIsNotNull()
|
||||
.and()
|
||||
.tagsElementContains(term, caseSensitive: false),
|
||||
),
|
||||
)
|
||||
.findAllSync();
|
||||
|
||||
if (labels.isEmpty) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return MainDB.instance
|
||||
.getAddresses(widget.walletId)
|
||||
.filter()
|
||||
.anyOf<AddressLabel, Address>(
|
||||
labels, (q, e) => q.valueEqualTo(e.addressString))
|
||||
.group((q) => q
|
||||
.subTypeEqualTo(AddressSubType.change)
|
||||
.or()
|
||||
.subTypeEqualTo(AddressSubType.receiving)
|
||||
.or()
|
||||
.subTypeEqualTo(AddressSubType.paynymReceive)
|
||||
.or()
|
||||
.subTypeEqualTo(AddressSubType.paynymNotification))
|
||||
.and()
|
||||
.not()
|
||||
.typeEqualTo(AddressType.nonWallet)
|
||||
.sortByDerivationIndex()
|
||||
.idProperty()
|
||||
.findAllSync();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_searchController = TextEditingController();
|
||||
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_searchController.dispose();
|
||||
searchFieldFocusNode.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final coin = ref.watch(walletsChangeNotifierProvider
|
||||
.select((value) => value.getManager(widget.walletId).coin));
|
||||
|
||||
final ids = _search(_searchString);
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
SizedBox(
|
||||
height: widget.searchHeight!,
|
||||
child: Center(
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(
|
||||
Constants.size.circularBorderRadius,
|
||||
),
|
||||
child: TextField(
|
||||
autocorrect: !isDesktop,
|
||||
enableSuggestions: !isDesktop,
|
||||
controller: _searchController,
|
||||
focusNode: searchFieldFocusNode,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_searchString = value;
|
||||
});
|
||||
},
|
||||
style: isDesktop
|
||||
? STextStyles.desktopTextExtraSmall(context).copyWith(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.textFieldActiveText,
|
||||
height: 1.8,
|
||||
)
|
||||
: STextStyles.field(context),
|
||||
decoration: standardInputDecoration(
|
||||
"Search...",
|
||||
searchFieldFocusNode,
|
||||
context,
|
||||
desktopMed: isDesktop,
|
||||
).copyWith(
|
||||
prefixIcon: Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: isDesktop ? 12 : 10,
|
||||
vertical: isDesktop ? 18 : 16,
|
||||
),
|
||||
child: SvgPicture.asset(
|
||||
Assets.svg.search,
|
||||
width: isDesktop ? 20 : 16,
|
||||
height: isDesktop ? 20 : 16,
|
||||
),
|
||||
),
|
||||
suffixIcon: _searchController.text.isNotEmpty
|
||||
? Padding(
|
||||
padding: const EdgeInsets.only(right: 0),
|
||||
child: UnconstrainedBox(
|
||||
child: Row(
|
||||
children: [
|
||||
TextFieldIconButton(
|
||||
child: const XIcon(),
|
||||
onTap: () async {
|
||||
setState(() {
|
||||
_searchController.text = "";
|
||||
_searchString = "";
|
||||
});
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
: null,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
child: RoundedWhiteContainer(
|
||||
padding: EdgeInsets.zero,
|
||||
child: ListView.separated(
|
||||
shrinkWrap: true,
|
||||
itemCount: ids.length,
|
||||
separatorBuilder: (_, __) => Container(
|
||||
height: 1,
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.backgroundAppBar,
|
||||
),
|
||||
itemBuilder: (_, index) => Padding(
|
||||
padding: const EdgeInsets.all(4),
|
||||
child: AddressCard(
|
||||
key: Key("addressCardDesktop_key_${ids[index]}"),
|
||||
walletId: widget.walletId,
|
||||
addressId: ids[index],
|
||||
coin: coin,
|
||||
onPressed: () {
|
||||
ref.read(desktopSelectedAddressId.state).state =
|
||||
ids[index];
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
|
@ -4,13 +4,13 @@ import 'package:event_bus/event_bus.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/delete_wallet_button.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_features.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_wallet_summary.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/my_wallet.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/network_info_button.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/recent_desktop_transactions.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/wallet_keys_button.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/wallet_options_button.dart';
|
||||
import 'package:stackwallet/providers/global/auto_swb_service_provider.dart';
|
||||
import 'package:stackwallet/providers/providers.dart';
|
||||
import 'package:stackwallet/providers/ui/transaction_filter_provider.dart';
|
||||
|
@ -208,7 +208,7 @@ class _DesktopWalletViewState extends ConsumerState<DesktopWalletView> {
|
|||
const SizedBox(
|
||||
width: 2,
|
||||
),
|
||||
DeleteWalletButton(
|
||||
WalletOptionsButton(
|
||||
walletId: widget.walletId,
|
||||
),
|
||||
const SizedBox(
|
||||
|
|
|
@ -1,164 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_delete_wallet_dialog.dart';
|
||||
import 'package:stackwallet/route_generator.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
||||
|
||||
class DeleteWalletButton extends ConsumerStatefulWidget {
|
||||
const DeleteWalletButton({
|
||||
Key? key,
|
||||
required this.walletId,
|
||||
}) : super(key: key);
|
||||
|
||||
final String walletId;
|
||||
|
||||
@override
|
||||
ConsumerState<DeleteWalletButton> createState() => _DeleteWalletButton();
|
||||
}
|
||||
|
||||
class _DeleteWalletButton extends ConsumerState<DeleteWalletButton> {
|
||||
late final String walletId;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
walletId = widget.walletId;
|
||||
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return RawMaterialButton(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(1000),
|
||||
),
|
||||
onPressed: () async {
|
||||
final shouldOpenDeleteDialog = await showDialog<bool?>(
|
||||
context: context,
|
||||
barrierColor: Colors.transparent,
|
||||
builder: (context) {
|
||||
return DeletePopupButton(
|
||||
onTap: () async {
|
||||
Navigator.of(context).pop(true);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
if (shouldOpenDeleteDialog == true) {
|
||||
final result = await showDialog<bool?>(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => Navigator(
|
||||
initialRoute: DesktopDeleteWalletDialog.routeName,
|
||||
onGenerateRoute: RouteGenerator.generateRoute,
|
||||
onGenerateInitialRoutes: (_, __) {
|
||||
return [
|
||||
RouteGenerator.generateRoute(
|
||||
RouteSettings(
|
||||
name: DesktopDeleteWalletDialog.routeName,
|
||||
arguments: walletId,
|
||||
),
|
||||
),
|
||||
];
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
if (result == true) {
|
||||
if (mounted) {
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 19,
|
||||
horizontal: 32,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
Assets.svg.ellipsis,
|
||||
width: 20,
|
||||
height: 20,
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.buttonTextSecondary,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class DeletePopupButton extends StatefulWidget {
|
||||
const DeletePopupButton({
|
||||
Key? key,
|
||||
this.onTap,
|
||||
}) : super(key: key);
|
||||
|
||||
final VoidCallback? onTap;
|
||||
|
||||
@override
|
||||
State<DeletePopupButton> createState() => _DeletePopupButtonState();
|
||||
}
|
||||
|
||||
class _DeletePopupButtonState extends State<DeletePopupButton> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(
|
||||
children: [
|
||||
Positioned(
|
||||
top: 24,
|
||||
left: MediaQuery.of(context).size.width - 234,
|
||||
child: MouseRegion(
|
||||
cursor: SystemMouseCursors.click,
|
||||
child: GestureDetector(
|
||||
onTap: widget.onTap,
|
||||
child: Container(
|
||||
width: 210,
|
||||
height: 70,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(
|
||||
Constants.size.circularBorderRadius * 2,
|
||||
),
|
||||
color: Theme.of(context).extension<StackColors>()!.popupBG,
|
||||
boxShadow: [
|
||||
Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.standardBoxShadow,
|
||||
],
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(width: 24),
|
||||
SvgPicture.asset(
|
||||
Assets.svg.trash,
|
||||
),
|
||||
const SizedBox(width: 14),
|
||||
Text(
|
||||
"Delete wallet",
|
||||
style: STextStyles.desktopTextExtraExtraSmall(context)
|
||||
.copyWith(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.textDark),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,275 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/addresses/desktop_wallet_addresses_view.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_delete_wallet_dialog.dart';
|
||||
import 'package:stackwallet/route_generator.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
||||
|
||||
enum _WalletOptions {
|
||||
addressList,
|
||||
deleteWallet;
|
||||
|
||||
String get prettyName {
|
||||
switch (this) {
|
||||
case _WalletOptions.addressList:
|
||||
return "Address list";
|
||||
case _WalletOptions.deleteWallet:
|
||||
return "Delete wallet";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class WalletOptionsButton extends ConsumerStatefulWidget {
|
||||
const WalletOptionsButton({
|
||||
Key? key,
|
||||
required this.walletId,
|
||||
}) : super(key: key);
|
||||
|
||||
final String walletId;
|
||||
|
||||
@override
|
||||
ConsumerState<WalletOptionsButton> createState() =>
|
||||
_WalletOptionsButtonState();
|
||||
}
|
||||
|
||||
class _WalletOptionsButtonState extends ConsumerState<WalletOptionsButton> {
|
||||
late final String walletId;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
walletId = widget.walletId;
|
||||
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return RawMaterialButton(
|
||||
constraints: const BoxConstraints(
|
||||
minHeight: 32,
|
||||
minWidth: 32,
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(1000),
|
||||
),
|
||||
onPressed: () async {
|
||||
final func = await showDialog<_WalletOptions?>(
|
||||
context: context,
|
||||
barrierColor: Colors.transparent,
|
||||
builder: (context) {
|
||||
return WalletOptionsPopupMenu(
|
||||
onDeletePressed: () async {
|
||||
Navigator.of(context).pop(_WalletOptions.deleteWallet);
|
||||
},
|
||||
onAddressListPressed: () async {
|
||||
Navigator.of(context).pop(_WalletOptions.addressList);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
if (mounted && func != null) {
|
||||
switch (func) {
|
||||
case _WalletOptions.addressList:
|
||||
unawaited(
|
||||
Navigator.of(context).pushNamed(
|
||||
DesktopWalletAddressesView.routeName,
|
||||
arguments: walletId,
|
||||
),
|
||||
);
|
||||
break;
|
||||
case _WalletOptions.deleteWallet:
|
||||
final result = await showDialog<bool?>(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => Navigator(
|
||||
initialRoute: DesktopDeleteWalletDialog.routeName,
|
||||
onGenerateRoute: RouteGenerator.generateRoute,
|
||||
onGenerateInitialRoutes: (_, __) {
|
||||
return [
|
||||
RouteGenerator.generateRoute(
|
||||
RouteSettings(
|
||||
name: DesktopDeleteWalletDialog.routeName,
|
||||
arguments: walletId,
|
||||
),
|
||||
),
|
||||
];
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
if (result == true) {
|
||||
if (mounted) {
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 19,
|
||||
horizontal: 32,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
Assets.svg.ellipsis,
|
||||
width: 20,
|
||||
height: 20,
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.buttonTextSecondary,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class WalletOptionsPopupMenu extends StatelessWidget {
|
||||
const WalletOptionsPopupMenu({
|
||||
Key? key,
|
||||
required this.onDeletePressed,
|
||||
required this.onAddressListPressed,
|
||||
}) : super(key: key);
|
||||
|
||||
final VoidCallback onDeletePressed;
|
||||
final VoidCallback onAddressListPressed;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(
|
||||
children: [
|
||||
Positioned(
|
||||
top: 24,
|
||||
left: MediaQuery.of(context).size.width - 234,
|
||||
child: Container(
|
||||
width: 220,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(
|
||||
Constants.size.circularBorderRadius * 2,
|
||||
),
|
||||
color: Theme.of(context).extension<StackColors>()!.popupBG,
|
||||
boxShadow: [
|
||||
Theme.of(context).extension<StackColors>()!.standardBoxShadow,
|
||||
],
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
TransparentButton(
|
||||
onPressed: onAddressListPressed,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
Assets.svg.list,
|
||||
width: 20,
|
||||
height: 20,
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.textFieldActiveSearchIconLeft,
|
||||
),
|
||||
const SizedBox(width: 14),
|
||||
Expanded(
|
||||
child: Text(
|
||||
_WalletOptions.addressList.prettyName,
|
||||
style: STextStyles.desktopTextExtraExtraSmall(
|
||||
context)
|
||||
.copyWith(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.textDark,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 8,
|
||||
),
|
||||
TransparentButton(
|
||||
onPressed: onDeletePressed,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
Assets.svg.trash,
|
||||
width: 20,
|
||||
height: 20,
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.textFieldActiveSearchIconLeft,
|
||||
),
|
||||
const SizedBox(width: 14),
|
||||
Expanded(
|
||||
child: Text(
|
||||
_WalletOptions.deleteWallet.prettyName,
|
||||
style: STextStyles.desktopTextExtraExtraSmall(
|
||||
context)
|
||||
.copyWith(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.textDark,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class TransparentButton extends StatelessWidget {
|
||||
const TransparentButton({
|
||||
Key? key,
|
||||
required this.child,
|
||||
this.onPressed,
|
||||
}) : super(key: key);
|
||||
|
||||
final Widget child;
|
||||
final VoidCallback? onPressed;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return RawMaterialButton(
|
||||
constraints: const BoxConstraints(
|
||||
minHeight: 32,
|
||||
minWidth: 32,
|
||||
),
|
||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(
|
||||
Constants.size.circularBorderRadius,
|
||||
),
|
||||
),
|
||||
onPressed: onPressed,
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
}
|
|
@ -272,6 +272,7 @@ class _ThemeToggle extends ConsumerState<ThemeToggle> {
|
|||
child: SvgPicture.asset(
|
||||
assetNameFor(ThemeType.values[i]),
|
||||
height: 160,
|
||||
width: 200,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
|
|
|
@ -99,6 +99,7 @@ import 'package:stackwallet/pages/wallet_view/transaction_views/transaction_sear
|
|||
import 'package:stackwallet/pages/wallet_view/wallet_view.dart';
|
||||
import 'package:stackwallet/pages/wallets_view/wallets_view.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/address_book_view/desktop_address_book.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/addresses/desktop_wallet_addresses_view.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/coin_control/desktop_coin_control_view.dart';
|
||||
// import 'package:stackwallet/pages_desktop_specific/desktop_exchange/desktop_all_buys_view.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/desktop_buy/desktop_buy_view.dart';
|
||||
|
@ -1320,6 +1321,20 @@ class RouteGenerator {
|
|||
}
|
||||
return _routeError("${settings.name} invalid args: ${args.toString()}");
|
||||
|
||||
case DesktopWalletAddressesView.routeName:
|
||||
if (args is String) {
|
||||
return getRoute(
|
||||
shouldUseMaterialRoute: useMaterialPageRoute,
|
||||
builder: (_) => DesktopWalletAddressesView(
|
||||
walletId: args,
|
||||
),
|
||||
settings: RouteSettings(
|
||||
name: settings.name,
|
||||
),
|
||||
);
|
||||
}
|
||||
return _routeError("${settings.name} invalid args: ${args.toString()}");
|
||||
|
||||
case DesktopCoinControlView.routeName:
|
||||
if (args is String) {
|
||||
return getRoute(
|
||||
|
|
|
@ -52,7 +52,7 @@ class SimpleEditButton extends StatelessWidget {
|
|||
builder: (context) {
|
||||
return DesktopDialog(
|
||||
maxWidth: 580,
|
||||
maxHeight: 360,
|
||||
maxHeight: 300,
|
||||
child: SingleFieldEditView(
|
||||
initialValue: editValue!,
|
||||
label: editLabel!,
|
||||
|
|
|
@ -31,6 +31,12 @@ class RoundedContainer extends StatelessWidget {
|
|||
return ConditionalParent(
|
||||
condition: onPressed != null,
|
||||
builder: (child) => RawMaterialButton(
|
||||
fillColor: color,
|
||||
elevation: 0,
|
||||
highlightElevation: 0,
|
||||
disabledElevation: 0,
|
||||
hoverElevation: 0,
|
||||
focusElevation: 0,
|
||||
padding: const EdgeInsets.all(0),
|
||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
shape: RoundedRectangleBorder(
|
||||
|
@ -45,7 +51,7 @@ class RoundedContainer extends StatelessWidget {
|
|||
width: width,
|
||||
height: height,
|
||||
decoration: BoxDecoration(
|
||||
color: color,
|
||||
color: onPressed != null ? Colors.transparent : color,
|
||||
borderRadius: BorderRadius.circular(
|
||||
Constants.size.circularBorderRadius * radiusMultiplier,
|
||||
),
|
||||
|
|
|
@ -337,6 +337,7 @@ flutter:
|
|||
- assets/svg/forest-theme.svg
|
||||
- assets/svg/chanstheme.svg
|
||||
- assets/svg/darkChansTheme.svg
|
||||
- assets/svg/orange-theme.svg
|
||||
|
||||
# light theme specific
|
||||
- assets/svg/themed/light/
|
||||
|
|
Loading…
Reference in a new issue