X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=client%2Fsrc%2Fapp%2Fheader%2Fsearch-typeahead.component.ts;h=c265f2c83d16777777621a8ba3205adffbed7471;hb=9b8a7aa8ea128f7e197ff38ca9f86ffa53bbe110;hp=084bdd58be24a3b25b72a9f9ce06eb790a48c1ce;hpb=6af662a5961b48ac12682df2b8b971060a2cc67d;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 084bdd58b..c265f2c83 100644 --- a/client/src/app/header/search-typeahead.component.ts +++ b/client/src/app/header/search-typeahead.component.ts @@ -1,19 +1,21 @@ import { Component, - ViewChild, - ElementRef, AfterViewInit, OnInit, OnDestroy, - QueryList + QueryList, + ViewChild, + ElementRef } from '@angular/core' -import { Router, NavigationEnd } from '@angular/router' -import { AuthService } from '@app/core' -import { I18n } from '@ngx-translate/i18n-polyfill' -import { filter } from 'rxjs/operators' +import { Router, Params, ActivatedRoute } from '@angular/router' +import { AuthService, ServerService } from '@app/core' +import { first, tap } from 'rxjs/operators' import { ListKeyManager } from '@angular/cdk/a11y' -import { UP_ARROW, DOWN_ARROW, ENTER, TAB } from '@angular/cdk/keycodes' -import { SuggestionComponent } from './suggestion.component' +import { UP_ARROW, DOWN_ARROW, ENTER } from '@angular/cdk/keycodes' +import { SuggestionComponent, Result } from './suggestion.component' +import { of } from 'rxjs' +import { getParameterByName } from '@app/shared/misc/utils' +import { ServerConfig } from '@shared/models' @Component({ selector: 'my-search-typeahead', @@ -21,19 +23,16 @@ import { SuggestionComponent } from './suggestion.component' styleUrls: [ './search-typeahead.component.scss' ] }) export class SearchTypeaheadComponent implements OnInit, OnDestroy, AfterViewInit { - @ViewChild('contentWrapper', { static: true }) contentWrapper: ElementRef + @ViewChild('searchVideo', { static: true }) searchInput: ElementRef hasChannel = false inChannel = false newSearch = true - searchInput: HTMLInputElement - URIPolicy: 'only-followed' | 'any' = 'any' + search = '' + serverConfig: ServerConfig - URIPolicyText: string - inAllText: string inThisChannelText: string - globalSearchIndex = 'https://index.joinpeertube.org' keyboardEventsManager: ListKeyManager results: any[] = [] @@ -41,21 +40,13 @@ export class SearchTypeaheadComponent implements OnInit, OnDestroy, AfterViewIni constructor ( private authService: AuthService, private router: Router, - 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 route: ActivatedRoute, + private serverService: ServerService + ) {} ngOnInit () { - this.router.events - .pipe(filter(event => event instanceof NavigationEnd)) - .subscribe((event: NavigationEnd) => { - this.hasChannel = event.url.startsWith('/videos/watch') - this.inChannel = event.url.startsWith('/video-channels') - this.computeResults() - }) + this.serverService.getConfig() + .subscribe(config => this.serverConfig = config) } ngOnDestroy () { @@ -63,95 +54,131 @@ export class SearchTypeaheadComponent implements OnInit, OnDestroy, AfterViewIni } 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 hasSearch () { - return !!this.searchInput && !!this.searchInput.value + this.search = getParameterByName('search', window.location.href) || '' } get activeResult () { return this.keyboardEventsManager && this.keyboardEventsManager.activeItem && this.keyboardEventsManager.activeItem.result } + get showInstructions () { + return !this.search + } + get showHelp () { - return this.hasSearch && this.newSearch && this.activeResult && this.activeResult.type === 'search-global' || false + return this.search && this.newSearch && this.activeResult && this.activeResult.type === 'search-global' || false + } + + get anyURI () { + if (!this.serverConfig) return false + return this.authService.isLoggedIn() + ? this.serverConfig.search.remoteUri.users + : this.serverConfig.search.remoteUri.anonymous + } + + onSearchChange () { + this.computeResults() } computeResults () { this.newSearch = true - let results = [ - { - text: 'Maître poney', - type: 'channel' - } - ] + 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, - type: 'search-instance' + 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' }, + */ ...results ] } this.results = results.filter( - result => { + (result: Result) => { // 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 } ) } + setEventItems (event: { items: QueryList, index?: number }) { + event.items.forEach(e => { + if (this.keyboardEventsManager.activeItem && this.keyboardEventsManager.activeItem === e) { + this.keyboardEventsManager.activeItem.active = true + } else { + e.active = false + } + }) + } + 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) - event.items.forEach(e => e.active = false) - this.keyboardEventsManager.activeItem.active = true + } else { + this.keyboardEventsManager.setFirstItemActive() } this.keyboardEventsManager.change.subscribe( - val => { - event.items.forEach(e => e.active = false) - this.keyboardEventsManager.activeItem.active = true - } + _ => this.setEventItems(event) ) } - isUserLoggedIn () { - return this.authService.isLoggedIn() - } - handleKeyUp (event: KeyboardEvent, indexSelected?: number) { event.stopImmediatePropagation() if (this.keyboardEventsManager) { - if (event.keyCode === TAB) { - this.keyboardEventsManager.setNextItemActive() - return false - } else if (event.keyCode === DOWN_ARROW || event.keyCode === UP_ARROW) { + if (event.keyCode === DOWN_ARROW || event.keyCode === UP_ARROW) { this.keyboardEventsManager.onKeydown(event) return false } else if (event.keyCode === ENTER) { this.newSearch = false - // this.router.navigate(this.keyboardEventsManager.activeItem.result) + this.doSearch() return false } } } + + doSearch () { + const queryParams: Params = {} + + if (window.location.pathname === '/search' && this.route.snapshot.queryParams) { + Object.assign(queryParams, this.route.snapshot.queryParams) + } + + Object.assign(queryParams, { search: this.search }) + + const o = this.authService.isLoggedIn() + ? this.loadUserLanguagesIfNeeded(queryParams) + : of(true) + + o.subscribe(() => this.router.navigate([ '/search' ], { queryParams })) + } + + private loadUserLanguagesIfNeeded (queryParams: any) { + if (queryParams && queryParams.languageOneOf) return of(queryParams) + + return this.authService.userInformationLoaded + .pipe( + first(), + tap(() => Object.assign(queryParams, { languageOneOf: this.authService.getUser().videoLanguages })) + ) + } }