signal-desktop/ts/components/conversation/media-gallery/groupMessagesByDate.ts

164 lines
4.1 KiB
TypeScript
Raw Normal View History

2018-04-13 20:25:52 +00:00
/**
* @prettier
*/
2018-04-13 00:45:14 +00:00
import moment from 'moment';
2018-04-13 20:25:52 +00:00
import { compact, groupBy, sortBy } from 'lodash';
2018-04-13 00:45:14 +00:00
import { Message } from './propTypes/Message';
// import { missingCaseError } from '../../../util/missingCaseError';
2018-04-13 00:45:14 +00:00
2018-04-13 20:27:06 +00:00
type StaticSectionType = 'today' | 'yesterday' | 'thisWeek' | 'thisMonth';
type YearMonthSectionType = 'yearMonth';
interface GenericSection<T> {
type: T;
messages: Array<Message>;
}
type StaticSection = GenericSection<StaticSectionType>;
type YearMonthSection = GenericSection<YearMonthSectionType> & {
year: number;
month: number;
};
export type Section = StaticSection | YearMonthSection;
2018-04-13 20:25:52 +00:00
export const groupMessagesByDate = (
timestamp: number,
messages: Array<Message>
2018-04-13 20:27:06 +00:00
): Array<Section> => {
2018-04-13 00:45:14 +00:00
const referenceDateTime = moment.utc(timestamp);
const today = moment(referenceDateTime).startOf('day');
2018-04-13 20:25:52 +00:00
const yesterday = moment(referenceDateTime)
.subtract(1, 'day')
.startOf('day');
2018-04-13 14:53:15 +00:00
const thisWeek = moment(referenceDateTime).startOf('isoWeek');
2018-04-13 00:45:14 +00:00
const thisMonth = moment(referenceDateTime).startOf('month');
2018-04-13 20:27:06 +00:00
const sortedMessages = sortBy(messages, message => -message.received_at);
const messagesWithSection = sortedMessages.map(
withSection({
today,
yesterday,
thisWeek,
thisMonth,
})
);
const groupedMessages = groupBy(messagesWithSection, 'type');
const yearMonthMessages = Object.values(
groupBy(groupedMessages.yearMonth, 'order')
).reverse();
return compact([
toSection(groupedMessages.today),
toSection(groupedMessages.yesterday),
toSection(groupedMessages.thisWeek),
toSection(groupedMessages.thisMonth),
...yearMonthMessages.map(group => toSection(group)),
]);
};
2018-04-13 00:45:14 +00:00
2018-04-13 20:27:06 +00:00
const toSection = (
messagesWithSection: Array<MessageWithSection> | undefined
): Section | null => {
if (!messagesWithSection || messagesWithSection.length === 0) {
return null;
}
const firstMessageWithSection: MessageWithSection = messagesWithSection[0];
if (!firstMessageWithSection) {
return null;
}
const messages = messagesWithSection.map(
messageWithSection => messageWithSection.message
);
switch (firstMessageWithSection.type) {
case 'today':
case 'yesterday':
case 'thisWeek':
case 'thisMonth':
2018-04-13 00:45:14 +00:00
return {
2018-04-13 20:27:06 +00:00
type: firstMessageWithSection.type,
2018-04-14 02:09:56 +00:00
messages,
2018-04-13 00:45:14 +00:00
};
2018-04-13 20:27:06 +00:00
case 'yearMonth':
2018-04-13 00:45:14 +00:00
return {
2018-04-13 20:27:06 +00:00
type: firstMessageWithSection.type,
year: firstMessageWithSection.year,
month: firstMessageWithSection.month,
messages,
2018-04-13 00:45:14 +00:00
};
2018-04-13 20:27:06 +00:00
default:
// NOTE: Investigate why we get the following error:
// error TS2345: Argument of type 'any' is not assignable to parameter
// of type 'never'.
// return missingCaseError(firstMessageWithSection.type);
return null;
}
};
2018-04-14 02:09:56 +00:00
interface GenericMessageWithSection<T> {
2018-04-13 20:27:06 +00:00
order: number;
type: T;
message: Message;
2018-04-14 02:09:56 +00:00
}
2018-04-13 20:27:06 +00:00
type MessageWithStaticSection = GenericMessageWithSection<StaticSectionType>;
type MessageWithYearMonthSection = GenericMessageWithSection<
YearMonthSectionType
> & {
year: number;
month: number;
};
type MessageWithSection =
| MessageWithStaticSection
| MessageWithYearMonthSection;
2018-04-13 00:45:14 +00:00
2018-04-13 20:27:06 +00:00
const withSection = ({
today,
yesterday,
thisWeek,
thisMonth,
}: {
today: moment.Moment;
yesterday: moment.Moment;
thisWeek: moment.Moment;
thisMonth: moment.Moment;
}) => (message: Message): MessageWithSection => {
const messageReceivedDate = moment.utc(message.received_at);
if (messageReceivedDate.isAfter(today)) {
return {
order: 0,
type: 'today',
message,
};
}
if (messageReceivedDate.isAfter(yesterday)) {
return {
order: 1,
type: 'yesterday',
message,
};
}
if (messageReceivedDate.isAfter(thisWeek)) {
return {
order: 2,
type: 'thisWeek',
message,
};
}
if (messageReceivedDate.isAfter(thisMonth)) {
2018-04-13 00:45:14 +00:00
return {
2018-04-13 20:27:06 +00:00
order: 3,
type: 'thisMonth',
2018-04-13 00:45:14 +00:00
message,
};
2018-04-13 20:27:06 +00:00
}
2018-04-13 00:45:14 +00:00
2018-04-13 20:27:06 +00:00
const month: number = messageReceivedDate.month();
const year: number = messageReceivedDate.year();
return {
order: year * 100 + month,
type: 'yearMonth',
month,
year,
message,
};
2018-04-13 00:45:14 +00:00
};