Invite Via Link: Show error when user is restricted to add new users (#4435)

This commit is contained in:
Alexander Zinchuk 2024-03-29 20:51:19 +01:00
parent 3eb675c8fa
commit e21249cf0f
3 changed files with 55 additions and 21 deletions

View File

@ -1444,10 +1444,11 @@ export async function addChatMembers(chat: ApiChat, users: ApiUser[]) {
shouldIgnoreUpdates: true, shouldIgnoreUpdates: true,
shouldThrow: true, shouldThrow: true,
}); });
if (updates) { if (!updates) {
processUpdate(updates); return undefined;
return handleUserPrivacyRestrictedUpdates(updates);
} }
processUpdate(updates);
return handleUserPrivacyRestrictedUpdates(updates);
} catch (err) { } catch (err) {
if ((err as Error).message === 'USER_PRIVACY_RESTRICTED') { if ((err as Error).message === 'USER_PRIVACY_RESTRICTED') {
return users.map(({ id }) => id); return users.map(({ id }) => id);

View File

@ -37,6 +37,7 @@ type OwnProps = {
isRoundCheckbox?: boolean; isRoundCheckbox?: boolean;
lockedIds?: string[]; lockedIds?: string[];
forceShowSelf?: boolean; forceShowSelf?: boolean;
isViewOnly?: boolean;
onSelectedIdsChange?: (ids: string[]) => void; onSelectedIdsChange?: (ids: string[]) => void;
onFilterChange?: (value: string) => void; onFilterChange?: (value: string) => void;
onDisabledClick?: (id: string) => void; onDisabledClick?: (id: string) => void;
@ -63,6 +64,7 @@ const Picker: FC<OwnProps> = ({
isRoundCheckbox, isRoundCheckbox,
lockedIds, lockedIds,
forceShowSelf, forceShowSelf,
isViewOnly,
onSelectedIdsChange, onSelectedIdsChange,
onFilterChange, onFilterChange,
onDisabledClick, onDisabledClick,
@ -171,7 +173,7 @@ const Picker: FC<OwnProps> = ({
> >
{viewportIds.map((id) => { {viewportIds.map((id) => {
const renderCheckbox = () => { const renderCheckbox = () => {
return ( return isViewOnly ? undefined : (
<Checkbox <Checkbox
label="" label=""
disabled={lockedIdsSet.has(id)} disabled={lockedIdsSet.has(id)}
@ -185,6 +187,7 @@ const Picker: FC<OwnProps> = ({
key={id} key={id}
className={buildClassName('chat-item-clickable picker-list-item', isRoundCheckbox && 'chat-item')} className={buildClassName('chat-item-clickable picker-list-item', isRoundCheckbox && 'chat-item')}
disabled={lockedIdsSet.has(id)} disabled={lockedIdsSet.has(id)}
inactive={isViewOnly}
allowDisabledClick={Boolean(onDisabledClick)} allowDisabledClick={Boolean(onDisabledClick)}
// eslint-disable-next-line react/jsx-no-bind // eslint-disable-next-line react/jsx-no-bind
onClick={() => handleItemClick(id)} onClick={() => handleItemClick(id)}

View File

@ -7,6 +7,7 @@ import React, {
import { getActions, getGlobal } from '../../global'; import { getActions, getGlobal } from '../../global';
import { getUserFullName } from '../../global/helpers'; import { getUserFullName } from '../../global/helpers';
import { selectChat } from '../../global/selectors';
import renderText from '../common/helpers/renderText'; import renderText from '../common/helpers/renderText';
import useLang from '../../hooks/useLang'; import useLang from '../../hooks/useLang';
@ -50,39 +51,68 @@ const InviteViaLinkModal: FC<OwnProps> = ({
return userIds?.map((userId) => getUserFullName(usersById[userId])).join(', '); return userIds?.map((userId) => getUserFullName(usersById[userId])).join(', ');
}, [userIds]); }, [userIds]);
const canSendInviteLink = useMemo(() => {
if (!chatId) {
return false;
}
const chat = selectChat(getGlobal(), chatId);
return Boolean(chat?.isCreator || chat?.adminRights?.inviteUsers);
}, [chatId]);
const contentText = useMemo(() => {
const langKey = canSendInviteLink
? 'SendInviteLink.TextAvailableSingleUser'
: 'SendInviteLink.TextUnavailableSingleUser';
return renderText(lang(langKey, userNames), ['simple_markdown']);
}, [userNames, lang, canSendInviteLink]);
return ( return (
<Modal <Modal
isOpen={Boolean(userIds && chatId)} isOpen={Boolean(userIds && chatId)}
title={lang('SendInviteLink.InviteTitle')} title={canSendInviteLink ? lang('SendInviteLink.InviteTitle') : lang('SendInviteLink.LinkUnavailableTitle')}
onClose={handleClose} onClose={handleClose}
isSlim isSlim
> >
<p className={styles.contentText}> <p className={styles.contentText}>
{renderText(lang('SendInviteLink.TextAvailableSingleUser', userNames), ['simple_markdown'])} {contentText}
</p> </p>
<Picker <Picker
className={styles.userPicker} className={styles.userPicker}
itemIds={userIds!} itemIds={userIds!}
selectedIds={selectedMemberIds} selectedIds={selectedMemberIds}
onSelectedIdsChange={setSelectedMemberIds} onSelectedIdsChange={setSelectedMemberIds}
isViewOnly={!canSendInviteLink}
isRoundCheckbox isRoundCheckbox
/> />
<div className="dialog-buttons"> <div className="dialog-buttons">
<Button {canSendInviteLink && (
className="confirm-dialog-button" <Button
isText className="confirm-dialog-button"
onClick={handleSendInviteLink} isText
disabled={!selectedMemberIds.length} onClick={handleSendInviteLink}
> disabled={!selectedMemberIds.length}
{lang('SendInviteLink.ActionInvite')} >
</Button> {lang('SendInviteLink.ActionInvite')}
<Button </Button>
className="confirm-dialog-button" )}
isText {canSendInviteLink && (
onClick={handleSkip} <Button
> className="confirm-dialog-button"
{lang('SendInviteLink.ActionSkip')} isText
</Button> onClick={handleSkip}
>
{lang('SendInviteLink.ActionSkip')}
</Button>
)}
{!canSendInviteLink && (
<Button
className="confirm-dialog-button"
isText
onClick={handleClose}
>
{lang('SendInviteLink.ActionClose')}
</Button>
)}
</div> </div>
</Modal> </Modal>
); );