From 19e90c8fbb0efe3116d1a05cace5a92d64013be5 Mon Sep 17 00:00:00 2001 From: Alexander Zinchuk Date: Fri, 3 May 2024 14:38:17 +0200 Subject: [PATCH] [Refactoring] Simplify modal registration (#4501) --- src/components/main/Main.tsx | 66 +------------------ src/components/modals/ModalContainer.tsx | 66 +++++++++++++++++++ .../AttachBotInstallModal.async.tsx | 4 +- .../AttachBotInstallModal.tsx | 8 ++- .../modals/boost/BoostModal.async.tsx | 4 +- src/components/modals/boost/BoostModal.tsx | 28 ++++---- .../modals/chatlist/ChatlistModal.async.tsx | 4 +- .../modals/chatlist/ChatlistModal.tsx | 12 ++-- .../InviteViaLinkModal.async.tsx | 4 +- .../inviteViaLink/InviteViaLinkModal.tsx | 13 ++-- src/components/modals/map/MapModal.async.tsx | 4 +- src/components/modals/map/MapModal.tsx | 9 +-- .../oneTimeMedia/OneTimeMediaModal.async.tsx | 4 +- .../modals/oneTimeMedia/OneTimeMediaModal.tsx | 8 +-- .../modals/urlAuth/UrlAuthModal.async.tsx | 4 +- .../modals/urlAuth/UrlAuthModal.tsx | 37 +++++++---- .../modals/webApp/WebAppModal.async.tsx | 4 +- src/components/modals/webApp/WebAppModal.tsx | 18 ++--- 18 files changed, 158 insertions(+), 139 deletions(-) create mode 100644 src/components/modals/ModalContainer.tsx diff --git a/src/components/main/Main.tsx b/src/components/main/Main.tsx index 039df6727..454867023 100644 --- a/src/components/main/Main.tsx +++ b/src/components/main/Main.tsx @@ -9,10 +9,8 @@ import { addExtraClass } from '../../lib/teact/teact-dom'; import { getActions, getGlobal, withGlobal } from '../../global'; import type { - ApiAttachBot, ApiChat, ApiChatFolder, - ApiGeoPoint, ApiMessage, ApiUser, } from '../../api/types'; @@ -24,7 +22,6 @@ import { BASE_EMOJI_KEYWORD_LANG, DEBUG, INACTIVE_MARKER, } from '../../config'; import { requestNextMutation } from '../../lib/fasterdom/fasterdom'; -import { getUserFullName } from '../../global/helpers'; import { selectCanAnimateInterface, selectChatFolder, @@ -75,15 +72,7 @@ import AudioPlayer from '../middle/AudioPlayer'; import ReactionPicker from '../middle/message/reactions/ReactionPicker.async'; import MessageListHistoryHandler from '../middle/MessageListHistoryHandler'; import MiddleColumn from '../middle/MiddleColumn'; -import AttachBotInstallModal from '../modals/attachBotInstall/AttachBotInstallModal.async'; -import BoostModal from '../modals/boost/BoostModal.async'; -import ChatlistModal from '../modals/chatlist/ChatlistModal.async'; -import GiftCodeModal from '../modals/giftcode/GiftCodeModal.async'; -import InviteViaLinkModal from '../modals/inviteViaLink/InviteViaLinkModal.async'; -import MapModal from '../modals/map/MapModal.async'; -import OneTimeMediaModal from '../modals/oneTimeMedia/OneTimeMediaModal.async'; -import UrlAuthModal from '../modals/urlAuth/UrlAuthModal.async'; -import WebAppModal from '../modals/webApp/WebAppModal.async'; +import ModalContainer from '../modals/ModalContainer'; import PaymentModal from '../payment/PaymentModal.async'; import ReceiptModal from '../payment/ReceiptModal.async'; import RightColumn from '../right/RightColumn'; @@ -126,8 +115,6 @@ type StateProps = { hasDialogs: boolean; audioMessage?: ApiMessage; safeLinkModalUrl?: string; - mapModalGeoPoint?: ApiGeoPoint; - mapModalZoom?: number; isHistoryCalendarOpen: boolean; shouldSkipHistoryAnimations?: boolean; openedStickerSetShortName?: string; @@ -144,15 +131,11 @@ type StateProps = { openedGame?: TabState['openedGame']; gameTitle?: string; isRatePhoneCallModalOpen?: boolean; - webApp?: TabState['webApp']; isPremiumModalOpen?: boolean; botTrustRequest?: TabState['botTrustRequest']; botTrustRequestBot?: ApiUser; - attachBotToInstall?: ApiAttachBot; requestedAttachBotInChat?: TabState['requestedAttachBotInChat']; requestedDraft?: TabState['requestedDraft']; - currentUserName?: string; - urlAuth?: TabState['urlAuth']; limitReached?: ApiLimitTypeWithModal; deleteFolderDialog?: ApiChatFolder; isPaymentModalOpen?: boolean; @@ -162,14 +145,9 @@ type StateProps = { isGiveawayModalOpen?: boolean; isPremiumGiftingModalOpen?: boolean; isCurrentUserPremium?: boolean; - chatlistModal?: TabState['chatlistModal']; - boostModal?: TabState['boostModal']; - giftCodeModal?: TabState['giftCodeModal']; noRightColumnAnimation?: boolean; withInterfaceAnimations?: boolean; isSynced?: boolean; - inviteViaLinkModal?: TabState['inviteViaLinkModal']; - oneTimeMediaModal?: TabState['oneTimeMediaModal']; }; const APP_OUTDATED_TIMEOUT_MS = 5 * 60 * 1000; // 5 min @@ -191,8 +169,6 @@ const Main: FC = ({ audioMessage, activeGroupCallId, safeLinkModalUrl, - mapModalGeoPoint, - mapModalZoom, isHistoryCalendarOpen, shouldSkipHistoryAnimations, limitReached, @@ -212,12 +188,8 @@ const Main: FC = ({ isRatePhoneCallModalOpen, botTrustRequest, botTrustRequestBot, - attachBotToInstall, requestedAttachBotInChat, requestedDraft, - webApp, - currentUserName, - urlAuth, isPremiumModalOpen, isGiveawayModalOpen, isPremiumGiftingModalOpen, @@ -227,13 +199,8 @@ const Main: FC = ({ isCurrentUserPremium, deleteFolderDialog, isMasterTab, - chatlistModal, - giftCodeModal, - boostModal, noRightColumnAnimation, isSynced, - inviteViaLinkModal, - oneTimeMediaModal, currentUserId, }) => { const { @@ -565,9 +532,8 @@ const Main: FC = ({ {audioMessage && } + - - = ({ userId={newContactUserId} isByPhoneNumber={newContactByPhoneNumber} /> - - - - - @@ -601,7 +562,6 @@ const Main: FC = ({ type={botTrustRequest?.type} shouldRequestWriteAccess={botTrustRequest?.shouldRequestWriteAccess} /> - {isPremiumModalOpen && } @@ -612,7 +572,6 @@ const Main: FC = ({ - ); }; @@ -630,13 +589,9 @@ export default memo(withGlobal( const { botTrustRequest, - requestedAttachBotInstall, requestedAttachBotInChat, requestedDraft, - urlAuth, - webApp, safeLinkModalUrl, - mapModal, openedStickerSetShortName, openedCustomEmojiSetIds, shouldSkipHistoryAnimations, @@ -655,11 +610,6 @@ export default memo(withGlobal( payment, limitReachedModal, deleteFolderDialogModal, - chatlistModal, - boostModal, - giftCodeModal, - inviteViaLinkModal, - oneTimeMediaModal, } = selectTabState(global); const { chatId: audioChatId, messageId: audioMessageId } = audioPlayer; @@ -668,7 +618,6 @@ export default memo(withGlobal( : undefined; const gameMessage = openedGame && selectChatMessage(global, openedGame.chatId, openedGame.messageId); const gameTitle = gameMessage?.content.game?.title; - const currentUser = global.currentUserId ? selectUser(global, global.currentUserId) : undefined; const { chatId } = selectCurrentMessageList(global) || {}; const noRightColumnAnimation = !selectPerformanceSettingsValue(global, 'rightColumnAnimations') || !selectCanAnimateInterface(global); @@ -688,8 +637,6 @@ export default memo(withGlobal( hasDialogs: Boolean(dialogs.length), audioMessage, safeLinkModalUrl, - mapModalGeoPoint: mapModal?.point, - mapModalZoom: mapModal?.zoom, isHistoryCalendarOpen: Boolean(historyCalendarSelectedAt), shouldSkipHistoryAnimations, openedStickerSetShortName, @@ -709,11 +656,7 @@ export default memo(withGlobal( isRatePhoneCallModalOpen: Boolean(ratingPhoneCall), botTrustRequest, botTrustRequestBot: botTrustRequest && selectUser(global, botTrustRequest.botId), - attachBotToInstall: requestedAttachBotInstall?.bot, requestedAttachBotInChat, - webApp, - currentUserName: getUserFullName(currentUser), - urlAuth, isCurrentUserPremium: selectIsCurrentUserPremium(global), isPremiumModalOpen: premiumModal?.isOpen, isGiveawayModalOpen: giveawayModal?.isOpen, @@ -724,13 +667,8 @@ export default memo(withGlobal( deleteFolderDialog, isMasterTab, requestedDraft, - chatlistModal, - boostModal, - giftCodeModal, noRightColumnAnimation, isSynced: global.isSynced, - inviteViaLinkModal, - oneTimeMediaModal, }; }, )(Main)); diff --git a/src/components/modals/ModalContainer.tsx b/src/components/modals/ModalContainer.tsx new file mode 100644 index 000000000..ecddef7eb --- /dev/null +++ b/src/components/modals/ModalContainer.tsx @@ -0,0 +1,66 @@ +import React, { memo } from '../../lib/teact/teact'; +import { withGlobal } from '../../global'; + +import type { TabState } from '../../global/types'; + +import { selectTabState } from '../../global/selectors'; +import { pick } from '../../util/iteratees'; + +import AttachBotInstallModal from './attachBotInstall/AttachBotInstallModal.async'; +import BoostModal from './boost/BoostModal.async'; +import ChatlistModal from './chatlist/ChatlistModal.async'; +import GiftCodeModal from './giftcode/GiftCodeModal.async'; +import InviteViaLinkModal from './inviteViaLink/InviteViaLinkModal.async'; +import OneTimeMediaModal from './oneTimeMedia/OneTimeMediaModal.async'; +import UrlAuthModal from './urlAuth/UrlAuthModal.async'; +import WebAppModal from './webApp/WebAppModal.async'; + +// `Pick` used only to provide tab completion +type ModalKey = keyof Pick; + +type StateProps = { + [K in ModalKey]?: TabState[K]; +}; +type ModalRegistry = { + [K in ModalKey]: React.FC<{ + modal: TabState[K]; + }>; +}; +type Entries = { + [K in keyof T]: [K, T[K]]; +}[keyof T][]; + +const MODALS: ModalRegistry = { + giftCodeModal: GiftCodeModal, + boostModal: BoostModal, + chatlistModal: ChatlistModal, + urlAuth: UrlAuthModal, + oneTimeMediaModal: OneTimeMediaModal, + inviteViaLinkModal: InviteViaLinkModal, + requestedAttachBotInstall: AttachBotInstallModal, + webApp: WebAppModal, +}; +const MODAL_KEYS = Object.keys(MODALS) as ModalKey[]; +const MODAL_ENTRIES = Object.entries(MODALS) as Entries; + +const ModalContainer = (modalProps: StateProps) => { + return MODAL_ENTRIES.map(([key, ModalComponent]) => ( + // @ts-ignore -- TS does not preserve tuple types in `map` callbacks + + )); +}; + +export default memo(withGlobal( + (global): StateProps => ( + pick(selectTabState(global), MODAL_KEYS) + ), +)(ModalContainer)); diff --git a/src/components/modals/attachBotInstall/AttachBotInstallModal.async.tsx b/src/components/modals/attachBotInstall/AttachBotInstallModal.async.tsx index 96b878fc8..8e72737f8 100644 --- a/src/components/modals/attachBotInstall/AttachBotInstallModal.async.tsx +++ b/src/components/modals/attachBotInstall/AttachBotInstallModal.async.tsx @@ -8,8 +8,8 @@ import { Bundles } from '../../../util/moduleLoader'; import useModuleLoader from '../../../hooks/useModuleLoader'; const AttachBotInstallModalAsync: FC = (props) => { - const { bot } = props; - const AttachBotInstallModal = useModuleLoader(Bundles.Extra, 'AttachBotInstallModal', !bot); + const { modal } = props; + const AttachBotInstallModal = useModuleLoader(Bundles.Extra, 'AttachBotInstallModal', !modal); // eslint-disable-next-line react/jsx-props-no-spreading return AttachBotInstallModal ? : undefined; diff --git a/src/components/modals/attachBotInstall/AttachBotInstallModal.tsx b/src/components/modals/attachBotInstall/AttachBotInstallModal.tsx index 5a2759695..2a8343d1a 100644 --- a/src/components/modals/attachBotInstall/AttachBotInstallModal.tsx +++ b/src/components/modals/attachBotInstall/AttachBotInstallModal.tsx @@ -4,7 +4,7 @@ import React, { } from '../../../lib/teact/teact'; import { getActions } from '../../../global'; -import type { ApiAttachBot } from '../../../api/types'; +import type { TabState } from '../../../global/types'; import { MINI_APP_TOS_URL } from '../../../config'; import renderText from '../../common/helpers/renderText'; @@ -15,13 +15,15 @@ import Checkbox from '../../ui/Checkbox'; import ConfirmDialog from '../../ui/ConfirmDialog'; export type OwnProps = { - bot?: ApiAttachBot; + modal: TabState['requestedAttachBotInstall']; }; const AttachBotInstallModal: FC = ({ - bot, + modal, }) => { const { confirmAttachBotInstall, cancelAttachBotInstall } = getActions(); + const bot = modal?.bot; + const [isTosAccepted, setIsTosAccepted] = useState(false); const lang = useLang(); diff --git a/src/components/modals/boost/BoostModal.async.tsx b/src/components/modals/boost/BoostModal.async.tsx index c6027accc..9f5e5fa50 100644 --- a/src/components/modals/boost/BoostModal.async.tsx +++ b/src/components/modals/boost/BoostModal.async.tsx @@ -8,8 +8,8 @@ import { Bundles } from '../../../util/moduleLoader'; import useModuleLoader from '../../../hooks/useModuleLoader'; const BoostModalAsync: FC = (props) => { - const { info } = props; - const BoostModal = useModuleLoader(Bundles.Extra, 'BoostModal', !info); + const { modal } = props; + const BoostModal = useModuleLoader(Bundles.Extra, 'BoostModal', !modal); // eslint-disable-next-line react/jsx-props-no-spreading return BoostModal ? : undefined; diff --git a/src/components/modals/boost/BoostModal.tsx b/src/components/modals/boost/BoostModal.tsx index 2345ac6d8..2b383b96f 100644 --- a/src/components/modals/boost/BoostModal.tsx +++ b/src/components/modals/boost/BoostModal.tsx @@ -46,7 +46,7 @@ type BoostInfo = ({ } & LoadedParams); export type OwnProps = { - info: TabState['boostModal']; + modal: TabState['boostModal']; }; type StateProps = { @@ -57,7 +57,7 @@ type StateProps = { }; const BoostModal = ({ - info, + modal, chat, chatFullInfo, prevBoostedChat, @@ -77,7 +77,7 @@ const BoostModal = ({ const isChannel = chat && isChatChannel(chat); - const isOpen = Boolean(info); + const isOpen = Boolean(modal); const lang = useLang(); @@ -115,7 +115,7 @@ const BoostModal = ({ descriptionText, canBoostMore, }: BoostInfo = useMemo(() => { - if (!info?.boostStatus || !chat) { + if (!modal?.boostStatus || !chat) { return { isStatusLoaded: false, title: lang('Loading'), @@ -124,10 +124,10 @@ const BoostModal = ({ const { hasMyBoost, - } = info.boostStatus; + } = modal.boostStatus; - const firstBoost = info?.myBoosts && getFirstAvailableBoost(info.myBoosts, chat.id); - const areBoostsInDifferentChannels = info?.myBoosts && !areAllBoostsInChannel(info.myBoosts, chat.id); + const firstBoost = modal?.myBoosts && getFirstAvailableBoost(modal.myBoosts, chat.id); + const areBoostsInDifferentChannels = modal?.myBoosts && !areAllBoostsInChannel(modal.myBoosts, chat.id); const { boosts, @@ -136,7 +136,7 @@ const BoostModal = ({ levelProgress, remainingBoosts, isMaxLevel, - } = getBoostProgressInfo(info.boostStatus, true); + } = getBoostProgressInfo(modal.boostStatus, true); const hasBoost = hasMyBoost; @@ -172,10 +172,10 @@ const BoostModal = ({ isBoosted: hasBoost, canBoostMore: areBoostsInDifferentChannels && !isMaxLevel, }; - }, [chat, chatTitle, info, lang, chatFullInfo, isChannel]); + }, [chat, chatTitle, modal, lang, chatFullInfo, isChannel]); - const isBoostDisabled = !info?.myBoosts?.length && isCurrentUserPremium; - const isReplacingBoost = boost?.chatId && boost.chatId !== info?.chatId; + const isBoostDisabled = !modal?.myBoosts?.length && isCurrentUserPremium; + const isReplacingBoost = boost?.chatId && boost.chatId !== modal?.chatId; const handleApplyBoost = useLastCallback(() => { closeReplaceModal(); @@ -342,10 +342,10 @@ function areAllBoostsInChannel(myBoosts: ApiMyBoost[], chatId: string) { } export default memo(withGlobal( - (global, { info }): StateProps => { - const chat = info && selectChat(global, info?.chatId); + (global, { modal }): StateProps => { + const chat = modal && selectChat(global, modal?.chatId); const chatFullInfo = chat && selectChatFullInfo(global, chat.id); - const firstBoost = info?.myBoosts && getFirstAvailableBoost(info.myBoosts, info.chatId); + const firstBoost = modal?.myBoosts && getFirstAvailableBoost(modal.myBoosts, modal.chatId); const boostedChat = firstBoost?.chatId ? selectChat(global, firstBoost?.chatId) : undefined; return { diff --git a/src/components/modals/chatlist/ChatlistModal.async.tsx b/src/components/modals/chatlist/ChatlistModal.async.tsx index 8691de88a..638eba508 100644 --- a/src/components/modals/chatlist/ChatlistModal.async.tsx +++ b/src/components/modals/chatlist/ChatlistModal.async.tsx @@ -8,8 +8,8 @@ import { Bundles } from '../../../util/moduleLoader'; import useModuleLoader from '../../../hooks/useModuleLoader'; const ChatlistModalAsync: FC = (props) => { - const { info } = props; - const ChatlistModal = useModuleLoader(Bundles.Extra, 'ChatlistModal', !info); + const { modal } = props; + const ChatlistModal = useModuleLoader(Bundles.Extra, 'ChatlistModal', !modal); // eslint-disable-next-line react/jsx-props-no-spreading return ChatlistModal ? : undefined; diff --git a/src/components/modals/chatlist/ChatlistModal.tsx b/src/components/modals/chatlist/ChatlistModal.tsx index 8f11fbcff..81fdc1d74 100644 --- a/src/components/modals/chatlist/ChatlistModal.tsx +++ b/src/components/modals/chatlist/ChatlistModal.tsx @@ -19,7 +19,7 @@ import ChatlistNew from './ChatlistNew'; import styles from './ChatlistModal.module.scss'; export type OwnProps = { - info?: TabState['chatlistModal']; + modal?: TabState['chatlistModal']; }; type StateProps = { @@ -27,15 +27,15 @@ type StateProps = { }; const ChatlistInviteModal: FC = ({ - info, + modal, folder, }) => { const { closeChatlistModal } = getActions(); const lang = useLang(); - const isOpen = Boolean(info); - const renderingInfo = usePrevious(info) || info; + const isOpen = Boolean(modal); + const renderingInfo = usePrevious(modal) || modal; const renderingFolder = usePrevious(folder) || folder; const title = useMemo(() => { @@ -111,8 +111,8 @@ const ChatlistInviteModal: FC = ({ }; export default memo(withGlobal( - (global, { info }): StateProps => { - const { invite, removal } = info || {}; + (global, { modal }): StateProps => { + const { invite, removal } = modal || {}; const folderId = removal?.folderId || (invite && 'folderId' in invite ? invite.folderId : undefined); const folder = folderId ? selectChatFolder(global, folderId) : undefined; diff --git a/src/components/modals/inviteViaLink/InviteViaLinkModal.async.tsx b/src/components/modals/inviteViaLink/InviteViaLinkModal.async.tsx index a26fcf32b..d9d480996 100644 --- a/src/components/modals/inviteViaLink/InviteViaLinkModal.async.tsx +++ b/src/components/modals/inviteViaLink/InviteViaLinkModal.async.tsx @@ -8,8 +8,8 @@ import { Bundles } from '../../../util/moduleLoader'; import useModuleLoader from '../../../hooks/useModuleLoader'; const InviteViaLinkModalAsync: FC = (props) => { - const { chatId } = props; - const InviteViaLinkModal = useModuleLoader(Bundles.Extra, 'InviteViaLinkModal', !chatId); + const { modal } = props; + const InviteViaLinkModal = useModuleLoader(Bundles.Extra, 'InviteViaLinkModal', !modal); // eslint-disable-next-line react/jsx-props-no-spreading return InviteViaLinkModal ? : undefined; diff --git a/src/components/modals/inviteViaLink/InviteViaLinkModal.tsx b/src/components/modals/inviteViaLink/InviteViaLinkModal.tsx index 46f631638..6c191f97f 100644 --- a/src/components/modals/inviteViaLink/InviteViaLinkModal.tsx +++ b/src/components/modals/inviteViaLink/InviteViaLinkModal.tsx @@ -6,7 +6,8 @@ import React, { } from '../../../lib/teact/teact'; import { getActions, getGlobal, withGlobal } from '../../../global'; -import type { ApiChat, ApiMissingInvitedUser } from '../../../api/types'; +import type { ApiChat } from '../../../api/types'; +import type { TabState } from '../../../global/types'; import { getUserFullName } from '../../../global/helpers'; import { selectChat } from '../../../global/selectors'; @@ -25,8 +26,7 @@ import Separator from '../../ui/Separator'; import styles from './InviteViaLinkModal.module.scss'; export type OwnProps = { - chatId?: string; - missingUsers?: ApiMissingInvitedUser[]; + modal: TabState['inviteViaLinkModal']; }; type StateProps = { @@ -34,10 +34,11 @@ type StateProps = { }; const InviteViaLinkModal: FC = ({ - missingUsers, + modal, chat, }) => { const { sendInviteMessages, closeInviteViaLinkModal, openPremiumModal } = getActions(); + const { missingUsers } = modal || {}; const lang = useLang(); const [selectedMemberIds, setSelectedMemberIds] = useState([]); @@ -196,8 +197,8 @@ const InviteViaLinkModal: FC = ({ }; export default memo(withGlobal( - (global, { chatId }): StateProps => { - const chat = chatId ? selectChat(global, chatId) : undefined; + (global, { modal }): StateProps => { + const chat = modal?.chatId ? selectChat(global, modal.chatId) : undefined; return { chat, diff --git a/src/components/modals/map/MapModal.async.tsx b/src/components/modals/map/MapModal.async.tsx index 719c076e7..9c093dd27 100644 --- a/src/components/modals/map/MapModal.async.tsx +++ b/src/components/modals/map/MapModal.async.tsx @@ -8,8 +8,8 @@ import { Bundles } from '../../../util/moduleLoader'; import useModuleLoader from '../../../hooks/useModuleLoader'; const MapModalAsync: FC = (props) => { - const { geoPoint } = props; - const MapModal = useModuleLoader(Bundles.Extra, 'MapModal', !geoPoint); + const { modal } = props; + const MapModal = useModuleLoader(Bundles.Extra, 'MapModal', !modal); // eslint-disable-next-line react/jsx-props-no-spreading return MapModal ? : undefined; diff --git a/src/components/modals/map/MapModal.tsx b/src/components/modals/map/MapModal.tsx index 0334a2a34..c41fcbd2e 100644 --- a/src/components/modals/map/MapModal.tsx +++ b/src/components/modals/map/MapModal.tsx @@ -1,7 +1,7 @@ import React, { memo, useMemo } from '../../../lib/teact/teact'; import { getActions } from '../../../global'; -import type { ApiGeoPoint } from '../../../api/types'; +import type { TabState } from '../../../global/types'; import { prepareMapUrl } from '../../../util/map'; import { IS_IOS, IS_MAC_OS } from '../../../util/windowEnvironment'; @@ -15,13 +15,14 @@ import Modal from '../../ui/Modal'; import styles from './MapModal.module.scss'; export type OwnProps = { - geoPoint?: ApiGeoPoint; - zoom?: number; + modal: TabState['mapModal']; }; -const OpenMapModal = ({ geoPoint, zoom }: OwnProps) => { +const OpenMapModal = ({ modal }: OwnProps) => { const { closeMapModal } = getActions(); + const { point: geoPoint, zoom } = modal || {}; + const lang = useLang(); const isOpen = Boolean(geoPoint); diff --git a/src/components/modals/oneTimeMedia/OneTimeMediaModal.async.tsx b/src/components/modals/oneTimeMedia/OneTimeMediaModal.async.tsx index 6edd5b050..b344fe726 100644 --- a/src/components/modals/oneTimeMedia/OneTimeMediaModal.async.tsx +++ b/src/components/modals/oneTimeMedia/OneTimeMediaModal.async.tsx @@ -8,8 +8,8 @@ import { Bundles } from '../../../util/moduleLoader'; import useModuleLoader from '../../../hooks/useModuleLoader'; const OneTimeMediaModalAsync: FC = (props) => { - const { info } = props; - const OneTimeMediaModal = useModuleLoader(Bundles.Extra, 'OneTimeMediaModal', !info); + const { modal } = props; + const OneTimeMediaModal = useModuleLoader(Bundles.Extra, 'OneTimeMediaModal', !modal); // eslint-disable-next-line react/jsx-props-no-spreading return OneTimeMediaModal ? : undefined; diff --git a/src/components/modals/oneTimeMedia/OneTimeMediaModal.tsx b/src/components/modals/oneTimeMedia/OneTimeMediaModal.tsx index cfef01749..965535b67 100644 --- a/src/components/modals/oneTimeMedia/OneTimeMediaModal.tsx +++ b/src/components/modals/oneTimeMedia/OneTimeMediaModal.tsx @@ -20,23 +20,23 @@ import Button from '../../ui/Button'; import styles from './OneTimeMediaModal.module.scss'; export type OwnProps = { - info: TabState['oneTimeMediaModal']; + modal: TabState['oneTimeMediaModal']; }; const OneTimeMediaModal = ({ - info, + modal, }: OwnProps) => { const { closeOneTimeMediaModal, } = getActions(); const lang = useLang(); - const message = useCurrentOrPrev(info?.message, true); + const message = useCurrentOrPrev(modal?.message, true); const { shouldRender, transitionClassNames, - } = useShowTransition(Boolean(info)); + } = useShowTransition(Boolean(modal)); const handlePlayVoice = useLastCallback(() => { return undefined; diff --git a/src/components/modals/urlAuth/UrlAuthModal.async.tsx b/src/components/modals/urlAuth/UrlAuthModal.async.tsx index d3568db25..5accd59f4 100644 --- a/src/components/modals/urlAuth/UrlAuthModal.async.tsx +++ b/src/components/modals/urlAuth/UrlAuthModal.async.tsx @@ -8,8 +8,8 @@ import { Bundles } from '../../../util/moduleLoader'; import useModuleLoader from '../../../hooks/useModuleLoader'; const UrlAuthModalAsync: FC = (props) => { - const { urlAuth } = props; - const UrlAuthModal = useModuleLoader(Bundles.Extra, 'UrlAuthModal', !urlAuth); + const { modal } = props; + const UrlAuthModal = useModuleLoader(Bundles.Extra, 'UrlAuthModal', !modal); // eslint-disable-next-line react/jsx-props-no-spreading return UrlAuthModal ? : undefined; diff --git a/src/components/modals/urlAuth/UrlAuthModal.tsx b/src/components/modals/urlAuth/UrlAuthModal.tsx index d8a9bab15..c8782161c 100644 --- a/src/components/modals/urlAuth/UrlAuthModal.tsx +++ b/src/components/modals/urlAuth/UrlAuthModal.tsx @@ -2,11 +2,13 @@ import type { FC } from '../../../lib/teact/teact'; import React, { memo, useCallback, useEffect, useState, } from '../../../lib/teact/teact'; -import { getActions, getGlobal } from '../../../global'; +import { getActions, getGlobal, withGlobal } from '../../../global'; +import type { ApiUser } from '../../../api/types'; import type { TabState } from '../../../global/types'; import { getUserFullName } from '../../../global/helpers'; +import { selectUser } from '../../../global/selectors'; import { ensureProtocol } from '../../../util/ensureProtocol'; import renderText from '../../common/helpers/renderText'; @@ -19,25 +21,28 @@ import ConfirmDialog from '../../ui/ConfirmDialog'; import styles from './UrlAuthModal.module.scss'; export type OwnProps = { - urlAuth?: TabState['urlAuth']; - currentUserName?: string; + modal?: TabState['urlAuth']; }; -const UrlAuthModal: FC = ({ - urlAuth, currentUserName, +type StateProps = { + currentUser?: ApiUser; +}; + +const UrlAuthModal: FC = ({ + modal, currentUser, }) => { const { closeUrlAuthModal, acceptBotUrlAuth, acceptLinkUrlAuth } = getActions(); const [isLoginChecked, setLoginChecked] = useState(true); const [isWriteAccessChecked, setWriteAccessChecked] = useState(true); - const currentAuth = useCurrentOrPrev(urlAuth, false); + const currentAuth = useCurrentOrPrev(modal, false); const { domain, botId, shouldRequestWriteAccess } = currentAuth?.request || {}; const bot = botId ? getGlobal().users.byId[botId] : undefined; const lang = useLang(); const handleOpen = useCallback(() => { - if (urlAuth?.url && isLoginChecked) { - const acceptAction = urlAuth.button ? acceptBotUrlAuth : acceptLinkUrlAuth; + if (modal?.url && isLoginChecked) { + const acceptAction = modal.button ? acceptBotUrlAuth : acceptLinkUrlAuth; acceptAction({ isWriteAllowed: isWriteAccessChecked, }); @@ -46,7 +51,7 @@ const UrlAuthModal: FC = ({ } closeUrlAuthModal(); }, [ - urlAuth, isLoginChecked, closeUrlAuthModal, acceptBotUrlAuth, acceptLinkUrlAuth, isWriteAccessChecked, currentAuth, + modal, isLoginChecked, closeUrlAuthModal, acceptBotUrlAuth, acceptLinkUrlAuth, isWriteAccessChecked, currentAuth, ]); const handleDismiss = useCallback(() => { @@ -68,7 +73,7 @@ const UrlAuthModal: FC = ({ return ( = ({ label={( <> {renderText( - lang('Conversation.OpenBotLinkLogin', [domain, currentUserName]), + lang('Conversation.OpenBotLinkLogin', [domain, getUserFullName(currentUser)]), ['simple_markdown'], )} @@ -109,5 +114,11 @@ const UrlAuthModal: FC = ({ ); }; - -export default memo(UrlAuthModal); +export default memo(withGlobal( + (global): StateProps => { + const currentUser = selectUser(global, global.currentUserId!); + return { + currentUser, + }; + }, +)(UrlAuthModal)); diff --git a/src/components/modals/webApp/WebAppModal.async.tsx b/src/components/modals/webApp/WebAppModal.async.tsx index 321b00c2d..00d83a484 100644 --- a/src/components/modals/webApp/WebAppModal.async.tsx +++ b/src/components/modals/webApp/WebAppModal.async.tsx @@ -8,8 +8,8 @@ import { Bundles } from '../../../util/moduleLoader'; import useModuleLoader from '../../../hooks/useModuleLoader'; const WebAppModalAsync: FC = (props) => { - const { webApp } = props; - const WebAppModal = useModuleLoader(Bundles.Extra, 'WebAppModal', !webApp); + const { modal } = props; + const WebAppModal = useModuleLoader(Bundles.Extra, 'WebAppModal', !modal); // eslint-disable-next-line react/jsx-props-no-spreading return WebAppModal ? : undefined; diff --git a/src/components/modals/webApp/WebAppModal.tsx b/src/components/modals/webApp/WebAppModal.tsx index fa8adaffc..296624a8a 100644 --- a/src/components/modals/webApp/WebAppModal.tsx +++ b/src/components/modals/webApp/WebAppModal.tsx @@ -52,7 +52,7 @@ type WebAppButton = { }; export type OwnProps = { - webApp?: TabState['webApp']; + modal?: TabState['webApp']; }; type StateProps = { @@ -88,7 +88,7 @@ const DEFAULT_BUTTON_TEXT: Record = { }; const WebAppModal: FC = ({ - webApp, + modal, chat, bot, attachBot, @@ -141,7 +141,7 @@ const WebAppModal: FC = ({ const lang = useLang(); const { url, buttonText, queryId, replyInfo, - } = webApp || {}; + } = modal || {}; const isOpen = Boolean(url); const isSimple = Boolean(buttonText); @@ -173,7 +173,7 @@ const WebAppModal: FC = ({ }); const handleRefreshClick = useLastCallback(() => { - reloadFrame(webApp!.url); + reloadFrame(modal!.url); }); const handleClose = useLastCallback(() => { @@ -215,11 +215,11 @@ const WebAppModal: FC = ({ useSyncEffect(([prevIsPaymentModalOpen]) => { if (isPaymentModalOpen === prevIsPaymentModalOpen) return; - if (webApp?.slug && !isPaymentModalOpen && paymentStatus) { + if (modal?.slug && !isPaymentModalOpen && paymentStatus) { sendEvent({ eventType: 'invoice_closed', eventData: { - slug: webApp.slug, + slug: modal.slug, status: paymentStatus, }, }); @@ -227,7 +227,7 @@ const WebAppModal: FC = ({ slug: undefined, }); } - }, [isPaymentModalOpen, paymentStatus, sendEvent, setWebAppPaymentSlug, webApp]); + }, [isPaymentModalOpen, paymentStatus, sendEvent, modal?.slug]); const handleRemoveAttachBot = useLastCallback(() => { toggleAttachBot({ @@ -693,8 +693,8 @@ const WebAppModal: FC = ({ }; export default memo(withGlobal( - (global, { webApp }): StateProps => { - const { botId } = webApp || {}; + (global, { modal }): StateProps => { + const { botId } = modal || {}; const attachBot = botId ? global.attachMenu.bots[botId] : undefined; const bot = botId ? selectUser(global, botId) : undefined; const chat = selectCurrentChat(global);