parent
							
								
									037abbdbcb
								
							
						
					
					
						commit
						fb94be1767
					
				@ -3,8 +3,8 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms';
 | 
			
		||||
import { Router } from '@angular/router';
 | 
			
		||||
import { AssetsService } from '../../services/assets.service';
 | 
			
		||||
import { StateService } from '../../services/state.service';
 | 
			
		||||
import { Observable, of, Subject, zip, BehaviorSubject } from 'rxjs';
 | 
			
		||||
import { debounceTime, distinctUntilChanged, switchMap, catchError, map } from 'rxjs/operators';
 | 
			
		||||
import { Observable, of, Subject, zip, BehaviorSubject, combineLatest } from 'rxjs';
 | 
			
		||||
import { debounceTime, distinctUntilChanged, switchMap, catchError, map, startWith,  tap } from 'rxjs/operators';
 | 
			
		||||
import { ElectrsApiService } from '../../services/electrs-api.service';
 | 
			
		||||
import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe';
 | 
			
		||||
import { ApiService } from '../../services/api.service';
 | 
			
		||||
@ -33,7 +33,7 @@ export class SearchFormComponent implements OnInit {
 | 
			
		||||
 | 
			
		||||
  @Output() searchTriggered = new EventEmitter();
 | 
			
		||||
  @ViewChild('searchResults') searchResults: SearchResultsComponent;
 | 
			
		||||
  @HostListener('keydown', ['$event']) keydown($event) {
 | 
			
		||||
  @HostListener('keydown', ['$event']) keydown($event): void {
 | 
			
		||||
    this.handleKeyDown($event);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -47,7 +47,7 @@ export class SearchFormComponent implements OnInit {
 | 
			
		||||
    private relativeUrlPipe: RelativeUrlPipe,
 | 
			
		||||
  ) { }
 | 
			
		||||
 | 
			
		||||
  ngOnInit() {
 | 
			
		||||
  ngOnInit(): void {
 | 
			
		||||
    this.stateService.networkChanged$.subscribe((network) => this.network = network);
 | 
			
		||||
 | 
			
		||||
    this.searchForm = this.formBuilder.group({
 | 
			
		||||
@ -61,7 +61,7 @@ export class SearchFormComponent implements OnInit {
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.typeAhead$ = this.searchForm.get('searchText').valueChanges
 | 
			
		||||
    const searchText$ = this.searchForm.get('searchText').valueChanges
 | 
			
		||||
    .pipe(
 | 
			
		||||
      map((text) => {
 | 
			
		||||
        if (this.network === 'bisq' && text.match(/^(b)[^c]/i)) {
 | 
			
		||||
@ -69,30 +69,26 @@ export class SearchFormComponent implements OnInit {
 | 
			
		||||
        }
 | 
			
		||||
        return text.trim();
 | 
			
		||||
      }),
 | 
			
		||||
        debounceTime(200),
 | 
			
		||||
      distinctUntilChanged(),
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    const searchResults$ = searchText$.pipe(
 | 
			
		||||
      debounceTime(200),
 | 
			
		||||
      switchMap((text) => {
 | 
			
		||||
        if (!text.length) {
 | 
			
		||||
          return of([
 | 
			
		||||
              '',
 | 
			
		||||
            [],
 | 
			
		||||
              {
 | 
			
		||||
                nodes: [],
 | 
			
		||||
                channels: [],
 | 
			
		||||
              }
 | 
			
		||||
            { nodes: [], channels: [] }
 | 
			
		||||
          ]);
 | 
			
		||||
        }
 | 
			
		||||
        this.isTypeaheading$.next(true);
 | 
			
		||||
        if (!this.stateService.env.LIGHTNING) {
 | 
			
		||||
          return zip(
 | 
			
		||||
              of(text),
 | 
			
		||||
            this.electrsApiService.getAddressesByPrefix$(text).pipe(catchError(() => of([]))),
 | 
			
		||||
            [{ nodes: [], channels: [] }],
 | 
			
		||||
              of(this.regexBlockheight.test(text)),
 | 
			
		||||
          );
 | 
			
		||||
        }
 | 
			
		||||
        return zip(
 | 
			
		||||
            of(text),
 | 
			
		||||
          this.electrsApiService.getAddressesByPrefix$(text).pipe(catchError(() => of([]))),
 | 
			
		||||
          this.apiService.lightningSearch$(text).pipe(catchError(() => of({
 | 
			
		||||
            nodes: [],
 | 
			
		||||
@ -100,31 +96,76 @@ export class SearchFormComponent implements OnInit {
 | 
			
		||||
          }))),
 | 
			
		||||
        );
 | 
			
		||||
      }),
 | 
			
		||||
        map((result: any[]) => {
 | 
			
		||||
      tap((result: any[]) => {
 | 
			
		||||
        this.isTypeaheading$.next(false);
 | 
			
		||||
          if (this.network === 'bisq') {
 | 
			
		||||
            return result[0].map((address: string) => 'B' + address);
 | 
			
		||||
      })
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    this.typeAhead$ = combineLatest(
 | 
			
		||||
      [
 | 
			
		||||
        searchText$,
 | 
			
		||||
        searchResults$.pipe(
 | 
			
		||||
        startWith([
 | 
			
		||||
          [],
 | 
			
		||||
          {
 | 
			
		||||
            nodes: [],
 | 
			
		||||
            channels: [],
 | 
			
		||||
          }
 | 
			
		||||
        ]))
 | 
			
		||||
      ]
 | 
			
		||||
      ).pipe(
 | 
			
		||||
        map((latestData) => {
 | 
			
		||||
          const searchText = latestData[0];
 | 
			
		||||
          if (!searchText.length) {
 | 
			
		||||
            return {
 | 
			
		||||
            searchText: result[0],
 | 
			
		||||
            blockHeight: this.regexBlockheight.test(result[0]) ? [parseInt(result[0], 10)] : [],
 | 
			
		||||
            addresses: result[1],
 | 
			
		||||
            nodes: result[2].nodes,
 | 
			
		||||
            channels: result[2].channels,
 | 
			
		||||
            totalResults: result[1].length + result[2].nodes.length + result[2].channels.length,
 | 
			
		||||
              searchText: '',
 | 
			
		||||
              hashQuickMatch: false,
 | 
			
		||||
              blockHeight: false,
 | 
			
		||||
              txId: false,
 | 
			
		||||
              address: false,
 | 
			
		||||
              addresses: [],
 | 
			
		||||
              nodes: [],
 | 
			
		||||
              channels: [],
 | 
			
		||||
            };
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          const result = latestData[1];
 | 
			
		||||
          const addressPrefixSearchResults = result[0];
 | 
			
		||||
          const lightningResults = result[1];
 | 
			
		||||
 | 
			
		||||
          if (this.network === 'bisq') {
 | 
			
		||||
            return searchText.map((address: string) => 'B' + address);
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          const matchesBlockHeight = this.regexBlockheight.test(searchText);
 | 
			
		||||
          const matchesTxId = this.regexTransaction.test(searchText) && !this.regexBlockhash.test(searchText);
 | 
			
		||||
          const matchesBlockHash = this.regexBlockhash.test(searchText);
 | 
			
		||||
          const matchesAddress = this.regexAddress.test(searchText);
 | 
			
		||||
 | 
			
		||||
          return {
 | 
			
		||||
            searchText: searchText,
 | 
			
		||||
            hashQuickMatch: +(matchesBlockHeight || matchesBlockHash || matchesTxId || matchesAddress),
 | 
			
		||||
            blockHeight: matchesBlockHeight,
 | 
			
		||||
            txId: matchesTxId,
 | 
			
		||||
            blockHash: matchesBlockHash,
 | 
			
		||||
            address: matchesAddress,
 | 
			
		||||
            addresses: addressPrefixSearchResults,
 | 
			
		||||
            nodes: lightningResults.nodes,
 | 
			
		||||
            channels: lightningResults.channels,
 | 
			
		||||
          };
 | 
			
		||||
        })
 | 
			
		||||
      );
 | 
			
		||||
  }
 | 
			
		||||
  handleKeyDown($event) {
 | 
			
		||||
 | 
			
		||||
  handleKeyDown($event): void {
 | 
			
		||||
    this.searchResults.handleKeyDown($event);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  itemSelected() {
 | 
			
		||||
  itemSelected(): void {
 | 
			
		||||
    setTimeout(() => this.search());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  selectedResult(result: any) {
 | 
			
		||||
  selectedResult(result: any): void {
 | 
			
		||||
    if (typeof result === 'string') {
 | 
			
		||||
      this.search(result);
 | 
			
		||||
    } else if (typeof result === 'number') {
 | 
			
		||||
@ -136,7 +177,7 @@ export class SearchFormComponent implements OnInit {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  search(result?: string) {
 | 
			
		||||
  search(result?: string): void {
 | 
			
		||||
    const searchText = result || this.searchForm.value.searchText.trim();
 | 
			
		||||
    if (searchText) {
 | 
			
		||||
      this.isSearching = true;
 | 
			
		||||
@ -170,7 +211,7 @@ export class SearchFormComponent implements OnInit {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  navigate(url: string, searchText: string, extras?: any) {
 | 
			
		||||
  navigate(url: string, searchText: string, extras?: any): void {
 | 
			
		||||
    this.router.navigate([this.relativeUrlPipe.transform(url), searchText], extras);
 | 
			
		||||
    this.searchTriggered.emit();
 | 
			
		||||
    this.searchForm.setValue({
 | 
			
		||||
 | 
			
		||||
@ -1,14 +1,32 @@
 | 
			
		||||
<div class="dropdown-menu show" *ngIf="results" [hidden]="!results.blockHeight.length && !results.addresses.length && !results.nodes.length && !results.channels.length">
 | 
			
		||||
  <ng-template [ngIf]="results.blockHeight.length">
 | 
			
		||||
<div class="dropdown-menu show" *ngIf="results" [hidden]="!results.hashQuickMatch && !results.addresses.length && !results.nodes.length && !results.channels.length">
 | 
			
		||||
  <ng-template [ngIf]="results.blockHeight">
 | 
			
		||||
    <div class="card-title">Bitcoin Block Height</div>
 | 
			
		||||
    <button (click)="clickItem(0)" [class.active]="0 === activeIdx" type="button" role="option" class="dropdown-item">
 | 
			
		||||
      Go to "{{ results.searchText }}"
 | 
			
		||||
    </button>
 | 
			
		||||
  </ng-template>
 | 
			
		||||
  <ng-template [ngIf]="results.txId">
 | 
			
		||||
    <div class="card-title">Bitcoin Transaction</div>
 | 
			
		||||
    <button (click)="clickItem(0)" [class.active]="0 === activeIdx" type="button" role="option" class="dropdown-item">
 | 
			
		||||
      Go to "{{ results.searchText | shortenString : 13 }}"
 | 
			
		||||
    </button>
 | 
			
		||||
  </ng-template>
 | 
			
		||||
  <ng-template [ngIf]="results.address">
 | 
			
		||||
    <div class="card-title">Bitcoin Address</div>
 | 
			
		||||
    <button (click)="clickItem(0)" [class.active]="0 === activeIdx" type="button" role="option" class="dropdown-item">
 | 
			
		||||
      Go to "{{ results.searchText | shortenString : 13 }}"
 | 
			
		||||
    </button>
 | 
			
		||||
  </ng-template>
 | 
			
		||||
  <ng-template [ngIf]="results.blockHash">
 | 
			
		||||
    <div class="card-title">Bitcoin Block</div>
 | 
			
		||||
    <button (click)="clickItem(0)" [class.active]="0 === activeIdx" type="button" role="option" class="dropdown-item">
 | 
			
		||||
      Go to "{{ results.searchText | shortenString : 13 }}"
 | 
			
		||||
    </button>
 | 
			
		||||
  </ng-template>
 | 
			
		||||
  <ng-template [ngIf]="results.addresses.length">
 | 
			
		||||
    <div class="card-title" *ngIf="stateService.env.LIGHTNING">Bitcoin Addresses</div>
 | 
			
		||||
    <ng-template ngFor [ngForOf]="results.addresses" let-address let-i="index">
 | 
			
		||||
      <button (click)="clickItem(results.blockHeight.length + i)" [class.active]="(results.blockHeight.length + i) === activeIdx" type="button" role="option" class="dropdown-item">
 | 
			
		||||
      <button (click)="clickItem(results.hashQuickMatch + i)" [class.active]="(results.hashQuickMatch + i) === activeIdx" type="button" role="option" class="dropdown-item">
 | 
			
		||||
        <ngb-highlight [result]="address | shortenString : isMobile ? 25 : 36" [term]="results.searchText"></ngb-highlight>
 | 
			
		||||
      </button>
 | 
			
		||||
    </ng-template>
 | 
			
		||||
@ -16,7 +34,7 @@
 | 
			
		||||
  <ng-template [ngIf]="results.nodes.length">
 | 
			
		||||
    <div class="card-title">Lightning Nodes</div>
 | 
			
		||||
    <ng-template ngFor [ngForOf]="results.nodes" let-node let-i="index">
 | 
			
		||||
      <button (click)="clickItem(results.blockHeight.length + results.addresses.length + i)" [class.inactive]="node.status === 0" [class.active]="results.blockHeight.length + results.addresses.length + i === activeIdx" [routerLink]="['/lightning/node' | relativeUrl, node.public_key]" type="button" role="option" class="dropdown-item">
 | 
			
		||||
      <button (click)="clickItem(results.hashQuickMatch + results.addresses.length + i)" [class.inactive]="node.status === 0" [class.active]="results.hashQuickMatch + results.addresses.length + i === activeIdx" [routerLink]="['/lightning/node' | relativeUrl, node.public_key]" type="button" role="option" class="dropdown-item">
 | 
			
		||||
        <ngb-highlight [result]="node.alias" [term]="results.searchText"></ngb-highlight>  <span class="symbol">{{ node.public_key | shortenString : 10 }}</span>
 | 
			
		||||
      </button>
 | 
			
		||||
    </ng-template>
 | 
			
		||||
@ -24,7 +42,7 @@
 | 
			
		||||
  <ng-template [ngIf]="results.channels.length">
 | 
			
		||||
    <div class="card-title">Lightning Channels</div>
 | 
			
		||||
    <ng-template ngFor [ngForOf]="results.channels" let-channel let-i="index">
 | 
			
		||||
      <button (click)="clickItem(results.blockHeight.length + results.addresses.length + results.nodes.length + i)" [class.inactive]="channel.status === 2"  [class.active]="results.blockHeight.length + results.addresses.length + results.nodes.length + i === activeIdx" type="button" role="option" class="dropdown-item">
 | 
			
		||||
      <button (click)="clickItem(results.hashQuickMatch + results.addresses.length + results.nodes.length + i)" [class.inactive]="channel.status === 2"  [class.active]="results.hashQuickMatch + results.addresses.length + results.nodes.length + i === activeIdx" type="button" role="option" class="dropdown-item">
 | 
			
		||||
        <ngb-highlight [result]="channel.short_id" [term]="results.searchText"></ngb-highlight>  <span class="symbol">{{ channel.id }}</span>
 | 
			
		||||
      </button>
 | 
			
		||||
    </ng-template>
 | 
			
		||||
 | 
			
		||||
@ -22,7 +22,7 @@ export class SearchResultsComponent implements OnChanges {
 | 
			
		||||
  ngOnChanges() {
 | 
			
		||||
    this.activeIdx = 0;
 | 
			
		||||
    if (this.results) {
 | 
			
		||||
      this.resultsFlattened = [...this.results.blockHeight, ...this.results.addresses, ...this.results.nodes, ...this.results.channels];
 | 
			
		||||
      this.resultsFlattened = [...(this.results.hashQuickMatch ? [this.results.searchText] : []), ...this.results.addresses, ...this.results.nodes, ...this.results.channels];
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user