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