Merge pull request #3025 from mempool/mononaut/offline-loading-blocks
Handling for network interruptions in scrollable blockchain
This commit is contained in:
		
						commit
						56789532ed
					
				@ -1,8 +1,8 @@
 | 
			
		||||
<div class="blocks-container blockchain-blocks-container" [class.time-ltr]="timeLtr"
 | 
			
		||||
  [style.left]="static ? (offset || 0) + 'px' : null"
 | 
			
		||||
  *ngIf="(loadingBlocks$ | async) === false; else loadingBlocksTemplate">
 | 
			
		||||
  *ngIf="static || (loadingBlocks$ | async) === false; else loadingBlocksTemplate">
 | 
			
		||||
  <div *ngFor="let block of blocks; let i = index; trackBy: trackByBlocksFn">
 | 
			
		||||
    <ng-container *ngIf="block && !block.loading && !block.placeholder; else placeholderBlock">
 | 
			
		||||
    <ng-container *ngIf="connected && block && !block.loading && !block.placeholder; else placeholderBlock">
 | 
			
		||||
      <div [attr.data-cy]="'bitcoin-block-offset-' + offset + '-index-' + i"
 | 
			
		||||
        class="text-center bitcoin-block mined-block blockchain-blocks-offset-{{ offset }}-index-{{ i }}"
 | 
			
		||||
        id="bitcoin-block-{{ block.height }}" [ngStyle]="blockStyles[i]"
 | 
			
		||||
@ -59,7 +59,7 @@
 | 
			
		||||
      </div>
 | 
			
		||||
    </ng-container>
 | 
			
		||||
    <ng-template #placeholderBlock>
 | 
			
		||||
      <ng-container *ngIf="block && block.placeholder; else loadingBlock">
 | 
			
		||||
      <ng-container *ngIf="block && block.placeholder && connected && !loadingTip; else loadingBlock">
 | 
			
		||||
        <div [attr.data-cy]="'bitcoin-block-' + offset + '-index-' + i"
 | 
			
		||||
          class="text-center bitcoin-block mined-block placeholder-block blockchain-blocks-{{ i }}"
 | 
			
		||||
          id="bitcoin-block-{{ block.height }}" [ngStyle]="blockStyles[i]">
 | 
			
		||||
@ -68,10 +68,10 @@
 | 
			
		||||
      </ng-container>
 | 
			
		||||
    </ng-template>
 | 
			
		||||
    <ng-template #loadingBlock>
 | 
			
		||||
      <ng-container *ngIf="block && block.loading">
 | 
			
		||||
        <div class="flashing">
 | 
			
		||||
      <ng-container *ngIf="!connected || loadingTip || (block && block.loading)">
 | 
			
		||||
        <div class="flashing loading">
 | 
			
		||||
          <div class="text-center bitcoin-block mined-block" id="bitcoin-block-{{ block.height }}"
 | 
			
		||||
            [ngStyle]="blockStyles[i]"></div>
 | 
			
		||||
            [ngStyle]="convertStyleForLoadingBlock(blockStyles[i])"></div>
 | 
			
		||||
        </div>
 | 
			
		||||
      </ng-container>
 | 
			
		||||
    </ng-template>
 | 
			
		||||
 | 
			
		||||
@ -137,6 +137,10 @@
 | 
			
		||||
  opacity: 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.loading .bitcoin-block.mined-block {
 | 
			
		||||
  background: #2d3348;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@keyframes opacityPulse {
 | 
			
		||||
  0% {opacity: 0.7;}
 | 
			
		||||
  50% {opacity: 1.0;}
 | 
			
		||||
 | 
			
		||||
@ -22,6 +22,8 @@ export class BlockchainBlocksComponent implements OnInit, OnChanges, OnDestroy {
 | 
			
		||||
  @Input() offset: number = 0;
 | 
			
		||||
  @Input() height: number = 0;
 | 
			
		||||
  @Input() count: number = 8;
 | 
			
		||||
  @Input() loadingTip: boolean = false;
 | 
			
		||||
  @Input() connected: boolean = true;
 | 
			
		||||
  
 | 
			
		||||
  specialBlocks = specialBlocks;
 | 
			
		||||
  network = '';
 | 
			
		||||
@ -288,6 +290,13 @@ export class BlockchainBlocksComponent implements OnInit, OnChanges, OnDestroy {
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  convertStyleForLoadingBlock(style) {
 | 
			
		||||
    return {
 | 
			
		||||
      ...style,
 | 
			
		||||
      background: "#2d3348",
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getStyleForLoadingBlock(index: number, animateEnterFrom: number = 0) {
 | 
			
		||||
    const addLeft = animateEnterFrom || 0;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -6,7 +6,7 @@
 | 
			
		||||
        <app-mempool-blocks [hidden]="pageIndex > 0"></app-mempool-blocks>
 | 
			
		||||
        <app-blockchain-blocks [hidden]="pageIndex > 0"></app-blockchain-blocks>
 | 
			
		||||
        <ng-container *ngFor="let page of pages; trackBy: trackByPageFn">
 | 
			
		||||
          <app-blockchain-blocks [static]="true" [offset]="page.offset" [height]="page.height" [count]="blocksPerPage"></app-blockchain-blocks>
 | 
			
		||||
          <app-blockchain-blocks [static]="true" [offset]="page.offset" [height]="page.height" [count]="blocksPerPage" [loadingTip]="loadingTip" [connected]="connected"></app-blockchain-blocks>
 | 
			
		||||
        </ng-container>
 | 
			
		||||
      </div>
 | 
			
		||||
      <div id="divider" [hidden]="pageIndex > 0">
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
import { Component, OnInit, OnDestroy, ChangeDetectionStrategy, Input, OnChanges, SimpleChanges } from '@angular/core';
 | 
			
		||||
import { Subscription } from 'rxjs';
 | 
			
		||||
import { firstValueFrom, Subscription } from 'rxjs';
 | 
			
		||||
import { StateService } from '../../services/state.service';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
@ -18,6 +18,9 @@ export class BlockchainComponent implements OnInit, OnDestroy {
 | 
			
		||||
  timeLtrSubscription: Subscription;
 | 
			
		||||
  timeLtr: boolean = this.stateService.timeLtr.value;
 | 
			
		||||
  ltrTransitionEnabled = false;
 | 
			
		||||
  connectionStateSubscription: Subscription;
 | 
			
		||||
  loadingTip: boolean = true;
 | 
			
		||||
  connected: boolean = true;
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    public stateService: StateService,
 | 
			
		||||
@ -28,10 +31,17 @@ export class BlockchainComponent implements OnInit, OnDestroy {
 | 
			
		||||
    this.timeLtrSubscription = this.stateService.timeLtr.subscribe((ltr) => {
 | 
			
		||||
      this.timeLtr = !!ltr;
 | 
			
		||||
    });
 | 
			
		||||
    this.connectionStateSubscription = this.stateService.connectionState$.subscribe(state => {
 | 
			
		||||
      this.connected = (state === 2);
 | 
			
		||||
    })
 | 
			
		||||
    firstValueFrom(this.stateService.chainTip$).then(tip => {
 | 
			
		||||
      this.loadingTip = false;
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnDestroy() {
 | 
			
		||||
    this.timeLtrSubscription.unsubscribe();
 | 
			
		||||
    this.connectionStateSubscription.unsubscribe();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  trackByPageFn(index: number, item: { index: number }) {
 | 
			
		||||
 | 
			
		||||
@ -21,6 +21,7 @@ export class StartComponent implements OnInit, OnDestroy {
 | 
			
		||||
  timeLtr: boolean = this.stateService.timeLtr.value;
 | 
			
		||||
  chainTipSubscription: Subscription;
 | 
			
		||||
  chainTip: number = -1;
 | 
			
		||||
  tipIsSet: boolean = false;
 | 
			
		||||
  markBlockSubscription: Subscription;
 | 
			
		||||
  blockCounterSubscription: Subscription;
 | 
			
		||||
  @ViewChild('blockchainContainer') blockchainContainer: ElementRef;
 | 
			
		||||
@ -58,6 +59,7 @@ export class StartComponent implements OnInit, OnDestroy {
 | 
			
		||||
    });
 | 
			
		||||
    this.chainTipSubscription = this.stateService.chainTip$.subscribe((height) => {
 | 
			
		||||
      this.chainTip = height;
 | 
			
		||||
      this.tipIsSet = true;
 | 
			
		||||
      this.updatePages();
 | 
			
		||||
      if (this.pendingMark != null) {
 | 
			
		||||
        this.scrollToBlock(this.pendingMark);
 | 
			
		||||
@ -66,7 +68,7 @@ export class StartComponent implements OnInit, OnDestroy {
 | 
			
		||||
    });
 | 
			
		||||
    this.markBlockSubscription = this.stateService.markBlock$.subscribe((mark) => {
 | 
			
		||||
      if (mark?.blockHeight != null) {
 | 
			
		||||
        if (this.chainTip >=0) {
 | 
			
		||||
        if (this.tipIsSet) {
 | 
			
		||||
          if (!this.blockInViewport(mark.blockHeight)) {
 | 
			
		||||
            this.scrollToBlock(mark.blockHeight);
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
@ -62,7 +62,12 @@ export class CacheService {
 | 
			
		||||
      for (let i = 0; i < chunkSize; i++) {
 | 
			
		||||
        this.blockLoading[maxHeight - i] = true;
 | 
			
		||||
      }
 | 
			
		||||
      const result = await firstValueFrom(this.apiService.getBlocks$(maxHeight));
 | 
			
		||||
      let result;
 | 
			
		||||
      try {
 | 
			
		||||
        result = await firstValueFrom(this.apiService.getBlocks$(maxHeight));
 | 
			
		||||
      } catch (e) {
 | 
			
		||||
        console.log("failed to load blocks: ", e.message);
 | 
			
		||||
      }
 | 
			
		||||
      for (let i = 0; i < chunkSize; i++) {
 | 
			
		||||
        delete this.blockLoading[maxHeight - i];
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user