Skip to content

Commit

Permalink
feature: Add string set for date format (#1221)
Browse files Browse the repository at this point in the history
[CLNP-5163](https://sendbird.atlassian.net/browse/CLNP-5163)
[SBISSUE-17143](https://sendbird.atlassian.net/browse/SBISSUE-17143)

#### ChangeLog
##### Features
- Added stringSet for date format and applied them
  | Key | Value |
  | --- | ----- |
  | DATE_FORMAT__MESSAGE_CREATED_AT | `'p'` |
  | DATE_FORMAT__UNREAD_SINCE | `'p MMM dd'` |
  | DATE_FORMAT__LAST_MESSAGE_CREATED_AT__TODAY | `'p'` |
  | DATE_FORMAT__LAST_MESSAGE_CREATED_AT__THIS_YEAR | `'MMM d'` |
  | DATE_FORMAT__LAST_MESSAGE_CREATED_AT__PREVIOUS_YEAR | `'yyyy/M/d'` |

[CLNP-5163]:
https://sendbird.atlassian.net/browse/CLNP-5163?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
[SBISSUE-17143]:
https://sendbird.atlassian.net/browse/SBISSUE-17143?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
  • Loading branch information
HoonBaek authored Sep 26, 2024
1 parent 95aeac7 commit 4922d04
Show file tree
Hide file tree
Showing 22 changed files with 114 additions and 45 deletions.
16 changes: 16 additions & 0 deletions src/modules/Channel/context/dux/__tests__/reducers.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ import * as actionTypes from '../actionTypes';
import reducers from '../reducers';
import initialState from '../initialState';
import { uuidv4 } from '../../../../../utils/uuid';
import { useLocalization } from '../../../../../lib/LocalizationContext';

jest.mock('../../../../../lib/LocalizationContext', () => ({
...jest.requireActual('../../../../../lib/LocalizationContext'),
useLocalization: jest.fn(),
}));

const getLastMessageOf = (messageList) => messageList[messageList.length - 1];

Expand All @@ -15,6 +21,16 @@ describe('Messages-Reducers', () => {
...initialState,
currentGroupChannel: { url: generateMockChannel().currentGroupChannel.url },
};

beforeEach(() => {
jest.clearAllMocks();
useLocalization.mockReturnValue({
stringSet: {
DATE_FORMAT__UNREAD_SINCE: 'p MMM dd',
},
});
});

it('should setloading true FETCH_INITIAL_MESSAGES_START', () => {
const nextState = reducers(initialState, {
type: actionTypes.FETCH_INITIAL_MESSAGES_START,
Expand Down
5 changes: 4 additions & 1 deletion src/modules/Channel/context/dux/reducers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
isSendableMessage,
} from '../../../../utils';
import { ChannelInitialStateType } from './initialState';
import { useLocalization } from '../../../../lib/LocalizationContext';

const getOldestMessageTimeStamp = (messages: CoreMessageType[] = []) => {
const oldestMessage = messages[0];
Expand All @@ -37,6 +38,8 @@ export default function channelReducer(
state: ChannelInitialStateType,
action: ChannelActionTypes,
): ChannelInitialStateType {
const { stringSet } = useLocalization();

return match(action)
.with({ type: channelActions.RESET_MESSAGES }, () => {
return {
Expand Down Expand Up @@ -268,7 +271,7 @@ export default function channelReducer(
return {
...state,
currentGroupChannel: channel,
unreadSince: state.unreadSince ?? format(new Date(), 'p MMM dd'),
unreadSince: state.unreadSince ?? format(new Date(), stringSet.DATE_FORMAT__UNREAD_SINCE),
unreadSinceDate: state.unreadSinceDate ?? new Date(),
allMessages: passUnsuccessfullMessages(state.allMessages, message),
};
Expand Down
6 changes: 5 additions & 1 deletion src/modules/Channel/context/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import format from 'date-fns/format';

import { CoreMessageType, SendableMessageType } from '../../../utils';
import { BaseMessage, SendingStatus } from '@sendbird/chat/message';
import { useLocalization } from '../../../lib/LocalizationContext';

export const scrollToRenderedMessage = (
scrollRef: React.RefObject<HTMLElement>,
Expand Down Expand Up @@ -115,7 +116,10 @@ export const mergeAndSortMessages = (oldMessages: BaseMessage[], newMessages: Ba
return sortByCreatedAt(unique);
};

export const getMessageCreatedAt = (message: BaseMessage) => format(message.createdAt, 'p');
export const getMessageCreatedAt = (message: BaseMessage) => {
const { stringSet } = useLocalization();
return format(message.createdAt, stringSet.DATE_FORMAT__MESSAGE_CREATED_AT);
};

export const passUnsuccessfullMessages = (
allMessages: (CoreMessageType | SendableMessageType)[],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { useLocalization } from "../../../../../lib/LocalizationContext";
import { getMessagePartsInfo } from "../getMessagePartsInfo";

jest.mock('../../../../../lib/LocalizationContext', () => ({
...jest.requireActual('../../../../../lib/LocalizationContext'),
useLocalization: jest.fn(),
}));

const mockChannel = {
isGroupChannel: () => true,
getUnreadMemberCount: () => 0,
Expand Down Expand Up @@ -40,6 +46,14 @@ const messageGroup3 = [1, 2, 3].map((n, i) => ({
}));

describe('getMessagePartsInfo', () => {
beforeEach(() => {
jest.clearAllMocks();
useLocalization.mockReturnValue({
stringSet: {
DATE_FORMAT__MESSAGE_CREATED_AT: 'p',
},
});
});
it('should group messages that are sent at same time', () => {
const defaultSetting = {
allMessages: messageGroup1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,15 @@ export const getLastMessageCreatedAt = ({ channel, locale, stringSet = LabelStri
return '';
}
if (isToday(createdAt)) {
return format(createdAt, 'p', optionalParam);
return format(createdAt, stringSet.DATE_FORMAT__LAST_MESSAGE_CREATED_AT__TODAY, optionalParam);
}
if (isYesterday(createdAt)) {
return stringSet.MESSAGE_STATUS__YESTERDAY || 'Yesterday';
}
if (isThisYear(createdAt)) {
return format(createdAt, 'MMM d', optionalParam);
return format(createdAt, stringSet.DATE_FORMAT__LAST_MESSAGE_CREATED_AT__THIS_YEAR, optionalParam);
}
return format(createdAt, 'yyyy/M/d', optionalParam);
return format(createdAt, stringSet.DATE_FORMAT__LAST_MESSAGE_CREATED_AT__PREVIOUS_YEAR, optionalParam);
};

export const getTotalMembers = (channel?: GroupChannel) => (channel?.memberCount ? channel.memberCount : 0);
Expand Down
6 changes: 5 additions & 1 deletion src/modules/OpenChannel/context/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@ import format from 'date-fns/format';

import { Logger } from '../../../lib/SendbirdState';
import { SendableMessageType } from '../../../utils';
import { useLocalization } from '../../../lib/LocalizationContext';

export const getMessageCreatedAt = (message: SendableMessageType): string => format(message.createdAt, 'p');
export const getMessageCreatedAt = (message: SendableMessageType): string => {
const { stringSet } = useLocalization();
return format(message.createdAt, stringSet.DATE_FORMAT__MESSAGE_CREATED_AT);
};

export const shouldFetchMore = (messageLength: number, maxMessages?: number): boolean => {
if (typeof maxMessages !== 'number') {
Expand Down
4 changes: 2 additions & 2 deletions src/modules/Thread/components/ParentMessageInfo/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export default function ParentMessageInfo({
const { stores, config } = useSendbirdStateContext();
const { isOnline, userMention, logger, groupChannel } = config;
const userId = stores.userStore.user?.userId ?? '';
const { dateLocale } = useLocalization();
const { dateLocale, stringSet } = useLocalization();
const {
currentChannel,
parentMessage,
Expand Down Expand Up @@ -301,7 +301,7 @@ export default function ParentMessageInfo({
type={LabelTypography.CAPTION_3}
color={LabelColors.ONBACKGROUND_2}
>
{format(parentMessage?.createdAt || 0, 'p', { locale: dateLocale })}
{format(parentMessage?.createdAt || 0, stringSet.DATE_FORMAT__MESSAGE_CREATED_AT, { locale: dateLocale })}
</Label>
</div>
{/* message content body */}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ export default function ThreadListItemContent(props: ThreadListItemContentProps)
} = deleteNullish(props);

const { isMobile } = useMediaQueryContext();
const { dateLocale } = useLocalization();
const { dateLocale, stringSet } = useLocalization();
const { config, eventHandlers } = useSendbirdStateContext?.() || {};
const { logger } = config;
const onPressUserProfileHandler = eventHandlers?.reaction?.onPressUserProfile;
Expand Down Expand Up @@ -272,7 +272,7 @@ export default function ThreadListItemContent(props: ThreadListItemContentProps)
type={LabelTypography.CAPTION_3}
color={LabelColors.ONBACKGROUND_2}
>
{format(message?.createdAt || 0, 'p', {
{format(message?.createdAt || 0, stringSet.DATE_FORMAT__MESSAGE_CREATED_AT, {
locale: dateLocale,
})}
</Label>
Expand Down
6 changes: 5 additions & 1 deletion src/modules/Thread/context/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import format from 'date-fns/format';
import { GroupChannel, Member } from '@sendbird/chat/groupChannel';
import { getOutgoingMessageState, OutgoingMessageStates } from '../../../utils/exports/getOutgoingMessageState';
import { SendableMessageType } from '../../../utils';
import { useLocalization } from '../../../lib/LocalizationContext';

export const getNicknamesMapFromMembers = (members: Member[] = []): Map<string, string> => {
const nicknamesMap = new Map();
Expand Down Expand Up @@ -57,7 +58,10 @@ export function compareIds(a: number | string, b: number | string): boolean {
return aString === bString;
}

export const getMessageCreatedAt = (message: SendableMessageType): string => format(message.createdAt, 'p');
export const getMessageCreatedAt = (message: SendableMessageType): string => {
const { stringSet } = useLocalization();
return format(message.createdAt, stringSet.DATE_FORMAT__MESSAGE_CREATED_AT);
};
export const isReadMessage = (channel: GroupChannel, message: SendableMessageType): boolean => (
getOutgoingMessageState(channel, message) === OutgoingMessageStates.READ
);
Expand Down
5 changes: 5 additions & 0 deletions src/ui/Label/stringSet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,11 @@ const stringSet = {
DATE_FORMAT__MESSAGE_LIST__NOTIFICATION__UNREAD_SINCE: 'p \'on\' MMM dd',
DATE_FORMAT__MESSAGE_LIST__DATE_SEPARATOR: 'MMMM dd, yyyy',
DATE_FORMAT__THREAD_LIST__DATE_SEPARATOR: 'MMM dd, yyyy',
DATE_FORMAT__MESSAGE_CREATED_AT: 'p',
DATE_FORMAT__UNREAD_SINCE: 'p MMM dd',
DATE_FORMAT__LAST_MESSAGE_CREATED_AT__TODAY: 'p',
DATE_FORMAT__LAST_MESSAGE_CREATED_AT__THIS_YEAR: 'MMM d',
DATE_FORMAT__LAST_MESSAGE_CREATED_AT__PREVIOUS_YEAR: 'yyyy/M/d',
// File upload
FILE_UPLOAD_NOTIFICATION__COUNT_LIMIT: 'Up to %d files can be attached.',
FILE_UPLOAD_NOTIFICATION__SIZE_LIMIT: 'The maximum size per file is %d MB.',
Expand Down
3 changes: 3 additions & 0 deletions src/ui/MessageContent/__tests__/MessageContent.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ describe('ui/MessageContent', () => {
};
const localeContextValue = {
dateLocale: {},
stringSet: {
DATE_FORMAT__MESSAGE_CREATED_AT: 'p',
},
};
const messageContextValue = {
message: {},
Expand Down
10 changes: 4 additions & 6 deletions src/ui/MessageContent/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { ReactElement, ReactNode, useContext, useMemo, useRef, useState } from 'react';
import React, { ReactElement, ReactNode, useMemo, useRef, useState } from 'react';
import format from 'date-fns/format';
import './index.scss';

Expand All @@ -25,7 +25,7 @@ import {
SendableMessageType,
UI_CONTAINER_TYPES,
} from '../../utils';
import { LocalizationContext, useLocalization } from '../../lib/LocalizationContext';
import { useLocalization } from '../../lib/LocalizationContext';
import useSendbirdStateContext from '../../hooks/useSendbirdStateContext';
import { GroupChannel } from '@sendbird/chat/groupChannel';
import { type EmojiCategory, EmojiContainer } from '@sendbird/chat';
Expand Down Expand Up @@ -137,7 +137,7 @@ export function MessageContent(props: MessageContentProps): ReactElement {
renderMobileMenuOnLongPress = (props: MobileBottomSheetProps) => <MobileMenu {...props} />,
} = deleteNullish(props);

const { dateLocale } = useLocalization();
const { dateLocale, stringSet } = useLocalization();
const { config, eventHandlers } = useSendbirdStateContext();
const { logger } = config;
const onPressUserProfileHandler = eventHandlers?.reaction?.onPressUserProfile;
Expand Down Expand Up @@ -176,8 +176,6 @@ export function MessageContent(props: MessageContentProps): ReactElement {
}
};

const { stringSet } = useContext(LocalizationContext);

const isByMe = (userId === (message as SendableMessageType)?.sender?.userId)
|| ((message as SendableMessageType)?.sendingStatus === 'pending')
|| ((message as SendableMessageType)?.sendingStatus === 'failed');
Expand Down Expand Up @@ -448,7 +446,7 @@ export function MessageContent(props: MessageContentProps): ReactElement {
color={LabelColors.ONBACKGROUND_2}
ref={timestampRef}
>
{format(message?.createdAt || 0, 'p', {
{format(message?.createdAt || 0, stringSet.DATE_FORMAT__MESSAGE_CREATED_AT, {
locale: dateLocale,
})}
</Label>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ import { getCreatedAt } from '../utils';
jest.useFakeTimers();
jest.setSystemTime(new Date('January 23, 2022 17:17:52'));

const stringSet = {
DATE_FORMAT__LAST_MESSAGE_CREATED_AT__TODAY: 'p',
MESSAGE_STATUS__YESTERDAY: 'Yesterday',
DATE_FORMAT__LAST_MESSAGE_CREATED_AT__THIS_YEAR: 'MMM d',
DATE_FORMAT__LAST_MESSAGE_CREATED_AT__PREVIOUS_YEAR: 'yyyy/M/dd',
};

describe('ui/MessageSearchFileItem', () => {
// should add test cases for each file types
// define id for each icon svg files first
Expand All @@ -34,15 +41,15 @@ describe('ui/MessageSearchFileItem', () => {
const nowTime = new Date(Date.now());
const isPM = nowTime?.getHours() > 12;
expect(
getCreatedAt({ createdAt: nowTime })
getCreatedAt({ createdAt: nowTime, stringSet })
).toBe(`${nowTime?.getHours() - (isPM ? 12 : 0)}:${nowTime?.getMinutes()} ${isPM ? 'PM' : 'AM'}`);
});

test('utils/getCreatedAt returns "Yesterday" if ts is created yesterday', () => {
const nowTime = new Date(Date.now());
nowTime.setDate(nowTime.getDate() - 1);
expect(
getCreatedAt({ createdAt: nowTime })
getCreatedAt({ createdAt: nowTime, stringSet })
).toBe("Yesterday");
})

Expand All @@ -51,21 +58,21 @@ describe('ui/MessageSearchFileItem', () => {
nowTime.setDate(nowTime.getDate() - 2);
const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
expect(
getCreatedAt({ createdAt: nowTime })
getCreatedAt({ createdAt: nowTime, stringSet })
).toBe(`${months[nowTime?.getMonth()]} ${nowTime?.getDate()}`);
expect(
getCreatedAt({ createdAt: nowTime })
getCreatedAt({ createdAt: nowTime, stringSet })
).toBe('Jan 21');
});

test('utils/getCreatedAt returns year, month, and date if ts is created last year', () => {
const nowTime = new Date(Date.now());
nowTime.setFullYear(nowTime.getFullYear() - 1);
expect(
getCreatedAt({ createdAt: nowTime })
getCreatedAt({ createdAt: nowTime, stringSet })
).toBe(`${nowTime?.getFullYear()}/${nowTime?.getMonth() + 1}/${nowTime?.getDate()}`);
expect(
getCreatedAt({ createdAt: nowTime })
getCreatedAt({ createdAt: nowTime, stringSet })
).toBe('2021/1/23');
});
});
10 changes: 5 additions & 5 deletions src/ui/MessageSearchFileItem/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { Types } from '../Icon/type';
export interface GetCreatedAtProps {
createdAt: number;
locale?: Locale;
stringSet?: Record<string, string>;
stringSet: Record<string, string>;
}

export function getCreatedAt({ createdAt, locale, stringSet }: GetCreatedAtProps): string {
Expand All @@ -22,15 +22,15 @@ export function getCreatedAt({ createdAt, locale, stringSet }: GetCreatedAtProps
return '';
}
if (isToday(createdAt)) {
return format(createdAt, 'p', optionalParam);
return format(createdAt, stringSet.DATE_FORMAT__LAST_MESSAGE_CREATED_AT__TODAY, optionalParam);
}
if (isYesterday(createdAt)) {
return stringSet?.MESSAGE_STATUS__YESTERDAY || 'Yesterday';
return stringSet.MESSAGE_STATUS__YESTERDAY;
}
if (isThisYear(createdAt)) {
return format(createdAt, 'MMM d', optionalParam);
return format(createdAt, stringSet.DATE_FORMAT__LAST_MESSAGE_CREATED_AT__THIS_YEAR, optionalParam);
}
return format(createdAt, 'yyyy/M/d', optionalParam);
return format(createdAt, stringSet.DATE_FORMAT__LAST_MESSAGE_CREATED_AT__PREVIOUS_YEAR, optionalParam);
}

export function getIconOfFileType(message: FileMessage | MultipleFilesMessage): Types {
Expand Down
Loading

0 comments on commit 4922d04

Please sign in to comment.