2019-01-14 22:49:58 +01:00
|
|
|
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';
|
2020-01-07 03:24:44 +01:00
|
|
|
import { PropsData as ConversationListItemPropsType } from '../../components/ConversationListItem';
|
2019-01-14 22:49:58 +01:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
2019-03-12 01:20:16 +01:00
|
|
|
export const getShowArchived = createSelector(
|
|
|
|
getConversations,
|
|
|
|
(state: ConversationsStateType): boolean => {
|
|
|
|
return Boolean(state.showArchived);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
2019-01-14 22:49:58 +01:00
|
|
|
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
|
|
|
|
);
|
|
|
|
|
2019-03-12 01:20:16 +01:00
|
|
|
export const _getLeftPaneLists = (
|
2019-01-14 22:49:58 +01:00
|
|
|
lookup: ConversationLookupType,
|
|
|
|
comparator: (left: ConversationType, right: ConversationType) => number,
|
|
|
|
selectedConversation?: string
|
2019-03-12 01:20:16 +01:00
|
|
|
): {
|
|
|
|
conversations: Array<ConversationType>;
|
|
|
|
archivedConversations: Array<ConversationType>;
|
2019-04-18 05:48:13 +02:00
|
|
|
friends: Array<ConversationType>;
|
2020-01-07 03:24:44 +01:00
|
|
|
receivedFriendsRequest: Array<ConversationListItemPropsType>;
|
|
|
|
sentFriendsRequest: Array<ConversationListItemPropsType>;
|
2019-03-12 01:20:16 +01:00
|
|
|
} => {
|
2019-01-14 22:49:58 +01:00
|
|
|
const values = Object.values(lookup);
|
2019-03-12 01:20:16 +01:00
|
|
|
const sorted = values.sort(comparator);
|
|
|
|
|
|
|
|
const conversations: Array<ConversationType> = [];
|
|
|
|
const archivedConversations: Array<ConversationType> = [];
|
2019-04-18 05:48:13 +02:00
|
|
|
const friends: Array<ConversationType> = [];
|
2020-01-07 03:24:44 +01:00
|
|
|
const receivedFriendsRequest: Array<ConversationListItemPropsType> = [];
|
|
|
|
const sentFriendsRequest: Array<ConversationListItemPropsType> = [];
|
2019-03-12 01:20:16 +01:00
|
|
|
|
|
|
|
const max = sorted.length;
|
|
|
|
for (let i = 0; i < max; i += 1) {
|
|
|
|
let conversation = sorted[i];
|
2019-04-18 02:37:23 +02:00
|
|
|
|
2019-03-12 01:20:16 +01:00
|
|
|
if (selectedConversation === conversation.id) {
|
|
|
|
conversation = {
|
|
|
|
...conversation,
|
|
|
|
isSelected: true,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2019-04-18 05:48:13 +02:00
|
|
|
if (conversation.isFriend) {
|
|
|
|
friends.push(conversation);
|
|
|
|
}
|
|
|
|
|
2020-01-07 03:24:44 +01:00
|
|
|
if (conversation.hasReceivedFriendRequest) {
|
|
|
|
receivedFriendsRequest.push(conversation);
|
|
|
|
}
|
|
|
|
if (conversation.hasSentFriendRequest) {
|
|
|
|
sentFriendsRequest.push(conversation);
|
|
|
|
}
|
|
|
|
|
2019-04-18 05:48:13 +02:00
|
|
|
if (!conversation.activeAt) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2019-03-12 01:20:16 +01:00
|
|
|
if (conversation.isArchived) {
|
|
|
|
archivedConversations.push(conversation);
|
|
|
|
} else {
|
|
|
|
conversations.push(conversation);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-07 03:24:44 +01:00
|
|
|
return {
|
|
|
|
conversations,
|
|
|
|
archivedConversations,
|
|
|
|
friends,
|
|
|
|
receivedFriendsRequest,
|
|
|
|
sentFriendsRequest,
|
|
|
|
};
|
2019-01-14 22:49:58 +01:00
|
|
|
};
|
|
|
|
|
2019-03-12 01:20:16 +01:00
|
|
|
export const getLeftPaneLists = createSelector(
|
2019-01-14 22:49:58 +01:00
|
|
|
getConversationLookup,
|
|
|
|
getConversationComparator,
|
|
|
|
getSelectedConversation,
|
2019-03-12 01:20:16 +01:00
|
|
|
_getLeftPaneLists
|
2019-01-14 22:49:58 +01:00
|
|
|
);
|
|
|
|
|
|
|
|
export const getMe = createSelector(
|
|
|
|
[getConversationLookup, getUserNumber],
|
|
|
|
(lookup: ConversationLookupType, ourNumber: string): ConversationType => {
|
|
|
|
return lookup[ourNumber];
|
|
|
|
}
|
|
|
|
);
|