import { createSelector } from 'reselect'; import { format } from '../../types/PhoneNumber'; import { LocalizerType } from '../../types/Util'; import { StateType } from '../reducer'; import { ConversationLookupType, ConversationsStateType, ConversationType, } from '../ducks/conversations'; import { getIntl, getRegionCode, getUserNumber } from './user'; import { PropsData as ConversationListItemPropsType } from '../../components/ConversationListItem'; export const getConversations = (state: StateType): ConversationsStateType => state.conversations; export const getConversationLookup = createSelector( getConversations, (state: ConversationsStateType): ConversationLookupType => { return state.conversationLookup; } ); export const getSelectedConversation = createSelector( getConversations, (state: ConversationsStateType): string | undefined => { return state.selectedConversation; } ); export const getShowArchived = createSelector( getConversations, (state: ConversationsStateType): boolean => { return Boolean(state.showArchived); } ); function getConversationTitle( conversation: ConversationType, options: { i18n: LocalizerType; ourRegionCode: string } ): string { if (conversation.name) { return conversation.name; } if (conversation.type === 'group') { const { i18n } = options; return i18n('unknownGroup'); } return format(conversation.phoneNumber, options); } const collator = new Intl.Collator(); export const _getConversationComparator = ( i18n: LocalizerType, ourRegionCode: string ) => { return (left: ConversationType, right: ConversationType): number => { const leftTimestamp = left.timestamp; const rightTimestamp = right.timestamp; if (leftTimestamp && !rightTimestamp) { return -1; } if (rightTimestamp && !leftTimestamp) { return 1; } if (leftTimestamp && rightTimestamp && leftTimestamp !== rightTimestamp) { return rightTimestamp - leftTimestamp; } const leftTitle = getConversationTitle(left, { i18n, ourRegionCode, }).toLowerCase(); const rightTitle = getConversationTitle(right, { i18n, ourRegionCode, }).toLowerCase(); return collator.compare(leftTitle, rightTitle); }; }; export const getConversationComparator = createSelector( getIntl, getRegionCode, _getConversationComparator ); export const _getLeftPaneLists = ( lookup: ConversationLookupType, comparator: (left: ConversationType, right: ConversationType) => number, selectedConversation?: string ): { conversations: Array; archivedConversations: Array; friends: Array; receivedFriendsRequest: Array; sentFriendsRequest: Array; unreadCount: number; } => { const values = Object.values(lookup); const sorted = values.sort(comparator); const conversations: Array = []; const archivedConversations: Array = []; const friends: Array = []; const receivedFriendsRequest: Array = []; const sentFriendsRequest: Array = []; const max = sorted.length; let unreadCount = 0; for (let i = 0; i < max; i += 1) { let conversation = sorted[i]; if (selectedConversation === conversation.id) { conversation = { ...conversation, isSelected: true, }; } if (conversation.isFriend) { friends.push(conversation); } if (conversation.hasReceivedFriendRequest) { receivedFriendsRequest.push(conversation); } else if ( unreadCount < 9 && conversation.isFriend && conversation.unreadCount > 0 ) { unreadCount += conversation.unreadCount; } if (conversation.hasSentFriendRequest) { sentFriendsRequest.push(conversation); } if (!conversation.activeAt) { continue; } if (conversation.isArchived) { archivedConversations.push(conversation); } else { conversations.push(conversation); } } return { conversations, archivedConversations, friends, receivedFriendsRequest, sentFriendsRequest, unreadCount, }; }; export const getLeftPaneLists = createSelector( getConversationLookup, getConversationComparator, getSelectedConversation, _getLeftPaneLists ); export const getMe = createSelector( [getConversationLookup, getUserNumber], (lookup: ConversationLookupType, ourNumber: string): ConversationType => { return lookup[ourNumber]; } );