Fix action propagation to timeline items
This commit is contained in:
parent
9ffa29ca0d
commit
5a57e2b704
14 changed files with 71 additions and 66 deletions
|
@ -50,39 +50,42 @@ export type CompositionAPIType = {
|
|||
resetEmojiResults: InputApi['resetEmojiResults'];
|
||||
};
|
||||
|
||||
export type OwnProps = {
|
||||
readonly i18n: LocalizerType;
|
||||
readonly areWePending?: boolean;
|
||||
readonly areWePendingApproval?: boolean;
|
||||
readonly announcementsOnly?: boolean;
|
||||
readonly areWeAdmin?: boolean;
|
||||
readonly groupAdmins: Array<ConversationType>;
|
||||
readonly groupVersion?: 1 | 2;
|
||||
readonly isGroupV1AndDisabled?: boolean;
|
||||
readonly isMissingMandatoryProfileSharing?: boolean;
|
||||
readonly isSMSOnly?: boolean;
|
||||
readonly isFetchingUUID?: boolean;
|
||||
readonly left?: boolean;
|
||||
readonly messageRequestsEnabled?: boolean;
|
||||
readonly acceptedMessageRequest?: boolean;
|
||||
readonly compositionApi?: React.MutableRefObject<CompositionAPIType>;
|
||||
readonly micCellEl?: HTMLElement;
|
||||
readonly draftAttachments: Array<AttachmentType>;
|
||||
readonly shouldSendHighQualityAttachments: boolean;
|
||||
export type OwnProps = Readonly<{
|
||||
i18n: LocalizerType;
|
||||
areWePending?: boolean;
|
||||
areWePendingApproval?: boolean;
|
||||
announcementsOnly?: boolean;
|
||||
areWeAdmin?: boolean;
|
||||
groupAdmins: Array<ConversationType>;
|
||||
groupVersion?: 1 | 2;
|
||||
isGroupV1AndDisabled?: boolean;
|
||||
isMissingMandatoryProfileSharing?: boolean;
|
||||
isSMSOnly?: boolean;
|
||||
isFetchingUUID?: boolean;
|
||||
left?: boolean;
|
||||
messageRequestsEnabled?: boolean;
|
||||
acceptedMessageRequest?: boolean;
|
||||
compositionApi?: React.MutableRefObject<CompositionAPIType>;
|
||||
micCellEl?: HTMLElement;
|
||||
draftAttachments: ReadonlyArray<AttachmentType>;
|
||||
shouldSendHighQualityAttachments: boolean;
|
||||
onChooseAttachment(): unknown;
|
||||
onAddAttachment(): unknown;
|
||||
onClickAttachment(): unknown;
|
||||
onCloseAttachment(): unknown;
|
||||
onClearAttachments(): unknown;
|
||||
onSelectMediaQuality(isHQ: boolean): unknown;
|
||||
readonly quotedMessageProps?: QuoteProps;
|
||||
quotedMessageProps?: Omit<
|
||||
QuoteProps,
|
||||
'i18n' | 'onClick' | 'onClose' | 'withContentAbove'
|
||||
>;
|
||||
onClickQuotedMessage(): unknown;
|
||||
setQuotedMessage(message: undefined): unknown;
|
||||
linkPreviewLoading: boolean;
|
||||
linkPreviewResult?: LinkPreviewWithDomain;
|
||||
onCloseLinkPreview(): unknown;
|
||||
openConversation(conversationId: string): unknown;
|
||||
};
|
||||
}>;
|
||||
|
||||
export type Props = Pick<
|
||||
CompositionInputProps,
|
||||
|
|
|
@ -23,7 +23,7 @@ type PropsType = {
|
|||
toggleProfileEditor: () => unknown;
|
||||
toggleProfileEditorHasError: () => unknown;
|
||||
} & PropsDataType &
|
||||
ProfileEditorPropsType;
|
||||
Omit<ProfileEditorPropsType, 'onEditStateChanged' | 'onProfileChanged'>;
|
||||
|
||||
export const ProfileEditorModal = ({
|
||||
hasError,
|
||||
|
|
|
@ -15,14 +15,14 @@ import {
|
|||
isVideoAttachment,
|
||||
} from '../../types/Attachment';
|
||||
|
||||
export type Props = {
|
||||
attachments: Array<AttachmentType>;
|
||||
export type Props = Readonly<{
|
||||
attachments: ReadonlyArray<AttachmentType>;
|
||||
i18n: LocalizerType;
|
||||
onAddAttachment?: () => void;
|
||||
onClickAttachment?: (attachment: AttachmentType) => void;
|
||||
onClose?: () => void;
|
||||
onCloseAttachment: (attachment: AttachmentType) => void;
|
||||
};
|
||||
}>;
|
||||
|
||||
const IMAGE_WIDTH = 120;
|
||||
const IMAGE_HEIGHT = 120;
|
||||
|
|
|
@ -25,7 +25,7 @@ export type Props = {
|
|||
bodyRanges?: BodyRangesType;
|
||||
i18n: LocalizerType;
|
||||
isFromMe: boolean;
|
||||
isIncoming: boolean;
|
||||
isIncoming?: boolean;
|
||||
withContentAbove: boolean;
|
||||
onClick?: () => void;
|
||||
onClose?: () => void;
|
||||
|
@ -33,7 +33,7 @@ export type Props = {
|
|||
rawAttachment?: QuotedAttachmentType;
|
||||
isViewOnce: boolean;
|
||||
referencedMessageNotFound: boolean;
|
||||
doubleCheckMissingQuoteReference: () => unknown;
|
||||
doubleCheckMissingQuoteReference?: () => unknown;
|
||||
};
|
||||
|
||||
type State = {
|
||||
|
@ -133,7 +133,7 @@ export class Quote extends React.Component<Props, State> {
|
|||
} = this.props;
|
||||
|
||||
if (referencedMessageNotFound) {
|
||||
doubleCheckMissingQuoteReference();
|
||||
doubleCheckMissingQuoteReference?.();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ export type PropsDataType = {
|
|||
haveOldest: boolean;
|
||||
isLoadingMessages: boolean;
|
||||
isNearBottom?: boolean;
|
||||
items: Array<string>;
|
||||
items: ReadonlyArray<string>;
|
||||
loadCountdownStart?: number;
|
||||
messageHeightChangeIndex?: number;
|
||||
oldestUnreadIndex?: number;
|
||||
|
@ -104,7 +104,7 @@ type PropsHousekeepingType = {
|
|||
i18n: LocalizerType;
|
||||
|
||||
renderItem: (props: {
|
||||
actions: PropsActionsType;
|
||||
actionProps: PropsActionsType;
|
||||
containerElementRef: RefObject<HTMLElement>;
|
||||
conversationId: string;
|
||||
messageId: string;
|
||||
|
@ -804,7 +804,7 @@ export class Timeline extends React.PureComponent<PropsType, StateType> {
|
|||
const nextMessageId: undefined | string = items[itemIndex + 1];
|
||||
stableKey = messageId;
|
||||
|
||||
const actions = getActions(this.props);
|
||||
const actionProps = getActions(this.props);
|
||||
|
||||
rowContents = (
|
||||
<div
|
||||
|
@ -816,7 +816,7 @@ export class Timeline extends React.PureComponent<PropsType, StateType> {
|
|||
>
|
||||
<ErrorBoundary i18n={i18n} showDebugLog={() => window.showDebugLog()}>
|
||||
{renderItem({
|
||||
actions,
|
||||
actionProps,
|
||||
containerElementRef: this.containerRef,
|
||||
conversationId: id,
|
||||
messageId,
|
||||
|
|
|
@ -888,10 +888,19 @@ export const getConversationMessagesSelector = createSelector(
|
|||
conversationMessagesSelector: CachedConversationMessagesSelectorType,
|
||||
messagesByConversation: MessagesByConversationType
|
||||
) => {
|
||||
return (id: string): TimelinePropsType | undefined => {
|
||||
return (id: string): TimelinePropsType => {
|
||||
const conversation = messagesByConversation[id];
|
||||
if (!conversation) {
|
||||
return undefined;
|
||||
// TODO: DESKTOP-2340
|
||||
return {
|
||||
haveNewest: false,
|
||||
haveOldest: false,
|
||||
isLoadingMessages: false,
|
||||
resetCounter: 0,
|
||||
scrollToIndexCounter: 0,
|
||||
totalUnread: 0,
|
||||
items: [],
|
||||
};
|
||||
}
|
||||
|
||||
return conversationMessagesSelector(conversation);
|
||||
|
|
|
@ -7,6 +7,7 @@ import { mapDispatchToProps } from '../actions';
|
|||
import { CompositionArea } from '../../components/CompositionArea';
|
||||
import { StateType } from '../reducer';
|
||||
import { isConversationSMSOnly } from '../../util/isConversationSMSOnly';
|
||||
import { dropNull } from '../../util/dropNull';
|
||||
|
||||
import { selectRecentEmojis } from '../selectors/emojis';
|
||||
import { getIntl, getUserConversationId } from '../selectors/user';
|
||||
|
@ -60,9 +61,10 @@ const mapStateToProps = (state: StateType, props: ExternalProps) => {
|
|||
['showStickersIntroduction'],
|
||||
false
|
||||
);
|
||||
const showPickerHint =
|
||||
const showPickerHint = Boolean(
|
||||
get(state.items, ['showStickerPickerHint'], false) &&
|
||||
receivedPacks.length > 0;
|
||||
receivedPacks.length > 0
|
||||
);
|
||||
|
||||
const {
|
||||
attachments: draftAttachments,
|
||||
|
@ -77,8 +79,6 @@ const mapStateToProps = (state: StateType, props: ExternalProps) => {
|
|||
return {
|
||||
// Base
|
||||
i18n: getIntl(state),
|
||||
draftText,
|
||||
draftBodyRanges,
|
||||
// AttachmentsList
|
||||
draftAttachments,
|
||||
// MediaQualitySelector
|
||||
|
@ -123,6 +123,9 @@ const mapStateToProps = (state: StateType, props: ExternalProps) => {
|
|||
announcementsOnly,
|
||||
areWeAdmin,
|
||||
groupAdmins: getGroupAdminsSelector(state)(conversation.id),
|
||||
|
||||
draftText: dropNull(draftText),
|
||||
draftBodyRanges,
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -138,5 +141,4 @@ const dispatchPropsMap = {
|
|||
|
||||
const smart = connect(mapStateToProps, dispatchPropsMap);
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export const SmartCompositionArea = smart(CompositionArea as any);
|
||||
export const SmartCompositionArea = smart(CompositionArea);
|
||||
|
|
|
@ -8,11 +8,7 @@ import { GlobalModalContainer } from '../../components/GlobalModalContainer';
|
|||
import { StateType } from '../reducer';
|
||||
import { SmartProfileEditorModal } from './ProfileEditorModal';
|
||||
|
||||
// Workaround: A react component's required properties are filtering up through connect()
|
||||
// https://github.com/DefinitelyTyped/DefinitelyTyped/issues/31363
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
const FilteredSmartProfileEditorModal = SmartProfileEditorModal as any;
|
||||
/* eslint-enable @typescript-eslint/no-explicit-any */
|
||||
const FilteredSmartProfileEditorModal = SmartProfileEditorModal;
|
||||
|
||||
function renderProfileEditor(): JSX.Element {
|
||||
return <FilteredSmartProfileEditorModal />;
|
||||
|
|
|
@ -47,11 +47,7 @@ import { SmartRelinkDialog } from './RelinkDialog';
|
|||
import { SmartUpdateDialog } from './UpdateDialog';
|
||||
import { SmartCaptchaDialog } from './CaptchaDialog';
|
||||
|
||||
// Workaround: A react component's required properties are filtering up through connect()
|
||||
// https://github.com/DefinitelyTyped/DefinitelyTyped/issues/31363
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
const FilteredSmartMessageSearchResult = SmartMessageSearchResult as any;
|
||||
/* eslint-enable @typescript-eslint/no-explicit-any */
|
||||
const FilteredSmartMessageSearchResult = SmartMessageSearchResult;
|
||||
|
||||
function renderExpiredBuildDialog(): JSX.Element {
|
||||
return <SmartExpiredBuildDialog />;
|
||||
|
|
|
@ -13,7 +13,7 @@ import { getMessageSearchResultSelector } from '../selectors/search';
|
|||
|
||||
type SmartProps = {
|
||||
id: string;
|
||||
style: CSSProperties;
|
||||
style?: CSSProperties;
|
||||
};
|
||||
|
||||
function mapStateToProps(state: StateType, ourProps: SmartProps) {
|
||||
|
|
|
@ -16,7 +16,8 @@ import { selectRecentEmojis } from '../selectors/emojis';
|
|||
|
||||
function mapStateToProps(
|
||||
state: StateType
|
||||
): PropsDataType & ProfileEditorModalPropsType {
|
||||
): Omit<PropsDataType, 'onEditStateChange' | 'onProfileChanged'> &
|
||||
ProfileEditorModalPropsType {
|
||||
const {
|
||||
avatarPath,
|
||||
avatars: userAvatarData = [],
|
||||
|
|
|
@ -243,6 +243,7 @@ const mapStateToProps = (state: StateType, props: ExternalProps) => {
|
|||
const { id, ...actions } = props;
|
||||
|
||||
const conversation = getConversationSelector(state)(id);
|
||||
|
||||
const conversationMessages = getConversationMessagesSelector(state)(id);
|
||||
const selectedMessage = getSelectedMessage(state);
|
||||
|
||||
|
@ -279,5 +280,4 @@ const mapStateToProps = (state: StateType, props: ExternalProps) => {
|
|||
|
||||
const smart = connect(mapStateToProps, mapDispatchToProps);
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export const SmartTimeline = smart(Timeline as any);
|
||||
export const SmartTimeline = smart(Timeline);
|
||||
|
|
|
@ -26,11 +26,7 @@ type ExternalProps = {
|
|||
previousMessageId: undefined | string;
|
||||
};
|
||||
|
||||
// Workaround: A react component's required properties are filtering up through connect()
|
||||
// https://github.com/DefinitelyTyped/DefinitelyTyped/issues/31363
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
const FilteredSmartContactName = SmartContactName as any;
|
||||
/* eslint-enable @typescript-eslint/no-explicit-any */
|
||||
const FilteredSmartContactName = SmartContactName;
|
||||
|
||||
function renderContact(conversationId: string): JSX.Element {
|
||||
return <FilteredSmartContactName conversationId={conversationId} />;
|
||||
|
|
|
@ -575,7 +575,7 @@ export function getExtensionForDisplay({
|
|||
return undefined;
|
||||
}
|
||||
|
||||
export function isAudio(attachments?: Array<AttachmentType>): boolean {
|
||||
export function isAudio(attachments?: ReadonlyArray<AttachmentType>): boolean {
|
||||
return Boolean(
|
||||
attachments &&
|
||||
attachments[0] &&
|
||||
|
@ -585,7 +585,9 @@ export function isAudio(attachments?: Array<AttachmentType>): boolean {
|
|||
);
|
||||
}
|
||||
|
||||
export function canDisplayImage(attachments?: Array<AttachmentType>): boolean {
|
||||
export function canDisplayImage(
|
||||
attachments?: ReadonlyArray<AttachmentType>
|
||||
): boolean {
|
||||
const { height, width } =
|
||||
attachments && attachments[0] ? attachments[0] : { height: 0, width: 0 };
|
||||
|
||||
|
@ -617,7 +619,7 @@ export function getUrl(attachment: AttachmentType): string | undefined {
|
|||
return attachment.url;
|
||||
}
|
||||
|
||||
export function isImage(attachments?: Array<AttachmentType>): boolean {
|
||||
export function isImage(attachments?: ReadonlyArray<AttachmentType>): boolean {
|
||||
return Boolean(
|
||||
attachments &&
|
||||
attachments[0] &&
|
||||
|
@ -644,7 +646,7 @@ export function canBeTranscoded(
|
|||
);
|
||||
}
|
||||
|
||||
export function hasImage(attachments?: Array<AttachmentType>): boolean {
|
||||
export function hasImage(attachments?: ReadonlyArray<AttachmentType>): boolean {
|
||||
return Boolean(
|
||||
attachments &&
|
||||
attachments[0] &&
|
||||
|
@ -652,7 +654,7 @@ export function hasImage(attachments?: Array<AttachmentType>): boolean {
|
|||
);
|
||||
}
|
||||
|
||||
export function isVideo(attachments?: Array<AttachmentType>): boolean {
|
||||
export function isVideo(attachments?: ReadonlyArray<AttachmentType>): boolean {
|
||||
if (!attachments || attachments.length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
@ -732,7 +734,7 @@ export function getImageDimensions(
|
|||
}
|
||||
|
||||
export function areAllAttachmentsVisual(
|
||||
attachments?: Array<AttachmentType>
|
||||
attachments?: ReadonlyArray<AttachmentType>
|
||||
): boolean {
|
||||
if (!attachments) {
|
||||
return false;
|
||||
|
@ -750,7 +752,7 @@ export function areAllAttachmentsVisual(
|
|||
}
|
||||
|
||||
export function getGridDimensions(
|
||||
attachments?: Array<AttachmentType>
|
||||
attachments?: ReadonlyArray<AttachmentType>
|
||||
): null | DimensionsType {
|
||||
if (!attachments || !attachments.length) {
|
||||
return null;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue