mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-11-17 01:37:54 +00:00
WIP desktop ordinal details view
This commit is contained in:
parent
6c6c9c8325
commit
e559ee1cc5
4 changed files with 213 additions and 161 deletions
|
@ -50,4 +50,24 @@ class InscriptionData {
|
|||
offset: json['offset'] as int,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'InscriptionData {'
|
||||
' inscriptionId: $inscriptionId,'
|
||||
' inscriptionNumber: $inscriptionNumber,'
|
||||
' address: $address,'
|
||||
' preview: $preview,'
|
||||
' content: $content,'
|
||||
' contentLength: $contentLength,'
|
||||
' contentType: $contentType,'
|
||||
' contentBody: $contentBody,'
|
||||
' timestamp: $timestamp,'
|
||||
' genesisTransaction: $genesisTransaction,'
|
||||
' location: $location,'
|
||||
' output: $output,'
|
||||
' outputValue: $outputValue,'
|
||||
' offset: $offset'
|
||||
' }';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import 'package:isar/isar.dart';
|
||||
import 'package:stackwallet/db/isar/main_db.dart';
|
||||
import 'package:stackwallet/dto/ordinals/inscription_data.dart';
|
||||
import 'package:stackwallet/models/isar/models/isar_models.dart';
|
||||
|
||||
part 'ordinal.g.dart';
|
||||
|
||||
|
@ -62,6 +64,17 @@ class Ordinal {
|
|||
);
|
||||
}
|
||||
|
||||
UTXO? getUTXO(MainDB db) {
|
||||
return db.isar.utxos
|
||||
.where()
|
||||
.walletIdEqualTo(walletId)
|
||||
.filter()
|
||||
.txidEqualTo(utxoTXID)
|
||||
.and()
|
||||
.voutEqualTo(utxoVOUT)
|
||||
.findFirstSync();
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Ordinal {'
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:stackwallet/models/isar/ordinal.dart';
|
||||
import 'package:stackwallet/pages/ordinals/ordinal_details_view.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/ordinals/desktop_ordinal_details_view.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/util.dart';
|
||||
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||
|
||||
class OrdinalCard extends StatelessWidget {
|
||||
|
@ -21,7 +23,9 @@ class OrdinalCard extends StatelessWidget {
|
|||
radiusMultiplier: 2,
|
||||
onPressed: () {
|
||||
Navigator.of(context).pushNamed(
|
||||
OrdinalDetailsView.routeName,
|
||||
Util.isDesktop
|
||||
? DesktopOrdinalDetailsView.routeName
|
||||
: OrdinalDetailsView.routeName,
|
||||
arguments: (walletId: walletId, ordinal: ordinal),
|
||||
);
|
||||
},
|
||||
|
|
|
@ -2,12 +2,20 @@ import 'dart:async';
|
|||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:stackwallet/models/isar/models/blockchain_data/utxo.dart';
|
||||
import 'package:stackwallet/models/isar/ordinal.dart';
|
||||
import 'package:stackwallet/notifications/show_flush_bar.dart';
|
||||
import 'package:stackwallet/pages/ordinals/widgets/dialogs.dart';
|
||||
import 'package:stackwallet/providers/db/main_db_provider.dart';
|
||||
import 'package:stackwallet/providers/global/wallets_provider.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/amount/amount.dart';
|
||||
import 'package:stackwallet/utilities/amount/amount_formatter.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/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||
import 'package:stackwallet/widgets/desktop/desktop_app_bar.dart';
|
||||
|
@ -16,7 +24,7 @@ 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 {
|
||||
class DesktopOrdinalDetailsView extends ConsumerStatefulWidget {
|
||||
const DesktopOrdinalDetailsView({
|
||||
Key? key,
|
||||
required this.walletId,
|
||||
|
@ -29,15 +37,27 @@ class DesktopOrdinalDetailsView extends StatefulWidget {
|
|||
static const routeName = "/desktopOrdinalDetailsView";
|
||||
|
||||
@override
|
||||
State<DesktopOrdinalDetailsView> createState() =>
|
||||
ConsumerState<DesktopOrdinalDetailsView> createState() =>
|
||||
_DesktopOrdinalDetailsViewState();
|
||||
}
|
||||
|
||||
class _DesktopOrdinalDetailsViewState extends State<DesktopOrdinalDetailsView> {
|
||||
class _DesktopOrdinalDetailsViewState
|
||||
extends ConsumerState<DesktopOrdinalDetailsView> {
|
||||
static const _spacing = 12.0;
|
||||
|
||||
late final UTXO? utxo;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
utxo = widget.ordinal.getUTXO(ref.read(mainDBProvider));
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final coin = ref.watch(walletsChangeNotifierProvider
|
||||
.select((value) => value.getManager(widget.walletId).coin));
|
||||
|
||||
return DesktopScaffold(
|
||||
appBar: DesktopAppBar(
|
||||
background: Theme.of(context).extension<StackColors>()!.popupBG,
|
||||
|
@ -67,18 +87,8 @@ class _DesktopOrdinalDetailsViewState extends State<DesktopOrdinalDetailsView> {
|
|||
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",
|
||||
"Ordinal details",
|
||||
style: STextStyles.desktopH3(context),
|
||||
),
|
||||
],
|
||||
|
@ -87,62 +97,161 @@ class _DesktopOrdinalDetailsViewState extends State<DesktopOrdinalDetailsView> {
|
|||
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,
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
left: 24,
|
||||
top: 24,
|
||||
right: 24,
|
||||
),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 300,
|
||||
height: 300,
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(
|
||||
Constants.size.circularBorderRadius,
|
||||
),
|
||||
child: _OrdinalImageGroup(
|
||||
ordinal: widget.ordinal,
|
||||
walletId: widget.walletId,
|
||||
child: Image.network(
|
||||
widget.ordinal
|
||||
.content, // Use the preview URL as the image source
|
||||
fit: BoxFit.cover,
|
||||
filterQuality:
|
||||
FilterQuality.none, // Set the filter mode to nearest
|
||||
),
|
||||
),
|
||||
_DetailsItemWCopy(
|
||||
title: "Inscription number",
|
||||
data: widget.ordinal.inscriptionNumber.toString(),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 16,
|
||||
),
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Column(
|
||||
children: [
|
||||
RoundedWhiteContainer(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"INSC. ${widget.ordinal.inscriptionNumber}",
|
||||
style: STextStyles.w600_20(context),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 16,
|
||||
),
|
||||
PrimaryButton(
|
||||
width: 150,
|
||||
label: "Send",
|
||||
icon: SvgPicture.asset(
|
||||
Assets.svg.send,
|
||||
width: 18,
|
||||
height: 18,
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.buttonTextPrimary,
|
||||
),
|
||||
buttonHeight: ButtonHeight.l,
|
||||
iconSpacing: 8,
|
||||
onPressed: () async {
|
||||
final response = await showDialog<String?>(
|
||||
context: context,
|
||||
builder: (_) =>
|
||||
const SendOrdinalUnfreezeDialog(),
|
||||
);
|
||||
if (response == "unfreeze") {
|
||||
// TODO: unfreeze and go to send ord screen
|
||||
}
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
width: 16,
|
||||
),
|
||||
SecondaryButton(
|
||||
width: 150,
|
||||
label: "Download",
|
||||
icon: SvgPicture.asset(
|
||||
Assets.svg.arrowDown,
|
||||
width: 13,
|
||||
height: 18,
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.buttonTextSecondary,
|
||||
),
|
||||
buttonHeight: ButtonHeight.l,
|
||||
iconSpacing: 8,
|
||||
onPressed: () {
|
||||
// TODO: save and download image to device
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 16,
|
||||
),
|
||||
_DetailsItemWCopy(
|
||||
title: "Inscription number",
|
||||
data: widget.ordinal.inscriptionNumber.toString(),
|
||||
),
|
||||
const SizedBox(
|
||||
height: _spacing,
|
||||
),
|
||||
_DetailsItemWCopy(
|
||||
title: "Inscription ID",
|
||||
data: widget.ordinal.inscriptionId,
|
||||
),
|
||||
const SizedBox(
|
||||
height: _spacing,
|
||||
),
|
||||
// todo: add utxo status
|
||||
const SizedBox(
|
||||
height: _spacing,
|
||||
),
|
||||
_DetailsItemWCopy(
|
||||
title: "Amount",
|
||||
data: utxo == null
|
||||
? "ERROR"
|
||||
: ref.watch(pAmountFormatter(coin)).format(
|
||||
Amount(
|
||||
rawValue: BigInt.from(utxo!.value),
|
||||
fractionDigits: coin.decimals,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: _spacing,
|
||||
),
|
||||
_DetailsItemWCopy(
|
||||
title: "Owner address",
|
||||
data: utxo?.address ?? "ERROR",
|
||||
),
|
||||
const SizedBox(
|
||||
height: _spacing,
|
||||
),
|
||||
_DetailsItemWCopy(
|
||||
title: "Transaction ID",
|
||||
data: widget.ordinal.utxoTXID,
|
||||
),
|
||||
const SizedBox(
|
||||
height: _spacing,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
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,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -206,97 +315,3 @@ class _DetailsItemWCopy extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue