]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - client/src/app/header/search-typeahead.component.ts
Fix search after first type on input
[github/Chocobozzz/PeerTube.git] / client / src / app / header / search-typeahead.component.ts
CommitLineData
4c1c1709
C
1import { Component, ElementRef, OnDestroy, OnInit, QueryList, ViewChild } from '@angular/core'
2import { ActivatedRoute, Params, Router } from '@angular/router'
9677fca7 3import { AuthService, ServerService } from '@app/core'
9b8a7aa8 4import { first, tap } from 'rxjs/operators'
6af662a5 5import { ListKeyManager } from '@angular/cdk/a11y'
4c1c1709 6import { Result, SuggestionComponent } from './suggestion.component'
52cc0d54 7import { of } from 'rxjs'
9677fca7 8import { ServerConfig } from '@shared/models'
f409f0c3
RK
9
10@Component({
11 selector: 'my-search-typeahead',
12 templateUrl: './search-typeahead.component.html',
13 styleUrls: [ './search-typeahead.component.scss' ]
14})
8a979d73 15export class SearchTypeaheadComponent implements OnInit, OnDestroy {
9b8a7aa8 16 @ViewChild('searchVideo', { static: true }) searchInput: ElementRef<HTMLInputElement>
f409f0c3
RK
17
18 hasChannel = false
19 inChannel = false
6af662a5 20 newSearch = true
f409f0c3 21
9b8a7aa8 22 search = ''
9677fca7 23 serverConfig: ServerConfig
f409f0c3 24
f409f0c3
RK
25 inThisChannelText: string
26
6af662a5 27 keyboardEventsManager: ListKeyManager<SuggestionComponent>
8a979d73 28 results: Result[] = []
f409f0c3
RK
29
30 constructor (
31 private authService: AuthService,
32 private router: Router,
52cc0d54 33 private route: ActivatedRoute,
9b8a7aa8
RK
34 private serverService: ServerService
35 ) {}
f409f0c3
RK
36
37 ngOnInit () {
71e75ef2
RK
38 this.route.queryParams
39 .pipe(first(params => params.search !== undefined && params.search !== null))
40 .subscribe(params => this.search = params.search)
9677fca7
RK
41 this.serverService.getConfig()
42 .subscribe(config => this.serverConfig = config)
f409f0c3
RK
43 }
44
6af662a5
RK
45 ngOnDestroy () {
46 if (this.keyboardEventsManager) this.keyboardEventsManager.change.unsubscribe()
47 }
48
6af662a5 49 get activeResult () {
8a979d73 50 return this.keyboardEventsManager?.activeItem?.result
6af662a5
RK
51 }
52
8a979d73 53 get areInstructionsDisplayed () {
9b8a7aa8
RK
54 return !this.search
55 }
56
6af662a5 57 get showHelp () {
8a979d73 58 return this.search && this.newSearch && this.activeResult?.type === 'search-global'
6af662a5
RK
59 }
60
8a979d73 61 get canSearchAnyURI () {
9b8a7aa8
RK
62 if (!this.serverConfig) return false
63 return this.authService.isLoggedIn()
64 ? this.serverConfig.search.remoteUri.users
65 : this.serverConfig.search.remoteUri.anonymous
66 }
67
68 onSearchChange () {
69 this.computeResults()
9677fca7
RK
70 }
71
f409f0c3 72 computeResults () {
6af662a5 73 this.newSearch = true
52cc0d54 74 let results: Result[] = []
f409f0c3 75
9b8a7aa8 76 if (this.search) {
f409f0c3 77 results = [
52cc0d54 78 /* Channel search is still unimplemented. Uncomment when it is.
f409f0c3 79 {
9b8a7aa8 80 text: this.search,
f409f0c3
RK
81 type: 'search-channel'
82 },
52cc0d54 83 */
6af662a5 84 {
9b8a7aa8 85 text: this.search,
52cc0d54
RK
86 type: 'search-instance',
87 default: true
6af662a5 88 },
52cc0d54 89 /* Global search is still unimplemented. Uncomment when it is.
f409f0c3 90 {
9b8a7aa8 91 text: this.search,
f409f0c3
RK
92 type: 'search-global'
93 },
52cc0d54 94 */
f409f0c3
RK
95 ...results
96 ]
97 }
98
99 this.results = results.filter(
52cc0d54 100 (result: Result) => {
f409f0c3
RK
101 // if we're not in a channel or one of its videos/playlits, show all channel-related results
102 if (!(this.hasChannel || this.inChannel)) return !result.type.includes('channel')
103 // if we're in a channel, show all channel-related results except for the channel redirection itself
9b8a7aa8
RK
104 if (this.inChannel) return result.type !== 'channel'
105 // all other result types are kept
f409f0c3
RK
106 return true
107 }
108 )
109 }
110
52cc0d54
RK
111 setEventItems (event: { items: QueryList<SuggestionComponent>, index?: number }) {
112 event.items.forEach(e => {
113 if (this.keyboardEventsManager.activeItem && this.keyboardEventsManager.activeItem === e) {
114 this.keyboardEventsManager.activeItem.active = true
115 } else {
116 e.active = false
117 }
118 })
119 }
120
6af662a5
RK
121 initKeyboardEventsManager (event: { items: QueryList<SuggestionComponent>, index?: number }) {
122 if (this.keyboardEventsManager) this.keyboardEventsManager.change.unsubscribe()
8a979d73 123
6af662a5 124 this.keyboardEventsManager = new ListKeyManager(event.items)
8a979d73 125
6af662a5
RK
126 if (event.index !== undefined) {
127 this.keyboardEventsManager.setActiveItem(event.index)
52cc0d54
RK
128 } else {
129 this.keyboardEventsManager.setFirstItemActive()
6af662a5 130 }
8a979d73 131
6af662a5 132 this.keyboardEventsManager.change.subscribe(
52cc0d54 133 _ => this.setEventItems(event)
6af662a5
RK
134 )
135 }
136
be6343d2 137 handleKey (event: KeyboardEvent) {
f409f0c3 138 event.stopImmediatePropagation()
8a979d73 139 if (!this.keyboardEventsManager) return
4c1c1709 140
8a979d73 141 switch (event.key) {
4c1c1709
C
142 case 'ArrowDown':
143 case 'ArrowUp':
f409f0c3 144 this.keyboardEventsManager.onKeydown(event)
8a979d73 145 break
f409f0c3
RK
146 }
147 }
52cc0d54
RK
148
149 doSearch () {
be6343d2 150 this.newSearch = false
52cc0d54
RK
151 const queryParams: Params = {}
152
153 if (window.location.pathname === '/search' && this.route.snapshot.queryParams) {
154 Object.assign(queryParams, this.route.snapshot.queryParams)
155 }
156
9b8a7aa8 157 Object.assign(queryParams, { search: this.search })
52cc0d54
RK
158
159 const o = this.authService.isLoggedIn()
160 ? this.loadUserLanguagesIfNeeded(queryParams)
161 : of(true)
162
163 o.subscribe(() => this.router.navigate([ '/search' ], { queryParams }))
164 }
165
166 private loadUserLanguagesIfNeeded (queryParams: any) {
167 if (queryParams && queryParams.languageOneOf) return of(queryParams)
168
169 return this.authService.userInformationLoaded
170 .pipe(
171 first(),
172 tap(() => Object.assign(queryParams, { languageOneOf: this.authService.getUser().videoLanguages }))
173 )
174 }
f409f0c3 175}