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,7 +228,11 @@ 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);
 | 
				
			||||||
      return this.layout.getTx(gridPosition);
 | 
					      if (gridPosition.x >= 0 && gridPosition.x < this.gridWidth && gridPosition.y >= 0 && gridPosition.y < this.gridHeight) {
 | 
				
			||||||
 | 
					        return this.layout.getTx(gridPosition);
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        return null;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      return null;
 | 
					      return null;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -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