multiblock interactivity
This commit is contained in:
		
							parent
							
								
									f7422f29dc
								
							
						
					
					
						commit
						580ac889df
					
				| @ -553,7 +553,7 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On | |||||||
|         x: cssX, |         x: cssX, | ||||||
|         y: cssY |         y: cssY | ||||||
|       }; |       }; | ||||||
|       const selected = this.scene.getTxAt({ x, y }); |       const selected = this.scene.getTxAt({ x, y: this.displayHeight - y }); | ||||||
|       const currentPreview = this.selectedTx || this.hoverTx; |       const currentPreview = this.selectedTx || this.hoverTx; | ||||||
| 
 | 
 | ||||||
|       if (selected !== currentPreview) { |       if (selected !== currentPreview) { | ||||||
| @ -627,7 +627,7 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On | |||||||
|     if (this.scene) { |     if (this.scene) { | ||||||
|       const x = cssX * window.devicePixelRatio; |       const x = cssX * window.devicePixelRatio; | ||||||
|       const y = cssY * window.devicePixelRatio; |       const y = cssY * window.devicePixelRatio; | ||||||
|       const selected = this.scene.getTxAt({ x, y }); |       const selected = this.scene.getTxAt({ x, y: this.displayHeight - y }); | ||||||
|       if (selected && selected.txid) { |       if (selected && selected.txid) { | ||||||
|         this.txClickEvent.emit({ tx: selected, keyModifier }); |         this.txClickEvent.emit({ tx: selected, keyModifier }); | ||||||
|       } |       } | ||||||
|  | |||||||
| @ -228,10 +228,14 @@ export default class BlockScene { | |||||||
|   getTxAt(position: Position): TxView | void { |   getTxAt(position: Position): TxView | void { | ||||||
|     if (this.layout) { |     if (this.layout) { | ||||||
|       const gridPosition = this.screenToGrid(position); |       const gridPosition = this.screenToGrid(position); | ||||||
|  |       if (gridPosition.x >= 0 && gridPosition.x < this.gridWidth && gridPosition.y >= 0 && gridPosition.y < this.gridHeight) { | ||||||
|         return this.layout.getTx(gridPosition); |         return this.layout.getTx(gridPosition); | ||||||
|       } else { |       } else { | ||||||
|         return null; |         return null; | ||||||
|       } |       } | ||||||
|  |     } else { | ||||||
|  |       return null; | ||||||
|  |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   setHover(tx: TxView, value: boolean): void { |   setHover(tx: TxView, value: boolean): void { | ||||||
| @ -465,7 +469,7 @@ export default class BlockScene { | |||||||
| 
 | 
 | ||||||
|   private screenToGrid(position: Position): Position { |   private screenToGrid(position: Position): Position { | ||||||
|     let x = position.x - this.x; |     let x = position.x - this.x; | ||||||
|     let y = this.height - (position.y - this.y); |     let y = position.y - this.y; | ||||||
|     let t; |     let t; | ||||||
| 
 | 
 | ||||||
|     switch (this.orientation) { |     switch (this.orientation) { | ||||||
|  | |||||||
| @ -523,6 +523,141 @@ export class BlockOverviewMultiComponent implements AfterViewInit, OnDestroy, On | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   @HostListener('document:click', ['$event']) | ||||||
|  |   clickAway(event) { | ||||||
|  |     if (!this.elRef.nativeElement.contains(event.target)) { | ||||||
|  |       const currentPreview = this.selectedTx || this.hoverTx; | ||||||
|  |       if (currentPreview) { | ||||||
|  |         for (const scene of this.scenes) { | ||||||
|  |           if (scene) { | ||||||
|  |             scene.setHover(currentPreview, false); | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |         this.start(); | ||||||
|  |       } | ||||||
|  |       this.hoverTx = null; | ||||||
|  |       this.selectedTx = null; | ||||||
|  |       this.onTxHover(null); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @HostListener('pointerup', ['$event']) | ||||||
|  |   onClick(event) { | ||||||
|  |     if (!this.canvas) { | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  |     if (event.target === this.canvas.nativeElement && event.pointerType === 'touch') { | ||||||
|  |       this.setPreviewTx(event.offsetX, event.offsetY, true); | ||||||
|  |     } else if (event.target === this.canvas.nativeElement) { | ||||||
|  |       const keyMod = event.shiftKey || event.ctrlKey || event.metaKey; | ||||||
|  |       const middleClick = event.which === 2 || event.button === 1; | ||||||
|  |       this.onTxClick(event.offsetX, event.offsetY, keyMod || middleClick); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @HostListener('pointermove', ['$event']) | ||||||
|  |   onPointerMove(event) { | ||||||
|  |     if (!this.canvas) { | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  |     if (event.target === this.canvas.nativeElement) { | ||||||
|  |       this.setPreviewTx(event.offsetX, event.offsetY, false); | ||||||
|  |     } else { | ||||||
|  |       this.onPointerLeave(event); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @HostListener('pointerleave', ['$event']) | ||||||
|  |   onPointerLeave(event) { | ||||||
|  |     if (event.pointerType !== 'touch') { | ||||||
|  |       this.setPreviewTx(-1, -1, true); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   setPreviewTx(cssX: number, cssY: number, clicked: boolean = false) { | ||||||
|  |     const x = cssX * window.devicePixelRatio; | ||||||
|  |     const y = cssY * window.devicePixelRatio; | ||||||
|  |     if (!this.selectedTx || clicked) { | ||||||
|  |       this.tooltipPosition = { | ||||||
|  |         x: cssX, | ||||||
|  |         y: cssY | ||||||
|  |       }; | ||||||
|  |       const currentPreview = this.selectedTx || this.hoverTx; | ||||||
|  |       let selected; | ||||||
|  |       for (const scene of this.scenes) { | ||||||
|  |         if (scene) { | ||||||
|  |           selected = scene.getTxAt({ x, y: this.displayHeight - y }); | ||||||
|  |           if (selected) { | ||||||
|  |             break; | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       if (selected !== currentPreview) { | ||||||
|  |         if (currentPreview) { | ||||||
|  |           for (const scene of this.scenes) { | ||||||
|  |             if (scene) { | ||||||
|  |               scene.setHover(currentPreview, false); | ||||||
|  |               break; | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |           this.start(); | ||||||
|  |         } | ||||||
|  |         if (selected) { | ||||||
|  |           for (const scene of this.scenes) { | ||||||
|  |             if (scene) { | ||||||
|  |               scene.setHover(selected, true); | ||||||
|  |               break; | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |           this.start(); | ||||||
|  |           if (clicked) { | ||||||
|  |             this.selectedTx = selected; | ||||||
|  |           } else { | ||||||
|  |             this.hoverTx = selected; | ||||||
|  |             this.onTxHover(this.hoverTx ? this.hoverTx.txid : null); | ||||||
|  |           } | ||||||
|  |         } else { | ||||||
|  |           if (clicked) { | ||||||
|  |             this.selectedTx = null; | ||||||
|  |           } | ||||||
|  |           this.hoverTx = null; | ||||||
|  |           this.onTxHover(null); | ||||||
|  |         } | ||||||
|  |       } else if (clicked) { | ||||||
|  |         if (selected === this.selectedTx) { | ||||||
|  |           this.hoverTx = this.selectedTx; | ||||||
|  |           this.selectedTx = null; | ||||||
|  |           this.onTxHover(this.hoverTx ? this.hoverTx.txid : null); | ||||||
|  |         } else { | ||||||
|  |           this.selectedTx = selected; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   updateSearchHighlight(): void { | ||||||
|  |     if (this.highlightTx && this.highlightTx.txid !== this.searchText) { | ||||||
|  |       for (const scene of this.scenes) { | ||||||
|  |         if (scene) { | ||||||
|  |           scene.setHighlight(this.highlightTx, false); | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |       this.start(); | ||||||
|  |     } else if (this.searchText && this.searchText.length === 64) { | ||||||
|  |       for (const scene of this.scenes) { | ||||||
|  |         if (scene) { | ||||||
|  |           const highlightTx = scene.txs[this.searchText]; | ||||||
|  |           if (highlightTx) { | ||||||
|  |             scene.setHighlight(highlightTx, true); | ||||||
|  |             this.highlightTx = highlightTx; | ||||||
|  |             this.start(); | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   setHighlightingEnabled(enabled: boolean): void { |   setHighlightingEnabled(enabled: boolean): void { | ||||||
|     for (const scene of this.scenes) { |     for (const scene of this.scenes) { | ||||||
|       scene.setHighlighting(enabled); |       scene.setHighlighting(enabled); | ||||||
| @ -530,6 +665,24 @@ export class BlockOverviewMultiComponent implements AfterViewInit, OnDestroy, On | |||||||
|     this.start(); |     this.start(); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   onTxClick(cssX: number, cssY: number, keyModifier: boolean = false) { | ||||||
|  |     for (const scene of this.scenes) { | ||||||
|  |       if (scene) { | ||||||
|  |         const x = cssX * window.devicePixelRatio; | ||||||
|  |         const y = cssY * window.devicePixelRatio; | ||||||
|  |         const selected = scene.getTxAt({ x, y: this.displayHeight - y }); | ||||||
|  |         if (selected && selected.txid) { | ||||||
|  |           this.txClickEvent.emit({ tx: selected, keyModifier }); | ||||||
|  |           return; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   onTxHover(hoverId: string) { | ||||||
|  |     this.txHoverEvent.emit(hoverId); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   getColorFunction(): ((tx: TxView) => Color) { |   getColorFunction(): ((tx: TxView) => Color) { | ||||||
|     if (this.overrideColors) { |     if (this.overrideColors) { | ||||||
|       return this.overrideColors; |       return this.overrideColors; | ||||||
|  | |||||||
| @ -11,4 +11,5 @@ | |||||||
|   [animationDuration]="animationDuration" |   [animationDuration]="animationDuration" | ||||||
|   [animationOffset]="animationOffset" |   [animationOffset]="animationOffset" | ||||||
|   [disableSpinner]="true" |   [disableSpinner]="true" | ||||||
|  |   (txClickEvent)="onTxClick($event)" | ||||||
| ></app-block-overview-multi> | ></app-block-overview-multi> | ||||||
| @ -12,6 +12,7 @@ import { BytesPipe } from '../../shared/pipes/bytes-pipe/bytes.pipe'; | |||||||
| import { BlockOverviewMultiComponent } from '../block-overview-multi/block-overview-multi.component'; | import { BlockOverviewMultiComponent } from '../block-overview-multi/block-overview-multi.component'; | ||||||
| import { CacheService } from '../../services/cache.service'; | import { CacheService } from '../../services/cache.service'; | ||||||
| import { isMempoolDelta, MempoolBlockDelta } from '../../interfaces/websocket.interface'; | import { isMempoolDelta, MempoolBlockDelta } from '../../interfaces/websocket.interface'; | ||||||
|  | import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe'; | ||||||
| 
 | 
 | ||||||
| function bestFitResolution(min, max, n): number { | function bestFitResolution(min, max, n): number { | ||||||
|   const target = (min + max) / 2; |   const target = (min + max) / 2; | ||||||
| @ -53,7 +54,6 @@ export class EightMempoolComponent implements OnInit, OnDestroy { | |||||||
|   queryParamsSubscription: Subscription; |   queryParamsSubscription: Subscription; | ||||||
|   graphChangeSubscription: Subscription; |   graphChangeSubscription: Subscription; | ||||||
|   blockSub: Subscription; |   blockSub: Subscription; | ||||||
|   mempoolBlockSub: Subscription; |  | ||||||
| 
 | 
 | ||||||
|   chainDirection: string = 'right'; |   chainDirection: string = 'right'; | ||||||
|   poolDirection: string = 'left'; |   poolDirection: string = 'left'; | ||||||
| @ -178,10 +178,18 @@ export class EightMempoolComponent implements OnInit, OnDestroy { | |||||||
|       .subscribe((network) => this.network = network); |       .subscribe((network) => this.network = network); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   onTxClick(event: { tx: TransactionStripped, keyModifier: boolean }): void { | ||||||
|  |     const url = new RelativeUrlPipe(this.stateService).transform(`/tx/${event.tx.txid}`); | ||||||
|  |     if (!event.keyModifier) { | ||||||
|  |       this.router.navigate([url]); | ||||||
|  |     } else { | ||||||
|  |       window.open(url, '_blank'); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   ngOnDestroy(): void { |   ngOnDestroy(): void { | ||||||
|     this.stateService.markBlock$.next({}); |     this.stateService.markBlock$.next({}); | ||||||
|     this.blockSub.unsubscribe(); |     this.blockSub.unsubscribe(); | ||||||
|     this.mempoolBlockSub.unsubscribe(); |  | ||||||
|     this.networkChangedSubscription?.unsubscribe(); |     this.networkChangedSubscription?.unsubscribe(); | ||||||
|     this.queryParamsSubscription?.unsubscribe(); |     this.queryParamsSubscription?.unsubscribe(); | ||||||
|   } |   } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user