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; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -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