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