diff --git a/index.html b/index.html
index 2dab011..4745170 100644
--- a/index.html
+++ b/index.html
@@ -1,7 +1,8 @@
-
+
+
Qortal Extension
diff --git a/src/atoms/global.ts b/src/atoms/global.ts
index cc1f02f..67d3aa5 100644
--- a/src/atoms/global.ts
+++ b/src/atoms/global.ts
@@ -56,4 +56,9 @@ export const fullScreenAtom = atom({
export const hasSettingsChangedAtom = atom({
key: 'hasSettingsChangedAtom',
default: false,
+});
+
+export const navigationControllerAtom = atom({
+ key: 'navigationControllerAtom',
+ default: {},
});
\ No newline at end of file
diff --git a/src/components/Apps/AppViewer.tsx b/src/components/Apps/AppViewer.tsx
index 49955f5..a2a5225 100644
--- a/src/components/Apps/AppViewer.tsx
+++ b/src/components/Apps/AppViewer.tsx
@@ -1,25 +1,9 @@
-import React, { useContext, useEffect, useMemo, useRef, useState } from "react";
-import {
- AppCircle,
- AppCircleContainer,
- AppCircleLabel,
- AppDownloadButton,
- AppDownloadButtonText,
- AppInfoAppName,
- AppInfoSnippetContainer,
- AppInfoSnippetLeft,
- AppInfoSnippetMiddle,
- AppInfoSnippetRight,
- AppInfoUserName,
- AppsLibraryContainer,
- AppsParent,
-} from "./Apps-styles";
-import { Avatar, Box, ButtonBase, InputBase } from "@mui/material";
+import React, { useContext, useEffect, useMemo, useState } from "react";
+
+import { Avatar, Box, } from "@mui/material";
import { Add } from "@mui/icons-material";
import { MyContext, getBaseApiReact, isMobile } from "../../App";
-import LogoSelected from "../../assets/svgs/LogoSelected.svg";
-import { Spacer } from "../../common/Spacer";
import { executeEvent, subscribeToEvent, unsubscribeFromEvent } from "../../utils/events";
import { useFrame } from "react-frame-component";
import { useQortalMessageListener } from "./useQortalMessageListener";
@@ -27,15 +11,16 @@ import { useQortalMessageListener } from "./useQortalMessageListener";
-export const AppViewer = ({ app }) => {
+export const AppViewer = React.forwardRef(({ app , hide}, iframeRef) => {
const { rootHeight } = useContext(MyContext);
- const iframeRef = useRef(null);
- const { document, window } = useFrame();
- const {path} = useQortalMessageListener(window)
+ // const iframeRef = useRef(null);
+ const { document, window: frameWindow } = useFrame();
+ const {path, history, changeCurrentIndex} = useQortalMessageListener(frameWindow, iframeRef, app?.tabId)
const [url, setUrl] = useState('')
+ console.log('historyreact', history)
useEffect(()=> {
- setUrl(`${getBaseApiReact()}/render/${app?.service}/${app?.name}${app?.path != null ? app?.path : ''}?theme=dark&identifier=${(app?.identifier != null && app?.identifier != 'null') ? app?.identifier : ''}`)
+ setUrl(`${getBaseApiReact()}/render/${app?.service}/${app?.name}${app?.path != null ? `/${app?.path}` : ''}?theme=dark&identifier=${(app?.identifier != null && app?.identifier != 'null') ? app?.identifier : ''}`)
}, [app?.service, app?.name, app?.identifier, app?.path])
const defaultUrl = useMemo(()=> {
return url
@@ -59,13 +44,106 @@ export const AppViewer = ({ app }) => {
};
}, [app, path]);
+ // Function to navigate back in iframe
+ const navigateBackInIframe = async () => {
+ if (iframeRef.current && iframeRef.current.contentWindow && history?.currentIndex > 0) {
+ // Calculate the previous index and path
+ const previousPageIndex = history.currentIndex - 1;
+ const previousPath = history.customQDNHistoryPaths[previousPageIndex];
+
+ // Signal non-manual navigation
+ iframeRef.current.contentWindow.postMessage(
+ { action: 'PERFORMING_NON_MANUAL' }, '*'
+ );
+ console.log('previousPageIndex', previousPageIndex)
+ // Update the current index locally
+ changeCurrentIndex(previousPageIndex);
+
+ // Create a navigation promise with a 200ms timeout
+ const navigationPromise = new Promise((resolve, reject) => {
+ function handleNavigationSuccess(event) {
+ console.log('listeninghandlenav', event)
+ if (event.data?.action === 'NAVIGATION_SUCCESS' && event.data.path === previousPath) {
+ frameWindow.removeEventListener('message', handleNavigationSuccess);
+ resolve();
+ }
+ }
+
+ frameWindow.addEventListener('message', handleNavigationSuccess);
+
+ // Timeout after 200ms if no response
+ setTimeout(() => {
+ window.removeEventListener('message', handleNavigationSuccess);
+ reject(new Error("Navigation timeout"));
+ }, 200);
+
+ // Send the navigation command after setting up the listener and timeout
+ iframeRef.current.contentWindow.postMessage(
+ { action: 'NAVIGATE_TO_PATH', path: previousPath, requestedHandler: 'UI' }, '*'
+ );
+ });
+
+ // Execute navigation promise and handle timeout fallback
+ try {
+ await navigationPromise;
+ console.log('Navigation succeeded within 200ms.');
+ } catch (error) {
+ iframeRef.current.contentWindow.postMessage(
+ { action: 'PERFORMING_NON_MANUAL' }, '*'
+ );
+ setUrl(`${getBaseApiReact()}/render/${app?.service}/${app?.name}${app?.previousPath != null ? previousPath : ''}?theme=dark&identifier=${(app?.identifier != null && app?.identifier != 'null') ? app?.identifier : ''}&time=${new Date().getMilliseconds()}&isManualNavigation=false`)
+ // iframeRef.current.contentWindow.location.href = previousPath; // Fallback URL update
+ }
+ } else {
+ console.log('Iframe not accessible or does not have a content window.');
+ }
+};
+
+ const navigateBackAppFunc = (e) => {
+
+ navigateBackInIframe()
+ };
+
+ useEffect(() => {
+ if(!app?.tabId) return
+ subscribeToEvent(`navigateBackApp-${app?.tabId}`, navigateBackAppFunc);
+
+ return () => {
+ unsubscribeFromEvent(`navigateBackApp-${app?.tabId}`, navigateBackAppFunc);
+ };
+ }, [app, history]);
+
+
+ // Function to navigate back in iframe
+ const navigateForwardInIframe = async () => {
+
+
+ if (iframeRef.current && iframeRef.current.contentWindow) {
+ console.log('iframeRef.contentWindow', iframeRef.current.contentWindow);
+ iframeRef.current.contentWindow.postMessage(
+ { action: 'NAVIGATE_FORWARD'},
+ '*'
+ );
+ } else {
+ console.log('Iframe not accessible or does not have a content window.');
+ }
+};
+
+
return (
-