mirror of
https://github.com/mempool/mempool.git
synced 2025-03-26 17:51:45 +01:00
multiblock interactivity
This commit is contained in:
parent
f7422f29dc
commit
580ac889df
@ -553,7 +553,7 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On
|
||||
x: cssX,
|
||||
y: cssY
|
||||
};
|
||||
const selected = this.scene.getTxAt({ x, y });
|
||||
const selected = this.scene.getTxAt({ x, y: this.displayHeight - y });
|
||||
const currentPreview = this.selectedTx || this.hoverTx;
|
||||
|
||||
if (selected !== currentPreview) {
|
||||
@ -627,7 +627,7 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On
|
||||
if (this.scene) {
|
||||
const x = cssX * window.devicePixelRatio;
|
||||
const y = cssY * window.devicePixelRatio;
|
||||
const selected = this.scene.getTxAt({ x, y });
|
||||
const selected = this.scene.getTxAt({ x, y: this.displayHeight - y });
|
||||
if (selected && selected.txid) {
|
||||
this.txClickEvent.emit({ tx: selected, keyModifier });
|
||||
}
|
||||
|
@ -228,7 +228,11 @@ export default class BlockScene {
|
||||
getTxAt(position: Position): TxView | void {
|
||||
if (this.layout) {
|
||||
const gridPosition = this.screenToGrid(position);
|
||||
return this.layout.getTx(gridPosition);
|
||||
if (gridPosition.x >= 0 && gridPosition.x < this.gridWidth && gridPosition.y >= 0 && gridPosition.y < this.gridHeight) {
|
||||
return this.layout.getTx(gridPosition);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@ -465,7 +469,7 @@ export default class BlockScene {
|
||||
|
||||
private screenToGrid(position: Position): Position {
|
||||
let x = position.x - this.x;
|
||||
let y = this.height - (position.y - this.y);
|
||||
let y = position.y - this.y;
|
||||
let t;
|
||||
|
||||
switch (this.orientation) {
|
||||
|
@ -523,6 +523,141 @@ export class BlockOverviewMultiComponent implements AfterViewInit, OnDestroy, On
|
||||
}
|
||||
}
|
||||
|
||||
@HostListener('document:click', ['$event'])
|
||||
clickAway(event) {
|
||||
if (!this.elRef.nativeElement.contains(event.target)) {
|
||||
const currentPreview = this.selectedTx || this.hoverTx;
|
||||
if (currentPreview) {
|
||||
for (const scene of this.scenes) {
|
||||
if (scene) {
|
||||
scene.setHover(currentPreview, false);
|
||||
}
|
||||
}
|
||||
this.start();
|
||||
}
|
||||
this.hoverTx = null;
|
||||
this.selectedTx = null;
|
||||
this.onTxHover(null);
|
||||
}
|
||||
}
|
||||
|
||||
@HostListener('pointerup', ['$event'])
|
||||
onClick(event) {
|
||||
if (!this.canvas) {
|
||||
return;
|
||||
}
|
||||
if (event.target === this.canvas.nativeElement && event.pointerType === 'touch') {
|
||||
this.setPreviewTx(event.offsetX, event.offsetY, true);
|
||||
} else if (event.target === this.canvas.nativeElement) {
|
||||
const keyMod = event.shiftKey || event.ctrlKey || event.metaKey;
|
||||
const middleClick = event.which === 2 || event.button === 1;
|
||||
this.onTxClick(event.offsetX, event.offsetY, keyMod || middleClick);
|
||||
}
|
||||
}
|
||||
|
||||
@HostListener('pointermove', ['$event'])
|
||||
onPointerMove(event) {
|
||||
if (!this.canvas) {
|
||||
return;
|
||||
}
|
||||
if (event.target === this.canvas.nativeElement) {
|
||||
this.setPreviewTx(event.offsetX, event.offsetY, false);
|
||||
} else {
|
||||
this.onPointerLeave(event);
|
||||
}
|
||||
}
|
||||
|
||||
@HostListener('pointerleave', ['$event'])
|
||||
onPointerLeave(event) {
|
||||
if (event.pointerType !== 'touch') {
|
||||
this.setPreviewTx(-1, -1, true);
|
||||
}
|
||||
}
|
||||
|
||||
setPreviewTx(cssX: number, cssY: number, clicked: boolean = false) {
|
||||
const x = cssX * window.devicePixelRatio;
|
||||
const y = cssY * window.devicePixelRatio;
|
||||
if (!this.selectedTx || clicked) {
|
||||
this.tooltipPosition = {
|
||||
x: cssX,
|
||||
y: cssY
|
||||
};
|
||||
const currentPreview = this.selectedTx || this.hoverTx;
|
||||
let selected;
|
||||
for (const scene of this.scenes) {
|
||||
if (scene) {
|
||||
selected = scene.getTxAt({ x, y: this.displayHeight - y });
|
||||
if (selected) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (selected !== currentPreview) {
|
||||
if (currentPreview) {
|
||||
for (const scene of this.scenes) {
|
||||
if (scene) {
|
||||
scene.setHover(currentPreview, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.start();
|
||||
}
|
||||
if (selected) {
|
||||
for (const scene of this.scenes) {
|
||||
if (scene) {
|
||||
scene.setHover(selected, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.start();
|
||||
if (clicked) {
|
||||
this.selectedTx = selected;
|
||||
} else {
|
||||
this.hoverTx = selected;
|
||||
this.onTxHover(this.hoverTx ? this.hoverTx.txid : null);
|
||||
}
|
||||
} else {
|
||||
if (clicked) {
|
||||
this.selectedTx = null;
|
||||
}
|
||||
this.hoverTx = null;
|
||||
this.onTxHover(null);
|
||||
}
|
||||
} else if (clicked) {
|
||||
if (selected === this.selectedTx) {
|
||||
this.hoverTx = this.selectedTx;
|
||||
this.selectedTx = null;
|
||||
this.onTxHover(this.hoverTx ? this.hoverTx.txid : null);
|
||||
} else {
|
||||
this.selectedTx = selected;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateSearchHighlight(): void {
|
||||
if (this.highlightTx && this.highlightTx.txid !== this.searchText) {
|
||||
for (const scene of this.scenes) {
|
||||
if (scene) {
|
||||
scene.setHighlight(this.highlightTx, false);
|
||||
}
|
||||
}
|
||||
this.start();
|
||||
} else if (this.searchText && this.searchText.length === 64) {
|
||||
for (const scene of this.scenes) {
|
||||
if (scene) {
|
||||
const highlightTx = scene.txs[this.searchText];
|
||||
if (highlightTx) {
|
||||
scene.setHighlight(highlightTx, true);
|
||||
this.highlightTx = highlightTx;
|
||||
this.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setHighlightingEnabled(enabled: boolean): void {
|
||||
for (const scene of this.scenes) {
|
||||
scene.setHighlighting(enabled);
|
||||
@ -530,6 +665,24 @@ export class BlockOverviewMultiComponent implements AfterViewInit, OnDestroy, On
|
||||
this.start();
|
||||
}
|
||||
|
||||
onTxClick(cssX: number, cssY: number, keyModifier: boolean = false) {
|
||||
for (const scene of this.scenes) {
|
||||
if (scene) {
|
||||
const x = cssX * window.devicePixelRatio;
|
||||
const y = cssY * window.devicePixelRatio;
|
||||
const selected = scene.getTxAt({ x, y: this.displayHeight - y });
|
||||
if (selected && selected.txid) {
|
||||
this.txClickEvent.emit({ tx: selected, keyModifier });
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onTxHover(hoverId: string) {
|
||||
this.txHoverEvent.emit(hoverId);
|
||||
}
|
||||
|
||||
getColorFunction(): ((tx: TxView) => Color) {
|
||||
if (this.overrideColors) {
|
||||
return this.overrideColors;
|
||||
|
@ -11,4 +11,5 @@
|
||||
[animationDuration]="animationDuration"
|
||||
[animationOffset]="animationOffset"
|
||||
[disableSpinner]="true"
|
||||
(txClickEvent)="onTxClick($event)"
|
||||
></app-block-overview-multi>
|
@ -12,6 +12,7 @@ import { BytesPipe } from '../../shared/pipes/bytes-pipe/bytes.pipe';
|
||||
import { BlockOverviewMultiComponent } from '../block-overview-multi/block-overview-multi.component';
|
||||
import { CacheService } from '../../services/cache.service';
|
||||
import { isMempoolDelta, MempoolBlockDelta } from '../../interfaces/websocket.interface';
|
||||
import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe';
|
||||
|
||||
function bestFitResolution(min, max, n): number {
|
||||
const target = (min + max) / 2;
|
||||
@ -53,7 +54,6 @@ export class EightMempoolComponent implements OnInit, OnDestroy {
|
||||
queryParamsSubscription: Subscription;
|
||||
graphChangeSubscription: Subscription;
|
||||
blockSub: Subscription;
|
||||
mempoolBlockSub: Subscription;
|
||||
|
||||
chainDirection: string = 'right';
|
||||
poolDirection: string = 'left';
|
||||
@ -178,10 +178,18 @@ export class EightMempoolComponent implements OnInit, OnDestroy {
|
||||
.subscribe((network) => this.network = network);
|
||||
}
|
||||
|
||||
onTxClick(event: { tx: TransactionStripped, keyModifier: boolean }): void {
|
||||
const url = new RelativeUrlPipe(this.stateService).transform(`/tx/${event.tx.txid}`);
|
||||
if (!event.keyModifier) {
|
||||
this.router.navigate([url]);
|
||||
} else {
|
||||
window.open(url, '_blank');
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.stateService.markBlock$.next({});
|
||||
this.blockSub.unsubscribe();
|
||||
this.mempoolBlockSub.unsubscribe();
|
||||
this.networkChangedSubscription?.unsubscribe();
|
||||
this.queryParamsSubscription?.unsubscribe();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user