Profile: Allow to reset the username (#2213)
This commit is contained in:
parent
dd49420851
commit
bbe2802db8
@ -50,7 +50,9 @@ export async function setChatUsername(
|
|||||||
username,
|
username,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const usernames = chat.usernames!.map((u) => (u.isEditable ? { ...u, username } : u));
|
const usernames = chat.usernames
|
||||||
|
? chat.usernames.map((u) => (u.isEditable ? { ...u, username } : u))
|
||||||
|
: [{ username, isEditable: true, isActive: true }];
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
onUpdate({
|
onUpdate({
|
||||||
@ -59,6 +61,8 @@ export async function setChatUsername(
|
|||||||
chat: { usernames },
|
chat: { usernames },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updatePrivateLink({
|
export async function updatePrivateLink({
|
||||||
|
|||||||
@ -60,8 +60,8 @@ export interface ApiUserStatus {
|
|||||||
|
|
||||||
export interface ApiUsername {
|
export interface ApiUsername {
|
||||||
username: string;
|
username: string;
|
||||||
isActive?: true;
|
isActive?: boolean;
|
||||||
isEditable?: true;
|
isEditable?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ApiChatType = typeof API_CHAT_TYPES[number];
|
export type ApiChatType = typeof API_CHAT_TYPES[number];
|
||||||
|
|||||||
@ -19,7 +19,7 @@ type OwnProps = {
|
|||||||
isLoading?: boolean;
|
isLoading?: boolean;
|
||||||
isUsernameAvailable?: boolean;
|
isUsernameAvailable?: boolean;
|
||||||
checkedUsername?: string;
|
checkedUsername?: string;
|
||||||
onChange: (value: string | false) => void;
|
onChange: (value: string) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const MIN_USERNAME_LENGTH = 5;
|
const MIN_USERNAME_LENGTH = 5;
|
||||||
@ -30,9 +30,11 @@ const USERNAME_REGEX = /^\D([a-zA-Z0-9_]+)$/;
|
|||||||
const runDebouncedForCheckUsername = debounce((cb) => cb(), 250, false);
|
const runDebouncedForCheckUsername = debounce((cb) => cb(), 250, false);
|
||||||
|
|
||||||
function isUsernameValid(username: string) {
|
function isUsernameValid(username: string) {
|
||||||
return username.length >= MIN_USERNAME_LENGTH
|
return username.length === 0 || (
|
||||||
|
username.length >= MIN_USERNAME_LENGTH
|
||||||
&& username.length <= MAX_USERNAME_LENGTH
|
&& username.length <= MAX_USERNAME_LENGTH
|
||||||
&& USERNAME_REGEX.test(username);
|
&& USERNAME_REGEX.test(username)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const UsernameInput: FC<OwnProps> = ({
|
const UsernameInput: FC<OwnProps> = ({
|
||||||
|
|||||||
@ -71,6 +71,7 @@ const ManageChatPrivacyType: FC<OwnProps & StateProps> = ({
|
|||||||
const isPublic = useMemo(() => isChatPublic(chat), [chat]);
|
const isPublic = useMemo(() => isChatPublic(chat), [chat]);
|
||||||
const privateLink = chat.fullInfo?.inviteLink;
|
const privateLink = chat.fullInfo?.inviteLink;
|
||||||
|
|
||||||
|
const [isProfileFieldsTouched, setIsProfileFieldsTouched] = useState(false);
|
||||||
const [privacyType, setPrivacyType] = useState<PrivacyType>(isPublic ? 'public' : 'private');
|
const [privacyType, setPrivacyType] = useState<PrivacyType>(isPublic ? 'public' : 'private');
|
||||||
const [editableUsername, setEditableUsername] = useState();
|
const [editableUsername, setEditableUsername] = useState();
|
||||||
const [isRevokeConfirmDialogOpen, openRevokeConfirmDialog, closeRevokeConfirmDialog] = useFlag();
|
const [isRevokeConfirmDialogOpen, openRevokeConfirmDialog, closeRevokeConfirmDialog] = useFlag();
|
||||||
@ -79,8 +80,10 @@ const ManageChatPrivacyType: FC<OwnProps & StateProps> = ({
|
|||||||
const previousIsUsernameAvailable = usePrevious(isUsernameAvailable);
|
const previousIsUsernameAvailable = usePrevious(isUsernameAvailable);
|
||||||
const renderingIsUsernameAvailable = isUsernameAvailable ?? previousIsUsernameAvailable;
|
const renderingIsUsernameAvailable = isUsernameAvailable ?? previousIsUsernameAvailable;
|
||||||
|
|
||||||
const canUpdate = Boolean(
|
const canUpdate = isProfileFieldsTouched && Boolean(
|
||||||
(privacyType === 'public' && editableUsername && renderingIsUsernameAvailable)
|
(privacyType === 'public'
|
||||||
|
&& (editableUsername || (currentUsername && editableUsername === ''))
|
||||||
|
&& renderingIsUsernameAvailable)
|
||||||
|| (privacyType === 'private' && isPublic),
|
|| (privacyType === 'private' && isPublic),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -89,12 +92,21 @@ const ManageChatPrivacyType: FC<OwnProps & StateProps> = ({
|
|||||||
onBack: onClose,
|
onBack: onClose,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setIsProfileFieldsTouched(false);
|
||||||
|
}, [currentUsername]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (privacyType && !privateLink) {
|
if (privacyType && !privateLink) {
|
||||||
updatePrivateLink();
|
updatePrivateLink();
|
||||||
}
|
}
|
||||||
}, [privacyType, privateLink, updatePrivateLink]);
|
}, [privacyType, privateLink, updatePrivateLink]);
|
||||||
|
|
||||||
|
const handleUsernameChange = useCallback((value: string) => {
|
||||||
|
setEditableUsername(value);
|
||||||
|
setIsProfileFieldsTouched(true);
|
||||||
|
}, []);
|
||||||
|
|
||||||
const handleOptionChange = useCallback((value: string, e: ChangeEvent<HTMLInputElement>) => {
|
const handleOptionChange = useCallback((value: string, e: ChangeEvent<HTMLInputElement>) => {
|
||||||
const myChats = Object.values(getGlobal().chats.byId)
|
const myChats = Object.values(getGlobal().chats.byId)
|
||||||
.filter((l) => l.isCreator && l.usernames?.some((c) => c.isActive));
|
.filter((l) => l.isCreator && l.usernames?.some((c) => c.isActive));
|
||||||
@ -109,6 +121,7 @@ const ManageChatPrivacyType: FC<OwnProps & StateProps> = ({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setPrivacyType(value as PrivacyType);
|
setPrivacyType(value as PrivacyType);
|
||||||
|
setIsProfileFieldsTouched(true);
|
||||||
}, [maxPublicLinks, openLimitReachedModal]);
|
}, [maxPublicLinks, openLimitReachedModal]);
|
||||||
|
|
||||||
const handleForwardingOptionChange = useCallback((value: string) => {
|
const handleForwardingOptionChange = useCallback((value: string) => {
|
||||||
@ -216,7 +229,7 @@ const ManageChatPrivacyType: FC<OwnProps & StateProps> = ({
|
|||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
isUsernameAvailable={isUsernameAvailable}
|
isUsernameAvailable={isUsernameAvailable}
|
||||||
checkedUsername={checkedUsername}
|
checkedUsername={checkedUsername}
|
||||||
onChange={setEditableUsername}
|
onChange={handleUsernameChange}
|
||||||
/>
|
/>
|
||||||
{error === USERNAME_PURCHASE_ERROR && renderPurchaseLink()}
|
{error === USERNAME_PURCHASE_ERROR && renderPurchaseLink()}
|
||||||
<p className="section-info" dir="auto">
|
<p className="section-info" dir="auto">
|
||||||
@ -228,7 +241,7 @@ const ManageChatPrivacyType: FC<OwnProps & StateProps> = ({
|
|||||||
<ManageUsernames
|
<ManageUsernames
|
||||||
chatId={chat.id}
|
chatId={chat.id}
|
||||||
usernames={chat.usernames!}
|
usernames={chat.usernames!}
|
||||||
onEditUsername={setEditableUsername}
|
onEditUsername={handleUsernameChange}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<div className="section" dir={lang.isRtl ? 'rtl' : undefined}>
|
<div className="section" dir={lang.isRtl ? 'rtl' : undefined}>
|
||||||
|
|||||||
@ -71,7 +71,7 @@ addActionHandler('updateProfile', async (global, actions, payload) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (username) {
|
if (username !== undefined) {
|
||||||
const result = await callApi('updateUsername', username);
|
const result = await callApi('updateUsername', username);
|
||||||
global = getGlobal();
|
global = getGlobal();
|
||||||
const currentUser = currentUserId && selectUser(global, currentUserId);
|
const currentUser = currentUserId && selectUser(global, currentUserId);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user