]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - client/src/app/helpers/utils.ts
Fix button icon in admin plugins
[github/Chocobozzz/PeerTube.git] / client / src / app / helpers / utils.ts
CommitLineData
9556ce48 1import { map } from 'rxjs/operators'
21e493d4 2import { SelectChannelItem } from 'src/types/select-options-item.model'
61bbc727 3import { DatePipe } from '@angular/common'
d4132d3f
RK
4import { HttpErrorResponse } from '@angular/common/http'
5import { Notifier } from '@app/core'
21e493d4 6import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
67ed6552
C
7import { environment } from '../../environments/environment'
8import { AuthService } from '../core/auth'
15a7387d 9
240458d0 10// Thanks: https://stackoverflow.com/questions/901115/how-can-i-get-query-string-values-in-javascript
f3aaa9a9
C
11function getParameterByName (name: string, url: string) {
12 if (!url) url = window.location.href
13 name = name.replace(/[\[\]]/g, '\\$&')
14
15 const regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)')
16 const results = regex.exec(url)
17
18 if (!results) return null
19 if (!results[2]) return ''
20
21 return decodeURIComponent(results[2].replace(/\+/g, ' '))
22}
23
9556ce48
C
24function listUserChannels (authService: AuthService) {
25 return authService.userInformationLoaded
26 .pipe(map(() => {
27 const user = authService.getUser()
28 if (!user) return undefined
29
30 const videoChannels = user.videoChannels
31 if (Array.isArray(videoChannels) === false) return undefined
32
dc2b2938
C
33 return videoChannels
34 .sort((a, b) => {
35 if (a.updatedAt < b.updatedAt) return 1
36 if (a.updatedAt > b.updatedAt) return -1
37 return 0
38 })
39 .map(c => ({
40 id: c.id,
41 label: c.displayName,
42 support: c.support,
43 avatarPath: c.avatar?.path
44 }) as SelectChannelItem)
9556ce48 45 }))
15a7387d
C
46}
47
c5911fd3 48function getAbsoluteAPIUrl () {
94148c90
C
49 let absoluteAPIUrl = environment.hmr === true
50 ? 'http://localhost:9000'
51 : environment.apiUrl
52
c5911fd3
C
53 if (!absoluteAPIUrl) {
54 // The API is on the same domain
55 absoluteAPIUrl = window.location.origin
56 }
57
58 return absoluteAPIUrl
59}
60
72493e44 61function getAbsoluteEmbedUrl () {
5beb89f2 62 let absoluteEmbedUrl = environment.originServerUrl
72493e44
C
63 if (!absoluteEmbedUrl) {
64 // The Embed is on the same domain
65 absoluteEmbedUrl = window.location.origin
66 }
67
68 return absoluteEmbedUrl
69}
70
61bbc727
C
71const datePipe = new DatePipe('en')
72function dateToHuman (date: string) {
73 return datePipe.transform(date, 'medium')
74}
75
11b8762f
C
76function durationToString (duration: number) {
77 const hours = Math.floor(duration / 3600)
78 const minutes = Math.floor((duration % 3600) / 60)
79 const seconds = duration % 60
80
81 const minutesPadding = minutes >= 10 ? '' : '0'
82 const secondsPadding = seconds >= 10 ? '' : '0'
83 const displayedHours = hours > 0 ? hours.toString() + ':' : ''
84
e66883b3
RK
85 return (
86 displayedHours + minutesPadding + minutes.toString() + ':' + secondsPadding + seconds.toString()
87 ).replace(/^0/, '')
11b8762f
C
88}
89
0cd4344f
C
90function immutableAssign <A, B> (target: A, source: B) {
91 return Object.assign({}, target, source)
92}
93
6de36768
C
94// Thanks: https://gist.github.com/ghinda/8442a57f22099bdb2e34
95function objectToFormData (obj: any, form?: FormData, namespace?: string) {
c4710631 96 const fd = form || new FormData()
6de36768
C
97 let formKey
98
c4710631 99 for (const key of Object.keys(obj)) {
6de36768
C
100 if (namespace) formKey = `${namespace}[${key}]`
101 else formKey = key
102
103 if (obj[key] === undefined) continue
104
2efd32f6
C
105 if (Array.isArray(obj[key]) && obj[key].length === 0) {
106 fd.append(key, null)
107 continue
108 }
109
360329cc 110 if (obj[key] !== null && typeof obj[ key ] === 'object' && !(obj[ key ] instanceof File)) {
40e87e9e 111 objectToFormData(obj[ key ], fd, formKey)
6de36768
C
112 } else {
113 fd.append(formKey, obj[ key ])
114 }
115 }
116
117 return fd
118}
119
1506307f 120function objectLineFeedToHtml (obj: any, keyToNormalize: string) {
5de8a55a 121 return immutableAssign(obj, {
1506307f 122 [keyToNormalize]: lineFeedToHtml(obj[keyToNormalize])
5de8a55a
C
123 })
124}
125
1506307f
C
126function lineFeedToHtml (text: string) {
127 if (!text) return text
128
129 return text.replace(/\r?\n|\r/g, '<br />')
130}
131
40e87e9e
C
132function removeElementFromArray <T> (arr: T[], elem: T) {
133 const index = arr.indexOf(elem)
134 if (index !== -1) arr.splice(index, 1)
135}
136
ad774752
C
137function sortBy (obj: any[], key1: string, key2?: string) {
138 return obj.sort((a, b) => {
139 const elem1 = key2 ? a[key1][key2] : a[key1]
140 const elem2 = key2 ? b[key1][key2] : b[key1]
141
142 if (elem1 < elem2) return -1
143 if (elem1 === elem2) return 0
144 return 1
145 })
146}
147
f3081d64
K
148function scrollToTop (behavior: 'auto' | 'smooth' = 'auto') {
149 window.scrollTo({
150 left: 0,
151 top: 0,
152 behavior
153 })
7373507f
C
154}
155
223b24e6
RK
156function isInViewport (el: HTMLElement) {
157 const bounding = el.getBoundingClientRect()
158 return (
159 bounding.top >= 0 &&
160 bounding.left >= 0 &&
161 bounding.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
162 bounding.right <= (window.innerWidth || document.documentElement.clientWidth)
163 )
164}
165
166function isXPercentInViewport (el: HTMLElement, percentVisible: number) {
167 const rect = el.getBoundingClientRect()
168 const windowHeight = (window.innerHeight || document.documentElement.clientHeight)
169
170 return !(
171 Math.floor(100 - (((rect.top >= 0 ? 0 : rect.top) / +-(rect.height / 1)) * 100)) < percentVisible ||
172 Math.floor(100 - ((rect.bottom - windowHeight) / rect.height) * 100) < percentVisible
173 )
174}
175
f6d6e7f8 176function genericUploadErrorHandler (parameters: {
177 err: Pick<HttpErrorResponse, 'message' | 'status' | 'headers'>
d4132d3f
RK
178 name: string
179 notifier: Notifier
180 sticky?: boolean
181}) {
182 const { err, name, notifier, sticky } = { sticky: false, ...parameters }
183 const title = $localize`The upload failed`
184 let message = err.message
185
186 if (err instanceof ErrorEvent) { // network error
187 message = $localize`The connection was interrupted`
188 notifier.error(message, title, null, sticky)
f6d6e7f8 189 } else if (err.status === HttpStatusCode.INTERNAL_SERVER_ERROR_500) {
190 message = $localize`The server encountered an error`
191 notifier.error(message, title, null, sticky)
d4132d3f
RK
192 } else if (err.status === HttpStatusCode.REQUEST_TIMEOUT_408) {
193 message = $localize`Your ${name} file couldn't be transferred before the set timeout (usually 10min)`
194 notifier.error(message, title, null, sticky)
195 } else if (err.status === HttpStatusCode.PAYLOAD_TOO_LARGE_413) {
196 const maxFileSize = err.headers?.get('X-File-Maximum-Size') || '8G'
197 message = $localize`Your ${name} file was too large (max. size: ${maxFileSize})`
198 notifier.error(message, title, null, sticky)
199 } else {
200 notifier.error(err.message, title)
201 }
202
203 return message
204}
205
f3aaa9a9 206export {
ad774752 207 sortBy,
11b8762f 208 durationToString,
1506307f 209 lineFeedToHtml,
15a7387d 210 getParameterByName,
61bbc727
C
211 getAbsoluteAPIUrl,
212 dateToHuman,
6de36768 213 immutableAssign,
5de8a55a 214 objectToFormData,
72493e44 215 getAbsoluteEmbedUrl,
1506307f 216 objectLineFeedToHtml,
7373507f 217 removeElementFromArray,
223b24e6
RK
218 scrollToTop,
219 isInViewport,
d4132d3f 220 isXPercentInViewport,
9556ce48 221 listUserChannels,
f6d6e7f8 222 genericUploadErrorHandler
f3aaa9a9 223}