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