This commit is contained in:
Daniel Eduardo Rios Quintero 2025-01-23 23:54:14 +09:00 committed by GitHub
commit 8074af8722
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 5158 additions and 10 deletions

View File

@ -5,6 +5,7 @@ on:
branches: [ "main" ] branches: [ "main" ]
pull_request: pull_request:
branches: [ "main" ] branches: [ "main" ]
workflow_dispatch:
jobs: jobs:
build: build:

1
.gitignore vendored
View File

@ -9,6 +9,7 @@ lerna-debug.log*
node_modules node_modules
dist dist
install
dist-ssr dist-ssr
*.local *.local

View File

@ -35,6 +35,13 @@ npm install
npm run dev npm run dev
``` ```
### Local Development Electron
Make sure you have the local environment (`Local Development`) enabled before running Electron:
```bash
npm run electron
```
### Build ### Build
```bash ```bash

44
main.cjs Normal file
View File

@ -0,0 +1,44 @@
const { app, BrowserWindow, Menu } = require('electron');
const path = require('path');
process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true';
function createWindow() {
const isDev = !app.isPackaged;
const win = new BrowserWindow({
width: 800,
height: 600,
icon: path.join(__dirname, 'public', 'icon.ico') ,
webPreferences: {
contextIsolation: true,
enableRemoteModule: false,
},
});
win.maximize();
if (isDev) {
win.loadURL('http://localhost:5173');
win.webContents.openDevTools();
} else {
win.loadURL(`file://${path.join(__dirname, 'dist/index.html')}`);
Menu.setApplicationMenu(null);
}
}
app.whenReady().then(() => {
createWindow();
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
});
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});

4992
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -3,9 +3,13 @@
"private": true, "private": true,
"version": "0.0.0", "version": "0.0.0",
"type": "module", "type": "module",
"main": "main.cjs",
"description": "Free, simple, and intuitive online database design tool and SQL generator.",
"author": "1ilit",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
"build": "vite build", "electron": "electron .",
"build": "vite build && electron-builder",
"lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0", "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview" "preview": "vite preview"
}, },
@ -22,6 +26,7 @@
"classnames": "^2.5.1", "classnames": "^2.5.1",
"dexie": "^3.2.4", "dexie": "^3.2.4",
"dexie-react-hooks": "^1.1.7", "dexie-react-hooks": "^1.1.7",
"electron-is": "^3.0.0",
"file-saver": "^2.0.5", "file-saver": "^2.0.5",
"framer-motion": "^10.18.0", "framer-motion": "^10.18.0",
"html-to-image": "^1.11.11", "html-to-image": "^1.11.11",
@ -46,6 +51,8 @@
"@types/react-dom": "^18.2.17", "@types/react-dom": "^18.2.17",
"@vitejs/plugin-react": "^4.2.1", "@vitejs/plugin-react": "^4.2.1",
"autoprefixer": "^10.4.16", "autoprefixer": "^10.4.16",
"electron": "^33.2.1",
"electron-builder": "^25.1.8",
"eslint": "^8.55.0", "eslint": "^8.55.0",
"eslint-config-prettier": "^9.1.0", "eslint-config-prettier": "^9.1.0",
"eslint-plugin-react": "^7.33.2", "eslint-plugin-react": "^7.33.2",
@ -56,6 +63,43 @@
"tailwindcss": "^3.3.6", "tailwindcss": "^3.3.6",
"vite": "^5.4.1" "vite": "^5.4.1"
}, },
"build": {
"appId": "com.drawDB.id",
"productName": "drawDB",
"directories": {
"output": "install",
"buildResources": "public"
},
"files": [
"dist/**/*",
"main.cjs",
"package.json",
"node_modules/**/*",
"public/icon.ico"
],
"win": {
"icon": "public/icon.ico",
"target": "nsis",
"signAndEditExecutable": false
},
"nsis": {
"oneClick": false,
"perMachine": true,
"allowToChangeInstallationDirectory": true,
"createDesktopShortcut": true,
"createStartMenuShortcut": true,
"shortcutName": "drawDB"
},
"mac": {
"icon": "public/icon.icns",
"target": "dmg"
},
"linux": {
"icon": "public/icon.png",
"target": "AppImage"
},
"publish": null
},
"overrides": { "overrides": {
"follow-redirects": "^1.15.4" "follow-redirects": "^1.15.4"
} }

BIN
public/icon.icns Normal file

Binary file not shown.

BIN
public/icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 KiB

BIN
public/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -1,4 +1,4 @@
import { BrowserRouter, Routes, Route, useLocation } from "react-router-dom"; import { BrowserRouter, HashRouter, Routes, Route, useLocation } from "react-router-dom";
import { useLayoutEffect } from "react"; import { useLayoutEffect } from "react";
import Editor from "./pages/Editor"; import Editor from "./pages/Editor";
import Survey from "./pages/Survey"; import Survey from "./pages/Survey";
@ -9,11 +9,14 @@ import LandingPage from "./pages/LandingPage";
import SettingsContextProvider from "./context/SettingsContext"; import SettingsContextProvider from "./context/SettingsContext";
import { useSettings } from "./hooks"; import { useSettings } from "./hooks";
import NotFound from "./pages/NotFound"; import NotFound from "./pages/NotFound";
import {isElectron} from "./utils/electronUtils"
const Router = isElectron() ? HashRouter : BrowserRouter;
export default function App() { export default function App() {
return ( return (
<SettingsContextProvider> <SettingsContextProvider>
<BrowserRouter> <Router>
<RestoreScroll /> <RestoreScroll />
<Routes> <Routes>
<Route path="/" element={<LandingPage />} /> <Route path="/" element={<LandingPage />} />
@ -52,7 +55,7 @@ export default function App() {
<Route path="/templates" element={<Templates />} /> <Route path="/templates" element={<Templates />} />
<Route path="*" element={<NotFound />} /> <Route path="*" element={<NotFound />} />
</Routes> </Routes>
</BrowserRouter> </Router>
</SettingsContextProvider> </SettingsContextProvider>
); );
} }

View File

@ -73,6 +73,7 @@ import { jsonToMermaid } from "../../utils/exportAs/mermaid";
import { isRtl } from "../../i18n/utils/rtl"; import { isRtl } from "../../i18n/utils/rtl";
import { jsonToDocumentation } from "../../utils/exportAs/documentation"; import { jsonToDocumentation } from "../../utils/exportAs/documentation";
import { IdContext } from "../Workspace"; import { IdContext } from "../Workspace";
import { isElectron } from "../../utils/electronUtils";
export default function ControlPanel({ export default function ControlPanel({
diagramId, diagramId,
@ -1342,21 +1343,40 @@ export default function ControlPanel({
}, },
help: { help: {
shortcuts: { shortcuts: {
function: () => window.open("/shortcuts", "_blank"), function: () => isElectron()
? (window.location.href = "#/shortcuts")
: window.open("/shortcuts", "_blank"),
shortcut: "Ctrl+H", shortcut: "Ctrl+H",
}, },
ask_on_discord: { ask_on_discord: {
function: () => window.open("https://discord.gg/BrjZgNrmR6", "_blank"), function: () => {
const discordAppUrl = "discord://invite/BrjZgNrmR6";
const fallbackUrl = "https://discord.gg/BrjZgNrmR6";
try {
if (isElectron()) {
window.electron(discordAppUrl);
} else {
window.open(fallbackUrl, "_blank");
}
} catch (error) {
window.open(fallbackUrl, "_blank");
}
},
}, },
report_bug: { report_bug: {
function: () => window.open("/bug-report", "_blank"), function: () => isElectron()
? (window.location.href = "#/bug-report")
: window.open("/bug-report", "_blank"),
}, },
feedback: { feedback: {
function: () => window.open("/survey", "_blank"), function: () => isElectron()
? (window.location.href = "#/survey")
: window.open("/survey", "_blank"),
}, },
}, },
}; };
useHotkeys("ctrl+i, meta+i", fileImport, { preventDefault: true }); useHotkeys("ctrl+i, meta+i", fileImport, { preventDefault: true });
useHotkeys("ctrl+z, meta+z", undo, { preventDefault: true }); useHotkeys("ctrl+z, meta+z", undo, { preventDefault: true });
useHotkeys("ctrl+y, meta+y", redo, { preventDefault: true }); useHotkeys("ctrl+y, meta+y", redo, { preventDefault: true });
@ -1396,7 +1416,7 @@ export default function ControlPanel({
style={isRtl(i18n.language) ? { direction: "rtl" } : {}} style={isRtl(i18n.language) ? { direction: "rtl" } : {}}
> >
{header()} {header()}
{window.name.split(" ")[0] !== "t" && ( {!isElectron() && window.name.split(" ")[0] !== "t" && (
<Button <Button
type="primary" type="primary"
className="text-base me-2 pe-6 ps-5 py-[18px] rounded-md" className="text-base me-2 pe-6 ps-5 py-[18px] rounded-md"

View File

@ -7,6 +7,7 @@ import { useLiveQuery } from "dexie-react-hooks";
import Thumbnail from "../components/Thumbnail"; import Thumbnail from "../components/Thumbnail";
import logo_light from "../assets/logo_light_160.png"; import logo_light from "../assets/logo_light_160.png";
import template_screenshot from "../assets/template_screenshot.png"; import template_screenshot from "../assets/template_screenshot.png";
import { isElectron } from "../utils/electronUtils";
export default function Templates() { export default function Templates() {
const defaultTemplates = useLiveQuery(() => const defaultTemplates = useLiveQuery(() =>
@ -22,13 +23,23 @@ export default function Templates() {
}; };
const editTemplate = (id) => { const editTemplate = (id) => {
if(isElectron()){
const newWindow = window.open("#/editor", "_blank");
newWindow.name = "t " + id;
}else{
const newWindow = window.open("/editor", "_blank"); const newWindow = window.open("/editor", "_blank");
newWindow.name = "t " + id; newWindow.name = "t " + id;
}
}; };
const forkTemplate = (id) => { const forkTemplate = (id) => {
if(isElectron()){
const newWindow = window.open("#/editor", "_blank");
newWindow.name = "lt " + id;
}else{
const newWindow = window.open("/editor", "_blank"); const newWindow = window.open("/editor", "_blank");
newWindow.name = "lt " + id; newWindow.name = "lt " + id;
}
}; };
useEffect(() => { useEffect(() => {

View File

@ -0,0 +1,20 @@
export function isElectron() {
if (
typeof window !== "undefined" &&
typeof window.process === "object" &&
window.process.type === "renderer"
) {
return true;
}
if (
typeof navigator === "object" &&
typeof navigator.userAgent === "string" &&
navigator.userAgent.indexOf("Electron") >= 0
) {
return true;
}
return false;
}

View File

@ -4,4 +4,9 @@ import react from '@vitejs/plugin-react'
// https://vitejs.dev/config/ // https://vitejs.dev/config/
export default defineConfig({ export default defineConfig({
plugins: [react()], plugins: [react()],
base: './',
build: {
outDir: 'dist',
emptyOutDir: true,
},
}) })