]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - client/src/app/shared/shared-video-miniature/video-filters.model.ts
Put private videos under a specific subdirectory
[github/Chocobozzz/PeerTube.git] / client / src / app / shared / shared-video-miniature / video-filters.model.ts
1 import { splitIntoArray, toBoolean } from '@app/helpers'
2 import { getAllPrivacies } from '@shared/core-utils'
3 import { AttributesOnly } from '@shared/typescript-utils'
4 import { BooleanBothQuery, NSFWPolicyType, VideoInclude, VideoPrivacy, VideoSortField } from '@shared/models'
5
6 type VideoFiltersKeys = {
7 [ id in keyof AttributesOnly<VideoFilters> ]: any
8 }
9
10 export type VideoFilterScope = 'local' | 'federated'
11
12 export class VideoFilters {
13 sort: VideoSortField
14 nsfw: BooleanBothQuery
15
16 languageOneOf: string[]
17 categoryOneOf: number[]
18
19 scope: VideoFilterScope
20 allVideos: boolean
21
22 live: BooleanBothQuery
23
24 search: string
25
26 private defaultValues = new Map<keyof VideoFilters, any>([
27 [ 'sort', '-publishedAt' ],
28 [ 'nsfw', 'false' ],
29 [ 'languageOneOf', undefined ],
30 [ 'categoryOneOf', undefined ],
31 [ 'scope', 'federated' ],
32 [ 'allVideos', false ],
33 [ 'live', 'both' ]
34 ])
35
36 private activeFilters: { key: string, canRemove: boolean, label: string, value?: string }[] = []
37 private defaultNSFWPolicy: NSFWPolicyType
38
39 private onChangeCallbacks: Array<() => void> = []
40 private oldFormObjectString: string
41
42 private readonly hiddenFields: string[] = []
43
44 constructor (defaultSort: string, defaultScope: VideoFilterScope, hiddenFields: string[] = []) {
45 this.setDefaultSort(defaultSort)
46 this.setDefaultScope(defaultScope)
47
48 this.hiddenFields = hiddenFields
49
50 this.reset()
51 }
52
53 onChange (cb: () => void) {
54 this.onChangeCallbacks.push(cb)
55 }
56
57 triggerChange () {
58 // Don't run on change if the values did not change
59 const currentFormObjectString = JSON.stringify(this.toFormObject())
60 if (this.oldFormObjectString && currentFormObjectString === this.oldFormObjectString) return
61
62 this.oldFormObjectString = currentFormObjectString
63
64 for (const cb of this.onChangeCallbacks) {
65 cb()
66 }
67 }
68
69 setDefaultScope (scope: VideoFilterScope) {
70 this.defaultValues.set('scope', scope)
71 }
72
73 setDefaultSort (sort: string) {
74 this.defaultValues.set('sort', sort)
75 }
76
77 setNSFWPolicy (nsfwPolicy: NSFWPolicyType) {
78 this.updateDefaultNSFW(nsfwPolicy)
79 }
80
81 reset (specificKey?: string) {
82 for (const [ key, value ] of this.defaultValues) {
83 if (specificKey && specificKey !== key) continue
84
85 // FIXME: typings
86 this[key as any] = value
87 }
88
89 this.buildActiveFilters()
90 }
91
92 load (obj: Partial<AttributesOnly<VideoFilters>>) {
93 if (obj.sort !== undefined) this.sort = obj.sort
94
95 if (obj.nsfw !== undefined) this.nsfw = obj.nsfw
96
97 if (obj.languageOneOf !== undefined) this.languageOneOf = splitIntoArray(obj.languageOneOf)
98 if (obj.categoryOneOf !== undefined) this.categoryOneOf = splitIntoArray(obj.categoryOneOf)
99
100 if (obj.scope !== undefined) this.scope = obj.scope
101 if (obj.allVideos !== undefined) this.allVideos = toBoolean(obj.allVideos)
102
103 if (obj.live !== undefined) this.live = obj.live
104
105 if (obj.search !== undefined) this.search = obj.search
106
107 this.buildActiveFilters()
108 }
109
110 buildActiveFilters () {
111 this.activeFilters = []
112
113 this.activeFilters.push({
114 key: 'nsfw',
115 canRemove: false,
116 label: $localize`Sensitive content`,
117 value: this.getNSFWValue()
118 })
119
120 this.activeFilters.push({
121 key: 'scope',
122 canRemove: false,
123 label: $localize`Scope`,
124 value: this.scope === 'federated'
125 ? $localize`Federated`
126 : $localize`Local`
127 })
128
129 if (this.languageOneOf && this.languageOneOf.length !== 0) {
130 this.activeFilters.push({
131 key: 'languageOneOf',
132 canRemove: true,
133 label: $localize`Languages`,
134 value: this.languageOneOf.map(l => l.toUpperCase()).join(', ')
135 })
136 }
137
138 if (this.categoryOneOf && this.categoryOneOf.length !== 0) {
139 this.activeFilters.push({
140 key: 'categoryOneOf',
141 canRemove: true,
142 label: $localize`Categories`,
143 value: this.categoryOneOf.join(', ')
144 })
145 }
146
147 if (this.allVideos) {
148 this.activeFilters.push({
149 key: 'allVideos',
150 canRemove: true,
151 label: $localize`All videos`
152 })
153 }
154
155 if (this.live === 'true') {
156 this.activeFilters.push({
157 key: 'live',
158 canRemove: true,
159 label: $localize`Live videos`
160 })
161 } else if (this.live === 'false') {
162 this.activeFilters.push({
163 key: 'live',
164 canRemove: true,
165 label: $localize`VOD videos`
166 })
167 }
168
169 this.activeFilters = this.activeFilters
170 .filter(a => this.hiddenFields.includes(a.key) === false)
171 }
172
173 getActiveFilters () {
174 return this.activeFilters
175 }
176
177 toFormObject (): VideoFiltersKeys {
178 const result: Partial<VideoFiltersKeys> = {}
179
180 for (const [ key ] of this.defaultValues) {
181 result[key] = this[key]
182 }
183
184 return result as VideoFiltersKeys
185 }
186
187 toUrlObject () {
188 const result: { [ id: string ]: any } = {}
189
190 for (const [ key, defaultValue ] of this.defaultValues) {
191 if (this[key] !== defaultValue) {
192 result[key] = this[key]
193 }
194 }
195
196 return result
197 }
198
199 toVideosAPIObject () {
200 let isLocal: boolean
201 let include: VideoInclude
202 let privacyOneOf: VideoPrivacy[]
203
204 if (this.scope === 'local') {
205 isLocal = true
206 }
207
208 if (this.allVideos) {
209 include = VideoInclude.NOT_PUBLISHED_STATE
210 privacyOneOf = getAllPrivacies()
211 }
212
213 let isLive: boolean
214 if (this.live === 'true') isLive = true
215 else if (this.live === 'false') isLive = false
216
217 return {
218 sort: this.sort,
219 nsfw: this.nsfw,
220 languageOneOf: this.languageOneOf,
221 categoryOneOf: this.categoryOneOf,
222 search: this.search,
223 isLocal,
224 include,
225 privacyOneOf,
226 isLive
227 }
228 }
229
230 getNSFWDisplayLabel () {
231 if (this.defaultNSFWPolicy === 'blur') return $localize`Blurred`
232
233 return $localize`Displayed`
234 }
235
236 private getNSFWValue () {
237 if (this.nsfw === 'false') return $localize`hidden`
238 if (this.defaultNSFWPolicy === 'blur') return $localize`blurred`
239
240 return $localize`displayed`
241 }
242
243 private updateDefaultNSFW (nsfwPolicy: NSFWPolicyType) {
244 const nsfw = nsfwPolicy === 'do_not_list'
245 ? 'false'
246 : 'both'
247
248 this.defaultValues.set('nsfw', nsfw)
249 this.defaultNSFWPolicy = nsfwPolicy
250
251 this.reset('nsfw')
252 }
253 }