]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - client/src/app/helpers/utils.ts
Fix embed url
[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.apiUrl
40 if (!absoluteAPIUrl) {
41 // The API is on the same domain
42 absoluteAPIUrl = window.location.origin
43 }
44
45 return absoluteAPIUrl
46 }
47
48 function 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
58 const datePipe = new DatePipe('en')
59 function dateToHuman (date: string) {
60 return datePipe.transform(date, 'medium')
61 }
62
63 function 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
72 return (
73 displayedHours + minutesPadding + minutes.toString() + ':' + secondsPadding + seconds.toString()
74 ).replace(/^0/, '')
75 }
76
77 function immutableAssign <A, B> (target: A, source: B) {
78 return Object.assign({}, target, source)
79 }
80
81 function 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
90 // Thanks: https://gist.github.com/ghinda/8442a57f22099bdb2e34
91 function objectToFormData (obj: any, form?: FormData, namespace?: string) {
92 const fd = form || new FormData()
93 let formKey
94
95 for (const key of Object.keys(obj)) {
96 if (namespace) formKey = `${namespace}[${key}]`
97 else formKey = key
98
99 if (obj[key] === undefined) continue
100
101 if (Array.isArray(obj[key]) && obj[key].length === 0) {
102 fd.append(key, null)
103 continue
104 }
105
106 if (obj[key] !== null && typeof obj[ key ] === 'object' && !(obj[ key ] instanceof File)) {
107 objectToFormData(obj[ key ], fd, formKey)
108 } else {
109 fd.append(formKey, obj[ key ])
110 }
111 }
112
113 return fd
114 }
115
116 function objectLineFeedToHtml (obj: any, keyToNormalize: string) {
117 return immutableAssign(obj, {
118 [keyToNormalize]: lineFeedToHtml(obj[keyToNormalize])
119 })
120 }
121
122 function lineFeedToHtml (text: string) {
123 if (!text) return text
124
125 return text.replace(/\r?\n|\r/g, '<br />')
126 }
127
128 function removeElementFromArray <T> (arr: T[], elem: T) {
129 const index = arr.indexOf(elem)
130 if (index !== -1) arr.splice(index, 1)
131 }
132
133 function 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
144 function scrollToTop () {
145 window.scroll(0, 0)
146 }
147
148 // Thanks: https://github.com/uupaa/dynamic-import-polyfill
149 function 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
183 function 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
193 function 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
203 export {
204 sortBy,
205 durationToString,
206 lineFeedToHtml,
207 objectToUrlEncoded,
208 getParameterByName,
209 populateAsyncUserVideoChannels,
210 getAbsoluteAPIUrl,
211 dateToHuman,
212 immutableAssign,
213 objectToFormData,
214 getAbsoluteEmbedUrl,
215 objectLineFeedToHtml,
216 removeElementFromArray,
217 importModule,
218 scrollToTop,
219 isInViewport,
220 isXPercentInViewport
221 }