Mini Apps: Use key as active tab id (#5268)

This commit is contained in:
zubiden 2024-12-06 19:43:59 +04:00 committed by Alexander Zinchuk
parent 87840629da
commit 00780ece5e
8 changed files with 61 additions and 52 deletions

View File

@ -7,7 +7,7 @@ import { getActions, getGlobal, withGlobal } from '../../../global';
import type { ApiUser } from '../../../api/types'; import type { ApiUser } from '../../../api/types';
import type { WebApp } from '../../../global/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 buildClassName from '../../../util/buildClassName';
import { unique } from '../../../util/iteratees'; import { unique } from '../../../util/iteratees';
@ -126,7 +126,7 @@ export default memo(withGlobal(
const tabState = selectTabState(global); const tabState = selectTabState(global);
const webApps = tabState.webApps; const webApps = tabState.webApps;
const { botId } = webApps?.activeWebApp || {}; const { botId } = selectActiveWebApp(global) || {};
const { modalState, openedWebApps } = webApps || {}; const { modalState, openedWebApps } = webApps || {};
const isMinimizedState = modalState === 'minimized'; const isMinimizedState = modalState === 'minimized';
const activeTabBot = botId ? selectUser(global, botId) : undefined; const activeTabBot = botId ? selectUser(global, botId) : undefined;

View File

@ -15,6 +15,7 @@ import type { WebAppOutboundEvent } from '../../../types/webapp';
import { getWebAppKey } from '../../../global/helpers/bots'; import { getWebAppKey } from '../../../global/helpers/bots';
import { import {
selectCurrentChat, selectTheme, selectUser, selectCurrentChat, selectTheme, selectUser,
selectWebApp,
} from '../../../global/selectors'; } from '../../../global/selectors';
import buildClassName from '../../../util/buildClassName'; import buildClassName from '../../../util/buildClassName';
import buildStyle from '../../../util/buildStyle'; import buildStyle from '../../../util/buildStyle';
@ -103,8 +104,9 @@ const WebAppModal: FC<OwnProps & StateProps> = ({
} }
const { const {
openedWebApps, activeWebApp, openedOrderedKeys, sessionKeys, isMoreAppsTabActive, openedWebApps, activeWebAppKey, openedOrderedKeys, sessionKeys, isMoreAppsTabActive,
} = modal || {}; } = modal || {};
const activeWebApp = activeWebAppKey ? openedWebApps?.[activeWebAppKey] : undefined;
const { const {
isBackButtonVisible, headerColor, backgroundColor, isSettingsButtonVisible, isBackButtonVisible, headerColor, backgroundColor, isSettingsButtonVisible,
} = activeWebApp || {}; } = activeWebApp || {};
@ -664,7 +666,8 @@ const WebAppModal: FC<OwnProps & StateProps> = ({
export default memo(withGlobal<OwnProps>( export default memo(withGlobal<OwnProps>(
(global, { modal }): StateProps => { (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 attachBot = activeBotId ? global.attachMenu.bots[activeBotId] : undefined;
const bot = activeBotId ? selectUser(global, activeBotId) : undefined; const bot = activeBotId ? selectUser(global, activeBotId) : undefined;

View File

@ -15,6 +15,7 @@ import { convertToApiChatType } from '../../../global/helpers';
import { getWebAppKey } from '../../../global/helpers/bots'; import { getWebAppKey } from '../../../global/helpers/bots';
import { import {
selectCurrentChat, selectTabState, selectTheme, selectUser, selectCurrentChat, selectTabState, selectTheme, selectUser,
selectWebApp,
} from '../../../global/selectors'; } from '../../../global/selectors';
import buildClassName from '../../../util/buildClassName'; import buildClassName from '../../../util/buildClassName';
import buildStyle from '../../../util/buildStyle'; import buildStyle from '../../../util/buildStyle';
@ -162,7 +163,7 @@ const WebAppModalTabContent: FC<OwnProps & StateProps> = ({
const [, setFullscreen, exitFullscreen] = useFullscreen(fullscreenElementRef, exitFullScreenCallback); const [, setFullscreen, exitFullscreen] = useFullscreen(fullscreenElementRef, exitFullScreenCallback);
const activeWebApp = modal?.activeWebApp; const activeWebApp = modal?.activeWebAppKey ? modal.openedWebApps[modal.activeWebAppKey] : undefined;
const activeWebAppName = activeWebApp?.appName; const activeWebAppName = activeWebApp?.appName;
const { const {
url, buttonText, headerColor, serverHeaderColorKey, serverHeaderColor, isBackButtonVisible, url, buttonText, headerColor, serverHeaderColorKey, serverHeaderColor, isBackButtonVisible,
@ -962,7 +963,8 @@ const WebAppModalTabContent: FC<OwnProps & StateProps> = ({
export default memo(withGlobal<OwnProps>( export default memo(withGlobal<OwnProps>(
(global, { modal }): StateProps => { (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 modalState = modal?.modalState;
const attachBot = activeBotId ? global.attachMenu.bots[activeBotId] : undefined; const attachBot = activeBotId ? global.attachMenu.bots[activeBotId] : undefined;

View File

@ -136,10 +136,12 @@ addActionHandler('apiUpdate', (global, actions, update): ActionReturnType => {
case 'updateWebViewResultSent': case 'updateWebViewResultSent':
Object.values(global.byTabId).forEach((tabState) => { Object.values(global.byTabId).forEach((tabState) => {
if (tabState.webApps.activeWebApp?.queryId === update.queryId) { Object.entries(tabState.webApps.openedWebApps).forEach(([webAppKey, webApp]) => {
actions.resetDraftReplyInfo({ tabId: tabState.id }); if (webApp.queryId === update.queryId) {
actions.closeActiveWebApp({ tabId: tabState.id }); actions.resetDraftReplyInfo({ tabId: tabState.id });
} actions.closeWebApp({ key: webAppKey, tabId: tabState.id });
}
});
}); });
break; break;

View File

@ -16,7 +16,9 @@ import {
updateWebApp, updateWebApp,
} from '../../reducers/bots'; } from '../../reducers/bots';
import { updateTabState } from '../../reducers/tabs'; import { updateTabState } from '../../reducers/tabs';
import { selectCurrentMessageList, selectTabState, selectWebApp } from '../../selectors'; import {
selectActiveWebApp, selectCurrentMessageList, selectTabState, selectWebApp,
} from '../../selectors';
addActionHandler('openWebAppTab', (global, actions, payload): ActionReturnType => { addActionHandler('openWebAppTab', (global, actions, payload): ActionReturnType => {
const { const {
@ -53,7 +55,7 @@ addActionHandler('openMoreAppsTab', (global, actions, payload): ActionReturnType
global = updateTabState(global, { global = updateTabState(global, {
webApps: { webApps: {
...tabState.webApps, ...tabState.webApps,
activeWebApp: undefined, activeWebAppKey: undefined,
isMoreAppsTabActive: true, isMoreAppsTabActive: true,
}, },
}, tabId); }, tabId);
@ -68,14 +70,14 @@ addActionHandler('closeMoreAppsTab', (global, actions, payload): ActionReturnTyp
const openedWebApps = tabState.webApps.openedWebApps; const openedWebApps = tabState.webApps.openedWebApps;
const openedWebAppsValues = Object.values(openedWebApps); const openedWebAppsKeys = Object.keys(openedWebApps);
const openedWebAppsCount = openedWebAppsValues.length; const openedWebAppsCount = openedWebAppsKeys.length;
global = updateTabState(global, { global = updateTabState(global, {
webApps: { webApps: {
...tabState.webApps, ...tabState.webApps,
isMoreAppsTabActive: false, isMoreAppsTabActive: false,
activeWebApp: openedWebAppsCount ? openedWebAppsValues[openedWebAppsCount - 1] : undefined, activeWebAppKey: openedWebAppsCount ? openedWebAppsKeys[openedWebAppsCount - 1] : undefined,
isModalOpen: openedWebAppsCount > 0, isModalOpen: openedWebAppsCount > 0,
}, },
}, tabId); }, tabId);
@ -117,8 +119,7 @@ addActionHandler('changeWebAppModalState', (global, actions, payload): ActionRet
addActionHandler('setWebAppPaymentSlug', (global, actions, payload): ActionReturnType => { addActionHandler('setWebAppPaymentSlug', (global, actions, payload): ActionReturnType => {
const { tabId = getCurrentTabId() } = payload; const { tabId = getCurrentTabId() } = payload;
const tabState = selectTabState(global, tabId); const activeWebApp = selectActiveWebApp(global, tabId);
const activeWebApp = tabState.webApps.activeWebApp;
if (!activeWebApp?.url) return undefined; if (!activeWebApp?.url) return undefined;
const key = getWebAppKey(activeWebApp); const key = getWebAppKey(activeWebApp);

View File

@ -5,7 +5,7 @@ import type {
import { getCurrentTabId } from '../../util/establishMultitabRole'; import { getCurrentTabId } from '../../util/establishMultitabRole';
import { getWebAppKey } from '../helpers/bots'; import { getWebAppKey } from '../helpers/bots';
import { selectTabState } from '../selectors'; import { selectActiveWebApp, selectTabState } from '../selectors';
import { updateTabState } from './tabs'; import { updateTabState } from './tabs';
export function replaceInlineBotSettings<T extends GlobalState>( export function replaceInlineBotSettings<T extends GlobalState>(
@ -55,14 +55,9 @@ export function updateWebApp <T extends GlobalState>(
const updatedWebAppKey = getWebAppKey(updatedValue); const updatedWebAppKey = getWebAppKey(updatedValue);
if (!updatedWebAppKey) return global; if (!updatedWebAppKey) return global;
const activeWebApp = currentTabState.webApps.activeWebApp;
const activeWebAppKey = activeWebApp && getWebAppKey(activeWebApp);
global = updateTabState(global, { global = updateTabState(global, {
webApps: { webApps: {
...currentTabState.webApps, ...currentTabState.webApps,
...updatedWebAppKey === activeWebAppKey && {
activeWebApp: updatedValue,
},
openedWebApps: { openedWebApps: {
...openedWebApps, ...openedWebApps,
[updatedWebAppKey]: updatedValue, [updatedWebAppKey]: updatedValue,
@ -84,13 +79,11 @@ export function activateWebAppIfOpen<T extends GlobalState>(
return global; return global;
} }
const newActiveWebApp = openedWebApps[webAppKey];
global = updateTabState(global, { global = updateTabState(global, {
webApps: { webApps: {
...currentTabState.webApps, ...currentTabState.webApps,
isMoreAppsTabActive: false, isMoreAppsTabActive: false,
activeWebApp: newActiveWebApp, activeWebAppKey: webAppKey,
modalState: 'maximized', modalState: 'maximized',
}, },
}, tabId); }, tabId);
@ -119,7 +112,7 @@ export function addWebAppToOpenList<T extends GlobalState>(
global = updateTabState(global, { global = updateTabState(global, {
webApps: { webApps: {
...currentTabState.webApps, ...currentTabState.webApps,
...makeActive && { activeWebApp: webApp }, ...makeActive && { activeWebAppKey: key },
isMoreAppsTabActive: false, isMoreAppsTabActive: false,
isModalOpen: openModalIfNotOpen, isModalOpen: openModalIfNotOpen,
modalState: 'maximized', modalState: 'maximized',
@ -139,12 +132,11 @@ export function removeActiveWebAppFromOpenList<T extends GlobalState>(
global: T, ...[tabId = getCurrentTabId()]: TabArgs<T> global: T, ...[tabId = getCurrentTabId()]: TabArgs<T>
): T { ): T {
const currentTabState = selectTabState(global, tabId); 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, activeWebAppKey, false, tabId);
return removeWebAppFromOpenList(global, key, false, tabId);
} }
export function removeWebAppFromOpenList<T extends GlobalState>( export function removeWebAppFromOpenList<T extends GlobalState>(
@ -152,7 +144,7 @@ export function removeWebAppFromOpenList<T extends GlobalState>(
...[tabId = getCurrentTabId()]: TabArgs<T> ...[tabId = getCurrentTabId()]: TabArgs<T>
): T { ): T {
const currentTabState = selectTabState(global, tabId); const currentTabState = selectTabState(global, tabId);
const openedWebApps = currentTabState.webApps.openedWebApps; const { openedWebApps, openedOrderedKeys, activeWebAppKey } = currentTabState.webApps;
const webApp = openedWebApps[key]; const webApp = openedWebApps[key];
if (!webApp) return global; if (!webApp) return global;
@ -163,26 +155,24 @@ export function removeWebAppFromOpenList<T extends GlobalState>(
const updatedOpenedWebApps = { ...openedWebApps }; const updatedOpenedWebApps = { ...openedWebApps };
const removingWebAppKey = getWebAppKey(webApp); const removingWebAppKey = getWebAppKey(webApp);
let newOpenedKeys = currentTabState.webApps.openedOrderedKeys; let newOpenedKeys = openedOrderedKeys;
if (removingWebAppKey) { if (removingWebAppKey) {
delete updatedOpenedWebApps[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 openedWebAppsKeys = Object.keys(updatedOpenedWebApps);
const openedWebAppsCount = openedWebAppsKeys.length;
const openedWebAppsValues = Object.values(updatedOpenedWebApps);
const openedWebAppsCount = openedWebAppsValues.length;
global = updateTabState(global, { global = updateTabState(global, {
webApps: { webApps: {
...currentTabState.webApps, ...currentTabState.webApps,
...isRemovedAppActive && { ...isRemovedAppActive && {
activeWebApp: openedWebAppsCount activeWebAppKey: openedWebAppsCount
? openedWebAppsValues[openedWebAppsCount - 1] : undefined, ? openedWebAppsKeys[openedWebAppsCount - 1] : undefined,
}, },
openedWebApps: updatedOpenedWebApps, openedWebApps: updatedOpenedWebApps,
openedOrderedKeys: newOpenedKeys, openedOrderedKeys: newOpenedKeys,
@ -203,8 +193,7 @@ export function clearOpenedWebApps<T extends GlobalState>(
const webAppsNotAllowedToClose = Object.fromEntries( const webAppsNotAllowedToClose = Object.fromEntries(
Object.entries(currentTabState.webApps.openedWebApps).filter( Object.entries(currentTabState.webApps.openedWebApps).filter(
// eslint-disable-next-line @typescript-eslint/no-unused-vars ([, webApp]) => webApp.shouldConfirmClosing,
([url, webApp]) => webApp.shouldConfirmClosing,
), ),
); );
@ -215,7 +204,7 @@ export function clearOpenedWebApps<T extends GlobalState>(
return updateTabState(global, { return updateTabState(global, {
webApps: { webApps: {
...currentTabState.webApps, ...currentTabState.webApps,
activeWebApp: undefined, activeWebAppKey: undefined,
openedWebApps: {}, openedWebApps: {},
openedOrderedKeys: [], openedOrderedKeys: [],
sessionKeys: [], sessionKeys: [],
@ -223,22 +212,25 @@ export function clearOpenedWebApps<T extends GlobalState>(
}, tabId); }, tabId);
} }
const currentActiveWebApp = currentTabState.webApps.activeWebApp; const currentActiveWebApp = selectActiveWebApp(global, tabId);
const newActiveWebApp = currentActiveWebApp?.shouldConfirmClosing const newActiveWebApp = currentActiveWebApp?.shouldConfirmClosing
? currentActiveWebApp : webAppsNotAllowedToCloseValues[0]; ? currentActiveWebApp : webAppsNotAllowedToCloseValues[0];
newActiveWebApp.isCloseModalOpen = true; const newActiveWebAppKey = getWebAppKey(newActiveWebApp);
const key = getWebAppKey(newActiveWebApp); if (newActiveWebAppKey) {
webAppsNotAllowedToClose[newActiveWebAppKey] = {
if (key) webAppsNotAllowedToClose[key] = newActiveWebApp; ...newActiveWebApp,
const newOpenedKeys = currentTabState.webApps.openedOrderedKeys.filter((k) => k in webAppsNotAllowedToClose); isCloseModalOpen: true,
};
}
const newOpenedKeys = currentTabState.webApps.openedOrderedKeys.filter((k) => webAppsNotAllowedToClose[k]);
return updateTabState(global, { return updateTabState(global, {
webApps: { webApps: {
...currentTabState.webApps, ...currentTabState.webApps,
activeWebApp: newActiveWebApp, activeWebAppKey: newActiveWebAppKey,
isMoreAppsTabActive: false, isMoreAppsTabActive: false,
openedWebApps: webAppsNotAllowedToClose, openedWebApps: webAppsNotAllowedToClose,
openedOrderedKeys: newOpenedKeys, openedOrderedKeys: newOpenedKeys,

View File

@ -156,3 +156,12 @@ export function selectWebApp<T extends GlobalState>(
) { ) {
return selectTabState(global, tabId).webApps.openedWebApps[key]; return selectTabState(global, tabId).webApps.openedWebApps[key];
} }
export function selectActiveWebApp<T extends GlobalState>(
global: T, ...[tabId = getCurrentTabId()]: TabArgs<T>
) {
const activeWebAppKey = selectTabState(global, tabId).webApps.activeWebAppKey;
if (!activeWebAppKey) return undefined;
return selectWebApp(global, activeWebAppKey, tabId);
}

View File

@ -695,7 +695,7 @@ export type TabState = {
}; };
webApps: { webApps: {
activeWebApp?: WebApp; activeWebAppKey?: string;
openedOrderedKeys: string[]; openedOrderedKeys: string[];
sessionKeys: string[]; sessionKeys: string[];
openedWebApps: Record<string, WebApp>; openedWebApps: Record<string, WebApp>;