Add setting to enable 24-hour time format

This commit is contained in:
Gimle Larpes 2025-05-28 21:17:38 +02:00
parent a23279e633
commit 8b4524607b
14 changed files with 114 additions and 30 deletions

View file

@ -4,10 +4,13 @@ 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 }) { function Time({ timestamp, fullTime, hour24Clock }) {
const date = new Date(timestamp); const date = new Date(timestamp);
const formattedFullTime = dateFormat(date, 'dd mmmm yyyy, hh:MM TT'); const formattedFullTime = dateFormat(
date,
hour24Clock ? 'dd mmmm yyyy, HH:MM' : 'dd mmmm yyyy, hh:MM TT'
);
let formattedDate = formattedFullTime; let formattedDate = formattedFullTime;
if (!fullTime) { if (!fullTime) {
@ -16,17 +19,16 @@ function Time({ timestamp, fullTime }) {
compareDate.setDate(compareDate.getDate() - 1); compareDate.setDate(compareDate.getDate() - 1);
const isYesterday = isInSameDay(date, compareDate); const isYesterday = isInSameDay(date, compareDate);
formattedDate = dateFormat(date, isToday || isYesterday ? 'hh:MM TT' : 'dd/mm/yyyy'); const timeFormat = hour24Clock ? 'HH:MM' : 'hh:MM TT';
formattedDate = dateFormat(date, isToday || isYesterday ? timeFormat : 'dd/mm/yyyy');
if (isYesterday) { if (isYesterday) {
formattedDate = `Yesterday, ${formattedDate}`; formattedDate = `Yesterday, ${formattedDate}`;
} }
} }
return ( return (
<time <time dateTime={date.toISOString()} title={formattedFullTime}>
dateTime={date.toISOString()}
title={formattedFullTime}
>
{formattedDate} {formattedDate}
</time> </time>
); );
@ -39,6 +41,7 @@ Time.defaultProps = {
Time.propTypes = { Time.propTypes = {
timestamp: PropTypes.number.isRequired, timestamp: PropTypes.number.isRequired,
fullTime: PropTypes.bool, fullTime: PropTypes.bool,
hour24Clock: PropTypes.bool.isRequired,
}; };
export default Time; export default Time;

View file

@ -8,16 +8,18 @@ export type TimeProps = {
}; };
export const Time = as<'span', TimeProps & ComponentProps<typeof Text>>( export const Time = as<'span', TimeProps & ComponentProps<typeof Text>>(
({ compact, ts, ...props }, ref) => { ({ compact, hour24Clock, ts, ...props }, ref) => {
const formattedTime = timeHourMinute(ts, hour24Clock);
let time = ''; let time = '';
if (compact) { if (compact) {
time = timeHourMinute(ts); time = formattedTime;
} else if (today(ts)) { } else if (today(ts)) {
time = timeHourMinute(ts); time = formattedTime;
} else if (yesterday(ts)) { } else if (yesterday(ts)) {
time = `Yesterday ${timeHourMinute(ts)}`; time = `Yesterday ${formattedTime}`;
} else { } else {
time = `${timeDayMonYear(ts)} ${timeHourMinute(ts)}`; time = `${timeDayMonYear(ts)} ${formattedTime}`;
} }
return ( return (

View file

@ -15,6 +15,8 @@ import { nameInitials } from '../../utils/common';
import { useRoomAvatar, useRoomName, useRoomTopic } from '../../hooks/useRoomMeta'; import { useRoomAvatar, useRoomName, useRoomTopic } from '../../hooks/useRoomMeta';
import { mDirectAtom } from '../../state/mDirectList'; import { mDirectAtom } from '../../state/mDirectList';
import { useMediaAuthentication } from '../../hooks/useMediaAuthentication'; import { useMediaAuthentication } from '../../hooks/useMediaAuthentication';
import { useSetting } from '../../state/hooks/settings';
import { settingsAtom } from '../../state/settings';
export type RoomIntroProps = { export type RoomIntroProps = {
room: Room; room: Room;
@ -43,6 +45,8 @@ export const RoomIntro = as<'div', RoomIntroProps>(({ room, ...props }, ref) =>
useCallback(async (roomId: string) => mx.joinRoom(roomId), [mx]) useCallback(async (roomId: string) => mx.joinRoom(roomId), [mx])
); );
const [hour24Clock] = useSetting(settingsAtom, 'hour24Clock');
return ( return (
<Box direction="Column" grow="Yes" gap="500" {...props} ref={ref}> <Box direction="Column" grow="Yes" gap="500" {...props} ref={ref}>
<Box> <Box>
@ -67,7 +71,7 @@ export const RoomIntro = as<'div', RoomIntroProps>(({ room, ...props }, ref) =>
<Text size="T200" priority="300"> <Text size="T200" priority="300">
{'Created by '} {'Created by '}
<b>@{creatorName}</b> <b>@{creatorName}</b>
{` on ${timeDayMonthYear(ts)} ${timeHourMinute(ts)}`} {` on ${timeDayMonthYear(ts)} ${timeHourMinute(ts, hour24Clock)}`}
</Text> </Text>
)} )}
</Box> </Box>

View file

@ -57,6 +57,8 @@ export function MessageSearch({
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 searchInputRef = useRef<HTMLInputElement>(null); const searchInputRef = useRef<HTMLInputElement>(null);
const scrollTopAnchorRef = useRef<HTMLDivElement>(null); const scrollTopAnchorRef = useRef<HTMLDivElement>(null);
const [searchParams, setSearchParams] = useSearchParams(); const [searchParams, setSearchParams] = useSearchParams();
@ -289,6 +291,7 @@ export function MessageSearch({
urlPreview={urlPreview} urlPreview={urlPreview}
onOpen={navigateRoom} onOpen={navigateRoom}
legacyUsernameColor={legacyUsernameColor || mDirects.has(groupRoom.roomId)} legacyUsernameColor={legacyUsernameColor || mDirects.has(groupRoom.roomId)}
hour24Clock={hour24Clock}
/> />
</VirtualTile> </VirtualTile>
); );

View file

@ -57,6 +57,7 @@ type SearchResultGroupProps = {
urlPreview?: boolean; urlPreview?: boolean;
onOpen: (roomId: string, eventId: string) => void; onOpen: (roomId: string, eventId: string) => void;
legacyUsernameColor?: boolean; legacyUsernameColor?: boolean;
hour24Clock: boolean;
}; };
export function SearchResultGroup({ export function SearchResultGroup({
room, room,
@ -66,6 +67,7 @@ export function SearchResultGroup({
urlPreview, urlPreview,
onOpen, onOpen,
legacyUsernameColor, legacyUsernameColor,
hour24Clock,
}: SearchResultGroupProps) { }: SearchResultGroupProps) {
const mx = useMatrixClient(); const mx = useMatrixClient();
const useAuthentication = useMediaAuthentication(); const useAuthentication = useMediaAuthentication();
@ -275,7 +277,7 @@ 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} /> <Time ts={event.origin_server_ts} hour24Clock={hour24Clock} />
</Box> </Box>
<Box shrink="No" gap="200" alignItems="Center"> <Box shrink="No" gap="200" alignItems="Center">
<Chip <Chip

View file

@ -448,6 +448,7 @@ export function RoomTimeline({
const [encUrlPreview] = useSetting(settingsAtom, 'encUrlPreview'); const [encUrlPreview] = useSetting(settingsAtom, 'encUrlPreview');
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 ignoredUsersList = useIgnoredUsers(); const ignoredUsersList = useIgnoredUsers();
const ignoredUsersSet = useMemo(() => new Set(ignoredUsersList), [ignoredUsersList]); const ignoredUsersSet = useMemo(() => new Set(ignoredUsersList), [ignoredUsersList]);
@ -1068,6 +1069,7 @@ export function RoomTimeline({
powerLevelTag={getPowerLevelTag(senderPowerLevel)} powerLevelTag={getPowerLevelTag(senderPowerLevel)}
accessibleTagColors={accessibleTagColors} accessibleTagColors={accessibleTagColors}
legacyUsernameColor={legacyUsernameColor || direct} legacyUsernameColor={legacyUsernameColor || direct}
hour24Clock={hour24Clock}
> >
{mEvent.isRedacted() ? ( {mEvent.isRedacted() ? (
<RedactedContent reason={mEvent.getUnsigned().redacted_because?.content.reason} /> <RedactedContent reason={mEvent.getUnsigned().redacted_because?.content.reason} />
@ -1149,6 +1151,7 @@ export function RoomTimeline({
powerLevelTag={getPowerLevelTag(senderPowerLevel)} powerLevelTag={getPowerLevelTag(senderPowerLevel)}
accessibleTagColors={accessibleTagColors} accessibleTagColors={accessibleTagColors}
legacyUsernameColor={legacyUsernameColor || direct} legacyUsernameColor={legacyUsernameColor || direct}
hour24Clock={hour24Clock}
> >
<EncryptedContent mEvent={mEvent}> <EncryptedContent mEvent={mEvent}>
{() => { {() => {
@ -1250,6 +1253,7 @@ export function RoomTimeline({
powerLevelTag={getPowerLevelTag(senderPowerLevel)} powerLevelTag={getPowerLevelTag(senderPowerLevel)}
accessibleTagColors={accessibleTagColors} accessibleTagColors={accessibleTagColors}
legacyUsernameColor={legacyUsernameColor || direct} legacyUsernameColor={legacyUsernameColor || direct}
hour24Clock={hour24Clock}
> >
{mEvent.isRedacted() ? ( {mEvent.isRedacted() ? (
<RedactedContent reason={mEvent.getUnsigned().redacted_because?.content.reason} /> <RedactedContent reason={mEvent.getUnsigned().redacted_because?.content.reason} />
@ -1278,7 +1282,11 @@ export function RoomTimeline({
const parsed = parseMemberEvent(mEvent); const parsed = parseMemberEvent(mEvent);
const timeJSX = ( const timeJSX = (
<Time ts={mEvent.getTs()} compact={messageLayout === MessageLayout.Compact} /> <Time
ts={mEvent.getTs()}
compact={messageLayout === MessageLayout.Compact}
hour24Clock={hour24Clock}
/>
); );
return ( return (
@ -1314,7 +1322,11 @@ export function RoomTimeline({
const senderName = getMemberDisplayName(room, senderId) || getMxIdLocalPart(senderId); const senderName = getMemberDisplayName(room, senderId) || getMxIdLocalPart(senderId);
const timeJSX = ( const timeJSX = (
<Time ts={mEvent.getTs()} compact={messageLayout === MessageLayout.Compact} /> <Time
ts={mEvent.getTs()}
compact={messageLayout === MessageLayout.Compact}
hour24Clock={hour24Clock}
/>
); );
return ( return (
@ -1351,7 +1363,11 @@ export function RoomTimeline({
const senderName = getMemberDisplayName(room, senderId) || getMxIdLocalPart(senderId); const senderName = getMemberDisplayName(room, senderId) || getMxIdLocalPart(senderId);
const timeJSX = ( const timeJSX = (
<Time ts={mEvent.getTs()} compact={messageLayout === MessageLayout.Compact} /> <Time
ts={mEvent.getTs()}
compact={messageLayout === MessageLayout.Compact}
hour24Clock={hour24Clock}
/>
); );
return ( return (
@ -1388,7 +1404,11 @@ export function RoomTimeline({
const senderName = getMemberDisplayName(room, senderId) || getMxIdLocalPart(senderId); const senderName = getMemberDisplayName(room, senderId) || getMxIdLocalPart(senderId);
const timeJSX = ( const timeJSX = (
<Time ts={mEvent.getTs()} compact={messageLayout === MessageLayout.Compact} /> <Time
ts={mEvent.getTs()}
compact={messageLayout === MessageLayout.Compact}
hour24Clock={hour24Clock}
/>
); );
return ( return (
@ -1427,7 +1447,11 @@ export function RoomTimeline({
const senderName = getMemberDisplayName(room, senderId) || getMxIdLocalPart(senderId); const senderName = getMemberDisplayName(room, senderId) || getMxIdLocalPart(senderId);
const timeJSX = ( const timeJSX = (
<Time ts={mEvent.getTs()} compact={messageLayout === MessageLayout.Compact} /> <Time
ts={mEvent.getTs()}
compact={messageLayout === MessageLayout.Compact}
hour24Clock={hour24Clock}
/>
); );
return ( return (
@ -1471,7 +1495,11 @@ export function RoomTimeline({
const senderName = getMemberDisplayName(room, senderId) || getMxIdLocalPart(senderId); const senderName = getMemberDisplayName(room, senderId) || getMxIdLocalPart(senderId);
const timeJSX = ( const timeJSX = (
<Time ts={mEvent.getTs()} compact={messageLayout === MessageLayout.Compact} /> <Time
ts={mEvent.getTs()}
compact={messageLayout === MessageLayout.Compact}
hour24Clock={hour24Clock}
/>
); );
return ( return (

View file

@ -678,6 +678,7 @@ export type MessageProps = {
powerLevelTag?: PowerLevelTag; powerLevelTag?: PowerLevelTag;
accessibleTagColors?: Map<string, string>; accessibleTagColors?: Map<string, string>;
legacyUsernameColor?: boolean; legacyUsernameColor?: boolean;
hour24Clock: boolean;
}; };
export const Message = as<'div', MessageProps>( export const Message = as<'div', MessageProps>(
( (
@ -706,6 +707,7 @@ export const Message = as<'div', MessageProps>(
powerLevelTag, powerLevelTag,
accessibleTagColors, accessibleTagColors,
legacyUsernameColor, legacyUsernameColor,
hour24Clock,
children, children,
...props ...props
}, },
@ -770,7 +772,11 @@ export const Message = as<'div', MessageProps>(
</Text> </Text>
</> </>
)} )}
<Time ts={mEvent.getTs()} compact={messageLayout === MessageLayout.Compact} /> <Time
ts={mEvent.getTs()}
compact={messageLayout === MessageLayout.Compact}
hour24Clock={hour24Clock}
/>
</Box> </Box>
</Box> </Box>
); );

View file

@ -102,6 +102,8 @@ function PinnedMessage({ room, eventId, renderContent, onOpen, canPinEvent }: Pi
const theme = useTheme(); const theme = useTheme();
const accessibleTagColors = useAccessibleTagColors(theme.kind, powerLevelTags); const accessibleTagColors = useAccessibleTagColors(theme.kind, powerLevelTags);
const [hour24Clock] = useSetting(settingsAtom, 'hour24Clock');
const [unpinState, unpin] = useAsyncCallback( const [unpinState, unpin] = useAsyncCallback(
useCallback(() => { useCallback(() => {
const pinEvent = getStateEvent(room, StateEvent.RoomPinnedEvents); const pinEvent = getStateEvent(room, StateEvent.RoomPinnedEvents);
@ -205,7 +207,7 @@ 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()} /> <Time ts={pinnedEvent.getTs()} hour24Clock={hour24Clock} />
</Box> </Box>
{renderOptions()} {renderOptions()}
</Box> </Box>

View file

@ -27,6 +27,8 @@ import { SequenceCard } from '../../../components/sequence-card';
import { SequenceCardStyle } from '../styles.css'; import { SequenceCardStyle } from '../styles.css';
import { LogoutDialog } from '../../../components/LogoutDialog'; import { LogoutDialog } from '../../../components/LogoutDialog';
import { stopPropagation } from '../../../utils/keyboard'; import { stopPropagation } from '../../../utils/keyboard';
import { useSetting } from '../../../state/hooks/settings';
import { settingsAtom } from '../../../state/settings';
export function DeviceTilePlaceholder() { export function DeviceTilePlaceholder() {
return ( return (
@ -41,6 +43,8 @@ export function DeviceTilePlaceholder() {
} }
function DeviceActiveTime({ ts }: { ts: number }) { function DeviceActiveTime({ ts }: { ts: number }) {
const [hour24Clock] = useSetting(settingsAtom, 'hour24Clock');
return ( return (
<Text className={BreakWord} size="T200"> <Text className={BreakWord} size="T200">
<Text size="Inherit" as="span" priority="300"> <Text size="Inherit" as="span" priority="300">
@ -49,7 +53,7 @@ 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)} {!today(ts) && !yesterday(ts) && timeDayMonYear(ts)} {timeHourMinute(ts, hour24Clock)}
</> </>
</Text> </Text>
); );

View file

@ -530,6 +530,7 @@ function Messages() {
const [urlPreview, setUrlPreview] = useSetting(settingsAtom, 'urlPreview'); const [urlPreview, setUrlPreview] = useSetting(settingsAtom, 'urlPreview');
const [encUrlPreview, setEncUrlPreview] = useSetting(settingsAtom, 'encUrlPreview'); const [encUrlPreview, setEncUrlPreview] = useSetting(settingsAtom, 'encUrlPreview');
const [showHiddenEvents, setShowHiddenEvents] = useSetting(settingsAtom, 'showHiddenEvents'); const [showHiddenEvents, setShowHiddenEvents] = useSetting(settingsAtom, 'showHiddenEvents');
const [hour24Clock, setHour24Clock] = useSetting(settingsAtom, 'hour24Clock');
return ( return (
<Box direction="Column" gap="100"> <Box direction="Column" gap="100">
@ -608,6 +609,12 @@ function Messages() {
} }
/> />
</SequenceCard> </SequenceCard>
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
<SettingTile
title="24-Hour Time Format"
after={<Switch variant="Primary" value={hour24Clock} onChange={setHour24Clock} />}
/>
</SequenceCard>
</Box> </Box>
); );
} }

View file

@ -65,6 +65,8 @@ import { testBadWords } from '../../../plugins/bad-words';
import { allRoomsAtom } from '../../../state/room-list/roomList'; import { allRoomsAtom } from '../../../state/room-list/roomList';
import { useIgnoredUsers } from '../../../hooks/useIgnoredUsers'; import { useIgnoredUsers } from '../../../hooks/useIgnoredUsers';
import { useReportRoomSupported } from '../../../hooks/useReportRoomSupported'; import { useReportRoomSupported } from '../../../hooks/useReportRoomSupported';
import { useSetting } from '../../../state/hooks/settings';
import { settingsAtom } from '../../../state/settings';
const COMPACT_CARD_WIDTH = 548; const COMPACT_CARD_WIDTH = 548;
@ -135,10 +137,11 @@ type NavigateHandler = (roomId: string, space: boolean) => void;
type InviteCardProps = { type InviteCardProps = {
invite: InviteData; invite: InviteData;
compact?: boolean; compact?: boolean;
hour24Clock: boolean;
onNavigate: NavigateHandler; onNavigate: NavigateHandler;
hideAvatar: boolean; hideAvatar: boolean;
}; };
function InviteCard({ invite, compact, onNavigate, hideAvatar }: InviteCardProps) { function InviteCard({ invite, compact, hour24Clock, onNavigate, hideAvatar }: InviteCardProps) {
const mx = useMatrixClient(); const mx = useMatrixClient();
const userId = mx.getSafeUserId(); const userId = mx.getSafeUserId();
@ -295,7 +298,7 @@ function InviteCard({ invite, compact, onNavigate, hideAvatar }: InviteCardProps
</Box> </Box>
{invite.inviteTs && ( {invite.inviteTs && (
<Box shrink="No"> <Box shrink="No">
<Time size="T200" ts={invite.inviteTs} priority="300" /> <Time size="T200" ts={invite.inviteTs} hour24Clock={hour24Clock} priority="300" />
</Box> </Box>
)} )}
</Box> </Box>
@ -384,8 +387,9 @@ type KnownInvitesProps = {
invites: InviteData[]; invites: InviteData[];
handleNavigate: NavigateHandler; handleNavigate: NavigateHandler;
compact: boolean; compact: boolean;
hour24Clock: boolean;
}; };
function KnownInvites({ invites, handleNavigate, compact }: KnownInvitesProps) { function KnownInvites({ invites, handleNavigate, compact, hour24Clock }: KnownInvitesProps) {
return ( return (
<Box direction="Column" gap="200"> <Box direction="Column" gap="200">
<Text size="H4">Primary</Text> <Text size="H4">Primary</Text>
@ -396,6 +400,7 @@ function KnownInvites({ invites, handleNavigate, compact }: KnownInvitesProps) {
key={invite.roomId} key={invite.roomId}
invite={invite} invite={invite}
compact={compact} compact={compact}
hour24Clock={hour24Clock}
onNavigate={handleNavigate} onNavigate={handleNavigate}
hideAvatar={false} hideAvatar={false}
/> />
@ -420,8 +425,9 @@ type UnknownInvitesProps = {
invites: InviteData[]; invites: InviteData[];
handleNavigate: NavigateHandler; handleNavigate: NavigateHandler;
compact: boolean; compact: boolean;
hour24Clock: boolean;
}; };
function UnknownInvites({ invites, handleNavigate, compact }: UnknownInvitesProps) { function UnknownInvites({ invites, handleNavigate, compact, hour24Clock }: UnknownInvitesProps) {
const mx = useMatrixClient(); const mx = useMatrixClient();
const [declineAllStatus, declineAll] = useAsyncCallback( const [declineAllStatus, declineAll] = useAsyncCallback(
@ -459,6 +465,7 @@ function UnknownInvites({ invites, handleNavigate, compact }: UnknownInvitesProp
key={invite.roomId} key={invite.roomId}
invite={invite} invite={invite}
compact={compact} compact={compact}
hour24Clock={hour24Clock}
onNavigate={handleNavigate} onNavigate={handleNavigate}
hideAvatar hideAvatar
/> />
@ -483,8 +490,9 @@ type SpamInvitesProps = {
invites: InviteData[]; invites: InviteData[];
handleNavigate: NavigateHandler; handleNavigate: NavigateHandler;
compact: boolean; compact: boolean;
hour24Clock: boolean;
}; };
function SpamInvites({ invites, handleNavigate, compact }: SpamInvitesProps) { function SpamInvites({ invites, handleNavigate, compact, hour24Clock }: SpamInvitesProps) {
const mx = useMatrixClient(); const mx = useMatrixClient();
const [showInvites, setShowInvites] = useState(false); const [showInvites, setShowInvites] = useState(false);
@ -608,6 +616,7 @@ function SpamInvites({ invites, handleNavigate, compact }: SpamInvitesProps) {
key={invite.roomId} key={invite.roomId}
invite={invite} invite={invite}
compact={compact} compact={compact}
hour24Clock={hour24Clock}
onNavigate={handleNavigate} onNavigate={handleNavigate}
hideAvatar hideAvatar
/> />
@ -671,6 +680,8 @@ export function Invites() {
); );
const screenSize = useScreenSizeContext(); const screenSize = useScreenSizeContext();
const [hour24Clock] = useSetting(settingsAtom, 'hour24Clock');
const handleNavigate = (roomId: string, space: boolean) => { const handleNavigate = (roomId: string, space: boolean) => {
if (space) { if (space) {
navigateSpace(roomId); navigateSpace(roomId);
@ -723,6 +734,7 @@ export function Invites() {
<KnownInvites <KnownInvites
invites={knownInvites} invites={knownInvites}
compact={compact} compact={compact}
hour24Clock={hour24Clock}
handleNavigate={handleNavigate} handleNavigate={handleNavigate}
/> />
)} )}
@ -731,6 +743,7 @@ export function Invites() {
<UnknownInvites <UnknownInvites
invites={unknownInvites} invites={unknownInvites}
compact={compact} compact={compact}
hour24Clock={hour24Clock}
handleNavigate={handleNavigate} handleNavigate={handleNavigate}
/> />
)} )}
@ -739,6 +752,7 @@ export function Invites() {
<SpamInvites <SpamInvites
invites={spamInvites} invites={spamInvites}
compact={compact} compact={compact}
hour24Clock={hour24Clock}
handleNavigate={handleNavigate} handleNavigate={handleNavigate}
/> />
)} )}

View file

@ -205,6 +205,7 @@ type RoomNotificationsGroupProps = {
hideActivity: boolean; hideActivity: boolean;
onOpen: (roomId: string, eventId: string) => void; onOpen: (roomId: string, eventId: string) => void;
legacyUsernameColor?: boolean; legacyUsernameColor?: boolean;
hour24Clock: boolean;
}; };
function RoomNotificationsGroupComp({ function RoomNotificationsGroupComp({
room, room,
@ -214,6 +215,7 @@ function RoomNotificationsGroupComp({
hideActivity, hideActivity,
onOpen, onOpen,
legacyUsernameColor, legacyUsernameColor,
hour24Clock,
}: RoomNotificationsGroupProps) { }: RoomNotificationsGroupProps) {
const mx = useMatrixClient(); const mx = useMatrixClient();
const useAuthentication = useMediaAuthentication(); const useAuthentication = useMediaAuthentication();
@ -496,7 +498,7 @@ function RoomNotificationsGroupComp({
</Username> </Username>
{tagIconSrc && <PowerIcon size="100" iconSrc={tagIconSrc} />} {tagIconSrc && <PowerIcon size="100" iconSrc={tagIconSrc} />}
</Box> </Box>
<Time ts={event.origin_server_ts} /> <Time ts={event.origin_server_ts} hour24Clock={hour24Clock} />
</Box> </Box>
<Box shrink="No" gap="200" alignItems="Center"> <Box shrink="No" gap="200" alignItems="Center">
<Chip <Chip
@ -549,6 +551,7 @@ export function Notifications() {
const [mediaAutoLoad] = useSetting(settingsAtom, 'mediaAutoLoad'); const [mediaAutoLoad] = useSetting(settingsAtom, 'mediaAutoLoad');
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 screenSize = useScreenSizeContext(); const screenSize = useScreenSizeContext();
const mDirects = useAtomValue(mDirectAtom); const mDirects = useAtomValue(mDirectAtom);
@ -713,6 +716,7 @@ export function Notifications() {
legacyUsernameColor={ legacyUsernameColor={
legacyUsernameColor || mDirects.has(groupRoom.roomId) legacyUsernameColor || mDirects.has(groupRoom.roomId)
} }
hour24Clock={hour24Clock}
/> />
</VirtualTile> </VirtualTile>
); );

View file

@ -35,6 +35,8 @@ export interface Settings {
showNotifications: boolean; showNotifications: boolean;
isNotificationSounds: boolean; isNotificationSounds: boolean;
hour24Clock: boolean;
developerTools: boolean; developerTools: boolean;
} }
@ -65,6 +67,8 @@ const defaultSettings: Settings = {
showNotifications: true, showNotifications: true,
isNotificationSounds: true, isNotificationSounds: true,
hour24Clock: false,
developerTools: false, developerTools: false,
}; };

View file

@ -9,7 +9,8 @@ export const today = (ts: number): boolean => dayjs(ts).isToday();
export const yesterday = (ts: number): boolean => dayjs(ts).isYesterday(); export const yesterday = (ts: number): boolean => dayjs(ts).isYesterday();
export const timeHourMinute = (ts: number): string => dayjs(ts).format('hh:mm A'); export const timeHourMinute = (ts: number, hour24Clock: boolean): string =>
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): string => dayjs(ts).format('D MMM YYYY');