X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=client%2Fsrc%2Fapp%2Fheader%2Fsearch-typeahead.component.ts;h=2bf1072f443b1ce9752e80b0e5292e818a5fd56e;hb=140ea386dea49220f4cdd5b67027e8d30eee1b06;hp=9b414bc568b3496333f206a67e86c4325ea12238;hpb=9677fca772349248925da6c5f34f600e9a2abbe6;p=github%2FChocobozzz%2FPeerTube.git diff --git a/client/src/app/header/search-typeahead.component.ts b/client/src/app/header/search-typeahead.component.ts index 9b414bc56..2bf1072f4 100644 --- a/client/src/app/header/search-typeahead.component.ts +++ b/client/src/app/header/search-typeahead.component.ts @@ -1,21 +1,10 @@ -import { - Component, - ViewChild, - ElementRef, - AfterViewInit, - OnInit, - OnDestroy, - QueryList -} from '@angular/core' -import { Router, NavigationEnd, Params, ActivatedRoute } from '@angular/router' +import { Component, ElementRef, OnDestroy, OnInit, QueryList, ViewChild } from '@angular/core' +import { ActivatedRoute, Params, Router } from '@angular/router' import { AuthService, ServerService } from '@app/core' -import { I18n } from '@ngx-translate/i18n-polyfill' -import { filter, first, tap, map } from 'rxjs/operators' +import { first, tap } from 'rxjs/operators' import { ListKeyManager } from '@angular/cdk/a11y' -import { UP_ARROW, DOWN_ARROW, ENTER } from '@angular/cdk/keycodes' -import { SuggestionComponent, Result } from './suggestion.component' +import { Result, SuggestionComponent } from './suggestion.component' import { of } from 'rxjs' -import { getParameterByName } from '@app/shared/misc/utils' import { ServerConfig } from '@shared/models' @Component({ @@ -23,52 +12,32 @@ import { ServerConfig } from '@shared/models' templateUrl: './search-typeahead.component.html', styleUrls: [ './search-typeahead.component.scss' ] }) -export class SearchTypeaheadComponent implements OnInit, OnDestroy, AfterViewInit { - @ViewChild('contentWrapper', { static: true }) contentWrapper: ElementRef +export class SearchTypeaheadComponent implements OnInit, OnDestroy { + @ViewChild('searchVideo', { static: true }) searchInput: ElementRef hasChannel = false inChannel = false newSearch = true - searchInput: HTMLInputElement + search = '' serverConfig: ServerConfig - URIPolicyText: string - inAllText: string inThisChannelText: string - globalSearchIndex = 'https://index.joinpeertube.org' keyboardEventsManager: ListKeyManager - results: any[] = [] + results: Result[] = [] constructor ( private authService: AuthService, private router: Router, private route: ActivatedRoute, - private serverService: ServerService, - private i18n: I18n - ) { - this.URIPolicyText = this.i18n('Determines whether you can resolve any distant content, or if your instance only allows doing so for instances it follows.') - this.inAllText = this.i18n('In all PeerTube') - this.inThisChannelText = this.i18n('In this channel') - } + private serverService: ServerService + ) {} ngOnInit () { - this.router.events - .pipe(filter(e => e instanceof NavigationEnd)) - .subscribe((event: NavigationEnd) => { - this.hasChannel = event.url.startsWith('/videos/watch') - this.inChannel = event.url.startsWith('/video-channels') - this.computeResults() - }) - - this.router.events - .pipe( - filter(e => e instanceof NavigationEnd), - map(() => getParameterByName('search', window.location.href)) - ) - .subscribe(searchQuery => this.searchInput.value = searchQuery || '') - + this.route.queryParams + .pipe(first(params => this.isOnSearch() && params.search !== undefined && params.search !== null)) + .subscribe(params => this.search = params.search) this.serverService.getConfig() .subscribe(config => this.serverConfig = config) } @@ -77,54 +46,49 @@ export class SearchTypeaheadComponent implements OnInit, OnDestroy, AfterViewIni if (this.keyboardEventsManager) this.keyboardEventsManager.change.unsubscribe() } - ngAfterViewInit () { - this.searchInput = this.contentWrapper.nativeElement.childNodes[0] - this.searchInput.addEventListener('input', this.computeResults.bind(this)) - this.searchInput.addEventListener('keyup', this.handleKeyUp.bind(this)) + get activeResult () { + return this.keyboardEventsManager?.activeItem?.result } - get hasSearch () { - return !!this.searchInput && !!this.searchInput.value + get areInstructionsDisplayed () { + return !this.search } - get activeResult () { - return this.keyboardEventsManager && this.keyboardEventsManager.activeItem && this.keyboardEventsManager.activeItem.result + get showHelp () { + return this.search && this.newSearch && this.activeResult?.type === 'search-global' } - get showHelp () { - return this.hasSearch && this.newSearch && this.activeResult && this.activeResult.type === 'search-global' || false + get canSearchAnyURI () { + if (!this.serverConfig) return false + return this.authService.isLoggedIn() + ? this.serverConfig.search.remoteUri.users + : this.serverConfig.search.remoteUri.anonymous } - get URIPolicy (): 'only-followed' | 'any' { - return ( - this.authService.isLoggedIn() - ? this.serverConfig.search.remoteUri.users - : this.serverConfig.search.remoteUri.anonymous - ) - ? 'any' - : 'only-followed' + onSearchChange () { + this.computeResults() } computeResults () { this.newSearch = true let results: Result[] = [] - if (this.hasSearch) { + if (this.search) { results = [ /* Channel search is still unimplemented. Uncomment when it is. { - text: this.searchInput.value, + text: this.search, type: 'search-channel' }, */ { - text: this.searchInput.value, + text: this.search, type: 'search-instance', default: true }, /* Global search is still unimplemented. Uncomment when it is. { - text: this.searchInput.value, + text: this.search, type: 'search-global' }, */ @@ -137,7 +101,8 @@ export class SearchTypeaheadComponent implements OnInit, OnDestroy, AfterViewIni // if we're not in a channel or one of its videos/playlits, show all channel-related results if (!(this.hasChannel || this.inChannel)) return !result.type.includes('channel') // if we're in a channel, show all channel-related results except for the channel redirection itself - if (this.inChannel) return !(result.type === 'channel') + if (this.inChannel) return result.type !== 'channel' + // all other result types are kept return true } ) @@ -155,39 +120,45 @@ export class SearchTypeaheadComponent implements OnInit, OnDestroy, AfterViewIni initKeyboardEventsManager (event: { items: QueryList, index?: number }) { if (this.keyboardEventsManager) this.keyboardEventsManager.change.unsubscribe() + this.keyboardEventsManager = new ListKeyManager(event.items) + if (event.index !== undefined) { this.keyboardEventsManager.setActiveItem(event.index) } else { this.keyboardEventsManager.setFirstItemActive() } + this.keyboardEventsManager.change.subscribe( _ => this.setEventItems(event) ) } - handleKeyUp (event: KeyboardEvent, indexSelected?: number) { + handleKey (event: KeyboardEvent) { event.stopImmediatePropagation() - if (this.keyboardEventsManager) { - if (event.keyCode === DOWN_ARROW || event.keyCode === UP_ARROW) { + if (!this.keyboardEventsManager) return + + switch (event.key) { + case 'ArrowDown': + case 'ArrowUp': this.keyboardEventsManager.onKeydown(event) - return false - } else if (event.keyCode === ENTER) { - this.newSearch = false - this.doSearch() - return false - } + break } } + isOnSearch () { + return window.location.pathname === '/search' + } + doSearch () { + this.newSearch = false const queryParams: Params = {} - if (window.location.pathname === '/search' && this.route.snapshot.queryParams) { + if (this.isOnSearch() && this.route.snapshot.queryParams) { Object.assign(queryParams, this.route.snapshot.queryParams) } - Object.assign(queryParams, { search: this.searchInput.value }) + Object.assign(queryParams, { search: this.search }) const o = this.authService.isLoggedIn() ? this.loadUserLanguagesIfNeeded(queryParams)