Bluesky app fork with some witchin' additions 馃挮
at main 64 lines 1.8 kB view raw
1import {useEffect, useState} from 'react' 2import {type I18n} from '@lingui/core' 3import {plural} from '@lingui/macro' 4 5export function displayDuration(i18n: I18n, durationInMinutes: number) { 6 const roundedDurationInMinutes = Math.round(durationInMinutes) 7 const hours = Math.floor(roundedDurationInMinutes / 60) 8 const minutes = roundedDurationInMinutes % 60 9 const minutesString = i18n._( 10 plural(minutes, {one: '# minute', other: '# minutes'}), 11 ) 12 return hours > 0 13 ? i18n._( 14 minutes > 0 15 ? plural(hours, { 16 one: `# hour ${minutesString}`, 17 other: `# hours ${minutesString}`, 18 }) 19 : plural(hours, { 20 one: '# hour', 21 other: '# hours', 22 }), 23 ) 24 : minutesString 25} 26 27// Trailing debounce 28export function useDebouncedValue<T>(val: T, delayMs: number): T { 29 const [prev, setPrev] = useState(val) 30 31 useEffect(() => { 32 const timeout = setTimeout(() => setPrev(val), delayMs) 33 return () => clearTimeout(timeout) 34 }, [val, delayMs]) 35 36 return prev 37} 38 39const serviceUrlToNameMap: Record<string, string> = { 40 'twitch.tv': 'Twitch', 41 'www.twitch.tv': 'Twitch', 42 'youtube.com': 'YouTube', 43 'www.youtube.com': 'YouTube', 44 'youtu.be': 'YouTube', 45 'nba.com': 'NBA', 46 'www.nba.com': 'NBA', 47 'nba.smart.link': 'nba.smart.link', 48 'espn.com': 'ESPN', 49 'www.espn.com': 'ESPN', 50 'stream.place': 'Streamplace', 51 'skylight.social': 'Skylight', 52 'bluecast.app': 'Bluecast', 53 'www.bluecast.app': 'Bluecast', 54} 55 56export function getLiveServiceNames(domains: Set<string>) { 57 const names = Array.from( 58 new Set(Array.from(domains.values()).map(d => serviceUrlToNameMap[d] || d)), 59 ) 60 return { 61 names, 62 formatted: names.join(', '), 63 } 64}