Add incomplete dateFormatString setting

This commit is contained in:
Gimle Larpes 2025-05-30 20:56:05 +02:00
parent 4588168a66
commit 1295c1c9b7
14 changed files with 203 additions and 15 deletions

View file

@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
import dateFormat from 'dateformat'; import dateFormat from 'dateformat';
import { isInSameDay } from '../../../util/common'; import { isInSameDay } from '../../../util/common';
function Time({ timestamp, fullTime, hour24Clock }) { function Time({ timestamp, fullTime, hour24Clock, dateFormatString }) {
const date = new Date(timestamp); const date = new Date(timestamp);
const formattedFullTime = dateFormat( const formattedFullTime = dateFormat(
@ -21,7 +21,7 @@ function Time({ timestamp, fullTime, hour24Clock }) {
const timeFormat = hour24Clock ? 'HH:MM' : 'hh:MM TT'; const timeFormat = hour24Clock ? 'HH:MM' : 'hh:MM TT';
formattedDate = dateFormat(date, isToday || isYesterday ? timeFormat : 'dd/mm/yyyy'); formattedDate = dateFormat(date, isToday || isYesterday ? timeFormat : dateFormatString);
if (isYesterday) { if (isYesterday) {
formattedDate = `Yesterday, ${formattedDate}`; formattedDate = `Yesterday, ${formattedDate}`;
} }
@ -42,6 +42,7 @@ Time.propTypes = {
timestamp: PropTypes.number.isRequired, timestamp: PropTypes.number.isRequired,
fullTime: PropTypes.bool, fullTime: PropTypes.bool,
hour24Clock: PropTypes.bool.isRequired, hour24Clock: PropTypes.bool.isRequired,
dateFormatString: PropTypes.string.isRequired,
}; };
export default Time; export default Time;

View file

@ -6,10 +6,11 @@ export type TimeProps = {
compact?: boolean; compact?: boolean;
ts: number; ts: number;
hour24Clock: boolean; hour24Clock: boolean;
dateFormatString: string;
}; };
export const Time = as<'span', TimeProps & ComponentProps<typeof Text>>( export const Time = as<'span', TimeProps & ComponentProps<typeof Text>>(
({ compact, hour24Clock, ts, ...props }, ref) => { ({ compact, hour24Clock, dateFormatString, ts, ...props }, ref) => {
const formattedTime = timeHourMinute(ts, hour24Clock); const formattedTime = timeHourMinute(ts, hour24Clock);
let time = ''; let time = '';
@ -20,7 +21,7 @@ export const Time = as<'span', TimeProps & ComponentProps<typeof Text>>(
} else if (yesterday(ts)) { } else if (yesterday(ts)) {
time = `Yesterday ${formattedTime}`; time = `Yesterday ${formattedTime}`;
} else { } else {
time = `${timeDayMonYear(ts)} ${formattedTime}`; time = `${timeDayMonYear(ts, dateFormatString)} ${formattedTime}`;
} }
return ( return (

View file

@ -58,6 +58,7 @@ export function MessageSearch({
const [legacyUsernameColor] = useSetting(settingsAtom, 'legacyUsernameColor'); const [legacyUsernameColor] = useSetting(settingsAtom, 'legacyUsernameColor');
const [hour24Clock] = useSetting(settingsAtom, 'hour24Clock'); const [hour24Clock] = useSetting(settingsAtom, 'hour24Clock');
const [dateFormatString] = useSetting(settingsAtom, 'dateFormatString');
const searchInputRef = useRef<HTMLInputElement>(null); const searchInputRef = useRef<HTMLInputElement>(null);
const scrollTopAnchorRef = useRef<HTMLDivElement>(null); const scrollTopAnchorRef = useRef<HTMLDivElement>(null);
@ -292,6 +293,7 @@ export function MessageSearch({
onOpen={navigateRoom} onOpen={navigateRoom}
legacyUsernameColor={legacyUsernameColor || mDirects.has(groupRoom.roomId)} legacyUsernameColor={legacyUsernameColor || mDirects.has(groupRoom.roomId)}
hour24Clock={hour24Clock} hour24Clock={hour24Clock}
dateFormatString={dateFormatString}
/> />
</VirtualTile> </VirtualTile>
); );

View file

@ -58,6 +58,7 @@ type SearchResultGroupProps = {
onOpen: (roomId: string, eventId: string) => void; onOpen: (roomId: string, eventId: string) => void;
legacyUsernameColor?: boolean; legacyUsernameColor?: boolean;
hour24Clock: boolean; hour24Clock: boolean;
dateFormatString: string;
}; };
export function SearchResultGroup({ export function SearchResultGroup({
room, room,
@ -68,6 +69,7 @@ export function SearchResultGroup({
onOpen, onOpen,
legacyUsernameColor, legacyUsernameColor,
hour24Clock, hour24Clock,
dateFormatString,
}: SearchResultGroupProps) { }: SearchResultGroupProps) {
const mx = useMatrixClient(); const mx = useMatrixClient();
const useAuthentication = useMediaAuthentication(); const useAuthentication = useMediaAuthentication();
@ -277,7 +279,11 @@ export function SearchResultGroup({
</Username> </Username>
{tagIconSrc && <PowerIcon size="100" iconSrc={tagIconSrc} />} {tagIconSrc && <PowerIcon size="100" iconSrc={tagIconSrc} />}
</Box> </Box>
<Time ts={event.origin_server_ts} hour24Clock={hour24Clock} /> <Time
ts={event.origin_server_ts}
hour24Clock={hour24Clock}
dateFormatString={dateFormatString}
/>
</Box> </Box>
<Box shrink="No" gap="200" alignItems="Center"> <Box shrink="No" gap="200" alignItems="Center">
<Chip <Chip

View file

@ -449,6 +449,7 @@ export function RoomTimeline({
const showUrlPreview = room.hasEncryptionStateEvent() ? encUrlPreview : urlPreview; const showUrlPreview = room.hasEncryptionStateEvent() ? encUrlPreview : urlPreview;
const [showHiddenEvents] = useSetting(settingsAtom, 'showHiddenEvents'); const [showHiddenEvents] = useSetting(settingsAtom, 'showHiddenEvents');
const [hour24Clock] = useSetting(settingsAtom, 'hour24Clock'); const [hour24Clock] = useSetting(settingsAtom, 'hour24Clock');
const [dateFormatString] = useSetting(settingsAtom, 'dateFormatString');
const ignoredUsersList = useIgnoredUsers(); const ignoredUsersList = useIgnoredUsers();
const ignoredUsersSet = useMemo(() => new Set(ignoredUsersList), [ignoredUsersList]); const ignoredUsersSet = useMemo(() => new Set(ignoredUsersList), [ignoredUsersList]);
@ -1070,6 +1071,7 @@ export function RoomTimeline({
accessibleTagColors={accessibleTagColors} accessibleTagColors={accessibleTagColors}
legacyUsernameColor={legacyUsernameColor || direct} legacyUsernameColor={legacyUsernameColor || direct}
hour24Clock={hour24Clock} hour24Clock={hour24Clock}
dateFormatString={dateFormatString}
> >
{mEvent.isRedacted() ? ( {mEvent.isRedacted() ? (
<RedactedContent reason={mEvent.getUnsigned().redacted_because?.content.reason} /> <RedactedContent reason={mEvent.getUnsigned().redacted_because?.content.reason} />
@ -1152,6 +1154,7 @@ export function RoomTimeline({
accessibleTagColors={accessibleTagColors} accessibleTagColors={accessibleTagColors}
legacyUsernameColor={legacyUsernameColor || direct} legacyUsernameColor={legacyUsernameColor || direct}
hour24Clock={hour24Clock} hour24Clock={hour24Clock}
dateFormatString={dateFormatString}
> >
<EncryptedContent mEvent={mEvent}> <EncryptedContent mEvent={mEvent}>
{() => { {() => {
@ -1254,6 +1257,7 @@ export function RoomTimeline({
accessibleTagColors={accessibleTagColors} accessibleTagColors={accessibleTagColors}
legacyUsernameColor={legacyUsernameColor || direct} legacyUsernameColor={legacyUsernameColor || direct}
hour24Clock={hour24Clock} hour24Clock={hour24Clock}
dateFormatString={dateFormatString}
> >
{mEvent.isRedacted() ? ( {mEvent.isRedacted() ? (
<RedactedContent reason={mEvent.getUnsigned().redacted_because?.content.reason} /> <RedactedContent reason={mEvent.getUnsigned().redacted_because?.content.reason} />
@ -1286,6 +1290,7 @@ export function RoomTimeline({
ts={mEvent.getTs()} ts={mEvent.getTs()}
compact={messageLayout === MessageLayout.Compact} compact={messageLayout === MessageLayout.Compact}
hour24Clock={hour24Clock} hour24Clock={hour24Clock}
dateFormatString={dateFormatString}
/> />
); );
@ -1326,6 +1331,7 @@ export function RoomTimeline({
ts={mEvent.getTs()} ts={mEvent.getTs()}
compact={messageLayout === MessageLayout.Compact} compact={messageLayout === MessageLayout.Compact}
hour24Clock={hour24Clock} hour24Clock={hour24Clock}
dateFormatString={dateFormatString}
/> />
); );
@ -1367,6 +1373,7 @@ export function RoomTimeline({
ts={mEvent.getTs()} ts={mEvent.getTs()}
compact={messageLayout === MessageLayout.Compact} compact={messageLayout === MessageLayout.Compact}
hour24Clock={hour24Clock} hour24Clock={hour24Clock}
dateFormatString={dateFormatString}
/> />
); );
@ -1408,6 +1415,7 @@ export function RoomTimeline({
ts={mEvent.getTs()} ts={mEvent.getTs()}
compact={messageLayout === MessageLayout.Compact} compact={messageLayout === MessageLayout.Compact}
hour24Clock={hour24Clock} hour24Clock={hour24Clock}
dateFormatString={dateFormatString}
/> />
); );
@ -1451,6 +1459,7 @@ export function RoomTimeline({
ts={mEvent.getTs()} ts={mEvent.getTs()}
compact={messageLayout === MessageLayout.Compact} compact={messageLayout === MessageLayout.Compact}
hour24Clock={hour24Clock} hour24Clock={hour24Clock}
dateFormatString={dateFormatString}
/> />
); );
@ -1499,6 +1508,7 @@ export function RoomTimeline({
ts={mEvent.getTs()} ts={mEvent.getTs()}
compact={messageLayout === MessageLayout.Compact} compact={messageLayout === MessageLayout.Compact}
hour24Clock={hour24Clock} hour24Clock={hour24Clock}
dateFormatString={dateFormatString}
/> />
); );

View file

@ -679,6 +679,7 @@ export type MessageProps = {
accessibleTagColors?: Map<string, string>; accessibleTagColors?: Map<string, string>;
legacyUsernameColor?: boolean; legacyUsernameColor?: boolean;
hour24Clock: boolean; hour24Clock: boolean;
dateFormatString: string;
}; };
export const Message = as<'div', MessageProps>( export const Message = as<'div', MessageProps>(
( (
@ -708,6 +709,7 @@ export const Message = as<'div', MessageProps>(
accessibleTagColors, accessibleTagColors,
legacyUsernameColor, legacyUsernameColor,
hour24Clock, hour24Clock,
dateFormatString,
children, children,
...props ...props
}, },
@ -776,6 +778,7 @@ export const Message = as<'div', MessageProps>(
ts={mEvent.getTs()} ts={mEvent.getTs()}
compact={messageLayout === MessageLayout.Compact} compact={messageLayout === MessageLayout.Compact}
hour24Clock={hour24Clock} hour24Clock={hour24Clock}
dateFormatString={dateFormatString}
/> />
</Box> </Box>
</Box> </Box>

View file

@ -103,6 +103,7 @@ function PinnedMessage({ room, eventId, renderContent, onOpen, canPinEvent }: Pi
const accessibleTagColors = useAccessibleTagColors(theme.kind, powerLevelTags); const accessibleTagColors = useAccessibleTagColors(theme.kind, powerLevelTags);
const [hour24Clock] = useSetting(settingsAtom, 'hour24Clock'); const [hour24Clock] = useSetting(settingsAtom, 'hour24Clock');
const [dateFormatString] = useSetting(settingsAtom, 'dateFormatString');
const [unpinState, unpin] = useAsyncCallback( const [unpinState, unpin] = useAsyncCallback(
useCallback(() => { useCallback(() => {
@ -207,7 +208,11 @@ function PinnedMessage({ room, eventId, renderContent, onOpen, canPinEvent }: Pi
</Username> </Username>
{tagIconSrc && <PowerIcon size="100" iconSrc={tagIconSrc} />} {tagIconSrc && <PowerIcon size="100" iconSrc={tagIconSrc} />}
</Box> </Box>
<Time ts={pinnedEvent.getTs()} hour24Clock={hour24Clock} /> <Time
ts={pinnedEvent.getTs()}
hour24Clock={hour24Clock}
dateFormatString={dateFormatString}
/>
</Box> </Box>
{renderOptions()} {renderOptions()}
</Box> </Box>

View file

@ -44,6 +44,7 @@ export function DeviceTilePlaceholder() {
function DeviceActiveTime({ ts }: { ts: number }) { function DeviceActiveTime({ ts }: { ts: number }) {
const [hour24Clock] = useSetting(settingsAtom, 'hour24Clock'); const [hour24Clock] = useSetting(settingsAtom, 'hour24Clock');
const [dateFormatString] = useSetting(settingsAtom, 'dateFormatString');
return ( return (
<Text className={BreakWord} size="T200"> <Text className={BreakWord} size="T200">
@ -53,7 +54,8 @@ function DeviceActiveTime({ ts }: { ts: number }) {
<> <>
{today(ts) && 'Today'} {today(ts) && 'Today'}
{yesterday(ts) && 'Yesterday'} {yesterday(ts) && 'Yesterday'}
{!today(ts) && !yesterday(ts) && timeDayMonYear(ts)} {timeHourMinute(ts, hour24Clock)} {!today(ts) && !yesterday(ts) && timeDayMonYear(ts, dateFormatString)}{' '}
{timeHourMinute(ts, hour24Clock)}
</> </>
</Text> </Text>
); );

View file

@ -28,7 +28,7 @@ import FocusTrap from 'focus-trap-react';
import { Page, PageContent, PageHeader } from '../../../components/page'; import { Page, PageContent, PageHeader } from '../../../components/page';
import { SequenceCard } from '../../../components/sequence-card'; import { SequenceCard } from '../../../components/sequence-card';
import { useSetting } from '../../../state/hooks/settings'; import { useSetting } from '../../../state/hooks/settings';
import { MessageLayout, MessageSpacing, settingsAtom } from '../../../state/settings'; import { DateFormat, MessageLayout, MessageSpacing, settingsAtom } from '../../../state/settings';
import { SettingTile } from '../../../components/setting-tile'; import { SettingTile } from '../../../components/setting-tile';
import { KeySymbol } from '../../../utils/key-symbol'; import { KeySymbol } from '../../../utils/key-symbol';
import { isMacOS } from '../../../utils/user-agent'; import { isMacOS } from '../../../utils/user-agent';
@ -44,6 +44,7 @@ import {
import { stopPropagation } from '../../../utils/keyboard'; import { stopPropagation } from '../../../utils/keyboard';
import { useMessageLayoutItems } from '../../../hooks/useMessageLayout'; import { useMessageLayoutItems } from '../../../hooks/useMessageLayout';
import { useMessageSpacingItems } from '../../../hooks/useMessageSpacing'; import { useMessageSpacingItems } from '../../../hooks/useMessageSpacing';
import { useDateFormatItems } from '../../../hooks/useDateFormat';
import { SequenceCardStyle } from '../styles.css'; import { SequenceCardStyle } from '../styles.css';
type ThemeSelectorProps = { type ThemeSelectorProps = {
@ -513,6 +514,76 @@ function SelectMessageSpacing() {
); );
} }
function SelectDateFormat() {
// ADD TEXT INPUT AND RELATED LOGIC-- ADD LIVE PREVIEW
const [menuCords, setMenuCords] = useState<RectCords>();
const [dateFormatString, setDateFormatString] = useSetting(settingsAtom, 'dateFormatString');
const dateFormatItems = useDateFormatItems();
const handleMenu: MouseEventHandler<HTMLButtonElement> = (evt) => {
setMenuCords(evt.currentTarget.getBoundingClientRect());
};
const handleSelect = (format: DateFormat) => {
setDateFormatString(format);
setMenuCords(undefined);
};
return (
<>
<Button
size="300"
variant="Secondary"
outlined
fill="Soft"
radii="300"
after={<Icon size="300" src={Icons.ChevronBottom} />}
onClick={handleMenu}
>
<Text size="T300">
{dateFormatItems.find((i) => i.format === dateFormatString)?.name ?? dateFormatString}
</Text>
</Button>
<PopOut
anchor={menuCords}
offset={5}
position="Bottom"
align="End"
content={
<FocusTrap
focusTrapOptions={{
initialFocus: false,
onDeactivate: () => setMenuCords(undefined),
clickOutsideDeactivates: true,
isKeyForward: (evt: KeyboardEvent) =>
evt.key === 'ArrowDown' || evt.key === 'ArrowRight',
isKeyBackward: (evt: KeyboardEvent) =>
evt.key === 'ArrowUp' || evt.key === 'ArrowLeft',
escapeDeactivates: stopPropagation,
}}
>
<Menu>
<Box direction="Column" gap="100" style={{ padding: config.space.S100 }}>
{dateFormatItems.map((item) => (
<MenuItem
key={item.format}
size="300"
variant={dateFormatString === item.format ? 'Primary' : 'Surface'}
radii="300"
onClick={() => handleSelect(item.format)}
>
<Text size="T300">{item.name}</Text>
</MenuItem>
))}
</Box>
</Menu>
</FocusTrap>
}
/>
</>
);
}
function Messages() { function Messages() {
const [legacyUsernameColor, setLegacyUsernameColor] = useSetting( const [legacyUsernameColor, setLegacyUsernameColor] = useSetting(
settingsAtom, settingsAtom,
@ -615,6 +686,9 @@ function Messages() {
after={<Switch variant="Primary" value={hour24Clock} onChange={setHour24Clock} />} after={<Switch variant="Primary" value={hour24Clock} onChange={setHour24Clock} />}
/> />
</SequenceCard> </SequenceCard>
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
<SettingTile title="Date Format" after={<SelectDateFormat />} />
</SequenceCard>
</Box> </Box>
); );
} }

View file

@ -0,0 +1,30 @@
import { useMemo } from 'react';
import { DateFormat } from '../state/settings';
export type DateFormatItem = {
name: string;
format: DateFormat;
};
export const useDateFormatItems = (): DateFormatItem[] =>
useMemo(
() => [
{
format: 'D MMM YYYY',
name: 'D MMM YYYY',
},
{
format: 'DD/MM/YYYY',
name: 'DD/MM/YYYY',
},
{
format: 'YYYY/MM/DD',
name: 'YYYY/MM/DD',
},
{
format: '',
name: 'Custom',
},
],
[]
);

View file

@ -138,10 +138,18 @@ type InviteCardProps = {
invite: InviteData; invite: InviteData;
compact?: boolean; compact?: boolean;
hour24Clock: boolean; hour24Clock: boolean;
dateFormatString: string;
onNavigate: NavigateHandler; onNavigate: NavigateHandler;
hideAvatar: boolean; hideAvatar: boolean;
}; };
function InviteCard({ invite, compact, hour24Clock, onNavigate, hideAvatar }: InviteCardProps) { function InviteCard({
invite,
compact,
hour24Clock,
dateFormatString,
onNavigate,
hideAvatar,
}: InviteCardProps) {
const mx = useMatrixClient(); const mx = useMatrixClient();
const userId = mx.getSafeUserId(); const userId = mx.getSafeUserId();
@ -298,7 +306,13 @@ function InviteCard({ invite, compact, hour24Clock, onNavigate, hideAvatar }: In
</Box> </Box>
{invite.inviteTs && ( {invite.inviteTs && (
<Box shrink="No"> <Box shrink="No">
<Time size="T200" ts={invite.inviteTs} hour24Clock={hour24Clock} priority="300" /> <Time
size="T200"
ts={invite.inviteTs}
hour24Clock={hour24Clock}
dateFormatString={dateFormatString}
priority="300"
/>
</Box> </Box>
)} )}
</Box> </Box>
@ -388,8 +402,15 @@ type KnownInvitesProps = {
handleNavigate: NavigateHandler; handleNavigate: NavigateHandler;
compact: boolean; compact: boolean;
hour24Clock: boolean; hour24Clock: boolean;
dateFormatString: string;
}; };
function KnownInvites({ invites, handleNavigate, compact, hour24Clock }: KnownInvitesProps) { function KnownInvites({
invites,
handleNavigate,
compact,
hour24Clock,
dateFormatString,
}: KnownInvitesProps) {
return ( return (
<Box direction="Column" gap="200"> <Box direction="Column" gap="200">
<Text size="H4">Primary</Text> <Text size="H4">Primary</Text>
@ -401,6 +422,7 @@ function KnownInvites({ invites, handleNavigate, compact, hour24Clock }: KnownIn
invite={invite} invite={invite}
compact={compact} compact={compact}
hour24Clock={hour24Clock} hour24Clock={hour24Clock}
dateFormatString={dateFormatString}
onNavigate={handleNavigate} onNavigate={handleNavigate}
hideAvatar={false} hideAvatar={false}
/> />
@ -426,8 +448,15 @@ type UnknownInvitesProps = {
handleNavigate: NavigateHandler; handleNavigate: NavigateHandler;
compact: boolean; compact: boolean;
hour24Clock: boolean; hour24Clock: boolean;
dateFormatString: string;
}; };
function UnknownInvites({ invites, handleNavigate, compact, hour24Clock }: UnknownInvitesProps) { function UnknownInvites({
invites,
handleNavigate,
compact,
hour24Clock,
dateFormatString,
}: UnknownInvitesProps) {
const mx = useMatrixClient(); const mx = useMatrixClient();
const [declineAllStatus, declineAll] = useAsyncCallback( const [declineAllStatus, declineAll] = useAsyncCallback(
@ -466,6 +495,7 @@ function UnknownInvites({ invites, handleNavigate, compact, hour24Clock }: Unkno
invite={invite} invite={invite}
compact={compact} compact={compact}
hour24Clock={hour24Clock} hour24Clock={hour24Clock}
dateFormatString={dateFormatString}
onNavigate={handleNavigate} onNavigate={handleNavigate}
hideAvatar hideAvatar
/> />
@ -491,8 +521,15 @@ type SpamInvitesProps = {
handleNavigate: NavigateHandler; handleNavigate: NavigateHandler;
compact: boolean; compact: boolean;
hour24Clock: boolean; hour24Clock: boolean;
dateFormatString: string;
}; };
function SpamInvites({ invites, handleNavigate, compact, hour24Clock }: SpamInvitesProps) { function SpamInvites({
invites,
handleNavigate,
compact,
hour24Clock,
dateFormatString,
}: SpamInvitesProps) {
const mx = useMatrixClient(); const mx = useMatrixClient();
const [showInvites, setShowInvites] = useState(false); const [showInvites, setShowInvites] = useState(false);
@ -617,6 +654,7 @@ function SpamInvites({ invites, handleNavigate, compact, hour24Clock }: SpamInvi
invite={invite} invite={invite}
compact={compact} compact={compact}
hour24Clock={hour24Clock} hour24Clock={hour24Clock}
dateFormatString={dateFormatString}
onNavigate={handleNavigate} onNavigate={handleNavigate}
hideAvatar hideAvatar
/> />
@ -681,6 +719,7 @@ export function Invites() {
const screenSize = useScreenSizeContext(); const screenSize = useScreenSizeContext();
const [hour24Clock] = useSetting(settingsAtom, 'hour24Clock'); const [hour24Clock] = useSetting(settingsAtom, 'hour24Clock');
const [dateFormatString] = useSetting(settingsAtom, 'dateFormatString');
const handleNavigate = (roomId: string, space: boolean) => { const handleNavigate = (roomId: string, space: boolean) => {
if (space) { if (space) {
@ -735,6 +774,7 @@ export function Invites() {
invites={knownInvites} invites={knownInvites}
compact={compact} compact={compact}
hour24Clock={hour24Clock} hour24Clock={hour24Clock}
dateFormatString={dateFormatString}
handleNavigate={handleNavigate} handleNavigate={handleNavigate}
/> />
)} )}
@ -744,6 +784,7 @@ export function Invites() {
invites={unknownInvites} invites={unknownInvites}
compact={compact} compact={compact}
hour24Clock={hour24Clock} hour24Clock={hour24Clock}
dateFormatString={dateFormatString}
handleNavigate={handleNavigate} handleNavigate={handleNavigate}
/> />
)} )}
@ -753,6 +794,7 @@ export function Invites() {
invites={spamInvites} invites={spamInvites}
compact={compact} compact={compact}
hour24Clock={hour24Clock} hour24Clock={hour24Clock}
dateFormatString={dateFormatString}
handleNavigate={handleNavigate} handleNavigate={handleNavigate}
/> />
)} )}

View file

@ -206,6 +206,7 @@ type RoomNotificationsGroupProps = {
onOpen: (roomId: string, eventId: string) => void; onOpen: (roomId: string, eventId: string) => void;
legacyUsernameColor?: boolean; legacyUsernameColor?: boolean;
hour24Clock: boolean; hour24Clock: boolean;
dateFormatString: string;
}; };
function RoomNotificationsGroupComp({ function RoomNotificationsGroupComp({
room, room,
@ -216,6 +217,7 @@ function RoomNotificationsGroupComp({
onOpen, onOpen,
legacyUsernameColor, legacyUsernameColor,
hour24Clock, hour24Clock,
dateFormatString,
}: RoomNotificationsGroupProps) { }: RoomNotificationsGroupProps) {
const mx = useMatrixClient(); const mx = useMatrixClient();
const useAuthentication = useMediaAuthentication(); const useAuthentication = useMediaAuthentication();
@ -498,7 +500,11 @@ function RoomNotificationsGroupComp({
</Username> </Username>
{tagIconSrc && <PowerIcon size="100" iconSrc={tagIconSrc} />} {tagIconSrc && <PowerIcon size="100" iconSrc={tagIconSrc} />}
</Box> </Box>
<Time ts={event.origin_server_ts} hour24Clock={hour24Clock} /> <Time
ts={event.origin_server_ts}
hour24Clock={hour24Clock}
dateFormatString={dateFormatString}
/>
</Box> </Box>
<Box shrink="No" gap="200" alignItems="Center"> <Box shrink="No" gap="200" alignItems="Center">
<Chip <Chip
@ -552,6 +558,7 @@ export function Notifications() {
const [urlPreview] = useSetting(settingsAtom, 'urlPreview'); const [urlPreview] = useSetting(settingsAtom, 'urlPreview');
const [legacyUsernameColor] = useSetting(settingsAtom, 'legacyUsernameColor'); const [legacyUsernameColor] = useSetting(settingsAtom, 'legacyUsernameColor');
const [hour24Clock] = useSetting(settingsAtom, 'hour24Clock'); const [hour24Clock] = useSetting(settingsAtom, 'hour24Clock');
const [dateFormatString] = useSetting(settingsAtom, 'dateFormatString');
const screenSize = useScreenSizeContext(); const screenSize = useScreenSizeContext();
const mDirects = useAtomValue(mDirectAtom); const mDirects = useAtomValue(mDirectAtom);
@ -717,6 +724,7 @@ export function Notifications() {
legacyUsernameColor || mDirects.has(groupRoom.roomId) legacyUsernameColor || mDirects.has(groupRoom.roomId)
} }
hour24Clock={hour24Clock} hour24Clock={hour24Clock}
dateFormatString={dateFormatString}
/> />
</VirtualTile> </VirtualTile>
); );

View file

@ -1,6 +1,7 @@
import { atom } from 'jotai'; import { atom } from 'jotai';
const STORAGE_KEY = 'settings'; const STORAGE_KEY = 'settings';
export type DateFormat = 'D MMM YYYY' | 'DD/MM/YYYY' | 'YYYY/MM/DD' | '';
export type MessageSpacing = '0' | '100' | '200' | '300' | '400' | '500'; export type MessageSpacing = '0' | '100' | '200' | '300' | '400' | '500';
export enum MessageLayout { export enum MessageLayout {
Modern = 0, Modern = 0,
@ -36,6 +37,7 @@ export interface Settings {
isNotificationSounds: boolean; isNotificationSounds: boolean;
hour24Clock: boolean; hour24Clock: boolean;
dateFormatString: string;
developerTools: boolean; developerTools: boolean;
} }
@ -68,6 +70,7 @@ const defaultSettings: Settings = {
isNotificationSounds: true, isNotificationSounds: true,
hour24Clock: false, hour24Clock: false,
dateFormatString: 'D MMM YYYY',
developerTools: false, developerTools: false,
}; };

View file

@ -12,7 +12,8 @@ export const yesterday = (ts: number): boolean => dayjs(ts).isYesterday();
export const timeHourMinute = (ts: number, hour24Clock: boolean): string => export const timeHourMinute = (ts: number, hour24Clock: boolean): string =>
dayjs(ts).format(hour24Clock ? 'HH:mm' : 'hh:mm A'); dayjs(ts).format(hour24Clock ? 'HH:mm' : 'hh:mm A');
export const timeDayMonYear = (ts: number): string => dayjs(ts).format('D MMM YYYY'); export const timeDayMonYear = (ts: number, dateFormatString: string): string =>
dayjs(ts).format(dateFormatString);
export const timeDayMonthYear = (ts: number): string => dayjs(ts).format('D MMMM YYYY'); export const timeDayMonthYear = (ts: number): string => dayjs(ts).format('D MMMM YYYY');