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; |   tooltipPosition: Position; | ||||||
| 
 | 
 | ||||||
|   readyNextFrame = false; |   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; |   searchText: string; | ||||||
|   searchSubscription: Subscription; |   searchSubscription: Subscription; | ||||||
| @ -176,6 +190,7 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On | |||||||
|   destroy(): void { |   destroy(): void { | ||||||
|     if (this.scene) { |     if (this.scene) { | ||||||
|       this.scene.destroy(); |       this.scene.destroy(); | ||||||
|  |       this.clearUpdateQueue(); | ||||||
|       this.start(); |       this.start(); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| @ -188,6 +203,7 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On | |||||||
|     } |     } | ||||||
|     this.filtersAvailable = filtersAvailable; |     this.filtersAvailable = filtersAvailable; | ||||||
|     if (this.scene) { |     if (this.scene) { | ||||||
|  |       this.clearUpdateQueue(); | ||||||
|       this.scene.setup(transactions); |       this.scene.setup(transactions); | ||||||
|       this.readyNextFrame = true; |       this.readyNextFrame = true; | ||||||
|       this.start(); |       this.start(); | ||||||
| @ -197,6 +213,7 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On | |||||||
| 
 | 
 | ||||||
|   enter(transactions: TransactionStripped[], direction: string): void { |   enter(transactions: TransactionStripped[], direction: string): void { | ||||||
|     if (this.scene) { |     if (this.scene) { | ||||||
|  |       this.clearUpdateQueue(); | ||||||
|       this.scene.enter(transactions, direction); |       this.scene.enter(transactions, direction); | ||||||
|       this.start(); |       this.start(); | ||||||
|       this.updateSearchHighlight(); |       this.updateSearchHighlight(); | ||||||
| @ -205,6 +222,7 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On | |||||||
| 
 | 
 | ||||||
|   exit(direction: string): void { |   exit(direction: string): void { | ||||||
|     if (this.scene) { |     if (this.scene) { | ||||||
|  |       this.clearUpdateQueue(); | ||||||
|       this.scene.exit(direction); |       this.scene.exit(direction); | ||||||
|       this.start(); |       this.start(); | ||||||
|       this.updateSearchHighlight(); |       this.updateSearchHighlight(); | ||||||
| @ -213,13 +231,61 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On | |||||||
| 
 | 
 | ||||||
|   replace(transactions: TransactionStripped[], direction: string, sort: boolean = true, startTime?: number): void { |   replace(transactions: TransactionStripped[], direction: string, sort: boolean = true, startTime?: number): void { | ||||||
|     if (this.scene) { |     if (this.scene) { | ||||||
|  |       this.clearUpdateQueue(); | ||||||
|       this.scene.replace(transactions || [], direction, sort, startTime); |       this.scene.replace(transactions || [], direction, sort, startTime); | ||||||
|       this.start(); |       this.start(); | ||||||
|       this.updateSearchHighlight(); |       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 { |   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) { |     if (this.scene) { | ||||||
|       add = add.filter(tx => !this.scene.txs[tx.txid]); |       add = add.filter(tx => !this.scene.txs[tx.txid]); | ||||||
|       remove = remove.filter(txid => this.scene.txs[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.scene.update(add, remove, change, direction, resetLayout); | ||||||
|       this.start(); |       this.start(); | ||||||
|  |       this.lastUpdate = performance.now(); | ||||||
|       this.updateSearchHighlight(); |       this.updateSearchHighlight(); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| @ -370,6 +437,7 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On | |||||||
|     if (!now) { |     if (!now) { | ||||||
|       now = performance.now(); |       now = performance.now(); | ||||||
|     } |     } | ||||||
|  |     this.applyQueuedUpdates(); | ||||||
|     // skip re-render if there's no change to the scene
 |     // skip re-render if there's no change to the scene
 | ||||||
|     if (this.scene && this.gl) { |     if (this.scene && this.gl) { | ||||||
|       /* SET UP SHADER UNIFORMS */ |       /* SET UP SHADER UNIFORMS */ | ||||||
|  | |||||||
| @ -13,7 +13,7 @@ export default class BlockScene { | |||||||
|   theme: ThemeService; |   theme: ThemeService; | ||||||
|   orientation: string; |   orientation: string; | ||||||
|   flip: boolean; |   flip: boolean; | ||||||
|   animationDuration: number = 900; |   animationDuration: number = 1000; | ||||||
|   configAnimationOffset: number | null; |   configAnimationOffset: number | null; | ||||||
|   animationOffset: number; |   animationOffset: number; | ||||||
|   highlightingEnabled: boolean; |   highlightingEnabled: boolean; | ||||||
| @ -179,7 +179,7 @@ export default class BlockScene { | |||||||
|       removed.forEach(tx => { |       removed.forEach(tx => { | ||||||
|         tx.destroy(); |         tx.destroy(); | ||||||
|       }); |       }); | ||||||
|     }, 1000); |     }, (startTime - performance.now()) + this.animationDuration + 1000); | ||||||
| 
 | 
 | ||||||
|     if (resetLayout) { |     if (resetLayout) { | ||||||
|       add.forEach(tx => { |       add.forEach(tx => { | ||||||
| @ -239,7 +239,7 @@ export default class BlockScene { | |||||||
|       { width: number, height: number, resolution: number, blockLimit: number, animationDuration: number, animationOffset: number, |       { 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 } |         orientation: string, flip: boolean, vertexArray: FastVertexArray, theme: ThemeService, highlighting: boolean, colorFunction: ((tx: TxView) => Color) | null } | ||||||
|   ): void { |   ): void { | ||||||
|     this.animationDuration = animationDuration || 1000; |     this.animationDuration = animationDuration || this.animationDuration || 1000; | ||||||
|     this.configAnimationOffset = animationOffset; |     this.configAnimationOffset = animationOffset; | ||||||
|     this.animationOffset = this.configAnimationOffset == null ? (this.width * 1.4) : this.configAnimationOffset; |     this.animationOffset = this.configAnimationOffset == null ? (this.width * 1.4) : this.configAnimationOffset; | ||||||
|     this.orientation = orientation; |     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; |       const direction = (this.blockIndex == null || this.index < this.blockIndex) ? this.poolDirection : this.chainDirection; | ||||||
|       this.blockGraph.replace(delta.added, direction); |       this.blockGraph.replace(delta.added, direction); | ||||||
|     } else { |     } else { | ||||||
|  |       if (blockMined) { | ||||||
|         this.blockGraph.update(delta.added, delta.removed, delta.changed || [], blockMined ? this.chainDirection : this.poolDirection, 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; |     this.lastBlockHeight = this.stateService.latestBlockHeight; | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user