]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - client/src/app/helpers/utils.ts
Improve markdown-it emoji list column display (#3253)
[github/Chocobozzz/PeerTube.git] / client / src / app / helpers / utils.ts
1 import { DatePipe } from '@angular/common'
2 import { SelectChannelItem } from '@app/shared/shared-forms'
3 import { environment } from '../../environments/environment'
4 import { AuthService } from '../core/auth'
5
6 // Thanks: https://stackoverflow.com/questions/901115/how-can-i-get-query-string-values-in-javascript
7 function getParameterByName (name: string, url: string) {
8 if (!url) url = window.location.href
9 name = name.replace(/[\[\]]/g, '\\$&')
10
11 const regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)')
12 const results = regex.exec(url)
13
14 if (!results) return null
15 if (!results[2]) return ''
16
17 return decodeURIComponent(results[2].replace(/\+/g, ' '))
18 }
19
20 function populateAsyncUserVideoChannels (
21 authService: AuthService,
22 channel: SelectChannelItem[]
23 ) {
24 return new Promise(res => {
25 authService.userInformationLoaded
26 .subscribe(
27 () => {
28 const user = authService.getUser()
29 if (!user) return
30
31 const videoChannels = user.videoChannels
32 if (Array.isArray(videoChannels) === false) return
33
34 videoChannels.forEach(c => channel.push({
35 id: c.id,
36 label: c.displayName,
37 support: c.support,
38 avatarPath: c.avatar?.path
39 }))
40
41 return res()
42 }
43 )
44 })
45 }
46
47 function getAbsoluteAPIUrl () {
48 let absoluteAPIUrl = environment.hmr === true
49 ? 'http://localhost:9000'
50 : environment.apiUrl
51
52 if (!absoluteAPIUrl) {
53 // The API is on the same domain
54 absoluteAPIUrl = window.location.origin
55 }
56
57 return absoluteAPIUrl
58 }
59
60 function getAbsoluteEmbedUrl () {
61 let absoluteEmbedUrl = environment.embedUrl
62 if (!absoluteEmbedUrl) {
63 // The Embed is on the same domain
64 absoluteEmbedUrl = window.location.origin
65 }
66
67 return absoluteEmbedUrl
68 }
69
70 const datePipe = new DatePipe('en')
71 function dateToHuman (date: string) {
72 return datePipe.transform(date, 'medium')
73 }
74
75 function durationToString (duration: number) {
76 const hours = Math.floor(duration / 3600)
77 const minutes = Math.floor((duration % 3600) / 60)
78 const seconds = duration % 60
79
80 const minutesPadding = minutes >= 10 ? '' : '0'
81 const secondsPadding = seconds >= 10 ? '' : '0'
82 const displayedHours = hours > 0 ? hours.toString() + ':' : ''
83
84 return (
85 displayedHours + minutesPadding + minutes.toString() + ':' + secondsPadding + seconds.toString()
86 ).replace(/^0/, '')
87 }
88
89 function immutableAssign <A, B> (target: A, source: B) {
90 return Object.assign({}, target, source)
91 }
92
93 // Thanks: https://gist.github.com/ghinda/8442a57f22099bdb2e34
94 function objectToFormData (obj: any, form?: FormData, namespace?: string) {
95 const fd = form || new FormData()
96 let formKey
97
98 for (const key of Object.keys(obj)) {
99 if (namespace) formKey = `${namespace}[${key}]`
100 else formKey = key
101
102 if (obj[key] === undefined) continue
103
104 if (Array.isArray(obj[key]) && obj[key].length === 0) {
105 fd.append(key, null)
106 continue
107 }
108
109 if (obj[key] !== null && typeof obj[ key ] === 'object' && !(obj[ key ] instanceof File)) {
110 objectToFormData(obj[ key ], fd, formKey)
111 } else {
112 fd.append(formKey, obj[ key ])
113 }
114 }
115
116 return fd
117 }
118
119 function objectLineFeedToHtml (obj: any, keyToNormalize: string) {
120 return immutableAssign(obj, {
121 [keyToNormalize]: lineFeedToHtml(obj[keyToNormalize])
122 })
123 }
124
125 function lineFeedToHtml (text: string) {
126 if (!text) return text
127
128 return text.replace(/\r?\n|\r/g, '<br />')
129 }
130
131 function removeElementFromArray <T> (arr: T[], elem: T) {
132 const index = arr.indexOf(elem)
133 if (index !== -1) arr.splice(index, 1)
134 }
135
136 function 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
147 function scrollToTop () {
148 window.scroll(0, 0)
149 }
150
151 function isInViewport (el: HTMLElement) {
152 const bounding = el.getBoundingClientRect()
153 return (
154 bounding.top >= 0 &&
155 bounding.left >= 0 &&
156 bounding.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
157 bounding.right <= (window.innerWidth || document.documentElement.clientWidth)
158 )
159 }
160
161 function isXPercentInViewport (el: HTMLElement, percentVisible: number) {
162 const rect = el.getBoundingClientRect()
163 const windowHeight = (window.innerHeight || document.documentElement.clientHeight)
164
165 return !(
166 Math.floor(100 - (((rect.top >= 0 ? 0 : rect.top) / +-(rect.height / 1)) * 100)) < percentVisible ||
167 Math.floor(100 - ((rect.bottom - windowHeight) / rect.height) * 100) < percentVisible
168 )
169 }
170
171 export {
172 sortBy,
173 durationToString,
174 lineFeedToHtml,
175 getParameterByName,
176 populateAsyncUserVideoChannels,
177 getAbsoluteAPIUrl,
178 dateToHuman,
179 immutableAssign,
180 objectToFormData,
181 getAbsoluteEmbedUrl,
182 objectLineFeedToHtml,
183 removeElementFromArray,
184 scrollToTop,
185 isInViewport,
186 isXPercentInViewport
187 }