From c01ff989a28636e11a00facc975d7e3aa03ad342 Mon Sep 17 00:00:00 2001 From: Carlos Date: Sun, 18 May 2025 17:05:42 +0200 Subject: [PATCH] Switch to React Native macOS Replace Electron with React Native macOS for the macOS editor. * **GitHub Actions Workflow**: Update `.github/workflows/build.yml` to build the React Native macOS app instead of Electron. * **Build Script**: Modify `build.sh` to remove Electron-specific commands and add commands to build and run the React Native macOS app. * **Documentation**: Update `docs/dependencies/dependencies.en.md` and `docs/dependencies/dependencies.es.md` to replace Electron with React Native macOS. Update `docs/installation/installation.en.md` and `docs/installation/installation.es.md` to reflect the new installation and build process. Update `docs/project-overview/project-overview.en.md` and `docs/project-overview/project-overview.es.md` to remove references to Electron. Update `docs/splash/splash-screen.en.md` and `docs/splash/splash-screen.es.md` to reflect the new splash screen implementation. * **Package Configuration**: Modify `package.json` to remove Electron-related dependencies and scripts, and add React Native macOS dependencies and scripts. * **Main Application**: Update `src/main.tsx` to initialize the application using React Native macOS. * **Vite Configuration**: Update `vite.config.ts` to remove Electron-specific settings. * **Remove Electron Files**: Delete `electron/main.js`, `electron/preload.js`, and `electron/splash.html`. --- For more details, open the [Copilot Workspace session](https://copilot-workspace.githubnext.com/espora-net/baobab?shareId=XXXX-XXXX-XXXX-XXXX). --- .github/workflows/build.yml | 18 +- build.sh | 6 +- docs/dependencies/dependencies.en.md | 2 +- docs/dependencies/dependencies.es.md | 2 +- docs/installation/installation.en.md | 20 +- docs/installation/installation.es.md | 20 +- docs/project-overview/project-overview.en.md | 6 +- docs/project-overview/project-overview.es.md | 6 +- docs/splash/splash-screen.en.md | 97 +++---- docs/splash/splash-screen.es.md | 97 +++---- electron/main.js | 291 ------------------- electron/preload.js | 55 ---- electron/splash.html | 82 ------ package.json | 65 +---- src/main.tsx | 4 +- vite.config.ts | 3 +- 16 files changed, 113 insertions(+), 661 deletions(-) mode change 100755 => 100644 build.sh delete mode 100644 electron/main.js delete mode 100644 electron/preload.js delete mode 100644 electron/splash.html diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 54b2f21..f376636 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,4 +1,4 @@ -name: Build macOS Editor DMG +name: Build macOS Editor App on: push: @@ -28,10 +28,10 @@ jobs: cd macos-editor npm install - - name: Build DMG + - name: Build React Native macOS App run: | cd macos-editor - ./build.sh + npm run build - name: Debug build artifacts run: ls -la macos-editor/dist/ @@ -39,8 +39,8 @@ jobs: - name: Upload artifact uses: actions/upload-artifact@v2 with: - name: macos-editor-dmg - path: macos-editor/dist/*.dmg + name: macos-editor-app + path: macos-editor/dist/*.app release: runs-on: macos-latest @@ -56,13 +56,13 @@ jobs: run: | cd macos-editor npm install - - name: Build DMG + - name: Build React Native macOS App run: | cd macos-editor - ./build.sh - - name: Upload DMG to GitHub Release + npm run build + - name: Upload App to GitHub Release uses: softprops/action-gh-release@v1 with: - files: macos-editor/dist/*.dmg + files: macos-editor/dist/*.app env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/build.sh b/build.sh old mode 100755 new mode 100644 index 936fccc..6bd4434 --- a/build.sh +++ b/build.sh @@ -7,7 +7,7 @@ MODE=$1 if [ -z "$MODE" ] || [ "$MODE" == "dev" ]; then echo "Iniciando en modo de desarrollo..." - npm run electron:dev + npx react-native run-macos elif [ "$MODE" == "dmg" ]; then echo "Generando DMG para macOS..." @@ -20,7 +20,7 @@ elif [ "$MODE" == "dmg" ]; then fi # Generar el DMG - npm run build:dmg + npx react-native run-macos --configuration Release else echo "Error: La generación de DMG solo es posible en macOS." echo "Actualmente estás ejecutando en: $OSTYPE" @@ -29,7 +29,7 @@ elif [ "$MODE" == "dmg" ]; then fi elif [ "$MODE" == "preview" ]; then echo "Iniciando vista previa de la aplicación..." - npm run electron:preview + npx react-native run-macos --configuration Release else echo "Uso: $0 [dev|dmg|preview]" echo " dev : Inicia la aplicación en modo de desarrollo (por defecto)." diff --git a/docs/dependencies/dependencies.en.md b/docs/dependencies/dependencies.en.md index ab6c7ea..2790e1d 100644 --- a/docs/dependencies/dependencies.en.md +++ b/docs/dependencies/dependencies.en.md @@ -2,4 +2,4 @@ The macOS editor is built using the following dependencies: - [Tiptap](https://github.com/ueberdosis/tiptap) -- [Electron](https://www.electronjs.org/) +- [React Native macOS](https://github.com/microsoft/react-native-macos) diff --git a/docs/dependencies/dependencies.es.md b/docs/dependencies/dependencies.es.md index 4203952..76b0373 100644 --- a/docs/dependencies/dependencies.es.md +++ b/docs/dependencies/dependencies.es.md @@ -2,4 +2,4 @@ El editor de macOS está construido usando las siguientes dependencias: - [Tiptap](https://github.com/ueberdosis/tiptap) -- [Electron](https://www.electronjs.org/) +- [React Native macOS](https://github.com/microsoft/react-native-macos) diff --git a/docs/installation/installation.en.md b/docs/installation/installation.en.md index 2f75832..c534184 100644 --- a/docs/installation/installation.en.md +++ b/docs/installation/installation.en.md @@ -14,13 +14,9 @@ ```sh npm install ``` -3. Build the React bundle: +3. Start the React Native macOS app: ```sh - npx esbuild ./index.jsx --bundle --outfile=./bundle.js --format=iife - ``` -4. Start the Electron app: - ```sh - npm start + npx react-native run-macos ``` ## Build DMG for macOS @@ -29,16 +25,10 @@ ```sh npm install ``` -2. Build the React bundle: - ```sh - npx esbuild ./index.jsx --bundle --outfile=./bundle.js --format=iife - ``` -3. Build the DMG: +2. Build the React Native macOS app: ```sh - npm run build - npx electron-builder --mac + npx react-native run-macos --configuration Release ``` - The DMG file will be in the `dist/` folder. ## Automated Script @@ -46,7 +36,7 @@ You can use the script: - For local development: ```sh - ./build.sh local + ./build.sh dev ``` - To generate the DMG: ```sh diff --git a/docs/installation/installation.es.md b/docs/installation/installation.es.md index 30c70d2..0dc177f 100644 --- a/docs/installation/installation.es.md +++ b/docs/installation/installation.es.md @@ -14,13 +14,9 @@ ```sh npm install ``` -3. Genera el bundle de React: +3. Inicia la aplicación React Native macOS: ```sh - npx esbuild ./index.jsx --bundle --outfile=./bundle.js --format=iife - ``` -4. Inicia la aplicación Electron: - ```sh - npm start + npx react-native run-macos ``` ## Generar DMG para macOS @@ -29,16 +25,10 @@ ```sh npm install ``` -2. Genera el bundle de React: - ```sh - npx esbuild ./index.jsx --bundle --outfile=./bundle.js --format=iife - ``` -3. Construye el instalador DMG: +2. Construye la aplicación React Native macOS: ```sh - npm run build - npx electron-builder --mac + npx react-native run-macos --configuration Release ``` - El archivo DMG estará en la carpeta `dist/`. ## Script automatizado @@ -46,7 +36,7 @@ Puedes usar el script: - Para desarrollo local: ```sh - ./build.sh local + ./build.sh dev ``` - Para generar el DMG: ```sh diff --git a/docs/project-overview/project-overview.en.md b/docs/project-overview/project-overview.en.md index 134cc33..5a78a9c 100644 --- a/docs/project-overview/project-overview.en.md +++ b/docs/project-overview/project-overview.en.md @@ -5,10 +5,7 @@ This project is organized as follows: - **macos-editor/** - `index.html`: Main HTML file where the React app is mounted. - `index.jsx`: React entry point. Defines the editor and toolbar using Tiptap and React. - - `bundle.js`: Bundle generated from `index.jsx` using esbuild. Loaded by the browser/Electron. - - `main.js`: Main Electron script. Controls the main window, splash, and app menu. - - `renderer.js`: (Obsolete) Old editor logic, now replaced by React. - - `splash.html`: Splash screen shown at app startup. + - `bundle.js`: Bundle generated from `index.jsx` using esbuild. Loaded by the browser. - `build.sh`: Script to automate install, build, and DMG packaging. - `package.json`: Editor-specific dependencies and scripts. - **docs/**: Detailed documentation about installation, dependencies, build, workflows, etc. @@ -19,5 +16,4 @@ This project is organized as follows: - **index.html**: Defines the `
` container for React and loads the generated bundle. - **index.jsx**: Contains the main React component, Tiptap configuration, and toolbar. -- **main.js**: Initializes the Electron app, manages windows, splash, and menu. - **build.sh**: Automates install and build for both development and DMG generation. diff --git a/docs/project-overview/project-overview.es.md b/docs/project-overview/project-overview.es.md index 337229e..0770e74 100644 --- a/docs/project-overview/project-overview.es.md +++ b/docs/project-overview/project-overview.es.md @@ -5,10 +5,7 @@ Este proyecto está organizado de la siguiente manera: - **macos-editor/** - `index.html`: Archivo HTML principal donde se monta la app React. - `index.jsx`: Punto de entrada de React. Aquí se define el editor y la barra de herramientas usando Tiptap y React. - - `bundle.js`: Bundle generado a partir de `index.jsx` usando esbuild. Es el archivo que carga el navegador/Electron. - - `main.js`: Script principal de Electron. Controla la ventana principal, el splash y el menú de la app. - - `renderer.js`: (Obsoleto) Lógica antigua del editor, ahora reemplazada por React. - - `splash.html`: Pantalla de bienvenida (splash) mostrada al iniciar la app. + - `bundle.js`: Bundle generado a partir de `index.jsx` usando esbuild. Es el archivo que carga el navegador. - `build.sh`: Script para automatizar la instalación, build y empaquetado DMG. - `package.json`: Dependencias y scripts específicos del editor. - **docs/**: Documentación detallada sobre instalación, dependencias, build, workflows, etc. @@ -19,5 +16,4 @@ Este proyecto está organizado de la siguiente manera: - **index.html**: Define el contenedor `
` donde se monta la app React y carga el bundle generado. - **index.jsx**: Contiene el componente principal de React, la configuración de Tiptap y la barra de herramientas. -- **main.js**: Inicializa la app Electron, gestiona ventanas, splash y menú. - **build.sh**: Permite automatizar la instalación y build tanto para desarrollo como para generar el DMG. diff --git a/docs/splash/splash-screen.en.md b/docs/splash/splash-screen.en.md index 7447b12..547c72c 100644 --- a/docs/splash/splash-screen.en.md +++ b/docs/splash/splash-screen.en.md @@ -1,66 +1,45 @@ # Splash Screen Functionality -The `macos-editor/main.js` file includes functionality for displaying a splash screen when the macOS editor is launched. The splash screen is displayed for 3 seconds before the main window is shown. The relevant code is as follows: +The splash screen component is implemented using React in the `src/components/splash-screen/splash-screen.tsx` file. The splash screen is displayed for a minimum of 1.5 seconds before the main application is shown. The relevant code is as follows: -```javascript -const { app, BrowserWindow } = require('electron'); -const path = require('path'); +```typescript +import React, { useEffect, useState } from 'react'; +import './splash-screen.scss'; -function createSplashWindow() { - const splashWindow = new BrowserWindow({ - width: 400, - height: 300, - frame: false, - alwaysOnTop: true, - transparent: true, - webPreferences: { - nodeIntegration: true, - contextIsolation: false - } - }); - - splashWindow.loadFile('splash.html'); - return splashWindow; -} - -function createWindow () { - const mainWindow = new BrowserWindow({ - width: 800, - height: 600, - show: false, - webPreferences: { - preload: path.join(__dirname, 'preload.js'), - nodeIntegration: true, - contextIsolation: false - } - }); - - mainWindow.loadFile('index.html'); - - mainWindow.once('ready-to-show', () => { - setTimeout(() => { - splashWindow.close(); - mainWindow.show(); - }, 3000); // Show splash screen for 3 seconds - }); +interface SplashScreenProps { + onComplete: () => void; + minimumDisplayTime?: number; } -let splashWindow; - -app.on('ready', () => { - splashWindow = createSplashWindow(); - createWindow(); -}); - -app.on('window-all-closed', () => { - if (process.platform !== 'darwin') { - app.quit(); - } -}); - -app.on('activate', () => { - if (BrowserWindow.getAllWindows().length === 0) { - createWindow(); - } -}); +export const SplashScreen: React.FC = ({ + onComplete, + minimumDisplayTime = 1500 +}) => { + const [shouldHide, setShouldHide] = useState(false); + + useEffect(() => { + const timer = setTimeout(() => { + setShouldHide(true); + onComplete(); + }, minimumDisplayTime); + + return () => clearTimeout(timer); + }, [minimumDisplayTime, onComplete]); + + return ( +
+
+
+ Pora Logo +
+

Pora

+
+
+
+
+
+
+
+ ); +}; ``` diff --git a/docs/splash/splash-screen.es.md b/docs/splash/splash-screen.es.md index 67adaf4..53bbc20 100644 --- a/docs/splash/splash-screen.es.md +++ b/docs/splash/splash-screen.es.md @@ -1,66 +1,45 @@ # Funcionalidad de la pantalla de bienvenida (Splash) -El archivo `macos-editor/main.js` incluye la funcionalidad para mostrar una pantalla de bienvenida (splash) al iniciar el editor de macOS. La pantalla de bienvenida se muestra durante 3 segundos antes de mostrar la ventana principal. El código relevante es el siguiente: +El componente de la pantalla de bienvenida está implementado usando React en el archivo `src/components/splash-screen/splash-screen.tsx`. La pantalla de bienvenida se muestra durante un mínimo de 1.5 segundos antes de mostrar la aplicación principal. El código relevante es el siguiente: -```javascript -const { app, BrowserWindow } = require('electron'); -const path = require('path'); +```typescript +import React, { useEffect, useState } from 'react'; +import './splash-screen.scss'; -function createSplashWindow() { - const splashWindow = new BrowserWindow({ - width: 400, - height: 300, - frame: false, - alwaysOnTop: true, - transparent: true, - webPreferences: { - nodeIntegration: true, - contextIsolation: false - } - }); - - splashWindow.loadFile('splash.html'); - return splashWindow; -} - -function createWindow () { - const mainWindow = new BrowserWindow({ - width: 800, - height: 600, - show: false, - webPreferences: { - preload: path.join(__dirname, 'preload.js'), - nodeIntegration: true, - contextIsolation: false - } - }); - - mainWindow.loadFile('index.html'); - - mainWindow.once('ready-to-show', () => { - setTimeout(() => { - splashWindow.close(); - mainWindow.show(); - }, 3000); // Mostrar splash durante 3 segundos - }); +interface SplashScreenProps { + onComplete: () => void; + minimumDisplayTime?: number; } -let splashWindow; - -app.on('ready', () => { - splashWindow = createSplashWindow(); - createWindow(); -}); - -app.on('window-all-closed', () => { - if (process.platform !== 'darwin') { - app.quit(); - } -}); - -app.on('activate', () => { - if (BrowserWindow.getAllWindows().length === 0) { - createWindow(); - } -}); +export const SplashScreen: React.FC = ({ + onComplete, + minimumDisplayTime = 1500 +}) => { + const [shouldHide, setShouldHide] = useState(false); + + useEffect(() => { + const timer = setTimeout(() => { + setShouldHide(true); + onComplete(); + }, minimumDisplayTime); + + return () => clearTimeout(timer); + }, [minimumDisplayTime, onComplete]); + + return ( +
+
+
+ Pora Logo +
+

Pora

+
+
+
+
+
+
+
+ ); +}; ``` diff --git a/electron/main.js b/electron/main.js deleted file mode 100644 index 42d4d73..0000000 --- a/electron/main.js +++ /dev/null @@ -1,291 +0,0 @@ -import { app, BrowserWindow, Menu, dialog, shell, ipcMain } from 'electron'; -import path from 'path'; - -const isDev = process.env.NODE_ENV === 'development'; -const isMac = process.platform === 'darwin'; - -// Keep a global reference of the window object to avoid garbage collection -let mainWindow; -let splashWindow; - -// Set app name for macOS menu -app.name = 'Pora'; - -// Create a splash window -function createSplashWindow() { - splashWindow = new BrowserWindow({ - width: 400, - height: 300, - transparent: true, - frame: false, - resizable: false, - webPreferences: { - nodeIntegration: false, - contextIsolation: true - }, - alwaysOnTop: true, - show: false // Don't show window until it's ready - }); - - // Load a custom splash screen HTML in production - // Or just use the main app in development (since it has the splash screen component) - if (isDev) { - splashWindow.loadURL('http://localhost:5173'); - } else { - splashWindow.loadFile(path.join(__dirname, '../dist/splash.html')); - } - - splashWindow.once('ready-to-show', () => { - splashWindow.show(); - }); - - splashWindow.on('closed', () => { - splashWindow = null; - }); -} - -function createWindow() { - // Create the browser window - mainWindow = new BrowserWindow({ - width: 1200, - height: 800, - minWidth: 800, - minHeight: 600, - webPreferences: { - nodeIntegration: false, - contextIsolation: true, - preload: path.join(__dirname, 'preload.js') - }, - titleBarStyle: 'hiddenInset', // macOS-style title bar - backgroundColor: '#ffffff', - show: false, // Don't show window until splash is done - vibrancy: 'under-window', // macOS vibrancy effect - visualEffectState: 'active', - trafficLightPosition: { x: 14, y: 14 } - }); - - // Load the app - if (isDev) { - // In development, load from Vite dev server - mainWindow.loadURL('http://localhost:5173'); - // Open DevTools - mainWindow.webContents.openDevTools(); - } else { - // In production, load the built app - mainWindow.loadFile(path.join(__dirname, '../dist/index.html')); - } - - // Show window when ready to avoid flickering - mainWindow.once('ready-to-show', () => { - if (splashWindow) { - // Add a delay to show the splash screen for at least a minimal time - setTimeout(() => { - splashWindow.destroy(); - mainWindow.show(); - }, 1500); - } else { - mainWindow.show(); - } - }); - - // Set up the application menu (macOS style) - const menuTemplate = [ - // App menu (macOS only) - ...(isMac ? [{ - label: app.name, - submenu: [ - { role: 'about' }, - { type: 'separator' }, - { - label: 'Preferences...', - accelerator: 'CmdOrCtrl+,', - click: () => { - // Show preferences window when implemented - mainWindow.webContents.send('show-preferences'); - } - }, - { type: 'separator' }, - { role: 'services' }, - { type: 'separator' }, - { role: 'hide' }, - { role: 'hideOthers' }, - { role: 'unhide' }, - { type: 'separator' }, - { role: 'quit' } - ] - }] : []), - // File menu - { - label: 'File', - submenu: [ - { - label: 'New Document', - accelerator: 'CmdOrCtrl+N', - click: () => { - mainWindow.webContents.send('new-document'); - } - }, - { - label: 'Open...', - accelerator: 'CmdOrCtrl+O', - click: async () => { - const { canceled, filePaths } = await dialog.showOpenDialog(mainWindow, { - filters: [ - { name: 'Text Documents', extensions: ['txt', 'md', 'html'] }, - { name: 'All Files', extensions: ['*'] } - ], - properties: ['openFile'] - }); - if (!canceled && filePaths.length > 0) { - mainWindow.webContents.send('open-document', filePaths[0]); - } - } - }, - { - label: 'Save', - accelerator: 'CmdOrCtrl+S', - click: () => { - mainWindow.webContents.send('save-document'); - } - }, - { - label: 'Save As...', - accelerator: 'CmdOrCtrl+Shift+S', - click: async () => { - const { canceled, filePath } = await dialog.showSaveDialog(mainWindow, { - filters: [ - { name: 'Text Documents', extensions: ['txt', 'md', 'html'] }, - { name: 'All Files', extensions: ['*'] } - ] - }); - if (!canceled && filePath) { - mainWindow.webContents.send('save-document-as', filePath); - } - } - }, - { type: 'separator' }, - isMac ? { role: 'close' } : { role: 'quit' } - ] - }, - { - label: 'Edit', - submenu: [ - { role: 'undo' }, - { role: 'redo' }, - { type: 'separator' }, - { role: 'cut' }, - { role: 'copy' }, - { role: 'paste' }, - { role: 'delete' }, - { type: 'separator' }, - { role: 'selectAll' } - ] - }, - { - label: 'View', - submenu: [ - { role: 'reload' }, - { role: 'forceReload' }, - { type: 'separator' }, - { role: 'resetZoom' }, - { role: 'zoomIn' }, - { role: 'zoomOut' }, - { type: 'separator' }, - { role: 'togglefullscreen' } - ] - }, - { - label: 'Window', - submenu: [ - { role: 'minimize' }, - { role: 'zoom' }, - { type: 'separator' }, - { role: 'front' }, - { type: 'separator' }, - { role: 'close' } - ] - }, - { - label: 'Help', - submenu: [ - { - label: 'Learn More', - click: async () => { - await shell.openExternal('https://pora.app'); - } - }, - { - label: 'Documentation', - click: async () => { - await shell.openExternal('https://docs.pora.app'); - } - }, - { type: 'separator' }, - { - label: 'About Pora', - click: () => { - dialog.showMessageBox(mainWindow, { - title: 'About Pora', - message: 'Pora - Rich Text Editor', - detail: `Version: ${app.getVersion()}\nElectron: ${process.versions.electron}\nChrome: ${process.versions.chrome}\nNode.js: ${process.versions.node}\nV8: ${process.versions.v8}`, - buttons: ['OK'], - icon: path.join(__dirname, '../build/icons/icon.icns') - }); - } - } - ] - } - ]; - - const menu = Menu.buildFromTemplate(menuTemplate); - Menu.setApplicationMenu(menu); - - // Handle window close event - mainWindow.on('closed', () => { - mainWindow = null; - }); - - // Open links in default browser - mainWindow.webContents.setWindowOpenHandler(({ url }) => { - shell.openExternal(url); - return { action: 'deny' }; - }); -} - -// Create window when Electron is ready -app.whenReady().then(() => { - // Show splash screen first - createSplashWindow(); - - // Create main window after a short delay - setTimeout(() => { - createWindow(); - }, 500); - - // On macOS, it's common to re-create a window when dock icon is clicked - app.on('activate', () => { - if (BrowserWindow.getAllWindows().length === 0) { - createWindow(); - } - }); -}); - -// Quit when all windows are closed, except on macOS -app.on('window-all-closed', () => { - if (process.platform !== 'darwin') { - app.quit(); - } -}); - -// Document event handlers -ipcMain.on('check-for-changes', async (event) => { - const choice = await dialog.showMessageBox(mainWindow, { - type: 'question', - buttons: ['Save', "Don't Save", 'Cancel'], - defaultId: 0, - title: 'Unsaved Changes', - message: 'There are unsaved changes. Do you want to save them?' - }); - - event.reply('check-for-changes-response', choice.response); -}); diff --git a/electron/preload.js b/electron/preload.js deleted file mode 100644 index 63519f2..0000000 --- a/electron/preload.js +++ /dev/null @@ -1,55 +0,0 @@ -import { contextBridge, ipcRenderer } from 'electron'; - -// Expose any needed APIs to the renderer process -contextBridge.exposeInMainWorld('electron', { - // Document operations - documentOperations: { - // Signal to save the document - saveDocument: (callback) => { - ipcRenderer.on('save-document', callback); - }, - // Signal to save the document with a specific path - saveDocumentAs: (callback) => { - ipcRenderer.on('save-document-as', callback); - }, - // Signal to open a document - openDocument: (callback) => { - ipcRenderer.on('open-document', callback); - }, - // Signal to create a new document - newDocument: (callback) => { - ipcRenderer.on('new-document', callback); - }, - // Check if there are unsaved changes - checkForChanges: () => { - return new Promise((resolve) => { - ipcRenderer.once('check-for-changes-response', (_, response) => { - resolve(response); - }); - ipcRenderer.send('check-for-changes'); - }); - } - }, - - // App operations - appOperations: { - // Signal to show preferences - showPreferences: (callback) => { - ipcRenderer.on('show-preferences', callback); - }, - // Get app version - getVersion: () => process.versions.electron - }, - - // Remove listeners when they're no longer needed - removeAllListeners: (channel) => { - ipcRenderer.removeAllListeners(channel); - } -}); - -window.addEventListener('DOMContentLoaded', () => { - // Any initialization that needs to happen after DOM is loaded - console.log('DOM fully loaded and parsed - Pora is running with Electron ' + process.versions.electron); -}); - -export default contextBridge; diff --git a/electron/splash.html b/electron/splash.html deleted file mode 100644 index 058473c..0000000 --- a/electron/splash.html +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - Pora - - - -
- -

Pora

-
-
-
-
- - diff --git a/package.json b/package.json index 17126a7..e221b46 100644 --- a/package.json +++ b/package.json @@ -11,12 +11,11 @@ "build": "tsc && vite build", "preview": "vite preview", "lint": "eslint \"src/**/*.ts\"", - "electron:dev": "concurrently \"npm run dev\" \"wait-on http://localhost:5173 && NODE_ENV=development electron electron/main.js\"", - "electron:build": "npm run build && electron-builder", - "electron:preview": "npm run build && NODE_ENV=production electron electron/main.js", - "build:dmg": "npm run electron:build -- --mac dmg" + "macos:dev": "npx react-native run-macos", + "macos:build": "npx react-native run-macos --configuration Release", + "macos:preview": "npx react-native run-macos --configuration Release" }, - "main": "electron/main.cjs", + "main": "src/main.tsx", "dependencies": { "@floating-ui/react": "^0.27.8", "@tiptap/extension-highlight": "^2.11.9", @@ -33,7 +32,9 @@ "@tiptap/react": "^2.11.9", "@tiptap/starter-kit": "^2.11.9", "react": "^18.3.1", - "react-dom": "^18.3.1" + "react-dom": "^18.3.1", + "react-native": "^0.71.8", + "react-native-macos": "^0.71.8" }, "devDependencies": { "@types/react": "^19.1.2", @@ -42,63 +43,11 @@ "@typescript-eslint/parser": "^7.18.0", "@vitejs/plugin-react": "^4.4.1", "concurrently": "^9.1.2", - "electron": "^36.2.1", - "electron-builder": "^26.0.12", "eslint": "^8.57.1", "eslint-config-prettier": "^9.1.0", "sass-embedded": "^1.87.0", "typescript": "5.5.4", "vite": "^6.3.5", "wait-on": "^8.0.3" - }, - "build": { - "appId": "com.pora.app", - "productName": "Pora", - "mac": { - "category": "public.app-category.productivity", - "darkModeSupport": true, - "icon": "build/icons/icon.icns", - "target": ["dmg"], - "hardenedRuntime": true, - "gatekeeperAssess": false, - "entitlements": "build/entitlements.mac.plist", - "entitlementsInherit": "build/entitlements.mac.plist", - "artifactName": "Pora-${version}.${ext}" - }, - "dmg": { - "contents": [ - { - "x": 130, - "y": 220 - }, - { - "x": 410, - "y": 220, - "type": "link", - "path": "/Applications" - } - ], - "window": { - "width": 540, - "height": 380 - }, - "backgroundColor": "#f0f0f0", - "icon": "build/icons/icon.icns", - "title": "Pora ${version}" - }, - "files": [ - "dist/**/*", - "electron/**/*" - ], - "directories": { - "buildResources": "build", - "output": "release" - }, - "protocols": [ - { - "name": "Pora URL", - "schemes": ["pora"] - } - ] } } diff --git a/src/main.tsx b/src/main.tsx index 709f857..de76f80 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -2,6 +2,8 @@ import { createRoot } from "react-dom/client" import { useState, useEffect } from "react" import { SimpleEditor } from "@/components/tiptap-templates/simple/simple-editor" import { SplashScreen } from "@/components/splash-screen/splash-screen" +import { AppRegistry } from 'react-native'; +import { name as appName } from './app.json'; const App = () => { const [showSplashScreen, setShowSplashScreen] = useState(true); @@ -29,4 +31,4 @@ const App = () => { ); }; -createRoot(document.getElementById("app")!).render() +AppRegistry.registerComponent(appName, () => App); diff --git a/vite.config.ts b/vite.config.ts index 8889368..97b4454 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -29,7 +29,7 @@ export default defineConfig({ } } ], - base: './', // Relative paths for electron compatibility + base: './', // Relative paths for compatibility resolve: { alias: { "@": path.resolve(__dirname, "./src"), @@ -43,7 +43,6 @@ export default defineConfig({ }, }, }, - // Electron specific settings build: { outDir: 'dist', assetsDir: 'assets',