Finish in-redux conversation lookups, getPropsForSearchResult moved
This commit is contained in:
parent
7fe40dbf83
commit
cbc6c29479
18 changed files with 901 additions and 146 deletions
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2019-2020 Signal Messenger, LLC
|
||||
// Copyright 2019-2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import memoizee from 'memoizee';
|
||||
|
@ -15,6 +15,7 @@ import {
|
|||
MessagesByConversationType,
|
||||
MessageType,
|
||||
} from '../ducks/conversations';
|
||||
import { getOwn } from '../../util/getOwn';
|
||||
import type { CallsByConversationType } from '../ducks/calling';
|
||||
import { getCallsByConversation } from './calling';
|
||||
import { getBubbleProps } from '../../shims/Whisper';
|
||||
|
@ -30,6 +31,20 @@ import {
|
|||
} from './user';
|
||||
import { getPinnedConversationIds } from './items';
|
||||
|
||||
let placeholderContact: ConversationType;
|
||||
export const getPlaceholderContact = (): ConversationType => {
|
||||
if (placeholderContact) {
|
||||
return placeholderContact;
|
||||
}
|
||||
|
||||
placeholderContact = {
|
||||
id: 'placeholder-contact',
|
||||
type: 'direct',
|
||||
title: window.i18n('unknownContact'),
|
||||
};
|
||||
return placeholderContact;
|
||||
};
|
||||
|
||||
export const getConversations = (state: StateType): ConversationsStateType =>
|
||||
state.conversations;
|
||||
|
||||
|
@ -40,6 +55,27 @@ export const getConversationLookup = createSelector(
|
|||
}
|
||||
);
|
||||
|
||||
export const getConversationsByUuid = createSelector(
|
||||
getConversations,
|
||||
(state: ConversationsStateType): ConversationLookupType => {
|
||||
return state.conversationsByUuid;
|
||||
}
|
||||
);
|
||||
|
||||
export const getConversationsByE164 = createSelector(
|
||||
getConversations,
|
||||
(state: ConversationsStateType): ConversationLookupType => {
|
||||
return state.conversationsByE164;
|
||||
}
|
||||
);
|
||||
|
||||
export const getConversationsByGroupId = createSelector(
|
||||
getConversations,
|
||||
(state: ConversationsStateType): ConversationLookupType => {
|
||||
return state.conversationsByGroupId;
|
||||
}
|
||||
);
|
||||
|
||||
export const getSelectedConversation = createSelector(
|
||||
getConversations,
|
||||
(state: ConversationsStateType): string | undefined => {
|
||||
|
@ -201,17 +237,21 @@ export const getMe = createSelector(
|
|||
// Backbone-based prop-generation functions expect to get Conversation information
|
||||
// directly via ConversationController
|
||||
export function _conversationSelector(
|
||||
conversation: ConversationType
|
||||
conversation?: ConversationType
|
||||
// regionCode: string,
|
||||
// userNumber: string
|
||||
): ConversationType {
|
||||
return conversation;
|
||||
if (conversation) {
|
||||
return conversation;
|
||||
}
|
||||
|
||||
return getPlaceholderContact();
|
||||
}
|
||||
|
||||
// A little optimization to reset our selector cache when high-level application data
|
||||
// changes: regionCode and userNumber.
|
||||
type CachedConversationSelectorType = (
|
||||
conversation: ConversationType
|
||||
conversation?: ConversationType
|
||||
) => ConversationType;
|
||||
export const getCachedSelectorForConversation = createSelector(
|
||||
getRegionCode,
|
||||
|
@ -223,23 +263,51 @@ export const getCachedSelectorForConversation = createSelector(
|
|||
}
|
||||
);
|
||||
|
||||
export type GetConversationByIdType = (
|
||||
id: string
|
||||
) => ConversationType | undefined;
|
||||
export type GetConversationByIdType = (id?: string) => ConversationType;
|
||||
export const getConversationSelector = createSelector(
|
||||
getCachedSelectorForConversation,
|
||||
getConversationLookup,
|
||||
getConversationsByUuid,
|
||||
getConversationsByE164,
|
||||
getConversationsByGroupId,
|
||||
(
|
||||
selector: CachedConversationSelectorType,
|
||||
lookup: ConversationLookupType
|
||||
byId: ConversationLookupType,
|
||||
byUuid: ConversationLookupType,
|
||||
byE164: ConversationLookupType,
|
||||
byGroupId: ConversationLookupType
|
||||
): GetConversationByIdType => {
|
||||
return (id: string) => {
|
||||
const conversation = lookup[id];
|
||||
if (!conversation) {
|
||||
return undefined;
|
||||
return (id?: string) => {
|
||||
if (!id) {
|
||||
window.log.warn(
|
||||
`getConversationSelector: Called with a falsey id ${id}`
|
||||
);
|
||||
// This will return a placeholder contact
|
||||
return selector(undefined);
|
||||
}
|
||||
|
||||
return selector(conversation);
|
||||
const onE164 = getOwn(byE164, id);
|
||||
if (onE164) {
|
||||
return selector(onE164);
|
||||
}
|
||||
const onUuid = getOwn(byUuid, id);
|
||||
if (onUuid) {
|
||||
return selector(onUuid);
|
||||
}
|
||||
const onGroupId = getOwn(byGroupId, id);
|
||||
if (onGroupId) {
|
||||
return selector(onGroupId);
|
||||
}
|
||||
const onId = getOwn(byId, id);
|
||||
if (onId) {
|
||||
return selector(onId);
|
||||
}
|
||||
|
||||
window.log.warn(
|
||||
`getConversationSelector: No conversation found for id ${id}`
|
||||
);
|
||||
// This will return a placeholder contact
|
||||
return selector(undefined);
|
||||
};
|
||||
}
|
||||
);
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
import memoizee from 'memoizee';
|
||||
import { createSelector } from 'reselect';
|
||||
import { getSearchResultsProps } from '../../shims/Whisper';
|
||||
import { instance } from '../../util/libphonenumberInstance';
|
||||
|
||||
import { StateType } from '../reducer';
|
||||
|
@ -24,7 +23,7 @@ import {
|
|||
} from '../../components/SearchResults';
|
||||
import { PropsDataType as MessageSearchResultPropsDataType } from '../../components/MessageSearchResult';
|
||||
|
||||
import { getRegionCode, getUserNumber } from './user';
|
||||
import { getRegionCode, getUserConversationId } from './user';
|
||||
import { getUserAgent } from './items';
|
||||
import {
|
||||
GetConversationByIdType,
|
||||
|
@ -221,18 +220,21 @@ export const getSearchResults = createSelector(
|
|||
|
||||
export function _messageSearchResultSelector(
|
||||
message: MessageSearchResultType,
|
||||
_ourNumber: string,
|
||||
_regionCode: string,
|
||||
_sender?: ConversationType,
|
||||
_recipient?: ConversationType,
|
||||
from: ConversationType,
|
||||
to: ConversationType,
|
||||
searchConversationId?: string,
|
||||
selectedMessageId?: string
|
||||
): MessageSearchResultPropsDataType {
|
||||
// Note: We don't use all of those parameters here, but the shim we call does.
|
||||
// We want to call this function again if any of those parameters change.
|
||||
return {
|
||||
...getSearchResultsProps(message),
|
||||
isSelected: message.id === selectedMessageId,
|
||||
from,
|
||||
to,
|
||||
|
||||
id: message.id,
|
||||
conversationId: message.conversationId,
|
||||
sentAt: message.sent_at,
|
||||
snippet: message.snippet,
|
||||
|
||||
isSelected: Boolean(selectedMessageId && message.id === selectedMessageId),
|
||||
isSearchingInConversation: Boolean(searchConversationId),
|
||||
};
|
||||
}
|
||||
|
@ -241,16 +243,13 @@ export function _messageSearchResultSelector(
|
|||
// changes: regionCode and userNumber.
|
||||
type CachedMessageSearchResultSelectorType = (
|
||||
message: MessageSearchResultType,
|
||||
ourNumber: string,
|
||||
regionCode: string,
|
||||
sender?: ConversationType,
|
||||
recipient?: ConversationType,
|
||||
from: ConversationType,
|
||||
to: ConversationType,
|
||||
searchConversationId?: string,
|
||||
selectedMessageId?: string
|
||||
) => MessageSearchResultPropsDataType;
|
||||
export const getCachedSelectorForMessageSearchResult = createSelector(
|
||||
getRegionCode,
|
||||
getUserNumber,
|
||||
getUserConversationId,
|
||||
(): CachedMessageSearchResultSelectorType => {
|
||||
// Note: memoizee will check all parameters provided, and only run our selector
|
||||
// if any of them have changed.
|
||||
|
@ -267,43 +266,47 @@ export const getMessageSearchResultSelector = createSelector(
|
|||
getSelectedMessage,
|
||||
getConversationSelector,
|
||||
getSearchConversationId,
|
||||
getRegionCode,
|
||||
getUserNumber,
|
||||
getUserConversationId,
|
||||
(
|
||||
messageSearchResultSelector: CachedMessageSearchResultSelectorType,
|
||||
messageSearchResultLookup: MessageSearchResultLookupType,
|
||||
selectedMessage: string | undefined,
|
||||
selectedMessageId: string | undefined,
|
||||
conversationSelector: GetConversationByIdType,
|
||||
searchConversationId: string | undefined,
|
||||
regionCode: string,
|
||||
ourNumber: string
|
||||
ourConversationId: string
|
||||
): GetMessageSearchResultByIdType => {
|
||||
return (id: string) => {
|
||||
const message = messageSearchResultLookup[id];
|
||||
if (!message) {
|
||||
window.log.warn(
|
||||
`getMessageSearchResultSelector: messageSearchResultLookup was missing id ${id}`
|
||||
);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const { conversationId, source, type } = message;
|
||||
let sender: ConversationType | undefined;
|
||||
let recipient: ConversationType | undefined;
|
||||
const { conversationId, source, sourceUuid, type } = message;
|
||||
let from: ConversationType;
|
||||
let to: ConversationType;
|
||||
|
||||
if (type === 'incoming') {
|
||||
sender = conversationSelector(source);
|
||||
recipient = conversationSelector(ourNumber);
|
||||
from = conversationSelector(sourceUuid || source);
|
||||
to = conversationSelector(conversationId);
|
||||
} else if (type === 'outgoing') {
|
||||
sender = conversationSelector(ourNumber);
|
||||
recipient = conversationSelector(conversationId);
|
||||
from = conversationSelector(ourConversationId);
|
||||
to = conversationSelector(conversationId);
|
||||
} else {
|
||||
window.log.warn(
|
||||
`getMessageSearchResultSelector: Got unexpected type ${type}`
|
||||
);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return messageSearchResultSelector(
|
||||
message,
|
||||
ourNumber,
|
||||
regionCode,
|
||||
sender,
|
||||
recipient,
|
||||
from,
|
||||
to,
|
||||
searchConversationId,
|
||||
selectedMessage
|
||||
selectedMessageId
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue