diff --git a/src/components/right/management/ManageChannel.tsx b/src/components/right/management/ManageChannel.tsx index ecaac702e..a18c5e440 100644 --- a/src/components/right/management/ManageChannel.tsx +++ b/src/components/right/management/ManageChannel.tsx @@ -379,4 +379,7 @@ export default memo(withGlobal( availableReactions: global.reactions.availableReactions, }; }, + (global, { chatId }) => { + return Boolean(selectChat(global, chatId)); + }, )(ManageChannel)); diff --git a/src/components/right/management/ManageChatAdministrators.tsx b/src/components/right/management/ManageChatAdministrators.tsx index 2b9db01d5..1d127a9d3 100644 --- a/src/components/right/management/ManageChatAdministrators.tsx +++ b/src/components/right/management/ManageChatAdministrators.tsx @@ -24,9 +24,9 @@ type OwnProps = { }; type StateProps = { - chat: ApiChat; + chat?: ApiChat; currentUserId?: string; - isChannel: boolean; + isChannel?: boolean; adminMembersById?: Record; }; @@ -47,7 +47,7 @@ const ManageChatAdministrators: FC = ({ onBack: onClose, }); - const canAddNewAdmins = Boolean(chat.isCreator || chat.adminRights?.addAdmins); + const canAddNewAdmins = Boolean(chat?.isCreator || chat?.adminRights?.addAdmins); const adminMembers = useMemo(() => { if (!adminMembersById) { @@ -141,12 +141,12 @@ const ManageChatAdministrators: FC = ({ export default memo(withGlobal( (global, { chatId }): StateProps => { - const chat = selectChat(global, chatId)!; + const chat = selectChat(global, chatId); return { chat, currentUserId: global.currentUserId, - isChannel: isChatChannel(chat), + isChannel: chat && isChatChannel(chat), adminMembersById: selectChatFullInfo(global, chatId)?.adminMembersById, }; }, diff --git a/src/components/right/management/ManageChatPrivacyType.tsx b/src/components/right/management/ManageChatPrivacyType.tsx index 3439a896c..932de7f9f 100644 --- a/src/components/right/management/ManageChatPrivacyType.tsx +++ b/src/components/right/management/ManageChatPrivacyType.tsx @@ -312,4 +312,7 @@ export default memo(withGlobal( privateInviteLink: selectChatFullInfo(global, chatId)?.inviteLink, }; }, + (global, { chatId }) => { + return Boolean(selectChat(global, chatId) && selectManagement(global, chatId)); + }, )(ManageChatPrivacyType)); diff --git a/src/components/right/management/ManageDiscussion.tsx b/src/components/right/management/ManageDiscussion.tsx index abfacddaf..e58f5716a 100644 --- a/src/components/right/management/ManageDiscussion.tsx +++ b/src/components/right/management/ManageDiscussion.tsx @@ -286,9 +286,7 @@ export default memo(withGlobal( const chat = selectChat(global, chatId); const { linkedChatId } = selectChatFullInfo(global, chatId) || {}; const { forDiscussionIds, byId: chatsByIds } = global.chats; - const linkedChat = linkedChatId - ? selectChat(global, linkedChatId) - : undefined; + const linkedChat = linkedChatId ? selectChat(global, linkedChatId) : undefined; return { chat, diff --git a/src/components/right/management/ManageGroup.tsx b/src/components/right/management/ManageGroup.tsx index da7f72d8b..2e8f01ef3 100644 --- a/src/components/right/management/ManageGroup.tsx +++ b/src/components/right/management/ManageGroup.tsx @@ -1,7 +1,7 @@ import type { ChangeEvent } from 'react'; import type { FC } from '../../../lib/teact/teact'; import React, { - memo, useCallback, useEffect, useMemo, useRef, useState, + memo, useEffect, useMemo, useRef, useState, } from '../../../lib/teact/teact'; import { getActions, withGlobal } from '../../../global'; @@ -25,6 +25,7 @@ import renderText from '../../common/helpers/renderText'; import useFlag from '../../../hooks/useFlag'; import useHistoryBack from '../../../hooks/useHistoryBack'; import useLang from '../../../hooks/useLang'; +import useLastCallback from '../../../hooks/useLastCallback'; import useMedia from '../../../hooks/useMedia'; import AvatarEditable from '../../ui/AvatarEditable'; @@ -158,50 +159,50 @@ const ManageGroup: FC = ({ } }, [progress]); - const handleClickEditType = useCallback(() => { + const handleClickEditType = useLastCallback(() => { onScreenSelect(ManagementScreens.ChatPrivacyType); - }, [onScreenSelect]); + }); - const handleClickDiscussion = useCallback(() => { + const handleClickDiscussion = useLastCallback(() => { onScreenSelect(ManagementScreens.Discussion); - }, [onScreenSelect]); + }); - const handleClickReactions = useCallback(() => { + const handleClickReactions = useLastCallback(() => { onScreenSelect(ManagementScreens.Reactions); - }, [onScreenSelect]); + }); - const handleClickPermissions = useCallback(() => { + const handleClickPermissions = useLastCallback(() => { onScreenSelect(ManagementScreens.GroupPermissions); - }, [onScreenSelect]); + }); - const handleClickAdministrators = useCallback(() => { + const handleClickAdministrators = useLastCallback(() => { onScreenSelect(ManagementScreens.ChatAdministrators); - }, [onScreenSelect]); + }); - const handleClickInvites = useCallback(() => { + const handleClickInvites = useLastCallback(() => { onScreenSelect(ManagementScreens.Invites); - }, [onScreenSelect]); + }); - const handleClickRequests = useCallback(() => { + const handleClickRequests = useLastCallback(() => { onScreenSelect(ManagementScreens.JoinRequests); - }, [onScreenSelect]); + }); - const handleSetPhoto = useCallback((file: File) => { + const handleSetPhoto = useLastCallback((file: File) => { setPhoto(file); setIsProfileFieldsTouched(true); - }, []); + }); - const handleTitleChange = useCallback((e: ChangeEvent) => { + const handleTitleChange = useLastCallback((e: ChangeEvent) => { setTitle(e.target.value); setIsProfileFieldsTouched(true); - }, []); + }); - const handleAboutChange = useCallback((e: ChangeEvent) => { + const handleAboutChange = useLastCallback((e: ChangeEvent) => { setAbout(e.target.value); setIsProfileFieldsTouched(true); - }, []); + }); - const handleUpdateGroup = useCallback(() => { + const handleUpdateGroup = useLastCallback(() => { const trimmedTitle = title.trim(); const trimmedAbout = about.trim(); @@ -216,13 +217,13 @@ const ManageGroup: FC = ({ about: trimmedAbout, photo, }); - }, [about, chatId, photo, title, updateChat]); + }); - const handleClickMembers = useCallback(() => { + const handleClickMembers = useLastCallback(() => { onScreenSelect(ManagementScreens.GroupMembers); - }, [onScreenSelect]); + }); - const handleTogglePreHistory = useCallback(() => { + const handleTogglePreHistory = useLastCallback(() => { if (!chatFullInfo) { return; } @@ -230,9 +231,9 @@ const ManageGroup: FC = ({ const { isPreHistoryHidden } = chatFullInfo; togglePreHistoryHidden({ chatId: chat.id, isEnabled: !isPreHistoryHidden }); - }, [chat.id, chatFullInfo]); + }); - const handleForumToggle = useCallback(() => { + const handleForumToggle = useLastCallback(() => { setIsForumEnabled((current) => { const newIsForumEnabled = !current; @@ -242,7 +243,7 @@ const ManageGroup: FC = ({ return newIsForumEnabled; }); - }, [chatId, toggleForum]); + }); useEffect(() => { if (!isChannelsPremiumLimitReached) { @@ -298,7 +299,7 @@ const ManageGroup: FC = ({ return Object.keys(chatFullInfo?.adminMembersById || {}).length; }, [chatFullInfo?.adminMembersById]); - const handleDeleteGroup = useCallback(() => { + const handleDeleteGroup = useLastCallback(() => { if (isBasicGroup) { deleteChat({ chatId: chat.id }); } else if (!chat.isCreator) { @@ -309,10 +310,7 @@ const ManageGroup: FC = ({ closeDeleteDialog(); closeManagement(); openChat({ id: undefined }); - }, [ - isBasicGroup, chat.isCreator, chat.id, - closeDeleteDialog, closeManagement, leaveChannel, deleteChannel, deleteChat, openChat, - ]); + }); if (chat.isRestricted || chat.isForbidden) { return undefined; @@ -497,6 +495,9 @@ export default memo(withGlobal( const isBasicGroup = isChatBasicGroup(chat); const { invites } = management.byChatId[chatId] || {}; const canEditForum = !hasLinkedChannel && (getHasAdminRight(chat, 'changeInfo') || chat.isCreator); + const canChangeInfo = chat.isCreator || getHasAdminRight(chat, 'changeInfo'); + const canBanUsers = chat.isCreator || getHasAdminRight(chat, 'banUsers'); + const canInvite = chat.isCreator || getHasAdminRight(chat, 'inviteUsers'); return { chat, @@ -504,13 +505,16 @@ export default memo(withGlobal( progress, isBasicGroup, hasLinkedChannel, - canChangeInfo: chat.isCreator || getHasAdminRight(chat, 'changeInfo'), - canBanUsers: chat.isCreator || getHasAdminRight(chat, 'banUsers'), - canInvite: chat.isCreator || getHasAdminRight(chat, 'inviteUsers'), + canChangeInfo, + canBanUsers, + canInvite, exportedInvites: invites, isChannelsPremiumLimitReached: limitReachedModal?.limit === 'channels', availableReactions: global.reactions.availableReactions, canEditForum, }; }, + (global, { chatId }) => { + return Boolean(selectChat(global, chatId)); + }, )(ManageGroup)); diff --git a/src/components/right/management/ManageGroupAdminRights.tsx b/src/components/right/management/ManageGroupAdminRights.tsx index e1ddbc92e..aba94a632 100644 --- a/src/components/right/management/ManageGroupAdminRights.tsx +++ b/src/components/right/management/ManageGroupAdminRights.tsx @@ -443,4 +443,7 @@ export default memo(withGlobal( adminMembersById: fullInfo?.adminMembersById, }; }, + (global, { chatId }) => { + return Boolean(selectChat(global, chatId)); + }, )(ManageGroupAdminRights)); diff --git a/src/components/right/management/ManageGroupUserPermissions.tsx b/src/components/right/management/ManageGroupUserPermissions.tsx index b1dcb7c91..2063a2e33 100644 --- a/src/components/right/management/ManageGroupUserPermissions.tsx +++ b/src/components/right/management/ManageGroupUserPermissions.tsx @@ -378,4 +378,7 @@ export default memo(withGlobal( members: fullInfo?.members, }; }, + (global, { chatId }) => { + return Boolean(selectChat(global, chatId)); + }, )(ManageGroupUserPermissions)); diff --git a/src/components/right/management/ManageInvite.tsx b/src/components/right/management/ManageInvite.tsx index c142e5e09..421b0c5ab 100644 --- a/src/components/right/management/ManageInvite.tsx +++ b/src/components/right/management/ManageInvite.tsx @@ -267,7 +267,7 @@ const ManageInvite: FC = ({ export default memo(withGlobal( (global, { chatId }): StateProps => { - const { editingInvite } = selectTabState(global).management.byChatId[chatId]; + const { editingInvite } = selectTabState(global).management.byChatId[chatId] || {}; return { editingInvite, diff --git a/src/components/right/management/ManageInviteInfo.tsx b/src/components/right/management/ManageInviteInfo.tsx index edd16922b..88dac22b4 100644 --- a/src/components/right/management/ManageInviteInfo.tsx +++ b/src/components/right/management/ManageInviteInfo.tsx @@ -186,7 +186,7 @@ const ManageInviteInfo: FC = ({ export default memo(withGlobal( (global, { chatId }): StateProps => { - const { inviteInfo } = selectTabState(global).management.byChatId[chatId]; + const { inviteInfo } = selectTabState(global).management.byChatId[chatId] || {}; const { invite, importers, requesters } = inviteInfo || {}; const chat = selectChat(global, chatId); const isChannel = chat && isChatChannel(chat); diff --git a/src/components/right/management/ManageInvites.tsx b/src/components/right/management/ManageInvites.tsx index 5238a20d0..c02000e78 100644 --- a/src/components/right/management/ManageInvites.tsx +++ b/src/components/right/management/ManageInvites.tsx @@ -377,7 +377,7 @@ const ManageInvites: FC = ({ export default memo(withGlobal( (global, { chatId }): StateProps => { - const { invites, revokedInvites } = selectTabState(global).management.byChatId[chatId]; + const { invites, revokedInvites } = selectTabState(global).management.byChatId[chatId] || {}; const chat = selectChat(global, chatId); const isChannel = chat && isChatChannel(chat); diff --git a/src/components/right/management/ManageReactions.tsx b/src/components/right/management/ManageReactions.tsx index c660bbf2b..d2f7d7dd8 100644 --- a/src/components/right/management/ManageReactions.tsx +++ b/src/components/right/management/ManageReactions.tsx @@ -188,4 +188,7 @@ export default memo(withGlobal( chat, }; }, + (global, { chatId }) => { + return Boolean(selectChat(global, chatId)); + }, )(ManageReactions)); diff --git a/src/global/actions/api/initial.ts b/src/global/actions/api/initial.ts index 1a98b2b65..253576e3e 100644 --- a/src/global/actions/api/initial.ts +++ b/src/global/actions/api/initial.ts @@ -16,7 +16,7 @@ import { getCurrentTabId } from '../../../util/establishMultitabRole'; import { buildCollectionByKey } from '../../../util/iteratees'; import { unsubscribe } from '../../../util/notifications'; import { clearEncryptedSession, encryptSession, forgetPasscode } from '../../../util/passcode'; -import { parseInitialLocationHash, resetInitialLocationHash } from '../../../util/routing'; +import { parseInitialLocationHash, resetInitialLocationHash, resetLocationHash } from '../../../util/routing'; import { clearLegacySessions, clearStoredSession, @@ -171,6 +171,7 @@ addActionHandler('signOut', async (global, actions, payload): Promise => { try { resetInitialLocationHash(); + resetLocationHash(); await unsubscribe(); await callApi('destroy'); await forceWebsync(false); diff --git a/src/util/routing.ts b/src/util/routing.ts index c5645467c..1c921c4b6 100644 --- a/src/util/routing.ts +++ b/src/util/routing.ts @@ -21,6 +21,10 @@ export function resetInitialLocationHash() { parsedInitialLocationHash = undefined; } +export function resetLocationHash() { + window.location.hash = ''; +} + export const createLocationHash = (chatId: string, type: MessageListType, threadId: ThreadId): string => { const displayType = type === 'thread' ? undefined : type; const parts = threadId === MAIN_THREAD_ID ? [chatId, displayType] : [chatId, threadId, displayType];