Highlight matching transactions in the block visualizations

This commit is contained in:
Mononaut 2023-07-12 10:11:04 +09:00
parent cff2022baf
commit e9c618849d
No known key found for this signature in database
GPG Key ID: A3F058E41374C04E
5 changed files with 74 additions and 2 deletions

View File

@ -6,6 +6,8 @@ import TxSprite from './tx-sprite';
import TxView from './tx-view';
import { Position } from './sprite-types';
import { Price } from '../../services/price.service';
import { StateService } from '../../services/state.service';
import { Subscription } from 'rxjs';
@Component({
selector: 'app-block-overview-graph',
@ -44,16 +46,25 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On
scene: BlockScene;
hoverTx: TxView | void;
selectedTx: TxView | void;
highlightTx: TxView | void;
mirrorTx: TxView | void;
tooltipPosition: Position;
readyNextFrame = false;
searchText: string;
searchSubscription: Subscription;
constructor(
readonly ngZone: NgZone,
readonly elRef: ElementRef,
private stateService: StateService,
) {
this.vertexArray = new FastVertexArray(512, TxSprite.dataSize);
this.searchSubscription = this.stateService.searchText$.subscribe((text) => {
this.searchText = text;
this.updateSearchHighlight();
});
}
ngAfterViewInit(): void {
@ -109,6 +120,7 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On
this.scene.setup(transactions);
this.readyNextFrame = true;
this.start();
this.updateSearchHighlight();
}
}
@ -116,6 +128,7 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On
if (this.scene) {
this.scene.enter(transactions, direction);
this.start();
this.updateSearchHighlight();
}
}
@ -123,6 +136,7 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On
if (this.scene) {
this.scene.exit(direction);
this.start();
this.updateSearchHighlight();
}
}
@ -130,6 +144,7 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On
if (this.scene) {
this.scene.replace(transactions || [], direction, sort);
this.start();
this.updateSearchHighlight();
}
}
@ -137,6 +152,7 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On
if (this.scene) {
this.scene.update(add, remove, change, direction, resetLayout);
this.start();
this.updateSearchHighlight();
}
}
@ -406,6 +422,19 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On
}
}
updateSearchHighlight(): void {
if (this.highlightTx && this.highlightTx.txid !== this.searchText && this.scene) {
this.scene.setHighlight(this.highlightTx, false);
this.start();
} else if (this.searchText && this.searchText.length === 64) {
this.highlightTx = this.scene.txs[this.searchText];
if (this.highlightTx) {
this.scene.setHighlight(this.highlightTx, true);
this.start();
}
}
}
setHighlightingEnabled(enabled: boolean): void {
if (this.scene) {
this.scene.setHighlighting(enabled);

View File

@ -215,6 +215,10 @@ export default class BlockScene {
this.animateUntil = Math.max(this.animateUntil, tx.setHover(value));
}
setHighlight(tx: TxView, value: boolean): void {
this.animateUntil = Math.max(this.animateUntil, tx.setHighlight(value));
}
private init({ width, height, resolution, blockLimit, orientation, flip, vertexArray, highlighting, pixelAlign }:
{ width: number, height: number, resolution: number, blockLimit: number,
orientation: string, flip: boolean, vertexArray: FastVertexArray, highlighting: boolean, pixelAlign: boolean }

View File

@ -7,6 +7,7 @@ import BlockScene from './block-scene';
const hoverTransitionTime = 300;
const defaultHoverColor = hexToColor('1bd8f4');
const defaultHighlightColor = hexToColor('800080');
const feeColors = mempoolFeeColors.map(hexToColor);
const auditFeeColors = feeColors.map((color) => darken(desaturate(color, 0.3), 0.9));
@ -44,8 +45,10 @@ export default class TxView implements TransactionStripped {
initialised: boolean;
vertexArray: FastVertexArray;
hover: boolean;
highlight: boolean;
sprite: TxSprite;
hoverColor: Color | void;
highlightColor: Color | void;
screenPosition: Square;
gridPosition: Square | void;
@ -150,8 +153,40 @@ export default class TxView implements TransactionStripped {
} else {
this.hover = false;
this.hoverColor = null;
if (this.sprite) {
this.sprite.resume(hoverTransitionTime);
if (this.highlight) {
this.setHighlight(true, this.highlightColor);
} else {
if (this.sprite) {
this.sprite.resume(hoverTransitionTime);
}
}
}
this.dirty = false;
return performance.now() + hoverTransitionTime;
}
// Temporarily override the tx color
// returns minimum transition end time
setHighlight(highlightOn: boolean, color: Color | void = defaultHighlightColor): number {
if (highlightOn) {
this.highlight = true;
this.highlightColor = color;
this.sprite.update({
...this.highlightColor,
duration: hoverTransitionTime,
adjust: false,
temp: true
});
} else {
this.highlight = false;
this.highlightColor = null;
if (this.hover) {
this.setHover(true, this.hoverColor);
} else {
if (this.sprite) {
this.sprite.resume(hoverTransitionTime);
}
}
}
this.dirty = false;

View File

@ -80,6 +80,9 @@ export class SearchFormComponent implements OnInit {
}
return text.trim();
}),
tap((text) => {
this.stateService.searchText$.next(text);
}),
distinctUntilChanged(),
);

View File

@ -129,6 +129,7 @@ export class StateService {
markBlock$ = new BehaviorSubject<MarkBlockState>({});
keyNavigation$ = new Subject<KeyboardEvent>();
searchText$ = new BehaviorSubject<string>('');
blockScrolling$: Subject<boolean> = new Subject<boolean>();
resetScroll$: Subject<boolean> = new Subject<boolean>();