Fix action propagation to timeline items

This commit is contained in:
Fedor Indutny 2021-09-12 19:36:41 -07:00 committed by GitHub
parent 9ffa29ca0d
commit 5a57e2b704
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 71 additions and 66 deletions

View file

@ -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,

View file

@ -23,7 +23,7 @@ type PropsType = {
toggleProfileEditor: () => unknown;
toggleProfileEditorHasError: () => unknown;
} & PropsDataType &
ProfileEditorPropsType;
Omit<ProfileEditorPropsType, 'onEditStateChanged' | 'onProfileChanged'>;
export const ProfileEditorModal = ({
hasError,

View file

@ -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;

View file

@ -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?.();
}
}

View file

@ -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,

View file

@ -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);

View file

@ -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);

View file

@ -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 />;

View file

@ -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 />;

View file

@ -13,7 +13,7 @@ import { getMessageSearchResultSelector } from '../selectors/search';
type SmartProps = {
id: string;
style: CSSProperties;
style?: CSSProperties;
};
function mapStateToProps(state: StateType, ourProps: SmartProps) {

View file

@ -16,7 +16,8 @@ import { selectRecentEmojis } from '../selectors/emojis';
function mapStateToProps(
state: StateType
): PropsDataType & ProfileEditorModalPropsType {
): Omit<PropsDataType, 'onEditStateChange' | 'onProfileChanged'> &
ProfileEditorModalPropsType {
const {
avatarPath,
avatars: userAvatarData = [],

View file

@ -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);

View file

@ -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} />;

View file

@ -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;