aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/app/helpers/utils.ts
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2020-06-23 14:10:17 +0200
committerChocobozzz <chocobozzz@cpy.re>2020-06-23 16:00:49 +0200
commit67ed6552b831df66713bac9e672738796128d33f (patch)
tree59c97d41e0b49d75a90aa3de987968ab9b1ff447 /client/src/app/helpers/utils.ts
parent0c4bacbff53bc732f5a2677d62a6ead7752e2405 (diff)
downloadPeerTube-67ed6552b831df66713bac9e672738796128d33f.tar.gz
PeerTube-67ed6552b831df66713bac9e672738796128d33f.tar.zst
PeerTube-67ed6552b831df66713bac9e672738796128d33f.zip
Reorganize client shared modules
Diffstat (limited to 'client/src/app/helpers/utils.ts')
-rw-r--r--client/src/app/helpers/utils.ts210
1 files changed, 210 insertions, 0 deletions
diff --git a/client/src/app/helpers/utils.ts b/client/src/app/helpers/utils.ts
new file mode 100644
index 000000000..879f697f4
--- /dev/null
+++ b/client/src/app/helpers/utils.ts
@@ -0,0 +1,210 @@
1import { DatePipe } from '@angular/common'
2import { environment } from '../../environments/environment'
3import { AuthService } from '../core/auth'
4
5// Thanks: https://stackoverflow.com/questions/901115/how-can-i-get-query-string-values-in-javascript
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
19function 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
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
48const datePipe = new DatePipe('en')
49function dateToHuman (date: string) {
50 return datePipe.transform(date, 'medium')
51}
52
53function durationToString (duration: number) {
54 const hours = Math.floor(duration / 3600)
55 const minutes = Math.floor((duration % 3600) / 60)
56 const seconds = duration % 60
57
58 const minutesPadding = minutes >= 10 ? '' : '0'
59 const secondsPadding = seconds >= 10 ? '' : '0'
60 const displayedHours = hours > 0 ? hours.toString() + ':' : ''
61
62 return (
63 displayedHours + minutesPadding + minutes.toString() + ':' + secondsPadding + seconds.toString()
64 ).replace(/^0/, '')
65}
66
67function immutableAssign <A, B> (target: A, source: B) {
68 return Object.assign({}, target, source)
69}
70
71function objectToUrlEncoded (obj: any) {
72 const str: string[] = []
73 for (const key of Object.keys(obj)) {
74 str.push(encodeURIComponent(key) + '=' + encodeURIComponent(obj[key]))
75 }
76
77 return str.join('&')
78}
79
80// Thanks: https://gist.github.com/ghinda/8442a57f22099bdb2e34
81function objectToFormData (obj: any, form?: FormData, namespace?: string) {
82 const fd = form || new FormData()
83 let formKey
84
85 for (const key of Object.keys(obj)) {
86 if (namespace) formKey = `${namespace}[${key}]`
87 else formKey = key
88
89 if (obj[key] === undefined) continue
90
91 if (Array.isArray(obj[key]) && obj[key].length === 0) {
92 fd.append(key, null)
93 continue
94 }
95
96 if (obj[key] !== null && typeof obj[ key ] === 'object' && !(obj[ key ] instanceof File)) {
97 objectToFormData(obj[ key ], fd, formKey)
98 } else {
99 fd.append(formKey, obj[ key ])
100 }
101 }
102
103 return fd
104}
105
106function objectLineFeedToHtml (obj: any, keyToNormalize: string) {
107 return immutableAssign(obj, {
108 [keyToNormalize]: lineFeedToHtml(obj[keyToNormalize])
109 })
110}
111
112function lineFeedToHtml (text: string) {
113 if (!text) return text
114
115 return text.replace(/\r?\n|\r/g, '<br />')
116}
117
118function removeElementFromArray <T> (arr: T[], elem: T) {
119 const index = arr.indexOf(elem)
120 if (index !== -1) arr.splice(index, 1)
121}
122
123function sortBy (obj: any[], key1: string, key2?: string) {
124 return obj.sort((a, b) => {
125 const elem1 = key2 ? a[key1][key2] : a[key1]
126 const elem2 = key2 ? b[key1][key2] : b[key1]
127
128 if (elem1 < elem2) return -1
129 if (elem1 === elem2) return 0
130 return 1
131 })
132}
133
134function scrollToTop () {
135 window.scroll(0, 0)
136}
137
138// Thanks: https://github.com/uupaa/dynamic-import-polyfill
139function importModule (path: string) {
140 return new Promise((resolve, reject) => {
141 const vector = '$importModule$' + Math.random().toString(32).slice(2)
142 const script = document.createElement('script')
143
144 const destructor = () => {
145 delete window[ vector ]
146 script.onerror = null
147 script.onload = null
148 script.remove()
149 URL.revokeObjectURL(script.src)
150 script.src = ''
151 }
152
153 script.defer = true
154 script.type = 'module'
155
156 script.onerror = () => {
157 reject(new Error(`Failed to import: ${path}`))
158 destructor()
159 }
160 script.onload = () => {
161 resolve(window[ vector ])
162 destructor()
163 }
164 const absURL = (environment.apiUrl || window.location.origin) + path
165 const loader = `import * as m from "${absURL}"; window.${vector} = m;` // export Module
166 const blob = new Blob([ loader ], { type: 'text/javascript' })
167 script.src = URL.createObjectURL(blob)
168
169 document.head.appendChild(script)
170 })
171}
172
173function isInViewport (el: HTMLElement) {
174 const bounding = el.getBoundingClientRect()
175 return (
176 bounding.top >= 0 &&
177 bounding.left >= 0 &&
178 bounding.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
179 bounding.right <= (window.innerWidth || document.documentElement.clientWidth)
180 )
181}
182
183function isXPercentInViewport (el: HTMLElement, percentVisible: number) {
184 const rect = el.getBoundingClientRect()
185 const windowHeight = (window.innerHeight || document.documentElement.clientHeight)
186
187 return !(
188 Math.floor(100 - (((rect.top >= 0 ? 0 : rect.top) / +-(rect.height / 1)) * 100)) < percentVisible ||
189 Math.floor(100 - ((rect.bottom - windowHeight) / rect.height) * 100) < percentVisible
190 )
191}
192
193export {
194 sortBy,
195 durationToString,
196 lineFeedToHtml,
197 objectToUrlEncoded,
198 getParameterByName,
199 populateAsyncUserVideoChannels,
200 getAbsoluteAPIUrl,
201 dateToHuman,
202 immutableAssign,
203 objectToFormData,
204 objectLineFeedToHtml,
205 removeElementFromArray,
206 importModule,
207 scrollToTop,
208 isInViewport,
209 isXPercentInViewport
210}