// Copyright 2018-2020 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only import moment from 'moment'; import { compact, groupBy, sortBy } from 'lodash'; import { MediaItemType } from '../../LightboxGallery'; // import { missingCaseError } from '../../../util/missingCaseError'; type StaticSectionType = 'today' | 'yesterday' | 'thisWeek' | 'thisMonth'; type YearMonthSectionType = 'yearMonth'; interface GenericSection { type: T; mediaItems: Array; } type StaticSection = GenericSection; type YearMonthSection = GenericSection & { year: number; month: number; }; export type Section = StaticSection | YearMonthSection; export const groupMediaItemsByDate = ( timestamp: number, mediaItems: Array ): Array
=> { const referenceDateTime = moment.utc(timestamp); const sortedMediaItem = sortBy(mediaItems, mediaItem => { const { message } = mediaItem; return -message.received_at; }); const messagesWithSection = sortedMediaItem.map( withSection(referenceDateTime) ); const groupedMediaItem = groupBy(messagesWithSection, 'type'); const yearMonthMediaItem = Object.values( groupBy(groupedMediaItem.yearMonth, 'order') ).reverse(); return compact([ toSection(groupedMediaItem.today), toSection(groupedMediaItem.yesterday), toSection(groupedMediaItem.thisWeek), toSection(groupedMediaItem.thisMonth), ...yearMonthMediaItem.map(toSection), ]); }; const toSection = ( messagesWithSection: Array | undefined ): Section | undefined => { if (!messagesWithSection || messagesWithSection.length === 0) { return; } const firstMediaItemWithSection: MediaItemWithSection = messagesWithSection[0]; if (!firstMediaItemWithSection) { return; } const mediaItems = messagesWithSection.map( messageWithSection => messageWithSection.mediaItem ); switch (firstMediaItemWithSection.type) { case 'today': case 'yesterday': case 'thisWeek': case 'thisMonth': // eslint-disable-next-line consistent-return return { type: firstMediaItemWithSection.type, mediaItems, }; case 'yearMonth': // eslint-disable-next-line consistent-return return { type: firstMediaItemWithSection.type, year: firstMediaItemWithSection.year, month: firstMediaItemWithSection.month, mediaItems, }; 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(firstMediaItemWithSection.type); // eslint-disable-next-line no-useless-return return; } }; interface GenericMediaItemWithSection { order: number; type: T; mediaItem: MediaItemType; } type MediaItemWithStaticSection = GenericMediaItemWithSection< StaticSectionType >; type MediaItemWithYearMonthSection = GenericMediaItemWithSection< YearMonthSectionType > & { year: number; month: number; }; type MediaItemWithSection = | MediaItemWithStaticSection | MediaItemWithYearMonthSection; const withSection = (referenceDateTime: moment.Moment) => ( mediaItem: MediaItemType ): MediaItemWithSection => { const today = moment(referenceDateTime).startOf('day'); const yesterday = moment(referenceDateTime).subtract(1, 'day').startOf('day'); const thisWeek = moment(referenceDateTime).startOf('isoWeek'); const thisMonth = moment(referenceDateTime).startOf('month'); const { message } = mediaItem; const mediaItemReceivedDate = moment.utc(message.received_at); if (mediaItemReceivedDate.isAfter(today)) { return { order: 0, type: 'today', mediaItem, }; } if (mediaItemReceivedDate.isAfter(yesterday)) { return { order: 1, type: 'yesterday', mediaItem, }; } if (mediaItemReceivedDate.isAfter(thisWeek)) { return { order: 2, type: 'thisWeek', mediaItem, }; } if (mediaItemReceivedDate.isAfter(thisMonth)) { return { order: 3, type: 'thisMonth', mediaItem, }; } const month: number = mediaItemReceivedDate.month(); const year: number = mediaItemReceivedDate.year(); return { order: year * 100 + month, type: 'yearMonth', month, year, mediaItem, }; };