mirror of
https://github.com/mempool/mempool.git
synced 2025-04-27 12:25:43 +02:00
Reversible mempool block visualization
This commit is contained in:
parent
03c6a7c54f
commit
135fbfc4f3
@ -1,4 +1,4 @@
|
|||||||
import { Component, ElementRef, ViewChild, HostListener, Input, Output, EventEmitter, NgZone, AfterViewInit, OnDestroy } from '@angular/core';
|
import { Component, ElementRef, ViewChild, HostListener, Input, Output, EventEmitter, NgZone, AfterViewInit, OnDestroy, OnChanges } from '@angular/core';
|
||||||
import { TransactionStripped } from '../../interfaces/websocket.interface';
|
import { TransactionStripped } from '../../interfaces/websocket.interface';
|
||||||
import { FastVertexArray } from './fast-vertex-array';
|
import { FastVertexArray } from './fast-vertex-array';
|
||||||
import BlockScene from './block-scene';
|
import BlockScene from './block-scene';
|
||||||
@ -11,7 +11,7 @@ import { Position } from './sprite-types';
|
|||||||
templateUrl: './block-overview-graph.component.html',
|
templateUrl: './block-overview-graph.component.html',
|
||||||
styleUrls: ['./block-overview-graph.component.scss'],
|
styleUrls: ['./block-overview-graph.component.scss'],
|
||||||
})
|
})
|
||||||
export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy {
|
export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, OnChanges {
|
||||||
@Input() isLoading: boolean;
|
@Input() isLoading: boolean;
|
||||||
@Input() resolution: number;
|
@Input() resolution: number;
|
||||||
@Input() blockLimit: number;
|
@Input() blockLimit: number;
|
||||||
@ -57,6 +57,14 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy {
|
|||||||
this.resizeCanvas();
|
this.resizeCanvas();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngOnChanges(changes): void {
|
||||||
|
if (changes.orientation || changes.flip) {
|
||||||
|
if (this.scene) {
|
||||||
|
this.scene.setOrientation(this.orientation, this.flip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
if (this.animationFrameRequest) {
|
if (this.animationFrameRequest) {
|
||||||
cancelAnimationFrame(this.animationFrameRequest);
|
cancelAnimationFrame(this.animationFrameRequest);
|
||||||
|
@ -42,6 +42,24 @@ export default class BlockScene {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setOrientation(orientation: string, flip: boolean): void {
|
||||||
|
this.orientation = orientation;
|
||||||
|
this.flip = flip;
|
||||||
|
this.dirty = true;
|
||||||
|
const startTime = performance.now();
|
||||||
|
Object.values(this.txs).forEach(txView => {
|
||||||
|
this.saveGridToScreenPosition(txView);
|
||||||
|
this.applyTxUpdate(txView, {
|
||||||
|
display: {
|
||||||
|
position: txView.screenPosition,
|
||||||
|
color: txView.getColor()
|
||||||
|
},
|
||||||
|
duration: 0
|
||||||
|
});
|
||||||
|
this.setTxOnScreen(txView, startTime, 0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Destroy the current layout and clean up graphics sprites without any exit animation
|
// Destroy the current layout and clean up graphics sprites without any exit animation
|
||||||
destroy(): void {
|
destroy(): void {
|
||||||
Object.values(this.txs).forEach(tx => tx.destroy());
|
Object.values(this.txs).forEach(tx => tx.destroy());
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
[isLoading]="isLoading$ | async"
|
[isLoading]="isLoading$ | async"
|
||||||
[resolution]="75"
|
[resolution]="75"
|
||||||
[blockLimit]="stateService.blockVSize"
|
[blockLimit]="stateService.blockVSize"
|
||||||
[orientation]="'left'"
|
[orientation]="timeLtr ? 'right' : 'left'"
|
||||||
[flip]="true"
|
[flip]="true"
|
||||||
(txClickEvent)="onTxClick($event)"
|
(txClickEvent)="onTxClick($event)"
|
||||||
></app-block-overview-graph>
|
></app-block-overview-graph>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Component, ComponentRef, ViewChild, HostListener, Input, Output, EventEmitter,
|
import { Component, ComponentRef, ViewChild, HostListener, Input, Output, EventEmitter,
|
||||||
OnDestroy, OnChanges, ChangeDetectionStrategy, AfterViewInit } from '@angular/core';
|
OnInit, OnDestroy, OnChanges, ChangeDetectionStrategy, ChangeDetectorRef, AfterViewInit } from '@angular/core';
|
||||||
import { StateService } from '../../services/state.service';
|
import { StateService } from '../../services/state.service';
|
||||||
import { MempoolBlockDelta, TransactionStripped } from '../../interfaces/websocket.interface';
|
import { MempoolBlockDelta, TransactionStripped } from '../../interfaces/websocket.interface';
|
||||||
import { BlockOverviewGraphComponent } from '../../components/block-overview-graph/block-overview-graph.component';
|
import { BlockOverviewGraphComponent } from '../../components/block-overview-graph/block-overview-graph.component';
|
||||||
@ -14,7 +14,7 @@ import { Router } from '@angular/router';
|
|||||||
templateUrl: './mempool-block-overview.component.html',
|
templateUrl: './mempool-block-overview.component.html',
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class MempoolBlockOverviewComponent implements OnDestroy, OnChanges, AfterViewInit {
|
export class MempoolBlockOverviewComponent implements OnInit, OnDestroy, OnChanges, AfterViewInit {
|
||||||
@Input() index: number;
|
@Input() index: number;
|
||||||
@Output() txPreviewEvent = new EventEmitter<TransactionStripped | void>();
|
@Output() txPreviewEvent = new EventEmitter<TransactionStripped | void>();
|
||||||
|
|
||||||
@ -23,6 +23,10 @@ export class MempoolBlockOverviewComponent implements OnDestroy, OnChanges, Afte
|
|||||||
lastBlockHeight: number;
|
lastBlockHeight: number;
|
||||||
blockIndex: number;
|
blockIndex: number;
|
||||||
isLoading$ = new BehaviorSubject<boolean>(true);
|
isLoading$ = new BehaviorSubject<boolean>(true);
|
||||||
|
timeLtrSubscription: Subscription;
|
||||||
|
timeLtr: boolean;
|
||||||
|
chainDirection: string = 'right';
|
||||||
|
poolDirection: string = 'left';
|
||||||
|
|
||||||
blockSub: Subscription;
|
blockSub: Subscription;
|
||||||
deltaSub: Subscription;
|
deltaSub: Subscription;
|
||||||
@ -31,8 +35,18 @@ export class MempoolBlockOverviewComponent implements OnDestroy, OnChanges, Afte
|
|||||||
public stateService: StateService,
|
public stateService: StateService,
|
||||||
private websocketService: WebsocketService,
|
private websocketService: WebsocketService,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
|
private cd: ChangeDetectorRef,
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.timeLtrSubscription = this.stateService.timeLtr.subscribe((ltr) => {
|
||||||
|
this.timeLtr = !!ltr;
|
||||||
|
this.chainDirection = ltr ? 'left' : 'right';
|
||||||
|
this.poolDirection = ltr ? 'right' : 'left';
|
||||||
|
this.cd.markForCheck();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
ngAfterViewInit(): void {
|
ngAfterViewInit(): void {
|
||||||
this.blockSub = merge(
|
this.blockSub = merge(
|
||||||
of(true),
|
of(true),
|
||||||
@ -50,7 +64,7 @@ export class MempoolBlockOverviewComponent implements OnDestroy, OnChanges, Afte
|
|||||||
ngOnChanges(changes): void {
|
ngOnChanges(changes): void {
|
||||||
if (changes.index) {
|
if (changes.index) {
|
||||||
if (this.blockGraph) {
|
if (this.blockGraph) {
|
||||||
this.blockGraph.clear(changes.index.currentValue > changes.index.previousValue ? 'right' : 'left');
|
this.blockGraph.clear(changes.index.currentValue > changes.index.previousValue ? this.chainDirection : this.poolDirection);
|
||||||
}
|
}
|
||||||
this.isLoading$.next(true);
|
this.isLoading$.next(true);
|
||||||
this.websocketService.startTrackMempoolBlock(changes.index.currentValue);
|
this.websocketService.startTrackMempoolBlock(changes.index.currentValue);
|
||||||
@ -60,16 +74,17 @@ export class MempoolBlockOverviewComponent implements OnDestroy, OnChanges, Afte
|
|||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
this.blockSub.unsubscribe();
|
this.blockSub.unsubscribe();
|
||||||
this.deltaSub.unsubscribe();
|
this.deltaSub.unsubscribe();
|
||||||
|
this.timeLtrSubscription.unsubscribe();
|
||||||
this.websocketService.stopTrackMempoolBlock();
|
this.websocketService.stopTrackMempoolBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
replaceBlock(transactionsStripped: TransactionStripped[]): void {
|
replaceBlock(transactionsStripped: TransactionStripped[]): void {
|
||||||
const blockMined = (this.stateService.latestBlockHeight > this.lastBlockHeight);
|
const blockMined = (this.stateService.latestBlockHeight > this.lastBlockHeight);
|
||||||
if (this.blockIndex !== this.index) {
|
if (this.blockIndex !== this.index) {
|
||||||
const direction = (this.blockIndex == null || this.index < this.blockIndex) ? 'left' : 'right';
|
const direction = (this.blockIndex == null || this.index < this.blockIndex) ? this.poolDirection : this.chainDirection;
|
||||||
this.blockGraph.enter(transactionsStripped, direction);
|
this.blockGraph.enter(transactionsStripped, direction);
|
||||||
} else {
|
} else {
|
||||||
this.blockGraph.replace(transactionsStripped, blockMined ? 'right' : 'left');
|
this.blockGraph.replace(transactionsStripped, blockMined ? this.chainDirection : this.poolDirection);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.lastBlockHeight = this.stateService.latestBlockHeight;
|
this.lastBlockHeight = this.stateService.latestBlockHeight;
|
||||||
@ -81,10 +96,10 @@ export class MempoolBlockOverviewComponent implements OnDestroy, OnChanges, Afte
|
|||||||
const blockMined = (this.stateService.latestBlockHeight > this.lastBlockHeight);
|
const blockMined = (this.stateService.latestBlockHeight > this.lastBlockHeight);
|
||||||
|
|
||||||
if (this.blockIndex !== this.index) {
|
if (this.blockIndex !== this.index) {
|
||||||
const direction = (this.blockIndex == null || this.index < this.blockIndex) ? 'left' : 'right';
|
const direction = (this.blockIndex == null || this.index < this.blockIndex) ? this.poolDirection : this.chainDirection;
|
||||||
this.blockGraph.replace(delta.added, direction);
|
this.blockGraph.replace(delta.added, direction);
|
||||||
} else {
|
} else {
|
||||||
this.blockGraph.update(delta.added, delta.removed, blockMined ? 'right' : 'left', blockMined);
|
this.blockGraph.update(delta.added, delta.removed, blockMined ? this.chainDirection : this.poolDirection, blockMined);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.lastBlockHeight = this.stateService.latestBlockHeight;
|
this.lastBlockHeight = this.stateService.latestBlockHeight;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user