load block/tx pages at correct blockchain scroll position

This commit is contained in:
Mononaut 2022-12-28 06:05:46 -06:00
parent 32bf30872d
commit bf941b0227
No known key found for this signature in database
GPG Key ID: A3F058E41374C04E
9 changed files with 40 additions and 11 deletions

View File

@ -49,7 +49,7 @@
</ng-container> </ng-container>
</ng-template> </ng-template>
</div> </div>
<div [hidden]="!arrowVisible" id="arrow-up" [style.transition]="transition" [ngStyle]="{'left': arrowLeftPx + 'px' }"></div> <div [hidden]="!arrowVisible" id="arrow-up" [style.transition]="arrowTransition" [ngStyle]="{'left': arrowLeftPx + 'px' }"></div>
</div> </div>
<ng-template #loadingBlocksTemplate> <ng-template #loadingBlocksTemplate>

View File

@ -43,7 +43,7 @@ export class BlockchainBlocksComponent implements OnInit, OnChanges, OnDestroy {
arrowVisible = false; arrowVisible = false;
arrowLeftPx = 30; arrowLeftPx = 30;
blocksFilled = false; blocksFilled = false;
transition = '1s'; arrowTransition = '1s';
showMiningInfo = false; showMiningInfo = false;
timeLtrSubscription: Subscription; timeLtrSubscription: Subscription;
timeLtr: boolean; timeLtr: boolean;
@ -179,13 +179,13 @@ export class BlockchainBlocksComponent implements OnInit, OnChanges, OnDestroy {
const blockindex = this.blocks.findIndex((b) => b.height === this.markHeight); const blockindex = this.blocks.findIndex((b) => b.height === this.markHeight);
if (blockindex > -1) { if (blockindex > -1) {
if (!animate) { if (!animate) {
this.transition = 'inherit'; this.arrowTransition = 'inherit';
} }
this.arrowVisible = true; this.arrowVisible = true;
if (newBlockFromLeft) { if (newBlockFromLeft) {
this.arrowLeftPx = blockindex * 155 + 30 - 205; this.arrowLeftPx = blockindex * 155 + 30 - 205;
setTimeout(() => { setTimeout(() => {
this.transition = '2s'; this.arrowTransition = '2s';
this.arrowLeftPx = blockindex * 155 + 30; this.arrowLeftPx = blockindex * 155 + 30;
this.cd.markForCheck(); this.cd.markForCheck();
}, 50); }, 50);
@ -193,9 +193,9 @@ export class BlockchainBlocksComponent implements OnInit, OnChanges, OnDestroy {
this.arrowLeftPx = blockindex * 155 + 30; this.arrowLeftPx = blockindex * 155 + 30;
if (!animate) { if (!animate) {
setTimeout(() => { setTimeout(() => {
this.transition = '2s'; this.arrowTransition = '2s';
this.cd.markForCheck(); this.cd.markForCheck();
}); }, 50);
} }
} }
} else { } else {

View File

@ -2,6 +2,7 @@
<div class="position-container" [ngClass]="network ? network : ''"> <div class="position-container" [ngClass]="network ? network : ''">
<span> <span>
<div class="blocks-wrapper"> <div class="blocks-wrapper">
<div class="scroll-spacer" *ngIf="minScrollWidth" [style.left]="minScrollWidth + 'px'"></div>
<app-mempool-blocks [hidden]="pageIndex > 0"></app-mempool-blocks> <app-mempool-blocks [hidden]="pageIndex > 0"></app-mempool-blocks>
<app-blockchain-blocks [hidden]="pageIndex > 0"></app-blockchain-blocks> <app-blockchain-blocks [hidden]="pageIndex > 0"></app-blockchain-blocks>
<ng-container *ngFor="let page of pages; trackBy: trackByPageFn"> <ng-container *ngFor="let page of pages; trackBy: trackByPageFn">

View File

@ -72,6 +72,15 @@
position: relative; position: relative;
} }
.scroll-spacer {
position: absolute;
top: 0;
left: 0;
width: 1px;
height: 1px;
pointer-events: none;
}
.loading-block { .loading-block {
position: absolute; position: absolute;
text-align: center; text-align: center;

View File

@ -12,6 +12,7 @@ export class BlockchainComponent implements OnInit, OnDestroy {
@Input() pages: any[] = []; @Input() pages: any[] = [];
@Input() pageIndex: number; @Input() pageIndex: number;
@Input() blocksPerPage: number = 8; @Input() blocksPerPage: number = 8;
@Input() minScrollWidth: number = 0;
network: string; network: string;
timeLtrSubscription: Subscription; timeLtrSubscription: Subscription;

View File

@ -13,7 +13,7 @@
(dragstart)="onDragStart($event)" (dragstart)="onDragStart($event)"
(scroll)="onScroll($event)" (scroll)="onScroll($event)"
> >
<app-blockchain [pageIndex]="pageIndex" [pages]="pages" [blocksPerPage]="blocksPerPage"></app-blockchain> <app-blockchain [pageIndex]="pageIndex" [pages]="pages" [blocksPerPage]="blocksPerPage" [minScrollWidth]="minScrollWidth"></app-blockchain>
</div> </div>
<router-outlet></router-outlet> <router-outlet></router-outlet>

View File

@ -29,8 +29,10 @@ export class StartComponent implements OnInit, OnDestroy {
blocksPerPage: number = 1; blocksPerPage: number = 1;
pageWidth: number; pageWidth: number;
firstPageWidth: number; firstPageWidth: number;
minScrollWidth: number;
pageIndex: number = 0; pageIndex: number = 0;
pages: any[] = []; pages: any[] = [];
pendingMark: number | void = null;
constructor( constructor(
private stateService: StateService, private stateService: StateService,
@ -39,17 +41,28 @@ export class StartComponent implements OnInit, OnDestroy {
ngOnInit() { ngOnInit() {
this.firstPageWidth = 40 + (this.blockWidth * this.stateService.env.KEEP_BLOCKS_AMOUNT); this.firstPageWidth = 40 + (this.blockWidth * this.stateService.env.KEEP_BLOCKS_AMOUNT);
this.onResize(); this.onResize();
this.updatePages();
this.timeLtrSubscription = this.stateService.timeLtr.subscribe((ltr) => { this.timeLtrSubscription = this.stateService.timeLtr.subscribe((ltr) => {
this.timeLtr = !!ltr; this.timeLtr = !!ltr;
}); });
this.chainTipSubscription = this.stateService.chainTip$.subscribe((height) => { this.chainTipSubscription = this.stateService.chainTip$.subscribe((height) => {
this.chainTip = height; this.chainTip = height;
this.updatePages(); this.updatePages();
if (this.pendingMark != null) {
this.scrollToBlock(this.pendingMark);
this.pendingMark = null;
}
}); });
this.markBlockSubscription = this.stateService.markBlock$.subscribe((mark) => { this.markBlockSubscription = this.stateService.markBlock$.subscribe((mark) => {
if (mark?.blockHeight != null && !this.blockInViewport(mark.blockHeight)) { if (mark?.blockHeight != null) {
if (this.chainTip >=0) {
if (!this.blockInViewport(mark.blockHeight)) {
this.scrollToBlock(mark.blockHeight); this.scrollToBlock(mark.blockHeight);
} }
} else {
this.pendingMark = mark.blockHeight;
}
}
}); });
this.stateService.blocks$ this.stateService.blocks$
.subscribe((blocks: any) => { .subscribe((blocks: any) => {
@ -96,6 +109,7 @@ export class StartComponent implements OnInit, OnDestroy {
this.blocksPerPage = Math.ceil(window.innerWidth / this.blockWidth); this.blocksPerPage = Math.ceil(window.innerWidth / this.blockWidth);
this.pageWidth = this.blocksPerPage * this.blockWidth; this.pageWidth = this.blocksPerPage * this.blockWidth;
this.minScrollWidth = this.firstPageWidth + (this.pageWidth * 2);
if (firstVisibleBlock != null) { if (firstVisibleBlock != null) {
this.scrollToBlock(firstVisibleBlock, offset); this.scrollToBlock(firstVisibleBlock, offset);
@ -270,5 +284,7 @@ export class StartComponent implements OnInit, OnDestroy {
ngOnDestroy() { ngOnDestroy() {
this.timeLtrSubscription.unsubscribe(); this.timeLtrSubscription.unsubscribe();
this.chainTipSubscription.unsubscribe();
this.markBlockSubscription.unsubscribe();
} }
} }

View File

@ -5,7 +5,7 @@ import { BlockExtended } from '../interfaces/node-api.interface';
import { StateService } from './state.service'; import { StateService } from './state.service';
import { ApiService } from './api.service'; import { ApiService } from './api.service';
const BLOCK_CACHE_SIZE = 50; const BLOCK_CACHE_SIZE = 500;
const KEEP_RECENT_BLOCKS = 50; const KEEP_RECENT_BLOCKS = 50;
@Injectable({ @Injectable({

View File

@ -224,12 +224,14 @@ export class WebsocketService {
handleResponse(response: WebsocketResponse) { handleResponse(response: WebsocketResponse) {
if (response.blocks && response.blocks.length) { if (response.blocks && response.blocks.length) {
const blocks = response.blocks; const blocks = response.blocks;
let maxHeight = 0;
blocks.forEach((block: BlockExtended) => { blocks.forEach((block: BlockExtended) => {
if (block.height > this.stateService.latestBlockHeight) { if (block.height > this.stateService.latestBlockHeight) {
this.stateService.updateChainTip(block.height); maxHeight = Math.max(maxHeight, block.height);
this.stateService.blocks$.next([block, false]); this.stateService.blocks$.next([block, false]);
} }
}); });
this.stateService.updateChainTip(maxHeight);
} }
if (response.tx) { if (response.tx) {