Composer / Embedded Message: Fix edit and reply (#2372)
This commit is contained in:
parent
8d4e447981
commit
55a9715bca
@ -54,6 +54,7 @@ import {
|
||||
selectChatType,
|
||||
selectRequestedDraftFiles,
|
||||
selectTabState,
|
||||
selectReplyingToId,
|
||||
} from '../../../global/selectors';
|
||||
import {
|
||||
getAllowedAttachmentOptions,
|
||||
@ -145,6 +146,7 @@ type StateProps =
|
||||
isChatWithBot?: boolean;
|
||||
isChatWithSelf?: boolean;
|
||||
isChannel?: boolean;
|
||||
replyingToId?: number;
|
||||
isForCurrentMessageList: boolean;
|
||||
isRightColumnShown?: boolean;
|
||||
isSelectModeActive?: boolean;
|
||||
@ -260,6 +262,7 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
sendAsChat,
|
||||
sendAsId,
|
||||
editingDraft,
|
||||
replyingToId,
|
||||
requestedDraftText,
|
||||
requestedDraftFiles,
|
||||
botMenuButton,
|
||||
@ -394,12 +397,6 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
sendMessageAction({ type: 'typing' });
|
||||
}, [editingMessage, html, sendMessageAction]);
|
||||
|
||||
const mainButtonState = editingMessage ? MainButtonState.Edit
|
||||
: (!IS_VOICE_RECORDING_SUPPORTED || activeVoiceRecording || (html && !attachments.length) || isForwarding)
|
||||
? (shouldSchedule ? MainButtonState.Schedule : MainButtonState.Send)
|
||||
: MainButtonState.Record;
|
||||
const canShowCustomSendMenu = !shouldSchedule;
|
||||
|
||||
const {
|
||||
isMentionTooltipOpen, closeMentionTooltip, insertMention, mentionFilteredUsers,
|
||||
} = useMentionTooltip(
|
||||
@ -438,13 +435,6 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
chatBotCommands,
|
||||
);
|
||||
|
||||
const {
|
||||
isContextMenuOpen: isCustomSendMenuOpen,
|
||||
handleContextMenu,
|
||||
handleContextMenuClose,
|
||||
handleContextMenuHide,
|
||||
} = useContextMenuHandlers(mainButtonRef, !(mainButtonState === MainButtonState.Send && canShowCustomSendMenu));
|
||||
|
||||
const {
|
||||
canSendStickers, canSendGifs, canAttachMedia, canAttachPolls, canAttachEmbedLinks,
|
||||
} = useMemo(() => getAllowedAttachmentOptions(chat, isChatWithBot), [chat, isChatWithBot]);
|
||||
@ -597,7 +587,7 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
customEmojiNotificationNumber.current = Number(!notificationNumber);
|
||||
}, [currentUserId, lang, showNotification]);
|
||||
|
||||
const [handleEditComplete, handleEditCancel] = useEditing(
|
||||
const [handleEditComplete, handleEditCancel, shouldForceShowEditing] = useEditing(
|
||||
htmlRef,
|
||||
setHtml,
|
||||
editingMessage,
|
||||
@ -608,7 +598,36 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
messageListType,
|
||||
draft,
|
||||
editingDraft,
|
||||
replyingToId,
|
||||
);
|
||||
|
||||
const mainButtonState = useMemo(() => {
|
||||
if (editingMessage && shouldForceShowEditing) {
|
||||
return MainButtonState.Edit;
|
||||
}
|
||||
|
||||
if (IS_VOICE_RECORDING_SUPPORTED && !activeVoiceRecording && !(html && !attachments.length) && !isForwarding) {
|
||||
return MainButtonState.Record;
|
||||
}
|
||||
|
||||
if (shouldSchedule) {
|
||||
return MainButtonState.Schedule;
|
||||
}
|
||||
|
||||
return MainButtonState.Send;
|
||||
}, [
|
||||
activeVoiceRecording, attachments.length, editingMessage, html, isForwarding, shouldForceShowEditing,
|
||||
shouldSchedule,
|
||||
]);
|
||||
const canShowCustomSendMenu = !shouldSchedule;
|
||||
|
||||
const {
|
||||
isContextMenuOpen: isCustomSendMenuOpen,
|
||||
handleContextMenu,
|
||||
handleContextMenuClose,
|
||||
handleContextMenuHide,
|
||||
} = useContextMenuHandlers(mainButtonRef, !(mainButtonState === MainButtonState.Send && canShowCustomSendMenu));
|
||||
|
||||
useDraft(draft, chatId, threadId, htmlRef, setHtml, editingMessage, lastSyncTime);
|
||||
useClipboardPaste(
|
||||
isForCurrentMessageList,
|
||||
@ -1264,7 +1283,10 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
/>
|
||||
<div id="message-compose">
|
||||
<div className="svg-appendix" ref={appendixRef} />
|
||||
<ComposerEmbeddedMessage onClear={handleEmbeddedClear} />
|
||||
<ComposerEmbeddedMessage
|
||||
onClear={handleEmbeddedClear}
|
||||
shouldForceShowEditing={Boolean(shouldForceShowEditing && editingMessage)}
|
||||
/>
|
||||
<WebPagePreview
|
||||
chatId={chatId}
|
||||
threadId={threadId}
|
||||
@ -1529,11 +1551,14 @@ export default memo(withGlobal<OwnProps>(
|
||||
? selectEditingScheduledDraft(global, chatId)
|
||||
: selectEditingDraft(global, chatId, threadId);
|
||||
|
||||
const replyingToId = selectReplyingToId(global, chatId, threadId);
|
||||
|
||||
const tabState = selectTabState(global);
|
||||
|
||||
return {
|
||||
editingMessage: selectEditingMessage(global, chatId, threadId, messageListType),
|
||||
connectionState: global.connectionState,
|
||||
replyingToId,
|
||||
draft: selectDraft(global, chatId, threadId),
|
||||
chat,
|
||||
isChatWithBot,
|
||||
|
||||
@ -54,6 +54,7 @@ type StateProps = {
|
||||
|
||||
type OwnProps = {
|
||||
onClear?: () => void;
|
||||
shouldForceShowEditing?: boolean;
|
||||
};
|
||||
|
||||
const FORWARD_RENDERING_DELAY = 300;
|
||||
@ -68,6 +69,7 @@ const ComposerEmbeddedMessage: FC<OwnProps & StateProps> = ({
|
||||
noAuthors,
|
||||
noCaptions,
|
||||
forwardsHaveCaptions,
|
||||
shouldForceShowEditing,
|
||||
isCurrentUserPremium,
|
||||
onClear,
|
||||
}) => {
|
||||
@ -99,7 +101,7 @@ const ComposerEmbeddedMessage: FC<OwnProps & StateProps> = ({
|
||||
} = useShowTransition(canAnimate && isShown, undefined, !shouldAnimate, undefined, !shouldAnimate);
|
||||
|
||||
const clearEmbedded = useCallback(() => {
|
||||
if (replyingToId) {
|
||||
if (replyingToId && !shouldForceShowEditing) {
|
||||
setReplyingToId({ messageId: undefined });
|
||||
} else if (editingId) {
|
||||
setEditingId({ messageId: undefined });
|
||||
@ -107,7 +109,10 @@ const ComposerEmbeddedMessage: FC<OwnProps & StateProps> = ({
|
||||
exitForwardMode();
|
||||
}
|
||||
onClear?.();
|
||||
}, [replyingToId, editingId, forwardedMessagesCount, onClear, setReplyingToId, setEditingId, exitForwardMode]);
|
||||
}, [
|
||||
replyingToId, shouldForceShowEditing, editingId, forwardedMessagesCount, onClear, setReplyingToId, setEditingId,
|
||||
exitForwardMode,
|
||||
]);
|
||||
|
||||
useEffect(() => (isShown ? captureEscKeyListener(clearEmbedded) : undefined), [isShown, clearEmbedded]);
|
||||
|
||||
@ -146,7 +151,7 @@ const ComposerEmbeddedMessage: FC<OwnProps & StateProps> = ({
|
||||
const className = buildClassName('ComposerEmbeddedMessage', transitionClassNames);
|
||||
|
||||
const leftIcon = useMemo(() => {
|
||||
if (replyingToId) {
|
||||
if (replyingToId && !shouldForceShowEditing) {
|
||||
return 'icon-reply';
|
||||
}
|
||||
if (editingId) {
|
||||
@ -157,7 +162,7 @@ const ComposerEmbeddedMessage: FC<OwnProps & StateProps> = ({
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}, [editingId, isForwarding, replyingToId]);
|
||||
}, [editingId, isForwarding, replyingToId, shouldForceShowEditing]);
|
||||
|
||||
const customText = forwardedMessagesCount && forwardedMessagesCount > 1
|
||||
? lang('ForwardedMessageCount', forwardedMessagesCount)
|
||||
@ -274,7 +279,7 @@ const ComposerEmbeddedMessage: FC<OwnProps & StateProps> = ({
|
||||
};
|
||||
|
||||
export default memo(withGlobal<OwnProps>(
|
||||
(global): StateProps => {
|
||||
(global, { shouldForceShowEditing }): StateProps => {
|
||||
const { chatId, threadId, type: messageListType } = selectCurrentMessageList(global) || {};
|
||||
if (!chatId || !threadId || !messageListType) {
|
||||
return {};
|
||||
@ -295,7 +300,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
const forwardedMessages = forwardMessageIds?.map((id) => selectChatMessage(global, fromChatId!, id)!);
|
||||
|
||||
let message: ApiMessage | undefined;
|
||||
if (replyingToId) {
|
||||
if (replyingToId && !shouldForceShowEditing) {
|
||||
message = selectChatMessage(global, chatId, replyingToId);
|
||||
} else if (editingId) {
|
||||
message = selectEditingMessage(global, chatId, threadId, messageListType);
|
||||
@ -304,7 +309,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
}
|
||||
|
||||
let sender: ApiChat | ApiUser | undefined;
|
||||
if (replyingToId && message) {
|
||||
if (replyingToId && message && !shouldForceShowEditing) {
|
||||
const { forwardInfo } = message;
|
||||
const isChatWithSelf = selectIsChatWithSelf(global, chatId);
|
||||
if (forwardInfo && (forwardInfo.isChannelPost || isChatWithSelf)) {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useCallback, useEffect } from '../../../../lib/teact/teact';
|
||||
import { useCallback, useEffect, useState } from '../../../../lib/teact/teact';
|
||||
import { getActions } from '../../../../global';
|
||||
|
||||
import type { ApiFormattedText, ApiMessage } from '../../../../api/types';
|
||||
@ -25,19 +25,30 @@ const useEditing = (
|
||||
type: MessageListType,
|
||||
draft?: ApiFormattedText,
|
||||
editingDraft?: ApiFormattedText,
|
||||
) => {
|
||||
replyingToId?: number,
|
||||
): [VoidFunction, VoidFunction, boolean] => {
|
||||
const { editMessage, setEditingDraft } = getActions();
|
||||
const [shouldForceShowEditing, setShouldForceShowEditing] = useState<boolean>();
|
||||
|
||||
useEffectWithPrevDeps(([prevEditedMessage]) => {
|
||||
useEffectWithPrevDeps(([prevEditedMessage, prevReplyingToId]) => {
|
||||
if (!editedMessage) {
|
||||
return;
|
||||
}
|
||||
if (prevEditedMessage?.id === editedMessage.id) {
|
||||
|
||||
if (replyingToId && prevReplyingToId !== replyingToId) {
|
||||
setHtml('');
|
||||
setShouldForceShowEditing(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (prevEditedMessage?.id === editedMessage.id && replyingToId === prevReplyingToId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const text = !prevEditedMessage && editingDraft?.text.length ? editingDraft : editedMessage.content.text;
|
||||
const html = getTextWithEntitiesAsHtml(text);
|
||||
setHtml(html);
|
||||
setShouldForceShowEditing(true);
|
||||
// `fastRaf` would execute syncronously in this case
|
||||
requestAnimationFrame(() => {
|
||||
const messageInput = document.querySelector<HTMLDivElement>(EDITABLE_INPUT_CSS_SELECTOR);
|
||||
@ -45,7 +56,7 @@ const useEditing = (
|
||||
focusEditableElement(messageInput, true);
|
||||
}
|
||||
});
|
||||
}, [editedMessage, setHtml] as const);
|
||||
}, [editedMessage, replyingToId, setHtml] as const);
|
||||
|
||||
useEffect(() => {
|
||||
if (!editedMessage) return undefined;
|
||||
@ -111,7 +122,7 @@ const useEditing = (
|
||||
useBackgroundMode(handleBlur);
|
||||
useBeforeUnload(handleBlur);
|
||||
|
||||
return [handleEditComplete, handleEditCancel];
|
||||
return [handleEditComplete, handleEditCancel, shouldForceShowEditing];
|
||||
};
|
||||
|
||||
export default useEditing;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user