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) ) }