diff --git a/frontend/src/app/components/search-form/search-form.component.ts b/frontend/src/app/components/search-form/search-form.component.ts
index 2361f8873..2fc25748e 100644
--- a/frontend/src/app/components/search-form/search-form.component.ts
+++ b/frontend/src/app/components/search-form/search-form.component.ts
@@ -1,6 +1,6 @@
import { Component, OnInit, ChangeDetectionStrategy, EventEmitter, Output, ViewChild, HostListener, ElementRef } from '@angular/core';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
-import { Router } from '@angular/router';
+import { EventType, NavigationStart, Router } from '@angular/router';
import { AssetsService } from '../../services/assets.service';
import { StateService } from '../../services/state.service';
import { Observable, of, Subject, zip, BehaviorSubject, combineLatest } from 'rxjs';
@@ -47,6 +47,8 @@ export class SearchFormComponent implements OnInit {
this.handleKeyDown($event);
}
+ @ViewChild('searchInput') searchInput: ElementRef;
+
constructor(
private formBuilder: UntypedFormBuilder,
private router: Router,
@@ -55,11 +57,24 @@ export class SearchFormComponent implements OnInit {
private electrsApiService: ElectrsApiService,
private apiService: ApiService,
private relativeUrlPipe: RelativeUrlPipe,
- private elementRef: ElementRef,
- ) { }
+ private elementRef: ElementRef
+ ) {
+ }
ngOnInit(): void {
this.stateService.networkChanged$.subscribe((network) => this.network = network);
+
+ this.router.events.subscribe((e: NavigationStart) => { // Reset search focus when changing page
+ if (e.type === EventType.NavigationStart) {
+ this.searchInput.nativeElement.blur();
+ }
+ });
+
+ this.stateService.searchFocus$.subscribe(focus => {
+ if (this.searchInput && focus === true) {
+ this.searchInput.nativeElement.focus();
+ }
+ });
this.searchForm = this.formBuilder.group({
searchText: ['', Validators.required],
diff --git a/frontend/src/app/dashboard/dashboard.component.ts b/frontend/src/app/dashboard/dashboard.component.ts
index aca3593d7..a9c0bb31c 100644
--- a/frontend/src/app/dashboard/dashboard.component.ts
+++ b/frontend/src/app/dashboard/dashboard.component.ts
@@ -1,7 +1,7 @@
-import { ChangeDetectionStrategy, Component, OnDestroy, OnInit } from '@angular/core';
+import { AfterViewChecked, ChangeDetectionStrategy, Component, OnDestroy, OnInit } from '@angular/core';
import { combineLatest, merge, Observable, of, Subscription } from 'rxjs';
import { filter, map, scan, share, switchMap, tap } from 'rxjs/operators';
-import { BlockExtended, OptimizedMempoolStats, RbfTree } from '../interfaces/node-api.interface';
+import { BlockExtended, OptimizedMempoolStats } from '../interfaces/node-api.interface';
import { MempoolInfo, TransactionStripped, ReplacementInfo } from '../interfaces/websocket.interface';
import { ApiService } from '../services/api.service';
import { StateService } from '../services/state.service';
@@ -31,7 +31,7 @@ interface MempoolStatsData {
styleUrls: ['./dashboard.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
-export class DashboardComponent implements OnInit, OnDestroy {
+export class DashboardComponent implements OnInit, OnDestroy, AfterViewChecked {
featuredAssets$: Observable
;
network$: Observable;
mempoolBlocksData$: Observable;
@@ -57,6 +57,10 @@ export class DashboardComponent implements OnInit, OnDestroy {
private seoService: SeoService
) { }
+ ngAfterViewChecked(): void {
+ this.stateService.searchFocus$.next(true);
+ }
+
ngOnDestroy(): void {
this.currencySubscription.unsubscribe();
this.websocketService.stopTrackRbfSummary();
diff --git a/frontend/src/app/services/state.service.ts b/frontend/src/app/services/state.service.ts
index 5ebca9ba1..2c4f06b49 100644
--- a/frontend/src/app/services/state.service.ts
+++ b/frontend/src/app/services/state.service.ts
@@ -138,6 +138,8 @@ export class StateService {
fiatCurrency$: BehaviorSubject;
rateUnits$: BehaviorSubject;
+ searchFocus$: Subject = new Subject();
+
constructor(
@Inject(PLATFORM_ID) private platformId: any,
@Inject(LOCALE_ID) private locale: string,
From da4a20cb8574916681602b0b995ca93fd2fe4b04 Mon Sep 17 00:00:00 2001
From: nymkappa <1612910616@pm.me>
Date: Mon, 24 Jul 2023 11:35:46 +0900
Subject: [PATCH 2/5] [search bar] dont auto focus if touch screen
---
.../mining-dashboard.component.ts | 2 +-
.../src/app/dashboard/dashboard.component.ts | 2 +-
frontend/src/app/services/state.service.ts | 7 +++++
.../src/app/shared/pipes/bytes-pipe/utils.ts | 26 +++++++++++++++++++
4 files changed, 35 insertions(+), 2 deletions(-)
diff --git a/frontend/src/app/components/mining-dashboard/mining-dashboard.component.ts b/frontend/src/app/components/mining-dashboard/mining-dashboard.component.ts
index 22d0e11fe..c7670bc1e 100644
--- a/frontend/src/app/components/mining-dashboard/mining-dashboard.component.ts
+++ b/frontend/src/app/components/mining-dashboard/mining-dashboard.component.ts
@@ -23,6 +23,6 @@ export class MiningDashboardComponent implements OnInit, AfterViewChecked {
}
ngAfterViewChecked(): void {
- this.stateService.searchFocus$.next(true);
+ this.stateService.focusSearchInputDesktop();
}
}
diff --git a/frontend/src/app/dashboard/dashboard.component.ts b/frontend/src/app/dashboard/dashboard.component.ts
index a9c0bb31c..6d61953cf 100644
--- a/frontend/src/app/dashboard/dashboard.component.ts
+++ b/frontend/src/app/dashboard/dashboard.component.ts
@@ -58,7 +58,7 @@ export class DashboardComponent implements OnInit, OnDestroy, AfterViewChecked {
) { }
ngAfterViewChecked(): void {
- this.stateService.searchFocus$.next(true);
+ this.stateService.focusSearchInputDesktop();
}
ngOnDestroy(): void {
diff --git a/frontend/src/app/services/state.service.ts b/frontend/src/app/services/state.service.ts
index 2c4f06b49..bebe751d6 100644
--- a/frontend/src/app/services/state.service.ts
+++ b/frontend/src/app/services/state.service.ts
@@ -7,6 +7,7 @@ import { Router, NavigationStart } from '@angular/router';
import { isPlatformBrowser } from '@angular/common';
import { filter, map, scan, shareReplay } from 'rxjs/operators';
import { StorageService } from './storage.service';
+import { hasTouchScreen } from '../shared/pipes/bytes-pipe/utils';
export interface MarkBlockState {
blockHeight?: number;
@@ -357,4 +358,10 @@ export class StateService {
this.blocks = this.blocks.slice(0, this.env.KEEP_BLOCKS_AMOUNT);
this.blocksSubject$.next(this.blocks);
}
+
+ focusSearchInputDesktop() {
+ if (!hasTouchScreen()) {
+ this.searchFocus$.next(true);
+ }
+ }
}
diff --git a/frontend/src/app/shared/pipes/bytes-pipe/utils.ts b/frontend/src/app/shared/pipes/bytes-pipe/utils.ts
index fc8c2b08f..86a1e1a1d 100644
--- a/frontend/src/app/shared/pipes/bytes-pipe/utils.ts
+++ b/frontend/src/app/shared/pipes/bytes-pipe/utils.ts
@@ -309,3 +309,29 @@ export function takeWhile(input: any[], predicate: CollectionPredicate) {
return takeUntil(input, (item: any, index: number | undefined, collection: any[] | undefined) =>
!predicate(item, index, collection));
}
+
+// https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent
+export function hasTouchScreen(): boolean {
+ let hasTouchScreen = false;
+ if ('maxTouchPoints' in navigator) {
+ hasTouchScreen = navigator.maxTouchPoints > 0;
+ } else if ('msMaxTouchPoints' in navigator) {
+ // @ts-ignore
+ hasTouchScreen = navigator.msMaxTouchPoints > 0;
+ } else {
+ const mQ = matchMedia?.('(pointer:coarse)');
+ if (mQ?.media === '(pointer:coarse)') {
+ hasTouchScreen = !!mQ.matches;
+ } else if ('orientation' in window) {
+ hasTouchScreen = true; // deprecated, but good fallback
+ } else {
+ // @ts-ignore - Only as a last resort, fall back to user agent sniffing
+ const UA = navigator.userAgent;
+ hasTouchScreen =
+ /\b(BlackBerry|webOS|iPhone|IEMobile)\b/i.test(UA) ||
+ /\b(Android|Windows Phone|iPad|iPod)\b/i.test(UA);
+ }
+ }
+ console.log(hasTouchScreen);
+ return hasTouchScreen;
+}
\ No newline at end of file
From 7db391d762514c3ed55fba67ba17f2b82729af7b Mon Sep 17 00:00:00 2001
From: nymkappa <1612910616@pm.me>
Date: Mon, 24 Jul 2023 11:51:15 +0900
Subject: [PATCH 3/5] [search bar] add missing autofocus on lightning dashboard
---
.../lightning-dashboard/lightning-dashboard.component.ts | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/frontend/src/app/lightning/lightning-dashboard/lightning-dashboard.component.ts b/frontend/src/app/lightning/lightning-dashboard/lightning-dashboard.component.ts
index 6fa4b454c..adaa8d115 100644
--- a/frontend/src/app/lightning/lightning-dashboard/lightning-dashboard.component.ts
+++ b/frontend/src/app/lightning/lightning-dashboard/lightning-dashboard.component.ts
@@ -1,4 +1,4 @@
-import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
+import { AfterViewChecked, ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
import { share } from 'rxjs/operators';
import { INodesRanking } from '../../interfaces/node-api.interface';
@@ -12,7 +12,7 @@ import { LightningApiService } from '../lightning-api.service';
styleUrls: ['./lightning-dashboard.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
-export class LightningDashboardComponent implements OnInit {
+export class LightningDashboardComponent implements OnInit, AfterViewChecked {
statistics$: Observable;
nodesRanking$: Observable;
officialMempoolSpace = this.stateService.env.OFFICIAL_MEMPOOL_SPACE;
@@ -30,4 +30,7 @@ export class LightningDashboardComponent implements OnInit {
this.statistics$ = this.lightningApiService.getLatestStatistics$().pipe(share());
}
+ ngAfterViewChecked(): void {
+ this.stateService.focusSearchInputDesktop();
+ }
}
From 07b0f24cf15d2e72a3b0458969278733addcb9dc Mon Sep 17 00:00:00 2001
From: softsimon
Date: Tue, 25 Jul 2023 14:26:43 +0900
Subject: [PATCH 4/5] Update frontend/src/app/shared/pipes/bytes-pipe/utils.ts
---
frontend/src/app/shared/pipes/bytes-pipe/utils.ts | 1 -
1 file changed, 1 deletion(-)
diff --git a/frontend/src/app/shared/pipes/bytes-pipe/utils.ts b/frontend/src/app/shared/pipes/bytes-pipe/utils.ts
index 86a1e1a1d..2700be45d 100644
--- a/frontend/src/app/shared/pipes/bytes-pipe/utils.ts
+++ b/frontend/src/app/shared/pipes/bytes-pipe/utils.ts
@@ -332,6 +332,5 @@ export function hasTouchScreen(): boolean {
/\b(Android|Windows Phone|iPad|iPod)\b/i.test(UA);
}
}
- console.log(hasTouchScreen);
return hasTouchScreen;
}
\ No newline at end of file
From 6d5be78dd06d2b13a6636201eb1d1cb960e50a2f Mon Sep 17 00:00:00 2001
From: nymkappa <1612910616@pm.me>
Date: Tue, 25 Jul 2023 15:03:39 +0900
Subject: [PATCH 5/5] [search bar] use afterviewinit instead of
afterviewchecked
---
.../mining-dashboard.component.ts | 17 +++++++++++++----
.../search-form/search-form.component.ts | 8 +++++---
.../src/app/dashboard/dashboard.component.ts | 6 +++---
.../lightning-dashboard.component.ts | 6 +++---
4 files changed, 24 insertions(+), 13 deletions(-)
diff --git a/frontend/src/app/components/mining-dashboard/mining-dashboard.component.ts b/frontend/src/app/components/mining-dashboard/mining-dashboard.component.ts
index c7670bc1e..6353ab8b8 100644
--- a/frontend/src/app/components/mining-dashboard/mining-dashboard.component.ts
+++ b/frontend/src/app/components/mining-dashboard/mining-dashboard.component.ts
@@ -1,7 +1,8 @@
-import { AfterViewChecked, ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
+import { AfterViewInit, ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { SeoService } from '../../services/seo.service';
import { WebsocketService } from '../../services/websocket.service';
import { StateService } from '../../services/state.service';
+import { EventType, NavigationStart, Router } from '@angular/router';
@Component({
selector: 'app-mining-dashboard',
@@ -9,11 +10,12 @@ import { StateService } from '../../services/state.service';
styleUrls: ['./mining-dashboard.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
-export class MiningDashboardComponent implements OnInit, AfterViewChecked {
+export class MiningDashboardComponent implements OnInit, AfterViewInit {
constructor(
private seoService: SeoService,
private websocketService: WebsocketService,
- private stateService: StateService
+ private stateService: StateService,
+ private router: Router
) {
this.seoService.setTitle($localize`:@@a681a4e2011bb28157689dbaa387de0dd0aa0c11:Mining Dashboard`);
}
@@ -22,7 +24,14 @@ export class MiningDashboardComponent implements OnInit, AfterViewChecked {
this.websocketService.want(['blocks', 'mempool-blocks', 'stats']);
}
- ngAfterViewChecked(): void {
+ ngAfterViewInit(): void {
this.stateService.focusSearchInputDesktop();
+ this.router.events.subscribe((e: NavigationStart) => {
+ if (e.type === EventType.NavigationStart) {
+ if (e.url.indexOf('graphs') === -1) { // The mining dashboard and the graph component are part of the same module so we can't use ngAfterViewInit in graphs.component.ts to blur the input
+ this.stateService.focusSearchInputDesktop();
+ }
+ }
+ });
}
}
diff --git a/frontend/src/app/components/search-form/search-form.component.ts b/frontend/src/app/components/search-form/search-form.component.ts
index 2fc25748e..61b3351b7 100644
--- a/frontend/src/app/components/search-form/search-form.component.ts
+++ b/frontend/src/app/components/search-form/search-form.component.ts
@@ -65,13 +65,15 @@ export class SearchFormComponent implements OnInit {
this.stateService.networkChanged$.subscribe((network) => this.network = network);
this.router.events.subscribe((e: NavigationStart) => { // Reset search focus when changing page
- if (e.type === EventType.NavigationStart) {
+ if (this.searchInput && e.type === EventType.NavigationStart) {
this.searchInput.nativeElement.blur();
}
});
- this.stateService.searchFocus$.subscribe(focus => {
- if (this.searchInput && focus === true) {
+ this.stateService.searchFocus$.subscribe(() => {
+ if (!this.searchInput) { // Try again a bit later once the view is properly initialized
+ setTimeout(() => this.searchInput.nativeElement.focus(), 100);
+ } else if (this.searchInput) {
this.searchInput.nativeElement.focus();
}
});
diff --git a/frontend/src/app/dashboard/dashboard.component.ts b/frontend/src/app/dashboard/dashboard.component.ts
index 6d61953cf..05381453d 100644
--- a/frontend/src/app/dashboard/dashboard.component.ts
+++ b/frontend/src/app/dashboard/dashboard.component.ts
@@ -1,4 +1,4 @@
-import { AfterViewChecked, ChangeDetectionStrategy, Component, OnDestroy, OnInit } from '@angular/core';
+import { AfterViewInit, ChangeDetectionStrategy, Component, OnDestroy, OnInit } from '@angular/core';
import { combineLatest, merge, Observable, of, Subscription } from 'rxjs';
import { filter, map, scan, share, switchMap, tap } from 'rxjs/operators';
import { BlockExtended, OptimizedMempoolStats } from '../interfaces/node-api.interface';
@@ -31,7 +31,7 @@ interface MempoolStatsData {
styleUrls: ['./dashboard.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
-export class DashboardComponent implements OnInit, OnDestroy, AfterViewChecked {
+export class DashboardComponent implements OnInit, OnDestroy, AfterViewInit {
featuredAssets$: Observable;
network$: Observable;
mempoolBlocksData$: Observable;
@@ -57,7 +57,7 @@ export class DashboardComponent implements OnInit, OnDestroy, AfterViewChecked {
private seoService: SeoService
) { }
- ngAfterViewChecked(): void {
+ ngAfterViewInit(): void {
this.stateService.focusSearchInputDesktop();
}
diff --git a/frontend/src/app/lightning/lightning-dashboard/lightning-dashboard.component.ts b/frontend/src/app/lightning/lightning-dashboard/lightning-dashboard.component.ts
index adaa8d115..e58d5f124 100644
--- a/frontend/src/app/lightning/lightning-dashboard/lightning-dashboard.component.ts
+++ b/frontend/src/app/lightning/lightning-dashboard/lightning-dashboard.component.ts
@@ -1,4 +1,4 @@
-import { AfterViewChecked, ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
+import { AfterViewInit, ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
import { share } from 'rxjs/operators';
import { INodesRanking } from '../../interfaces/node-api.interface';
@@ -12,7 +12,7 @@ import { LightningApiService } from '../lightning-api.service';
styleUrls: ['./lightning-dashboard.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
-export class LightningDashboardComponent implements OnInit, AfterViewChecked {
+export class LightningDashboardComponent implements OnInit, AfterViewInit {
statistics$: Observable;
nodesRanking$: Observable;
officialMempoolSpace = this.stateService.env.OFFICIAL_MEMPOOL_SPACE;
@@ -30,7 +30,7 @@ export class LightningDashboardComponent implements OnInit, AfterViewChecked {
this.statistics$ = this.lightningApiService.getLatestStatistics$().pipe(share());
}
- ngAfterViewChecked(): void {
+ ngAfterViewInit(): void {
this.stateService.focusSearchInputDesktop();
}
}