2022-08-10 13:26:09 +00:00
|
|
|
import {
|
|
|
|
Actions,
|
|
|
|
DispatchResponseEvent,
|
|
|
|
Events,
|
|
|
|
NotificationAction,
|
|
|
|
RedirectAction,
|
2022-09-06 11:11:06 +00:00
|
|
|
} from "@saleor/app-sdk/app-bridge";
|
2022-07-05 08:39:58 +00:00
|
|
|
import { appPath } from "@saleor/apps/urls";
|
2022-11-16 15:01:34 +00:00
|
|
|
import { getAppMountUri } from "@saleor/config";
|
2021-08-20 13:58:53 +00:00
|
|
|
import useNavigator from "@saleor/hooks/useNavigator";
|
2022-08-10 13:26:09 +00:00
|
|
|
import useNotifier from "@saleor/hooks/useNotifier";
|
2021-08-20 13:58:53 +00:00
|
|
|
import React from "react";
|
2022-03-25 12:39:09 +00:00
|
|
|
import { useIntl } from "react-intl";
|
2022-07-05 08:39:58 +00:00
|
|
|
import { useLocation } from "react-router";
|
2022-07-05 10:53:47 +00:00
|
|
|
import urlJoin from "url-join";
|
2021-08-20 13:58:53 +00:00
|
|
|
|
|
|
|
import { useExternalApp } from "../ExternalAppContext";
|
|
|
|
|
|
|
|
const sendResponseStatus = (
|
|
|
|
actionId: string,
|
2022-06-21 09:36:55 +00:00
|
|
|
ok: boolean,
|
2021-08-20 13:58:53 +00:00
|
|
|
): DispatchResponseEvent => ({
|
|
|
|
type: "response",
|
|
|
|
payload: {
|
|
|
|
actionId,
|
2022-06-21 09:36:55 +00:00
|
|
|
ok,
|
|
|
|
},
|
2021-08-20 13:58:53 +00:00
|
|
|
});
|
|
|
|
|
2022-07-05 08:39:58 +00:00
|
|
|
const isAppDeepUrlChange = (appId: string, from: string, to: string) => {
|
|
|
|
const appCompletePath = appPath(encodeURIComponent(appId));
|
|
|
|
|
|
|
|
return to.startsWith(appCompletePath) && from.startsWith(appCompletePath);
|
|
|
|
};
|
|
|
|
|
2021-08-20 13:58:53 +00:00
|
|
|
export const useAppActions = (
|
|
|
|
frameEl: React.MutableRefObject<HTMLIFrameElement>,
|
2022-06-21 09:36:55 +00:00
|
|
|
appOrigin: string,
|
2022-07-05 08:39:58 +00:00
|
|
|
appId: string,
|
2021-08-20 13:58:53 +00:00
|
|
|
) => {
|
|
|
|
const navigate = useNavigator();
|
2022-08-10 13:26:09 +00:00
|
|
|
const notify = useNotifier();
|
2022-07-05 08:39:58 +00:00
|
|
|
const location = useLocation();
|
2021-08-20 13:58:53 +00:00
|
|
|
const { closeApp } = useExternalApp();
|
2022-03-25 12:39:09 +00:00
|
|
|
const intl = useIntl();
|
2021-08-20 13:58:53 +00:00
|
|
|
|
|
|
|
const actionReducer = (
|
2022-06-21 09:36:55 +00:00
|
|
|
action: Actions | undefined,
|
2021-08-20 13:58:53 +00:00
|
|
|
): DispatchResponseEvent => {
|
|
|
|
switch (action?.type) {
|
2022-08-10 13:26:09 +00:00
|
|
|
case "notification": {
|
|
|
|
const {
|
|
|
|
actionId,
|
|
|
|
...notification
|
|
|
|
} = action.payload as NotificationAction["payload"];
|
|
|
|
|
|
|
|
notify({
|
|
|
|
...notification,
|
|
|
|
});
|
|
|
|
|
|
|
|
return sendResponseStatus(actionId, true);
|
|
|
|
}
|
2021-08-20 13:58:53 +00:00
|
|
|
case "redirect": {
|
2022-08-10 13:26:09 +00:00
|
|
|
const {
|
|
|
|
to,
|
|
|
|
newContext,
|
|
|
|
actionId,
|
|
|
|
} = action.payload as RedirectAction["payload"];
|
2021-08-20 13:58:53 +00:00
|
|
|
|
2022-03-25 12:39:09 +00:00
|
|
|
let success = true;
|
2022-07-05 08:39:58 +00:00
|
|
|
const appDeepUrlChange = isAppDeepUrlChange(
|
|
|
|
appId,
|
|
|
|
location.pathname,
|
|
|
|
to,
|
|
|
|
);
|
2022-03-25 12:39:09 +00:00
|
|
|
|
|
|
|
try {
|
|
|
|
if (newContext) {
|
|
|
|
window.open(to);
|
2022-07-05 08:39:58 +00:00
|
|
|
} else if (appDeepUrlChange) {
|
2022-11-16 15:01:34 +00:00
|
|
|
const exactLocation = urlJoin(getAppMountUri(), to);
|
2022-07-05 10:53:47 +00:00
|
|
|
|
2022-07-05 08:39:58 +00:00
|
|
|
// Change only url without reloading if we are in the same app
|
2022-07-05 10:53:47 +00:00
|
|
|
window.history.pushState(null, "", exactLocation);
|
2022-03-25 12:39:09 +00:00
|
|
|
} else if (to.startsWith("/")) {
|
|
|
|
navigate(to);
|
|
|
|
closeApp();
|
|
|
|
} else {
|
|
|
|
const isExternalDomain =
|
|
|
|
new URL(to).hostname !== window.location.hostname;
|
|
|
|
|
|
|
|
if (isExternalDomain) {
|
|
|
|
success = window.confirm(
|
|
|
|
intl.formatMessage({
|
2022-05-05 07:54:28 +00:00
|
|
|
id: "MSItJD",
|
2022-03-25 12:39:09 +00:00
|
|
|
defaultMessage:
|
2022-06-21 09:36:55 +00:00
|
|
|
"You are about to leave the Dashboard. Do you want to continue?",
|
|
|
|
}),
|
2022-03-25 12:39:09 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (success) {
|
|
|
|
window.location.href = to;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (e) {
|
|
|
|
success = false;
|
2021-08-20 13:58:53 +00:00
|
|
|
}
|
|
|
|
|
2022-03-25 12:39:09 +00:00
|
|
|
return sendResponseStatus(actionId, success);
|
2021-08-20 13:58:53 +00:00
|
|
|
}
|
|
|
|
default: {
|
2022-08-10 13:26:09 +00:00
|
|
|
throw new Error("Unknown action type");
|
2021-08-20 13:58:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const postToExtension = (event: Events) => {
|
|
|
|
if (frameEl.current) {
|
|
|
|
frameEl.current.contentWindow.postMessage(event, appOrigin);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
React.useEffect(() => {
|
|
|
|
const handler = (event: MessageEvent<Actions>) => {
|
|
|
|
if (event.origin === appOrigin) {
|
|
|
|
const response = actionReducer(event.data);
|
|
|
|
|
|
|
|
postToExtension(response);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
window.addEventListener("message", handler);
|
|
|
|
|
|
|
|
return () => {
|
|
|
|
window.removeEventListener("message", handler);
|
|
|
|
};
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
return {
|
2022-06-21 09:36:55 +00:00
|
|
|
postToExtension,
|
2021-08-20 13:58:53 +00:00
|
|
|
};
|
|
|
|
};
|