]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - client/src/app/helpers/utils.ts
825b6ca9620efe118e2c0c593b5bbd6bd959b290
[github/Chocobozzz/PeerTube.git] / client / src / app / helpers / utils.ts
1 import { DatePipe } from '@angular/common'
2 import { environment } from '../../environments/environment'
3 import { AuthService } from '../core/auth'
4
5 // Thanks: https://stackoverflow.com/questions/901115/how-can-i-get-query-string-values-in-javascript
6 function 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
19 function populateAsyncUserVideoChannels (authService: AuthService, channel: { id: number, label: string, support?: string }[]) {
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
30 videoChannels.forEach(c => channel.push({ id: c.id, label: c.displayName, support: c.support }))
31
32 return res()
33 }
34 )
35 })
36 }
37
38 function getAbsoluteAPIUrl () {
39 let absoluteAPIUrl = environment.hmr === true
40 ? 'http://localhost:9000'
41 : environment.apiUrl
42
43 if (!absoluteAPIUrl) {
44 // The API is on the same domain
45 absoluteAPIUrl = window.location.origin
46 }
47
48 return absoluteAPIUrl
49 }
50
51 function 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
61 const datePipe = new DatePipe('en')
62 function dateToHuman (date: string) {
63 return datePipe.transform(date, 'medium')
64 }
65
66 function 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
75 return (
76 displayedHours + minutesPadding + minutes.toString() + ':' + secondsPadding + seconds.toString()
77 ).replace(/^0/, '')
78 }
79
80 function immutableAssign <A, B> (target: A, source: B) {
81 return Object.assign({}, target, source)
82 }
83
84 // Thanks: https://gist.github.com/ghinda/8442a57f22099bdb2e34
85 function objectToFormData (obj: any, form?: FormData, namespace?: string) {
86 const fd = form || new FormData()
87 let formKey
88
89 for (const key of Object.keys(obj)) {
90 if (namespace) formKey = `${namespace}[${key}]`
91 else formKey = key
92
93 if (obj[key] === undefined) continue
94
95 if (Array.isArray(obj[key]) && obj[key].length === 0) {
96 fd.append(key, null)
97 continue
98 }
99
100 if (obj[key] !== null && typeof obj[ key ] === 'object' && !(obj[ key ] instanceof File)) {
101 objectToFormData(obj[ key ], fd, formKey)
102 } else {
103 fd.append(formKey, obj[ key ])
104 }
105 }
106
107 return fd
108 }
109
110 function objectLineFeedToHtml (obj: any, keyToNormalize: string) {
111 return immutableAssign(obj, {
112 [keyToNormalize]: lineFeedToHtml(obj[keyToNormalize])
113 })
114 }
115
116 function lineFeedToHtml (text: string) {
117 if (!text) return text
118
119 return text.replace(/\r?\n|\r/g, '<br />')
120 }
121
122 function removeElementFromArray <T> (arr: T[], elem: T) {
123 const index = arr.indexOf(elem)
124 if (index !== -1) arr.splice(index, 1)
125 }
126
127 function sortBy (obj: any[], key1: string, key2?: string) {
128 return obj.sort((a, b) => {
129 const elem1 = key2 ? a[key1][key2] : a[key1]
130 const elem2 = key2 ? b[key1][key2] : b[key1]
131
132 if (elem1 < elem2) return -1
133 if (elem1 === elem2) return 0
134 return 1
135 })
136 }
137
138 function scrollToTop () {
139 window.scroll(0, 0)
140 }
141
142 // Thanks: https://github.com/uupaa/dynamic-import-polyfill
143 function importModule (path: string) {
144 return new Promise((resolve, reject) => {
145 const vector = '$importModule$' + Math.random().toString(32).slice(2)
146 const script = document.createElement('script')
147
148 const destructor = () => {
149 delete window[ vector ]
150 script.onerror = null
151 script.onload = null
152 script.remove()
153 URL.revokeObjectURL(script.src)
154 script.src = ''
155 }
156
157 script.defer = true
158 script.type = 'module'
159
160 script.onerror = () => {
161 reject(new Error(`Failed to import: ${path}`))
162 destructor()
163 }
164 script.onload = () => {
165 resolve(window[ vector ])
166 destructor()
167 }
168 const absURL = (environment.apiUrl || window.location.origin) + path
169 const loader = `import * as m from "${absURL}"; window.${vector} = m;` // export Module
170 const blob = new Blob([ loader ], { type: 'text/javascript' })
171 script.src = URL.createObjectURL(blob)
172
173 document.head.appendChild(script)
174 })
175 }
176
177 function isInViewport (el: HTMLElement) {
178 const bounding = el.getBoundingClientRect()
179 return (
180 bounding.top >= 0 &&
181 bounding.left >= 0 &&
182 bounding.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
183 bounding.right <= (window.innerWidth || document.documentElement.clientWidth)
184 )
185 }
186
187 function isXPercentInViewport (el: HTMLElement, percentVisible: number) {
188 const rect = el.getBoundingClientRect()
189 const windowHeight = (window.innerHeight || document.documentElement.clientHeight)
190
191 return !(
192 Math.floor(100 - (((rect.top >= 0 ? 0 : rect.top) / +-(rect.height / 1)) * 100)) < percentVisible ||
193 Math.floor(100 - ((rect.bottom - windowHeight) / rect.height) * 100) < percentVisible
194 )
195 }
196
197 export {
198 sortBy,
199 durationToString,
200 lineFeedToHtml,
201 getParameterByName,
202 populateAsyncUserVideoChannels,
203 getAbsoluteAPIUrl,
204 dateToHuman,
205 immutableAssign,
206 objectToFormData,
207 getAbsoluteEmbedUrl,
208 objectLineFeedToHtml,
209 removeElementFromArray,
210 importModule,
211 scrollToTop,
212 isInViewport,
213 isXPercentInViewport
214 }