mirror of
https://github.com/Qortal/Qortal-Hub.git
synced 2025-04-23 19:37:52 +00:00
added preview mode
This commit is contained in:
parent
a41e5049ba
commit
52f7a3a640
@ -14,7 +14,11 @@ contextBridge.exposeInMainWorld('electronAPI', {
|
|||||||
contextBridge.exposeInMainWorld('electron', {
|
contextBridge.exposeInMainWorld('electron', {
|
||||||
onUpdateAvailable: (callback) => ipcRenderer.on('update_available', callback),
|
onUpdateAvailable: (callback) => ipcRenderer.on('update_available', callback),
|
||||||
onUpdateDownloaded: (callback) => ipcRenderer.on('update_downloaded', callback),
|
onUpdateDownloaded: (callback) => ipcRenderer.on('update_downloaded', callback),
|
||||||
restartApp: () => ipcRenderer.send('restart_app')
|
restartApp: () => ipcRenderer.send('restart_app'),
|
||||||
|
selectFile: async () => ipcRenderer.invoke('dialog:openFile'),
|
||||||
|
readFile: async (filePath) => ipcRenderer.invoke('fs:readFile', filePath),
|
||||||
|
selectAndZipDirectory: async (filePath) => ipcRenderer.invoke('fs:selectAndZip', filePath),
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcRenderer.send('test-ipc');
|
ipcRenderer.send('test-ipc');
|
@ -6,13 +6,15 @@ import {
|
|||||||
} from '@capacitor-community/electron';
|
} from '@capacitor-community/electron';
|
||||||
import chokidar from 'chokidar';
|
import chokidar from 'chokidar';
|
||||||
import type { MenuItemConstructorOptions } from 'electron';
|
import type { MenuItemConstructorOptions } from 'electron';
|
||||||
import { app, BrowserWindow, Menu, MenuItem, nativeImage, Tray, session, ipcMain } from 'electron';
|
import { app, BrowserWindow, Menu, MenuItem, nativeImage, Tray, session, ipcMain, dialog } from 'electron';
|
||||||
import electronIsDev from 'electron-is-dev';
|
import electronIsDev from 'electron-is-dev';
|
||||||
import electronServe from 'electron-serve';
|
import electronServe from 'electron-serve';
|
||||||
import windowStateKeeper from 'electron-window-state';
|
import windowStateKeeper from 'electron-window-state';
|
||||||
|
const AdmZip = require('adm-zip');
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
import { myCapacitorApp } from '.';
|
import { myCapacitorApp } from '.';
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
const defaultDomains = [
|
const defaultDomains = [
|
||||||
'capacitor-electron://-',
|
'capacitor-electron://-',
|
||||||
@ -361,3 +363,70 @@ ipcMain.on('set-allowed-domains', (event, domains: string[]) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
ipcMain.handle('dialog:openFile', async () => {
|
||||||
|
const result = await dialog.showOpenDialog({
|
||||||
|
properties: ['openFile'],
|
||||||
|
filters: [
|
||||||
|
{ name: 'ZIP Files', extensions: ['zip'] } // Restrict to ZIP files
|
||||||
|
],
|
||||||
|
});
|
||||||
|
return result.filePaths[0];
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.handle('fs:readFile', async (_, filePath) => {
|
||||||
|
try {
|
||||||
|
// Ensure the file exists
|
||||||
|
if (!fs.existsSync(filePath)) {
|
||||||
|
throw new Error('File does not exist.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure the filePath is an absolute path (optional but recommended for safety)
|
||||||
|
const absolutePath = path.resolve(filePath);
|
||||||
|
|
||||||
|
// Read the file as a Buffer
|
||||||
|
const fileBuffer = fs.readFileSync(absolutePath);
|
||||||
|
|
||||||
|
return fileBuffer
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error reading file:', error.message);
|
||||||
|
return null; // Return null on error
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.handle('fs:selectAndZip', async (_, path) => {
|
||||||
|
let directoryPath = path
|
||||||
|
if(!directoryPath){
|
||||||
|
const { canceled, filePaths } = await dialog.showOpenDialog({
|
||||||
|
properties: ['openDirectory'],
|
||||||
|
});
|
||||||
|
if (canceled || filePaths.length === 0) {
|
||||||
|
console.log('No directory selected');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
directoryPath = filePaths[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
// Add the entire directory to the zip
|
||||||
|
const zip = new AdmZip();
|
||||||
|
|
||||||
|
// Add the entire directory to the zip
|
||||||
|
zip.addLocalFolder(directoryPath);
|
||||||
|
|
||||||
|
// Generate the zip file as a buffer
|
||||||
|
const zipBuffer = zip.toBuffer();
|
||||||
|
|
||||||
|
return {buffer: zipBuffer, directoryPath}
|
||||||
|
} catch (error) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
9
package-lock.json
generated
9
package-lock.json
generated
@ -41,6 +41,7 @@
|
|||||||
"@tiptap/starter-kit": "^2.5.9",
|
"@tiptap/starter-kit": "^2.5.9",
|
||||||
"@transistorsoft/capacitor-background-fetch": "^6.0.1",
|
"@transistorsoft/capacitor-background-fetch": "^6.0.1",
|
||||||
"@types/chrome": "^0.0.263",
|
"@types/chrome": "^0.0.263",
|
||||||
|
"adm-zip": "^0.5.16",
|
||||||
"asmcrypto.js": "2.3.2",
|
"asmcrypto.js": "2.3.2",
|
||||||
"axios": "^1.7.7",
|
"axios": "^1.7.7",
|
||||||
"bcryptjs": "2.4.3",
|
"bcryptjs": "2.4.3",
|
||||||
@ -4830,6 +4831,14 @@
|
|||||||
"node": ">=0.4.0"
|
"node": ">=0.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/adm-zip": {
|
||||||
|
"version": "0.5.16",
|
||||||
|
"resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.16.tgz",
|
||||||
|
"integrity": "sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/agent-base": {
|
"node_modules/agent-base": {
|
||||||
"version": "7.1.1",
|
"version": "7.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz",
|
||||||
|
@ -45,6 +45,7 @@
|
|||||||
"@tiptap/starter-kit": "^2.5.9",
|
"@tiptap/starter-kit": "^2.5.9",
|
||||||
"@transistorsoft/capacitor-background-fetch": "^6.0.1",
|
"@transistorsoft/capacitor-background-fetch": "^6.0.1",
|
||||||
"@types/chrome": "^0.0.263",
|
"@types/chrome": "^0.0.263",
|
||||||
|
"adm-zip": "^0.5.16",
|
||||||
"asmcrypto.js": "2.3.2",
|
"asmcrypto.js": "2.3.2",
|
||||||
"axios": "^1.7.7",
|
"axios": "^1.7.7",
|
||||||
"bcryptjs": "2.4.3",
|
"bcryptjs": "2.4.3",
|
||||||
|
@ -78,9 +78,7 @@ async function computePow(chatBytes, difficulty) {
|
|||||||
workBufferPtr = sbrk(workBufferLength);
|
workBufferPtr = sbrk(workBufferLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Starting POW computation...');
|
|
||||||
const nonce = compute(hashPtr, workBufferPtr, workBufferLength, difficulty);
|
const nonce = compute(hashPtr, workBufferPtr, workBufferLength, difficulty);
|
||||||
console.log('POW computation finished.');
|
|
||||||
|
|
||||||
return { nonce, chatBytesArray };
|
return { nonce, chatBytesArray };
|
||||||
}
|
}
|
||||||
|
@ -15,31 +15,44 @@ export const AppViewer = React.forwardRef(({ app , hide, isDevMode}, iframeRef)
|
|||||||
const { rootHeight } = useContext(MyContext);
|
const { rootHeight } = useContext(MyContext);
|
||||||
// const iframeRef = useRef(null);
|
// const iframeRef = useRef(null);
|
||||||
const { document, window: frameWindow } = useFrame();
|
const { document, window: frameWindow } = useFrame();
|
||||||
const {path, history, changeCurrentIndex} = useQortalMessageListener(frameWindow, iframeRef, app?.tabId, isDevMode, app?.name, app?.service)
|
const {path, history, changeCurrentIndex, resetHistory} = useQortalMessageListener(frameWindow, iframeRef, app?.tabId, isDevMode, app?.name, app?.service)
|
||||||
const [url, setUrl] = useState('')
|
const [url, setUrl] = useState('')
|
||||||
|
|
||||||
|
|
||||||
useEffect(()=> {
|
useEffect(()=> {
|
||||||
|
if(app?.isPreview) return
|
||||||
if(isDevMode){
|
if(isDevMode){
|
||||||
setUrl(app?.url)
|
setUrl(app?.url)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
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])
|
}, [app?.service, app?.name, app?.identifier, app?.path, app?.isPreview])
|
||||||
|
|
||||||
|
useEffect(()=> {
|
||||||
|
if(app?.isPreview && app?.url){
|
||||||
|
resetHistory()
|
||||||
|
setUrl(app.url)
|
||||||
|
}
|
||||||
|
}, [app?.url, app?.isPreview])
|
||||||
const defaultUrl = useMemo(()=> {
|
const defaultUrl = useMemo(()=> {
|
||||||
return url
|
return url
|
||||||
}, [url, isDevMode])
|
}, [url, isDevMode])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const refreshAppFunc = (e) => {
|
const refreshAppFunc = (e) => {
|
||||||
const {tabId} = e.detail
|
const {tabId} = e.detail
|
||||||
if(tabId === app?.tabId){
|
if(tabId === app?.tabId){
|
||||||
if(isDevMode){
|
if(isDevMode){
|
||||||
setUrl(app?.url + `?time=${Date.now()}`)
|
|
||||||
|
resetHistory()
|
||||||
|
if(!app?.isPreview){
|
||||||
|
setUrl(app?.url + `?time=${Date.now()}`)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const constructUrl = `${getBaseApiReact()}/render/${app?.service}/${app?.name}${path != null ? path : ''}?theme=dark&identifier=${app?.identifier != null ? app?.identifier : ''}&time=${new Date().getMilliseconds()}`
|
const constructUrl = `${getBaseApiReact()}/render/${app?.service}/${app?.name}${path != null ? path : ''}?theme=dark&identifier=${app?.identifier != null ? app?.identifier : ''}&time=${new Date().getMilliseconds()}`
|
||||||
setUrl(constructUrl)
|
setUrl(constructUrl)
|
||||||
}
|
}
|
||||||
@ -123,7 +136,10 @@ export const AppViewer = React.forwardRef(({ app , hide, isDevMode}, iframeRef)
|
|||||||
try {
|
try {
|
||||||
await navigationPromise;
|
await navigationPromise;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
if(isDevMode){
|
||||||
|
setUrl(`${url}${previousPath != null ? previousPath : ''}?theme=dark&time=${new Date().getMilliseconds()}&isManualNavigation=false`)
|
||||||
|
return
|
||||||
|
}
|
||||||
setUrl(`${getBaseApiReact()}/render/${app?.service}/${app?.name}${previousPath != null ? previousPath : ''}?theme=dark&identifier=${(app?.identifier != null && app?.identifier != 'null') ? app?.identifier : ''}&time=${new Date().getMilliseconds()}&isManualNavigation=false`)
|
setUrl(`${getBaseApiReact()}/render/${app?.service}/${app?.name}${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
|
// iframeRef.current.contentWindow.location.href = previousPath; // Fallback URL update
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ import { AppsDevModeHome } from "./AppsDevModeHome";
|
|||||||
import { Spacer } from "../../common/Spacer";
|
import { Spacer } from "../../common/Spacer";
|
||||||
import { MyContext, getBaseApiReact } from "../../App";
|
import { MyContext, getBaseApiReact } from "../../App";
|
||||||
import { AppInfo } from "./AppInfo";
|
import { AppInfo } from "./AppInfo";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
executeEvent,
|
executeEvent,
|
||||||
subscribeToEvent,
|
subscribeToEvent,
|
||||||
@ -113,6 +114,38 @@ export const AppsDevMode = ({ mode, setMode, show , myName, goToHome, setDesktop
|
|||||||
unsubscribeFromEvent("appsDevModeAddTab", addTabFunc);
|
unsubscribeFromEvent("appsDevModeAddTab", addTabFunc);
|
||||||
};
|
};
|
||||||
}, [tabs]);
|
}, [tabs]);
|
||||||
|
|
||||||
|
const updateTabFunc = (e) => {
|
||||||
|
const data = e.detail?.data;
|
||||||
|
if(!data.tabId) return
|
||||||
|
const findIndexTab = tabs.findIndex((tab)=> tab?.tabId === data?.tabId)
|
||||||
|
if(findIndexTab === -1) return
|
||||||
|
const copyTabs = [...tabs]
|
||||||
|
const newTab ={
|
||||||
|
...copyTabs[findIndexTab],
|
||||||
|
url: data.url
|
||||||
|
|
||||||
|
}
|
||||||
|
copyTabs[findIndexTab] = newTab
|
||||||
|
|
||||||
|
setTabs(copyTabs);
|
||||||
|
setSelectedTab(newTab);
|
||||||
|
setMode("viewer");
|
||||||
|
|
||||||
|
setIsNewTabWindow(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
subscribeToEvent("appsDevModeUpdateTab", updateTabFunc);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
unsubscribeFromEvent("appsDevModeUpdateTab", updateTabFunc);
|
||||||
|
};
|
||||||
|
}, [tabs]);
|
||||||
|
|
||||||
|
|
||||||
const setSelectedTabFunc = (e) => {
|
const setSelectedTabFunc = (e) => {
|
||||||
const data = e.detail?.data;
|
const data = e.detail?.data;
|
||||||
if(!e.detail?.isDevMode) return
|
if(!e.detail?.isDevMode) return
|
||||||
@ -281,7 +314,7 @@ export const AppsDevMode = ({ mode, setMode, show , myName, goToHome, setDesktop
|
|||||||
}}>
|
}}>
|
||||||
|
|
||||||
<Spacer height="30px" />
|
<Spacer height="30px" />
|
||||||
<AppsDevModeHome availableQapps={availableQapps} setMode={setMode} myApp={null} myWebsite={null} />
|
<AppsDevModeHome myName={myName} availableQapps={availableQapps} setMode={setMode} myApp={null} myWebsite={null} />
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@ -315,7 +348,7 @@ export const AppsDevMode = ({ mode, setMode, show , myName, goToHome, setDesktop
|
|||||||
}}>
|
}}>
|
||||||
|
|
||||||
<Spacer height="30px" />
|
<Spacer height="30px" />
|
||||||
<AppsDevModeHome availableQapps={availableQapps} setMode={setMode} myApp={null} myWebsite={null} />
|
<AppsDevModeHome myName={myName} availableQapps={availableQapps} setMode={setMode} myApp={null} myWebsite={null} />
|
||||||
</Box>
|
</Box>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
@ -7,6 +7,8 @@ import {
|
|||||||
AppsContainer,
|
AppsContainer,
|
||||||
AppsParent,
|
AppsParent,
|
||||||
} from "./Apps-styles";
|
} from "./Apps-styles";
|
||||||
|
import {Buffer} from 'buffer'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Avatar,
|
Avatar,
|
||||||
Box,
|
Box,
|
||||||
@ -24,9 +26,8 @@ import { MyContext, getBaseApiReact, isMobile } from "../../App";
|
|||||||
import LogoSelected from "../../assets/svgs/LogoSelected.svg";
|
import LogoSelected from "../../assets/svgs/LogoSelected.svg";
|
||||||
import { executeEvent } from "../../utils/events";
|
import { executeEvent } from "../../utils/events";
|
||||||
import { Spacer } from "../../common/Spacer";
|
import { Spacer } from "../../common/Spacer";
|
||||||
import { AppsDevModeSortablePinnedApps } from "./AppsDevModeSortablePinnedApps";
|
|
||||||
import { useModal } from "../../common/useModal";
|
import { useModal } from "../../common/useModal";
|
||||||
import { isUsingLocal } from "../../background";
|
import { createEndpoint, isUsingLocal } from "../../background";
|
||||||
import { Label } from "../Group/AddGroup";
|
import { Label } from "../Group/AddGroup";
|
||||||
|
|
||||||
export const AppsDevModeHome = ({
|
export const AppsDevModeHome = ({
|
||||||
@ -34,10 +35,13 @@ export const AppsDevModeHome = ({
|
|||||||
myApp,
|
myApp,
|
||||||
myWebsite,
|
myWebsite,
|
||||||
availableQapps,
|
availableQapps,
|
||||||
|
myName
|
||||||
}) => {
|
}) => {
|
||||||
|
|
||||||
const [domain, setDomain] = useState("127.0.0.1");
|
const [domain, setDomain] = useState("127.0.0.1");
|
||||||
const [port, setPort] = useState("");
|
const [port, setPort] = useState("");
|
||||||
|
const [selectedPreviewFile, setSelectedPreviewFile] = useState(null);
|
||||||
|
|
||||||
const { isShow, onCancel, onOk, show, message } = useModal();
|
const { isShow, onCancel, onOk, show, message } = useModal();
|
||||||
const {
|
const {
|
||||||
openSnackGlobal,
|
openSnackGlobal,
|
||||||
@ -46,6 +50,27 @@ export const AppsDevModeHome = ({
|
|||||||
setInfoSnackCustom,
|
setInfoSnackCustom,
|
||||||
} = useContext(MyContext);
|
} = useContext(MyContext);
|
||||||
|
|
||||||
|
const handleSelectFile = async (existingFilePath) => {
|
||||||
|
const filePath = existingFilePath || await window.electron.selectFile();
|
||||||
|
if (filePath) {
|
||||||
|
|
||||||
|
const content = await window.electron.readFile(filePath);
|
||||||
|
return {buffer: content, filePath}
|
||||||
|
} else {
|
||||||
|
console.log('No file selected.');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const handleSelectDirectry = async (existingDirectoryPath) => {
|
||||||
|
const {buffer, directoryPath} = await window.electron.selectAndZipDirectory(existingDirectoryPath);
|
||||||
|
if (buffer) {
|
||||||
|
|
||||||
|
|
||||||
|
return {buffer, directoryPath}
|
||||||
|
} else {
|
||||||
|
console.log('No file selected.');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const addDevModeApp = async () => {
|
const addDevModeApp = async () => {
|
||||||
try {
|
try {
|
||||||
const usingLocal = await isUsingLocal();
|
const usingLocal = await isUsingLocal();
|
||||||
@ -82,6 +107,170 @@ export const AppsDevModeHome = ({
|
|||||||
});
|
});
|
||||||
} catch (error) {}
|
} catch (error) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const addPreviewApp = async (isRefresh, existingFilePath, tabId) => {
|
||||||
|
try {
|
||||||
|
const usingLocal = await isUsingLocal();
|
||||||
|
if (!usingLocal) {
|
||||||
|
setOpenSnackGlobal(true);
|
||||||
|
|
||||||
|
setInfoSnackCustom({
|
||||||
|
type: "error",
|
||||||
|
message:
|
||||||
|
"Please use your local node for dev mode! Logout and use Local node.",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!myName) {
|
||||||
|
setOpenSnackGlobal(true);
|
||||||
|
|
||||||
|
setInfoSnackCustom({
|
||||||
|
type: "error",
|
||||||
|
message:
|
||||||
|
"You need a name to use preview",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const {buffer, filePath} = await handleSelectFile(existingFilePath)
|
||||||
|
|
||||||
|
if (!buffer) {
|
||||||
|
setOpenSnackGlobal(true);
|
||||||
|
|
||||||
|
setInfoSnackCustom({
|
||||||
|
type: "error",
|
||||||
|
message:
|
||||||
|
"Please select a file",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const postBody = Buffer.from(buffer).toString('base64')
|
||||||
|
|
||||||
|
const endpoint = await createEndpoint(`/arbitrary/APP/${myName}/zip?preview=true`)
|
||||||
|
const response = await fetch(
|
||||||
|
endpoint
|
||||||
|
,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "text/plain",
|
||||||
|
},
|
||||||
|
body: postBody,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if(!response?.ok) throw new Error('Invalid zip')
|
||||||
|
const previewPath = await response.text();
|
||||||
|
if(tabId){
|
||||||
|
executeEvent("appsDevModeUpdateTab", {
|
||||||
|
data: {
|
||||||
|
url: "http://127.0.0.1:12391" + previewPath,
|
||||||
|
isPreview: true,
|
||||||
|
filePath,
|
||||||
|
refreshFunc: (tabId)=> {
|
||||||
|
addPreviewApp(true, filePath, tabId)
|
||||||
|
},
|
||||||
|
tabId
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return
|
||||||
|
}
|
||||||
|
executeEvent("appsDevModeAddTab", {
|
||||||
|
data: {
|
||||||
|
url: "http://127.0.0.1:12391" + previewPath,
|
||||||
|
isPreview: true,
|
||||||
|
filePath,
|
||||||
|
refreshFunc: (tabId)=> {
|
||||||
|
addPreviewApp(true, filePath, tabId)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const addPreviewAppWithDirectory = async (isRefresh, existingDir, tabId) => {
|
||||||
|
try {
|
||||||
|
const usingLocal = await isUsingLocal();
|
||||||
|
if (!usingLocal) {
|
||||||
|
setOpenSnackGlobal(true);
|
||||||
|
|
||||||
|
setInfoSnackCustom({
|
||||||
|
type: "error",
|
||||||
|
message:
|
||||||
|
"Please use your local node for dev mode! Logout and use Local node.",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!myName) {
|
||||||
|
setOpenSnackGlobal(true);
|
||||||
|
|
||||||
|
setInfoSnackCustom({
|
||||||
|
type: "error",
|
||||||
|
message:
|
||||||
|
"You need a name to use preview",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const {buffer, directoryPath} = await handleSelectDirectry(existingDir)
|
||||||
|
|
||||||
|
if (!buffer) {
|
||||||
|
setOpenSnackGlobal(true);
|
||||||
|
|
||||||
|
setInfoSnackCustom({
|
||||||
|
type: "error",
|
||||||
|
message:
|
||||||
|
"Please select a file",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const postBody = Buffer.from(buffer).toString('base64')
|
||||||
|
|
||||||
|
const endpoint = await createEndpoint(`/arbitrary/APP/${myName}/zip?preview=true`)
|
||||||
|
const response = await fetch(
|
||||||
|
endpoint
|
||||||
|
,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "text/plain",
|
||||||
|
},
|
||||||
|
body: postBody,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if(!response?.ok) throw new Error('Invalid zip')
|
||||||
|
const previewPath = await response.text();
|
||||||
|
if(tabId){
|
||||||
|
executeEvent("appsDevModeUpdateTab", {
|
||||||
|
data: {
|
||||||
|
url: "http://127.0.0.1:12391" + previewPath,
|
||||||
|
isPreview: true,
|
||||||
|
directoryPath,
|
||||||
|
refreshFunc: (tabId)=> {
|
||||||
|
addPreviewAppWithDirectory(true, directoryPath, tabId)
|
||||||
|
},
|
||||||
|
tabId
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return
|
||||||
|
}
|
||||||
|
executeEvent("appsDevModeAddTab", {
|
||||||
|
data: {
|
||||||
|
url: "http://127.0.0.1:12391" + previewPath,
|
||||||
|
isPreview: true,
|
||||||
|
directoryPath,
|
||||||
|
refreshFunc: (tabId)=> {
|
||||||
|
addPreviewAppWithDirectory(true, directoryPath, tabId)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -118,7 +307,39 @@ export const AppsDevModeHome = ({
|
|||||||
<AppCircle>
|
<AppCircle>
|
||||||
<Add>+</Add>
|
<Add>+</Add>
|
||||||
</AppCircle>
|
</AppCircle>
|
||||||
<AppCircleLabel>App</AppCircleLabel>
|
<AppCircleLabel>Server</AppCircleLabel>
|
||||||
|
</AppCircleContainer>
|
||||||
|
</ButtonBase>
|
||||||
|
<ButtonBase
|
||||||
|
onClick={() => {
|
||||||
|
addPreviewApp();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<AppCircleContainer
|
||||||
|
sx={{
|
||||||
|
gap: !isMobile ? "10px" : "5px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<AppCircle>
|
||||||
|
<Add>+</Add>
|
||||||
|
</AppCircle>
|
||||||
|
<AppCircleLabel>Zip</AppCircleLabel>
|
||||||
|
</AppCircleContainer>
|
||||||
|
</ButtonBase>
|
||||||
|
<ButtonBase
|
||||||
|
onClick={() => {
|
||||||
|
addPreviewAppWithDirectory();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<AppCircleContainer
|
||||||
|
sx={{
|
||||||
|
gap: !isMobile ? "10px" : "5px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<AppCircle>
|
||||||
|
<Add>+</Add>
|
||||||
|
</AppCircle>
|
||||||
|
<AppCircleLabel>Directory</AppCircleLabel>
|
||||||
</AppCircleContainer>
|
</AppCircleContainer>
|
||||||
</ButtonBase>
|
</ButtonBase>
|
||||||
</AppsContainer>
|
</AppsContainer>
|
||||||
|
@ -189,9 +189,14 @@ export const AppsDevModeNavBar = () => {
|
|||||||
|
|
||||||
<ButtonBase
|
<ButtonBase
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
executeEvent("refreshApp", {
|
if(selectedTab?.refreshFunc){
|
||||||
tabId: selectedTab?.tabId,
|
selectedTab.refreshFunc(selectedTab?.tabId)
|
||||||
});
|
} else {
|
||||||
|
executeEvent("refreshApp", {
|
||||||
|
tabId: selectedTab?.tabId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<RefreshIcon
|
<RefreshIcon
|
||||||
|
@ -395,6 +395,7 @@ isDOMContentLoaded: false
|
|||||||
infoSnackCustom,
|
infoSnackCustom,
|
||||||
setInfoSnackCustom } = useContext(MyContext);
|
setInfoSnackCustom } = useContext(MyContext);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(()=> {
|
useEffect(()=> {
|
||||||
if(tabId && !isNaN(history?.currentIndex)){
|
if(tabId && !isNaN(history?.currentIndex)){
|
||||||
@ -509,7 +510,7 @@ isDOMContentLoaded: false
|
|||||||
event?.data?.action === 'QDN_RESOURCE_DISPLAYED'){
|
event?.data?.action === 'QDN_RESOURCE_DISPLAYED'){
|
||||||
const pathUrl = event?.data?.path != null ? (event?.data?.path.startsWith('/') ? '' : '/') + event?.data?.path : null
|
const pathUrl = event?.data?.path != null ? (event?.data?.path.startsWith('/') ? '' : '/') + event?.data?.path : null
|
||||||
setPath(pathUrl)
|
setPath(pathUrl)
|
||||||
if(appName.toLowerCase() === 'q-mail'){
|
if(appName?.toLowerCase() === 'q-mail'){
|
||||||
window.sendMessage("addEnteredQmailTimestamp").catch((error) => {
|
window.sendMessage("addEnteredQmailTimestamp").catch((error) => {
|
||||||
// error
|
// error
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user