Improve blockchain animations while syncing backend

This commit is contained in:
Mononaut 2023-04-06 09:32:58 +09:00
parent d18ebdfc59
commit 00d94f5614
No known key found for this signature in database
GPG Key ID: A3F058E41374C04E
8 changed files with 19 additions and 17 deletions

View File

@ -22,6 +22,7 @@ export class BlockchainBlocksComponent implements OnInit, OnChanges, OnDestroy {
@Input() offset: number = 0; @Input() offset: number = 0;
@Input() height: number = 0; // max height of blocks in chunk (dynamic blocks only) @Input() height: number = 0; // max height of blocks in chunk (dynamic blocks only)
@Input() count: number = 8; // number of blocks in this chunk (dynamic blocks only) @Input() count: number = 8; // number of blocks in this chunk (dynamic blocks only)
@Input() dynamicBlockCount: number = 8; // number of blocks in the dynamic block chunk
@Input() loadingTip: boolean = false; @Input() loadingTip: boolean = false;
@Input() connected: boolean = true; @Input() connected: boolean = true;
@ -45,7 +46,6 @@ export class BlockchainBlocksComponent implements OnInit, OnChanges, OnDestroy {
feeRounding = '1.0-0'; feeRounding = '1.0-0';
arrowVisible = false; arrowVisible = false;
arrowLeftPx = 30; arrowLeftPx = 30;
blocksFilled = false;
arrowTransition = '1s'; arrowTransition = '1s';
showMiningInfo = false; showMiningInfo = false;
timeLtrSubscription: Subscription; timeLtrSubscription: Subscription;
@ -96,14 +96,13 @@ export class BlockchainBlocksComponent implements OnInit, OnChanges, OnDestroy {
this.tabHiddenSubscription = this.stateService.isTabHidden$.subscribe((tabHidden) => this.tabHidden = tabHidden); this.tabHiddenSubscription = this.stateService.isTabHidden$.subscribe((tabHidden) => this.tabHidden = tabHidden);
if (!this.static) { if (!this.static) {
this.blocksSubscription = this.stateService.blocks$ this.blocksSubscription = this.stateService.blocks$
.subscribe(([block, txConfirmed]) => { .subscribe(([block, txConfirmed, batch]) => {
if (this.blocks.some((b) => b.height === block.height)) { if (this.blocks.some((b) => b.height === block.height)) {
return; return;
} }
if (this.blocks.length && block.height !== this.blocks[0].height + 1) { if (this.blocks.length && block.height !== this.blocks[0].height + 1) {
this.blocks = []; this.blocks = [];
this.blocksFilled = false;
} }
this.blocks.unshift(block); this.blocks.unshift(block);
@ -117,7 +116,7 @@ export class BlockchainBlocksComponent implements OnInit, OnChanges, OnDestroy {
} }
this.blockStyles = []; this.blockStyles = [];
if (this.blocksFilled && block.height > this.chainTip) { if (!batch && block.height > this.chainTip) {
this.blocks.forEach((b, i) => this.blockStyles.push(this.getStyleForBlock(b, i, i ? -155 : -205))); this.blocks.forEach((b, i) => this.blockStyles.push(this.getStyleForBlock(b, i, i ? -155 : -205)));
setTimeout(() => { setTimeout(() => {
this.blockStyles = []; this.blockStyles = [];
@ -128,10 +127,6 @@ export class BlockchainBlocksComponent implements OnInit, OnChanges, OnDestroy {
this.blocks.forEach((b, i) => this.blockStyles.push(this.getStyleForBlock(b, i))); this.blocks.forEach((b, i) => this.blockStyles.push(this.getStyleForBlock(b, i)));
} }
if (this.blocks.length === this.dynamicBlocksAmount) {
this.blocksFilled = true;
}
this.chainTip = Math.max(this.chainTip, block.height); this.chainTip = Math.max(this.chainTip, block.height);
this.cd.markForCheck(); this.cd.markForCheck();
}); });
@ -160,7 +155,7 @@ export class BlockchainBlocksComponent implements OnInit, OnChanges, OnDestroy {
ngOnChanges(changes: SimpleChanges): void { ngOnChanges(changes: SimpleChanges): void {
if (this.static) { if (this.static) {
const animateSlide = changes.height && (changes.height.currentValue === changes.height.previousValue + 1); const animateSlide = !!changes.dynamicBlockCount || (changes.height && (changes.height.currentValue === changes.height.previousValue + 1));
this.updateStaticBlocks(animateSlide); this.updateStaticBlocks(animateSlide);
} }
} }

View File

@ -6,7 +6,7 @@
<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">
<app-blockchain-blocks [static]="true" [offset]="page.offset" [height]="page.height" [count]="blocksPerPage" [loadingTip]="loadingTip" [connected]="connected"></app-blockchain-blocks> <app-blockchain-blocks [static]="true" [offset]="page.offset" [height]="page.height" [dynamicBlockCount]="dynamicBlockCount" [count]="blocksPerPage" [loadingTip]="loadingTip" [connected]="connected"></app-blockchain-blocks>
</ng-container> </ng-container>
</div> </div>
<div id="divider" [hidden]="pageIndex > 0"> <div id="divider" [hidden]="pageIndex > 0">

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() dynamicBlockCount: number = 8;
@Input() minScrollWidth: number = 0; @Input() minScrollWidth: number = 0;
network: string; network: string;

View File

@ -105,7 +105,6 @@ export class MempoolBlocksComponent implements OnInit, OnDestroy {
}); });
this.reduceMempoolBlocksToFitScreen(this.mempoolBlocks); this.reduceMempoolBlocksToFitScreen(this.mempoolBlocks);
this.stateService.isTabHidden$.subscribe((tabHidden) => this.tabHidden = tabHidden); this.stateService.isTabHidden$.subscribe((tabHidden) => this.tabHidden = tabHidden);
this.loadingBlocks$ = this.stateService.isLoadingWebSocket$;
this.mempoolBlocks$ = merge( this.mempoolBlocks$ = merge(
of(true), of(true),
@ -141,6 +140,13 @@ export class MempoolBlocksComponent implements OnInit, OnDestroy {
}) })
); );
this.loadingBlocks$ = combineLatest([
this.stateService.isLoadingWebSocket$,
this.mempoolBlocks$
]).pipe(map(([loading, mempoolBlocks]) => {
return loading || !mempoolBlocks.length;
}));
this.difficultyAdjustments$ = this.stateService.difficultyAdjustment$ this.difficultyAdjustments$ = this.stateService.difficultyAdjustment$
.pipe( .pipe(
map((da) => { map((da) => {

View File

@ -16,7 +16,7 @@
(dragstart)="onDragStart($event)" (dragstart)="onDragStart($event)"
(scroll)="onScroll($event)" (scroll)="onScroll($event)"
> >
<app-blockchain [pageIndex]="pageIndex" [pages]="pages" [blocksPerPage]="blocksPerPage" [minScrollWidth]="minScrollWidth"></app-blockchain> <app-blockchain [pageIndex]="pageIndex" [pages]="pages" [dynamicBlockCount]="dynamicBlocksAmount" [blocksPerPage]="blocksPerPage" [minScrollWidth]="minScrollWidth"></app-blockchain>
</div> </div>
<div class="reset-scroll" [class.hidden]="pageIndex === 0" (click)="resetScroll()"> <div class="reset-scroll" [class.hidden]="pageIndex === 0" (click)="resetScroll()">
<fa-icon [icon]="['fas', 'circle-left']" [fixedWidth]="true"></fa-icon> <fa-icon [icon]="['fas', 'circle-left']" [fixedWidth]="true"></fa-icon>

View File

@ -29,7 +29,7 @@ export class StartComponent implements OnInit, OnDestroy {
isMobile: boolean = false; isMobile: boolean = false;
isiOS: boolean = false; isiOS: boolean = false;
blockWidth = 155; blockWidth = 155;
dynamicBlocksAmount: number = 8; dynamicBlocksAmount: number = 0;
blockCount: number = 0; blockCount: number = 0;
blocksPerPage: number = 1; blocksPerPage: number = 1;
pageWidth: number; pageWidth: number;

View File

@ -89,7 +89,7 @@ export class StateService {
networkChanged$ = new ReplaySubject<string>(1); networkChanged$ = new ReplaySubject<string>(1);
lightningChanged$ = new ReplaySubject<boolean>(1); lightningChanged$ = new ReplaySubject<boolean>(1);
blocks$: ReplaySubject<[BlockExtended, boolean]>; blocks$: ReplaySubject<[BlockExtended, boolean, boolean]>;
transactions$ = new ReplaySubject<TransactionStripped>(6); transactions$ = new ReplaySubject<TransactionStripped>(6);
conversions$ = new ReplaySubject<any>(1); conversions$ = new ReplaySubject<any>(1);
bsqPrice$ = new ReplaySubject<number>(1); bsqPrice$ = new ReplaySubject<number>(1);
@ -157,7 +157,7 @@ export class StateService {
} }
}); });
this.blocks$ = new ReplaySubject<[BlockExtended, boolean]>(this.env.KEEP_BLOCKS_AMOUNT); this.blocks$ = new ReplaySubject<[BlockExtended, boolean, boolean]>(this.env.KEEP_BLOCKS_AMOUNT);
if (this.env.BASE_MODULE === 'bisq') { if (this.env.BASE_MODULE === 'bisq') {
this.network = this.env.BASE_MODULE; this.network = this.env.BASE_MODULE;

View File

@ -228,7 +228,7 @@ export class WebsocketService {
blocks.forEach((block: BlockExtended) => { blocks.forEach((block: BlockExtended) => {
if (block.height > this.stateService.latestBlockHeight) { if (block.height > this.stateService.latestBlockHeight) {
maxHeight = Math.max(maxHeight, block.height); maxHeight = Math.max(maxHeight, block.height);
this.stateService.blocks$.next([block, false]); this.stateService.blocks$.next([block, false, true]);
} }
}); });
this.stateService.updateChainTip(maxHeight); this.stateService.updateChainTip(maxHeight);
@ -241,7 +241,7 @@ export class WebsocketService {
if (response.block) { if (response.block) {
if (response.block.height > this.stateService.latestBlockHeight) { if (response.block.height > this.stateService.latestBlockHeight) {
this.stateService.updateChainTip(response.block.height); this.stateService.updateChainTip(response.block.height);
this.stateService.blocks$.next([response.block, !!response.txConfirmed]); this.stateService.blocks$.next([response.block, !!response.txConfirmed, false]);
} }
if (response.txConfirmed) { if (response.txConfirmed) {