You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
session-desktop/ts/state/selectors/conversations.ts

205 lines
5.7 KiB
TypeScript

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<ConversationType>;
archivedConversations: Array<ConversationType>;
friends: Array<ConversationType>;
receivedFriendsRequest: Array<ConversationListItemPropsType>;
sentFriendsRequest: Array<ConversationListItemPropsType>;
unreadCount: number;
} => {
const _ = window.Lodash;
const values = Object.values(lookup);
const sorted = values.sort(comparator);
const conversations: Array<ConversationType> = [];
const archivedConversations: Array<ConversationType> = [];
const friends: Array<ConversationType> = [];
const receivedFriendsRequest: Array<ConversationListItemPropsType> = [];
const sentFriendsRequest: Array<ConversationListItemPropsType> = [];
const max = sorted.length;
let unreadCount = 0;
// Map pubkeys to their primary pubkey so you don't need to call getPrimaryDeviceFor
// every time.
5 years ago
const filterToPrimary = (group: Array<ConversationType | ConversationListItemPropsType>) => {
// Used to ensure that only the primary device gets added to LeftPane filtered groups
// Get one result per user. Dont just ignore secondaries, in case
// a user hasn't synced with primary but FR or contact is duplicated.
5 years ago
// You can't just get the primary device for each conversation, as different
// devices might have seperate FR and contacts status, etc.
5 years ago
// Build up propsData into ConversationType
const constructedGroup = conversations.filter(c => group.some(g => c.id === g.id));
const filteredGroup = constructedGroup.filter(c => !(c.isSecondary && group.some(g => g.id === c.primaryDevice)));
5 years ago
5 years ago
console.log('[group] conversations:', conversations);
5 years ago
console.log('[group] group:', group);
5 years ago
console.log('[group] filteredGroup:', filteredGroup);
5 years ago
5 years ago
return filteredGroup;
};
for (let i = 0; i < max; i += 1) {
let conversation = sorted[i];
if (selectedConversation === conversation.id) {
conversation = {
...conversation,
isSelected: true,
};
}
if (conversation.isFriend && conversation.activeAt !== undefined) {
5 years ago
friends.push(conversation)
}
if (conversation.hasReceivedFriendRequest) {
5 years ago
receivedFriendsRequest.push(conversation)
} else if (
unreadCount < 9 &&
conversation.isFriend &&
conversation.unreadCount > 0
) {
unreadCount += conversation.unreadCount;
}
if (conversation.hasSentFriendRequest) {
5 years ago
sentFriendsRequest.push(conversation);
}
if (!conversation.activeAt) {
continue;
}
if (conversation.isArchived) {
archivedConversations.push(conversation);
} else {
conversations.push(conversation);
}
}
5 years ago
const vFriends = filterToPrimary(friends);
console.log('[group] vFriends:', vFriends);
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];
}
);