WIP desktop ordinal details view

This commit is contained in:
julian 2023-07-21 19:52:43 -06:00
parent 6c6c9c8325
commit e559ee1cc5
4 changed files with 213 additions and 161 deletions

View file

@ -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'
' }';
}
}

View file

@ -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 {'

View file

@ -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),
);
},

View file

@ -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
}
},
),
),
],
),
],
);
}
}