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