stream-chat-react-native-core
Version:
The official React Native and Expo components for Stream Chat, a service for building chat applications
99 lines (88 loc) • 3.17 kB
text/typescript
import { isDayjs } from 'dayjs';
import type { Duration as DayjsDuration } from 'dayjs/plugin/duration';
import { getDateString } from './getDateString';
import { DurationFormatterOptions, PredefinedFormatters, TimestampFormatterOptions } from './types';
import { isDayOrMoment } from '../../contexts/translationContext/isDayOrMoment';
export const predefinedFormatters: PredefinedFormatters = {
durationFormatter:
(streamI18n) =>
(value, _, { format, withSuffix }: DurationFormatterOptions) => {
if (format && isDayjs(streamI18n.DateTimeParser)) {
return (streamI18n.DateTimeParser.duration(value) as DayjsDuration).format(format);
}
return streamI18n.DateTimeParser.duration(value).humanize(!!withSuffix);
},
timestampFormatter:
(streamI18n) =>
(
value,
_,
{
calendarFormats,
...options
}: Pick<TimestampFormatterOptions, 'calendar' | 'format'> & {
calendarFormats?: Record<string, string> | string;
},
) => {
let parsedCalendarFormats;
try {
if (!options.calendar) {
parsedCalendarFormats = {};
} else if (typeof calendarFormats === 'string') {
parsedCalendarFormats = JSON.parse(calendarFormats);
} else if (typeof calendarFormats === 'object') {
parsedCalendarFormats = calendarFormats;
}
} catch (e) {
console.error('[TIMESTAMP FORMATTER]', e);
}
const result = getDateString({
...options,
calendarFormats: parsedCalendarFormats,
date: value,
tDateTimeParser: streamI18n.tDateTimeParser,
});
if (!result || typeof result === 'number') {
return JSON.stringify(value);
}
return result;
},
fromNowFormatter:
(streamI18n) =>
(value, _, { withSuffix }: { withSuffix?: boolean } = {}) => {
const parsedTime = streamI18n.tDateTimeParser(value);
if (!isDayOrMoment(parsedTime) || typeof parsedTime.fromNow !== 'function') {
return JSON.stringify(value);
}
// fromNow(withoutSuffix); default to including the "ago" suffix
return parsedTime.fromNow(withSuffix === false);
},
relativeCompactDateFormatter: (streamI18n) => (value) => {
if (value === undefined || value === null) {
return JSON.stringify(value);
}
const parsedTime = streamI18n.tDateTimeParser(value);
const parsedNow = streamI18n.tDateTimeParser();
if (!isDayOrMoment(parsedTime) || !isDayOrMoment(parsedNow)) {
return JSON.stringify(value);
}
const oneDayInMs = 24 * 60 * 60 * 1000;
const startOfNowDayMs = parsedNow.startOf('day').valueOf();
const startOfTimeDayMs = parsedTime.startOf('day').valueOf();
const daysAgo = Math.floor((startOfNowDayMs - startOfTimeDayMs) / oneDayInMs);
if (daysAgo <= 0) {
return 'Today';
}
if (daysAgo === 1) {
return 'Yesterday';
}
if (daysAgo <= 6) {
return `${daysAgo}d ago`;
}
const weeksAgo = Math.floor(daysAgo / 7);
if (weeksAgo <= 3) {
return `${weeksAgo}w ago`;
}
return parsedTime.format('DD/MM/YY');
},
};