diff --git a/src/components/modals/webApp/MinimizedWebAppModal.tsx b/src/components/modals/webApp/MinimizedWebAppModal.tsx index f7354cc22..2e1df861e 100644 --- a/src/components/modals/webApp/MinimizedWebAppModal.tsx +++ b/src/components/modals/webApp/MinimizedWebAppModal.tsx @@ -7,7 +7,7 @@ import { getActions, getGlobal, withGlobal } from '../../../global'; import type { ApiUser } from '../../../api/types'; import type { WebApp } from '../../../global/types'; -import { selectTabState, selectUser } from '../../../global/selectors'; +import { selectActiveWebApp, selectTabState, selectUser } from '../../../global/selectors'; import buildClassName from '../../../util/buildClassName'; import { unique } from '../../../util/iteratees'; @@ -126,7 +126,7 @@ export default memo(withGlobal( const tabState = selectTabState(global); const webApps = tabState.webApps; - const { botId } = webApps?.activeWebApp || {}; + const { botId } = selectActiveWebApp(global) || {}; const { modalState, openedWebApps } = webApps || {}; const isMinimizedState = modalState === 'minimized'; const activeTabBot = botId ? selectUser(global, botId) : undefined; diff --git a/src/components/modals/webApp/WebAppModal.tsx b/src/components/modals/webApp/WebAppModal.tsx index 91bfa2ee9..e7636c161 100644 --- a/src/components/modals/webApp/WebAppModal.tsx +++ b/src/components/modals/webApp/WebAppModal.tsx @@ -15,6 +15,7 @@ import type { WebAppOutboundEvent } from '../../../types/webapp'; import { getWebAppKey } from '../../../global/helpers/bots'; import { selectCurrentChat, selectTheme, selectUser, + selectWebApp, } from '../../../global/selectors'; import buildClassName from '../../../util/buildClassName'; import buildStyle from '../../../util/buildStyle'; @@ -103,8 +104,9 @@ const WebAppModal: FC = ({ } const { - openedWebApps, activeWebApp, openedOrderedKeys, sessionKeys, isMoreAppsTabActive, + openedWebApps, activeWebAppKey, openedOrderedKeys, sessionKeys, isMoreAppsTabActive, } = modal || {}; + const activeWebApp = activeWebAppKey ? openedWebApps?.[activeWebAppKey] : undefined; const { isBackButtonVisible, headerColor, backgroundColor, isSettingsButtonVisible, } = activeWebApp || {}; @@ -664,7 +666,8 @@ const WebAppModal: FC = ({ export default memo(withGlobal( (global, { modal }): StateProps => { - const { botId: activeBotId } = modal?.activeWebApp || {}; + const activeWebApp = modal?.activeWebAppKey ? selectWebApp(global, modal.activeWebAppKey) : undefined; + const { botId: activeBotId } = activeWebApp || {}; const attachBot = activeBotId ? global.attachMenu.bots[activeBotId] : undefined; const bot = activeBotId ? selectUser(global, activeBotId) : undefined; diff --git a/src/components/modals/webApp/WebAppModalTabContent.tsx b/src/components/modals/webApp/WebAppModalTabContent.tsx index c630b0dd9..8632fcbfc 100644 --- a/src/components/modals/webApp/WebAppModalTabContent.tsx +++ b/src/components/modals/webApp/WebAppModalTabContent.tsx @@ -15,6 +15,7 @@ import { convertToApiChatType } from '../../../global/helpers'; import { getWebAppKey } from '../../../global/helpers/bots'; import { selectCurrentChat, selectTabState, selectTheme, selectUser, + selectWebApp, } from '../../../global/selectors'; import buildClassName from '../../../util/buildClassName'; import buildStyle from '../../../util/buildStyle'; @@ -162,7 +163,7 @@ const WebAppModalTabContent: FC = ({ const [, setFullscreen, exitFullscreen] = useFullscreen(fullscreenElementRef, exitFullScreenCallback); - const activeWebApp = modal?.activeWebApp; + const activeWebApp = modal?.activeWebAppKey ? modal.openedWebApps[modal.activeWebAppKey] : undefined; const activeWebAppName = activeWebApp?.appName; const { url, buttonText, headerColor, serverHeaderColorKey, serverHeaderColor, isBackButtonVisible, @@ -962,7 +963,8 @@ const WebAppModalTabContent: FC = ({ export default memo(withGlobal( (global, { modal }): StateProps => { - const { botId: activeBotId } = modal?.activeWebApp || {}; + const activeWebApp = modal?.activeWebAppKey ? selectWebApp(global, modal.activeWebAppKey) : undefined; + const { botId: activeBotId } = activeWebApp || {}; const modalState = modal?.modalState; const attachBot = activeBotId ? global.attachMenu.bots[activeBotId] : undefined; diff --git a/src/global/actions/apiUpdaters/misc.ts b/src/global/actions/apiUpdaters/misc.ts index c394d95c5..6dbd2d39f 100644 --- a/src/global/actions/apiUpdaters/misc.ts +++ b/src/global/actions/apiUpdaters/misc.ts @@ -136,10 +136,12 @@ addActionHandler('apiUpdate', (global, actions, update): ActionReturnType => { case 'updateWebViewResultSent': Object.values(global.byTabId).forEach((tabState) => { - if (tabState.webApps.activeWebApp?.queryId === update.queryId) { - actions.resetDraftReplyInfo({ tabId: tabState.id }); - actions.closeActiveWebApp({ tabId: tabState.id }); - } + Object.entries(tabState.webApps.openedWebApps).forEach(([webAppKey, webApp]) => { + if (webApp.queryId === update.queryId) { + actions.resetDraftReplyInfo({ tabId: tabState.id }); + actions.closeWebApp({ key: webAppKey, tabId: tabState.id }); + } + }); }); break; diff --git a/src/global/actions/ui/bots.ts b/src/global/actions/ui/bots.ts index beb430d3c..2b33fa1aa 100644 --- a/src/global/actions/ui/bots.ts +++ b/src/global/actions/ui/bots.ts @@ -16,7 +16,9 @@ import { updateWebApp, } from '../../reducers/bots'; import { updateTabState } from '../../reducers/tabs'; -import { selectCurrentMessageList, selectTabState, selectWebApp } from '../../selectors'; +import { + selectActiveWebApp, selectCurrentMessageList, selectTabState, selectWebApp, +} from '../../selectors'; addActionHandler('openWebAppTab', (global, actions, payload): ActionReturnType => { const { @@ -53,7 +55,7 @@ addActionHandler('openMoreAppsTab', (global, actions, payload): ActionReturnType global = updateTabState(global, { webApps: { ...tabState.webApps, - activeWebApp: undefined, + activeWebAppKey: undefined, isMoreAppsTabActive: true, }, }, tabId); @@ -68,14 +70,14 @@ addActionHandler('closeMoreAppsTab', (global, actions, payload): ActionReturnTyp const openedWebApps = tabState.webApps.openedWebApps; - const openedWebAppsValues = Object.values(openedWebApps); - const openedWebAppsCount = openedWebAppsValues.length; + const openedWebAppsKeys = Object.keys(openedWebApps); + const openedWebAppsCount = openedWebAppsKeys.length; global = updateTabState(global, { webApps: { ...tabState.webApps, isMoreAppsTabActive: false, - activeWebApp: openedWebAppsCount ? openedWebAppsValues[openedWebAppsCount - 1] : undefined, + activeWebAppKey: openedWebAppsCount ? openedWebAppsKeys[openedWebAppsCount - 1] : undefined, isModalOpen: openedWebAppsCount > 0, }, }, tabId); @@ -117,8 +119,7 @@ addActionHandler('changeWebAppModalState', (global, actions, payload): ActionRet addActionHandler('setWebAppPaymentSlug', (global, actions, payload): ActionReturnType => { const { tabId = getCurrentTabId() } = payload; - const tabState = selectTabState(global, tabId); - const activeWebApp = tabState.webApps.activeWebApp; + const activeWebApp = selectActiveWebApp(global, tabId); if (!activeWebApp?.url) return undefined; const key = getWebAppKey(activeWebApp); diff --git a/src/global/reducers/bots.ts b/src/global/reducers/bots.ts index d953a6268..a85a3e5e4 100644 --- a/src/global/reducers/bots.ts +++ b/src/global/reducers/bots.ts @@ -5,7 +5,7 @@ import type { import { getCurrentTabId } from '../../util/establishMultitabRole'; import { getWebAppKey } from '../helpers/bots'; -import { selectTabState } from '../selectors'; +import { selectActiveWebApp, selectTabState } from '../selectors'; import { updateTabState } from './tabs'; export function replaceInlineBotSettings( @@ -55,14 +55,9 @@ export function updateWebApp ( const updatedWebAppKey = getWebAppKey(updatedValue); if (!updatedWebAppKey) return global; - const activeWebApp = currentTabState.webApps.activeWebApp; - const activeWebAppKey = activeWebApp && getWebAppKey(activeWebApp); global = updateTabState(global, { webApps: { ...currentTabState.webApps, - ...updatedWebAppKey === activeWebAppKey && { - activeWebApp: updatedValue, - }, openedWebApps: { ...openedWebApps, [updatedWebAppKey]: updatedValue, @@ -84,13 +79,11 @@ export function activateWebAppIfOpen( return global; } - const newActiveWebApp = openedWebApps[webAppKey]; - global = updateTabState(global, { webApps: { ...currentTabState.webApps, isMoreAppsTabActive: false, - activeWebApp: newActiveWebApp, + activeWebAppKey: webAppKey, modalState: 'maximized', }, }, tabId); @@ -119,7 +112,7 @@ export function addWebAppToOpenList( global = updateTabState(global, { webApps: { ...currentTabState.webApps, - ...makeActive && { activeWebApp: webApp }, + ...makeActive && { activeWebAppKey: key }, isMoreAppsTabActive: false, isModalOpen: openModalIfNotOpen, modalState: 'maximized', @@ -139,12 +132,11 @@ export function removeActiveWebAppFromOpenList( global: T, ...[tabId = getCurrentTabId()]: TabArgs ): T { const currentTabState = selectTabState(global, tabId); + const activeWebAppKey = currentTabState.webApps.activeWebAppKey; - if (!currentTabState.webApps.activeWebApp) return global; + if (!activeWebAppKey) return global; - const key = getWebAppKey(currentTabState.webApps.activeWebApp); - - return removeWebAppFromOpenList(global, key, false, tabId); + return removeWebAppFromOpenList(global, activeWebAppKey, false, tabId); } export function removeWebAppFromOpenList( @@ -152,7 +144,7 @@ export function removeWebAppFromOpenList( ...[tabId = getCurrentTabId()]: TabArgs ): T { const currentTabState = selectTabState(global, tabId); - const openedWebApps = currentTabState.webApps.openedWebApps; + const { openedWebApps, openedOrderedKeys, activeWebAppKey } = currentTabState.webApps; const webApp = openedWebApps[key]; if (!webApp) return global; @@ -163,26 +155,24 @@ export function removeWebAppFromOpenList( const updatedOpenedWebApps = { ...openedWebApps }; const removingWebAppKey = getWebAppKey(webApp); - let newOpenedKeys = currentTabState.webApps.openedOrderedKeys; + let newOpenedKeys = openedOrderedKeys; if (removingWebAppKey) { delete updatedOpenedWebApps[removingWebAppKey]; - newOpenedKeys = currentTabState.webApps.openedOrderedKeys.filter((k) => k !== removingWebAppKey); + newOpenedKeys = openedOrderedKeys.filter((k) => k !== removingWebAppKey); } - const activeWebApp = currentTabState.webApps.activeWebApp; + const isRemovedAppActive = activeWebAppKey === getWebAppKey(webApp); - const isRemovedAppActive = activeWebApp && (getWebAppKey(activeWebApp) === getWebAppKey(webApp)); - - const openedWebAppsValues = Object.values(updatedOpenedWebApps); - const openedWebAppsCount = openedWebAppsValues.length; + const openedWebAppsKeys = Object.keys(updatedOpenedWebApps); + const openedWebAppsCount = openedWebAppsKeys.length; global = updateTabState(global, { webApps: { ...currentTabState.webApps, ...isRemovedAppActive && { - activeWebApp: openedWebAppsCount - ? openedWebAppsValues[openedWebAppsCount - 1] : undefined, + activeWebAppKey: openedWebAppsCount + ? openedWebAppsKeys[openedWebAppsCount - 1] : undefined, }, openedWebApps: updatedOpenedWebApps, openedOrderedKeys: newOpenedKeys, @@ -203,8 +193,7 @@ export function clearOpenedWebApps( const webAppsNotAllowedToClose = Object.fromEntries( Object.entries(currentTabState.webApps.openedWebApps).filter( - // eslint-disable-next-line @typescript-eslint/no-unused-vars - ([url, webApp]) => webApp.shouldConfirmClosing, + ([, webApp]) => webApp.shouldConfirmClosing, ), ); @@ -215,7 +204,7 @@ export function clearOpenedWebApps( return updateTabState(global, { webApps: { ...currentTabState.webApps, - activeWebApp: undefined, + activeWebAppKey: undefined, openedWebApps: {}, openedOrderedKeys: [], sessionKeys: [], @@ -223,22 +212,25 @@ export function clearOpenedWebApps( }, tabId); } - const currentActiveWebApp = currentTabState.webApps.activeWebApp; + const currentActiveWebApp = selectActiveWebApp(global, tabId); const newActiveWebApp = currentActiveWebApp?.shouldConfirmClosing ? currentActiveWebApp : webAppsNotAllowedToCloseValues[0]; - newActiveWebApp.isCloseModalOpen = true; + const newActiveWebAppKey = getWebAppKey(newActiveWebApp); - const key = getWebAppKey(newActiveWebApp); - - if (key) webAppsNotAllowedToClose[key] = newActiveWebApp; - const newOpenedKeys = currentTabState.webApps.openedOrderedKeys.filter((k) => k in webAppsNotAllowedToClose); + if (newActiveWebAppKey) { + webAppsNotAllowedToClose[newActiveWebAppKey] = { + ...newActiveWebApp, + isCloseModalOpen: true, + }; + } + const newOpenedKeys = currentTabState.webApps.openedOrderedKeys.filter((k) => webAppsNotAllowedToClose[k]); return updateTabState(global, { webApps: { ...currentTabState.webApps, - activeWebApp: newActiveWebApp, + activeWebAppKey: newActiveWebAppKey, isMoreAppsTabActive: false, openedWebApps: webAppsNotAllowedToClose, openedOrderedKeys: newOpenedKeys, diff --git a/src/global/selectors/ui.ts b/src/global/selectors/ui.ts index 38ebb543a..2a26f993d 100644 --- a/src/global/selectors/ui.ts +++ b/src/global/selectors/ui.ts @@ -156,3 +156,12 @@ export function selectWebApp( ) { return selectTabState(global, tabId).webApps.openedWebApps[key]; } + +export function selectActiveWebApp( + global: T, ...[tabId = getCurrentTabId()]: TabArgs +) { + const activeWebAppKey = selectTabState(global, tabId).webApps.activeWebAppKey; + if (!activeWebAppKey) return undefined; + + return selectWebApp(global, activeWebAppKey, tabId); +} diff --git a/src/global/types.ts b/src/global/types.ts index f7da57a23..7fc230b6c 100644 --- a/src/global/types.ts +++ b/src/global/types.ts @@ -695,7 +695,7 @@ export type TabState = { }; webApps: { - activeWebApp?: WebApp; + activeWebAppKey?: string; openedOrderedKeys: string[]; sessionKeys: string[]; openedWebApps: Record;