]>
Commit | Line | Data |
---|---|---|
67ed6552 C |
1 | import { Subject } from 'rxjs' |
2 | import { debounceTime, distinctUntilChanged } from 'rxjs/operators' | |
6702a1b2 | 3 | import { Component, OnInit } from '@angular/core' |
6702a1b2 | 4 | import { ActivatedRoute, Router } from '@angular/router' |
67ed6552 | 5 | import { PluginApiService } from '@app/+admin/plugins/shared/plugin-api.service' |
c96e457b | 6 | import { ComponentPagination, ConfirmService, hasMoreItems, Notifier, PluginService } from '@app/core' |
428ccb8b | 7 | import { PeerTubePluginIndex, PluginType } from '@shared/models' |
d00dc28d C |
8 | |
9 | @Component({ | |
10 | selector: 'my-plugin-search', | |
11 | templateUrl: './plugin-search.component.html', | |
2accfdd8 | 12 | styleUrls: [ './plugin-search.component.scss' ] |
d00dc28d C |
13 | }) |
14 | export class PluginSearchComponent implements OnInit { | |
2accfdd8 | 15 | pluginType: PluginType |
6702a1b2 C |
16 | |
17 | pagination: ComponentPagination = { | |
18 | currentPage: 1, | |
440d39c5 C |
19 | itemsPerPage: 10, |
20 | totalItems: null | |
6702a1b2 C |
21 | } |
22 | sort = '-popularity' | |
23 | ||
24 | search = '' | |
25 | isSearching = false | |
26 | ||
27 | plugins: PeerTubePluginIndex[] = [] | |
28 | installing: { [name: string]: boolean } = {} | |
89c344db | 29 | pluginInstalled = false |
6702a1b2 | 30 | |
ad453580 C |
31 | onDataSubject = new Subject<any[]>() |
32 | ||
6702a1b2 | 33 | private searchSubject = new Subject<string>() |
d00dc28d C |
34 | |
35 | constructor ( | |
c96e457b | 36 | private pluginService: PluginService, |
078b4716 | 37 | private pluginApiService: PluginApiService, |
6702a1b2 C |
38 | private notifier: Notifier, |
39 | private confirmService: ConfirmService, | |
40 | private router: Router, | |
41 | private route: ActivatedRoute | |
d00dc28d | 42 | ) { |
d00dc28d C |
43 | } |
44 | ||
45 | ngOnInit () { | |
2accfdd8 C |
46 | if (!this.route.snapshot.queryParams['pluginType']) { |
47 | const queryParams = { pluginType: PluginType.PLUGIN } | |
48 | ||
49 | this.router.navigate([], { queryParams }) | |
50 | } | |
51 | ||
52 | this.route.queryParams.subscribe(query => { | |
53 | if (!query['pluginType']) return | |
54 | ||
55 | this.pluginType = parseInt(query['pluginType'], 10) | |
56 | this.search = query['search'] || '' | |
57 | ||
58 | this.reloadPlugins() | |
59 | }) | |
6702a1b2 C |
60 | |
61 | this.searchSubject.asObservable() | |
62 | .pipe( | |
63 | debounceTime(400), | |
64 | distinctUntilChanged() | |
65 | ) | |
2accfdd8 | 66 | .subscribe(search => this.router.navigate([], { queryParams: { search }, queryParamsHandling: 'merge' })) |
6702a1b2 C |
67 | } |
68 | ||
be27ef3b C |
69 | onSearchChange (event: Event) { |
70 | const target = event.target as HTMLInputElement | |
71 | ||
72 | this.searchSubject.next(target.value) | |
6702a1b2 C |
73 | } |
74 | ||
75 | reloadPlugins () { | |
76 | this.pagination.currentPage = 1 | |
77 | this.plugins = [] | |
78 | ||
6702a1b2 C |
79 | this.loadMorePlugins() |
80 | } | |
81 | ||
82 | loadMorePlugins () { | |
83 | this.isSearching = true | |
84 | ||
078b4716 | 85 | this.pluginApiService.searchAvailablePlugins(this.pluginType, this.pagination, this.sort, this.search) |
1378c0d3 C |
86 | .subscribe({ |
87 | next: res => { | |
6702a1b2 C |
88 | this.isSearching = false |
89 | ||
90 | this.plugins = this.plugins.concat(res.data) | |
91 | this.pagination.totalItems = res.total | |
ad453580 C |
92 | |
93 | this.onDataSubject.next(res.data) | |
6702a1b2 C |
94 | }, |
95 | ||
1378c0d3 | 96 | error: err => { |
f0c5e8b6 C |
97 | console.error(err) |
98 | ||
66357162 | 99 | const message = $localize`The plugin index is not available. Please retry later.` |
f0c5e8b6 C |
100 | this.notifier.error(message) |
101 | } | |
1378c0d3 | 102 | }) |
6702a1b2 C |
103 | } |
104 | ||
105 | onNearOfBottom () { | |
106 | if (!hasMoreItems(this.pagination)) return | |
107 | ||
108 | this.pagination.currentPage += 1 | |
109 | ||
110 | this.loadMorePlugins() | |
111 | } | |
112 | ||
113 | isInstalling (plugin: PeerTubePluginIndex) { | |
114 | return !!this.installing[plugin.npmName] | |
115 | } | |
116 | ||
c96e457b C |
117 | getShowRouterLink (plugin: PeerTubePluginIndex) { |
118 | return [ '/admin', 'plugins', 'show', this.pluginService.nameToNpmName(plugin.name, this.pluginType) ] | |
119 | } | |
120 | ||
121 | isThemeSearch () { | |
122 | return this.pluginType === PluginType.THEME | |
123 | } | |
124 | ||
6702a1b2 C |
125 | async install (plugin: PeerTubePluginIndex) { |
126 | if (this.installing[plugin.npmName]) return | |
127 | ||
128 | const res = await this.confirmService.confirm( | |
66357162 C |
129 | $localize`Please only install plugins or themes you trust, since they can execute any code on your instance.`, |
130 | $localize`Install ${plugin.name}?` | |
6702a1b2 C |
131 | ) |
132 | if (res === false) return | |
133 | ||
134 | this.installing[plugin.npmName] = true | |
135 | ||
078b4716 | 136 | this.pluginApiService.install(plugin.npmName) |
1378c0d3 C |
137 | .subscribe({ |
138 | next: () => { | |
6702a1b2 | 139 | this.installing[plugin.npmName] = false |
89c344db | 140 | this.pluginInstalled = true |
6702a1b2 | 141 | |
66357162 | 142 | this.notifier.success($localize`${plugin.name} installed.`) |
6702a1b2 C |
143 | |
144 | plugin.installed = true | |
145 | }, | |
146 | ||
1378c0d3 C |
147 | error: err => this.notifier.error(err.message) |
148 | }) | |
d00dc28d C |
149 | } |
150 | } |