mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-11-16 17:27:39 +00:00
Merge pull request #925 from cypherstack/testing
make xpubs layout similar to xprivs
This commit is contained in:
commit
fb09bc6cc9
1 changed files with 190 additions and 109 deletions
|
@ -10,14 +10,17 @@
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:dropdown_button2/dropdown_button2.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:flutter_svg/svg.dart';
|
||||||
|
|
||||||
import '../../../../notifications/show_flush_bar.dart';
|
import '../../../../notifications/show_flush_bar.dart';
|
||||||
import '../../../../themes/stack_colors.dart';
|
import '../../../../themes/stack_colors.dart';
|
||||||
import '../../../../utilities/assets.dart';
|
import '../../../../utilities/assets.dart';
|
||||||
import '../../../../utilities/clipboard_interface.dart';
|
import '../../../../utilities/clipboard_interface.dart';
|
||||||
|
import '../../../../utilities/constants.dart';
|
||||||
import '../../../../utilities/text_styles.dart';
|
import '../../../../utilities/text_styles.dart';
|
||||||
import '../../../../utilities/util.dart';
|
import '../../../../utilities/util.dart';
|
||||||
import '../../../../wallets/isar/providers/wallet_info_provider.dart';
|
import '../../../../wallets/isar/providers/wallet_info_provider.dart';
|
||||||
|
@ -25,16 +28,14 @@ import '../../../../wallets/wallet/wallet_mixin_interfaces/extended_keys_interfa
|
||||||
import '../../../../widgets/background.dart';
|
import '../../../../widgets/background.dart';
|
||||||
import '../../../../widgets/conditional_parent.dart';
|
import '../../../../widgets/conditional_parent.dart';
|
||||||
import '../../../../widgets/custom_buttons/app_bar_icon_button.dart';
|
import '../../../../widgets/custom_buttons/app_bar_icon_button.dart';
|
||||||
import '../../../../widgets/custom_tab_view.dart';
|
|
||||||
import '../../../../widgets/desktop/desktop_dialog.dart';
|
import '../../../../widgets/desktop/desktop_dialog.dart';
|
||||||
import '../../../../widgets/desktop/desktop_dialog_close_button.dart';
|
import '../../../../widgets/desktop/desktop_dialog_close_button.dart';
|
||||||
import '../../../../widgets/desktop/primary_button.dart';
|
import '../../../../widgets/desktop/primary_button.dart';
|
||||||
import '../../../../widgets/desktop/secondary_button.dart';
|
|
||||||
import '../../../../widgets/detail_item.dart';
|
import '../../../../widgets/detail_item.dart';
|
||||||
import '../../../../widgets/qr.dart';
|
import '../../../../widgets/qr.dart';
|
||||||
import '../../../../widgets/rounded_white_container.dart';
|
import '../../../../widgets/rounded_white_container.dart';
|
||||||
|
|
||||||
class XPubView extends ConsumerWidget {
|
class XPubView extends ConsumerStatefulWidget {
|
||||||
const XPubView({
|
const XPubView({
|
||||||
super.key,
|
super.key,
|
||||||
required this.walletId,
|
required this.walletId,
|
||||||
|
@ -49,7 +50,39 @@ class XPubView extends ConsumerWidget {
|
||||||
static const String routeName = "/xpub";
|
static const String routeName = "/xpub";
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
ConsumerState<XPubView> createState() => XPubViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class XPubViewState extends ConsumerState<XPubView> {
|
||||||
|
late String _currentDropDownValue;
|
||||||
|
|
||||||
|
String _current(String key) =>
|
||||||
|
widget.xpubData.xpubs.firstWhere((e) => e.path == key).xpub;
|
||||||
|
|
||||||
|
Future<void> _copy() async {
|
||||||
|
await widget.clipboardInterface.setData(
|
||||||
|
ClipboardData(text: _current(_currentDropDownValue)),
|
||||||
|
);
|
||||||
|
if (mounted) {
|
||||||
|
unawaited(
|
||||||
|
showFloatingFlushBar(
|
||||||
|
type: FlushBarType.info,
|
||||||
|
message: "Copied to clipboard",
|
||||||
|
iconAsset: Assets.svg.copy,
|
||||||
|
context: context,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
_currentDropDownValue = widget.xpubData.xpubs.first.path;
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
final bool isDesktop = Util.isDesktop;
|
final bool isDesktop = Util.isDesktop;
|
||||||
|
|
||||||
return ConditionalParent(
|
return ConditionalParent(
|
||||||
|
@ -75,7 +108,25 @@ class XPubView extends ConsumerWidget {
|
||||||
left: 16,
|
left: 16,
|
||||||
right: 16,
|
right: 16,
|
||||||
),
|
),
|
||||||
child: SingleChildScrollView(child: child),
|
child: LayoutBuilder(
|
||||||
|
builder: (context, constraints) => SingleChildScrollView(
|
||||||
|
child: ConstrainedBox(
|
||||||
|
constraints: BoxConstraints(minHeight: constraints.maxHeight),
|
||||||
|
child: IntrinsicHeight(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 16,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -95,7 +146,7 @@ class XPubView extends ConsumerWidget {
|
||||||
left: 32,
|
left: 32,
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
"${ref.watch(pWalletName(walletId))} xpub(s)",
|
"${ref.watch(pWalletName(widget.walletId))} xpub(s)",
|
||||||
style: STextStyles.desktopH2(context),
|
style: STextStyles.desktopH2(context),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -119,28 +170,146 @@ class XPubView extends ConsumerWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: Util.isDesktop ? MainAxisSize.min : MainAxisSize.max,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
if (isDesktop) const SizedBox(height: 16),
|
SizedBox(
|
||||||
|
height: Util.isDesktop ? 12 : 16,
|
||||||
|
),
|
||||||
DetailItem(
|
DetailItem(
|
||||||
title: "Master fingerprint",
|
title: "Master fingerprint",
|
||||||
detail: xpubData.fingerprint,
|
detail: widget.xpubData.fingerprint,
|
||||||
horizontal: true,
|
horizontal: true,
|
||||||
|
borderColor: Util.isDesktop
|
||||||
|
? Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.textFieldDefaultBG
|
||||||
|
: null,
|
||||||
),
|
),
|
||||||
if (isDesktop) const SizedBox(height: 16),
|
SizedBox(
|
||||||
CustomTabView(
|
height: Util.isDesktop ? 12 : 16,
|
||||||
titles: xpubData.xpubs.map((e) => e.path).toList(),
|
),
|
||||||
children: xpubData.xpubs
|
DetailItemBase(
|
||||||
.map(
|
horizontal: true,
|
||||||
(e) => Padding(
|
borderColor: Util.isDesktop
|
||||||
padding: const EdgeInsets.only(top: 16),
|
? Theme.of(context)
|
||||||
child: _XPub(
|
.extension<StackColors>()!
|
||||||
xpub: e.xpub,
|
.textFieldDefaultBG
|
||||||
derivation: e.path,
|
: null,
|
||||||
|
title: Text(
|
||||||
|
"Derivation",
|
||||||
|
style: STextStyles.itemSubtitle(context),
|
||||||
|
),
|
||||||
|
detail: SizedBox(
|
||||||
|
width: Util.isDesktop ? 200 : 170,
|
||||||
|
child: DropdownButtonHideUnderline(
|
||||||
|
child: DropdownButton2<String>(
|
||||||
|
value: _currentDropDownValue,
|
||||||
|
items: [
|
||||||
|
...widget.xpubData.xpubs.map(
|
||||||
|
(e) => DropdownMenuItem(
|
||||||
|
value: e.path,
|
||||||
|
child: Text(
|
||||||
|
e.path,
|
||||||
|
style: STextStyles.w500_14(context),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
onChanged: (value) {
|
||||||
|
if (value is String) {
|
||||||
|
setState(() {
|
||||||
|
_currentDropDownValue = value;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isExpanded: true,
|
||||||
|
buttonStyleData: ButtonStyleData(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.textFieldDefaultBG,
|
||||||
|
borderRadius: BorderRadius.circular(
|
||||||
|
Constants.size.circularBorderRadius,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
iconStyleData: IconStyleData(
|
||||||
.toList(),
|
icon: Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 10),
|
||||||
|
child: SvgPicture.asset(
|
||||||
|
Assets.svg.chevronDown,
|
||||||
|
width: 12,
|
||||||
|
height: 6,
|
||||||
|
color: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.textFieldActiveSearchIconRight,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
dropdownStyleData: DropdownStyleData(
|
||||||
|
offset: const Offset(0, -10),
|
||||||
|
elevation: 0,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.textFieldDefaultBG,
|
||||||
|
borderRadius: BorderRadius.circular(
|
||||||
|
Constants.size.circularBorderRadius,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
menuItemStyleData: const MenuItemStyleData(
|
||||||
|
padding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 16,
|
||||||
|
vertical: 8,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Util.isDesktop ? 12 : 16,
|
||||||
|
),
|
||||||
|
QR(
|
||||||
|
data: _current(_currentDropDownValue),
|
||||||
|
size: Util.isDesktop
|
||||||
|
? 256
|
||||||
|
: MediaQuery.of(context).size.width / 1.5,
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Util.isDesktop ? 12 : 16,
|
||||||
|
),
|
||||||
|
RoundedWhiteContainer(
|
||||||
|
borderColor: Util.isDesktop
|
||||||
|
? Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.textFieldDefaultBG
|
||||||
|
: null,
|
||||||
|
child: SelectableText(
|
||||||
|
_current(_currentDropDownValue),
|
||||||
|
style: STextStyles.w500_14(context),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Util.isDesktop ? 12 : 16,
|
||||||
|
),
|
||||||
|
if (!Util.isDesktop) const Spacer(),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
if (Util.isDesktop) const Spacer(),
|
||||||
|
if (Util.isDesktop)
|
||||||
|
const SizedBox(
|
||||||
|
width: 16,
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: PrimaryButton(
|
||||||
|
label: "Copy",
|
||||||
|
onPressed: _copy,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -148,91 +317,3 @@ class XPubView extends ConsumerWidget {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _XPub extends StatelessWidget {
|
|
||||||
const _XPub({
|
|
||||||
super.key,
|
|
||||||
required this.xpub,
|
|
||||||
required this.derivation,
|
|
||||||
this.clipboardInterface = const ClipboardWrapper(),
|
|
||||||
});
|
|
||||||
|
|
||||||
final String xpub;
|
|
||||||
final String derivation;
|
|
||||||
|
|
||||||
final ClipboardInterface clipboardInterface;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final bool isDesktop = Util.isDesktop;
|
|
||||||
|
|
||||||
return Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
const SizedBox(
|
|
||||||
height: 25,
|
|
||||||
),
|
|
||||||
ConditionalParent(
|
|
||||||
condition: !isDesktop,
|
|
||||||
builder: (child) => RoundedWhiteContainer(
|
|
||||||
child: child,
|
|
||||||
),
|
|
||||||
child: QR(
|
|
||||||
data: xpub,
|
|
||||||
size: isDesktop ? 280 : MediaQuery.of(context).size.width / 1.5,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 25),
|
|
||||||
RoundedWhiteContainer(
|
|
||||||
padding: const EdgeInsets.all(16),
|
|
||||||
borderColor:
|
|
||||||
Theme.of(context).extension<StackColors>()!.backgroundAppBar,
|
|
||||||
child: SelectableText(
|
|
||||||
xpub,
|
|
||||||
style: STextStyles.largeMedium14(context),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 32),
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
if (isDesktop)
|
|
||||||
Expanded(
|
|
||||||
child: SecondaryButton(
|
|
||||||
buttonHeight: ButtonHeight.xl,
|
|
||||||
label: "Cancel",
|
|
||||||
onPressed: Navigator.of(
|
|
||||||
context,
|
|
||||||
rootNavigator: true,
|
|
||||||
).pop,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (isDesktop) const SizedBox(width: 16),
|
|
||||||
Expanded(
|
|
||||||
child: PrimaryButton(
|
|
||||||
buttonHeight: ButtonHeight.xl,
|
|
||||||
label: "Copy",
|
|
||||||
onPressed: () async {
|
|
||||||
await clipboardInterface.setData(
|
|
||||||
ClipboardData(
|
|
||||||
text: xpub,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
if (context.mounted) {
|
|
||||||
unawaited(
|
|
||||||
showFloatingFlushBar(
|
|
||||||
type: FlushBarType.info,
|
|
||||||
message: "Copied to clipboard",
|
|
||||||
iconAsset: Assets.svg.copy,
|
|
||||||
context: context,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue