mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2025-01-11 05:04:35 +00:00
Merge branch 'ordinals-desktop' into ordinals
This commit is contained in:
commit
f478f0e9ec
8 changed files with 660 additions and 16 deletions
|
@ -3,7 +3,6 @@ import 'dart:async';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:stackwallet/dto/ordinals/inscription_data.dart';
|
|
||||||
import 'package:stackwallet/models/ordinal.dart';
|
import 'package:stackwallet/models/ordinal.dart';
|
||||||
import 'package:stackwallet/notifications/show_flush_bar.dart';
|
import 'package:stackwallet/notifications/show_flush_bar.dart';
|
||||||
import 'package:stackwallet/pages/ordinals/widgets/dialogs.dart';
|
import 'package:stackwallet/pages/ordinals/widgets/dialogs.dart';
|
||||||
|
@ -199,16 +198,14 @@ class _OrdinalImageGroup extends StatelessWidget {
|
||||||
// height: _spacing,
|
// height: _spacing,
|
||||||
// ),
|
// ),
|
||||||
AspectRatio(
|
AspectRatio(
|
||||||
aspectRatio: 1,
|
|
||||||
child: AspectRatio(
|
|
||||||
aspectRatio: 1,
|
aspectRatio: 1,
|
||||||
child: Container(
|
child: Container(
|
||||||
color: Colors.red,
|
color: Colors.red,
|
||||||
child: Image.network(
|
child: Image.network(
|
||||||
ordinal.content, // Use the preview URL as the image source
|
ordinal.content, // Use the preview URL as the image source
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
filterQuality: FilterQuality.none, // Set the filter mode to nearest
|
filterQuality:
|
||||||
),
|
FilterQuality.none, // Set the filter mode to nearest
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -19,6 +19,7 @@ import 'package:stackwallet/notifications/show_flush_bar.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_desktop_specific/coin_control/desktop_coin_control_view.dart';
|
import 'package:stackwallet/pages_desktop_specific/coin_control/desktop_coin_control_view.dart';
|
||||||
|
import 'package:stackwallet/pages_desktop_specific/ordinals/desktop_ordinals_view.dart';
|
||||||
import 'package:stackwallet/pages_desktop_specific/desktop_menu.dart';
|
import 'package:stackwallet/pages_desktop_specific/desktop_menu.dart';
|
||||||
import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart';
|
import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart';
|
||||||
import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart';
|
import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart';
|
||||||
|
@ -80,6 +81,7 @@ class _DesktopWalletFeaturesState extends ConsumerState<DesktopWalletFeatures> {
|
||||||
onCoinControlPressed: _onCoinControlPressed,
|
onCoinControlPressed: _onCoinControlPressed,
|
||||||
onAnonymizeAllPressed: _onAnonymizeAllPressed,
|
onAnonymizeAllPressed: _onAnonymizeAllPressed,
|
||||||
onWhirlpoolPressed: _onWhirlpoolPressed,
|
onWhirlpoolPressed: _onWhirlpoolPressed,
|
||||||
|
onOrdinalsPressed: _onOrdinalsPressed,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -313,6 +315,15 @@ class _DesktopWalletFeaturesState extends ConsumerState<DesktopWalletFeatures> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _onOrdinalsPressed() {
|
||||||
|
Navigator.of(context, rootNavigator: true).pop();
|
||||||
|
|
||||||
|
Navigator.of(context).pushNamed(
|
||||||
|
DesktopOrdinalsView.routeName,
|
||||||
|
arguments: widget.walletId,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final manager = ref.watch(
|
final manager = ref.watch(
|
||||||
|
|
|
@ -29,6 +29,7 @@ class MoreFeaturesDialog extends ConsumerStatefulWidget {
|
||||||
required this.onCoinControlPressed,
|
required this.onCoinControlPressed,
|
||||||
required this.onAnonymizeAllPressed,
|
required this.onAnonymizeAllPressed,
|
||||||
required this.onWhirlpoolPressed,
|
required this.onWhirlpoolPressed,
|
||||||
|
required this.onOrdinalsPressed,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
final String walletId;
|
final String walletId;
|
||||||
|
@ -36,6 +37,7 @@ class MoreFeaturesDialog extends ConsumerStatefulWidget {
|
||||||
final VoidCallback? onCoinControlPressed;
|
final VoidCallback? onCoinControlPressed;
|
||||||
final VoidCallback? onAnonymizeAllPressed;
|
final VoidCallback? onAnonymizeAllPressed;
|
||||||
final VoidCallback? onWhirlpoolPressed;
|
final VoidCallback? onWhirlpoolPressed;
|
||||||
|
final VoidCallback? onOrdinalsPressed;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ConsumerState<MoreFeaturesDialog> createState() => _MoreFeaturesDialogState();
|
ConsumerState<MoreFeaturesDialog> createState() => _MoreFeaturesDialogState();
|
||||||
|
@ -100,9 +102,16 @@ class _MoreFeaturesDialogState extends ConsumerState<MoreFeaturesDialog> {
|
||||||
_MoreFeaturesItem(
|
_MoreFeaturesItem(
|
||||||
label: "PayNym",
|
label: "PayNym",
|
||||||
detail: "Increased address privacy using BIP47",
|
detail: "Increased address privacy using BIP47",
|
||||||
iconAsset: Assets.svg.robotHead,
|
iconAsset: Assets.svg.ordinal,
|
||||||
onPressed: () => widget.onPaynymPressed?.call(),
|
onPressed: () => widget.onPaynymPressed?.call(),
|
||||||
),
|
),
|
||||||
|
if (manager.hasOrdinalsSupport)
|
||||||
|
_MoreFeaturesItem(
|
||||||
|
label: "Ordinals",
|
||||||
|
detail: "View and control your ordinals in Stack",
|
||||||
|
iconAsset: Assets.svg.ordinal,
|
||||||
|
onPressed: () => widget.onOrdinalsPressed?.call(),
|
||||||
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 28,
|
height: 28,
|
||||||
),
|
),
|
||||||
|
|
|
@ -0,0 +1,302 @@
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
import 'package:stackwallet/models/ordinal.dart';
|
||||||
|
import 'package:stackwallet/notifications/show_flush_bar.dart';
|
||||||
|
import 'package:stackwallet/pages/ordinals/widgets/dialogs.dart';
|
||||||
|
import 'package:stackwallet/themes/stack_colors.dart';
|
||||||
|
import 'package:stackwallet/utilities/assets.dart';
|
||||||
|
import 'package:stackwallet/utilities/text_styles.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';
|
||||||
|
import 'package:stackwallet/widgets/desktop/primary_button.dart';
|
||||||
|
import 'package:stackwallet/widgets/desktop/secondary_button.dart';
|
||||||
|
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||||
|
|
||||||
|
class DesktopOrdinalDetailsView extends StatefulWidget {
|
||||||
|
const DesktopOrdinalDetailsView({
|
||||||
|
Key? key,
|
||||||
|
required this.walletId,
|
||||||
|
required this.ordinal,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
final String walletId;
|
||||||
|
final Ordinal ordinal;
|
||||||
|
|
||||||
|
static const routeName = "/desktopOrdinalDetailsView";
|
||||||
|
|
||||||
|
@override
|
||||||
|
_DesktopOrdinalDetailsViewState createState() =>
|
||||||
|
_DesktopOrdinalDetailsViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DesktopOrdinalDetailsViewState extends State<DesktopOrdinalDetailsView> {
|
||||||
|
static const _spacing = 12.0;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return DesktopScaffold(
|
||||||
|
appBar: DesktopAppBar(
|
||||||
|
background: Theme.of(context).extension<StackColors>()!.popupBG,
|
||||||
|
leading: Expanded(
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
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: 18,
|
||||||
|
),
|
||||||
|
SvgPicture.asset(
|
||||||
|
Assets.svg.ordinal,
|
||||||
|
width: 32,
|
||||||
|
height: 32,
|
||||||
|
color:
|
||||||
|
Theme.of(context).extension<StackColors>()!.textSubtitle1,
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 12,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
"Ordinals",
|
||||||
|
style: STextStyles.desktopH3(context),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
useSpacers: false,
|
||||||
|
isCompactHeight: true,
|
||||||
|
),
|
||||||
|
body: SingleChildScrollView(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 12,
|
||||||
|
horizontal: 39,
|
||||||
|
),
|
||||||
|
child: _OrdinalImageGroup(
|
||||||
|
ordinal: widget.ordinal,
|
||||||
|
walletId: widget.walletId,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
_DetailsItemWCopy(
|
||||||
|
title: "Inscription number",
|
||||||
|
data: widget.ordinal.inscriptionNumber.toString(),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: _spacing,
|
||||||
|
),
|
||||||
|
_DetailsItemWCopy(
|
||||||
|
title: "ID",
|
||||||
|
data: widget.ordinal.inscriptionId,
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: _spacing,
|
||||||
|
),
|
||||||
|
// todo: add utxo status
|
||||||
|
const SizedBox(
|
||||||
|
height: _spacing,
|
||||||
|
),
|
||||||
|
const _DetailsItemWCopy(
|
||||||
|
title: "Amount",
|
||||||
|
data: "TODO", // TODO infer from utxo utxoTXID:utxoVOUT
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: _spacing,
|
||||||
|
),
|
||||||
|
const _DetailsItemWCopy(
|
||||||
|
title: "Owner address",
|
||||||
|
data: "TODO", // infer from address associated w utxoTXID
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: _spacing,
|
||||||
|
),
|
||||||
|
_DetailsItemWCopy(
|
||||||
|
title: "Transaction ID",
|
||||||
|
data: widget.ordinal.utxoTXID,
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: _spacing,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DetailsItemWCopy extends StatelessWidget {
|
||||||
|
const _DetailsItemWCopy({
|
||||||
|
Key? key,
|
||||||
|
required this.title,
|
||||||
|
required this.data,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
final String title;
|
||||||
|
final String data;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return RoundedWhiteContainer(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
title,
|
||||||
|
style: STextStyles.itemSubtitle(context),
|
||||||
|
),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () async {
|
||||||
|
await Clipboard.setData(ClipboardData(text: data));
|
||||||
|
if (context.mounted) {
|
||||||
|
unawaited(
|
||||||
|
showFloatingFlushBar(
|
||||||
|
type: FlushBarType.info,
|
||||||
|
message: "Copied to clipboard",
|
||||||
|
context: context,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: SvgPicture.asset(
|
||||||
|
Assets.svg.copy,
|
||||||
|
color:
|
||||||
|
Theme.of(context).extension<StackColors>()!.infoItemIcons,
|
||||||
|
width: 12,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 4,
|
||||||
|
),
|
||||||
|
SelectableText(
|
||||||
|
data,
|
||||||
|
style: STextStyles.itemSubtitle12(context),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _OrdinalImageGroup extends StatelessWidget {
|
||||||
|
const _OrdinalImageGroup({
|
||||||
|
Key? key,
|
||||||
|
required this.walletId,
|
||||||
|
required this.ordinal,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
final String walletId;
|
||||||
|
final Ordinal ordinal;
|
||||||
|
|
||||||
|
static const _spacing = 12.0;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
// Text(
|
||||||
|
// "${ordinal.inscriptionId}", // Use any other property you want
|
||||||
|
// style: STextStyles.w600_16(context),
|
||||||
|
// ),
|
||||||
|
// const SizedBox(
|
||||||
|
// height: _spacing,
|
||||||
|
// ),
|
||||||
|
AspectRatio(
|
||||||
|
aspectRatio: 1,
|
||||||
|
child: Container(
|
||||||
|
color: Colors.red,
|
||||||
|
child: Image.network(
|
||||||
|
ordinal.content, // Use the preview URL as the image source
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
filterQuality:
|
||||||
|
FilterQuality.none, // Set the filter mode to nearest
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: _spacing,
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: SecondaryButton(
|
||||||
|
label: "Download",
|
||||||
|
icon: SvgPicture.asset(
|
||||||
|
Assets.svg.arrowDown,
|
||||||
|
width: 10,
|
||||||
|
height: 12,
|
||||||
|
color: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.buttonTextSecondary,
|
||||||
|
),
|
||||||
|
buttonHeight: ButtonHeight.l,
|
||||||
|
iconSpacing: 4,
|
||||||
|
onPressed: () {
|
||||||
|
// TODO: save and download image to device
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: _spacing,
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: PrimaryButton(
|
||||||
|
label: "Send",
|
||||||
|
icon: SvgPicture.asset(
|
||||||
|
Assets.svg.send,
|
||||||
|
width: 10,
|
||||||
|
height: 10,
|
||||||
|
color: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.buttonTextPrimary,
|
||||||
|
),
|
||||||
|
buttonHeight: ButtonHeight.l,
|
||||||
|
iconSpacing: 4,
|
||||||
|
onPressed: () async {
|
||||||
|
final response = await showDialog<String?>(
|
||||||
|
context: context,
|
||||||
|
builder: (_) => const SendOrdinalUnfreezeDialog(),
|
||||||
|
);
|
||||||
|
if (response == "unfreeze") {
|
||||||
|
// TODO: unfreeze and go to send ord screen
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
190
lib/pages_desktop_specific/ordinals/desktop_ordinals_view.dart
Normal file
190
lib/pages_desktop_specific/ordinals/desktop_ordinals_view.dart
Normal file
|
@ -0,0 +1,190 @@
|
||||||
|
/*
|
||||||
|
* This file is part of Stack Wallet.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2023 Cypher Stack
|
||||||
|
* All Rights Reserved.
|
||||||
|
* The code is distributed under GPLv3 license, see LICENSE file for details.
|
||||||
|
* Generated by Cypher Stack on 2023-05-26
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:flutter_svg/svg.dart';
|
||||||
|
import 'package:stackwallet/models/isar/models/contact_entry.dart';
|
||||||
|
import 'package:stackwallet/pages/address_book_views/subviews/add_address_book_entry_view.dart';
|
||||||
|
import 'package:stackwallet/pages/address_book_views/subviews/address_book_filter_view.dart';
|
||||||
|
import 'package:stackwallet/pages_desktop_specific/ordinals/subwidgets/desktop_ordinals_list.dart';
|
||||||
|
import 'package:stackwallet/pages_desktop_specific/address_book_view/subwidgets/desktop_address_book_scaffold.dart';
|
||||||
|
import 'package:stackwallet/pages_desktop_specific/address_book_view/subwidgets/desktop_contact_details.dart';
|
||||||
|
import 'package:stackwallet/providers/global/address_book_service_provider.dart';
|
||||||
|
import 'package:stackwallet/providers/providers.dart';
|
||||||
|
import 'package:stackwallet/providers/ui/address_book_providers/address_book_filter_provider.dart';
|
||||||
|
import 'package:stackwallet/services/mixins/ordinals_interface.dart';
|
||||||
|
import 'package:stackwallet/themes/stack_colors.dart';
|
||||||
|
import 'package:stackwallet/utilities/assets.dart';
|
||||||
|
import 'package:stackwallet/utilities/constants.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/address_book_card.dart';
|
||||||
|
import 'package:stackwallet/widgets/desktop/desktop_app_bar.dart';
|
||||||
|
import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
|
||||||
|
import 'package:stackwallet/widgets/desktop/desktop_scaffold.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/rounded_container.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 DesktopOrdinalsView extends ConsumerStatefulWidget {
|
||||||
|
const DesktopOrdinalsView({
|
||||||
|
super.key,
|
||||||
|
required this.walletId,
|
||||||
|
});
|
||||||
|
|
||||||
|
static const String routeName = "/desktopOrdinalsView";
|
||||||
|
|
||||||
|
final String walletId;
|
||||||
|
|
||||||
|
@override
|
||||||
|
ConsumerState<DesktopOrdinalsView> createState() => _DesktopOrdinals();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DesktopOrdinals extends ConsumerState<DesktopOrdinalsView> {
|
||||||
|
late final TextEditingController searchController;
|
||||||
|
late final FocusNode searchFocusNode;
|
||||||
|
|
||||||
|
String _searchTerm = "";
|
||||||
|
dynamic _manager;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
searchController = TextEditingController();
|
||||||
|
searchFocusNode = FocusNode();
|
||||||
|
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didChangeDependencies() {
|
||||||
|
super.didChangeDependencies();
|
||||||
|
// Set _manager here when the widget's dependencies change
|
||||||
|
_manager = ref.watch(walletsChangeNotifierProvider
|
||||||
|
.select((value) => value.getManager(widget.walletId)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
searchController.dispose();
|
||||||
|
searchFocusNode.dispose();
|
||||||
|
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
debugPrint("BUILD: $runtimeType");
|
||||||
|
|
||||||
|
return DesktopScaffold(
|
||||||
|
appBar: DesktopAppBar(
|
||||||
|
isCompactHeight: true,
|
||||||
|
leading: Row(
|
||||||
|
children: [
|
||||||
|
const SizedBox(
|
||||||
|
width: 24,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
"Ordinals",
|
||||||
|
style: STextStyles.desktopH3(context),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
body: Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
left: 24,
|
||||||
|
right: 24,
|
||||||
|
bottom: 24,
|
||||||
|
),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
left: 16,
|
||||||
|
right: 16,
|
||||||
|
top: 8,
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(
|
||||||
|
Constants.size.circularBorderRadius,
|
||||||
|
),
|
||||||
|
child: TextField(
|
||||||
|
autocorrect: Util.isDesktop ? false : true,
|
||||||
|
enableSuggestions: Util.isDesktop ? false : true,
|
||||||
|
controller: searchController,
|
||||||
|
focusNode: searchFocusNode,
|
||||||
|
onChanged: (value) {
|
||||||
|
setState(() {
|
||||||
|
_searchTerm = value;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
style: STextStyles.field(context),
|
||||||
|
decoration: standardInputDecoration(
|
||||||
|
"Search",
|
||||||
|
searchFocusNode,
|
||||||
|
context,
|
||||||
|
).copyWith(
|
||||||
|
prefixIcon: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 10,
|
||||||
|
vertical: 16,
|
||||||
|
),
|
||||||
|
child: SvgPicture.asset(
|
||||||
|
Assets.svg.search,
|
||||||
|
width: 16,
|
||||||
|
height: 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 = "";
|
||||||
|
_searchTerm = "";
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 16,
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: DesktopOrdinalsList(
|
||||||
|
walletId: widget.walletId,
|
||||||
|
ordinalsFuture: (_manager.wallet as OrdinalsInterface).getOrdinals(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'package:stackwallet/models/ordinal.dart';
|
||||||
|
import 'package:stackwallet/pages_desktop_specific/ordinals/desktop_ordinal_details_view.dart';
|
||||||
|
import 'package:stackwallet/utilities/text_styles.dart';
|
||||||
|
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||||
|
|
||||||
|
class DesktopOrdinalCard extends StatelessWidget {
|
||||||
|
const DesktopOrdinalCard({
|
||||||
|
Key? key,
|
||||||
|
required this.walletId,
|
||||||
|
required this.ordinal,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
final String walletId;
|
||||||
|
final Ordinal ordinal;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return RoundedWhiteContainer(
|
||||||
|
radiusMultiplier: 2,
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pushNamed(
|
||||||
|
DesktopOrdinalDetailsView.routeName,
|
||||||
|
arguments: (walletId: walletId, ordinal: ordinal),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
AspectRatio(
|
||||||
|
aspectRatio: 1,
|
||||||
|
child: Container(
|
||||||
|
color: Colors.red,
|
||||||
|
child: Image.network(
|
||||||
|
ordinal.content, // Use the preview URL as the image source
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
filterQuality: FilterQuality.none, // Set the filter mode to nearest
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
|
Text(
|
||||||
|
'INSC. ${ordinal.inscriptionNumber}', // infer from address associated with utxoTXID
|
||||||
|
style: STextStyles.w500_12(context),
|
||||||
|
),
|
||||||
|
// const Spacer(),
|
||||||
|
// Text(
|
||||||
|
// "ID ${ordinal.inscriptionId}",
|
||||||
|
// style: STextStyles.w500_8(context),
|
||||||
|
// ),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:stackwallet/models/ordinal.dart';
|
||||||
|
|
||||||
|
import 'package:stackwallet/pages_desktop_specific/ordinals/subwidgets/desktop_ordinal_card.dart';
|
||||||
|
|
||||||
|
class DesktopOrdinalsList extends StatelessWidget {
|
||||||
|
const DesktopOrdinalsList({
|
||||||
|
Key? key,
|
||||||
|
required this.walletId,
|
||||||
|
required this.ordinalsFuture,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
final String walletId;
|
||||||
|
final Future<List<Ordinal>> ordinalsFuture;
|
||||||
|
|
||||||
|
get spacing => 2.0;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return FutureBuilder<List<Ordinal>>(
|
||||||
|
future: ordinalsFuture,
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||||
|
return const CircularProgressIndicator();
|
||||||
|
} else if (snapshot.hasError) {
|
||||||
|
return Text('Error: ${snapshot.error}');
|
||||||
|
} else if (snapshot.hasData) {
|
||||||
|
final List<Ordinal> ordinals = snapshot.data!;
|
||||||
|
return GridView.builder(
|
||||||
|
shrinkWrap: true,
|
||||||
|
itemCount: ordinals.length,
|
||||||
|
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||||
|
crossAxisSpacing: spacing as double,
|
||||||
|
mainAxisSpacing: spacing as double,
|
||||||
|
crossAxisCount: 4,
|
||||||
|
childAspectRatio: 6 / 7, // was 3/4, less data displayed now
|
||||||
|
),
|
||||||
|
itemBuilder: (_, i) => DesktopOrdinalCard(
|
||||||
|
walletId: walletId,
|
||||||
|
ordinal: ordinals[i],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return const Text('No data found.');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,7 +12,6 @@ import 'package:flutter/cupertino.dart';
|
||||||
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:isar/isar.dart';
|
import 'package:isar/isar.dart';
|
||||||
import 'package:stackwallet/dto/ordinals/inscription_data.dart';
|
|
||||||
import 'package:stackwallet/models/add_wallet_list_entity/add_wallet_list_entity.dart';
|
import 'package:stackwallet/models/add_wallet_list_entity/add_wallet_list_entity.dart';
|
||||||
import 'package:stackwallet/models/add_wallet_list_entity/sub_classes/eth_token_entity.dart';
|
import 'package:stackwallet/models/add_wallet_list_entity/sub_classes/eth_token_entity.dart';
|
||||||
import 'package:stackwallet/models/buy/response_objects/quote.dart';
|
import 'package:stackwallet/models/buy/response_objects/quote.dart';
|
||||||
|
@ -20,7 +19,7 @@ import 'package:stackwallet/models/exchange/incomplete_exchange.dart';
|
||||||
import 'package:stackwallet/models/exchange/response_objects/trade.dart';
|
import 'package:stackwallet/models/exchange/response_objects/trade.dart';
|
||||||
import 'package:stackwallet/models/isar/models/contact_entry.dart';
|
import 'package:stackwallet/models/isar/models/contact_entry.dart';
|
||||||
import 'package:stackwallet/models/isar/models/isar_models.dart';
|
import 'package:stackwallet/models/isar/models/isar_models.dart';
|
||||||
import 'package:stackwallet/models/ordinal.dart'; // TODO generalize InscriptionData -> Ordinal
|
import 'package:stackwallet/models/ordinal.dart';
|
||||||
import 'package:stackwallet/models/paynym/paynym_account_lite.dart';
|
import 'package:stackwallet/models/paynym/paynym_account_lite.dart';
|
||||||
import 'package:stackwallet/models/send_view_auto_fill_data.dart';
|
import 'package:stackwallet/models/send_view_auto_fill_data.dart';
|
||||||
import 'package:stackwallet/pages/add_wallet_views/add_token_view/add_custom_token_view.dart';
|
import 'package:stackwallet/pages/add_wallet_views/add_token_view/add_custom_token_view.dart';
|
||||||
|
@ -147,6 +146,8 @@ import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub
|
||||||
import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/unlock_wallet_keys_desktop.dart';
|
import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/unlock_wallet_keys_desktop.dart';
|
||||||
import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/wallet_keys_desktop_popup.dart';
|
import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/wallet_keys_desktop_popup.dart';
|
||||||
import 'package:stackwallet/pages_desktop_specific/notifications/desktop_notifications_view.dart';
|
import 'package:stackwallet/pages_desktop_specific/notifications/desktop_notifications_view.dart';
|
||||||
|
import 'package:stackwallet/pages_desktop_specific/ordinals/desktop_ordinal_details_view.dart';
|
||||||
|
import 'package:stackwallet/pages_desktop_specific/ordinals/desktop_ordinals_view.dart';
|
||||||
import 'package:stackwallet/pages_desktop_specific/password/create_password_view.dart';
|
import 'package:stackwallet/pages_desktop_specific/password/create_password_view.dart';
|
||||||
import 'package:stackwallet/pages_desktop_specific/password/delete_password_warning_view.dart';
|
import 'package:stackwallet/pages_desktop_specific/password/delete_password_warning_view.dart';
|
||||||
import 'package:stackwallet/pages_desktop_specific/password/forgot_password_desktop_view.dart';
|
import 'package:stackwallet/pages_desktop_specific/password/forgot_password_desktop_view.dart';
|
||||||
|
@ -423,6 +424,20 @@ class RouteGenerator {
|
||||||
}
|
}
|
||||||
return _routeError("${settings.name} invalid args: ${args.toString()}");
|
return _routeError("${settings.name} invalid args: ${args.toString()}");
|
||||||
|
|
||||||
|
case DesktopOrdinalsView.routeName:
|
||||||
|
if (args is String) {
|
||||||
|
return getRoute(
|
||||||
|
shouldUseMaterialRoute: useMaterialPageRoute,
|
||||||
|
builder: (_) => DesktopOrdinalsView(
|
||||||
|
walletId: args,
|
||||||
|
),
|
||||||
|
settings: RouteSettings(
|
||||||
|
name: settings.name,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return _routeError("${settings.name} invalid args: ${args.toString()}");
|
||||||
|
|
||||||
case OrdinalDetailsView.routeName:
|
case OrdinalDetailsView.routeName:
|
||||||
if (args is ({Ordinal ordinal, String walletId})) {
|
if (args is ({Ordinal ordinal, String walletId})) {
|
||||||
return getRoute(
|
return getRoute(
|
||||||
|
@ -438,6 +453,21 @@ class RouteGenerator {
|
||||||
}
|
}
|
||||||
return _routeError("${settings.name} invalid args: ${args.toString()}");
|
return _routeError("${settings.name} invalid args: ${args.toString()}");
|
||||||
|
|
||||||
|
case DesktopOrdinalDetailsView.routeName:
|
||||||
|
if (args is ({Ordinal ordinal, String walletId})) {
|
||||||
|
return getRoute(
|
||||||
|
shouldUseMaterialRoute: useMaterialPageRoute,
|
||||||
|
builder: (_) => DesktopOrdinalDetailsView(
|
||||||
|
walletId: args.walletId,
|
||||||
|
ordinal: args.ordinal,
|
||||||
|
),
|
||||||
|
settings: RouteSettings(
|
||||||
|
name: settings.name,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return _routeError("${settings.name} invalid args: ${args.toString()}");
|
||||||
|
|
||||||
case OrdinalsFilterView.routeName:
|
case OrdinalsFilterView.routeName:
|
||||||
return getRoute(
|
return getRoute(
|
||||||
shouldUseMaterialRoute: useMaterialPageRoute,
|
shouldUseMaterialRoute: useMaterialPageRoute,
|
||||||
|
|
Loading…
Reference in a new issue