1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import type { Track } from './types'
export const isMobile = () => (
matchMedia('(pointer: coarse)').matches
&& (navigator.maxTouchPoints > 0)
)
export const randomString = (): string => {
let arr = new Uint8Array(16)
window.crypto.getRandomValues(arr)
const validChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
arr = arr.map(x => validChars.charCodeAt(x % validChars.length))
return String.fromCharCode.apply(null, Array.from(arr))
}
export const shuffle = (list: any[], moveFirst?: number): void => {
if (moveFirst !== undefined)
[list[0], list[moveFirst]] = [list[moveFirst], list[0]]
const
end = list.length - 1,
start = (
(moveFirst !== undefined)
? 1
: 0
)
for (let i = end; i > start; i--) {
const j = Math.floor(Math.random() * (i - start + 1) + start);
[list[i], list[j]] = [list[j], list[i]]
}
}
export const shuffled = (list: any[], moveFirst?: number): any[] => {
list = [...list]
shuffle(list, moveFirst)
return list
}
export const trackListEquals = (a: Track[], b: Track[]): boolean => {
if (a.length !== b.length)
return false
for (let i = 0; i < a.length; i++) {
if (a[i]?.id !== b[i]?.id) return false
}
return true
}
export const formatArtists = (artists: { name: string }[]): string => artists.map(ar => ar.name).join(', ')
export const formatTitle = (title: string): string => (
(!title)
? ''
: (
(title.length > 40)
? title.slice(0, 37) + '…'
: title
)
)
export const formatDuration = (value: number): string => {
if (!isFinite(value))
return '∞'
const
minutes = Math.floor(value / 60),
seconds = Math.floor(value % 60)
return `${minutes < 10 ? '0' : ''}${minutes}:${seconds < 10 ? '0' : ''}${seconds}`;
}
export const formatBytes = (bytes: number, decimals: number): string => {
if (bytes === 0) return '0 Bytes';
const
k = 1024,
i = Math.floor(Math.log(bytes) / Math.log(k)),
unit = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'][i];
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(decimals || 2))} ${unit}`;
}
export const sleep = async (ms: number) => new Promise(
resolve => setTimeout(resolve, ms)
)
export const isElementInViewport = (element: HTMLElement | null) => {
if (!element) return false
const rect = element.getBoundingClientRect()
return (
rect.bottom >= 0 &&
rect.right >= 0 &&
rect.top <= (window.innerHeight || document.documentElement.clientHeight) &&
rect.left <= (window.innerWidth || document.documentElement.clientWidth)
)
}