mempool block entry animation
This commit is contained in:
parent
870a7e51b1
commit
64ab14f995
@ -2,7 +2,7 @@
|
|||||||
<div class="mempool-blocks-container" [class.time-ltr]="timeLtr" *ngIf="(difficultyAdjustments$ | async) as da;">
|
<div class="mempool-blocks-container" [class.time-ltr]="timeLtr" *ngIf="(difficultyAdjustments$ | async) as da;">
|
||||||
<div class="flashing">
|
<div class="flashing">
|
||||||
<ng-template ngFor let-projectedBlock [ngForOf]="mempoolBlocks$ | async" let-i="index" [ngForTrackBy]="trackByFn">
|
<ng-template ngFor let-projectedBlock [ngForOf]="mempoolBlocks$ | async" let-i="index" [ngForTrackBy]="trackByFn">
|
||||||
<div [attr.data-cy]="'mempool-block-' + i" class="bitcoin-block text-center mempool-block" id="mempool-block-{{ i }}" [ngStyle]="mempoolBlockStyles[i]" [class.blink-bg]="projectedBlock.blink">
|
<div @blockEntryTrigger [@.disabled]="!animateEntry" [attr.data-cy]="'mempool-block-' + i" class="bitcoin-block text-center mempool-block" id="mempool-block-{{ i }}" [ngStyle]="mempoolBlockStyles[i]" [class.blink-bg]="projectedBlock.blink">
|
||||||
<a draggable="false" [routerLink]="['/mempool-block/' | relativeUrl, i]"
|
<a draggable="false" [routerLink]="['/mempool-block/' | relativeUrl, i]"
|
||||||
class="blockLink" [ngClass]="{'disabled': (this.stateService.blockScrolling$ | async)}"> </a>
|
class="blockLink" [ngClass]="{'disabled': (this.stateService.blockScrolling$ | async)}"> </a>
|
||||||
<div class="block-body">
|
<div class="block-body">
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Component, OnInit, OnDestroy, ChangeDetectionStrategy, ChangeDetectorRef, Input } from '@angular/core';
|
import { Component, OnInit, OnDestroy, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
|
||||||
import { Subscription, Observable, fromEvent, merge, of, combineLatest, timer } from 'rxjs';
|
import { Subscription, Observable, fromEvent, merge, of, combineLatest } from 'rxjs';
|
||||||
import { MempoolBlock } from '../../interfaces/websocket.interface';
|
import { MempoolBlock } from '../../interfaces/websocket.interface';
|
||||||
import { StateService } from '../../services/state.service';
|
import { StateService } from '../../services/state.service';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
@ -9,11 +9,18 @@ import { specialBlocks } from '../../app.constants';
|
|||||||
import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe';
|
import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe';
|
||||||
import { Location } from '@angular/common';
|
import { Location } from '@angular/common';
|
||||||
import { DifficultyAdjustment } from '../../interfaces/node-api.interface';
|
import { DifficultyAdjustment } from '../../interfaces/node-api.interface';
|
||||||
|
import { animate, style, transition, trigger } from '@angular/animations';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-mempool-blocks',
|
selector: 'app-mempool-blocks',
|
||||||
templateUrl: './mempool-blocks.component.html',
|
templateUrl: './mempool-blocks.component.html',
|
||||||
styleUrls: ['./mempool-blocks.component.scss'],
|
styleUrls: ['./mempool-blocks.component.scss'],
|
||||||
|
animations: [trigger('blockEntryTrigger', [
|
||||||
|
transition(':enter', [
|
||||||
|
style({ transform: 'translateX(-155px)' }),
|
||||||
|
animate('2s 0s ease', style({ transform: '' })),
|
||||||
|
]),
|
||||||
|
])],
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class MempoolBlocksComponent implements OnInit, OnDestroy {
|
export class MempoolBlocksComponent implements OnInit, OnDestroy {
|
||||||
@ -32,12 +39,14 @@ export class MempoolBlocksComponent implements OnInit, OnDestroy {
|
|||||||
isLoadingWebsocketSubscription: Subscription;
|
isLoadingWebsocketSubscription: Subscription;
|
||||||
blockSubscription: Subscription;
|
blockSubscription: Subscription;
|
||||||
networkSubscription: Subscription;
|
networkSubscription: Subscription;
|
||||||
|
chainTipSubscription: Subscription;
|
||||||
network = '';
|
network = '';
|
||||||
now = new Date().getTime();
|
now = new Date().getTime();
|
||||||
timeOffset = 0;
|
timeOffset = 0;
|
||||||
showMiningInfo = false;
|
showMiningInfo = false;
|
||||||
timeLtrSubscription: Subscription;
|
timeLtrSubscription: Subscription;
|
||||||
timeLtr: boolean;
|
timeLtr: boolean;
|
||||||
|
animateEntry: boolean = false;
|
||||||
|
|
||||||
blockWidth = 125;
|
blockWidth = 125;
|
||||||
blockPadding = 30;
|
blockPadding = 30;
|
||||||
@ -53,6 +62,7 @@ export class MempoolBlocksComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
resetTransitionTimeout: number;
|
resetTransitionTimeout: number;
|
||||||
|
|
||||||
|
chainTip: number = -1;
|
||||||
blockIndex = 1;
|
blockIndex = 1;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@ -69,6 +79,8 @@ export class MempoolBlocksComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
|
this.chainTip = this.stateService.latestBlockHeight;
|
||||||
|
|
||||||
if (['', 'testnet', 'signet'].includes(this.stateService.network)) {
|
if (['', 'testnet', 'signet'].includes(this.stateService.network)) {
|
||||||
this.enabledMiningInfoIfNeeded(this.location.path());
|
this.enabledMiningInfoIfNeeded(this.location.path());
|
||||||
this.location.onUrlChange((url) => this.enabledMiningInfoIfNeeded(url));
|
this.location.onUrlChange((url) => this.enabledMiningInfoIfNeeded(url));
|
||||||
@ -155,11 +167,24 @@ export class MempoolBlocksComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
this.blockSubscription = this.stateService.blocks$
|
this.blockSubscription = this.stateService.blocks$
|
||||||
.subscribe(([block]) => {
|
.subscribe(([block]) => {
|
||||||
|
if (this.chainTip === -1) {
|
||||||
|
this.animateEntry = block.height === this.stateService.latestBlockHeight;
|
||||||
|
} else {
|
||||||
|
this.animateEntry = block.height > this.chainTip;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.chainTip = this.stateService.latestBlockHeight;
|
||||||
if (block?.extras?.matchRate >= 66 && !this.tabHidden) {
|
if (block?.extras?.matchRate >= 66 && !this.tabHidden) {
|
||||||
this.blockIndex++;
|
this.blockIndex++;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.chainTipSubscription = this.stateService.chainTip$.subscribe((height) => {
|
||||||
|
if (this.chainTip === -1) {
|
||||||
|
this.chainTip = height;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
this.networkSubscription = this.stateService.networkChanged$
|
this.networkSubscription = this.stateService.networkChanged$
|
||||||
.subscribe((network) => this.network = network);
|
.subscribe((network) => this.network = network);
|
||||||
|
|
||||||
@ -195,11 +220,12 @@ export class MempoolBlocksComponent implements OnInit, OnDestroy {
|
|||||||
this.blockSubscription.unsubscribe();
|
this.blockSubscription.unsubscribe();
|
||||||
this.networkSubscription.unsubscribe();
|
this.networkSubscription.unsubscribe();
|
||||||
this.timeLtrSubscription.unsubscribe();
|
this.timeLtrSubscription.unsubscribe();
|
||||||
|
this.chainTipSubscription.unsubscribe();
|
||||||
clearTimeout(this.resetTransitionTimeout);
|
clearTimeout(this.resetTransitionTimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
trackByFn(index: number, block: MempoolBlock) {
|
trackByFn(index: number, block: MempoolBlock) {
|
||||||
return block.index;
|
return (block.isStack) ? 'stack' : block.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
reduceMempoolBlocksToFitScreen(blocks: MempoolBlock[]): MempoolBlock[] {
|
reduceMempoolBlocksToFitScreen(blocks: MempoolBlock[]): MempoolBlock[] {
|
||||||
@ -216,6 +242,9 @@ export class MempoolBlocksComponent implements OnInit, OnDestroy {
|
|||||||
lastBlock.medianFee = this.median(lastBlock.feeRange);
|
lastBlock.medianFee = this.median(lastBlock.feeRange);
|
||||||
lastBlock.totalFees += block.totalFees;
|
lastBlock.totalFees += block.totalFees;
|
||||||
}
|
}
|
||||||
|
if (blocks.length) {
|
||||||
|
blocks[blocks.length - 1].isStack = blocks[blocks.length - 1].blockVSize > this.stateService.blockVSize;
|
||||||
|
}
|
||||||
return blocks;
|
return blocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -334,4 +363,4 @@ export class MempoolBlocksComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
return emptyBlocks;
|
return emptyBlocks;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -43,6 +43,7 @@ export interface MempoolBlock {
|
|||||||
totalFees: number;
|
totalFees: number;
|
||||||
feeRange: number[];
|
feeRange: number[];
|
||||||
index: number;
|
index: number;
|
||||||
|
isStack?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MempoolBlockWithTransactions extends MempoolBlock {
|
export interface MempoolBlockWithTransactions extends MempoolBlock {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user