From 52cc0d54850e0acf069d2f95d063826f16ff5238 Mon Sep 17 00:00:00 2001 From: Rigel Kent Date: Mon, 3 Feb 2020 14:04:42 +0100 Subject: Gracefully downsize search bar for mobile devices --- .../src/app/header/search-typeahead.component.ts | 86 ++++++++++++++++------ 1 file changed, 63 insertions(+), 23 deletions(-) (limited to 'client/src/app/header/search-typeahead.component.ts') diff --git a/client/src/app/header/search-typeahead.component.ts b/client/src/app/header/search-typeahead.component.ts index 084bdd58b..514c04704 100644 --- a/client/src/app/header/search-typeahead.component.ts +++ b/client/src/app/header/search-typeahead.component.ts @@ -7,13 +7,15 @@ import { OnDestroy, QueryList } from '@angular/core' -import { Router, NavigationEnd } from '@angular/router' +import { Router, NavigationEnd, Params, ActivatedRoute } from '@angular/router' import { AuthService } from '@app/core' import { I18n } from '@ngx-translate/i18n-polyfill' -import { filter } from 'rxjs/operators' +import { filter, first, tap, map } 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 { SuggestionComponent, Result } from './suggestion.component' +import { of } from 'rxjs' +import { getParameterByName } from '@app/shared/misc/utils' @Component({ selector: 'my-search-typeahead', @@ -41,6 +43,7 @@ export class SearchTypeaheadComponent implements OnInit, OnDestroy, AfterViewIni constructor ( private authService: AuthService, private router: Router, + private route: ActivatedRoute, 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.') @@ -50,12 +53,19 @@ export class SearchTypeaheadComponent implements OnInit, OnDestroy, AfterViewIni ngOnInit () { this.router.events - .pipe(filter(event => event instanceof NavigationEnd)) + .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 || '') } ngOnDestroy () { @@ -82,33 +92,33 @@ export class SearchTypeaheadComponent implements OnInit, OnDestroy, AfterViewIni computeResults () { this.newSearch = true - let results = [ - { - text: 'MaƮtre poney', - type: 'channel' - } - ] + let results: Result[] = [] if (this.hasSearch) { results = [ + /* Channel search is still unimplemented. Uncomment when it is. { text: this.searchInput.value, type: 'search-channel' }, + */ { text: this.searchInput.value, - type: 'search-instance' + type: 'search-instance', + default: true }, + /* Global search is still unimplemented. Uncomment when it is. { text: this.searchInput.value, 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 @@ -118,19 +128,26 @@ export class SearchTypeaheadComponent implements OnInit, OnDestroy, AfterViewIni ) } + 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) ) } @@ -141,17 +158,40 @@ export class SearchTypeaheadComponent implements OnInit, OnDestroy, AfterViewIni 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.searchInput.value }) + + 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 })) + ) + } } -- cgit v1.2.3