Refactored frontend data handling.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
<div class="txBubble" *ngIf="tx">
|
||||
<div class="txBubble" [ngStyle]="txBubbleStyle" *ngIf="txTrackingEnabled && tx">
|
||||
<span class="txBubbleText" ngClass="arrow-{{ arrowPosition }}">
|
||||
<table style="width: 100%;">
|
||||
<tr>
|
||||
@@ -6,8 +6,8 @@
|
||||
<td class="text-right"><a href="https://www.blockstream.info/tx/{{ tx?.txid }}" target="_blank">{{ txIdShort }}</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-left"><b>Fees:</b></td>
|
||||
<td class="text-right">{{ tx?.fee }} BTC</td>
|
||||
<td class="text-left"><b>Fee:</b></td>
|
||||
<td class="text-right">{{ tx?.fee * 100000000 | number }} sats <span *ngIf="conversions">(<span class="green-color">{{ conversions.USD * tx?.fee | currency:'USD':'symbol':'1.2-2' }}</span>)</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-left"><b>Fee per vByte:</b></td>
|
||||
|
||||
@@ -63,3 +63,7 @@
|
||||
.txBubble .arrow-top-left.txBubbleText::after {
|
||||
left: 20%;
|
||||
}
|
||||
|
||||
.green-color {
|
||||
color: #3bcc49;
|
||||
}
|
||||
|
||||
@@ -1,26 +1,144 @@
|
||||
import { Component, OnInit, Input, OnChanges } from '@angular/core';
|
||||
import { ITransaction } from '../blockchain/interfaces';
|
||||
import { Component, OnInit, OnDestroy, HostListener } from '@angular/core';
|
||||
import { ITransaction, IProjectedBlock } from '../blockchain/interfaces';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { ITxTracking, MemPoolService } from '../services/mem-pool.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-tx-bubble',
|
||||
templateUrl: './tx-bubble.component.html',
|
||||
styleUrls: ['./tx-bubble.component.scss']
|
||||
})
|
||||
export class TxBubbleComponent implements OnChanges {
|
||||
@Input() tx: ITransaction | null = null;
|
||||
@Input() txTrackingBlockHeight = 0;
|
||||
@Input() latestBlockHeight = 0;
|
||||
@Input() arrowPosition: 'top' | 'right' | 'bottom' | 'top-right' | 'top-left' = 'top';
|
||||
export class TxBubbleComponent implements OnInit, OnDestroy {
|
||||
tx: ITransaction | null = null;
|
||||
txTrackingBlockHeight = 0;
|
||||
latestBlockHeight = 0;
|
||||
arrowPosition: 'top' | 'right' | 'bottom' | 'top-right' | 'top-left' = 'top';
|
||||
|
||||
txTrackingSubscription: Subscription;
|
||||
projectedBlocksSubscription: Subscription;
|
||||
blocksSubscription: Subscription;
|
||||
|
||||
projectedBlocks: IProjectedBlock[] = [];
|
||||
|
||||
txIdShort = '';
|
||||
confirmations = 0;
|
||||
conversions: any;
|
||||
|
||||
constructor() { }
|
||||
txBubbleStyle: any = {
|
||||
'position': 'absolute',
|
||||
'top': '425px',
|
||||
'visibility': 'hidden',
|
||||
};
|
||||
|
||||
ngOnChanges() {
|
||||
if (this.tx) {
|
||||
this.txIdShort = this.tx.txid.substring(0, 6) + '...' + this.tx.txid.substring(this.tx.txid.length - 6);
|
||||
txTrackingLoading = false;
|
||||
txTrackingEnabled = false;
|
||||
txTrackingTx: ITransaction | null = null;
|
||||
txShowTxNotFound = false;
|
||||
|
||||
txBubbleArrowPosition = 'top';
|
||||
|
||||
@HostListener('window:resize', ['$event'])
|
||||
onResize(event: Event) {
|
||||
this.moveTxBubbleToPosition();
|
||||
}
|
||||
|
||||
constructor(
|
||||
private memPoolService: MemPoolService,
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
this.txTrackingSubscription = this.memPoolService.txTracking$
|
||||
.subscribe((response: ITxTracking) => {
|
||||
this.txTrackingBlockHeight = response.blockHeight;
|
||||
this.txTrackingEnabled = response.enabled;
|
||||
if (response.tx) {
|
||||
this.tx = response.tx;
|
||||
}
|
||||
if (this.txTrackingEnabled) {
|
||||
setTimeout(() => this.moveTxBubbleToPosition());
|
||||
}
|
||||
if (this.txShowTxNotFound) {
|
||||
setTimeout(() => { this.txShowTxNotFound = false; }, 2000);
|
||||
}
|
||||
if (this.tx) {
|
||||
this.txIdShort = this.tx.txid.substring(0, 6) + '...' + this.tx.txid.substring(this.tx.txid.length - 6);
|
||||
}
|
||||
if (this.latestBlockHeight) {
|
||||
this.confirmations = (this.latestBlockHeight - this.txTrackingBlockHeight) + 1;
|
||||
}
|
||||
});
|
||||
|
||||
this.projectedBlocksSubscription = this.memPoolService.projectedBlocks$
|
||||
.subscribe((projectedblocks) => this.projectedBlocks = projectedblocks);
|
||||
|
||||
this.blocksSubscription = this.memPoolService.blocks$
|
||||
.subscribe((block) => {
|
||||
this.latestBlockHeight = block.height;
|
||||
if (this.txTrackingBlockHeight) {
|
||||
this.confirmations = (this.latestBlockHeight - this.txTrackingBlockHeight) + 1;
|
||||
}
|
||||
});
|
||||
|
||||
this.memPoolService.conversions$
|
||||
.subscribe((conversions) => {
|
||||
this.conversions = conversions;
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.projectedBlocksSubscription.unsubscribe();
|
||||
this.txTrackingSubscription.unsubscribe();
|
||||
this.blocksSubscription.unsubscribe();
|
||||
}
|
||||
|
||||
moveTxBubbleToPosition() {
|
||||
let element: HTMLElement | null = null;
|
||||
if (this.txTrackingBlockHeight === 0) {
|
||||
const index = this.projectedBlocks.findIndex((pB) => pB.hasMytx);
|
||||
if (index > -1) {
|
||||
element = document.getElementById('projected-block-' + index);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
element = document.getElementById('bitcoin-block-' + this.txTrackingBlockHeight);
|
||||
}
|
||||
|
||||
this.txBubbleStyle['visibility'] = 'visible';
|
||||
this.txBubbleStyle['position'] = 'absolute';
|
||||
|
||||
if (!element) {
|
||||
if (window.innerWidth <= 768) {
|
||||
this.txBubbleArrowPosition = 'bottom';
|
||||
this.txBubbleStyle['left'] = window.innerWidth / 2 - 50 + 'px';
|
||||
this.txBubbleStyle['bottom'] = '270px';
|
||||
this.txBubbleStyle['top'] = 'inherit';
|
||||
this.txBubbleStyle['position'] = 'fixed';
|
||||
} else {
|
||||
this.txBubbleStyle['left'] = window.innerWidth - 220 + 'px';
|
||||
this.txBubbleArrowPosition = 'right';
|
||||
this.txBubbleStyle['top'] = '425px';
|
||||
}
|
||||
} else {
|
||||
this.txBubbleArrowPosition = 'top';
|
||||
const domRect: DOMRect | ClientRect = element.getBoundingClientRect();
|
||||
this.txBubbleStyle['left'] = domRect.left - 50 + 'px';
|
||||
this.txBubbleStyle['top'] = domRect.top + 140 + window.scrollY + 'px';
|
||||
|
||||
if (domRect.left + 100 > window.innerWidth) {
|
||||
this.txBubbleStyle['left'] = window.innerWidth - 220 + 'px';
|
||||
this.txBubbleArrowPosition = 'right';
|
||||
} else if (domRect.left + 220 > window.innerWidth) {
|
||||
this.txBubbleStyle['left'] = window.innerWidth - 240 + 'px';
|
||||
this.txBubbleArrowPosition = 'top-right';
|
||||
} else {
|
||||
this.txBubbleStyle['left'] = domRect.left + 15 + 'px';
|
||||
}
|
||||
|
||||
if (domRect.left < 86) {
|
||||
this.txBubbleArrowPosition = 'top-left';
|
||||
this.txBubbleStyle['left'] = 125 + 'px';
|
||||
}
|
||||
}
|
||||
this.confirmations = (this.latestBlockHeight - this.txTrackingBlockHeight) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user