diff --git a/package-lock.json b/package-lock.json index b2194882b..79e0e21eb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5293,9 +5293,9 @@ } }, "@saleor/app-bridge": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/@saleor/app-bridge/-/app-bridge-0.1.7.tgz", - "integrity": "sha512-EXNNAZD1g79fCtoaNLqoTKg9GiB1Lj26E7iKz4PmUOQZyDeBEBxc6CLpUwNptb4Xw7+KULMHdtxJVkp/RTC2TQ==", + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/@saleor/app-bridge/-/app-bridge-0.1.9.tgz", + "integrity": "sha512-p0+rXVAyOMrW6IfSrQg91UA330yO8xcCdSI73VcPpwFQb7es9i4Iqr/eFC4UsHTsQn/qZYp8Mnw+6TMnh4YjTQ==", "dev": true, "requires": { "uuid": "^8.3.2" diff --git a/package.json b/package.json index fa49281f2..98e60403f 100644 --- a/package.json +++ b/package.json @@ -109,7 +109,7 @@ "@pollyjs/core": "^5.0.0", "@pollyjs/persister-fs": "^5.0.0", "@release-it/bumper": "^2.0.0", - "@saleor/app-bridge": "^0.1.7", + "@saleor/app-bridge": "^0.1.9", "@sentry/webpack-plugin": "^1.14.0", "@storybook/addon-storyshots": "^5.2.8", "@storybook/react": "^5.1.9", diff --git a/src/apps/components/AppFrame/AppFrame.tsx b/src/apps/components/AppFrame/AppFrame.tsx index f157b8f1c..49d792a01 100644 --- a/src/apps/components/AppFrame/AppFrame.tsx +++ b/src/apps/components/AppFrame/AppFrame.tsx @@ -1,7 +1,9 @@ +import { getAppDeepPathFromDashboardUrl } from "@saleor/apps/urls"; import useShop from "@saleor/hooks/useShop"; import { useTheme } from "@saleor/macaw-ui"; import clsx from "clsx"; -import React from "react"; +import React, { useEffect } from "react"; +import { useLocation } from "react-router"; import urlJoin from "url-join"; import { useStyles } from "./styles"; @@ -31,7 +33,17 @@ export const AppFrame: React.FC = ({ const { sendThemeToExtension } = useTheme(); const classes = useStyles(); const appOrigin = getOrigin(src); - const { postToExtension } = useAppActions(frameRef, appOrigin); + const { postToExtension } = useAppActions(frameRef, appOrigin, appId); + const location = useLocation(); + + useEffect(() => { + postToExtension({ + type: "redirect", + payload: { + path: getAppDeepPathFromDashboardUrl(location.pathname, appId), + }, + }); + }, [location.pathname]); const handleLoad = () => { postToExtension({ diff --git a/src/apps/components/AppFrame/useAppActions.ts b/src/apps/components/AppFrame/useAppActions.ts index 16f387536..10fa2f60e 100644 --- a/src/apps/components/AppFrame/useAppActions.ts +++ b/src/apps/components/AppFrame/useAppActions.ts @@ -1,7 +1,9 @@ import { Actions, DispatchResponseEvent, Events } from "@saleor/app-bridge"; +import { appPath } from "@saleor/apps/urls"; import useNavigator from "@saleor/hooks/useNavigator"; import React from "react"; import { useIntl } from "react-intl"; +import { useLocation } from "react-router"; import { useExternalApp } from "../ExternalAppContext"; @@ -16,11 +18,19 @@ const sendResponseStatus = ( }, }); +const isAppDeepUrlChange = (appId: string, from: string, to: string) => { + const appCompletePath = appPath(encodeURIComponent(appId)); + + return to.startsWith(appCompletePath) && from.startsWith(appCompletePath); +}; + export const useAppActions = ( frameEl: React.MutableRefObject, appOrigin: string, + appId: string, ) => { const navigate = useNavigator(); + const location = useLocation(); const { closeApp } = useExternalApp(); const intl = useIntl(); @@ -32,10 +42,18 @@ export const useAppActions = ( const { to, newContext, actionId } = action.payload; let success = true; + const appDeepUrlChange = isAppDeepUrlChange( + appId, + location.pathname, + to, + ); try { if (newContext) { window.open(to); + } else if (appDeepUrlChange) { + // Change only url without reloading if we are in the same app + window.history.pushState(null, "", to); } else if (to.startsWith("/")) { navigate(to); closeApp(); diff --git a/src/apps/urls.ts b/src/apps/urls.ts index 702f15de1..19b0a7f0f 100644 --- a/src/apps/urls.ts +++ b/src/apps/urls.ts @@ -69,6 +69,16 @@ export const appDeepUrl = ( params?: AppDetailsUrlQueryParams, ) => appDeepPath(encodeURIComponent(id), subPath) + "?" + stringifyQs(params); +export const getAppDeepPathFromDashboardUrl = ( + dashboardUrl: string, + appId: string, +) => { + const deepSubPath = dashboardUrl.replace( + appPath(encodeURIComponent(appId)), + "", + ); + return deepSubPath || "/"; +}; export const getAppCompleteUrlFromDashboardUrl = ( dashboardUrl: string, appUrl?: string,