User: Add 'Block' option to menu (#3877)

This commit is contained in:
Alexander Zinchuk 2023-09-25 13:00:12 +02:00
parent bcb1a7ae26
commit 548430bd2e
3 changed files with 86 additions and 17 deletions

View File

@ -57,6 +57,7 @@ interface StateProps {
isRightColumnShown?: boolean; isRightColumnShown?: boolean;
canStartBot?: boolean; canStartBot?: boolean;
canRestartBot?: boolean; canRestartBot?: boolean;
canUnblock?: boolean;
canSubscribe?: boolean; canSubscribe?: boolean;
canSearch?: boolean; canSearch?: boolean;
canCall?: boolean; canCall?: boolean;
@ -88,6 +89,7 @@ const HeaderActions: FC<OwnProps & StateProps> = ({
isChannel, isChannel,
canStartBot, canStartBot,
canRestartBot, canRestartBot,
canUnblock,
canSubscribe, canSubscribe,
canSearch, canSearch,
canCall, canCall,
@ -124,6 +126,7 @@ const HeaderActions: FC<OwnProps & StateProps> = ({
togglePeerTranslations, togglePeerTranslations,
openChatLanguageModal, openChatLanguageModal,
setSettingOption, setSettingOption,
unblockUser,
} = getActions(); } = getActions();
// eslint-disable-next-line no-null/no-null // eslint-disable-next-line no-null/no-null
const menuButtonRef = useRef<HTMLButtonElement>(null); const menuButtonRef = useRef<HTMLButtonElement>(null);
@ -162,6 +165,10 @@ const HeaderActions: FC<OwnProps & StateProps> = ({
restartBot({ chatId }); restartBot({ chatId });
}); });
const handleUnblock = useLastCallback(() => {
unblockUser({ userId: chatId });
});
const handleTranslateClick = useLastCallback(() => { const handleTranslateClick = useLastCallback(() => {
if (isTranslating) { if (isTranslating) {
requestChatTranslation({ chatId, toLanguageCode: undefined }); requestChatTranslation({ chatId, toLanguageCode: undefined });
@ -341,6 +348,16 @@ const HeaderActions: FC<OwnProps & StateProps> = ({
{lang('BotRestart')} {lang('BotRestart')}
</Button> </Button>
)} )}
{canExpandActions && canUnblock && (
<Button
size="tiny"
ripple
fluid
onClick={handleUnblock}
>
{lang('Unblock')}
</Button>
)}
{canSearch && ( {canSearch && (
<Button <Button
round round
@ -403,7 +420,6 @@ const HeaderActions: FC<OwnProps & StateProps> = ({
withExtraActions={isMobile || !canExpandActions} withExtraActions={isMobile || !canExpandActions}
isChannel={isChannel} isChannel={isChannel}
canStartBot={canStartBot} canStartBot={canStartBot}
canRestartBot={canRestartBot}
canSubscribe={canSubscribe} canSubscribe={canSubscribe}
canSearch={canSearch} canSearch={canSearch}
canCall={canCall} canCall={canCall}
@ -434,6 +450,7 @@ export default memo(withGlobal<OwnProps>(
const isChannel = Boolean(chat && isChatChannel(chat)); const isChannel = Boolean(chat && isChatChannel(chat));
const language = selectLanguageCode(global); const language = selectLanguageCode(global);
const translationLanguage = selectTranslationLanguage(global); const translationLanguage = selectTranslationLanguage(global);
const isPrivate = isUserId(chatId);
const { doNotTranslate } = global.settings.byKey; const { doNotTranslate } = global.settings.byKey;
if (!chat || chat.isRestricted || selectIsInSelectMode(global)) { if (!chat || chat.isRestricted || selectIsInSelectMode(global)) {
@ -446,16 +463,18 @@ export default memo(withGlobal<OwnProps>(
} }
const bot = selectBot(global, chatId); const bot = selectBot(global, chatId);
const chatFullInfo = !isUserId(chatId) ? selectChatFullInfo(global, chatId) : undefined; const chatFullInfo = !isPrivate ? selectChatFullInfo(global, chatId) : undefined;
const userFullInfo = isUserId(chatId) ? selectUserFullInfo(global, chatId) : undefined; const userFullInfo = isPrivate ? selectUserFullInfo(global, chatId) : undefined;
const fullInfo = chatFullInfo || userFullInfo; const fullInfo = chatFullInfo || userFullInfo;
const isChatWithSelf = selectIsChatWithSelf(global, chatId); const isChatWithSelf = selectIsChatWithSelf(global, chatId);
const isMainThread = messageListType === 'thread' && threadId === MAIN_THREAD_ID; const isMainThread = messageListType === 'thread' && threadId === MAIN_THREAD_ID;
const isDiscussionThread = messageListType === 'thread' && threadId !== MAIN_THREAD_ID; const isDiscussionThread = messageListType === 'thread' && threadId !== MAIN_THREAD_ID;
const isRightColumnShown = selectIsRightColumnShown(global, isMobile); const isRightColumnShown = selectIsRightColumnShown(global, isMobile);
const canRestartBot = Boolean(bot && selectIsUserBlocked(global, bot.id)); const isUserBlocked = isPrivate ? selectIsUserBlocked(global, chatId) : false;
const canRestartBot = Boolean(bot && isUserBlocked);
const canStartBot = !canRestartBot && Boolean(selectIsChatBotNotStarted(global, chatId)); const canStartBot = !canRestartBot && Boolean(selectIsChatBotNotStarted(global, chatId));
const canUnblock = isUserBlocked && !bot;
const canSubscribe = Boolean( const canSubscribe = Boolean(
(isMainThread || chat.isForum) && (isChannel || isChatSuperGroup(chat)) && chat.isNotJoined, (isMainThread || chat.isForum) && (isChannel || isChatSuperGroup(chat)) && chat.isNotJoined,
); );
@ -499,6 +518,7 @@ export default memo(withGlobal<OwnProps>(
language, language,
doNotTranslate, doNotTranslate,
detectedChatLanguage: chat.detectedLanguage, detectedChatLanguage: chat.detectedLanguage,
canUnblock,
}; };
}, },
)(HeaderActions)); )(HeaderActions));

View File

@ -76,7 +76,6 @@ export type OwnProps = {
anchor: IAnchorPosition; anchor: IAnchorPosition;
isChannel?: boolean; isChannel?: boolean;
canStartBot?: boolean; canStartBot?: boolean;
canRestartBot?: boolean;
canSubscribe?: boolean; canSubscribe?: boolean;
canSearch?: boolean; canSearch?: boolean;
canCall?: boolean; canCall?: boolean;
@ -114,6 +113,8 @@ type StateProps = {
isRightColumnShown?: boolean; isRightColumnShown?: boolean;
canManage?: boolean; canManage?: boolean;
canTranslate?: boolean; canTranslate?: boolean;
isBlocked?: boolean;
isBot?: boolean;
}; };
const CLOSE_MENU_ANIMATION_DURATION = 200; const CLOSE_MENU_ANIMATION_DURATION = 200;
@ -131,7 +132,6 @@ const HeaderMenuContainer: FC<OwnProps & StateProps> = ({
isForum, isForum,
isChatInfoShown, isChatInfoShown,
canStartBot, canStartBot,
canRestartBot,
canSubscribe, canSubscribe,
canSearch, canSearch,
canCall, canCall,
@ -154,6 +154,8 @@ const HeaderMenuContainer: FC<OwnProps & StateProps> = ({
canManage, canManage,
isRightColumnShown, isRightColumnShown,
canTranslate, canTranslate,
isBlocked,
isBot,
onJoinRequestsClick, onJoinRequestsClick,
onSubscribeChannel, onSubscribeChannel,
onSearchClick, onSearchClick,
@ -179,6 +181,8 @@ const HeaderMenuContainer: FC<OwnProps & StateProps> = ({
openChat, openChat,
toggleManagement, toggleManagement,
togglePeerTranslations, togglePeerTranslations,
blockUser,
unblockUser,
} = getActions(); } = getActions();
const { isMobile } = useAppLayout(); const { isMobile } = useAppLayout();
@ -343,6 +347,16 @@ const HeaderMenuContainer: FC<OwnProps & StateProps> = ({
closeMenu(); closeMenu();
}); });
const handleBlock = useLastCallback(() => {
blockUser({ userId: chatId });
closeMenu();
});
const handleUnblock = useLastCallback(() => {
unblockUser({ userId: chatId });
closeMenu();
});
useEffect(() => { useEffect(() => {
disableScrolling(); disableScrolling();
@ -459,14 +473,6 @@ const HeaderMenuContainer: FC<OwnProps & StateProps> = ({
{lang('BotStart')} {lang('BotStart')}
</MenuItem> </MenuItem>
)} )}
{withExtraActions && canRestartBot && (
<MenuItem
icon="bots"
onClick={handleRestartBot}
>
{lang('BotRestart')}
</MenuItem>
)}
{withExtraActions && canSubscribe && ( {withExtraActions && canSubscribe && (
<MenuItem <MenuItem
icon={isChannel ? 'channel' : 'group'} icon={isChannel ? 'channel' : 'group'}
@ -573,6 +579,22 @@ const HeaderMenuContainer: FC<OwnProps & StateProps> = ({
{lang('GiftPremium')} {lang('GiftPremium')}
</MenuItem> </MenuItem>
)} )}
{isBot && (
<MenuItem
icon={isBlocked ? 'bots' : 'hand-stop'}
onClick={isBlocked ? handleRestartBot : handleBlock}
>
{isBlocked ? lang('BotRestart') : lang('Bot.Stop')}
</MenuItem>
)}
{isPrivate && !isBot && (
<MenuItem
icon={isBlocked ? 'user' : 'hand-stop'}
onClick={isBlocked ? handleUnblock : handleBlock}
>
{isBlocked ? lang('Unblock') : lang('BlockUser')}
</MenuItem>
)}
{canLeave && ( {canLeave && (
<> <>
<MenuSeparator /> <MenuSeparator />
@ -666,6 +688,8 @@ export default memo(withGlobal<OwnProps>(
canManage, canManage,
isRightColumnShown: selectIsRightColumnShown(global), isRightColumnShown: selectIsRightColumnShown(global),
canTranslate, canTranslate,
isBlocked: userFullInfo?.isBlocked,
isBot: Boolean(chatBot),
}; };
}, },
)(HeaderMenuContainer)); )(HeaderMenuContainer));

View File

@ -144,6 +144,7 @@ type StateProps = {
pinnedIds?: number[]; pinnedIds?: number[];
topMessageId?: number; topMessageId?: number;
canUnpin?: boolean; canUnpin?: boolean;
canUnblock?: boolean;
}; };
function isImage(item: DataTransferItem) { function isImage(item: DataTransferItem) {
@ -198,6 +199,7 @@ function MiddleColumn({
pinnedIds, pinnedIds,
topMessageId, topMessageId,
canUnpin, canUnpin,
canUnblock,
}: OwnProps & StateProps) { }: OwnProps & StateProps) {
const { const {
openChat, openChat,
@ -214,6 +216,7 @@ function MiddleColumn({
loadFullChat, loadFullChat,
setLeftColumnWidth, setLeftColumnWidth,
resetLeftColumnWidth, resetLeftColumnWidth,
unblockUser,
} = getActions(); } = getActions();
const { width: windowWidth } = useWindowSize(); const { width: windowWidth } = useWindowSize();
@ -251,8 +254,10 @@ function MiddleColumn({
const renderingCanSubscribe = usePrevDuringAnimation(canSubscribe, closeAnimationDuration); const renderingCanSubscribe = usePrevDuringAnimation(canSubscribe, closeAnimationDuration);
const renderingCanStartBot = usePrevDuringAnimation(canStartBot, closeAnimationDuration); const renderingCanStartBot = usePrevDuringAnimation(canStartBot, closeAnimationDuration);
const renderingCanRestartBot = usePrevDuringAnimation(canRestartBot, closeAnimationDuration); const renderingCanRestartBot = usePrevDuringAnimation(canRestartBot, closeAnimationDuration);
const renderingCanUnblock = usePrevDuringAnimation(canUnblock, closeAnimationDuration);
const renderingCanPost = usePrevDuringAnimation(canPost, closeAnimationDuration) const renderingCanPost = usePrevDuringAnimation(canPost, closeAnimationDuration)
&& !renderingCanRestartBot && !renderingCanStartBot && !renderingCanSubscribe && chatId !== TMP_CHAT_ID; && !renderingCanRestartBot && !renderingCanStartBot && !renderingCanSubscribe && !renderingCanUnblock
&& chatId !== TMP_CHAT_ID;
const renderingHasTools = usePrevDuringAnimation(hasTools, closeAnimationDuration); const renderingHasTools = usePrevDuringAnimation(hasTools, closeAnimationDuration);
const renderingIsFabShown = usePrevDuringAnimation(isFabShown, closeAnimationDuration) && chatId !== TMP_CHAT_ID; const renderingIsFabShown = usePrevDuringAnimation(isFabShown, closeAnimationDuration) && chatId !== TMP_CHAT_ID;
const renderingIsChannel = usePrevDuringAnimation(isChannel, closeAnimationDuration); const renderingIsChannel = usePrevDuringAnimation(isChannel, closeAnimationDuration);
@ -399,6 +404,10 @@ function MiddleColumn({
restartBot({ chatId: chatId! }); restartBot({ chatId: chatId! });
}); });
const handleUnblock = useLastCallback(() => {
unblockUser({ userId: chatId! });
});
const customBackgroundValue = useCustomBackground(theme, customBackground); const customBackgroundValue = useCustomBackground(theme, customBackground);
const className = buildClassName( const className = buildClassName(
@ -460,7 +469,7 @@ function MiddleColumn({
); );
const withMessageListBottomShift = Boolean( const withMessageListBottomShift = Boolean(
renderingCanRestartBot || renderingCanSubscribe || renderingShouldSendJoinRequest || renderingCanStartBot renderingCanRestartBot || renderingCanSubscribe || renderingShouldSendJoinRequest || renderingCanStartBot
|| isPinnedMessageList, || isPinnedMessageList || renderingCanUnblock,
); );
const withExtraShift = Boolean(isMessagingDisabled || isSelectModeActive || isPinnedMessageList); const withExtraShift = Boolean(isMessagingDisabled || isSelectModeActive || isPinnedMessageList);
@ -622,6 +631,19 @@ function MiddleColumn({
</Button> </Button>
</div> </div>
)} )}
{isMobile && renderingCanUnblock && (
<div className="middle-column-footer-button-container" dir={lang.isRtl ? 'rtl' : undefined}>
<Button
size="tiny"
fluid
ripple
className="join-subscribe-button"
onClick={handleUnblock}
>
{lang('Unblock')}
</Button>
</div>
)}
<MessageSelectToolbar <MessageSelectToolbar
messageListType={renderingMessageListType} messageListType={renderingMessageListType}
isActive={isSelectModeActive} isActive={isSelectModeActive}
@ -723,8 +745,10 @@ export default memo(withGlobal<OwnProps>(
); );
const shouldJoinToSend = Boolean(chat?.isNotJoined && chat.isJoinToSend); const shouldJoinToSend = Boolean(chat?.isNotJoined && chat.isJoinToSend);
const shouldSendJoinRequest = Boolean(chat?.isNotJoined && chat.isJoinRequest); const shouldSendJoinRequest = Boolean(chat?.isNotJoined && chat.isJoinRequest);
const canRestartBot = Boolean(bot && selectIsUserBlocked(global, bot.id)); const isUserBlocked = isPrivate ? selectIsUserBlocked(global, chatId) : false;
const canRestartBot = Boolean(bot && isUserBlocked);
const canStartBot = !canRestartBot && isBotNotStarted; const canStartBot = !canRestartBot && isBotNotStarted;
const canUnblock = isUserBlocked && !bot;
const shouldLoadFullChat = Boolean( const shouldLoadFullChat = Boolean(
chat && isChatGroup(chat) && !selectChatFullInfo(global, chat.id), chat && isChatGroup(chat) && !selectChatFullInfo(global, chat.id),
); );
@ -778,6 +802,7 @@ export default memo(withGlobal<OwnProps>(
pinnedIds, pinnedIds,
topMessageId, topMessageId,
canUnpin, canUnpin,
canUnblock,
}; };
}, },
)(MiddleColumn)); )(MiddleColumn));