diff --git a/app/.electron/main.ts b/app/.electron/main.ts index f4cf9ef3..d304609a 100644 --- a/app/.electron/main.ts +++ b/app/.electron/main.ts @@ -8,11 +8,17 @@ const path = require('path'); import { app, protocol, + net, BrowserWindow, session, ipcMain, - dialog + dialog, + webContents, + WebContents, + Event } from 'electron'; +import * as fs from 'fs' +const{ default: axios } = require('axios') // The splash screen is what appears while the app is loading // const { initSplashScreen, OfficeTemplate } = require('electron-splashscreen'); import { resolve } from 'app-root-path'; @@ -23,15 +29,15 @@ import { resolve } from 'app-root-path'; // } = require('electron-devtools-installer'); import debug from 'electron-debug'; // import custom protocol in protocol.js -import Protocol from './protocol'; +// import { scheme } from './protocol'; // menu from another file to modularize the code - -import MenuBuilder from './menu'; - +import { MenuBuilder } from './menu'; +import { string } from 'prop-types'; +import { hostname } from 'os'; +console.log('Main.ts has started'); // mode that the app is running in const isDev = - import.meta.env.NODE_ENV === 'development' || - import.meta.env.NODE_ENV === 'test'; + process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test'; const port = 8080; const selfHost = `http://localhost:${port}`; @@ -45,7 +51,6 @@ let menuBuilder: any; async function createWindow() { // install react dev tools if we are in development mode // this will happen before creating the browser window. it returns a Boolean whether the protocol of scheme 'app://' was successfully registered and a file (index-prod.html) was sent as the response - protocol.registerBufferProtocol(Protocol.scheme, Protocol.requestHandler); // Create the browser window. win = new BrowserWindow({ @@ -74,10 +79,10 @@ async function createWindow() { // Electron API only available from preload, not loaded page contextIsolation: true, // disables remote module. critical for ensuring that rendering process doesn't have access to node functionality - enableRemoteModule: true, + // EnableRemoteModule: true is Deprecated // path of preload script. preload is how the renderer page will have access to electron functionality - preload: path.join(__dirname, 'preload.js'), - nativeWindowOpen: true + preload: path.join(__dirname, 'preload.js') + // nativeWindowOpen: true is Deprecated } }); @@ -101,7 +106,7 @@ async function createWindow() { win.loadURL(selfHost); } else { // load local file if in production - win.loadURL(`${Protocol.scheme}://rse/index-prod.html`); + win.loadURL(`app://rse/index-prod.html`); } // load page once window is loaded @@ -159,11 +164,11 @@ async function createWindow() { .fromPartition(partition) .webRequest.onBeforeRequest( { urls: ['http://localhost./*'] }, - (listener) => { - if (listener.url.indexOf('http://') >= 0) { - listener.callback({ - cancel: true - }); + (details, callback) => { + if (details.url.indexOf('http://') >= 0) { + callback({ cancel: true }); + } else { + callback({}); } } ); @@ -175,7 +180,7 @@ async function createWindow() { // https://electronjs.org/docs/api/protocol#protocolregisterschemesasprivilegedcustomschemes protocol.registerSchemesAsPrivileged([ { - scheme: Protocol.scheme, + scheme: 'app', privileges: { standard: true, secure: true, @@ -185,11 +190,32 @@ protocol.registerSchemesAsPrivileged([ } ]); +const DIST_PATH = path.join(__dirname, '../../app/dist') + +protocol.handle('app', (request) => { + const url = new URL(request.url); + const filePath = url.pathname; + + // Construct the full path using DIST_PATH and requested file path + const fullPath = path.join(DIST_PATH, filePath); + + // Fetch the resource and return a promise + return new Promise((resolve, reject) => { + net.fetch(fullPath) + .then((response) => { + // Resolve with the fetched response + resolve(response); + }) + .catch((error) => { + // Reject with the error + reject(error); + }); + }); +}); // This method will be called when Electron has finished // initialization and is ready to create browser windows. // Some APIs can only be used after this event occurs. app.on('ready', createWindow); - // TRYING ELECTRON-WINDOW-MANAGER When the application is ready // Quit when all windows are closed. @@ -209,130 +235,143 @@ app.on('activate', () => { // redirects are a common attack vector // after the contents of the webpage are rendered, set up event listeners on the webContents -app.on('web-contents-created', (event, contents) => { - contents.on('will-navigate', (event, navigationUrl) => { - const parsedUrl = new URL(navigationUrl); - const validOrigins = [ - selfHost, - //'https://reactype-1.herokuapp.com', - 'https://reactype-caret.herokuapp.com', - `http://localhost:${DEV_PORT}`, - 'https://reactype.herokuapp.com', - 'https://github.com', - 'https://nextjs.org', - 'https://www.facebook.com', - 'https://developer.mozilla.org', - 'https://www.smashingmagazine.com', - 'https://www.html5rocks.com', - 'null', - 'app://rse/' - ]; - // Log and prevent the app from navigating to a new page if that page's origin is not whitelisted - if (!validOrigins.includes(parsedUrl.origin)) { - console.error( - `The application tried to navigate to the following address: '${parsedUrl}'. This origin is not whitelisted attempt to navigate was blocked.` - ); - // if the requested URL is not in the whitelisted array, then don't navigate there - event.preventDefault(); - } - }); +app.on( + 'web-contents-created', + (event: Electron.Event, contents: Electron.WebContents) => { + contents.on( + 'will-navigate', + (event: Electron.Event, navigationUrl: string) => { + const parsedUrl = new URL(navigationUrl); + const validOrigins = [ + selfHost, + //'https://reactype-1.herokuapp.com', + 'https://reactype-caret.herokuapp.com', + `http://localhost:${DEV_PORT}`, + 'https://reactype.herokuapp.com', + 'https://github.com', + 'https://nextjs.org', + 'https://www.facebook.com', + 'https://developer.mozilla.org', + 'https://www.smashingmagazine.com', + 'https://www.html5rocks.com', + 'null', + 'app://rse/' + ]; + // Log and prevent the app from navigating to a new page if that page's origin is not whitelisted + if (!validOrigins.includes(parsedUrl.origin)) { + console.error( + `The application tried to navigate to the following address: '${parsedUrl}'. This origin is not whitelisted attempt to navigate was blocked.` + ); + // if the requested URL is not in the whitelisted array, then don't navigate there + event.preventDefault(); + } + } + ); - contents.on('will-redirect', (event, navigationUrl) => { - const parsedUrl = new URL(navigationUrl); - const validOrigins = [ - selfHost, - //'https://reactype-1.herokuapp.com/', - 'https://reactype-caret.herokuapp.com', - `http://localhost:${DEV_PORT}`, - 'https://reactype.herokuapp.com', - 'https://github.com', - 'https://nextjs.org', - 'https://developer.mozilla.org', - 'https://www.facebook.com', - 'https://www.smashingmagazine.com', - 'https://www.html5rocks.com', - 'app://rse/', - 'null' - ]; - // Log and prevent the app from redirecting to a new page - if ( - !validOrigins.includes(parsedUrl.origin) && - !validOrigins.includes(parsedUrl.href) - ) { - console.error( - `The application tried to redirect to the following address: '${navigationUrl}'. This attempt was blocked.` - ); - - event.preventDefault(); - } - }); + contents.on( + 'will-redirect', + (event: Electron.Event, navigationUrl: string) => { + const parsedUrl = new URL(navigationUrl); + const validOrigins = [ + selfHost, + //'https://reactype-1.herokuapp.com/', + 'https://reactype-caret.herokuapp.com', + `http://localhost:${DEV_PORT}`, + 'https://reactype.herokuapp.com', + 'https://github.com', + 'https://nextjs.org', + 'https://developer.mozilla.org', + 'https://www.facebook.com', + 'https://www.smashingmagazine.com', + 'https://www.html5rocks.com', + 'app://rse/', + 'null' + ]; + // Log and prevent the app from redirecting to a new page + if ( + !validOrigins.includes(parsedUrl.origin) && + !validOrigins.includes(parsedUrl.href) + ) { + console.error( + `The application tried to redirect to the following address: '${navigationUrl}'. This attempt was blocked.` + ); + + event.preventDefault(); + } + } + ); - // https://electronjs.org/docs/tutorial/security#11-verify-webview-options-before-creation - // The web-view is used to embed guest content in a page - // This event listener deletes web-views if they happen to occur in the app - // https://www.electronjs.org/docs/api/web-contents#event-will-attach-webview - contents.on('will-attach-webview', (event, webPreferences, params) => { - // Strip away preload scripts if unused or verify their location is legitimate - delete webPreferences.preload; - delete webPreferences.preloadURL; - - // Disable Node.js integration - webPreferences.nodeIntegration = false; - }); + // https://electronjs.org/docs/tutorial/security#11-verify-webview-options-before-creation + // The web-view is used to embed guest content in a page + // This event listener deletes web-views if they happen to occur in the app + // https://www.electronjs.org/docs/api/web-contents#event-will-attach-webview + contents.on( + 'will-attach-webview', + (event: Electron.Event, webPreferences: Electron.WebPreferences) => { + // Strip away preload scripts if unused or verify their location is legitimate + delete webPreferences.preload; + + // Disable Node.js integration + webPreferences.nodeIntegration = false; + } + ); - // https://electronjs.org/docs/tutorial/security#13-disable-or-limit-creation-of-new-windows - contents.on('new-window', async (event, navigationUrl) => { - // Log and prevent opening up a new window - const parsedUrl = new URL(navigationUrl); - const validOrigins = [ - selfHost, - //'https://reactype-1.herokuapp.com/', - 'https://reactype-caret.herokuapp.com', - `http://localhost:${DEV_PORT}`, - 'https://reactype.herokuapp.com', - 'https://nextjs.org', - 'https://developer.mozilla.org', - 'https://github.com', - 'https://www.facebook.com', - 'https://www.smashingmagazine.com', - 'https://www.html5rocks.com', - 'null', - 'app://rse/' - ]; - // Log and prevent the app from navigating to a new page if that page's origin is not whitelisted - if (!validOrigins.includes(parsedUrl.origin)) { - console.error( - `The application tried to open a new window at the following address: '${navigationUrl}'. This attempt was blocked.` - ); - // if the requested URL is not in the whitelisted array, then don't navigate there - event.preventDefault(); - } - }); -}); + // https://electronjs.org/docs/tutorial/security#13-disable-or-limit-creation-of-new-windows + contents.setWindowOpenHandler(({ url }) => { + // Log and prevent opening up a new window + const parsedUrl = new URL(url); + const validOrigins = [ + selfHost, + //'https://reactype-1.herokuapp.com/', + 'https://reactype-caret.herokuapp.com', + `http://localhost:${DEV_PORT}`, + 'https://reactype.herokuapp.com', + 'https://nextjs.org', + 'https://developer.mozilla.org', + 'https://github.com', + 'https://www.facebook.com', + 'https://www.smashingmagazine.com', + 'https://www.html5rocks.com', + 'null', + 'app://rse/' + ]; + // Log and prevent the app from navigating to a new page if that page's origin is not whitelisted + if (!validOrigins.includes(parsedUrl.origin)) { + console.error( + `The application tried to open a new window at the following address: '${url}'. This attempt was blocked.` + ); + // if the requested URL is not in the whitelisted array, then don't navigate there + return { action: 'deny' }; + } + return { action: 'allow' }; + }); + } +); // Filter loading any module via remote; // you shouldn't be using remote at all, though // https://electronjs.org/docs/tutorial/security#16-filter-the-remote-module -app.on('remote-require', (event, webContents, moduleName) => { - event.preventDefault(); -}); +// commented out due to lack of remote usage / deprecation / all this code does is prevent the usage of remote. +// app.on('remote-require', (event, webContents, moduleName) => { +// event.preventDefault(); +// }); -// built-ins are modules such as "app" -app.on('remote-get-builtin', (event, webContents, moduleName) => { - event.preventDefault(); -}); +// // built-ins are modules such as "app" +// app.on('remote-get-builtin', (event, webContents, moduleName) => { +// event.preventDefault(); +// }); -app.on('remote-get-global', (event, webContents, globalName) => { - event.preventDefault(); -}); +// app.on('remote-get-global', (event, webContents, globalName) => { +// event.preventDefault(); +// }); -app.on('remote-get-current-window', (event, webContents) => { - event.preventDefault(); -}); +// app.on('remote-get-current-window', (event, webContents) => { +// event.preventDefault(); +// }); -app.on('remote-get-current-web-contents', (event, webContents) => { - event.preventDefault(); -}); +// app.on('remote-get-current-web-contents', (event, webContents) => { +// event.preventDefault(); +// }); // When a user selects "Export project", a function (chooseAppDir loaded via preload.js) // is triggered that sends a "choose_app_dir" message to the main process @@ -384,128 +423,180 @@ ipcMain.on('delete_cookie', (event) => { }); // opens new window for github oauth when button on sign in page is clicked -ipcMain.on('github', (event) => { - const githubURL = isDev - ? `http://localhost:${DEV_PORT}/auth/github` - : `https://reactype-caret.herokuapp.com/auth/github`; +// ipcMain.on('github', (event) => { +// const githubURL = isDev +// ? `http://localhost:${DEV_PORT}/auth/github` +// : `https://reactype-caret.herokuapp.com/auth/github`; +// const options = { +// client_id: process.env.GITHUB_CLIENT, +// client_secret: process.env.GITHUB_SECRET, +// scopes: ['user:email', 'notifications'] +// }; +// // create new browser window object with size, title, security options +// const github: BrowserWindow | null = new BrowserWindow({ +// width: 800, +// height: 600, +// title: 'Github Oauth', +// webPreferences: { +// nodeIntegration: true, +// nodeIntegrationInWorker: false, +// nodeIntegrationInSubFrames: false, +// contextIsolation: true, +// zoomFactor: 1.0 +// } +// }); + +// github.loadURL(githubURL); +// github.show(); +// const handleCallback = (url) => { +// const raw_code = /code=([^&]\*)/.exec(url) || null; +// const code = raw_code && raw_code.length > 1 ? raw_code[1] : null; +// const error = /\?error=(.+)\$/.exec(url); + +// if (code || error) { +// // Close the browser if code found or error +// github.destroy(); +// } + +// // If there is a code, proceed to get token from github +// if (code) { +// self.requestGithubToken(options, code); +// } else if (error) { +// alert( +// "Oops! Something went wrong and we couldn't" + +// 'log you in using Github. Please try again.' +// ); +// } +// }; + +// github.webContents.on('will-navigate', (e, url) => handleCallback(url)); + +// github.webContents.on('did-finish-load', (e, url, a, b) => { +// github.webContents.selectAll(); +// }); + +// github.webContents.on( +// 'will-redirect', +// (event: Electron.Event, callbackUrl: string): void => +// handleCallback(callbackUrl) +// ); +// // Reset the authWindow on close +// github.on('close', () => { +// github = null; +// }); + +// // if final callback is reached and we get a redirect from server back to our app, close oauth window +// github.webContents.on('will-redirect', (e, callbackUrl) => { +// const matches = callbackUrl.match(/(?<=\?=).*/); +// const ssid = matches ? matches[0] : ''; +// callbackUrl = callbackUrl.replace(/\?=.*/, ''); +// let redirectUrl = 'app://rse/'; +// if (isDev) { +// redirectUrl = 'http://localhost:8080/'; +// } + +// if (callbackUrl === redirectUrl) { +// dialog.showMessageBox({ +// type: 'info', +// title: 'ReacType', +// icon: resolve('app/src/public/icons/png/256x256.png'), +// message: 'Github Oauth Successful!' +// }); +// github.close(); +// win!.webContents +// .executeJavaScript(`window.localStorage.setItem('ssid', '${ssid}')`) +// .then((result) => win!.loadURL(`${redirectUrl}`)) +// .catch((err) => console.log(err)); +// } +// }); +// }); +// updated github OAuth +ipcMain.on('github', (event, webContents: WebContents) => { + const githubAuthURL = 'https://github.com/login/oauth/authorize'; + const githubTokenURL = 'https://github.com/login/oauth/access_token'; + const options = { - client_id: import.meta.env.GITHUB_ID, - client_secret: import.meta.env.GITHUB_SECRET, - scopes: ['user:email', 'notifications'] + client_id: process.env.GITHUB_CLIENT, + client_secret: process.env.GITHUB_SECRET, + redirect_uri: isDev ? 'http://localhost:8080/' : 'app://rse/', // Your redirect URL + scopes: ['user:email', 'notifications'], }; - // create new browser window object with size, title, security options - const github = new BrowserWindow({ + + const authWindow = new BrowserWindow({ width: 800, height: 600, - title: 'Github Oauth', + title: 'GitHub OAuth', webPreferences: { - nodeIntegration: true, - nodeIntegrationInWorker: false, - nodeIntegrationInSubFrames: false, + nodeIntegration: false, contextIsolation: true, - enableRemoteModule: true, - zoomFactor: 1.0 - } + }, }); - github.loadURL(githubURL); - github.show(); - const handleCallback = (url) => { - const raw_code = /code=([^&]\*)/.exec(url) || null; - const code = raw_code && raw_code.length > 1 ? raw_code[1] : null; - const error = /\?error=(.+)\$/.exec(url); + const authURL = `${githubAuthURL}?client_id=${options.client_id}&scope=${options.scopes.join(',')}`; + authWindow.loadURL(authURL); - if (code || error) { - // Close the browser if code found or error - github.destroy(); - } + authWindow.webContents.on('will-redirect', async (event, url) => { + const rawCode = /code=([^&]*)/.exec(url) || null; + const code = rawCode && rawCode.length > 1 ? rawCode[1] : null; + const error = /\?error=(.+)$/.exec(url); - // If there is a code, proceed to get token from github if (code) { - self.requestGithubToken(options, code); + try { + const { data } = await axios.post(githubTokenURL, { + code, + client_id: options.client_id, + client_secret: options.client_secret, + redirect_uri: options.redirect_uri, + }); + + const accessToken = data.access_token; + // Store accessToken securely + webContents.send('github-auth-success', accessToken); + } catch (error) { + // Handle error + console.error('Error exchanging code for token:', error); + webContents.send('github-auth-failure'); + } } else if (error) { - alert( - "Oops! Something went wrong and we couldn't" + - 'log you in using Github. Please try again.' - ); - } - }; - - github.webContents.on('will-navigate', (e, url) => handleCallback(url)); - - github.webContents.on('did-finish-load', (e, url, a, b) => { - github.webContents.selectAll(); - }); - - github.webContents.on('did-get-redirect-request', (e, oldUrl, newUrl) => - handleCallback(newUrl) - ); - - // Reset the authWindow on close - github.on('close', () => (authWindow = null), false); - - // if final callback is reached and we get a redirect from server back to our app, close oauth window - github.webContents.on('will-redirect', (e, callbackUrl) => { - const matches = callbackUrl.match(/(?<=\?=).*/); - const ssid = matches ? matches[0] : ''; - callbackUrl = callbackUrl.replace(/\?=.*/, ''); - let redirectUrl = 'app://rse/'; - if (isDev) { - redirectUrl = 'http://localhost:8080/'; + // Handle error + console.error('Error during GitHub OAuth:', error[1]); + webContents.send('github-auth-failure'); } - if (callbackUrl === redirectUrl) { - dialog.showMessageBox({ - type: 'info', - title: 'ReacType', - icon: resolve('app/src/public/icons/png/256x256.png'), - message: 'Github Oauth Successful!' - }); - github.close(); - win!.webContents - .executeJavaScript(`window.localStorage.setItem('ssid', '${ssid}')`) - .then((result) => win!.loadURL(`${redirectUrl}`)) - .catch((err) => console.log(err)); - } + authWindow.close(); }); }); -ipcMain.on('tutorial', (event) => { - // create new browser window object with size, title, security options - const tutorial = new BrowserWindow({ - width: 800, - height: 600, - minWidth: 661, - title: 'Tutorial', - webPreferences: { - nodeIntegration: true, - nodeIntegrationInWorker: false, - nodeIntegrationInSubFrames: false, - contextIsolation: true, - enableRemoteModule: true, - zoomFactor: 1.0 - } - }); - // redirects to relevant server endpoint - github.loadURL(`${serverUrl}/github`); - // show window - tutorial.show(); - // if final callback is reached and we get a redirect from server back to our app, close oauth window - github.webContents.on('will-redirect', (e, callbackUrl) => { - let redirectUrl = 'app://rse/'; - if (isDev) { - redirectUrl = 'http://localhost:8080/'; - } - if (callbackUrl === redirectUrl) { - dialog.showMessageBox({ - type: 'info', - title: 'ReacType', - icon: resolve('app/src/public/icons/png/256x256.png'), - message: 'Github Oauth Successful!' - }); - github.close(); - } - }); -}); +// ipcMain.on('openTutorialWindow', (event) => { +// // create new browser window object with size, title, security options +// const tutorial = new BrowserWindow({ +// width: 800, +// height: 600, +// minWidth: 661, +// title: 'Tutorial', +// webPreferences: { +// nodeIntegration: true, +// nodeIntegrationInWorker: false, +// nodeIntegrationInSubFrames: false, +// contextIsolation: true, +// zoomFactor: 1.0 +// } +// }); +// // redirects to relevant server endpoint +// tutorial.loadURL(`${serverUrl}/github`); +// // show window +// tutorial.show(); +// // if final callback is reached and we get a redirect from server back to our app, close oauth window +// tutorial.webContents.on('will-redirect', (e, callbackUrl) => { +// let redirectUrl = 'app://rse/'; +// if (isDev) { +// redirectUrl = 'http://localhost:8080/'; +// } +// if (callbackUrl === redirectUrl) { +// event.sender.send('showOAuthSuccessMessage'); +// tutorial.close(); +// } +// }); +// }); module.exports = dialog; diff --git a/app/.electron/menu.ts b/app/.electron/menu.ts index abaacf72..61904449 100644 --- a/app/.electron/menu.ts +++ b/app/.electron/menu.ts @@ -1,6 +1,6 @@ import { Menu, BrowserWindow, Shell } from 'electron'; const isMac = process.platform === 'darwin'; -import Protocol from './protocol'; +import {scheme, requestHandler } from './protocol'; /* DESCRIPTION: This file generates an array containing a menu based on the operating system the user is running. menuBuilder: The entire file is encompassed in menuBuilder. Ultimately, menuBuilder returns a function called @@ -31,29 +31,28 @@ var MenuBuilder = function (mainWindow, appName) { // you can also create custom menu items with their own "on click" functionality if you need to // different roles are available between mac and windows - function openTutorial(): void { - const tutorial = new BrowserWindow({ - width: 1180, - height: 900, - minWidth: 665, - title: 'Tutorial', - webPreferences: { - nodeIntegration: true, - nodeIntegrationInWorker: false, - nodeIntegrationInSubFrames: false, - contextIsolation: true, - enableRemoteModule: true, - zoomFactor: 1.0, - devTools: false - } - }); - if (import.meta.env.NODE_ENV === 'development') { - tutorial.loadURL(`http://localhost:8080/#/tutorial`); - } else { - tutorial.loadURL(`${Protocol.scheme}://rse/index-prod.html#/tutorial`); - } - tutorial.show(); - } + // function openTutorial(): void { + // const tutorial = new BrowserWindow({ + // width: 1180, + // height: 900, + // minWidth: 665, + // title: 'Tutorial', + // webPreferences: { + // nodeIntegration: true, + // nodeIntegrationInWorker: false, + // nodeIntegrationInSubFrames: false, + // contextIsolation: true, + // zoomFactor: 1.0, + // devTools: false + // } + // }); + // if (import.meta.env.NODE_ENV === 'development') { + // tutorial.loadURL(`http://localhost:8080/#/tutorial`); + // } else { + // tutorial.loadURL(`${scheme}://rse/index-prod.html#/tutorial`); + // } + // tutorial.show(); + // } const defaultTemplate= (): Electron.MenuItemConstructorOptions[] => [ ...(isMac @@ -223,10 +222,10 @@ var MenuBuilder = function (mainWindow, appName) { ); } }, - { - label: 'Tutorial', - click: () => openTutorial() - } + // { + // label: 'Tutorial', + // click: () => openTutorial() + // } ] } ]; @@ -243,6 +242,5 @@ var MenuBuilder = function (mainWindow, appName) { return menu; } }; -}; export { MenuBuilder }; diff --git a/app/.electron/protocol.ts b/app/.electron/protocol.ts index 3f36cf06..6b0a0490 100644 --- a/app/.electron/protocol.ts +++ b/app/.electron/protocol.ts @@ -3,74 +3,76 @@ @exports: scheme, requestHandler @usage: is used in main.js */ +// import { Request, Response } from 'electron'; +// const { stringify } = require('querystring'); unused +// import * as fs from 'fs'; +// import * as path from 'path'; -const { stringify } = require('querystring'); -import * as fs from 'fs'; -import * as path from 'path'; -const DIST_PATH = path.join(__dirname, '../../app/dist'); +// const DIST_PATH = path.join(__dirname, '../../app/dist'); -const scheme = 'app'; // it will serve resources like app://..... instead of default file://... +// const scheme = 'app'; // it will serve resources like app://..... instead of default file://... -const mimeTypes: Record = { - '.js': 'text/javascript', - '.mjs': 'text/javascript', - '.html': 'text/html', - '.htm': 'text/html', - '.json': 'application/json', - '.css': 'text/css', - '.svg': 'application/svg+xml', - '.ico': 'image/vnd.microsoft.icon', - '.png': 'image/png', - '.jpg': 'image/jpeg', - '.map': 'text/plain' -}; +// const mimeTypes: Record = { +// '.js': 'text/javascript', +// '.mjs': 'text/javascript', +// '.html': 'text/html', +// '.htm': 'text/html', +// '.json': 'application/json', +// '.css': 'text/css', +// '.svg': 'application/svg+xml', +// '.ico': 'image/vnd.microsoft.icon', +// '.png': 'image/png', +// '.jpg': 'image/jpeg', +// '.map': 'text/plain' +// }; -function charset(mimeType: string): string | null { - return ['.html', '.htm', '.js', '.mjs'].some((m) => m === mimeType) - ? 'utf-8' - : null; -} -// return the file type -function mime(filename: string): string | null { - const type = mimeTypes[path.extname(`${filename || ''}`).toLowerCase()]; - return type || null; -} +// function charset(mimeType: string): string | null { +// return ['.html', '.htm', '.js', '.mjs'].some((m) => m === mimeType) +// ? 'utf-8' +// : null; +// } +// // return the file type +// function mime(filename: string): string | null { +// const type = mimeTypes[path.extname(`${filename || ''}`).toLowerCase()]; +// return type || null; +// } /* requestHandler servers index-prod.html when we access the root endpoint '/' read the file above and pass on an object includes mimeType, charset, and exisiting data read from the file */ -function requestHandler( - req: Electron.ProtocolRequest, - next: (response: Electron.ProtocolResponse) => void -): void { - // The URL() constructor returns a newly created URL object representing the URL defined by the parameters. - const reqUrl = new URL(req.url); - // path.normalize resolves '..' and '.' segments in sequential path segments - // url.pathname: an initial '/' followed by the path of the URL not including the query string or fragment (or the empty string if there is no path). - let reqPath = path.normalize(reqUrl.pathname); +// function requestHandler( +// req: Request, +// callback: (response: Response | Promise) => void +// ): void { +// // The URL() constructor returns a newly created URL object representing the URL defined by the parameters. +// const reqUrl = new URL(req.url); +// // path.normalize resolves '..' and '.' segments in sequential path segments +// // url.pathname: an initial '/' followed by the path of the URL not including the query string or fragment (or the empty string if there is no path). +// let reqPath = path.normalize(reqUrl.pathname); - // when app opens, serve index-prod.html - if (reqPath === '/') { - reqPath = '/index-prod.html'; - } - // path.basename returns the last portion of a path which includes filename we want to serve - const reqFilename = path.basename(reqPath); - // use fs module to read index-prod.html (reqPath) in dist folder - fs.readFile(path.join(DIST_PATH, reqPath), (err, data) => { - const mimeType = mime(reqFilename); // returns the file type - // check if there is no error and file type is valid, pass on the info to the next middleware - if (!err && mimeType !== null) { - next({ - mimeType, - charset: charset(mimeType), - data - }); - } else { - console.error(err); - } - }); -} -export { scheme, requestHandler }; +// // when app opens, serve index-prod.html +// if (reqPath === '/') { +// reqPath = '/index-prod.html'; +// } +// // path.basename returns the last portion of a path which includes filename we want to serve +// const reqFilename = path.basename(reqPath); +// // use fs module to read index-prod.html (reqPath) in dist folder +// fs.readFile(path.join(DIST_PATH, reqPath), (err, data) => { +// const mimeType = mime(reqFilename); // returns the file type +// // check if there is no error and file type is valid, pass on the info to the next middleware +// if (!err && mimeType !== null) { +// callback({ +// mimeType, +// charset: charset(mimeType), +// data +// }); +// } else { +// console.error(err); +// } +// }); +// } + +// export { scheme }; diff --git a/app/.electron/render.ts b/app/.electron/render.ts index 1cdf66de..f6f79be6 100644 --- a/app/.electron/render.ts +++ b/app/.electron/render.ts @@ -1,11 +1,11 @@ -import {remote} from 'electron'; -import {BrowserWindow} from 'electron-window-manager'; +// import {remote} from 'electron'; +// import {BrowserWindow} from 'electron-window-manager'; -const win2 = browserwindow.createNew('win2', 'Windows #2'); -win2.setURL('/win2.html'); -win2.onReady(() => {...}); -win2.open() +// const win2 = BrowserWindow.createNew('win2', 'Windows #2'); +// win2.setURL('/win2.html'); +// win2.onReady(() => {...}); +// win2.open() @@ -15,3 +15,7 @@ win2.open() =windowManager.createNew('win2', 'Windows #2'); win2.setURL('/win2.html'); win2.onReady( ... ); win2.open(); ; */ + + +// unnecesary code / file +// win2 is unused nor needed. diff --git a/app/src/components/top/NavBarButtons.tsx b/app/src/components/top/NavBarButtons.tsx index 7b361d72..d0d8b265 100644 --- a/app/src/components/top/NavBarButtons.tsx +++ b/app/src/components/top/NavBarButtons.tsx @@ -14,7 +14,6 @@ import ProjectsFolder from '../right/OpenProjects'; import { RootState } from '../../redux/store'; import SaveProjectButton from '../right/SaveProjectButton'; import serverConfig from '../../serverConfig.js'; - import createModal from '../right/createModal'; import createStyles from '@mui/styles/createStyles'; import makeStyles from '@mui/styles/makeStyles'; @@ -90,7 +89,6 @@ const StyledMenuItem = withStyles((theme) => ({ // where the main function starts // const navbarDropDown = (props) => { const dispatch = useDispatch(); - const [modal, setModal] = React.useState(null); const [anchorEl, setAnchorEl] = React.useState(null); const classes = useStyles(); @@ -105,6 +103,8 @@ const navbarDropDown = (props) => { const closeModal = () => setModal(''); const handleClick = (event) => { setAnchorEl(event.currentTarget); + + props.setDropDownMenu(true) }; const clearWorkspace = () => { @@ -188,7 +188,7 @@ const navbarDropDown = (props) => { return (
- + - {/* */} +

ReacType Tutorial

@@ -159,4 +166,5 @@ const Tutorial: React.FC = () => { ); }; -export default withRouter(Tutorial); + +export default Tutorial; diff --git a/app/src/tutorial/TutorialPage.tsx b/app/src/tutorial/TutorialPage.tsx index cd8ed45d..2870bc71 100644 --- a/app/src/tutorial/TutorialPage.tsx +++ b/app/src/tutorial/TutorialPage.tsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useState , useEffect } from 'react'; import makeStyles from '@mui/styles/makeStyles'; import { Link, withRouter, RouteComponentProps } from 'react-router-dom'; import Pages from './Pages'; @@ -89,9 +89,16 @@ const tutorialPageStyle = { } }; -const TutorialPage: React.FC = (props) => { +const TutorialPage: React.FC> = (props) => { + console.log('TutorialPage component is rendered'); const classes = useStyles(); const [page, setPage] = useState(props.match.params.learn); + console.log(props.match.params.learn) + console.log('TutorialPage rendered with page:', page); + + useEffect(() => { + console.log('Page:', page); + }, [page]); return (
@@ -221,4 +228,4 @@ const TutorialPage: React.FC = (props) => { ); }; -export default withRouter(TutorialPage); +export default TutorialPage; diff --git a/config.js b/config.js index 7c65496b..751a15e3 100644 --- a/config.js +++ b/config.js @@ -7,8 +7,6 @@ const config = { // : 'http://localhost:8080', API_BASE_URL2: isProduction ? 'https://app.reactype.dev' - : 'http://localhost:8080' + : 'http://localhost:8080', }; module.exports = config; - -// export default config; diff --git a/package-lock.json b/package-lock.json index 92a81fea..94f118db 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "@aws-amplify/core": "^5.8.4", "@babel/cli": "^7.23.4", "@babel/register": "^7.22.15", + "@electron/remote": "^2.1.2", "@graphql-tools/schema": "^9.0.19", "@mui/icons-material": "^5.15.7", "@mui/lab": "^5.0.0-alpha.93", @@ -103,6 +104,7 @@ "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^12.1.5", "@types/chai": "^4.3.11", + "@types/electron": "^1.6.10", "@types/jest": "^28.1.8", "@typescript-eslint/eslint-plugin": "^5.62.0", "@typescript-eslint/parser": "^5.62.0", @@ -9230,7 +9232,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.3.tgz", "integrity": "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==", - "dev": true, "dependencies": { "debug": "^4.1.1", "env-paths": "^2.2.0", @@ -9365,6 +9366,14 @@ "node": ">= 10.0.0" } }, + "node_modules/@electron/remote": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@electron/remote/-/remote-2.1.2.tgz", + "integrity": "sha512-EPwNx+nhdrTBxyCqXt/pftoQg/ybtWDW3DUWHafejvnB1ZGGfMpv6e15D8KeempocjXe78T7WreyGGb3mlZxdA==", + "peerDependencies": { + "electron": ">= 13.0.0" + } + }, "node_modules/@electron/universal": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.4.1.tgz", @@ -13887,7 +13896,6 @@ "version": "4.6.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", - "dev": true, "engines": { "node": ">=10" }, @@ -14214,7 +14222,6 @@ "version": "4.0.6", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", - "dev": true, "dependencies": { "defer-to-connect": "^2.0.0" }, @@ -14480,7 +14487,6 @@ "version": "6.0.3", "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", - "dev": true, "dependencies": { "@types/http-cache-semantics": "*", "@types/keyv": "^3.1.4", @@ -14543,6 +14549,16 @@ "@types/ms": "*" } }, + "node_modules/@types/electron": { + "version": "1.6.10", + "resolved": "https://registry.npmjs.org/@types/electron/-/electron-1.6.10.tgz", + "integrity": "sha512-MOCVyzIwkBEloreoCVrTV108vSf8fFIJPsGruLCoAoBZdxtnJUqKA4lNonf/2u1twSjAspPEfmEheC+TLm/cMw==", + "deprecated": "This is a stub types definition for electron (https://github.com/electron/electron). electron provides its own type definitions, so you don't need @types/electron installed!", + "dev": true, + "dependencies": { + "electron": "*" + } + }, "node_modules/@types/eslint": { "version": "8.44.8", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.8.tgz", @@ -14632,8 +14648,7 @@ "node_modules/@types/http-cache-semantics": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", - "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", - "dev": true + "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==" }, "node_modules/@types/http-errors": { "version": "2.0.4", @@ -14739,7 +14754,6 @@ "version": "3.1.4", "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -14929,7 +14943,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -15120,7 +15133,6 @@ "version": "2.10.3", "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", - "dev": true, "optional": true, "dependencies": { "@types/node": "*" @@ -18182,7 +18194,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", - "dev": true + "devOptional": true }, "node_modules/bowser": { "version": "2.11.0", @@ -18300,7 +18312,6 @@ "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true, "engines": { "node": "*" } @@ -18461,7 +18472,6 @@ "version": "5.0.4", "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", - "dev": true, "engines": { "node": ">=10.6.0" } @@ -18470,7 +18480,6 @@ "version": "7.0.4", "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", - "dev": true, "dependencies": { "clone-response": "^1.0.2", "get-stream": "^5.1.0", @@ -18488,7 +18497,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, "dependencies": { "pump": "^3.0.0" }, @@ -19134,7 +19142,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", - "dev": true, "dependencies": { "mimic-response": "^1.0.0" }, @@ -20349,7 +20356,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "dev": true, "dependencies": { "mimic-response": "^3.1.0" }, @@ -20364,7 +20370,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "dev": true, "engines": { "node": ">=10" }, @@ -20467,7 +20472,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", - "dev": true, "engines": { "node": ">=10" } @@ -20593,7 +20597,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true + "devOptional": true }, "node_modules/dezalgo": { "version": "1.0.4", @@ -21019,7 +21023,6 @@ "version": "28.0.0", "resolved": "https://registry.npmjs.org/electron/-/electron-28.0.0.tgz", "integrity": "sha512-eDhnCFBvG0PGFVEpNIEdBvyuGUBsFdlokd+CtuCe2ER3P+17qxaRfWRxMmksCOKgDHb5Wif5UxqOkZSlA4snlw==", - "dev": true, "hasInstallScript": true, "dependencies": { "@electron/get": "^2.0.0", @@ -21337,7 +21340,6 @@ "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, "dependencies": { "once": "^1.4.0" } @@ -21470,7 +21472,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true, "engines": { "node": ">=6" } @@ -21749,7 +21750,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", - "dev": true + "devOptional": true }, "node_modules/esbuild": { "version": "0.14.54", @@ -23094,7 +23095,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dev": true, "dependencies": { "debug": "^4.1.1", "get-stream": "^5.1.0", @@ -23114,7 +23114,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, "dependencies": { "pump": "^3.0.0" }, @@ -23242,7 +23241,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "dev": true, "dependencies": { "pend": "~1.2.0" } @@ -23840,7 +23838,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", - "dev": true, + "devOptional": true, "dependencies": { "boolean": "^3.0.1", "es6-error": "^4.1.1", @@ -23857,7 +23855,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, + "devOptional": true, "dependencies": { "yallist": "^4.0.0" }, @@ -23869,7 +23867,7 @@ "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, + "devOptional": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -23892,7 +23890,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", - "dev": true, + "devOptional": true, "dependencies": { "define-properties": "^1.1.3" }, @@ -24003,7 +24001,6 @@ "version": "11.8.6", "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", - "dev": true, "dependencies": { "@sindresorhus/is": "^4.0.0", "@szmarczak/http-timer": "^4.0.5", @@ -24598,8 +24595,7 @@ "node_modules/http-cache-semantics": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", - "dev": true + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" }, "node_modules/http-call": { "version": "5.3.0", @@ -24714,7 +24710,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", - "dev": true, "dependencies": { "quick-lru": "^5.1.1", "resolve-alpn": "^1.0.0" @@ -24727,7 +24722,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true, "engines": { "node": ">=10" }, @@ -27378,7 +27372,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true + "devOptional": true }, "node_modules/json5": { "version": "2.2.3", @@ -28372,7 +28366,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true, "engines": { "node": ">=8" } @@ -28501,7 +28494,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", - "dev": true, + "devOptional": true, "dependencies": { "escape-string-regexp": "^4.0.0" }, @@ -29368,7 +29361,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true, "engines": { "node": ">=4" } @@ -30052,7 +30044,6 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "dev": true, "engines": { "node": ">=10" }, @@ -30548,7 +30539,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", - "dev": true, "engines": { "node": ">=8" } @@ -30894,8 +30884,7 @@ "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==" }, "node_modules/performance-now": { "version": "2.1.0", @@ -31318,7 +31307,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, "engines": { "node": ">=0.4.0" } @@ -31420,7 +31408,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -32443,8 +32430,7 @@ "node_modules/resolve-alpn": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", - "dev": true + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==" }, "node_modules/resolve-cwd": { "version": "3.0.0", @@ -32493,7 +32479,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", - "dev": true, "dependencies": { "lowercase-keys": "^2.0.0" }, @@ -32580,7 +32565,7 @@ "version": "2.15.4", "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", - "dev": true, + "devOptional": true, "dependencies": { "boolean": "^3.0.1", "detect-node": "^2.0.4", @@ -32597,7 +32582,7 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", - "dev": true + "devOptional": true }, "node_modules/robust-predicates": { "version": "3.0.2", @@ -32847,7 +32832,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", - "dev": true + "devOptional": true }, "node_modules/send": { "version": "0.18.0", @@ -32916,7 +32901,7 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", - "dev": true, + "devOptional": true, "dependencies": { "type-fest": "^0.13.1" }, @@ -32931,7 +32916,7 @@ "version": "0.13.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", - "dev": true, + "devOptional": true, "engines": { "node": ">=10" }, @@ -33819,7 +33804,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", - "dev": true, "dependencies": { "debug": "^4.1.0" }, @@ -36533,7 +36517,6 @@ "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", - "dev": true, "dependencies": { "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" diff --git a/package.json b/package.json index 9b0350bb..86e7773b 100644 --- a/package.json +++ b/package.json @@ -129,6 +129,7 @@ "@aws-amplify/core": "^5.8.4", "@babel/cli": "^7.23.4", "@babel/register": "^7.22.15", + "@electron/remote": "^2.1.2", "@graphql-tools/schema": "^9.0.19", "@mui/icons-material": "^5.15.7", "@mui/lab": "^5.0.0-alpha.93", @@ -216,6 +217,7 @@ "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^12.1.5", "@types/chai": "^4.3.11", + "@types/electron": "^1.6.10", "@types/jest": "^28.1.8", "@typescript-eslint/eslint-plugin": "^5.62.0", "@typescript-eslint/parser": "^5.62.0", diff --git a/vite.config.ts b/vite.config.ts index 08663882..0ff26af1 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -9,11 +9,15 @@ export default defineConfig({ build: { outDir: 'build' }, - assetsInclude: ['**/*.PNG'], + optimizeDeps: { + exclude: [ 'electron', 'fs' ] + }, + assetsInclude: ['**/*.png'], server: { port: 8080 }, plugins: [ react(), svgr({ + include: '**/*.svg', svgrOptions: { icon: true // ...svgr options (https://react-svgr.com/docs/options/)