Skip to content

Commit

Permalink
Merge branch 'feat/datetime' into evergreen
Browse files Browse the repository at this point in the history
  • Loading branch information
greentore committed Apr 18, 2023
2 parents 0807296 + 2a6b02b commit b409495
Show file tree
Hide file tree
Showing 12 changed files with 143 additions and 76 deletions.
9 changes: 0 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
"@tippyjs/react": "4.2.6",
"blurhash": "2.0.4",
"browser-encrypt-attachment": "0.3.0",
"dateformat": "5.0.3",
"emojibase-data": "7.0.1",
"file-saver": "2.0.5",
"flux": "4.0.3",
Expand Down
44 changes: 0 additions & 44 deletions src/app/atoms/time/Time.jsx

This file was deleted.

36 changes: 36 additions & 0 deletions src/app/atoms/time/Time.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React from 'react';

import { isInSameDay, DateTime } from '../../../util/time';

interface TimeProps {
timestamp: number;
fullTime?: boolean;
}

function Time({ timestamp, fullTime }: TimeProps) {
const date = new Date(timestamp);

const formattedFullTime = DateTime.full(date);
let formattedDate = formattedFullTime;

if (!fullTime) {
const compareDate = new Date();
const isToday = isInSameDay(date, compareDate);
compareDate.setDate(compareDate.getDate() - 1);
const isYesterday = isInSameDay(date, compareDate);

formattedDate = isToday || isYesterday ? DateTime.time(date) : DateTime.dateISO(date);
if (isYesterday) {
const yesterday = DateTime.relative(-1, 'day') ?? 'Yesterday';
formattedDate = `${yesterday}, ${formattedDate}`;
}
}

return (
<time dateTime={date.toISOString()} title={formattedFullTime}>
{formattedDate}
</time>
);
}

export default Time;
8 changes: 4 additions & 4 deletions src/app/organisms/room/RoomViewContent.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ import React, {
import PropTypes from 'prop-types';
import './RoomViewContent.scss';

import dateFormat from 'dateformat';
import { twemojify } from '../../../util/twemojify';

import initMatrix from '../../../client/initMatrix';
import cons from '../../../client/state/cons';
import navigation from '../../../client/state/navigation';
import { openProfileViewer } from '../../../client/action/navigation';
import { diffMinutes, isInSameDay, Throttle } from '../../../util/common';
import { Throttle } from '../../../util/common';
import { diffMinutes, isInSameDay, DateTime } from '../../../util/time'
import { markAsRead } from '../../../client/action/notifications';

import Divider from '../../atoms/divider/Divider';
Expand Down Expand Up @@ -98,7 +98,7 @@ function RoomIntroContainer({ event, timeline }) {
name={room.name}
heading={twemojify(heading)}
desc={desc}
time={event ? `Created at ${dateFormat(event.getDate(), 'dd mmmm yyyy, hh:MM TT')}` : null}
time={event ? `Created on ${DateTime.full(event.getDate())}` : null}
/>
);
}
Expand Down Expand Up @@ -576,7 +576,7 @@ function RoomViewContent({ eventId, roomTimeline }) {
}
const dayDivider = prevMEvent && !isInSameDay(mEvent.getDate(), prevMEvent.getDate());
if (dayDivider) {
tl.push(<Divider key={`divider-${mEvent.getId()}`} text={`${dateFormat(mEvent.getDate(), 'mmmm dd, yyyy')}`} />);
tl.push(<Divider key={`divider-${mEvent.getId()}`} text={`${DateTime.date(mEvent.getDate())}`} />);
itemCountIndex += 1;
}

Expand Down
6 changes: 3 additions & 3 deletions src/app/organisms/settings/DeviceManage.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React, { useState, useEffect } from 'react';
import './DeviceManage.scss';
import dateFormat from 'dateformat';

import initMatrix from '../../../client/initMatrix';
import { isCrossVerified } from '../../../util/matrixUtil';
import { DateTime } from '../../../util/time';
import { openReusableDialog, openEmojiVerification } from '../../../client/action/navigation';

import Text from '../../atoms/text/Text';
Expand Down Expand Up @@ -184,9 +184,9 @@ function DeviceManage() {
<Text variant="b3">
Last activity
<span style={{ color: 'var(--tc-surface-normal)' }}>
{dateFormat(new Date(lastTS), ' hh:MM TT, dd/mm/yyyy')}
{` ${DateTime.full(new Date(lastTS))}`}
</span>
{lastIP ? ` at ${lastIP}` : ''}
{lastIP ? ` from ${lastIP}` : ''}
</Text>
)}
{isCurrentDevice && (
Expand Down
12 changes: 11 additions & 1 deletion src/app/organisms/settings/Settings.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import navigation from '../../../client/state/navigation';
import {
toggleSystemTheme, toggleMarkdown, toggleGreentext,
toggleMembershipEvents, toggleNickAvatarEvents, toggleNotifications,
toggleNotificationSounds, toggleTypingNotifications, toggleReadReceipts,
toggleNotificationSounds, toggleTypingNotifications, toggleReadReceipts, toggleTime12,
} from '../../../client/action/settings';
import { usePermission } from '../../hooks/usePermission';

Expand Down Expand Up @@ -138,6 +138,16 @@ function AppearanceSection() {
)}
content={<Text variant="b3">Hide nick and avatar change messages from room timeline.</Text>}
/>
<SettingTile
title="12 hour time"
options={(
<Toggle
isActive={settings.isTime12}
onToggle={() => { toggleTime12(); updateState({}); }}
/>
)}
content={<Text variant="b3">Show timestamps in 12 hour format.</Text>}
/>
</div>
</div>
);
Expand Down
6 changes: 6 additions & 0 deletions src/client/action/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,9 @@ export function toggleReadReceipts() {
type: cons.actions.settings.TOGGLE_READ_RECEIPTS,
});
}

export function toggleTime12() {
appDispatcher.dispatch({
type: cons.actions.settings.TOGGLE_TIME12,
});
}
2 changes: 2 additions & 0 deletions src/client/state/cons.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ const cons = {
TOGGLE_NOTIFICATION_SOUNDS: 'TOGGLE_NOTIFICATION_SOUNDS',
TOGGLE_TYPING_NOTIFICATIONS: 'TOGGLE_TYPING_NOTIFICATIONS',
TOGGLE_READ_RECEIPTS: 'TOGGLE_READ_RECEIPTS',
TOGGLE_TIME12: 'TOGGLE_TIME12',
},
},
events: {
Expand Down Expand Up @@ -160,6 +161,7 @@ const cons = {
NOTIFICATION_SOUNDS_TOGGLED: 'NOTIFICATION_SOUNDS_TOGGLED',
TYPING_NOTIFICATIONS_TOGGLED: 'TYPING_NOTIFICATIONS_TOGGLED',
READ_RECEIPTS_TOGGLED: 'READ_RECEIPTS_TOGGLED',
TIME12_TOGGLED: 'TIME12_TOGGLED',
},
},
};
Expand Down
14 changes: 14 additions & 0 deletions src/client/state/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,15 @@ class Settings extends EventEmitter {
return settings.sendReadReceipts;
}

getIsTime12() {
if (typeof this.isTime12 === 'boolean') return this.isTime12;

const settings = getSettings();
if (settings === null) return false;
if (typeof settings.isTime12 === 'undefined') return true;
return settings.isTime12;
}

setter(action) {
const actions = {
[cons.actions.settings.TOGGLE_SYSTEM_THEME]: () => {
Expand Down Expand Up @@ -231,6 +240,11 @@ class Settings extends EventEmitter {
setSettings('sendReadReceipts', this.sendReadReceipts);
this.emit(cons.events.settings.READ_RECEIPTS_TOGGLED, this.sendReadReceipts);
},
[cons.actions.settings.TOGGLE_TIME12]: () => {
this.isTime12 = !this.isTime12;
setSettings('isTime12', this.isTime12);
this.emit(cons.events.settings.TIME12_TOGGLED, this.isTime12);
},
};

actions[action.type]?.();
Expand Down
14 changes: 0 additions & 14 deletions src/util/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,6 @@ export function bytesToSize(bytes) {
return `${(bytes / (1024 ** i)).toFixed(1)} ${sizes[i]}`;
}

export function diffMinutes(dt2, dt1) {
let diff = (dt2.getTime() - dt1.getTime()) / 1000;
diff /= 60;
return Math.abs(Math.round(diff));
}

export function isInSameDay(dt2, dt1) {
return (
dt2.getFullYear() === dt1.getFullYear()
&& dt2.getMonth() === dt1.getMonth()
&& dt2.getDate() === dt1.getDate()
);
}

/**
* @param {Event} ev
* @param {string} [targetSelector] element selector for Element.matches([selector])
Expand Down
67 changes: 67 additions & 0 deletions src/util/time.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import cons from '../client/state/cons';
import settings from '../client/state/settings';

function capitalize(string: string) {
return string.charAt(0).toLocaleUpperCase() + string.slice(1);
}

const hourCycle = () => (settings.isTime12 ? 'h12' : 'h23');

let fullFormat: Intl.DateTimeFormat;
let dateFormat: Intl.DateTimeFormat;
let timeFormat: Intl.DateTimeFormat;
let relativeFormat: Intl.RelativeTimeFormat | undefined;

function initDateFormats() {
fullFormat = new Intl.DateTimeFormat('en', {
hourCycle: hourCycle(),
dateStyle: 'full',
timeStyle: 'short',
});

dateFormat = new Intl.DateTimeFormat('en', {
dateStyle: 'long',
});

timeFormat = new Intl.DateTimeFormat('en', {
hourCycle: hourCycle(),
hour: 'numeric',
minute: 'numeric',
});

relativeFormat = Intl.RelativeTimeFormat
? new Intl.RelativeTimeFormat('en', { numeric: 'auto' })
: undefined;
}
initDateFormats();

export class DateTime {
static full = (date: Date) => fullFormat.format(date);

static date = (date: Date) => dateFormat.format(date);

static time = (date: Date) => timeFormat.format(date);

static relative = (value: number, unit: Intl.RelativeTimeFormatUnit) =>
relativeFormat ? capitalize(relativeFormat.format(value, unit)) : undefined;

static dateISO = (date: Date) => date.toISOString().split('T')[0];
}

export function diffMinutes(dt2: Date, dt1: Date): number {
let diff = (dt2.getTime() - dt1.getTime()) / 1000;
diff /= 60;
return Math.abs(Math.round(diff));
}

export function isInSameDay(dt2: Date, dt1: Date): boolean {
return (
dt2.getFullYear() === dt1.getFullYear() &&
dt2.getMonth() === dt1.getMonth() &&
dt2.getDate() === dt1.getDate()
);
}

settings.on(cons.events.settings.TIME12_TOGGLED, () => {
initDateFormats();
});

0 comments on commit b409495

Please sign in to comment.