169 lines
4.4 KiB
TypeScript
Raw Normal View History

2022-04-16 21:14:03 +08:00
import { IpcChannels } from '@/shared/IpcChannels'
2022-03-13 14:40:38 +08:00
import dayjs from 'dayjs'
import duration from 'dayjs/plugin/duration'
2022-04-16 21:14:03 +08:00
import { APIs } from '@/shared/CacheAPIs'
2022-04-12 01:48:14 +08:00
import { average } from 'color.js'
import { colord } from 'colord'
2022-03-13 14:40:38 +08:00
/**
* @description
* @param {string} url URL
* @param {'xs'|'sm'|'md'|'lg'} size - 128px | 256px | 512px | 1024px
*/
export function resizeImage(
url: string,
size: 'xs' | 'sm' | 'md' | 'lg'
): string {
if (!url) return ''
2022-04-13 16:17:21 +08:00
2022-03-13 14:40:38 +08:00
const sizeMap = {
xs: '128',
sm: '256',
md: '512',
lg: '1024',
}
2022-03-19 17:03:29 +08:00
return `${url}?param=${sizeMap[size]}y${sizeMap[size]}`.replace(
2022-05-29 17:53:27 +08:00
/http(s?):\/\/p\d.music.126.net/,
'https://p1.music.126.net'
2022-03-19 17:03:29 +08:00
)
2022-03-13 14:40:38 +08:00
}
export const storage = {
get(key: string): object | [] | null {
const text = localStorage.getItem(key)
return text ? JSON.parse(text) : null
},
set(key: string, value: object | []): void {
localStorage.setItem(key, JSON.stringify(value))
},
}
/**
* @description
* @param {number} timestamp -
* @param {'en'|'zh-TW'|'zh-CN'='en'} locale -
* @param {string='default'} format - dayjs
*/
export function formatDate(
timestamp: number,
2022-04-13 16:17:21 +08:00
locale: 'en' | 'zh-TW' | 'zh-CN' = 'zh-CN',
2022-03-13 14:40:38 +08:00
format: string = 'default'
): string {
if (!timestamp) return ''
if (format === 'default') {
format = 'MMM D, YYYY'
if (['zh-CN', 'zh-TW'].includes(locale)) format = 'YYYY年MM月DD日'
}
return dayjs(timestamp).format(format)
}
/**
* @description
* @param {number} milliseconds -
* @param {'en'|'zh-TW'|'zh-CN'='en'} locale -
* @param {'hh:mm:ss'|'hh[hr]mm[min]'='hh:mm:ss'} format -
*/
export function formatDuration(
milliseconds: number,
2022-04-13 16:17:21 +08:00
locale: 'en' | 'zh-TW' | 'zh-CN' = 'zh-CN',
2022-03-13 14:40:38 +08:00
format: 'hh:mm:ss' | 'hh[hr] mm[min]' = 'hh:mm:ss'
): string {
dayjs.extend(duration)
2022-04-12 01:48:14 +08:00
const time = dayjs.duration(milliseconds)
const hours = time.hours().toString()
const mins = time.minutes().toString()
const seconds = time.seconds().toString().padStart(2, '0')
2022-03-13 14:40:38 +08:00
if (format === 'hh:mm:ss') {
return hours !== '0'
? `${hours}:${mins.padStart(2, '0')}:${seconds}`
: `${mins}:${seconds}`
2022-04-15 00:34:36 +08:00
} else {
2022-03-13 14:40:38 +08:00
const units = {
en: {
hours: 'hr',
mins: 'min',
},
'zh-CN': {
hours: '小时',
mins: '分钟',
},
'zh-TW': {
hours: '小時',
mins: '分鐘',
},
}
2022-04-13 16:17:21 +08:00
2022-03-13 14:40:38 +08:00
return hours !== '0'
2022-04-13 16:17:21 +08:00
? `${hours} ${units[locale].hours}${
mins === '0' ? '' : ` ${mins} ${units[locale].mins}`
}`
2022-03-13 14:40:38 +08:00
: `${mins} ${units[locale].mins}`
}
}
2022-03-17 19:30:43 +08:00
export function scrollToTop(smooth = false) {
const main = document.getElementById('mainContainer')
if (!main) return
main.scrollTo({ top: 0, behavior: smooth ? 'smooth' : 'auto' })
}
2022-04-12 01:48:14 +08:00
export async function getCoverColor(coverUrl: string) {
2022-04-16 21:14:03 +08:00
let id: string | undefined
try {
id = new URL(coverUrl).pathname.split('/').pop()?.split('.')[0]
} catch (e) {
return
}
2022-04-12 01:48:14 +08:00
const colorFromCache = window.ipcRenderer?.sendSync(
IpcChannels.GetApiCacheSync,
{
api: APIs.CoverColor,
query: {
id,
},
}
) as string | undefined
return colorFromCache || calcCoverColor(coverUrl)
}
export async function cacheCoverColor(coverUrl: string, color: string) {
2022-04-16 21:14:03 +08:00
let id: string | undefined
try {
id = new URL(coverUrl).pathname.split('/').pop()?.split('.')[0]
} catch (e) {
return
}
if (!id || isNaN(Number(id))) return
2022-04-12 01:48:14 +08:00
window.ipcRenderer?.send(IpcChannels.CacheCoverColor, {
2022-04-16 21:14:03 +08:00
id: Number(id),
color,
2022-04-12 01:48:14 +08:00
})
}
export async function calcCoverColor(coverUrl: string) {
if (!coverUrl) return
const cover = resizeImage(coverUrl, 'xs')
return average(cover, { amount: 1, format: 'hex', sample: 1 }).then(color => {
let c = colord(color as string)
const hsl = c.toHsl()
if (hsl.s > 50) c = colord({ ...hsl, s: 50 })
if (hsl.l > 50) c = colord({ ...c.toHsl(), l: 50 })
if (hsl.l < 30) c = colord({ ...c.toHsl(), l: 30 })
cacheCoverColor(coverUrl, c.toHex())
return c.toHex()
})
}
2022-06-08 11:48:22 +08:00
export const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent)
2022-06-12 15:29:14 +08:00
export const isSafari = /^((?!chrome|android).)*safari/i.test(
navigator.userAgent
)
2022-06-08 11:48:22 +08:00
export const isPWA =
(navigator as any).standalone ||
window.matchMedia('(display-mode: standalone)').matches