Reimplement mempool animation smoothing within viz component
This commit is contained in:
		
							parent
							
								
									a8868b5f0f
								
							
						
					
					
						commit
						44116424b0
					
				@ -81,6 +81,20 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On
 | 
			
		||||
  tooltipPosition: Position;
 | 
			
		||||
 | 
			
		||||
  readyNextFrame = false;
 | 
			
		||||
  lastUpdate: number = 0;
 | 
			
		||||
  pendingUpdate: {
 | 
			
		||||
    count: number,
 | 
			
		||||
    add: { [txid: string]: TransactionStripped },
 | 
			
		||||
    remove: { [txid: string]: string },
 | 
			
		||||
    change: { [txid: string]: { txid: string, rate: number | undefined, acc: boolean | undefined } },
 | 
			
		||||
    direction?: string,
 | 
			
		||||
  } = {
 | 
			
		||||
    count: 0,
 | 
			
		||||
    add: {},
 | 
			
		||||
    remove: {},
 | 
			
		||||
    change: {},
 | 
			
		||||
    direction: 'left',
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  searchText: string;
 | 
			
		||||
  searchSubscription: Subscription;
 | 
			
		||||
@ -176,6 +190,7 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On
 | 
			
		||||
  destroy(): void {
 | 
			
		||||
    if (this.scene) {
 | 
			
		||||
      this.scene.destroy();
 | 
			
		||||
      this.clearUpdateQueue();
 | 
			
		||||
      this.start();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
@ -188,6 +203,7 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On
 | 
			
		||||
    }
 | 
			
		||||
    this.filtersAvailable = filtersAvailable;
 | 
			
		||||
    if (this.scene) {
 | 
			
		||||
      this.clearUpdateQueue();
 | 
			
		||||
      this.scene.setup(transactions);
 | 
			
		||||
      this.readyNextFrame = true;
 | 
			
		||||
      this.start();
 | 
			
		||||
@ -197,6 +213,7 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On
 | 
			
		||||
 | 
			
		||||
  enter(transactions: TransactionStripped[], direction: string): void {
 | 
			
		||||
    if (this.scene) {
 | 
			
		||||
      this.clearUpdateQueue();
 | 
			
		||||
      this.scene.enter(transactions, direction);
 | 
			
		||||
      this.start();
 | 
			
		||||
      this.updateSearchHighlight();
 | 
			
		||||
@ -205,6 +222,7 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On
 | 
			
		||||
 | 
			
		||||
  exit(direction: string): void {
 | 
			
		||||
    if (this.scene) {
 | 
			
		||||
      this.clearUpdateQueue();
 | 
			
		||||
      this.scene.exit(direction);
 | 
			
		||||
      this.start();
 | 
			
		||||
      this.updateSearchHighlight();
 | 
			
		||||
@ -213,13 +231,61 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On
 | 
			
		||||
 | 
			
		||||
  replace(transactions: TransactionStripped[], direction: string, sort: boolean = true, startTime?: number): void {
 | 
			
		||||
    if (this.scene) {
 | 
			
		||||
      this.clearUpdateQueue();
 | 
			
		||||
      this.scene.replace(transactions || [], direction, sort, startTime);
 | 
			
		||||
      this.start();
 | 
			
		||||
      this.updateSearchHighlight();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // collates non-urgent updates into a set of consistent pending changes
 | 
			
		||||
  queueUpdate(add: TransactionStripped[], remove: string[], change: { txid: string, rate: number | undefined, acc: boolean | undefined }[], direction: string = 'left'): void {
 | 
			
		||||
    for (const tx of add) {
 | 
			
		||||
      this.pendingUpdate.add[tx.txid] = tx;
 | 
			
		||||
      delete this.pendingUpdate.remove[tx.txid];
 | 
			
		||||
      delete this.pendingUpdate.change[tx.txid];
 | 
			
		||||
    }
 | 
			
		||||
    for (const txid of remove) {
 | 
			
		||||
      delete this.pendingUpdate.add[txid];
 | 
			
		||||
      this.pendingUpdate.remove[txid] = txid;
 | 
			
		||||
      delete this.pendingUpdate.change[txid];
 | 
			
		||||
    }
 | 
			
		||||
    for (const tx of change) {
 | 
			
		||||
      if (this.pendingUpdate.add[tx.txid]) {
 | 
			
		||||
        this.pendingUpdate.add[tx.txid].rate = tx.rate;
 | 
			
		||||
        this.pendingUpdate.add[tx.txid].acc = tx.acc;
 | 
			
		||||
      } else {
 | 
			
		||||
        this.pendingUpdate.change[tx.txid] = tx;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    this.pendingUpdate.direction = direction;
 | 
			
		||||
    this.pendingUpdate.count++;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  applyQueuedUpdates(): void {
 | 
			
		||||
    if (this.pendingUpdate.count && performance.now() > (this.lastUpdate + this.animationDuration)) {
 | 
			
		||||
      this.update([], [], [], this.pendingUpdate?.direction);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  clearUpdateQueue(): void {
 | 
			
		||||
    this.pendingUpdate = {
 | 
			
		||||
      count: 0,
 | 
			
		||||
      add: {},
 | 
			
		||||
      remove: {},
 | 
			
		||||
      change: {},
 | 
			
		||||
    };
 | 
			
		||||
    this.lastUpdate = performance.now();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  update(add: TransactionStripped[], remove: string[], change: { txid: string, rate: number | undefined, acc: boolean | undefined }[], direction: string = 'left', resetLayout: boolean = false): void {
 | 
			
		||||
    // merge any pending changes into this update
 | 
			
		||||
    this.queueUpdate(add, remove, change);
 | 
			
		||||
    this.applyUpdate(Object.values(this.pendingUpdate.add), Object.values(this.pendingUpdate.remove), Object.values(this.pendingUpdate.change), direction, resetLayout);
 | 
			
		||||
    this.clearUpdateQueue();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  applyUpdate(add: TransactionStripped[], remove: string[], change: { txid: string, rate: number | undefined, acc: boolean | undefined }[], direction: string = 'left', resetLayout: boolean = false): void {
 | 
			
		||||
    if (this.scene) {
 | 
			
		||||
      add = add.filter(tx => !this.scene.txs[tx.txid]);
 | 
			
		||||
      remove = remove.filter(txid => this.scene.txs[txid]);
 | 
			
		||||
@ -230,6 +296,7 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On
 | 
			
		||||
      }
 | 
			
		||||
      this.scene.update(add, remove, change, direction, resetLayout);
 | 
			
		||||
      this.start();
 | 
			
		||||
      this.lastUpdate = performance.now();
 | 
			
		||||
      this.updateSearchHighlight();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
@ -370,6 +437,7 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On
 | 
			
		||||
    if (!now) {
 | 
			
		||||
      now = performance.now();
 | 
			
		||||
    }
 | 
			
		||||
    this.applyQueuedUpdates();
 | 
			
		||||
    // skip re-render if there's no change to the scene
 | 
			
		||||
    if (this.scene && this.gl) {
 | 
			
		||||
      /* SET UP SHADER UNIFORMS */
 | 
			
		||||
 | 
			
		||||
@ -13,7 +13,7 @@ export default class BlockScene {
 | 
			
		||||
  theme: ThemeService;
 | 
			
		||||
  orientation: string;
 | 
			
		||||
  flip: boolean;
 | 
			
		||||
  animationDuration: number = 900;
 | 
			
		||||
  animationDuration: number = 1000;
 | 
			
		||||
  configAnimationOffset: number | null;
 | 
			
		||||
  animationOffset: number;
 | 
			
		||||
  highlightingEnabled: boolean;
 | 
			
		||||
@ -179,7 +179,7 @@ export default class BlockScene {
 | 
			
		||||
      removed.forEach(tx => {
 | 
			
		||||
        tx.destroy();
 | 
			
		||||
      });
 | 
			
		||||
    }, 1000);
 | 
			
		||||
    }, (startTime - performance.now()) + this.animationDuration + 1000);
 | 
			
		||||
 | 
			
		||||
    if (resetLayout) {
 | 
			
		||||
      add.forEach(tx => {
 | 
			
		||||
@ -239,7 +239,7 @@ export default class BlockScene {
 | 
			
		||||
      { width: number, height: number, resolution: number, blockLimit: number, animationDuration: number, animationOffset: number,
 | 
			
		||||
        orientation: string, flip: boolean, vertexArray: FastVertexArray, theme: ThemeService, highlighting: boolean, colorFunction: ((tx: TxView) => Color) | null }
 | 
			
		||||
  ): void {
 | 
			
		||||
    this.animationDuration = animationDuration || 1000;
 | 
			
		||||
    this.animationDuration = animationDuration || this.animationDuration || 1000;
 | 
			
		||||
    this.configAnimationOffset = animationOffset;
 | 
			
		||||
    this.animationOffset = this.configAnimationOffset == null ? (this.width * 1.4) : this.configAnimationOffset;
 | 
			
		||||
    this.orientation = orientation;
 | 
			
		||||
 | 
			
		||||
@ -141,7 +141,11 @@ export class MempoolBlockOverviewComponent implements OnInit, OnDestroy, OnChang
 | 
			
		||||
      const direction = (this.blockIndex == null || this.index < this.blockIndex) ? this.poolDirection : this.chainDirection;
 | 
			
		||||
      this.blockGraph.replace(delta.added, direction);
 | 
			
		||||
    } else {
 | 
			
		||||
      this.blockGraph.update(delta.added, delta.removed, delta.changed || [], blockMined ? this.chainDirection : this.poolDirection, blockMined);
 | 
			
		||||
      if (blockMined) {
 | 
			
		||||
        this.blockGraph.update(delta.added, delta.removed, delta.changed || [], blockMined ? this.chainDirection : this.poolDirection, blockMined);
 | 
			
		||||
      } else {
 | 
			
		||||
        this.blockGraph.queueUpdate(delta.added, delta.removed, delta.changed || [], this.poolDirection);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.lastBlockHeight = this.stateService.latestBlockHeight;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user