Merge branch 'relative-timestamp-tsx' into 'develop'

RelativeTimestamp: convert to TSX

See merge request soapbox-pub/soapbox-fe!1762
environments/review-develop-3zknud/deployments/884
Alex Gleason 2022-09-01 17:03:46 +00:00
commit 1876af9be7
11 zmienionych plików z 53 dodań i 40 usunięć

Wyświetl plik

@ -8,7 +8,7 @@ import { useAppSelector, useOnScreen } from 'soapbox/hooks';
import { getAcct } from 'soapbox/utils/accounts';
import { displayFqn } from 'soapbox/utils/state';
import RelativeTimestamp from './relative_timestamp';
import RelativeTimestamp from './relative-timestamp';
import { Avatar, Emoji, HStack, Icon, IconButton, Stack, Text } from './ui';
import type { Account as AccountEntity } from 'soapbox/types/entities';
@ -54,7 +54,7 @@ interface IAccount {
id?: string,
onActionClick?: (account: any) => void,
showProfileHoverCard?: boolean,
timestamp?: string | Date,
timestamp?: string,
timestampUrl?: string,
futureTimestamp?: boolean,
withAccountNote?: boolean,

Wyświetl plik

@ -6,7 +6,7 @@ import { useSoapboxConfig } from 'soapbox/hooks';
import { getAcct } from '../utils/accounts';
import Icon from './icon';
import RelativeTimestamp from './relative_timestamp';
import RelativeTimestamp from './relative-timestamp';
import VerificationBadge from './verification_badge';
import type { Account } from 'soapbox/types/entities';

Wyświetl plik

@ -4,7 +4,7 @@ import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import { fetchPoll, vote } from 'soapbox/actions/polls';
import { useAppDispatch } from 'soapbox/hooks';
import RelativeTimestamp from '../relative_timestamp';
import RelativeTimestamp from '../relative-timestamp';
import { Button, HStack, Stack, Text, Tooltip } from '../ui';
import type { Selected } from './poll';

Wyświetl plik

@ -1,8 +1,7 @@
import PropTypes from 'prop-types';
import React from 'react';
import { injectIntl, defineMessages } from 'react-intl';
import { injectIntl, defineMessages, IntlShape, FormatDateOptions } from 'react-intl';
import { Text } from './ui';
import Text, { IText } from './ui/text/text';
const messages = defineMessages({
just_now: { id: 'relative_time.just_now', defaultMessage: 'now' },
@ -17,7 +16,7 @@ const messages = defineMessages({
days_remaining: { id: 'time_remaining.days', defaultMessage: '{number, plural, one {# day} other {# days}} left' },
});
const dateFormatOptions = {
const dateFormatOptions: FormatDateOptions = {
hour12: false,
year: 'numeric',
month: 'short',
@ -26,7 +25,7 @@ const dateFormatOptions = {
minute: '2-digit',
};
const shortDateFormatOptions = {
const shortDateFormatOptions: FormatDateOptions = {
month: 'short',
day: 'numeric',
};
@ -38,7 +37,7 @@ const DAY = 1000 * 60 * 60 * 24;
const MAX_DELAY = 2147483647;
const selectUnits = delta => {
const selectUnits = (delta: number) => {
const absDelta = Math.abs(delta);
if (absDelta < MINUTE) {
@ -52,7 +51,7 @@ const selectUnits = delta => {
return 'day';
};
const getUnitDelay = units => {
const getUnitDelay = (units: string) => {
switch (units) {
case 'second':
return SECOND;
@ -67,7 +66,7 @@ const getUnitDelay = units => {
}
};
export const timeAgoString = (intl, date, now, year) => {
export const timeAgoString = (intl: IntlShape, date: Date, now: number, year: number) => {
const delta = now - date.getTime();
let relativeTime;
@ -93,7 +92,7 @@ export const timeAgoString = (intl, date, now, year) => {
return relativeTime;
};
const timeRemainingString = (intl, date, now) => {
const timeRemainingString = (intl: IntlShape, date: Date, now: number) => {
const delta = date.getTime() - now;
let relativeTime;
@ -113,16 +112,21 @@ const timeRemainingString = (intl, date, now) => {
return relativeTime;
};
export default @injectIntl
class RelativeTimestamp extends React.Component {
interface RelativeTimestampProps extends IText {
intl: IntlShape,
timestamp: string,
year?: number,
futureDate?: boolean,
}
static propTypes = {
intl: PropTypes.object.isRequired,
timestamp: PropTypes.string.isRequired,
year: PropTypes.number.isRequired,
theme: PropTypes.string,
futureDate: PropTypes.bool,
};
interface RelativeTimestampState {
now: number,
}
/** Displays a timestamp compared to the current time, eg "1m" for one minute ago. */
class RelativeTimestamp extends React.Component<RelativeTimestampProps, RelativeTimestampState> {
_timer: NodeJS.Timeout | undefined;
state = {
now: Date.now(),
@ -130,10 +134,10 @@ class RelativeTimestamp extends React.Component {
static defaultProps = {
year: (new Date()).getFullYear(),
theme: 'inherit',
theme: 'inherit' as const,
};
shouldComponentUpdate(nextProps, nextState) {
shouldComponentUpdate(nextProps: RelativeTimestampProps, nextState: RelativeTimestampState) {
// As of right now the locale doesn't change without a new page load,
// but we might as well check in case that ever changes.
return this.props.timestamp !== nextProps.timestamp ||
@ -141,14 +145,14 @@ class RelativeTimestamp extends React.Component {
this.state.now !== nextState.now;
}
UNSAFE_componentWillReceiveProps(prevProps) {
UNSAFE_componentWillReceiveProps(prevProps: RelativeTimestampProps) {
if (this.props.timestamp !== prevProps.timestamp) {
this.setState({ now: Date.now() });
}
}
componentDidMount() {
this._scheduleNextUpdate(this.props, this.state);
this._scheduleNextUpdate();
}
UNSAFE_componentWillUpdate() {
@ -156,11 +160,15 @@ class RelativeTimestamp extends React.Component {
}
componentWillUnmount() {
clearTimeout(this._timer);
if (this._timer) {
clearTimeout(this._timer);
}
}
_scheduleNextUpdate() {
clearTimeout(this._timer);
if (this._timer) {
clearTimeout(this._timer);
}
const { timestamp } = this.props;
const delta = (new Date(timestamp)).getTime() - this.state.now;
@ -177,8 +185,8 @@ class RelativeTimestamp extends React.Component {
render() {
const { timestamp, intl, year, futureDate, theme, ...textProps } = this.props;
const date = new Date(timestamp);
const relativeTime = futureDate ? timeRemainingString(intl, date, this.state.now) : timeAgoString(intl, date, this.state.now, year);
const date = new Date(timestamp);
const relativeTime = futureDate ? timeRemainingString(intl, date, this.state.now) : timeAgoString(intl, date, this.state.now, year!);
return (
<Text {...textProps} theme={theme} tag='time' title={intl.formatDate(date, dateFormatOptions)}>
@ -188,3 +196,5 @@ class RelativeTimestamp extends React.Component {
}
}
export default injectIntl(RelativeTimestamp);

Wyświetl plik

@ -84,7 +84,9 @@ interface IText extends Pick<React.HTMLAttributes<HTMLParagraphElement>, 'danger
/** Whether to truncate the text if its container is too small. */
truncate?: boolean,
/** Font weight of the text. */
weight?: Weights
weight?: Weights,
/** Tooltip title. */
title?: string,
}
/** UI-friendly text container with dark mode support. */
@ -133,4 +135,7 @@ const Text: React.FC<IText> = React.forwardRef(
},
);
export default Text;
export {
Text as default,
IText,
};

Wyświetl plik

@ -6,7 +6,7 @@ import { getSettings } from 'soapbox/actions/settings';
import Avatar from 'soapbox/components/avatar';
import DisplayName from 'soapbox/components/display-name';
import Permalink from 'soapbox/components/permalink';
import RelativeTimestamp from 'soapbox/components/relative_timestamp';
import RelativeTimestamp from 'soapbox/components/relative-timestamp';
import { Text } from 'soapbox/components/ui';
import ActionButton from 'soapbox/features/ui/components/action-button';
import { useAppSelector } from 'soapbox/hooks';

Wyświetl plik

@ -21,7 +21,6 @@ describe('normalizePoll()', () => {
expect(ImmutableRecord.isRecord(result)).toBe(true);
expect(ImmutableRecord.isRecord(result.options.get(0))).toBe(true);
expect(result.toJS()).toMatchObject(expected);
expect(result.expires_at instanceof Date).toBe(true);
});
it('normalizes a Pleroma logged-out poll', () => {

Wyświetl plik

@ -164,7 +164,6 @@ describe('normalizeStatus()', () => {
expect(ImmutableRecord.isRecord(poll)).toBe(true);
expect(ImmutableRecord.isRecord(poll.options.get(0))).toBe(true);
expect(poll.toJS()).toMatchObject(expected);
expect(poll.expires_at instanceof Date).toBe(true);
});
it('normalizes a Pleroma logged-out poll', () => {

Wyświetl plik

@ -26,7 +26,7 @@ export const AccountRecord = ImmutableRecord({
avatar_static: '',
birthday: '',
bot: false,
created_at: new Date(),
created_at: '',
discoverable: false,
display_name: '',
emojis: ImmutableList<Emoji>(),
@ -38,7 +38,7 @@ export const AccountRecord = ImmutableRecord({
header: '',
header_static: '',
id: '',
last_status_at: new Date(),
last_status_at: '',
location: '',
locked: false,
moved: null as EmbeddedEntity<any>,

Wyświetl plik

@ -21,7 +21,7 @@ import type { Emoji, PollOption } from 'soapbox/types/entities';
export const PollRecord = ImmutableRecord({
emojis: ImmutableList<Emoji>(),
expired: false,
expires_at: new Date(),
expires_at: '',
id: '',
multiple: false,
options: ImmutableList<PollOption>(),

Wyświetl plik

@ -28,8 +28,8 @@ export const StatusRecord = ImmutableRecord({
bookmarked: false,
card: null as Card | null,
content: '',
created_at: new Date(),
edited_at: null as Date | null,
created_at: '',
edited_at: null as string | null,
emojis: ImmutableList<Emoji>(),
favourited: false,
favourites_count: 0,