Scroll to input/output when clicked in tx diagram

This commit is contained in:
Mononaut
2022-10-04 21:00:46 +00:00
parent 54c44565fb
commit c10ace8fb5
7 changed files with 88 additions and 50 deletions

View File

@@ -20,9 +20,9 @@
<div class="col">
<table class="table table-borderless smaller-text table-sm table-tx-vin">
<tbody>
<ng-template ngFor let-vin let-vindex="index" [ngForOf]="tx['@vinLimit'] ? ((tx.vin.length > rowLimit) ? tx.vin.slice(0, rowLimit - 2) : tx.vin.slice(0, rowLimit)) : tx.vin" [ngForTrackBy]="trackByIndexFn">
<ng-template ngFor let-vin let-vindex="index" [ngForOf]="tx['@vinLimit'] ? ((tx.vin.length > inputRowLimit) ? tx.vin.slice(0, inputRowLimit - 2) : tx.vin.slice(0, inputRowLimit)) : tx.vin" [ngForTrackBy]="trackByIndexFn">
<tr [ngClass]="{
'assetBox': assetsMinimal && vin.prevout && assetsMinimal[vin.prevout.asset] && !vin.is_coinbase && vin.prevout.scriptpubkey_address && tx._unblinded,
'assetBox': (assetsMinimal && vin.prevout && assetsMinimal[vin.prevout.asset] && !vin.is_coinbase && vin.prevout.scriptpubkey_address && tx._unblinded) || inputIndex === vindex,
'highlight': vin.prevout?.scriptpubkey_address === this.address && this.address !== ''
}">
<td class="arrow-td">
@@ -146,7 +146,7 @@
</td>
</tr>
</ng-template>
<tr *ngIf="tx.vin.length > rowLimit && tx['@vinLimit']">
<tr *ngIf="tx.vin.length > inputRowLimit && tx['@vinLimit']">
<td colspan="3" class="text-center">
<button class="btn btn-sm btn-primary mt-2" (click)="loadMoreInputs(tx);"><span i18n="show-all">Show all</span> ({{ tx.vin.length }})</button>
</td>
@@ -158,7 +158,7 @@
<div class="col mobile-bottomcol">
<table class="table table-borderless smaller-text table-sm table-tx-vout">
<tbody>
<ng-template ngFor let-vout let-vindex="index" [ngForOf]="tx['@voutLimit'] && !outputIndex ? ((tx.vout.length > rowLimit) ? tx.vout.slice(0, rowLimit - 2) : tx.vout.slice(0, rowLimit)) : tx.vout" [ngForTrackBy]="trackByIndexFn">
<ng-template ngFor let-vout let-vindex="index" [ngForOf]="tx['@voutLimit'] ? ((tx.vout.length > outputRowLimit) ? tx.vout.slice(0, outputRowLimit - 2) : tx.vout.slice(0, outputRowLimit)) : tx.vout" [ngForTrackBy]="trackByIndexFn">
<tr [ngClass]="{
'assetBox': assetsMinimal && assetsMinimal[vout.asset] && vout.scriptpubkey_address && tx.vin && !tx.vin[0].is_coinbase && tx._unblinded || outputIndex === vindex,
'highlight': vout.scriptpubkey_address === this.address && this.address !== ''
@@ -257,7 +257,7 @@
</td>
</tr>
</ng-template>
<tr *ngIf="tx.vout.length > rowLimit && tx['@voutLimit'] && !outputIndex">
<tr *ngIf="tx.vout.length > outputRowLimit && tx['@voutLimit']">
<td colspan="3" class="text-center">
<button class="btn btn-sm btn-primary mt-2" (click)="tx['@voutLimit'] = false;"><span i18n="show-all">Show all</span> ({{ tx.vout.length }})</button>
</td>

View File

@@ -24,6 +24,7 @@ export class TransactionsListComponent implements OnInit, OnChanges {
@Input() transactionPage = false;
@Input() errorUnblinded = false;
@Input() paginated = false;
@Input() inputIndex: number;
@Input() outputIndex: number;
@Input() address: string = '';
@Input() rowLimit = 12;
@@ -37,6 +38,8 @@ export class TransactionsListComponent implements OnInit, OnChanges {
showDetails$ = new BehaviorSubject<boolean>(false);
assetsMinimal: any;
transactionsLength: number = 0;
inputRowLimit: number = 12;
outputRowLimit: number = 12;
constructor(
public stateService: StateService,
@@ -97,50 +100,57 @@ export class TransactionsListComponent implements OnInit, OnChanges {
).subscribe(() => this.ref.markForCheck());
}
ngOnChanges(): void {
if (!this.transactions || !this.transactions.length) {
return;
ngOnChanges(changes): void {
if (changes.inputIndex || changes.outputIndex || changes.rowLimit) {
this.inputRowLimit = Math.max(this.rowLimit, (this.inputIndex || 0) + 3);
this.outputRowLimit = Math.max(this.rowLimit, (this.outputIndex || 0) + 3);
if (this.inputIndex || this.outputIndex) {
setTimeout(() => {
const assetBoxElements = document.getElementsByClassName('assetBox');
if (assetBoxElements && assetBoxElements[0]) {
assetBoxElements[0].scrollIntoView({block: "center"});
}
}, 10);
}
}
this.transactionsLength = this.transactions.length;
if (this.outputIndex) {
setTimeout(() => {
const assetBoxElements = document.getElementsByClassName('assetBox');
if (assetBoxElements && assetBoxElements[0]) {
assetBoxElements[0].scrollIntoView();
}
}, 10);
}
this.transactions.forEach((tx) => {
tx['@voutLimit'] = true;
tx['@vinLimit'] = true;
if (tx['addressValue'] !== undefined) {
if (changes.transactions || changes.address) {
if (!this.transactions || !this.transactions.length) {
return;
}
if (this.address) {
const addressIn = tx.vout
.filter((v: Vout) => v.scriptpubkey_address === this.address)
.map((v: Vout) => v.value || 0)
.reduce((a: number, b: number) => a + b, 0);
this.transactionsLength = this.transactions.length;
const addressOut = tx.vin
.filter((v: Vin) => v.prevout && v.prevout.scriptpubkey_address === this.address)
.map((v: Vin) => v.prevout.value || 0)
.reduce((a: number, b: number) => a + b, 0);
tx['addressValue'] = addressIn - addressOut;
}
});
const txIds = this.transactions.filter((tx) => !tx._outspends).map((tx) => tx.txid);
if (txIds.length) {
this.refreshOutspends$.next(txIds);
}
if (this.stateService.env.LIGHTNING) {
const txIds = this.transactions.filter((tx) => !tx._channels).map((tx) => tx.txid);
this.transactions.forEach((tx) => {
tx['@voutLimit'] = true;
tx['@vinLimit'] = true;
if (tx['addressValue'] !== undefined) {
return;
}
if (this.address) {
const addressIn = tx.vout
.filter((v: Vout) => v.scriptpubkey_address === this.address)
.map((v: Vout) => v.value || 0)
.reduce((a: number, b: number) => a + b, 0);
const addressOut = tx.vin
.filter((v: Vin) => v.prevout && v.prevout.scriptpubkey_address === this.address)
.map((v: Vin) => v.prevout.value || 0)
.reduce((a: number, b: number) => a + b, 0);
tx['addressValue'] = addressIn - addressOut;
}
});
const txIds = this.transactions.filter((tx) => !tx._outspends).map((tx) => tx.txid);
if (txIds.length) {
this.refreshChannels$.next(txIds);
this.refreshOutspends$.next(txIds);
}
if (this.stateService.env.LIGHTNING) {
const txIds = this.transactions.filter((tx) => !tx._channels).map((tx) => tx.txid);
if (txIds.length) {
this.refreshChannels$.next(txIds);
}
}
}
}