]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - client/src/app/helpers/utils.ts
Sort channels by -updatedAt
[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
d4132d3f
RK
176function uploadErrorHandler (parameters: {
177 err: HttpErrorResponse
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)
189 } else if (err.status === HttpStatusCode.REQUEST_TIMEOUT_408) {
190 message = $localize`Your ${name} file couldn't be transferred before the set timeout (usually 10min)`
191 notifier.error(message, title, null, sticky)
192 } else if (err.status === HttpStatusCode.PAYLOAD_TOO_LARGE_413) {
193 const maxFileSize = err.headers?.get('X-File-Maximum-Size') || '8G'
194 message = $localize`Your ${name} file was too large (max. size: ${maxFileSize})`
195 notifier.error(message, title, null, sticky)
196 } else {
197 notifier.error(err.message, title)
198 }
199
200 return message
201}
202
f3aaa9a9 203export {
ad774752 204 sortBy,
11b8762f 205 durationToString,
1506307f 206 lineFeedToHtml,
15a7387d 207 getParameterByName,
61bbc727
C
208 getAbsoluteAPIUrl,
209 dateToHuman,
6de36768 210 immutableAssign,
5de8a55a 211 objectToFormData,
72493e44 212 getAbsoluteEmbedUrl,
1506307f 213 objectLineFeedToHtml,
7373507f 214 removeElementFromArray,
223b24e6
RK
215 scrollToTop,
216 isInViewport,
d4132d3f 217 isXPercentInViewport,
9556ce48 218 listUserChannels,
d4132d3f 219 uploadErrorHandler
f3aaa9a9 220}