]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - client/src/app/header/search-typeahead.component.ts
Search typeahead initial design
[github/Chocobozzz/PeerTube.git] / client / src / app / header / search-typeahead.component.ts
1 import { Component, ViewChild, ElementRef, AfterViewInit, OnInit } from '@angular/core'
2 import { Router, NavigationEnd } from '@angular/router'
3 import { AuthService } from '@app/core'
4 import { I18n } from '@ngx-translate/i18n-polyfill'
5 import { filter } from 'rxjs/operators'
6 import { ListKeyManager, ListKeyManagerOption } from '@angular/cdk/a11y'
7 import { UP_ARROW, DOWN_ARROW, ENTER } from '@angular/cdk/keycodes'
8
9 @Component({
10 selector: 'my-search-typeahead',
11 templateUrl: './search-typeahead.component.html',
12 styleUrls: [ './search-typeahead.component.scss' ]
13 })
14 export class SearchTypeaheadComponent implements OnInit, AfterViewInit {
15 @ViewChild('contentWrapper', { static: true }) contentWrapper: ElementRef
16 @ViewChild('optionsList', { static: true }) optionsList: ElementRef
17
18 hasChannel = false
19 inChannel = false
20 keyboardEventsManager: ListKeyManager<ListKeyManagerOption>
21
22 searchInput: HTMLInputElement
23 URIPolicy: 'only-followed' | 'any' = 'any'
24
25 URIPolicyText: string
26 inAllText: string
27 inThisChannelText: string
28
29 results: any[] = []
30
31 constructor (
32 private authService: AuthService,
33 private router: Router,
34 private i18n: I18n
35 ) {
36 this.URIPolicyText = this.i18n('Determines whether you can resolve any distant content from its URL, or if your instance only allows doing so for instances it follows.')
37 this.inAllText = this.i18n('In all PeerTube')
38 this.inThisChannelText = this.i18n('In this channel')
39 }
40
41 ngOnInit () {
42 this.router.events
43 .pipe(filter(event => event instanceof NavigationEnd))
44 .subscribe((event: NavigationEnd) => {
45 this.hasChannel = event.url.startsWith('/videos/watch')
46 this.inChannel = event.url.startsWith('/video-channels')
47 this.computeResults()
48 })
49 }
50
51 ngAfterViewInit () {
52 this.searchInput = this.contentWrapper.nativeElement.childNodes[0]
53 this.searchInput.addEventListener('input', this.computeResults.bind(this))
54 }
55
56 get hasSearch () {
57 return !!this.searchInput && !!this.searchInput.value
58 }
59
60 computeResults () {
61 let results = [
62 {
63 text: 'MaƮtre poney',
64 type: 'channel'
65 }
66 ]
67
68 if (this.hasSearch) {
69 results = [
70 {
71 text: this.searchInput.value,
72 type: 'search-channel'
73 },
74 {
75 text: this.searchInput.value,
76 type: 'search-global'
77 },
78 ...results
79 ]
80 }
81
82 this.results = results.filter(
83 result => {
84 // if we're not in a channel or one of its videos/playlits, show all channel-related results
85 if (!(this.hasChannel || this.inChannel)) return !result.type.includes('channel')
86 // if we're in a channel, show all channel-related results except for the channel redirection itself
87 if (this.inChannel) return !(result.type === 'channel')
88 return true
89 }
90 )
91 }
92
93 isUserLoggedIn () {
94 return this.authService.isLoggedIn()
95 }
96
97 handleKeyUp (event: KeyboardEvent) {
98 event.stopImmediatePropagation()
99 if (this.keyboardEventsManager) {
100 if (event.keyCode === DOWN_ARROW || event.keyCode === UP_ARROW) {
101 // passing the event to key manager so we get a change fired
102 this.keyboardEventsManager.onKeydown(event)
103 return false
104 } else if (event.keyCode === ENTER) {
105 // when we hit enter, the keyboardManager should call the selectItem method of the `ListItemComponent`
106 // this.keyboardEventsManager.activeItem
107 return false
108 }
109 }
110 }
111 }