Composer: Redesign Embedded, support forwarding options (#1935)
This commit is contained in:
parent
f43a2bd57f
commit
7735be21ba
@ -1196,6 +1196,8 @@ export function buildLocalForwardedMessage(
|
||||
message: ApiMessage,
|
||||
serverTimeOffset: number,
|
||||
scheduledAt?: number,
|
||||
noAuthor?: boolean,
|
||||
noCaption?: boolean,
|
||||
): ApiMessage {
|
||||
const localId = getNextLocalMessageId();
|
||||
const {
|
||||
@ -1211,11 +1213,16 @@ export function buildLocalForwardedMessage(
|
||||
const asIncomingInChatWithSelf = (
|
||||
toChat.id === currentUserId && (fromChatId !== toChat.id || message.forwardInfo) && !isAudio
|
||||
);
|
||||
const shouldHideText = Object.keys(content).length > 1 && content.text && noCaption;
|
||||
const updatedContent = {
|
||||
...content,
|
||||
text: !shouldHideText ? content.text : undefined,
|
||||
};
|
||||
|
||||
return {
|
||||
id: localId,
|
||||
chatId: toChat.id,
|
||||
content,
|
||||
content: updatedContent,
|
||||
date: scheduledAt || Math.round(Date.now() / 1000) + serverTimeOffset,
|
||||
isOutgoing: !asIncomingInChatWithSelf && toChat.type !== 'chatTypeChannel',
|
||||
senderId: currentUserId,
|
||||
@ -1223,7 +1230,7 @@ export function buildLocalForwardedMessage(
|
||||
groupedId,
|
||||
isInAlbum,
|
||||
// Forward info doesn't get added when users forwards his own messages, also when forwarding audio
|
||||
...(senderId !== currentUserId && !isAudio && {
|
||||
...(senderId !== currentUserId && !isAudio && !noAuthor && {
|
||||
forwardInfo: {
|
||||
date: message.date,
|
||||
isChannelPost: false,
|
||||
|
||||
@ -1126,6 +1126,8 @@ export async function forwardMessages({
|
||||
scheduledAt,
|
||||
sendAs,
|
||||
withMyScore,
|
||||
noAuthors,
|
||||
noCaptions,
|
||||
}: {
|
||||
fromChat: ApiChat;
|
||||
toChat: ApiChat;
|
||||
@ -1135,12 +1137,16 @@ export async function forwardMessages({
|
||||
scheduledAt?: number;
|
||||
sendAs?: ApiUser | ApiChat;
|
||||
withMyScore?: boolean;
|
||||
noAuthors?: boolean;
|
||||
noCaptions?: boolean;
|
||||
}) {
|
||||
const messageIds = messages.map(({ id }) => id);
|
||||
const randomIds = messages.map(generateRandomBigInt);
|
||||
|
||||
messages.forEach((message, index) => {
|
||||
const localMessage = buildLocalForwardedMessage(toChat, message, serverTimeOffset, scheduledAt);
|
||||
const localMessage = buildLocalForwardedMessage(
|
||||
toChat, message, serverTimeOffset, scheduledAt, noAuthors, noCaptions,
|
||||
);
|
||||
localDb.localMessages[String(randomIds[index])] = localMessage;
|
||||
|
||||
onUpdate({
|
||||
@ -1158,6 +1164,8 @@ export async function forwardMessages({
|
||||
id: messageIds,
|
||||
withMyScore: withMyScore || undefined,
|
||||
silent: isSilent || undefined,
|
||||
dropAuthor: noAuthors || undefined,
|
||||
dropMediaCaptions: noCaptions || undefined,
|
||||
...(scheduledAt && { scheduleDate: scheduledAt }),
|
||||
...(sendAs && { sendAs: buildInputPeer(sendAs.id, sendAs.accessHash) }),
|
||||
}), true);
|
||||
|
||||
@ -125,13 +125,10 @@
|
||||
|
||||
&.inside-input {
|
||||
padding-inline-start: 0.5625rem;
|
||||
margin: 0 0 -0.125rem -0.1875rem;
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
grid-template-rows: 1fr;
|
||||
width: 100%;
|
||||
--accent-color: var(--color-primary);
|
||||
--hover-color: var(--color-interactive-element-hover);
|
||||
--active-color: var(--color-reply-active);
|
||||
|
||||
&::before {
|
||||
bottom: 0.3125rem;
|
||||
@ -143,11 +140,18 @@
|
||||
|
||||
.message-text {
|
||||
margin-inline-start: 0.375rem;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.message-title {
|
||||
font-weight: 500;
|
||||
color: var(--accent-color);
|
||||
}
|
||||
|
||||
.embedded-more {
|
||||
font-size: 1.5rem;
|
||||
opacity: 0.8;
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -33,6 +33,7 @@ type OwnProps = {
|
||||
customText?: string;
|
||||
noUserColors?: boolean;
|
||||
isProtected?: boolean;
|
||||
hasContextMenu?: boolean;
|
||||
onClick: NoneToVoidFunction;
|
||||
};
|
||||
|
||||
@ -46,6 +47,7 @@ const EmbeddedMessage: FC<OwnProps> = ({
|
||||
customText,
|
||||
isProtected,
|
||||
noUserColors,
|
||||
hasContextMenu,
|
||||
observeIntersection,
|
||||
onClick,
|
||||
}) => {
|
||||
@ -84,6 +86,7 @@ const EmbeddedMessage: FC<OwnProps> = ({
|
||||
</p>
|
||||
<div className="message-title" dir="auto">{renderText(senderTitle || title || NBSP)}</div>
|
||||
</div>
|
||||
{hasContextMenu && <i className="embedded-more icon-more" />}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@ -202,8 +202,8 @@ const MediaViewer: FC<StateProps> = ({
|
||||
|
||||
const handleForward = useCallback(() => {
|
||||
openForwardMenu({
|
||||
fromChatId: chatId,
|
||||
messageIds: [mediaId],
|
||||
fromChatId: chatId!,
|
||||
messageIds: [mediaId!],
|
||||
});
|
||||
}, [openForwardMenu, chatId, mediaId]);
|
||||
|
||||
|
||||
@ -22,17 +22,46 @@
|
||||
padding-top: 0.1875rem;
|
||||
}
|
||||
|
||||
& > div > .Button {
|
||||
& .embedded-left-icon {
|
||||
flex-shrink: 0;
|
||||
background: none !important;
|
||||
width: 3.5rem;
|
||||
height: 2.875rem;
|
||||
margin: 0 -0.0625rem 0 0;
|
||||
padding: 0;
|
||||
align-self: center;
|
||||
display: grid;
|
||||
place-content: center;
|
||||
font-size: 1.5rem;
|
||||
color: var(--color-primary);
|
||||
|
||||
@media (max-width: 600px) {
|
||||
width: 2.875rem;
|
||||
}
|
||||
}
|
||||
|
||||
& .embedded-cancel {
|
||||
flex-shrink: 0;
|
||||
background: none !important;
|
||||
width: 2.25rem;
|
||||
height: 2.875rem;
|
||||
margin: 0 -0.0625rem 0 0.75rem;
|
||||
padding: 0;
|
||||
align-self: center;
|
||||
|
||||
@media (max-width: 600px) {
|
||||
width: 1.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
.forward-context-menu {
|
||||
position: absolute;
|
||||
|
||||
.bubble {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.icon-placeholder {
|
||||
width: 1.25rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import type { FC } from '../../../lib/teact/teact';
|
||||
import React, { memo, useCallback, useEffect } from '../../../lib/teact/teact';
|
||||
import React, {
|
||||
memo, useCallback, useEffect, useMemo, useRef,
|
||||
} from '../../../lib/teact/teact';
|
||||
import { getActions, withGlobal } from '../../../global';
|
||||
|
||||
import type { FC } from '../../../lib/teact/teact';
|
||||
import type { ApiChat, ApiMessage, ApiUser } from '../../../api/types';
|
||||
|
||||
import {
|
||||
@ -23,9 +25,15 @@ import { isUserId } from '../../../global/helpers';
|
||||
|
||||
import useAsyncRendering from '../../right/hooks/useAsyncRendering';
|
||||
import useShowTransition from '../../../hooks/useShowTransition';
|
||||
import useLang from '../../../hooks/useLang';
|
||||
import useContextMenuHandlers from '../../../hooks/useContextMenuHandlers';
|
||||
import useContextMenuPosition from '../../../hooks/useContextMenuPosition';
|
||||
|
||||
import Button from '../../ui/Button';
|
||||
import EmbeddedMessage from '../../common/EmbeddedMessage';
|
||||
import MenuItem from '../../ui/MenuItem';
|
||||
import Menu from '../../ui/Menu';
|
||||
import MenuSeparator from '../../ui/MenuSeparator';
|
||||
|
||||
import './ComposerEmbeddedMessage.scss';
|
||||
|
||||
@ -36,6 +44,9 @@ type StateProps = {
|
||||
sender?: ApiUser | ApiChat;
|
||||
shouldAnimate?: boolean;
|
||||
forwardedMessagesCount?: number;
|
||||
noAuthors?: boolean;
|
||||
noCaptions?: boolean;
|
||||
forwardsHaveCaptions?: boolean;
|
||||
};
|
||||
|
||||
type OwnProps = {
|
||||
@ -51,15 +62,25 @@ const ComposerEmbeddedMessage: FC<OwnProps & StateProps> = ({
|
||||
sender,
|
||||
shouldAnimate,
|
||||
forwardedMessagesCount,
|
||||
noAuthors,
|
||||
noCaptions,
|
||||
forwardsHaveCaptions,
|
||||
onClear,
|
||||
}) => {
|
||||
const {
|
||||
setReplyingToId,
|
||||
setEditingId,
|
||||
focusMessage,
|
||||
changeForwardRecipient,
|
||||
setForwardNoAuthors,
|
||||
setForwardNoCaptions,
|
||||
exitForwardMode,
|
||||
} = getActions();
|
||||
// eslint-disable-next-line no-null/no-null
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
const lang = useLang();
|
||||
|
||||
const isForwarding = Boolean(forwardedMessagesCount);
|
||||
const isShown = Boolean(
|
||||
((replyingToId || editingId) && message)
|
||||
|| (sender && forwardedMessagesCount),
|
||||
@ -87,13 +108,55 @@ const ComposerEmbeddedMessage: FC<OwnProps & StateProps> = ({
|
||||
useEffect(() => (isShown ? captureEscKeyListener(clearEmbedded) : undefined), [isShown, clearEmbedded]);
|
||||
|
||||
const handleMessageClick = useCallback((): void => {
|
||||
if (isForwarding) return;
|
||||
focusMessage({ chatId: message!.chatId, messageId: message!.id });
|
||||
}, [focusMessage, message]);
|
||||
}, [focusMessage, isForwarding, message]);
|
||||
|
||||
const handleClearClick = useCallback((e: React.MouseEvent<HTMLButtonElement, MouseEvent>): void => {
|
||||
e.stopPropagation();
|
||||
clearEmbedded();
|
||||
}, [clearEmbedded]);
|
||||
|
||||
const handleChangeRecipientClick = useCallback(() => {
|
||||
changeForwardRecipient();
|
||||
}, [changeForwardRecipient]);
|
||||
|
||||
const {
|
||||
isContextMenuOpen, contextMenuPosition, handleContextMenu,
|
||||
handleContextMenuClose, handleContextMenuHide,
|
||||
} = useContextMenuHandlers(ref);
|
||||
|
||||
const getTriggerElement = useCallback(() => ref.current, []);
|
||||
const getRootElement = useCallback(() => ref.current!, []);
|
||||
const getMenuElement = useCallback(() => ref.current!.querySelector('.forward-context-menu .bubble'), []);
|
||||
|
||||
const {
|
||||
positionX, positionY, transformOriginX, transformOriginY, style: menuStyle,
|
||||
} = useContextMenuPosition(
|
||||
contextMenuPosition,
|
||||
getTriggerElement,
|
||||
getRootElement,
|
||||
getMenuElement,
|
||||
);
|
||||
|
||||
const className = buildClassName('ComposerEmbeddedMessage', transitionClassNames);
|
||||
|
||||
const leftIcon = useMemo(() => {
|
||||
if (replyingToId) {
|
||||
return 'icon-reply';
|
||||
}
|
||||
if (editingId) {
|
||||
return 'icon-edit';
|
||||
}
|
||||
if (isForwarding) {
|
||||
return 'icon-forward';
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}, [editingId, isForwarding, replyingToId]);
|
||||
|
||||
const customText = forwardedMessagesCount && forwardedMessagesCount > 1
|
||||
? `${forwardedMessagesCount} forwarded messages`
|
||||
? lang('ForwardedMessageCount', forwardedMessagesCount)
|
||||
: undefined;
|
||||
|
||||
if (!shouldRender) {
|
||||
@ -101,19 +164,85 @@ const ComposerEmbeddedMessage: FC<OwnProps & StateProps> = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
<div className={className} ref={ref} onContextMenu={handleContextMenu} onClick={handleContextMenu}>
|
||||
<div>
|
||||
<Button round faded color="translucent" ariaLabel="Cancel replying" onClick={clearEmbedded}>
|
||||
<i className="icon-close" />
|
||||
</Button>
|
||||
<div className="embedded-left-icon">
|
||||
<i className={leftIcon} />
|
||||
</div>
|
||||
<EmbeddedMessage
|
||||
className="inside-input"
|
||||
message={message}
|
||||
sender={sender}
|
||||
sender={!noAuthors ? sender : undefined}
|
||||
customText={customText}
|
||||
title={editingId ? 'Edit Message' : undefined}
|
||||
title={editingId ? lang('EditMessage') : noAuthors ? lang('HiddenSendersNameDescription') : undefined}
|
||||
onClick={handleMessageClick}
|
||||
hasContextMenu={isForwarding}
|
||||
/>
|
||||
<Button
|
||||
className="embedded-cancel"
|
||||
round
|
||||
faded
|
||||
color="translucent"
|
||||
ariaLabel={lang('Cancel')}
|
||||
onClick={handleClearClick}
|
||||
>
|
||||
<i className="icon-close" />
|
||||
</Button>
|
||||
{isForwarding && (
|
||||
<Menu
|
||||
isOpen={isContextMenuOpen}
|
||||
transformOriginX={transformOriginX}
|
||||
transformOriginY={transformOriginY}
|
||||
positionX={positionX}
|
||||
positionY={positionY}
|
||||
style={menuStyle}
|
||||
className="forward-context-menu"
|
||||
onClose={handleContextMenuClose}
|
||||
onCloseAnimationEnd={handleContextMenuHide}
|
||||
>
|
||||
<MenuItem
|
||||
icon={!noAuthors ? 'message-succeeded' : undefined}
|
||||
customIcon={noAuthors ? <i className="icon-placeholder" /> : undefined}
|
||||
// eslint-disable-next-line react/jsx-no-bind
|
||||
onClick={() => setForwardNoAuthors(false)}
|
||||
>
|
||||
{lang(forwardedMessagesCount > 1 ? 'ShowSenderNames' : 'ShowSendersName')}
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
icon={noAuthors ? 'message-succeeded' : undefined}
|
||||
customIcon={!noAuthors ? <i className="icon-placeholder" /> : undefined}
|
||||
// eslint-disable-next-line react/jsx-no-bind
|
||||
onClick={() => setForwardNoAuthors(true)}
|
||||
>
|
||||
{lang(forwardedMessagesCount > 1 ? 'HideSenderNames' : 'HideSendersName')}
|
||||
</MenuItem>
|
||||
{forwardsHaveCaptions && (
|
||||
<>
|
||||
<MenuSeparator />
|
||||
<MenuItem
|
||||
icon={!noCaptions ? 'message-succeeded' : undefined}
|
||||
customIcon={noCaptions ? <i className="icon-placeholder" /> : undefined}
|
||||
// eslint-disable-next-line react/jsx-no-bind
|
||||
onClick={() => setForwardNoCaptions(false)}
|
||||
>
|
||||
{lang(forwardedMessagesCount > 1 ? 'Conversation.ForwardOptions.ShowCaption' : 'ShowCaption')}
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
icon={noCaptions ? 'message-succeeded' : undefined}
|
||||
customIcon={!noCaptions ? <i className="icon-placeholder" /> : undefined}
|
||||
// eslint-disable-next-line react/jsx-no-bind
|
||||
onClick={() => setForwardNoCaptions(true)}
|
||||
>
|
||||
{lang(forwardedMessagesCount > 1 ? 'Conversation.ForwardOptions.HideCaption' : 'HideCaption')}
|
||||
</MenuItem>
|
||||
</>
|
||||
)}
|
||||
<MenuSeparator />
|
||||
<MenuItem icon="replace" onClick={handleChangeRecipientClick}>
|
||||
{lang('ChangeRecipient')}
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@ -127,7 +256,9 @@ export default memo(withGlobal<OwnProps>(
|
||||
}
|
||||
|
||||
const {
|
||||
forwardMessages: { fromChatId, toChatId, messageIds: forwardMessageIds },
|
||||
forwardMessages: {
|
||||
fromChatId, toChatId, messageIds: forwardMessageIds, noAuthors, noCaptions,
|
||||
},
|
||||
} = global;
|
||||
|
||||
const replyingToId = selectReplyingToId(global, chatId, threadId);
|
||||
@ -136,14 +267,15 @@ export default memo(withGlobal<OwnProps>(
|
||||
: selectEditingId(global, chatId, threadId);
|
||||
const shouldAnimate = global.settings.byKey.animationLevel >= 1;
|
||||
const isForwarding = toChatId === chatId;
|
||||
const forwardedMessages = forwardMessageIds?.map((id) => selectChatMessage(global, fromChatId!, id)!);
|
||||
|
||||
let message;
|
||||
let message: ApiMessage | undefined;
|
||||
if (replyingToId) {
|
||||
message = selectChatMessage(global, chatId, replyingToId);
|
||||
} else if (editingId) {
|
||||
message = selectEditingMessage(global, chatId, threadId, messageListType);
|
||||
} else if (isForwarding && forwardMessageIds!.length === 1) {
|
||||
message = selectChatMessage(global, fromChatId!, forwardMessageIds![0]);
|
||||
message = forwardedMessages?.[0];
|
||||
}
|
||||
|
||||
let sender: ApiChat | ApiUser | undefined;
|
||||
@ -169,6 +301,10 @@ export default memo(withGlobal<OwnProps>(
|
||||
}
|
||||
}
|
||||
|
||||
const forwardsHaveCaptions = forwardedMessages?.some((forward) => (
|
||||
forward?.content.text && Object.keys(forward.content).length > 1
|
||||
));
|
||||
|
||||
return {
|
||||
replyingToId,
|
||||
editingId,
|
||||
@ -176,6 +312,9 @@ export default memo(withGlobal<OwnProps>(
|
||||
sender,
|
||||
shouldAnimate,
|
||||
forwardedMessagesCount: isForwarding ? forwardMessageIds!.length : undefined,
|
||||
noAuthors,
|
||||
noCaptions,
|
||||
forwardsHaveCaptions,
|
||||
};
|
||||
},
|
||||
)(ComposerEmbeddedMessage));
|
||||
|
||||
@ -29,24 +29,42 @@
|
||||
margin-top: 0.75rem;
|
||||
}
|
||||
|
||||
& > div > .Button {
|
||||
& &-left-icon {
|
||||
flex-shrink: 0;
|
||||
background: none !important;
|
||||
width: 3.5rem;
|
||||
height: 2.875rem;
|
||||
margin: 0 -0.0625rem 0 0;
|
||||
padding: 0;
|
||||
align-self: center;
|
||||
display: grid;
|
||||
place-content: center;
|
||||
font-size: 1.5rem;
|
||||
color: var(--color-primary);
|
||||
|
||||
@media (max-width: 600px) {
|
||||
width: 2.875rem;
|
||||
}
|
||||
}
|
||||
|
||||
& &-clear {
|
||||
flex-shrink: 0;
|
||||
background: none !important;
|
||||
width: 2.25rem;
|
||||
height: 2.875rem;
|
||||
margin: 0 -0.0625rem 0 0;
|
||||
padding: 0;
|
||||
align-self: center;
|
||||
|
||||
@media (max-width: 600px) {
|
||||
width: 1.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
.WebPage {
|
||||
flex-grow: 1;
|
||||
margin: 0.1875rem 0 0.1875rem 0.125rem;
|
||||
max-width: calc(100% - 3.375rem);
|
||||
overflow: hidden;
|
||||
|
||||
&::before {
|
||||
top: 0.125rem;
|
||||
|
||||
@ -105,10 +105,20 @@ const WebPagePreview: FC<OwnProps & StateProps> = ({
|
||||
return (
|
||||
<div className={buildClassName('WebPagePreview', transitionClassNames)}>
|
||||
<div>
|
||||
<Button round faded color="translucent" ariaLabel="Clear Webpage Preview" onClick={handleClearWebpagePreview}>
|
||||
<div className="WebPagePreview-left-icon">
|
||||
<i className="icon-link" />
|
||||
</div>
|
||||
<WebPage message={messageStub} inPreview theme={theme} />
|
||||
<Button
|
||||
className="WebPagePreview-clear"
|
||||
round
|
||||
faded
|
||||
color="translucent"
|
||||
ariaLabel="Clear Webpage Preview"
|
||||
onClick={handleClearWebpagePreview}
|
||||
>
|
||||
<i className="icon-close" />
|
||||
</Button>
|
||||
<WebPage message={messageStub} inPreview theme={theme} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
6
src/components/ui/MenuSeparator.module.scss
Normal file
6
src/components/ui/MenuSeparator.module.scss
Normal file
@ -0,0 +1,6 @@
|
||||
.root {
|
||||
margin: 0.25rem 1rem;
|
||||
height: 1px;
|
||||
border-radius: 1px;
|
||||
background-color: var(--color-interactive-inactive);
|
||||
}
|
||||
19
src/components/ui/MenuSeparator.tsx
Normal file
19
src/components/ui/MenuSeparator.tsx
Normal file
@ -0,0 +1,19 @@
|
||||
import React from '../../lib/teact/teact';
|
||||
|
||||
import type { FC } from '../../lib/teact/teact';
|
||||
|
||||
import buildClassName from '../../util/buildClassName';
|
||||
|
||||
import styles from './MenuSeparator.module.scss';
|
||||
|
||||
type OwnProps = {
|
||||
className?: string;
|
||||
};
|
||||
|
||||
const MenuSeparator: FC<OwnProps> = ({ className }) => {
|
||||
return (
|
||||
<div className={buildClassName(styles.root, className)} />
|
||||
);
|
||||
};
|
||||
|
||||
export default MenuSeparator;
|
||||
@ -602,7 +602,7 @@ addActionHandler('loadPollOptionResults', (global, actions, payload) => {
|
||||
|
||||
addActionHandler('forwardMessages', (global, action, payload) => {
|
||||
const {
|
||||
fromChatId, messageIds, toChatId, withMyScore,
|
||||
fromChatId, messageIds, toChatId, withMyScore, noAuthors, noCaptions,
|
||||
} = global.forwardMessages;
|
||||
const fromChat = fromChatId ? selectChat(global, fromChatId) : undefined;
|
||||
const toChat = toChatId ? selectChat(global, toChatId) : undefined;
|
||||
@ -630,6 +630,8 @@ addActionHandler('forwardMessages', (global, action, payload) => {
|
||||
scheduledAt,
|
||||
sendAs,
|
||||
withMyScore,
|
||||
noAuthors,
|
||||
noCaptions,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -413,7 +413,7 @@ addActionHandler('focusMessage', (global, actions, payload) => {
|
||||
addActionHandler('openForwardMenu', (global, actions, payload) => {
|
||||
const {
|
||||
fromChatId, messageIds, groupedId, withMyScore,
|
||||
} = payload!;
|
||||
} = payload;
|
||||
let groupedMessageIds;
|
||||
if (groupedId) {
|
||||
groupedMessageIds = selectMessageIdsByGroupId(global, fromChatId, groupedId);
|
||||
@ -429,6 +429,41 @@ addActionHandler('openForwardMenu', (global, actions, payload) => {
|
||||
};
|
||||
});
|
||||
|
||||
addActionHandler('changeForwardRecipient', (global) => {
|
||||
return {
|
||||
...global,
|
||||
forwardMessages: {
|
||||
...global.forwardMessages,
|
||||
toChatId: undefined,
|
||||
isModalShown: true,
|
||||
noAuthors: false,
|
||||
noCaptions: false,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
addActionHandler('setForwardNoAuthors', (global, actions, payload) => {
|
||||
return {
|
||||
...global,
|
||||
forwardMessages: {
|
||||
...global.forwardMessages,
|
||||
noAuthors: payload,
|
||||
noCaptions: payload && global.forwardMessages.noCaptions, // `noCaptions` cannot be true when `noAuthors` is false
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
addActionHandler('setForwardNoCaptions', (global, actions, payload) => {
|
||||
return {
|
||||
...global,
|
||||
forwardMessages: {
|
||||
...global.forwardMessages,
|
||||
noCaptions: payload,
|
||||
noAuthors: payload, // On other clients `noAuthors` updates together with `noCaptions`
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
addActionHandler('exitForwardMode', (global) => {
|
||||
setGlobal({
|
||||
...global,
|
||||
@ -437,7 +472,7 @@ addActionHandler('exitForwardMode', (global) => {
|
||||
});
|
||||
|
||||
addActionHandler('setForwardChatId', (global, actions, payload) => {
|
||||
const { id } = payload!;
|
||||
const { id } = payload;
|
||||
|
||||
setGlobal({
|
||||
...global,
|
||||
|
||||
@ -437,6 +437,8 @@ export type GlobalState = {
|
||||
messageIds?: number[];
|
||||
toChatId?: string;
|
||||
withMyScore?: boolean;
|
||||
noAuthors?: boolean;
|
||||
noCaptions?: boolean;
|
||||
};
|
||||
|
||||
pollResults: {
|
||||
@ -824,6 +826,26 @@ export interface ActionPayloads {
|
||||
shouldSharePhoneNumber?: boolean;
|
||||
};
|
||||
|
||||
// Forwards
|
||||
openForwardMenu: {
|
||||
fromChatId: string;
|
||||
messageIds?: number[];
|
||||
groupedId?: string;
|
||||
withMyScore?: boolean;
|
||||
};
|
||||
openForwardMenuForSelectedMessages: never;
|
||||
setForwardChatId: {
|
||||
id: string;
|
||||
};
|
||||
forwardMessages: {
|
||||
isSilent?: boolean;
|
||||
scheduledAt?: number;
|
||||
};
|
||||
setForwardNoAuthors: boolean;
|
||||
setForwardNoCaptions: boolean;
|
||||
exitForwardMode: never;
|
||||
changeForwardRecipient: never;
|
||||
|
||||
// Stickers
|
||||
addRecentSticker: {
|
||||
sticker: ApiSticker;
|
||||
@ -1097,9 +1119,6 @@ export type NonTypedActionNames = (
|
||||
'loadScheduledHistory' | 'sendScheduledMessages' | 'rescheduleMessage' | 'deleteScheduledMessages' |
|
||||
// poll result
|
||||
'openPollResults' | 'closePollResults' | 'loadPollOptionResults' |
|
||||
// forwarding messages
|
||||
'openForwardMenu' | 'exitForwardMode' | 'setForwardChatId' | 'forwardMessages' |
|
||||
'openForwardMenuForSelectedMessages' |
|
||||
// global search
|
||||
'setGlobalSearchQuery' | 'searchMessagesGlobal' | 'addRecentlyFoundChatId' | 'clearRecentlyFoundChats' |
|
||||
'setGlobalSearchContent' | 'setGlobalSearchChatId' | 'setGlobalSearchDate' |
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user