Composer: Add silent post button and hide them on text (#5749)
This commit is contained in:
parent
440001b938
commit
7522a16188
@ -735,27 +735,26 @@ async function getFullChannelInfo(
|
||||
};
|
||||
}
|
||||
|
||||
export function updateChatMutedState({
|
||||
chat, isMuted, mutedUntil = 0,
|
||||
export function updateChatNotifySettings({
|
||||
chat, settings,
|
||||
}: {
|
||||
chat: ApiChat; isMuted?: boolean; mutedUntil?: number;
|
||||
chat: ApiChat; settings: Partial<ApiPeerNotifySettings>;
|
||||
}) {
|
||||
if (isMuted && !mutedUntil) {
|
||||
mutedUntil = MAX_INT_32;
|
||||
}
|
||||
invokeRequest(new GramJs.account.UpdateNotifySettings({
|
||||
peer: new GramJs.InputNotifyPeer({
|
||||
peer: buildInputPeer(chat.id, chat.accessHash),
|
||||
}),
|
||||
settings: new GramJs.InputPeerNotifySettings({ muteUntil: mutedUntil }),
|
||||
settings: new GramJs.InputPeerNotifySettings({
|
||||
muteUntil: settings.mutedUntil,
|
||||
showPreviews: settings.shouldShowPreviews,
|
||||
silent: settings.isSilentPosting,
|
||||
}),
|
||||
}));
|
||||
|
||||
sendApiUpdate({
|
||||
'@type': 'updateChatNotifySettings',
|
||||
chatId: chat.id,
|
||||
settings: {
|
||||
mutedUntil,
|
||||
},
|
||||
settings,
|
||||
});
|
||||
|
||||
void requestChatUpdate({
|
||||
|
||||
@ -1271,6 +1271,18 @@
|
||||
"AriaOpenBotMenu" = "Open bot menu";
|
||||
"AriaOpenSymbolMenu" = "Choose emoji, sticker or GIF";
|
||||
"AriaComposerOpenScheduled" = "Open scheduled messages";
|
||||
"AriaComposerBotKeyboard" = "Show bot keyboard";
|
||||
"AriaComposerSilentPostingEnable" = "Enable silent notifications.";
|
||||
"AriaComposerSilentPostingDisable" = "Disable silent notifications.";
|
||||
"ComposerSilentPostingEnabledTootlip" = "Subscribers will receive a silent notification.";
|
||||
"ComposerSilentPostingDisabledTootlip" = "Subscribers will be notified when you post.";
|
||||
"ComposerPlaceholder" = "Message";
|
||||
"ComposerPlaceholderBroadcast" = "Broadcast";
|
||||
"ComposerPlaceholderBroadcastSilent" = "Silent Broadcast";
|
||||
"ComposerPlaceholderTopic" = "Message in {topic}";
|
||||
"ComposerPlaceholderTopicGeneral" = "Message in General";
|
||||
"ComposerStoryPlaceholderLocked" = "Replies restricted";
|
||||
"ComposerPlaceholderNoText" = "Text not allowed";
|
||||
"AriaComposerCancelVoice" = "Cancel voice recording";
|
||||
"PreviewForwardedMessage_one" = "{count} forwarded message";
|
||||
"PreviewForwardedMessage_other" = "{count} forwarded messages";
|
||||
|
||||
@ -292,6 +292,24 @@
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.composer-action-buttons-container {
|
||||
width: auto;
|
||||
position: relative;
|
||||
|
||||
+ .AttachMenu {
|
||||
margin-left: var(--action-button-compact-fix);
|
||||
}
|
||||
}
|
||||
|
||||
.composer-action-buttons {
|
||||
display: flex;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: auto;
|
||||
width: auto;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.mobile-symbol-menu-button {
|
||||
@ -384,25 +402,32 @@
|
||||
}
|
||||
|
||||
.message-input-wrapper {
|
||||
--action-button-size: var(--base-height, 3.5rem);
|
||||
--action-button-compact-fix: -1rem;
|
||||
display: flex;
|
||||
|
||||
@media (max-width: 600px) {
|
||||
--action-button-size: 2.875rem;
|
||||
--action-button-compact-fix: -0.6875rem;
|
||||
}
|
||||
|
||||
.input-scroller {
|
||||
margin-right: 0.5rem;
|
||||
padding-right: 0.25rem;
|
||||
--_scroller-right-gap: calc((var(--action-button-size) + var(--action-button-compact-fix) - 0.125rem));
|
||||
margin-right: calc(-1 * var(--_scroller-right-gap));
|
||||
padding-right: var(--_scroller-right-gap);
|
||||
}
|
||||
|
||||
> .Spinner {
|
||||
align-self: center;
|
||||
--spinner-size: 1.5rem;
|
||||
margin-right: -0.5rem;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
> .AttachMenu > .Button,
|
||||
> .Button {
|
||||
.composer-action-button {
|
||||
flex-shrink: 0;
|
||||
background: none !important;
|
||||
width: var(--base-height, 3.5rem);
|
||||
height: var(--base-height, 3.5rem);
|
||||
width: var(--action-button-size);
|
||||
height: var(--action-button-size);
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
align-self: flex-end;
|
||||
@ -411,17 +436,8 @@
|
||||
color: var(--color-composer-button);
|
||||
}
|
||||
|
||||
+ .Button, + .AttachMenu {
|
||||
margin-left: -1rem;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
width: 2.875rem;
|
||||
height: 2.875rem;
|
||||
|
||||
+ .Button, + .AttachMenu {
|
||||
margin-left: -0.6875rem;
|
||||
}
|
||||
+ .composer-action-button {
|
||||
margin-left: var(--action-button-compact-fix);
|
||||
}
|
||||
|
||||
&.bot-menu {
|
||||
|
||||
@ -66,6 +66,7 @@ import {
|
||||
isSystemBot,
|
||||
isUserId,
|
||||
} from '../../global/helpers';
|
||||
import { getChatNotifySettings } from '../../global/helpers/notifications';
|
||||
import {
|
||||
selectBot,
|
||||
selectCanPlayAnimatedEmojis,
|
||||
@ -86,6 +87,8 @@ import {
|
||||
selectIsReactionPickerOpen,
|
||||
selectIsRightColumnShown,
|
||||
selectNewestMessageWithBotKeyboardButtons,
|
||||
selectNotifyDefaults,
|
||||
selectNotifyException,
|
||||
selectNoWebPage,
|
||||
selectPeerStory,
|
||||
selectPerformanceSettingsValue,
|
||||
@ -126,6 +129,7 @@ import useDerivedState from '../../hooks/useDerivedState';
|
||||
import useEffectWithPrevDeps from '../../hooks/useEffectWithPrevDeps';
|
||||
import useFlag from '../../hooks/useFlag';
|
||||
import useGetSelectionRange from '../../hooks/useGetSelectionRange';
|
||||
import useLang from '../../hooks/useLang';
|
||||
import useLastCallback from '../../hooks/useLastCallback';
|
||||
import useOldLang from '../../hooks/useOldLang';
|
||||
import usePreviousDeprecated from '../../hooks/usePreviousDeprecated';
|
||||
@ -170,6 +174,7 @@ import ReactionSelector from '../middle/message/reactions/ReactionSelector';
|
||||
import Button from '../ui/Button';
|
||||
import ResponsiveHoverButton from '../ui/ResponsiveHoverButton';
|
||||
import Spinner from '../ui/Spinner';
|
||||
import Transition from '../ui/Transition';
|
||||
import Avatar from './Avatar';
|
||||
import Icon from './icons/Icon';
|
||||
import ReactionAnimatedEmoji from './reactions/ReactionAnimatedEmoji';
|
||||
@ -272,6 +277,7 @@ type StateProps =
|
||||
canPlayEffect?: boolean;
|
||||
shouldPlayEffect?: boolean;
|
||||
maxMessageLength: number;
|
||||
isSilentPosting?: boolean;
|
||||
};
|
||||
|
||||
enum MainButtonState {
|
||||
@ -304,9 +310,6 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
canScheduleUntilOnline,
|
||||
isReady,
|
||||
isMobile,
|
||||
onDropHide,
|
||||
onFocus,
|
||||
onBlur,
|
||||
editingMessage,
|
||||
chatId,
|
||||
threadId,
|
||||
@ -376,7 +379,6 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
quickReplyMessages,
|
||||
quickReplies,
|
||||
canSendQuickReplies,
|
||||
onForward,
|
||||
webPagePreview,
|
||||
noWebPage,
|
||||
isContactRequirePremium,
|
||||
@ -386,6 +388,11 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
canPlayEffect,
|
||||
shouldPlayEffect,
|
||||
maxMessageLength,
|
||||
isSilentPosting,
|
||||
onDropHide,
|
||||
onFocus,
|
||||
onBlur,
|
||||
onForward,
|
||||
}) => {
|
||||
const {
|
||||
sendMessage,
|
||||
@ -412,9 +419,11 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
saveEffectInDraft,
|
||||
setReactionEffect,
|
||||
hideEffectInComposer,
|
||||
updateChatSilentPosting,
|
||||
} = getActions();
|
||||
|
||||
const lang = useOldLang();
|
||||
const oldLang = useOldLang();
|
||||
const lang = useLang();
|
||||
|
||||
// eslint-disable-next-line no-null/no-null
|
||||
const inputRef = useRef<HTMLDivElement>(null);
|
||||
@ -785,21 +794,21 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
const notificationNumber = customEmojiNotificationNumber.current;
|
||||
if (!notificationNumber) {
|
||||
showNotification({
|
||||
message: lang('UnlockPremiumEmojiHint'),
|
||||
message: oldLang('UnlockPremiumEmojiHint'),
|
||||
action: {
|
||||
action: 'openPremiumModal',
|
||||
payload: { initialSection: 'animated_emoji' },
|
||||
},
|
||||
actionText: lang('PremiumMore'),
|
||||
actionText: oldLang('PremiumMore'),
|
||||
});
|
||||
} else {
|
||||
showNotification({
|
||||
message: lang('UnlockPremiumEmojiHint2'),
|
||||
message: oldLang('UnlockPremiumEmojiHint2'),
|
||||
action: {
|
||||
action: 'openChat',
|
||||
payload: { id: currentUserId, shouldReplaceHistory: true },
|
||||
},
|
||||
actionText: lang('Open'),
|
||||
actionText: oldLang('Open'),
|
||||
});
|
||||
}
|
||||
customEmojiNotificationNumber.current = Number(!notificationNumber);
|
||||
@ -910,7 +919,7 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
: slowMode.seconds - secondsSinceLastMessage!;
|
||||
showDialog({
|
||||
data: {
|
||||
message: lang('SlowModeHint', formatMediaDuration(secondsRemaining)),
|
||||
message: oldLang('SlowModeHint', formatMediaDuration(secondsRemaining)),
|
||||
isSlowMode: true,
|
||||
hasErrorKey: false,
|
||||
},
|
||||
@ -942,6 +951,7 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
if (!currentMessageList && !storyId) {
|
||||
return;
|
||||
}
|
||||
isSilent = isSilent || isSilentPosting;
|
||||
|
||||
const { text, entities } = parseHtmlAsFormattedText(getHtml());
|
||||
if (!text && !attachmentsToSend.length) {
|
||||
@ -1018,6 +1028,8 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
return;
|
||||
}
|
||||
|
||||
isSilent = isSilent || isSilentPosting;
|
||||
|
||||
let currentAttachments = attachments;
|
||||
|
||||
if (activeVoiceRecording) {
|
||||
@ -1129,7 +1141,7 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
threadId,
|
||||
queryId,
|
||||
scheduledAt,
|
||||
isSilent,
|
||||
isSilent: isSilent || isSilentPosting,
|
||||
});
|
||||
return;
|
||||
}
|
||||
@ -1197,6 +1209,8 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
return;
|
||||
}
|
||||
|
||||
isSilent = isSilent || isSilentPosting;
|
||||
|
||||
if (isInScheduledList || isScheduleRequested) {
|
||||
forceShowSymbolMenu();
|
||||
requestCalendar((scheduledAt) => {
|
||||
@ -1225,6 +1239,8 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
return;
|
||||
}
|
||||
|
||||
isSilent = isSilent || isSilentPosting;
|
||||
|
||||
sticker = {
|
||||
...sticker,
|
||||
isPreloadedGlobally: true,
|
||||
@ -1261,6 +1277,8 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
return;
|
||||
}
|
||||
|
||||
isSilent = isSilent || isSilentPosting;
|
||||
|
||||
if (isInScheduledList || isScheduleRequested) {
|
||||
requestCalendar((scheduledAt) => {
|
||||
handleMessageSchedule({
|
||||
@ -1308,7 +1326,7 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
});
|
||||
closePollModal();
|
||||
} else {
|
||||
sendMessage({ messageList: currentMessageList, poll });
|
||||
sendMessage({ messageList: currentMessageList, poll, isSilent: isSilentPosting });
|
||||
closePollModal();
|
||||
}
|
||||
});
|
||||
@ -1378,6 +1396,17 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
});
|
||||
});
|
||||
|
||||
const handleToggleSilentPosting = useLastCallback(() => {
|
||||
const newValue = !isSilentPosting;
|
||||
updateChatSilentPosting({ chatId, isEnabled: newValue });
|
||||
|
||||
showNotification({
|
||||
localId: 'silentPosting',
|
||||
icon: newValue ? 'mute' : 'unmute',
|
||||
message: lang(`ComposerSilentPosting${newValue ? 'Enabled' : 'Disabled'}Tootlip`),
|
||||
});
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (isRightColumnShown && isMobile) {
|
||||
closeSymbolMenu();
|
||||
@ -1396,10 +1425,11 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
}
|
||||
}, [isSelectModeActive, enableHover, disableHover, isReady]);
|
||||
|
||||
const withBotMenuButton = isChatWithBot && botMenuButton?.type === 'webApp' && !editingMessage;
|
||||
const isBotMenuButtonOpen = useDerivedState(() => {
|
||||
return withBotMenuButton && !getHtml() && !activeVoiceRecording;
|
||||
}, [withBotMenuButton, getHtml, activeVoiceRecording]);
|
||||
const hasText = useDerivedState(() => Boolean(getHtml()), [getHtml]);
|
||||
|
||||
const withBotMenuButton = isChatWithBot && botMenuButton?.type === 'webApp' && !editingMessage
|
||||
&& messageListType === 'thread';
|
||||
const isBotMenuButtonOpen = withBotMenuButton && !hasText && !activeVoiceRecording;
|
||||
|
||||
const [timedPlaceholderLangKey, timedPlaceholderDate] = useMemo(() => {
|
||||
if (slowMode?.nextSendDate) {
|
||||
@ -1419,11 +1449,33 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
|| isCustomSendMenuOpen || Boolean(activeVoiceRecording) || attachments.length > 0 || isInputHasFocus;
|
||||
const isReactionSelectorOpen = isComposerHasFocus && !isReactionPickerOpen && isInStoryViewer && !isAttachMenuOpen
|
||||
&& !isSymbolMenuOpen;
|
||||
const placeholderForForumAsMessages = chat?.isForum && chat?.isForumAsMessages && threadId === MAIN_THREAD_ID
|
||||
? (replyToTopic
|
||||
? lang('Chat.InputPlaceholderReplyInTopic', replyToTopic.title)
|
||||
: lang('Message.Placeholder.MessageInGeneral'))
|
||||
: undefined;
|
||||
|
||||
const placeholder = useMemo(() => {
|
||||
if (activeVoiceRecording && windowWidth <= SCREEN_WIDTH_TO_HIDE_PLACEHOLDER) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (!isComposerBlocked) {
|
||||
if (botKeyboardPlaceholder) return botKeyboardPlaceholder;
|
||||
if (inputPlaceholder) return inputPlaceholder;
|
||||
if (chat?.isForum && chat?.isForumAsMessages && threadId === MAIN_THREAD_ID) {
|
||||
return replyToTopic
|
||||
? lang('ComposerPlaceholderTopic', { topic: replyToTopic.title })
|
||||
: lang('ComposerPlaceholderTopicGeneral');
|
||||
}
|
||||
if (isChannel) {
|
||||
return lang(isSilentPosting ? 'ComposerPlaceholderBroadcastSilent' : 'ComposerPlaceholderBroadcast');
|
||||
}
|
||||
return lang('ComposerPlaceholder');
|
||||
}
|
||||
|
||||
if (isInStoryViewer) return lang('ComposerStoryPlaceholderLocked');
|
||||
|
||||
return lang('ComposerPlaceholderNoText');
|
||||
}, [
|
||||
activeVoiceRecording, botKeyboardPlaceholder, chat, inputPlaceholder, isChannel, isComposerBlocked,
|
||||
isInStoryViewer, isSilentPosting, lang, replyToTopic, threadId, windowWidth,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isComposerHasFocus) {
|
||||
@ -1452,7 +1504,7 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
if (areVoiceMessagesNotAllowed) {
|
||||
if (!canSendVoiceByPrivacy) {
|
||||
showNotification({
|
||||
message: lang('VoiceMessagesRestrictedByPrivacy', chat?.title),
|
||||
message: oldLang('VoiceMessagesRestrictedByPrivacy', chat?.title),
|
||||
});
|
||||
} else if (!canSendVoices) {
|
||||
showAllowedMessageTypesNotification({ chatId });
|
||||
@ -1788,9 +1840,10 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
round
|
||||
color="translucent"
|
||||
onClick={isSendAsMenuOpen ? closeSendAsMenu : handleSendAsMenuOpen}
|
||||
ariaLabel={lang('SendMessageAsTitle')}
|
||||
ariaLabel={oldLang('SendMessageAsTitle')}
|
||||
className={buildClassName(
|
||||
'send-as-button',
|
||||
'composer-action-button',
|
||||
shouldAnimateSendAsButtonRef.current && 'appear-animation',
|
||||
)}
|
||||
>
|
||||
@ -1840,13 +1893,7 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
isReady={isReady}
|
||||
isActive={!hasAttachments}
|
||||
getHtml={getHtml}
|
||||
placeholder={
|
||||
activeVoiceRecording && windowWidth <= SCREEN_WIDTH_TO_HIDE_PLACEHOLDER
|
||||
? ''
|
||||
: (!isComposerBlocked
|
||||
? (botKeyboardPlaceholder || inputPlaceholder || lang(placeholderForForumAsMessages || 'Message'))
|
||||
: isInStoryViewer ? lang('StoryRepliesLocked') : lang('Chat.PlaceholderTextNotAllowed'))
|
||||
}
|
||||
placeholder={placeholder}
|
||||
timedPlaceholderDate={timedPlaceholderDate}
|
||||
timedPlaceholderLangKey={timedPlaceholderLangKey}
|
||||
forcedPlaceholder={inlineBotHelp}
|
||||
@ -1866,29 +1913,55 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
{isInlineBotLoading && Boolean(inlineBotId) && (
|
||||
<Spinner color="gray" />
|
||||
)}
|
||||
{withScheduledButton && (
|
||||
<Button
|
||||
round
|
||||
faded
|
||||
className="scheduled-button"
|
||||
color="translucent"
|
||||
onClick={handleAllScheduledClick}
|
||||
ariaLabel="Open scheduled messages"
|
||||
>
|
||||
<Icon name="schedule" />
|
||||
</Button>
|
||||
)}
|
||||
{Boolean(botKeyboardMessageId) && !activeVoiceRecording && !editingMessage && (
|
||||
<ResponsiveHoverButton
|
||||
className={isBotKeyboardOpen ? 'activated' : ''}
|
||||
round
|
||||
color="translucent"
|
||||
onActivate={openBotKeyboard}
|
||||
ariaLabel="Open bot command keyboard"
|
||||
>
|
||||
<Icon name="bot-command" />
|
||||
</ResponsiveHoverButton>
|
||||
)}
|
||||
<Transition
|
||||
className="composer-action-buttons-container"
|
||||
slideClassName="composer-action-buttons"
|
||||
activeKey={Number(hasText)}
|
||||
direction="inverse"
|
||||
name="slideFadeAndroid"
|
||||
>
|
||||
{!hasText && (
|
||||
<>
|
||||
{isChannel && (
|
||||
<Button
|
||||
round
|
||||
faded
|
||||
className="composer-action-button"
|
||||
color="translucent"
|
||||
onClick={handleToggleSilentPosting}
|
||||
ariaLabel={lang(
|
||||
isSilentPosting ? 'AriaComposerSilentPostingDisable' : 'AriaComposerSilentPostingEnable',
|
||||
)}
|
||||
>
|
||||
<Icon name={isSilentPosting ? 'mute' : 'unmute'} />
|
||||
</Button>
|
||||
)}
|
||||
{withScheduledButton && (
|
||||
<Button
|
||||
round
|
||||
faded
|
||||
className="composer-action-button scheduled-button"
|
||||
color="translucent"
|
||||
onClick={handleAllScheduledClick}
|
||||
ariaLabel={lang('AriaComposerOpenScheduled')}
|
||||
>
|
||||
<Icon name="schedule" />
|
||||
</Button>
|
||||
)}
|
||||
{Boolean(botKeyboardMessageId) && !activeVoiceRecording && !editingMessage && (
|
||||
<ResponsiveHoverButton
|
||||
className={buildClassName('composer-action-button', isBotKeyboardOpen && 'activated')}
|
||||
round
|
||||
color="translucent"
|
||||
onActivate={openBotKeyboard}
|
||||
ariaLabel={lang('AriaComposerBotKeyboard')}
|
||||
>
|
||||
<Icon name="bot-command" />
|
||||
</ResponsiveHoverButton>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</Transition>
|
||||
</>
|
||||
)}
|
||||
{activeVoiceRecording && Boolean(currentRecordTime) && (
|
||||
@ -1968,7 +2041,7 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
className={buildClassName('view-once', isViewOnceEnabled && 'active')}
|
||||
round
|
||||
color="secondary"
|
||||
ariaLabel={lang('Chat.PlayOnceVoiceMessageTooltip')}
|
||||
ariaLabel={oldLang('Chat.PlayOnceVoiceMessageTooltip')}
|
||||
onClick={toogleViewOnceEnabled}
|
||||
>
|
||||
<Icon name="view-once" />
|
||||
@ -1994,7 +2067,7 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
onClick={handleLikeStory}
|
||||
onContextMenu={handleStoryPickerContextMenu}
|
||||
onMouseDown={handleBeforeStoryPickerContextMenu}
|
||||
ariaLabel={lang('AccDescrLike')}
|
||||
ariaLabel={oldLang('AccDescrLike')}
|
||||
ref={storyReactionRef}
|
||||
>
|
||||
{sentStoryReaction && (
|
||||
@ -2023,7 +2096,7 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
disabled={areVoiceMessagesNotAllowed}
|
||||
allowDisabledClick
|
||||
noFastClick
|
||||
ariaLabel={lang(sendButtonAriaLabel)}
|
||||
ariaLabel={oldLang(sendButtonAriaLabel)}
|
||||
onClick={mainButtonHandler}
|
||||
onContextMenu={
|
||||
mainButtonState === MainButtonState.Send && canShowCustomSendMenu ? handleContextMenu : undefined
|
||||
@ -2140,6 +2213,11 @@ export default memo(withGlobal<OwnProps>(
|
||||
const canSendQuickReplies = isChatWithUser && !isChatWithBot && !isInScheduledList && !isChatWithSelf;
|
||||
|
||||
const noWebPage = selectNoWebPage(global, chatId, threadId);
|
||||
const isSilentPosting = chat && getChatNotifySettings(
|
||||
chat,
|
||||
selectNotifyDefaults(global),
|
||||
selectNotifyException(global, chatId),
|
||||
)?.isSilentPosting;
|
||||
|
||||
const areEffectsSupported = isChatWithUser && !isChatWithBot
|
||||
&& !isInScheduledList && !isChatWithSelf && type !== 'story' && chatId !== SERVICE_NOTIFICATIONS_USER_ID;
|
||||
@ -2227,6 +2305,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
canPlayEffect,
|
||||
shouldPlayEffect,
|
||||
maxMessageLength,
|
||||
isSilentPosting,
|
||||
};
|
||||
},
|
||||
)(Composer));
|
||||
|
||||
@ -20,6 +20,7 @@ import {
|
||||
getMessageWebPagePhoto,
|
||||
getMessageWebPageVideo,
|
||||
} from '../../../global/helpers';
|
||||
import buildClassName from '../../../util/buildClassName';
|
||||
import { getDebugLogs } from '../../../util/debugConsole';
|
||||
import { validateFiles } from '../../../util/files';
|
||||
import { openSystemFilesDialog } from '../../../util/systemFilesDialog';
|
||||
@ -175,7 +176,7 @@ const AttachMenu: FC<OwnProps> = ({
|
||||
editingMessage && canEditMedia ? (
|
||||
<ResponsiveHoverButton
|
||||
id="replace-menu-button"
|
||||
className={isAttachMenuOpen ? 'AttachMenu--button activated' : 'AttachMenu--button'}
|
||||
className={buildClassName('AttachMenu--button composer-action-button', isAttachMenuOpen && 'activated')}
|
||||
round
|
||||
color="translucent"
|
||||
onActivate={handleToggleAttachMenu}
|
||||
@ -189,7 +190,7 @@ const AttachMenu: FC<OwnProps> = ({
|
||||
<ResponsiveHoverButton
|
||||
id="attach-menu-button"
|
||||
disabled={Boolean(editingMessage)}
|
||||
className={isAttachMenuOpen ? 'AttachMenu--button activated' : 'AttachMenu--button'}
|
||||
className={buildClassName('AttachMenu--button composer-action-button', isAttachMenuOpen && 'activated')}
|
||||
round
|
||||
color="translucent"
|
||||
onActivate={handleToggleAttachMenu}
|
||||
|
||||
@ -46,7 +46,7 @@ const BotMenuButton: FC<OwnProps> = ({
|
||||
|
||||
return (
|
||||
<Button
|
||||
className={buildClassName('bot-menu', isOpen && 'open')}
|
||||
className={buildClassName('composer-action-button bot-menu', isOpen && 'open')}
|
||||
round
|
||||
color="translucent"
|
||||
disabled={isDisabled}
|
||||
|
||||
@ -92,7 +92,7 @@ const SymbolMenuButton: FC<OwnProps> = ({
|
||||
const [contextMenuAnchor, setContextMenuAnchor] = useState<IAnchorPosition | undefined>(undefined);
|
||||
|
||||
const symbolMenuButtonClassName = buildClassName(
|
||||
'mobile-symbol-menu-button',
|
||||
'composer-action-button mobile-symbol-menu-button',
|
||||
!isReady && 'not-ready',
|
||||
isSymbolMenuLoaded
|
||||
? (isSymbolMenuOpen && 'menu-opened')
|
||||
@ -157,7 +157,7 @@ const SymbolMenuButton: FC<OwnProps> = ({
|
||||
</Button>
|
||||
) : (
|
||||
<ResponsiveHoverButton
|
||||
className={buildClassName('symbol-menu-button', isSymbolMenuOpen && 'activated')}
|
||||
className={buildClassName('composer-action-button symbol-menu-button', isSymbolMenuOpen && 'activated')}
|
||||
round
|
||||
color="translucent"
|
||||
onActivate={handleActivateSymbolMenu}
|
||||
|
||||
@ -23,6 +23,7 @@ import {
|
||||
CHAT_LIST_LOAD_SLICE,
|
||||
DEBUG,
|
||||
GLOBAL_SUGGESTED_CHANNELS_ID,
|
||||
MAX_INT_32,
|
||||
RE_TG_LINK,
|
||||
SAVED_FOLDER_ID,
|
||||
SERVICE_NOTIFICATIONS_USER_ID,
|
||||
@ -625,13 +626,29 @@ addActionHandler('requestSavedDialogUpdate', async (global, actions, payload): P
|
||||
});
|
||||
|
||||
addActionHandler('updateChatMutedState', (global, actions, payload): ActionReturnType => {
|
||||
const { chatId, isMuted, mutedUntil } = payload;
|
||||
const { chatId, isMuted } = payload;
|
||||
let { mutedUntil } = payload;
|
||||
|
||||
const chat = selectChat(global, chatId);
|
||||
if (!chat) {
|
||||
return;
|
||||
}
|
||||
if (isMuted && !mutedUntil) {
|
||||
mutedUntil = MAX_INT_32;
|
||||
}
|
||||
|
||||
void callApi('updateChatNotifySettings', { chat, settings: { mutedUntil } });
|
||||
});
|
||||
|
||||
addActionHandler('updateChatSilentPosting', (global, actions, payload): ActionReturnType => {
|
||||
const { chatId, isEnabled } = payload;
|
||||
|
||||
const chat = selectChat(global, chatId);
|
||||
if (!chat) {
|
||||
return;
|
||||
}
|
||||
|
||||
void callApi('updateChatMutedState', { chat, isMuted, mutedUntil });
|
||||
void callApi('updateChatNotifySettings', { chat, settings: { isSilentPosting: isEnabled } });
|
||||
});
|
||||
|
||||
addActionHandler('updateTopicMutedState', (global, actions, payload): ActionReturnType => {
|
||||
|
||||
@ -1051,6 +1051,10 @@ export interface ActionPayloads {
|
||||
isMuted?: boolean;
|
||||
mutedUntil?: number;
|
||||
};
|
||||
updateChatSilentPosting: {
|
||||
chatId: string;
|
||||
isEnabled: boolean;
|
||||
};
|
||||
|
||||
updateChat: {
|
||||
chatId: string;
|
||||
|
||||
14
src/types/language.d.ts
vendored
14
src/types/language.d.ts
vendored
@ -1087,6 +1087,17 @@ export interface LangPair {
|
||||
'AriaOpenBotMenu': undefined;
|
||||
'AriaOpenSymbolMenu': undefined;
|
||||
'AriaComposerOpenScheduled': undefined;
|
||||
'AriaComposerBotKeyboard': undefined;
|
||||
'AriaComposerSilentPostingEnable': undefined;
|
||||
'AriaComposerSilentPostingDisable': undefined;
|
||||
'ComposerSilentPostingEnabledTootlip': undefined;
|
||||
'ComposerSilentPostingDisabledTootlip': undefined;
|
||||
'ComposerPlaceholder': undefined;
|
||||
'ComposerPlaceholderBroadcast': undefined;
|
||||
'ComposerPlaceholderBroadcastSilent': undefined;
|
||||
'ComposerPlaceholderTopicGeneral': undefined;
|
||||
'ComposerStoryPlaceholderLocked': undefined;
|
||||
'ComposerPlaceholderNoText': undefined;
|
||||
'AriaComposerCancelVoice': undefined;
|
||||
'PreviewEditMessage': undefined;
|
||||
'FileDropZoneTitle': undefined;
|
||||
@ -1706,6 +1717,9 @@ export interface LangPairWithVariables<V extends unknown = LangVariable> {
|
||||
'MediaViewDownloading': {
|
||||
'count': V;
|
||||
};
|
||||
'ComposerPlaceholderTopic': {
|
||||
'topic': V;
|
||||
};
|
||||
'ChannelManagementLinkDiscussion': {
|
||||
'group': V;
|
||||
'channel': V;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user