Bluesky app fork with some witchin' additions 馃挮 witchsky.app
bluesky fork client
119
fork

Configure Feed

Select the types of activity you want to include in your feed.

at a876aae44ea07494ebea9727350aa060b81f317b 191 lines 5.0 kB view raw
1import {useCallback} from 'react' 2import {type I18n} from '@lingui/core' 3import {defineMessage, msg, plural} from '@lingui/core/macro' 4import {useLingui} from '@lingui/react' 5import {differenceInSeconds} from 'date-fns' 6 7export type DateDiffFormat = 'long' | 'short' 8 9type DateDiff = { 10 value: number 11 unit: 'now' | 'second' | 'minute' | 'hour' | 'day' | 'month' 12 earlier: Date 13 later: Date 14} 15 16const NOW = 5 17const MINUTE = 60 18const HOUR = MINUTE * 60 19const DAY = HOUR * 24 20const MONTH_30 = DAY * 30 21 22export function useGetTimeAgo({future = false}: {future?: boolean} = {}) { 23 const {i18n} = useLingui() 24 return useCallback( 25 ( 26 earlier: number | string | Date, 27 later: number | string | Date, 28 options?: {format: DateDiffFormat}, 29 ) => { 30 const diff = dateDiff(earlier, later, future ? 'up' : 'down') 31 return formatDateDiff({diff, i18n, format: options?.format}) 32 }, 33 [i18n, future], 34 ) 35} 36 37/** 38 * Returns the difference between `earlier` and `later` dates, based on 39 * opinionated rules. 40 * 41 * - All month are considered exactly 30 days. 42 * - Dates assume `earlier` <= `later`, and will otherwise return 'now'. 43 * - All values round down 44 */ 45export function dateDiff( 46 earlier: number | string | Date, 47 later: number | string | Date, 48 rounding: 'up' | 'down' = 'down', 49): DateDiff { 50 let diff = { 51 value: 0, 52 unit: 'now' as DateDiff['unit'], 53 } 54 const e = new Date(earlier) 55 const l = new Date(later) 56 const diffSeconds = differenceInSeconds(l, e) 57 58 if (diffSeconds < NOW) { 59 diff = { 60 value: 0, 61 unit: 'now' as DateDiff['unit'], 62 } 63 } else if (diffSeconds < MINUTE) { 64 diff = { 65 value: diffSeconds, 66 unit: 'second' as DateDiff['unit'], 67 } 68 } else if (diffSeconds < HOUR) { 69 const value = 70 rounding === 'up' 71 ? Math.ceil(diffSeconds / MINUTE) 72 : Math.floor(diffSeconds / MINUTE) 73 diff = { 74 value, 75 unit: 'minute' as DateDiff['unit'], 76 } 77 } else if (diffSeconds < DAY) { 78 const value = 79 rounding === 'up' 80 ? Math.ceil(diffSeconds / HOUR) 81 : Math.floor(diffSeconds / HOUR) 82 diff = { 83 value, 84 unit: 'hour' as DateDiff['unit'], 85 } 86 } else if (diffSeconds < MONTH_30) { 87 const value = 88 rounding === 'up' 89 ? Math.ceil(diffSeconds / DAY) 90 : Math.floor(diffSeconds / DAY) 91 diff = { 92 value, 93 unit: 'day' as DateDiff['unit'], 94 } 95 } else { 96 const value = 97 rounding === 'up' 98 ? Math.ceil(diffSeconds / MONTH_30) 99 : Math.floor(diffSeconds / MONTH_30) 100 diff = { 101 value, 102 unit: 'month' as DateDiff['unit'], 103 } 104 } 105 106 return { 107 ...diff, 108 earlier: e, 109 later: l, 110 } 111} 112 113/** 114 * Accepts a `DateDiff` and teturns the difference between `earlier` and 115 * `later` dates, formatted as a natural language string. 116 * 117 * - All month are considered exactly 30 days. 118 * - Dates assume `earlier` <= `later`, and will otherwise return 'now'. 119 * - Differences >= 360 days are returned as the "M/D/YYYY" string 120 * - All values round down 121 */ 122export function formatDateDiff({ 123 diff, 124 format = 'short', 125 i18n, 126}: { 127 diff: DateDiff 128 format?: DateDiffFormat 129 i18n: I18n 130}): string { 131 const long = format === 'long' 132 133 switch (diff.unit) { 134 case 'now': { 135 return i18n._(msg`now`) 136 } 137 case 'second': { 138 return long 139 ? i18n._(plural(diff.value, {one: '# second', other: '# seconds'})) 140 : i18n._( 141 defineMessage({ 142 message: `${diff.value}s`, 143 comment: `How many seconds have passed, displayed in a narrow form`, 144 }), 145 ) 146 } 147 case 'minute': { 148 return long 149 ? i18n._(plural(diff.value, {one: '# minute', other: '# minutes'})) 150 : i18n._( 151 defineMessage({ 152 message: `${diff.value}m`, 153 comment: `How many minutes have passed, displayed in a narrow form`, 154 }), 155 ) 156 } 157 case 'hour': { 158 return long 159 ? i18n._(plural(diff.value, {one: '# hour', other: '# hours'})) 160 : i18n._( 161 defineMessage({ 162 message: `${diff.value}h`, 163 comment: `How many hours have passed, displayed in a narrow form`, 164 }), 165 ) 166 } 167 case 'day': { 168 return long 169 ? i18n._(plural(diff.value, {one: '# day', other: '# days'})) 170 : i18n._( 171 defineMessage({ 172 message: `${diff.value}d`, 173 comment: `How many days have passed, displayed in a narrow form`, 174 }), 175 ) 176 } 177 case 'month': { 178 if (diff.value < 12) { 179 return long 180 ? i18n._(plural(diff.value, {one: '# month', other: '# months'})) 181 : i18n._( 182 defineMessage({ 183 message: plural(diff.value, {one: '#mo', other: '#mo'}), 184 comment: `How many months have passed, displayed in a narrow form`, 185 }), 186 ) 187 } 188 return i18n.date(new Date(diff.earlier)) 189 } 190 } 191}