diff --git a/src/components/modals/attachBotInstall/AttachBotInstallModal.tsx b/src/components/modals/attachBotInstall/AttachBotInstallModal.tsx index 0dfd129dc..5a2759695 100644 --- a/src/components/modals/attachBotInstall/AttachBotInstallModal.tsx +++ b/src/components/modals/attachBotInstall/AttachBotInstallModal.tsx @@ -65,9 +65,7 @@ const AttachBotInstallModal: FC = ({ label={tosLabel} onCheck={setIsTosAccepted} /> - {bot?.isInactive && bot.isForSideMenu && ( - renderText(lang('WebBot.Account.Desclaimer.Desc', bot?.shortName), ['simple_markdown']) - )} + {renderText(lang('WebBot.Account.Desclaimer.Desc', bot?.shortName), ['simple_markdown'])} ); }; diff --git a/src/components/modals/webApp/WebAppModal.tsx b/src/components/modals/webApp/WebAppModal.tsx index cdf745bbc..2902dce81 100644 --- a/src/components/modals/webApp/WebAppModal.tsx +++ b/src/components/modals/webApp/WebAppModal.tsx @@ -20,6 +20,7 @@ import { getColorLuma } from '../../../util/colors'; import { hexToRgb } from '../../../util/switchTheme'; import { extractCurrentThemeParams, validateHexColor } from '../../../util/themeStyle'; import { callApi } from '../../../api/gramjs'; +import renderText from '../../common/helpers/renderText'; import useAppLayout from '../../../hooks/useAppLayout'; import useFlag from '../../../hooks/useFlag'; @@ -31,6 +32,7 @@ import useSyncEffect from '../../../hooks/useSyncEffect'; import usePopupLimit from './hooks/usePopupLimit'; import useWebAppFrame from './hooks/useWebAppFrame'; +import Icon from '../../common/Icon'; import Button from '../../ui/Button'; import ConfirmDialog from '../../ui/ConfirmDialog'; import DropdownMenu from '../../ui/DropdownMenu'; @@ -114,6 +116,7 @@ const WebAppModal: FC = ({ const [shouldConfirmClosing, setShouldConfirmClosing] = useState(false); const [isCloseModalOpen, openCloseModal, hideCloseModal] = useFlag(false); + const [isRemoveModalOpen, openRemoveModal, hideRemoveModal] = useFlag(false); const [isLoaded, markLoaded, markUnloaded] = useFlag(false); @@ -226,10 +229,23 @@ const WebAppModal: FC = ({ } }, [isPaymentModalOpen, paymentStatus, sendEvent, setWebAppPaymentSlug, webApp]); - const handleToggleClick = useLastCallback(() => { + const handleRemoveAttachBot = useLastCallback(() => { toggleAttachBot({ botId: bot!.id, - isEnabled: !attachBot, + isEnabled: false, + }); + closeWebApp(); + }); + + const handleToggleClick = useLastCallback(() => { + if (attachBot) { + openRemoveModal(); + return; + } + + toggleAttachBot({ + botId: bot!.id, + isEnabled: true, }); }); @@ -340,6 +356,7 @@ const WebAppModal: FC = ({ setShouldConfirmClosing(false); hideCloseModal(); + hideRemoveModal(); setPopupParameters(undefined); setIsRequestingPhone(false); setIsRequestingWriteAccess(false); @@ -350,7 +367,7 @@ const WebAppModal: FC = ({ setHeaderColor(themeParams.bg_color); markUnloaded(); } - }, [hideCloseModal, isOpen, markUnloaded]); + }, [isOpen]); function handleEvent(event: WebAppInboundEvent) { const { eventType, eventData } = event; @@ -479,7 +496,7 @@ const WebAppModal: FC = ({ onClick={onTrigger} ariaLabel="More actions" > - + ); }, [isMobile]); @@ -663,6 +680,14 @@ const WebAppModal: FC = ({ confirmIsDestructive confirmLabel={lang('lng_bot_close_warning_sure')} /> + ); }; diff --git a/src/global/actions/api/bots.ts b/src/global/actions/api/bots.ts index f95ae1581..ef8365491 100644 --- a/src/global/actions/api/bots.ts +++ b/src/global/actions/api/bots.ts @@ -586,13 +586,46 @@ addActionHandler('requestWebView', async (global, actions, payload): Promise => { const { - botId, appName, startApp, theme, isWriteAllowed, + botId, appName, startApp, theme, isWriteAllowed, isFromConfirm, tabId = getCurrentTabId(), } = payload; const bot = selectUser(global, botId); if (!bot) return; + // Native clients require to install attach bots before using their named mini apps + const isAttachBotInstalled = Boolean(global.attachMenu.bots[bot.id]); + if (bot.isAttachBot && !isFromConfirm && !isAttachBotInstalled) { + const result = await callApi('loadAttachBot', { + bot, + }); + if (result) { + const attachBot = result.bot; + global = getGlobal(); + global = addUsers(global, buildCollectionByKey(result.users, 'id')); + setGlobal(global); + + const shouldAskForTos = attachBot.isDisclaimerNeeded || attachBot.isForAttachMenu || attachBot.isForSideMenu; + + if (shouldAskForTos) { + global = updateTabState(global, { + requestedAttachBotInstall: { + bot: attachBot, + onConfirm: { + action: 'requestAppWebView', + payload: { + ...payload, + isFromConfirm: true, + }, + }, + }, + }, tabId); + setGlobal(global); + return; + } + } + } + const botApp = await callApi('fetchBotApp', { bot, appName, diff --git a/src/global/types.ts b/src/global/types.ts index 4dab905fb..53b9062a8 100644 --- a/src/global/types.ts +++ b/src/global/types.ts @@ -2563,6 +2563,7 @@ export interface ActionPayloads { theme?: ApiThemeParameters; startApp?: string; isWriteAllowed?: boolean; + isFromConfirm?: boolean; } & WithTabId; setWebAppPaymentSlug: { slug?: string;