diff --git a/frontend/src/app/components/mempool-block-overview/block-scene.ts b/frontend/src/app/components/mempool-block-overview/block-scene.ts
index 825569100..5e781e429 100644
--- a/frontend/src/app/components/mempool-block-overview/block-scene.ts
+++ b/frontend/src/app/components/mempool-block-overview/block-scene.ts
@@ -90,7 +90,7 @@ export default class BlockScene {
this.updateAll(startTime, direction)
}
- update (add: TransactionStripped[], remove: string[], direction: string = 'left'): void {
+ update (add: TransactionStripped[], remove: string[], direction: string = 'left', resetLayout: boolean = false): void {
const startTime = performance.now()
const removed = this.removeBatch(remove, startTime, direction)
@@ -101,17 +101,25 @@ export default class BlockScene {
})
}, 1000)
- // try to insert new txs directly
- const remaining = []
- add.map(tx => new TxView(tx, this.vertexArray)).sort((a,b) => { return b.feerate - a.feerate }).forEach(tx => {
- if (!this.tryInsertByFee(tx)) {
- remaining.push(tx)
- }
- })
-
- this.placeBatch(remaining)
-
- this.layout.applyGravity()
+ if (resetLayout) {
+ add.forEach(tx => {
+ if (!this.txs[tx.txid]) this.txs[tx.txid] = new TxView(tx, this.vertexArray)
+ })
+ this.layout = new BlockLayout({ width: this.gridWidth, height: this.gridHeight })
+ Object.values(this.txs).sort((a,b) => { return b.feerate - a.feerate }).forEach(tx => {
+ this.place(tx)
+ })
+ } else {
+ // try to insert new txs directly
+ const remaining = []
+ add.map(tx => new TxView(tx, this.vertexArray)).sort((a,b) => { return b.feerate - a.feerate }).forEach(tx => {
+ if (!this.tryInsertByFee(tx)) {
+ remaining.push(tx)
+ }
+ })
+ this.placeBatch(remaining)
+ this.layout.applyGravity()
+ }
this.updateAll(startTime, direction)
}
diff --git a/frontend/src/app/components/mempool-block-overview/mempool-block-overview.component.html b/frontend/src/app/components/mempool-block-overview/mempool-block-overview.component.html
index 275cc8833..6951120d7 100644
--- a/frontend/src/app/components/mempool-block-overview/mempool-block-overview.component.html
+++ b/frontend/src/app/components/mempool-block-overview/mempool-block-overview.component.html
@@ -1,3 +1,6 @@
diff --git a/frontend/src/app/components/mempool-block-overview/mempool-block-overview.component.scss b/frontend/src/app/components/mempool-block-overview/mempool-block-overview.component.scss
index d14af382f..8c3c271d1 100644
--- a/frontend/src/app/components/mempool-block-overview/mempool-block-overview.component.scss
+++ b/frontend/src/app/components/mempool-block-overview/mempool-block-overview.component.scss
@@ -3,6 +3,9 @@
width: 100%;
padding-bottom: 100%;
background: #181b2d;
+ display: flex;
+ justify-content: center;
+ align-items: center;
}
.block-overview {
@@ -13,3 +16,20 @@
bottom: 0;
overflow: hidden;
}
+
+.loader-wrapper {
+ position: absolute;
+ left: 0;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ transition: opacity 500ms 500ms;
+
+ &.hidden {
+ opacity: 0;
+ transition: opacity 500ms;
+ }
+}
diff --git a/frontend/src/app/components/mempool-block-overview/mempool-block-overview.component.ts b/frontend/src/app/components/mempool-block-overview/mempool-block-overview.component.ts
index 4edbbb49e..e75a78896 100644
--- a/frontend/src/app/components/mempool-block-overview/mempool-block-overview.component.ts
+++ b/frontend/src/app/components/mempool-block-overview/mempool-block-overview.component.ts
@@ -1,7 +1,7 @@
import { Component, ElementRef, ViewChild, HostListener, Input, Output, EventEmitter, OnInit, OnDestroy, OnChanges, ChangeDetectionStrategy, NgZone } from '@angular/core';
import { StateService } from 'src/app/services/state.service';
import { MempoolBlockWithTransactions, MempoolBlockDelta, TransactionStripped } from 'src/app/interfaces/websocket.interface';
-import { Observable, Subscription } from 'rxjs';
+import { Observable, Subscription, BehaviorSubject } from 'rxjs';
import { WebsocketService } from 'src/app/services/websocket.service';
import { FastVertexArray } from './fast-vertex-array';
import BlockScene from './block-scene';
@@ -33,6 +33,7 @@ export class MempoolBlockOverviewComponent implements OnInit, OnDestroy, OnChang
selectedTx: TxView | void;
lastBlockHeight: number;
blockIndex: number;
+ isLoading$ = new BehaviorSubject(true);
blockSub: Subscription;
deltaSub: Subscription;
@@ -65,6 +66,8 @@ export class MempoolBlockOverviewComponent implements OnInit, OnDestroy, OnChang
ngOnChanges(changes): void {
if (changes.index) {
+ this.clearBlock(changes.index.currentValue > changes.index.previousValue ? 'right' : 'left')
+ this.isLoading$.next(true)
this.websocketService.startTrackMempoolBlock(changes.index.currentValue);
}
}
@@ -75,6 +78,15 @@ export class MempoolBlockOverviewComponent implements OnInit, OnDestroy, OnChang
this.websocketService.stopTrackMempoolBlock();
}
+ clearBlock(direction): void {
+ if (this.scene) {
+ this.scene.exit(direction)
+ }
+ this.hoverTx = null
+ this.selectedTx = null
+ this.txPreviewEvent.emit(null)
+ }
+
replaceBlock(block: MempoolBlockWithTransactions): void {
if (!this.scene) {
this.scene = new BlockScene({ width: this.displayWidth, height: this.displayHeight, resolution: 75, blockLimit: this.stateService.blockVSize, vertexArray: this.vertexArray })
@@ -82,8 +94,6 @@ export class MempoolBlockOverviewComponent implements OnInit, OnDestroy, OnChang
const blockMined = (this.stateService.latestBlockHeight > this.lastBlockHeight)
if (this.blockIndex != this.index) {
const direction = (this.blockIndex == null || this.index < this.blockIndex) ? 'left' : 'right'
- this.scene.exit(direction)
- this.scene = new BlockScene({ width: this.displayWidth, height: this.displayHeight, resolution: 75, blockLimit: this.stateService.blockVSize, vertexArray: this.vertexArray })
this.scene.enter(block.transactions, direction)
} else {
this.scene.replace(block.transactions, blockMined ? 'right' : 'left')
@@ -91,6 +101,7 @@ export class MempoolBlockOverviewComponent implements OnInit, OnDestroy, OnChang
this.lastBlockHeight = this.stateService.latestBlockHeight
this.blockIndex = this.index
+ this.isLoading$.next(false)
}
updateBlock(delta: MempoolBlockDelta): void {
@@ -105,11 +116,12 @@ export class MempoolBlockOverviewComponent implements OnInit, OnDestroy, OnChang
this.scene = new BlockScene({ width: this.displayWidth, height: this.displayHeight, resolution: 75, blockLimit: this.stateService.blockVSize, vertexArray: this.vertexArray })
this.scene.enter(delta.added, direction)
} else {
- this.scene.update(delta.added, delta.removed, blockMined ? 'right' : 'left')
+ this.scene.update(delta.added, delta.removed, blockMined ? 'right' : 'left', blockMined)
}
this.lastBlockHeight = this.stateService.latestBlockHeight
this.blockIndex = this.index
+ this.isLoading$.next(false)
}
initCanvas (): void {
diff --git a/frontend/src/app/components/mempool-block/mempool-block.component.html b/frontend/src/app/components/mempool-block/mempool-block.component.html
index 9e8502ee5..da1e91f1b 100644
--- a/frontend/src/app/components/mempool-block/mempool-block.component.html
+++ b/frontend/src/app/components/mempool-block/mempool-block.component.html
@@ -68,10 +68,11 @@
-
+
diff --git a/frontend/src/app/components/mempool-block/mempool-block.component.ts b/frontend/src/app/components/mempool-block/mempool-block.component.ts
index bab26eb2e..e20c0b67d 100644
--- a/frontend/src/app/components/mempool-block/mempool-block.component.ts
+++ b/frontend/src/app/components/mempool-block/mempool-block.component.ts
@@ -19,13 +19,16 @@ export class MempoolBlockComponent implements OnInit, OnDestroy {
mempoolBlock$: Observable;
ordinal$: BehaviorSubject = new BehaviorSubject('');
previewTx: TransactionStripped | void;
+ webGlEnabled: boolean;
constructor(
private route: ActivatedRoute,
public stateService: StateService,
private seoService: SeoService,
private websocketService: WebsocketService,
- ) { }
+ ) {
+ this.webGlEnabled = detectWebGL();
+ }
ngOnInit(): void {
this.websocketService.want(['blocks', 'mempool-blocks']);
@@ -81,3 +84,9 @@ export class MempoolBlockComponent implements OnInit, OnDestroy {
this.previewTx = event
}
}
+
+function detectWebGL () {
+ const canvas = document.createElement("canvas");
+ const gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
+ return (gl && gl instanceof WebGLRenderingContext)
+}