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