]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - client/src/app/helpers/utils.ts
add ng-select for templatable select options
[github/Chocobozzz/PeerTube.git] / client / src / app / helpers / utils.ts
CommitLineData
61bbc727 1import { DatePipe } from '@angular/common'
67ed6552
C
2import { environment } from '../../environments/environment'
3import { AuthService } from '../core/auth'
15a7387d 4
240458d0 5// Thanks: https://stackoverflow.com/questions/901115/how-can-i-get-query-string-values-in-javascript
f3aaa9a9
C
6function getParameterByName (name: string, url: string) {
7 if (!url) url = window.location.href
8 name = name.replace(/[\[\]]/g, '\\$&')
9
10 const regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)')
11 const results = regex.exec(url)
12
13 if (!results) return null
14 if (!results[2]) return ''
15
16 return decodeURIComponent(results[2].replace(/\+/g, ' '))
17}
18
02c01341
RK
19function populateAsyncUserVideoChannels (
20 authService: AuthService,
21 channel: { id: number, label: string, support?: string, avatarPath?: string, recent?: boolean }[]
22) {
15a7387d
C
23 return new Promise(res => {
24 authService.userInformationLoaded
25 .subscribe(
26 () => {
27 const user = authService.getUser()
28 if (!user) return
29
30 const videoChannels = user.videoChannels
31 if (Array.isArray(videoChannels) === false) return
32
02c01341
RK
33 videoChannels.forEach(c => channel.push({
34 id: c.id,
35 label: c.displayName,
36 support: c.support,
37 avatarPath: c.avatar?.path
38 }))
15a7387d
C
39
40 return res()
41 }
42 )
43 })
44}
45
c5911fd3 46function getAbsoluteAPIUrl () {
94148c90
C
47 let absoluteAPIUrl = environment.hmr === true
48 ? 'http://localhost:9000'
49 : environment.apiUrl
50
c5911fd3
C
51 if (!absoluteAPIUrl) {
52 // The API is on the same domain
53 absoluteAPIUrl = window.location.origin
54 }
55
56 return absoluteAPIUrl
57}
58
72493e44
C
59function getAbsoluteEmbedUrl () {
60 let absoluteEmbedUrl = environment.embedUrl
61 if (!absoluteEmbedUrl) {
62 // The Embed is on the same domain
63 absoluteEmbedUrl = window.location.origin
64 }
65
66 return absoluteEmbedUrl
67}
68
61bbc727
C
69const datePipe = new DatePipe('en')
70function dateToHuman (date: string) {
71 return datePipe.transform(date, 'medium')
72}
73
11b8762f
C
74function durationToString (duration: number) {
75 const hours = Math.floor(duration / 3600)
76 const minutes = Math.floor((duration % 3600) / 60)
77 const seconds = duration % 60
78
79 const minutesPadding = minutes >= 10 ? '' : '0'
80 const secondsPadding = seconds >= 10 ? '' : '0'
81 const displayedHours = hours > 0 ? hours.toString() + ':' : ''
82
e66883b3
RK
83 return (
84 displayedHours + minutesPadding + minutes.toString() + ':' + secondsPadding + seconds.toString()
85 ).replace(/^0/, '')
11b8762f
C
86}
87
0cd4344f
C
88function immutableAssign <A, B> (target: A, source: B) {
89 return Object.assign({}, target, source)
90}
91
6de36768
C
92// Thanks: https://gist.github.com/ghinda/8442a57f22099bdb2e34
93function objectToFormData (obj: any, form?: FormData, namespace?: string) {
c4710631 94 const fd = form || new FormData()
6de36768
C
95 let formKey
96
c4710631 97 for (const key of Object.keys(obj)) {
6de36768
C
98 if (namespace) formKey = `${namespace}[${key}]`
99 else formKey = key
100
101 if (obj[key] === undefined) continue
102
2efd32f6
C
103 if (Array.isArray(obj[key]) && obj[key].length === 0) {
104 fd.append(key, null)
105 continue
106 }
107
360329cc 108 if (obj[key] !== null && typeof obj[ key ] === 'object' && !(obj[ key ] instanceof File)) {
40e87e9e 109 objectToFormData(obj[ key ], fd, formKey)
6de36768
C
110 } else {
111 fd.append(formKey, obj[ key ])
112 }
113 }
114
115 return fd
116}
117
1506307f 118function objectLineFeedToHtml (obj: any, keyToNormalize: string) {
5de8a55a 119 return immutableAssign(obj, {
1506307f 120 [keyToNormalize]: lineFeedToHtml(obj[keyToNormalize])
5de8a55a
C
121 })
122}
123
1506307f
C
124function lineFeedToHtml (text: string) {
125 if (!text) return text
126
127 return text.replace(/\r?\n|\r/g, '<br />')
128}
129
40e87e9e
C
130function removeElementFromArray <T> (arr: T[], elem: T) {
131 const index = arr.indexOf(elem)
132 if (index !== -1) arr.splice(index, 1)
133}
134
ad774752
C
135function sortBy (obj: any[], key1: string, key2?: string) {
136 return obj.sort((a, b) => {
137 const elem1 = key2 ? a[key1][key2] : a[key1]
138 const elem2 = key2 ? b[key1][key2] : b[key1]
139
140 if (elem1 < elem2) return -1
141 if (elem1 === elem2) return 0
142 return 1
143 })
144}
145
7373507f
C
146function scrollToTop () {
147 window.scroll(0, 0)
148}
149
0c503f5c
C
150// Thanks: https://github.com/uupaa/dynamic-import-polyfill
151function importModule (path: string) {
152 return new Promise((resolve, reject) => {
153 const vector = '$importModule$' + Math.random().toString(32).slice(2)
154 const script = document.createElement('script')
155
156 const destructor = () => {
157 delete window[ vector ]
158 script.onerror = null
159 script.onload = null
160 script.remove()
161 URL.revokeObjectURL(script.src)
162 script.src = ''
163 }
164
165 script.defer = true
166 script.type = 'module'
167
168 script.onerror = () => {
169 reject(new Error(`Failed to import: ${path}`))
170 destructor()
171 }
172 script.onload = () => {
173 resolve(window[ vector ])
174 destructor()
175 }
176 const absURL = (environment.apiUrl || window.location.origin) + path
177 const loader = `import * as m from "${absURL}"; window.${vector} = m;` // export Module
178 const blob = new Blob([ loader ], { type: 'text/javascript' })
179 script.src = URL.createObjectURL(blob)
180
181 document.head.appendChild(script)
182 })
183}
184
223b24e6
RK
185function isInViewport (el: HTMLElement) {
186 const bounding = el.getBoundingClientRect()
187 return (
188 bounding.top >= 0 &&
189 bounding.left >= 0 &&
190 bounding.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
191 bounding.right <= (window.innerWidth || document.documentElement.clientWidth)
192 )
193}
194
195function isXPercentInViewport (el: HTMLElement, percentVisible: number) {
196 const rect = el.getBoundingClientRect()
197 const windowHeight = (window.innerHeight || document.documentElement.clientHeight)
198
199 return !(
200 Math.floor(100 - (((rect.top >= 0 ? 0 : rect.top) / +-(rect.height / 1)) * 100)) < percentVisible ||
201 Math.floor(100 - ((rect.bottom - windowHeight) / rect.height) * 100) < percentVisible
202 )
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,
0c503f5c 218 importModule,
223b24e6
RK
219 scrollToTop,
220 isInViewport,
221 isXPercentInViewport
f3aaa9a9 222}