]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - client/src/app/helpers/utils.ts
Translated using Weblate (Thai)
[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 const datePipe = new DatePipe('en')
49 function dateToHuman (date: string) {
50 return datePipe.transform(date, 'medium')
51 }
52
53 function 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
67 function immutableAssign <A, B> (target: A, source: B) {
68 return Object.assign({}, target, source)
69 }
70
71 function 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
81 function 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
106 function objectLineFeedToHtml (obj: any, keyToNormalize: string) {
107 return immutableAssign(obj, {
108 [keyToNormalize]: lineFeedToHtml(obj[keyToNormalize])
109 })
110 }
111
112 function lineFeedToHtml (text: string) {
113 if (!text) return text
114
115 return text.replace(/\r?\n|\r/g, '<br />')
116 }
117
118 function removeElementFromArray <T> (arr: T[], elem: T) {
119 const index = arr.indexOf(elem)
120 if (index !== -1) arr.splice(index, 1)
121 }
122
123 function 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
134 function scrollToTop () {
135 window.scroll(0, 0)
136 }
137
138 // Thanks: https://github.com/uupaa/dynamic-import-polyfill
139 function 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
173 function 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
183 function 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
193 export {
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 }