Merge pull request #3863 from mempool/mononaut/scrollable-mempool
scroll to see all mempool blocks
This commit is contained in:
		
						commit
						dac5d7ed58
					
				@ -1,9 +1,9 @@
 | 
			
		||||
<div class="text-center" class="blockchain-wrapper" [class.time-ltr]="timeLtr" [class.ltr-transition]="ltrTransitionEnabled" #container>
 | 
			
		||||
  <div class="position-container" [ngClass]="network ? network : ''">
 | 
			
		||||
  <div class="position-container" [ngClass]="network ? network : ''" [style.--divider-offset]="dividerOffset + 'px'" [style.--mempool-offset]="mempoolOffset + 'px'">
 | 
			
		||||
    <span>
 | 
			
		||||
      <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" [allBlocks]="scrollableMempool" (widthChange)="onMempoolWidthChange($event)"></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" [loadingTip]="loadingTip" [connected]="connected"></app-blockchain-blocks>
 | 
			
		||||
 | 
			
		||||
@ -26,43 +26,14 @@
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  left: 0;
 | 
			
		||||
  top: 75px;
 | 
			
		||||
  transform: translateX(50vw);
 | 
			
		||||
  --divider-offset: 50vw;
 | 
			
		||||
  --mempool-offset: 0px;
 | 
			
		||||
  transform: translateX(calc(var(--divider-offset) + var(--mempool-offset)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.position-container.liquid, .position-container.liquidtestnet {
 | 
			
		||||
  transform: translateX(420px);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@media (min-width: 768px) {
 | 
			
		||||
  .blockchain-wrapper.time-ltr {
 | 
			
		||||
    .position-container.liquid, .position-container.liquidtestnet {
 | 
			
		||||
      transform: translateX(calc(100vw - 420px));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@media (max-width: 767.98px) {
 | 
			
		||||
  .blockchain-wrapper {
 | 
			
		||||
    .position-container {
 | 
			
		||||
      transform: translateX(95vw);
 | 
			
		||||
    }
 | 
			
		||||
    .position-container.liquid, .position-container.liquidtestnet {
 | 
			
		||||
      transform: translateX(50vw);
 | 
			
		||||
    }
 | 
			
		||||
    .position-container.loading {
 | 
			
		||||
      transform: translateX(50vw);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  .blockchain-wrapper.time-ltr {
 | 
			
		||||
    .position-container {
 | 
			
		||||
      transform: translateX(5vw);
 | 
			
		||||
    }
 | 
			
		||||
    .position-container.liquid, .position-container.liquidtestnet {
 | 
			
		||||
      transform: translateX(50vw);
 | 
			
		||||
    }
 | 
			
		||||
    .position-container.loading {
 | 
			
		||||
      transform: translateX(50vw);
 | 
			
		||||
    }
 | 
			
		||||
.blockchain-wrapper.time-ltr {
 | 
			
		||||
  .position-container {
 | 
			
		||||
    transform: translateX(calc(100vw - var(--divider-offset) - var(--mempool-offset)));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
import { Component, OnInit, OnDestroy, ChangeDetectionStrategy, Input, OnChanges, SimpleChanges } from '@angular/core';
 | 
			
		||||
import { Component, OnInit, OnDestroy, ChangeDetectionStrategy, Input, Output, EventEmitter, HostListener, ChangeDetectorRef } from '@angular/core';
 | 
			
		||||
import { firstValueFrom, Subscription } from 'rxjs';
 | 
			
		||||
import { StateService } from '../../services/state.service';
 | 
			
		||||
 | 
			
		||||
@ -13,43 +13,95 @@ export class BlockchainComponent implements OnInit, OnDestroy {
 | 
			
		||||
  @Input() pageIndex: number;
 | 
			
		||||
  @Input() blocksPerPage: number = 8;
 | 
			
		||||
  @Input() minScrollWidth: number = 0;
 | 
			
		||||
  @Input() scrollableMempool: boolean = false;
 | 
			
		||||
 | 
			
		||||
  @Output() mempoolOffsetChange: EventEmitter<number> = new EventEmitter();
 | 
			
		||||
 | 
			
		||||
  network: string;
 | 
			
		||||
  timeLtrSubscription: Subscription;
 | 
			
		||||
  timeLtr: boolean = this.stateService.timeLtr.value;
 | 
			
		||||
  ltrTransitionEnabled = false;
 | 
			
		||||
  flipping = false;
 | 
			
		||||
  connectionStateSubscription: Subscription;
 | 
			
		||||
  loadingTip: boolean = true;
 | 
			
		||||
  connected: boolean = true;
 | 
			
		||||
 | 
			
		||||
  dividerOffset: number = 0;
 | 
			
		||||
  mempoolOffset: number = 0;
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    public stateService: StateService,
 | 
			
		||||
    private cd: ChangeDetectorRef,
 | 
			
		||||
  ) {}
 | 
			
		||||
 | 
			
		||||
  ngOnInit() {
 | 
			
		||||
  ngOnInit(): void {
 | 
			
		||||
    this.onResize();
 | 
			
		||||
    this.network = this.stateService.network;
 | 
			
		||||
    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 => {
 | 
			
		||||
    });
 | 
			
		||||
    firstValueFrom(this.stateService.chainTip$).then(() => {
 | 
			
		||||
      this.loadingTip = false;
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnDestroy() {
 | 
			
		||||
  ngOnDestroy(): void {
 | 
			
		||||
    this.timeLtrSubscription.unsubscribe();
 | 
			
		||||
    this.connectionStateSubscription.unsubscribe();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  trackByPageFn(index: number, item: { index: number }) {
 | 
			
		||||
  trackByPageFn(index: number, item: { index: number }): number {
 | 
			
		||||
    return item.index;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  toggleTimeDirection() {
 | 
			
		||||
    this.ltrTransitionEnabled = true;
 | 
			
		||||
    this.stateService.timeLtr.next(!this.timeLtr);
 | 
			
		||||
  toggleTimeDirection(): void {
 | 
			
		||||
    this.ltrTransitionEnabled = false;
 | 
			
		||||
    const prevOffset = this.mempoolOffset;
 | 
			
		||||
    this.mempoolOffset = 0;
 | 
			
		||||
    this.mempoolOffsetChange.emit(0);
 | 
			
		||||
    setTimeout(() => {
 | 
			
		||||
      this.ltrTransitionEnabled = true;
 | 
			
		||||
      this.flipping = true;
 | 
			
		||||
      this.stateService.timeLtr.next(!this.timeLtr);
 | 
			
		||||
      setTimeout(() => {
 | 
			
		||||
        this.ltrTransitionEnabled = false;
 | 
			
		||||
        this.flipping = false;
 | 
			
		||||
        this.mempoolOffset = prevOffset;
 | 
			
		||||
        this.mempoolOffsetChange.emit(this.mempoolOffset);
 | 
			
		||||
      },  1000);
 | 
			
		||||
    }, 0);
 | 
			
		||||
    this.cd.markForCheck();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  onMempoolWidthChange(width): void {
 | 
			
		||||
    if (this.flipping) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    this.mempoolOffset = Math.max(0, width - this.dividerOffset);
 | 
			
		||||
    this.cd.markForCheck();
 | 
			
		||||
    setTimeout(() => {
 | 
			
		||||
      this.mempoolOffsetChange.emit(this.mempoolOffset);
 | 
			
		||||
    }, 0);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @HostListener('window:resize', ['$event'])
 | 
			
		||||
  onResize(): void {
 | 
			
		||||
    if (window.innerWidth >= 768) {
 | 
			
		||||
      if (this.stateService.isLiquid()) {
 | 
			
		||||
        this.dividerOffset = 420;
 | 
			
		||||
      } else {
 | 
			
		||||
        this.dividerOffset = window.innerWidth * 0.5;
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      if (this.stateService.isLiquid()) {
 | 
			
		||||
        this.dividerOffset = window.innerWidth * 0.5;
 | 
			
		||||
      } else {
 | 
			
		||||
        this.dividerOffset = window.innerWidth * 0.95;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    this.cd.markForCheck();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,9 +1,9 @@
 | 
			
		||||
import { Component, OnInit, OnDestroy, ChangeDetectionStrategy, ChangeDetectorRef, HostListener, Input, OnChanges, SimpleChanges } from '@angular/core';
 | 
			
		||||
import { Component, OnInit, OnDestroy, ChangeDetectionStrategy, ChangeDetectorRef, HostListener, Input, OnChanges, SimpleChanges, Output, EventEmitter } from '@angular/core';
 | 
			
		||||
import { Subscription, Observable, fromEvent, merge, of, combineLatest } from 'rxjs';
 | 
			
		||||
import { MempoolBlock } from '../../interfaces/websocket.interface';
 | 
			
		||||
import { StateService } from '../../services/state.service';
 | 
			
		||||
import { Router } from '@angular/router';
 | 
			
		||||
import { take, map, switchMap } from 'rxjs/operators';
 | 
			
		||||
import { take, map, switchMap, tap } from 'rxjs/operators';
 | 
			
		||||
import { feeLevels, mempoolFeeColors } from '../../app.constants';
 | 
			
		||||
import { specialBlocks } from '../../app.constants';
 | 
			
		||||
import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe';
 | 
			
		||||
@ -29,6 +29,9 @@ export class MempoolBlocksComponent implements OnInit, OnChanges, OnDestroy {
 | 
			
		||||
  @Input() count: number = null;
 | 
			
		||||
  @Input() spotlight: number = 0;
 | 
			
		||||
  @Input() getHref?: (index) => string = (index) => `/mempool-block/${index}`;
 | 
			
		||||
  @Input() allBlocks: boolean = false;
 | 
			
		||||
 | 
			
		||||
  @Output() widthChange: EventEmitter<number> = new EventEmitter();
 | 
			
		||||
 | 
			
		||||
  specialBlocks = specialBlocks;
 | 
			
		||||
  mempoolBlocks: MempoolBlock[] = [];
 | 
			
		||||
@ -147,7 +150,12 @@ export class MempoolBlocksComponent implements OnInit, OnChanges, OnDestroy {
 | 
			
		||||
 | 
			
		||||
          this.updateMempoolBlockStyles();
 | 
			
		||||
          this.calculateTransactionPosition();
 | 
			
		||||
 
 | 
			
		||||
          return this.mempoolBlocks;
 | 
			
		||||
        }),
 | 
			
		||||
        tap(() => {
 | 
			
		||||
          this.cd.markForCheck();
 | 
			
		||||
          this.widthChange.emit(this.containerOffset + this.mempoolBlocks.length * this.blockOffset);
 | 
			
		||||
        })
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
@ -257,7 +265,10 @@ export class MempoolBlocksComponent implements OnInit, OnChanges, OnDestroy {
 | 
			
		||||
 | 
			
		||||
  reduceEmptyBlocksToFitScreen(blocks: MempoolBlock[]): MempoolBlock[] {
 | 
			
		||||
    const innerWidth = this.stateService.env.BASE_MODULE !== 'liquid' && window.innerWidth <= 767.98 ? window.innerWidth : window.innerWidth / 2;
 | 
			
		||||
    const blocksAmount = Math.min(this.stateService.env.MEMPOOL_BLOCKS_AMOUNT, Math.floor(innerWidth / (this.blockWidth + this.blockPadding)));
 | 
			
		||||
    let blocksAmount = this.stateService.env.MEMPOOL_BLOCKS_AMOUNT;
 | 
			
		||||
    if (!this.allBlocks) {
 | 
			
		||||
      blocksAmount = Math.min(this.stateService.env.MEMPOOL_BLOCKS_AMOUNT, Math.floor(innerWidth / (this.blockWidth + this.blockPadding)));
 | 
			
		||||
    }
 | 
			
		||||
    while (blocks.length < blocksAmount) {
 | 
			
		||||
      blocks.push({
 | 
			
		||||
        blockSize: 0,
 | 
			
		||||
@ -277,10 +288,10 @@ export class MempoolBlocksComponent implements OnInit, OnChanges, OnDestroy {
 | 
			
		||||
 | 
			
		||||
  reduceMempoolBlocksToFitScreen(blocks: MempoolBlock[]): MempoolBlock[] {
 | 
			
		||||
    const innerWidth = this.stateService.env.BASE_MODULE !== 'liquid' && window.innerWidth <= 767.98 ? window.innerWidth : window.innerWidth / 2;
 | 
			
		||||
    let blocksAmount;
 | 
			
		||||
    let blocksAmount = this.stateService.env.MEMPOOL_BLOCKS_AMOUNT;
 | 
			
		||||
    if (this.count) {
 | 
			
		||||
      blocksAmount = 8;
 | 
			
		||||
    } else {
 | 
			
		||||
    } else if (!this.allBlocks) {
 | 
			
		||||
      blocksAmount = Math.min(this.stateService.env.MEMPOOL_BLOCKS_AMOUNT, Math.floor(innerWidth / (this.blockWidth + this.blockPadding)));
 | 
			
		||||
    }
 | 
			
		||||
    while (blocks.length > blocksAmount) {
 | 
			
		||||
 | 
			
		||||
@ -18,7 +18,7 @@
 | 
			
		||||
    (dragstart)="onDragStart($event)"
 | 
			
		||||
    (scroll)="onScroll($event)"
 | 
			
		||||
  >
 | 
			
		||||
    <app-blockchain [pageIndex]="pageIndex" [pages]="pages" [blocksPerPage]="blocksPerPage" [minScrollWidth]="minScrollWidth"></app-blockchain>
 | 
			
		||||
    <app-blockchain [pageIndex]="pageIndex" [pages]="pages" [blocksPerPage]="blocksPerPage" [minScrollWidth]="minScrollWidth" [scrollableMempool]="true" (mempoolOffsetChange)="onMempoolOffsetChange($event)"></app-blockchain>
 | 
			
		||||
  </div>
 | 
			
		||||
  <div class="reset-scroll" [class.hidden]="pageIndex === 0" (click)="resetScroll()">
 | 
			
		||||
    <fa-icon [icon]="['fas', 'circle-left']" [fixedWidth]="true"></fa-icon>
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
import { Component, ElementRef, HostListener, OnInit, OnDestroy, ViewChild, Input } from '@angular/core';
 | 
			
		||||
import { Subscription } from 'rxjs';
 | 
			
		||||
import { StateService } from '../../services/state.service';
 | 
			
		||||
import { MarkBlockState, StateService } from '../../services/state.service';
 | 
			
		||||
import { specialBlocks } from '../../app.constants';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
@ -24,6 +24,7 @@ export class StartComponent implements OnInit, OnDestroy {
 | 
			
		||||
  chainTipSubscription: Subscription;
 | 
			
		||||
  chainTip: number = -1;
 | 
			
		||||
  tipIsSet: boolean = false;
 | 
			
		||||
  lastMark: MarkBlockState;
 | 
			
		||||
  markBlockSubscription: Subscription;
 | 
			
		||||
  blockCounterSubscription: Subscription;
 | 
			
		||||
  @ViewChild('blockchainContainer') blockchainContainer: ElementRef;
 | 
			
		||||
@ -40,10 +41,11 @@ export class StartComponent implements OnInit, OnDestroy {
 | 
			
		||||
  minScrollWidth: number;
 | 
			
		||||
  pageIndex: number = 0;
 | 
			
		||||
  pages: any[] = [];
 | 
			
		||||
  pendingMark: number | void = null;
 | 
			
		||||
  pendingMark: number | null = null;
 | 
			
		||||
  lastUpdate: number = 0;
 | 
			
		||||
  lastMouseX: number;
 | 
			
		||||
  velocity: number = 0;
 | 
			
		||||
  mempoolOffset: number = 0;
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    private stateService: StateService,
 | 
			
		||||
@ -70,19 +72,40 @@ export class StartComponent implements OnInit, OnDestroy {
 | 
			
		||||
      this.chainTip = height;
 | 
			
		||||
      this.tipIsSet = true;
 | 
			
		||||
      this.updatePages();
 | 
			
		||||
      if (this.pendingMark != null) {
 | 
			
		||||
        this.scrollToBlock(this.pendingMark);
 | 
			
		||||
        this.pendingMark = null;
 | 
			
		||||
      }
 | 
			
		||||
      this.applyPendingMarkArrow();
 | 
			
		||||
    });
 | 
			
		||||
    this.markBlockSubscription = this.stateService.markBlock$.subscribe((mark) => {
 | 
			
		||||
      let blockHeight;
 | 
			
		||||
      let newMark = true;
 | 
			
		||||
      if (mark?.blockHeight != null) {
 | 
			
		||||
        if (this.lastMark?.blockHeight === mark.blockHeight) {
 | 
			
		||||
          newMark = false;
 | 
			
		||||
        }
 | 
			
		||||
        blockHeight = mark.blockHeight;
 | 
			
		||||
      } else if (mark?.mempoolBlockIndex != null) {
 | 
			
		||||
        if (this.lastMark?.mempoolBlockIndex === mark.mempoolBlockIndex || (mark.txid && this.lastMark?.txid === mark.txid)) {
 | 
			
		||||
          newMark = false;
 | 
			
		||||
        }
 | 
			
		||||
        blockHeight = -1 - mark.mempoolBlockIndex;
 | 
			
		||||
      } else if (mark?.mempoolPosition?.block != null) {
 | 
			
		||||
        if (this.lastMark?.txid === mark.txid) {
 | 
			
		||||
          newMark = false;
 | 
			
		||||
        }
 | 
			
		||||
        blockHeight = -1 - mark.mempoolPosition.block;
 | 
			
		||||
      }
 | 
			
		||||
      this.lastMark = mark;
 | 
			
		||||
      if (blockHeight != null) {
 | 
			
		||||
        if (this.tipIsSet) {
 | 
			
		||||
          if (!this.blockInViewport(mark.blockHeight)) {
 | 
			
		||||
            this.scrollToBlock(mark.blockHeight);
 | 
			
		||||
          let scrollToHeight = blockHeight;
 | 
			
		||||
          if (blockHeight < 0) {
 | 
			
		||||
            scrollToHeight = this.chainTip - blockHeight;
 | 
			
		||||
          }
 | 
			
		||||
        } else {
 | 
			
		||||
          this.pendingMark = mark.blockHeight;
 | 
			
		||||
          if (newMark && !this.blockInViewport(scrollToHeight)) {
 | 
			
		||||
            this.scrollToBlock(scrollToHeight);
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        if (!this.tipIsSet || (blockHeight < 0 && !this.mempoolOffset)) {
 | 
			
		||||
          this.pendingMark = blockHeight;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
@ -117,6 +140,24 @@ export class StartComponent implements OnInit, OnDestroy {
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  onMempoolOffsetChange(offset): void {
 | 
			
		||||
    const delta = offset - this.mempoolOffset;
 | 
			
		||||
    this.addConvertedScrollOffset(delta);
 | 
			
		||||
    this.mempoolOffset = offset;
 | 
			
		||||
    this.applyPendingMarkArrow();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  applyPendingMarkArrow(): void {
 | 
			
		||||
    if (this.pendingMark != null) {
 | 
			
		||||
      if (this.pendingMark < 0) {
 | 
			
		||||
        this.scrollToBlock(this.chainTip - this.pendingMark);
 | 
			
		||||
      } else {
 | 
			
		||||
        this.scrollToBlock(this.pendingMark);
 | 
			
		||||
      }
 | 
			
		||||
      this.pendingMark = null;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @HostListener('window:resize', ['$event'])
 | 
			
		||||
  onResize(): void {
 | 
			
		||||
    this.isMobile = window.innerWidth <= 767.98;
 | 
			
		||||
@ -350,7 +391,7 @@ export class StartComponent implements OnInit, OnDestroy {
 | 
			
		||||
 | 
			
		||||
  resetScroll(): void {
 | 
			
		||||
    this.scrollToBlock(this.chainTip);
 | 
			
		||||
    this.blockchainContainer.nativeElement.scrollLeft = 0;
 | 
			
		||||
    this.setScrollLeft(0);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getPageIndexOf(height: number): number {
 | 
			
		||||
@ -368,9 +409,17 @@ export class StartComponent implements OnInit, OnDestroy {
 | 
			
		||||
 | 
			
		||||
  getConvertedScrollOffset(): number {
 | 
			
		||||
    if (this.timeLtr) {
 | 
			
		||||
      return -this.blockchainContainer?.nativeElement?.scrollLeft || 0;
 | 
			
		||||
      return -(this.blockchainContainer?.nativeElement?.scrollLeft || 0) - this.mempoolOffset;
 | 
			
		||||
    } else {
 | 
			
		||||
      return this.blockchainContainer?.nativeElement?.scrollLeft || 0;
 | 
			
		||||
      return (this.blockchainContainer?.nativeElement?.scrollLeft || 0) - this.mempoolOffset;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  setScrollLeft(offset: number): void {
 | 
			
		||||
    if (this.timeLtr) {
 | 
			
		||||
      this.blockchainContainer.nativeElement.scrollLeft = offset - this.mempoolOffset;
 | 
			
		||||
    } else {
 | 
			
		||||
      this.blockchainContainer.nativeElement.scrollLeft = offset + this.mempoolOffset;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -388,7 +437,7 @@ export class StartComponent implements OnInit, OnDestroy {
 | 
			
		||||
  ngOnDestroy() {
 | 
			
		||||
    if (this.blockchainContainer?.nativeElement) {
 | 
			
		||||
      // clean up scroll position to prevent caching wrong scroll in Firefox
 | 
			
		||||
      this.blockchainContainer.nativeElement.scrollLeft = 0;
 | 
			
		||||
      this.setScrollLeft(0);
 | 
			
		||||
    }
 | 
			
		||||
    this.timeLtrSubscription.unsubscribe();
 | 
			
		||||
    this.chainTipSubscription.unsubscribe();
 | 
			
		||||
 | 
			
		||||
@ -241,6 +241,7 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
 | 
			
		||||
        this.mempoolPosition = txPosition.position;
 | 
			
		||||
        if (this.tx && !this.tx.status.confirmed) {
 | 
			
		||||
          this.stateService.markBlock$.next({
 | 
			
		||||
            txid: txPosition.txid,
 | 
			
		||||
            mempoolPosition: this.mempoolPosition
 | 
			
		||||
          });
 | 
			
		||||
          this.txInBlockIndex = this.mempoolPosition.block;
 | 
			
		||||
@ -360,6 +361,7 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
 | 
			
		||||
          } else {
 | 
			
		||||
            if (tx.cpfpChecked) {
 | 
			
		||||
              this.stateService.markBlock$.next({
 | 
			
		||||
                txid: tx.txid,
 | 
			
		||||
                txFeePerVSize: tx.effectiveFeePerVsize,
 | 
			
		||||
                mempoolPosition: this.mempoolPosition,
 | 
			
		||||
              });
 | 
			
		||||
 | 
			
		||||
@ -8,8 +8,9 @@ import { isPlatformBrowser } from '@angular/common';
 | 
			
		||||
import { map, scan, shareReplay, tap } from 'rxjs/operators';
 | 
			
		||||
import { StorageService } from './storage.service';
 | 
			
		||||
 | 
			
		||||
interface MarkBlockState {
 | 
			
		||||
export interface MarkBlockState {
 | 
			
		||||
  blockHeight?: number;
 | 
			
		||||
  txid?: string;
 | 
			
		||||
  mempoolBlockIndex?: number;
 | 
			
		||||
  txFeePerVSize?: number;
 | 
			
		||||
  mempoolPosition?: MempoolPosition;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user