mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-11-17 09:47:37 +00:00
WIP address details
This commit is contained in:
parent
172429f94a
commit
c35eaf0b0f
10 changed files with 778 additions and 183 deletions
|
@ -122,7 +122,26 @@ enum AddressType {
|
||||||
cryptonote,
|
cryptonote,
|
||||||
mimbleWimble,
|
mimbleWimble,
|
||||||
unknown,
|
unknown,
|
||||||
nonWallet,
|
nonWallet;
|
||||||
|
|
||||||
|
String get readableName {
|
||||||
|
switch (this) {
|
||||||
|
case AddressType.p2pkh:
|
||||||
|
return "Legacy";
|
||||||
|
case AddressType.p2sh:
|
||||||
|
return "Wrapped segwit";
|
||||||
|
case AddressType.p2wpkh:
|
||||||
|
return "Segwit";
|
||||||
|
case AddressType.cryptonote:
|
||||||
|
return "Cryptonote";
|
||||||
|
case AddressType.mimbleWimble:
|
||||||
|
return "Mimble Wimble";
|
||||||
|
case AddressType.unknown:
|
||||||
|
return "Unknown";
|
||||||
|
case AddressType.nonWallet:
|
||||||
|
return "Non wallet/unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// do not modify
|
// do not modify
|
||||||
|
@ -133,7 +152,26 @@ enum AddressSubType {
|
||||||
paynymSend,
|
paynymSend,
|
||||||
paynymReceive,
|
paynymReceive,
|
||||||
unknown,
|
unknown,
|
||||||
nonWallet,
|
nonWallet;
|
||||||
|
|
||||||
|
String get prettyName {
|
||||||
|
switch (this) {
|
||||||
|
case AddressSubType.receiving:
|
||||||
|
return "Receiving";
|
||||||
|
case AddressSubType.change:
|
||||||
|
return "Change";
|
||||||
|
case AddressSubType.paynymNotification:
|
||||||
|
return "PayNym Notification";
|
||||||
|
case AddressSubType.paynymSend:
|
||||||
|
return "PayNym Send";
|
||||||
|
case AddressSubType.paynymReceive:
|
||||||
|
return "PayNym Receiving";
|
||||||
|
case AddressSubType.unknown:
|
||||||
|
return "Unknown";
|
||||||
|
case AddressSubType.nonWallet:
|
||||||
|
return "Non wallet/unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Embedded(inheritance: false)
|
@Embedded(inheritance: false)
|
||||||
|
|
|
@ -196,7 +196,11 @@ class _SingleFieldEditViewState extends State<SingleFieldEditView> {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
|
if (!isDesktop)
|
||||||
|
const SizedBox(
|
||||||
|
height: 16,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,21 +1,13 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
import 'package:isar/isar.dart';
|
import 'package:isar/isar.dart';
|
||||||
import 'package:stackwallet/db/main_db.dart';
|
import 'package:stackwallet/db/main_db.dart';
|
||||||
import 'package:stackwallet/models/isar/models/isar_models.dart';
|
import 'package:stackwallet/models/isar/models/isar_models.dart';
|
||||||
import 'package:stackwallet/notifications/show_flush_bar.dart';
|
import 'package:stackwallet/pages/receive_view/addresses/address_tag.dart';
|
||||||
import 'package:stackwallet/pages/receive_view/addresses/address_qr_popup.dart';
|
|
||||||
import 'package:stackwallet/pages/receive_view/addresses/edit_address_label_view.dart';
|
|
||||||
import 'package:stackwallet/utilities/clipboard_interface.dart';
|
import 'package:stackwallet/utilities/clipboard_interface.dart';
|
||||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||||
import 'package:stackwallet/utilities/text_styles.dart';
|
import 'package:stackwallet/utilities/text_styles.dart';
|
||||||
import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
|
||||||
import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
|
|
||||||
import 'package:stackwallet/widgets/desktop/secondary_button.dart';
|
|
||||||
import 'package:stackwallet/widgets/icon_widgets/copy_icon.dart';
|
|
||||||
import 'package:stackwallet/widgets/icon_widgets/qrcode_icon.dart';
|
|
||||||
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||||
|
|
||||||
class AddressCard extends StatefulWidget {
|
class AddressCard extends StatefulWidget {
|
||||||
|
@ -24,6 +16,7 @@ class AddressCard extends StatefulWidget {
|
||||||
required this.addressId,
|
required this.addressId,
|
||||||
required this.walletId,
|
required this.walletId,
|
||||||
required this.coin,
|
required this.coin,
|
||||||
|
this.onPressed,
|
||||||
this.clipboard = const ClipboardWrapper(),
|
this.clipboard = const ClipboardWrapper(),
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@ -31,6 +24,7 @@ class AddressCard extends StatefulWidget {
|
||||||
final String walletId;
|
final String walletId;
|
||||||
final Coin coin;
|
final Coin coin;
|
||||||
final ClipboardInterface clipboard;
|
final ClipboardInterface clipboard;
|
||||||
|
final VoidCallback? onPressed;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<AddressCard> createState() => _AddressCardState();
|
State<AddressCard> createState() => _AddressCardState();
|
||||||
|
@ -72,106 +66,126 @@ class _AddressCardState extends State<AddressCard> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return RoundedWhiteContainer(
|
return RoundedWhiteContainer(
|
||||||
|
onPressed: widget.onPressed,
|
||||||
child: StreamBuilder<AddressLabel?>(
|
child: StreamBuilder<AddressLabel?>(
|
||||||
stream: stream,
|
stream: stream,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasData) {
|
if (snapshot.hasData) {
|
||||||
label = snapshot.data!;
|
label = snapshot.data!;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
Row(
|
children: [
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
if (label!.value.isNotEmpty)
|
||||||
children: [
|
Text(
|
||||||
Text(
|
label!.value,
|
||||||
label!.value,
|
style: STextStyles.itemSubtitle(context),
|
||||||
style: STextStyles.itemSubtitle(context),
|
textAlign: TextAlign.left,
|
||||||
),
|
|
||||||
CustomTextButton(
|
|
||||||
text: "Edit label",
|
|
||||||
textSize: 14,
|
|
||||||
onTap: () {
|
|
||||||
Navigator.of(context).pushNamed(
|
|
||||||
EditAddressLabelView.routeName,
|
|
||||||
arguments: label!.id,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
|
// 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(
|
const SizedBox(
|
||||||
height: 8,
|
height: 8,
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: SelectableText(
|
child: SelectableText(
|
||||||
address.value,
|
address.value,
|
||||||
style: STextStyles.itemSubtitle12(context),
|
style: STextStyles.itemSubtitle12(context),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 10,
|
height: 10,
|
||||||
),
|
),
|
||||||
Row(
|
|
||||||
children: [
|
if (label!.tags != null && label!.tags!.isNotEmpty)
|
||||||
Expanded(
|
Wrap(
|
||||||
child: SecondaryButton(
|
spacing: 10,
|
||||||
label: "Copy address",
|
runSpacing: 10,
|
||||||
icon: CopyIcon(
|
children: label!.tags!
|
||||||
color: Theme.of(context)
|
.map(
|
||||||
.extension<StackColors>()!
|
(e) => AddressTag(
|
||||||
.buttonTextSecondary,
|
tag: e,
|
||||||
),
|
),
|
||||||
onPressed: () async {
|
)
|
||||||
await widget.clipboard.setData(
|
.toList(),
|
||||||
ClipboardData(
|
),
|
||||||
text: address.value,
|
// Row(
|
||||||
),
|
// children: [
|
||||||
);
|
// Expanded(
|
||||||
if (mounted) {
|
// child: SecondaryButton(
|
||||||
unawaited(
|
// label: "Copy address",
|
||||||
showFloatingFlushBar(
|
// icon: CopyIcon(
|
||||||
type: FlushBarType.info,
|
// color: Theme.of(context)
|
||||||
message: "Copied to clipboard",
|
// .extension<StackColors>()!
|
||||||
context: context,
|
// .buttonTextSecondary,
|
||||||
),
|
// ),
|
||||||
);
|
// onPressed: () async {
|
||||||
}
|
// await widget.clipboard.setData(
|
||||||
},
|
// ClipboardData(
|
||||||
),
|
// text: address.value,
|
||||||
),
|
// ),
|
||||||
const SizedBox(
|
// );
|
||||||
width: 12,
|
// if (mounted) {
|
||||||
),
|
// unawaited(
|
||||||
Expanded(
|
// showFloatingFlushBar(
|
||||||
child: SecondaryButton(
|
// type: FlushBarType.info,
|
||||||
label: "Show QR Code",
|
// message: "Copied to clipboard",
|
||||||
icon: QrCodeIcon(
|
// context: context,
|
||||||
color: Theme.of(context)
|
// ),
|
||||||
.extension<StackColors>()!
|
// );
|
||||||
.buttonTextSecondary,
|
// }
|
||||||
),
|
// },
|
||||||
onPressed: () {
|
// ),
|
||||||
showDialog<void>(
|
// ),
|
||||||
context: context,
|
// const SizedBox(
|
||||||
builder: (context) => AddressQrPopup(
|
// width: 12,
|
||||||
addressString: address.value,
|
// ),
|
||||||
coin: widget.coin,
|
// Expanded(
|
||||||
clipboard: widget.clipboard,
|
// 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,
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
// },
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
// )
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
346
lib/pages/receive_view/addresses/address_details_view.dart
Normal file
346
lib/pages/receive_view/addresses/address_details_view.dart
Normal file
|
@ -0,0 +1,346 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:isar/isar.dart';
|
||||||
|
import 'package:qr_flutter/qr_flutter.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/pages/wallet_view/sub_widgets/transactions_list.dart';
|
||||||
|
import 'package:stackwallet/providers/global/wallets_provider.dart';
|
||||||
|
import 'package:stackwallet/utilities/address_utils.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/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/simple_copy_button.dart';
|
||||||
|
import 'package:stackwallet/widgets/custom_buttons/simple_edit_button.dart';
|
||||||
|
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||||
|
|
||||||
|
class AddressDetailsView extends ConsumerStatefulWidget {
|
||||||
|
const AddressDetailsView({
|
||||||
|
Key? key,
|
||||||
|
required this.addressId,
|
||||||
|
required this.walletId,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
static const String routeName = "/addressDetailsView";
|
||||||
|
|
||||||
|
final Id addressId;
|
||||||
|
final String walletId;
|
||||||
|
|
||||||
|
@override
|
||||||
|
ConsumerState<AddressDetailsView> createState() => _AddressDetailsViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _AddressDetailsViewState extends ConsumerState<AddressDetailsView> {
|
||||||
|
final _qrKey = GlobalKey();
|
||||||
|
final isDesktop = Util.isDesktop;
|
||||||
|
|
||||||
|
late Stream<AddressLabel?> stream;
|
||||||
|
late final Address address;
|
||||||
|
|
||||||
|
AddressLabel? label;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
address = MainDB.instance.isar.addresses
|
||||||
|
.where()
|
||||||
|
.idEqualTo(widget.addressId)
|
||||||
|
.findFirstSync()!;
|
||||||
|
|
||||||
|
label = MainDB.instance.getAddressLabelSync(widget.walletId, address.value);
|
||||||
|
Id? id = label?.id;
|
||||||
|
if (id == null) {
|
||||||
|
label = AddressLabel(
|
||||||
|
walletId: widget.walletId,
|
||||||
|
addressString: address.value,
|
||||||
|
value: "",
|
||||||
|
tags: address.subType == AddressSubType.receiving
|
||||||
|
? ["receiving"]
|
||||||
|
: address.subType == AddressSubType.change
|
||||||
|
? ["change"]
|
||||||
|
: null,
|
||||||
|
);
|
||||||
|
id = MainDB.instance.putAddressLabelSync(label!);
|
||||||
|
}
|
||||||
|
stream = MainDB.instance.watchAddressLabel(id: id);
|
||||||
|
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final coin = ref.watch(walletsChangeNotifierProvider
|
||||||
|
.select((value) => value.getManager(widget.walletId).coin));
|
||||||
|
return ConditionalParent(
|
||||||
|
condition: !isDesktop,
|
||||||
|
builder: (child) => Background(
|
||||||
|
child: Scaffold(
|
||||||
|
backgroundColor:
|
||||||
|
Theme.of(context).extension<StackColors>()!.background,
|
||||||
|
appBar: AppBar(
|
||||||
|
backgroundColor:
|
||||||
|
Theme.of(context).extension<StackColors>()!.backgroundAppBar,
|
||||||
|
leading: AppBarBackButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
titleSpacing: 0,
|
||||||
|
title: Text(
|
||||||
|
"Wallet addresses",
|
||||||
|
style: STextStyles.navBarTitle(context),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
body: SafeArea(
|
||||||
|
child: NestedScrollView(
|
||||||
|
floatHeaderSlivers: true,
|
||||||
|
headerSliverBuilder: (context, innerBoxIsScrolled) {
|
||||||
|
return [
|
||||||
|
SliverOverlapAbsorber(
|
||||||
|
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(
|
||||||
|
context),
|
||||||
|
sliver: SliverToBoxAdapter(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
left: 16,
|
||||||
|
right: 16,
|
||||||
|
top: 16,
|
||||||
|
),
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
];
|
||||||
|
},
|
||||||
|
body: TransactionsList(
|
||||||
|
walletId: widget.walletId,
|
||||||
|
managerProvider: ref.watch(
|
||||||
|
walletsChangeNotifierProvider.select((value) =>
|
||||||
|
value.getManagerProvider(widget.walletId)))),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: StreamBuilder<AddressLabel?>(
|
||||||
|
stream: stream,
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.hasData) {
|
||||||
|
label = snapshot.data!;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
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,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
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,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 12,
|
||||||
|
),
|
||||||
|
_Tags(
|
||||||
|
tags: label!.tags,
|
||||||
|
),
|
||||||
|
if (address.derivationPath != null)
|
||||||
|
const SizedBox(
|
||||||
|
height: 12,
|
||||||
|
),
|
||||||
|
if (address.derivationPath != null)
|
||||||
|
_Item(
|
||||||
|
title: "Derivation path",
|
||||||
|
data: address.derivationPath!.value,
|
||||||
|
button: SimpleEditButton(
|
||||||
|
editValue: label!.value,
|
||||||
|
editLabel: 'label',
|
||||||
|
onValueChanged: (value) {
|
||||||
|
MainDB.instance.putAddressLabel(
|
||||||
|
label!.copyWith(
|
||||||
|
label: value,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
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",
|
||||||
|
style: STextStyles.itemSubtitle(context).copyWith(
|
||||||
|
color: Theme.of(context).extension<StackColors>()!.textDark3,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _Tags extends StatelessWidget {
|
||||||
|
const _Tags({
|
||||||
|
Key? key,
|
||||||
|
required this.tags,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
final List<String>? tags;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return RoundedWhiteContainer(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Tags",
|
||||||
|
style: STextStyles.itemSubtitle(context),
|
||||||
|
),
|
||||||
|
SimpleEditButton(
|
||||||
|
onPressedOverride: () {
|
||||||
|
// TODO edit tags
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 8,
|
||||||
|
),
|
||||||
|
tags != null && tags!.isNotEmpty
|
||||||
|
? Wrap(
|
||||||
|
spacing: 10,
|
||||||
|
runSpacing: 10,
|
||||||
|
children: tags!
|
||||||
|
.map(
|
||||||
|
(e) => AddressTag(
|
||||||
|
tag: e,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
|
)
|
||||||
|
: Text(
|
||||||
|
"Tags will appear here",
|
||||||
|
style: STextStyles.w500_14(context).copyWith(
|
||||||
|
color: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.textSubtitle3,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _Item extends StatelessWidget {
|
||||||
|
const _Item({
|
||||||
|
Key? key,
|
||||||
|
required this.title,
|
||||||
|
required this.data,
|
||||||
|
required this.button,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
final String title;
|
||||||
|
final String data;
|
||||||
|
final Widget button;
|
||||||
|
|
||||||
|
@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,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
26
lib/pages/receive_view/addresses/address_tag.dart
Normal file
26
lib/pages/receive_view/addresses/address_tag.dart
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_native_splash/cli_commands.dart';
|
||||||
|
import 'package:stackwallet/utilities/text_styles.dart';
|
||||||
|
import 'package:stackwallet/widgets/rounded_container.dart';
|
||||||
|
|
||||||
|
class AddressTag extends StatelessWidget {
|
||||||
|
const AddressTag({Key? key, required this.tag}) : super(key: key);
|
||||||
|
|
||||||
|
final String tag;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return RoundedContainer(
|
||||||
|
radiusMultiplier: 0.5,
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 5,
|
||||||
|
horizontal: 7,
|
||||||
|
),
|
||||||
|
color: Colors.black,
|
||||||
|
child: Text(
|
||||||
|
tag.capitalize(),
|
||||||
|
style: STextStyles.w500_14(context),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +1,11 @@
|
||||||
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/svg.dart';
|
||||||
import 'package:isar/isar.dart';
|
import 'package:isar/isar.dart';
|
||||||
import 'package:stackwallet/db/main_db.dart';
|
import 'package:stackwallet/db/main_db.dart';
|
||||||
import 'package:stackwallet/models/isar/models/isar_models.dart';
|
import 'package:stackwallet/models/isar/models/isar_models.dart';
|
||||||
import 'package:stackwallet/pages/receive_view/addresses/address_card.dart';
|
import 'package:stackwallet/pages/receive_view/addresses/address_card.dart';
|
||||||
|
import 'package:stackwallet/pages/receive_view/addresses/address_details_view.dart';
|
||||||
import 'package:stackwallet/providers/global/wallets_provider.dart';
|
import 'package:stackwallet/providers/global/wallets_provider.dart';
|
||||||
import 'package:stackwallet/utilities/constants.dart';
|
import 'package:stackwallet/utilities/constants.dart';
|
||||||
import 'package:stackwallet/utilities/text_styles.dart';
|
import 'package:stackwallet/utilities/text_styles.dart';
|
||||||
|
@ -13,7 +15,12 @@ import 'package:stackwallet/widgets/background.dart';
|
||||||
import 'package:stackwallet/widgets/conditional_parent.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/app_bar_icon_button.dart';
|
||||||
import 'package:stackwallet/widgets/loading_indicator.dart';
|
import 'package:stackwallet/widgets/loading_indicator.dart';
|
||||||
import 'package:stackwallet/widgets/toggle.dart';
|
import 'package:stackwallet/widgets/stack_text_field.dart';
|
||||||
|
import 'package:tuple/tuple.dart';
|
||||||
|
|
||||||
|
import '../../../utilities/assets.dart';
|
||||||
|
import '../../../widgets/icon_widgets/x_icon.dart';
|
||||||
|
import '../../../widgets/textfield_icon_button.dart';
|
||||||
|
|
||||||
class WalletAddressesView extends ConsumerStatefulWidget {
|
class WalletAddressesView extends ConsumerStatefulWidget {
|
||||||
const WalletAddressesView({
|
const WalletAddressesView({
|
||||||
|
@ -33,7 +40,88 @@ class WalletAddressesView extends ConsumerStatefulWidget {
|
||||||
class _WalletAddressesViewState extends ConsumerState<WalletAddressesView> {
|
class _WalletAddressesViewState extends ConsumerState<WalletAddressesView> {
|
||||||
final bool isDesktop = Util.isDesktop;
|
final bool isDesktop = Util.isDesktop;
|
||||||
|
|
||||||
bool _showChange = false;
|
String _searchString = "";
|
||||||
|
|
||||||
|
late final TextEditingController _searchController;
|
||||||
|
final searchFieldFocusNode = FocusNode();
|
||||||
|
|
||||||
|
Future<List<int>> _search(String term) async {
|
||||||
|
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()
|
||||||
|
.findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
final labels = await 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),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.findAll();
|
||||||
|
|
||||||
|
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()
|
||||||
|
.findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
_searchController = TextEditingController();
|
||||||
|
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_searchController.dispose();
|
||||||
|
searchFieldFocusNode.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -68,26 +156,66 @@ class _WalletAddressesViewState extends ConsumerState<WalletAddressesView> {
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: isDesktop ? 56 : 48,
|
|
||||||
width: isDesktop ? 490 : null,
|
width: isDesktop ? 490 : null,
|
||||||
child: Toggle(
|
child: ClipRRect(
|
||||||
key: UniqueKey(),
|
borderRadius: BorderRadius.circular(
|
||||||
onColor: Theme.of(context).extension<StackColors>()!.popupBG,
|
Constants.size.circularBorderRadius,
|
||||||
onText: "Receiving",
|
),
|
||||||
offColor: Theme.of(context)
|
child: TextField(
|
||||||
.extension<StackColors>()!
|
autocorrect: !isDesktop,
|
||||||
.textFieldDefaultBG,
|
enableSuggestions: !isDesktop,
|
||||||
offText: "Change",
|
controller: _searchController,
|
||||||
isOn: _showChange,
|
focusNode: searchFieldFocusNode,
|
||||||
onValueChanged: (value) {
|
onChanged: (value) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_showChange = value;
|
_searchString = value;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
decoration: BoxDecoration(
|
style: isDesktop
|
||||||
color: Colors.transparent,
|
? STextStyles.desktopTextExtraSmall(context).copyWith(
|
||||||
borderRadius: BorderRadius.circular(
|
color: Theme.of(context)
|
||||||
Constants.size.circularBorderRadius,
|
.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,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -97,23 +225,7 @@ class _WalletAddressesViewState extends ConsumerState<WalletAddressesView> {
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: FutureBuilder(
|
child: FutureBuilder(
|
||||||
future: MainDB.instance
|
future: _search(_searchString),
|
||||||
.getAddresses(widget.walletId)
|
|
||||||
.filter()
|
|
||||||
.group(
|
|
||||||
(q) => _showChange
|
|
||||||
? q.subTypeEqualTo(AddressSubType.change)
|
|
||||||
: q
|
|
||||||
.subTypeEqualTo(AddressSubType.receiving)
|
|
||||||
.or()
|
|
||||||
.subTypeEqualTo(AddressSubType.paynymReceive),
|
|
||||||
)
|
|
||||||
.and()
|
|
||||||
.not()
|
|
||||||
.typeEqualTo(AddressType.nonWallet)
|
|
||||||
.sortByDerivationIndex()
|
|
||||||
.idProperty()
|
|
||||||
.findAll(),
|
|
||||||
builder: (context, AsyncSnapshot<List<int>> snapshot) {
|
builder: (context, AsyncSnapshot<List<int>> snapshot) {
|
||||||
if (snapshot.connectionState == ConnectionState.done &&
|
if (snapshot.connectionState == ConnectionState.done &&
|
||||||
snapshot.data != null) {
|
snapshot.data != null) {
|
||||||
|
@ -127,6 +239,15 @@ class _WalletAddressesViewState extends ConsumerState<WalletAddressesView> {
|
||||||
walletId: widget.walletId,
|
walletId: widget.walletId,
|
||||||
addressId: snapshot.data![index],
|
addressId: snapshot.data![index],
|
||||||
coin: coin,
|
coin: coin,
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pushNamed(
|
||||||
|
AddressDetailsView.routeName,
|
||||||
|
arguments: Tuple2(
|
||||||
|
snapshot.data![index],
|
||||||
|
widget.walletId,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -48,6 +48,7 @@ import 'package:stackwallet/pages/paynym/add_new_paynym_follow_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/pages/pinpad_views/create_pin_view.dart';
|
import 'package:stackwallet/pages/pinpad_views/create_pin_view.dart';
|
||||||
|
import 'package:stackwallet/pages/receive_view/addresses/address_details_view.dart';
|
||||||
import 'package:stackwallet/pages/receive_view/addresses/edit_address_label_view.dart';
|
import 'package:stackwallet/pages/receive_view/addresses/edit_address_label_view.dart';
|
||||||
import 'package:stackwallet/pages/receive_view/addresses/wallet_addresses_view.dart';
|
import 'package:stackwallet/pages/receive_view/addresses/wallet_addresses_view.dart';
|
||||||
import 'package:stackwallet/pages/receive_view/generate_receiving_uri_qr_code_view.dart';
|
import 'package:stackwallet/pages/receive_view/generate_receiving_uri_qr_code_view.dart';
|
||||||
|
@ -928,6 +929,21 @@ class RouteGenerator {
|
||||||
}
|
}
|
||||||
return _routeError("${settings.name} invalid args: ${args.toString()}");
|
return _routeError("${settings.name} invalid args: ${args.toString()}");
|
||||||
|
|
||||||
|
case AddressDetailsView.routeName:
|
||||||
|
if (args is Tuple2<Id, String>) {
|
||||||
|
return getRoute(
|
||||||
|
shouldUseMaterialRoute: useMaterialPageRoute,
|
||||||
|
builder: (_) => AddressDetailsView(
|
||||||
|
walletId: args.item2,
|
||||||
|
addressId: args.item1,
|
||||||
|
),
|
||||||
|
settings: RouteSettings(
|
||||||
|
name: settings.name,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return _routeError("${settings.name} invalid args: ${args.toString()}");
|
||||||
|
|
||||||
case SendView.routeName:
|
case SendView.routeName:
|
||||||
if (args is Tuple2<String, Coin>) {
|
if (args is Tuple2<String, Coin>) {
|
||||||
return getRoute(
|
return getRoute(
|
||||||
|
|
|
@ -221,11 +221,27 @@ class DbVersionMigrator with WalletDB {
|
||||||
|
|
||||||
final List<isar_models.AddressLabel> labels = [];
|
final List<isar_models.AddressLabel> labels = [];
|
||||||
for (final address in addresses) {
|
for (final address in addresses) {
|
||||||
final tags = address.subType == AddressSubType.receiving
|
List<String>? tags;
|
||||||
? ["receiving"]
|
switch (address.subType) {
|
||||||
: address.subType == AddressSubType.change
|
case AddressSubType.receiving:
|
||||||
? ["change"]
|
tags = ["receiving"];
|
||||||
: null;
|
break;
|
||||||
|
case AddressSubType.change:
|
||||||
|
tags = ["change"];
|
||||||
|
break;
|
||||||
|
case AddressSubType.paynymNotification:
|
||||||
|
tags = ["paynym notification"];
|
||||||
|
break;
|
||||||
|
case AddressSubType.paynymSend:
|
||||||
|
break;
|
||||||
|
case AddressSubType.paynymReceive:
|
||||||
|
tags = ["paynym receiving"];
|
||||||
|
break;
|
||||||
|
case AddressSubType.unknown:
|
||||||
|
break;
|
||||||
|
case AddressSubType.nonWallet:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// update/create label if tags is not empty
|
// update/create label if tags is not empty
|
||||||
if (tags != null) {
|
if (tags != null) {
|
||||||
|
|
|
@ -13,14 +13,23 @@ import '../icon_widgets/pencil_icon.dart';
|
||||||
class SimpleEditButton extends StatelessWidget {
|
class SimpleEditButton extends StatelessWidget {
|
||||||
const SimpleEditButton({
|
const SimpleEditButton({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.editValue,
|
this.editValue,
|
||||||
required this.editLabel,
|
this.editLabel,
|
||||||
required this.onValueChanged,
|
this.onValueChanged,
|
||||||
}) : super(key: key);
|
this.onPressedOverride,
|
||||||
|
}) : assert(
|
||||||
|
(editLabel != null && editValue != null && onValueChanged != null) ||
|
||||||
|
(editLabel == null &&
|
||||||
|
editValue == null &&
|
||||||
|
onValueChanged == null &&
|
||||||
|
onPressedOverride != null),
|
||||||
|
),
|
||||||
|
super(key: key);
|
||||||
|
|
||||||
final String editValue;
|
final String? editValue;
|
||||||
final String editLabel;
|
final String? editLabel;
|
||||||
final void Function(String) onValueChanged;
|
final void Function(String)? onValueChanged;
|
||||||
|
final VoidCallback? onPressedOverride;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -36,24 +45,25 @@ class SimpleEditButton extends StatelessWidget {
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(6),
|
borderRadius: BorderRadius.circular(6),
|
||||||
),
|
),
|
||||||
onPressed: () async {
|
onPressed: onPressedOverride ??
|
||||||
final result = await showDialog<String?>(
|
() async {
|
||||||
context: context,
|
final result = await showDialog<String?>(
|
||||||
builder: (context) {
|
context: context,
|
||||||
return DesktopDialog(
|
builder: (context) {
|
||||||
maxWidth: 580,
|
return DesktopDialog(
|
||||||
maxHeight: 360,
|
maxWidth: 580,
|
||||||
child: SingleFieldEditView(
|
maxHeight: 360,
|
||||||
initialValue: editValue,
|
child: SingleFieldEditView(
|
||||||
label: editLabel,
|
initialValue: editValue!,
|
||||||
),
|
label: editLabel!,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
if (result is String && result != editValue!) {
|
||||||
|
onValueChanged?.call(result);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
);
|
|
||||||
if (result is String && result != editValue) {
|
|
||||||
onValueChanged(result);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(5),
|
padding: const EdgeInsets.all(5),
|
||||||
child: PencilIcon(
|
child: PencilIcon(
|
||||||
|
@ -66,18 +76,19 @@ class SimpleEditButton extends StatelessWidget {
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: () async {
|
onTap: onPressedOverride ??
|
||||||
final result = await Navigator.of(context).pushNamed(
|
() async {
|
||||||
SingleFieldEditView.routeName,
|
final result = await Navigator.of(context).pushNamed(
|
||||||
arguments: Tuple2(
|
SingleFieldEditView.routeName,
|
||||||
editValue,
|
arguments: Tuple2(
|
||||||
editLabel,
|
editValue!,
|
||||||
),
|
editLabel!,
|
||||||
);
|
),
|
||||||
if (result is String && result != editValue) {
|
);
|
||||||
onValueChanged(result);
|
if (result is String && result != editValue!) {
|
||||||
}
|
onValueChanged?.call(result);
|
||||||
},
|
}
|
||||||
|
},
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
SvgPicture.asset(
|
SvgPicture.asset(
|
||||||
|
|
|
@ -12,6 +12,7 @@ class RoundedWhiteContainer extends StatelessWidget {
|
||||||
this.height,
|
this.height,
|
||||||
this.borderColor,
|
this.borderColor,
|
||||||
this.boxShadow,
|
this.boxShadow,
|
||||||
|
this.onPressed,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
final Widget? child;
|
final Widget? child;
|
||||||
|
@ -21,6 +22,7 @@ class RoundedWhiteContainer extends StatelessWidget {
|
||||||
final double? height;
|
final double? height;
|
||||||
final Color? borderColor;
|
final Color? borderColor;
|
||||||
final List<BoxShadow>? boxShadow;
|
final List<BoxShadow>? boxShadow;
|
||||||
|
final VoidCallback? onPressed;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -32,6 +34,7 @@ class RoundedWhiteContainer extends StatelessWidget {
|
||||||
height: height,
|
height: height,
|
||||||
borderColor: borderColor,
|
borderColor: borderColor,
|
||||||
boxShadow: boxShadow,
|
boxShadow: boxShadow,
|
||||||
|
onPressed: onPressed,
|
||||||
child: child,
|
child: child,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue