@directivegames/genesys.sdk 3.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +60 -0
- package/dist/src/asset-pack/eslint.config.js +43 -0
- package/dist/src/asset-pack/scripts/postinstall.js +64 -0
- package/dist/src/asset-pack/src/index.js +1 -0
- package/dist/src/core/cli.js +306 -0
- package/dist/src/core/common.js +324 -0
- package/dist/src/core/index.js +6 -0
- package/dist/src/core/tools/build-project.js +450 -0
- package/dist/src/core/tools/index.js +2 -0
- package/dist/src/core/tools/new-asset-pack.js +150 -0
- package/dist/src/core/tools/new-project.js +292 -0
- package/dist/src/core/types.js +1 -0
- package/dist/src/dependencies.js +82 -0
- package/dist/src/electron/IpcSerializableError.js +38 -0
- package/dist/src/electron/api.js +7 -0
- package/dist/src/electron/backend/actions.js +56 -0
- package/dist/src/electron/backend/handler.js +441 -0
- package/dist/src/electron/backend/logging.js +41 -0
- package/dist/src/electron/backend/main.js +315 -0
- package/dist/src/electron/backend/menu.js +208 -0
- package/dist/src/electron/backend/state.js +201 -0
- package/dist/src/electron/backend/tools/const.js +9 -0
- package/dist/src/electron/backend/tools/file-server.js +383 -0
- package/dist/src/electron/backend/tools/open-project.js +261 -0
- package/dist/src/electron/backend/window.js +161 -0
- package/dist/src/templates/eslint.config.js +43 -0
- package/dist/src/templates/scripts/genesys/build-project.js +42 -0
- package/dist/src/templates/scripts/genesys/calc-bounding-box.js +205 -0
- package/dist/src/templates/scripts/genesys/common.js +36 -0
- package/dist/src/templates/scripts/genesys/const.js +9 -0
- package/dist/src/templates/scripts/genesys/dev/dump-default-scene.js +8 -0
- package/dist/src/templates/scripts/genesys/dev/generate-manifest.js +116 -0
- package/dist/src/templates/scripts/genesys/dev/launcher.js +39 -0
- package/dist/src/templates/scripts/genesys/dev/storage-provider.js +188 -0
- package/dist/src/templates/scripts/genesys/dev/update-template-scenes.js +67 -0
- package/dist/src/templates/scripts/genesys/doc-server.js +12 -0
- package/dist/src/templates/scripts/genesys/genesys-mcp.js +413 -0
- package/dist/src/templates/scripts/genesys/mcp/doc-tools.js +70 -0
- package/dist/src/templates/scripts/genesys/mcp/editor-functions.js +123 -0
- package/dist/src/templates/scripts/genesys/mcp/editor-tools.js +51 -0
- package/dist/src/templates/scripts/genesys/mcp/get-scene-state.js +26 -0
- package/dist/src/templates/scripts/genesys/mcp/run-subprocess.js +23 -0
- package/dist/src/templates/scripts/genesys/mcp/search-actors.js +703 -0
- package/dist/src/templates/scripts/genesys/mcp/search-assets.js +296 -0
- package/dist/src/templates/scripts/genesys/mcp/utils.js +234 -0
- package/dist/src/templates/scripts/genesys/misc.js +32 -0
- package/dist/src/templates/scripts/genesys/mock.js +5 -0
- package/dist/src/templates/scripts/genesys/place-actors.js +112 -0
- package/dist/src/templates/scripts/genesys/post-install.js +25 -0
- package/dist/src/templates/scripts/genesys/remove-engine-comments.js +113 -0
- package/dist/src/templates/scripts/genesys/storageProvider.js +146 -0
- package/dist/src/templates/scripts/genesys/validate-prefabs.js +115 -0
- package/dist/src/templates/src/index.js +20 -0
- package/dist/src/templates/src/templates/firstPerson/src/auto-imports.js +1 -0
- package/dist/src/templates/src/templates/firstPerson/src/game.js +30 -0
- package/dist/src/templates/src/templates/firstPerson/src/player.js +60 -0
- package/dist/src/templates/src/templates/fps/src/auto-imports.js +1 -0
- package/dist/src/templates/src/templates/fps/src/game.js +30 -0
- package/dist/src/templates/src/templates/fps/src/player.js +64 -0
- package/dist/src/templates/src/templates/fps/src/weapon.js +62 -0
- package/dist/src/templates/src/templates/freeCamera/src/auto-imports.js +1 -0
- package/dist/src/templates/src/templates/freeCamera/src/game.js +30 -0
- package/dist/src/templates/src/templates/freeCamera/src/player.js +43 -0
- package/dist/src/templates/src/templates/sideScroller/src/auto-imports.js +1 -0
- package/dist/src/templates/src/templates/sideScroller/src/const.js +43 -0
- package/dist/src/templates/src/templates/sideScroller/src/game.js +103 -0
- package/dist/src/templates/src/templates/sideScroller/src/level-generator.js +249 -0
- package/dist/src/templates/src/templates/sideScroller/src/player.js +105 -0
- package/dist/src/templates/src/templates/thirdPerson/src/auto-imports.js +1 -0
- package/dist/src/templates/src/templates/thirdPerson/src/game.js +30 -0
- package/dist/src/templates/src/templates/thirdPerson/src/player.js +63 -0
- package/dist/src/templates/src/templates/vehicle/src/auto-imports.js +1 -0
- package/dist/src/templates/src/templates/vehicle/src/base-vehicle.js +122 -0
- package/dist/src/templates/src/templates/vehicle/src/game.js +33 -0
- package/dist/src/templates/src/templates/vehicle/src/mesh-vehicle.js +189 -0
- package/dist/src/templates/src/templates/vehicle/src/player.js +102 -0
- package/dist/src/templates/src/templates/vehicle/src/primitive-vehicle.js +259 -0
- package/dist/src/templates/src/templates/vehicle/src/ui-hints.js +100 -0
- package/dist/src/templates/src/templates/vr-game/src/auto-imports.js +1 -0
- package/dist/src/templates/src/templates/vr-game/src/game.js +55 -0
- package/dist/src/templates/src/templates/vr-game/src/sample-vr-actor.js +29 -0
- package/dist/src/templates/vite.config.js +46 -0
- package/package.json +176 -0
- package/scripts/post-install.ts +143 -0
- package/src/asset-pack/.gitattributes +89 -0
- package/src/asset-pack/eslint.config.js +45 -0
- package/src/asset-pack/gitignore +11 -0
- package/src/asset-pack/scripts/postinstall.ts +81 -0
- package/src/asset-pack/src/index.ts +0 -0
- package/src/asset-pack/tsconfig.json +34 -0
- package/src/templates/.cursor/mcp.json +20 -0
- package/src/templates/.cursorignore +2 -0
- package/src/templates/.gitattributes +89 -0
- package/src/templates/.vscode/settings.json +6 -0
- package/src/templates/AGENTS.md +86 -0
- package/src/templates/CLAUDE.md +1 -0
- package/src/templates/README.md +24 -0
- package/src/templates/eslint.config.js +45 -0
- package/src/templates/gitignore +11 -0
- package/src/templates/index.html +34 -0
- package/src/templates/pnpm-lock.yaml +3676 -0
- package/src/templates/scripts/genesys/build-project.ts +51 -0
- package/src/templates/scripts/genesys/calc-bounding-box.ts +272 -0
- package/src/templates/scripts/genesys/common.ts +46 -0
- package/src/templates/scripts/genesys/const.ts +9 -0
- package/src/templates/scripts/genesys/dev/dump-default-scene.ts +11 -0
- package/src/templates/scripts/genesys/dev/generate-manifest.ts +146 -0
- package/src/templates/scripts/genesys/dev/launcher.ts +46 -0
- package/src/templates/scripts/genesys/dev/storage-provider.ts +229 -0
- package/src/templates/scripts/genesys/dev/update-template-scenes.ts +84 -0
- package/src/templates/scripts/genesys/doc-server.ts +16 -0
- package/src/templates/scripts/genesys/genesys-mcp.ts +526 -0
- package/src/templates/scripts/genesys/mcp/doc-tools.ts +86 -0
- package/src/templates/scripts/genesys/mcp/editor-functions.ts +151 -0
- package/src/templates/scripts/genesys/mcp/editor-tools.ts +73 -0
- package/src/templates/scripts/genesys/mcp/get-scene-state.ts +35 -0
- package/src/templates/scripts/genesys/mcp/run-subprocess.ts +30 -0
- package/src/templates/scripts/genesys/mcp/search-actors.ts +858 -0
- package/src/templates/scripts/genesys/mcp/search-assets.ts +380 -0
- package/src/templates/scripts/genesys/mcp/utils.ts +281 -0
- package/src/templates/scripts/genesys/misc.ts +42 -0
- package/src/templates/scripts/genesys/mock.ts +6 -0
- package/src/templates/scripts/genesys/place-actors.ts +179 -0
- package/src/templates/scripts/genesys/post-install.ts +30 -0
- package/src/templates/scripts/genesys/prefab.schema.json +85 -0
- package/src/templates/scripts/genesys/remove-engine-comments.ts +135 -0
- package/src/templates/scripts/genesys/run-mcp-inspector.bat +5 -0
- package/src/templates/scripts/genesys/storageProvider.ts +182 -0
- package/src/templates/scripts/genesys/validate-prefabs.ts +138 -0
- package/src/templates/src/index.ts +22 -0
- package/src/templates/src/templates/firstPerson/assets/default.genesys-scene +166 -0
- package/src/templates/src/templates/firstPerson/src/auto-imports.ts +0 -0
- package/src/templates/src/templates/firstPerson/src/game.ts +39 -0
- package/src/templates/src/templates/firstPerson/src/player.ts +63 -0
- package/src/templates/src/templates/fps/assets/default.genesys-scene +9460 -0
- package/src/templates/src/templates/fps/assets/models/SM_Beam_400.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_ChamferCube.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_Floor_Thick_400x400.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_Floor_Thick_400x400_Orange.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_Floor_Thin_400x400.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_Floor_Thin_400x400_Orange.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_Ramp_400x400.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_Rifle.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_Wall_Thin_400x200.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_Wall_Thin_400x200_Orange.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_Wall_Thin_400x400.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_Wall_Thin_400x400_Orange.glb +0 -0
- package/src/templates/src/templates/fps/src/auto-imports.ts +0 -0
- package/src/templates/src/templates/fps/src/game.ts +39 -0
- package/src/templates/src/templates/fps/src/player.ts +69 -0
- package/src/templates/src/templates/fps/src/weapon.ts +54 -0
- package/src/templates/src/templates/freeCamera/assets/default.genesys-scene +166 -0
- package/src/templates/src/templates/freeCamera/src/auto-imports.ts +0 -0
- package/src/templates/src/templates/freeCamera/src/game.ts +39 -0
- package/src/templates/src/templates/freeCamera/src/player.ts +45 -0
- package/src/templates/src/templates/sideScroller/assets/default.genesys-scene +122 -0
- package/src/templates/src/templates/sideScroller/src/auto-imports.ts +0 -0
- package/src/templates/src/templates/sideScroller/src/const.ts +46 -0
- package/src/templates/src/templates/sideScroller/src/game.ts +122 -0
- package/src/templates/src/templates/sideScroller/src/level-generator.ts +361 -0
- package/src/templates/src/templates/sideScroller/src/player.ts +125 -0
- package/src/templates/src/templates/thirdPerson/assets/default.genesys-scene +166 -0
- package/src/templates/src/templates/thirdPerson/src/auto-imports.ts +0 -0
- package/src/templates/src/templates/thirdPerson/src/game.ts +39 -0
- package/src/templates/src/templates/thirdPerson/src/player.ts +61 -0
- package/src/templates/src/templates/vehicle/assets/default.genesys-scene +226 -0
- package/src/templates/src/templates/vehicle/assets/models/cyberTruck/chassis.glb +0 -0
- package/src/templates/src/templates/vehicle/assets/models/cyberTruck/wheel.glb +0 -0
- package/src/templates/src/templates/vehicle/src/auto-imports.ts +0 -0
- package/src/templates/src/templates/vehicle/src/base-vehicle.ts +145 -0
- package/src/templates/src/templates/vehicle/src/game.ts +43 -0
- package/src/templates/src/templates/vehicle/src/mesh-vehicle.ts +191 -0
- package/src/templates/src/templates/vehicle/src/player.ts +109 -0
- package/src/templates/src/templates/vehicle/src/primitive-vehicle.ts +266 -0
- package/src/templates/src/templates/vehicle/src/ui-hints.ts +101 -0
- package/src/templates/src/templates/vr-game/assets/default.genesys-scene +247 -0
- package/src/templates/src/templates/vr-game/src/auto-imports.ts +1 -0
- package/src/templates/src/templates/vr-game/src/game.ts +66 -0
- package/src/templates/src/templates/vr-game/src/sample-vr-actor.ts +26 -0
- package/src/templates/tsconfig.json +35 -0
- package/src/templates/vite.config.ts +52 -0
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { fileURLToPath } from 'url';
|
|
3
|
+
import { app, dialog, Menu } from 'electron';
|
|
4
|
+
import { BrowserWindow } from 'electron';
|
|
5
|
+
import { installExtension, MOBX_DEVTOOLS, REACT_DEVELOPER_TOOLS } from 'electron-devtools-installer';
|
|
6
|
+
import isDev from 'electron-is-dev';
|
|
7
|
+
import log from 'electron-log';
|
|
8
|
+
import electronUpdater from 'electron-updater';
|
|
9
|
+
import { getAppInfo } from './handler.js';
|
|
10
|
+
import { configureLogging, logger } from './logging.js';
|
|
11
|
+
import { buildAppMenu } from './menu.js';
|
|
12
|
+
import { GENESYS_LOCAL_URL, GENESYS_URL } from './tools/const.js';
|
|
13
|
+
import { createWindow, parseFeatures } from './window.js';
|
|
14
|
+
const { autoUpdater } = electronUpdater;
|
|
15
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
16
|
+
const __dirname = path.dirname(__filename);
|
|
17
|
+
export let mainWindow = null;
|
|
18
|
+
// Deep link URL storage
|
|
19
|
+
let pendingDeepLinkUrl = null;
|
|
20
|
+
export function getPendingDeepLinkUrl() {
|
|
21
|
+
return pendingDeepLinkUrl;
|
|
22
|
+
}
|
|
23
|
+
export function clearPendingDeepLinkUrl() {
|
|
24
|
+
pendingDeepLinkUrl = null;
|
|
25
|
+
}
|
|
26
|
+
configureLogging();
|
|
27
|
+
start();
|
|
28
|
+
function start() {
|
|
29
|
+
// Register deep link protocols
|
|
30
|
+
registerDeepLinkProtocols();
|
|
31
|
+
const hasLock = app.requestSingleInstanceLock();
|
|
32
|
+
app.on('second-instance', (event, argv, workingDirectory, additionalData) => {
|
|
33
|
+
logger.log('🔗 [deep-link] Second instance detected, checking for deep link URL');
|
|
34
|
+
// Handle deep link from second instance
|
|
35
|
+
const deepLinkUrl = getDeepLinkFromArgs(argv);
|
|
36
|
+
if (deepLinkUrl) {
|
|
37
|
+
logger.log('🔗 [deep-link] Processing URL from second instance:', deepLinkUrl);
|
|
38
|
+
handleDeepLink(deepLinkUrl);
|
|
39
|
+
}
|
|
40
|
+
if (mainWindow) {
|
|
41
|
+
mainWindow.isMinimized() && mainWindow.restore();
|
|
42
|
+
mainWindow.focus();
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
if (!hasLock) {
|
|
46
|
+
return app.quit();
|
|
47
|
+
}
|
|
48
|
+
// Handle deep link from first instance
|
|
49
|
+
const deepLinkUrl = getDeepLinkFromArgs(process.argv);
|
|
50
|
+
if (deepLinkUrl) {
|
|
51
|
+
logger.log('🔗 [deep-link] Processing URL from first instance:', deepLinkUrl);
|
|
52
|
+
pendingDeepLinkUrl = deepLinkUrl;
|
|
53
|
+
}
|
|
54
|
+
// Get custom URL from command line arguments (--url=https://example.com)
|
|
55
|
+
const customUrl = app.commandLine.hasSwitch('url') ? app.commandLine.getSwitchValue('url') : undefined;
|
|
56
|
+
if (customUrl) {
|
|
57
|
+
logger.log('Custom URL provided:', customUrl);
|
|
58
|
+
}
|
|
59
|
+
logger.log('===============================================');
|
|
60
|
+
logger.log(`\n${JSON.stringify(getAppInfo(), null, 2)}`);
|
|
61
|
+
logger.log('===============================================');
|
|
62
|
+
// Handle macOS deep links
|
|
63
|
+
app.on('open-url', (event, url) => {
|
|
64
|
+
event.preventDefault();
|
|
65
|
+
logger.log('🔗 [deep-link] macOS open-url event:', url);
|
|
66
|
+
handleDeepLink(url);
|
|
67
|
+
});
|
|
68
|
+
app.whenReady().then(async () => {
|
|
69
|
+
await initMainWindow();
|
|
70
|
+
Menu.setApplicationMenu(buildAppMenu(mainWindow));
|
|
71
|
+
checkForUpdates();
|
|
72
|
+
// Process pending deep link after window is ready
|
|
73
|
+
if (pendingDeepLinkUrl) {
|
|
74
|
+
logger.log('🔗 [deep-link] Processing pending deep link URL:', pendingDeepLinkUrl);
|
|
75
|
+
handleDeepLink(pendingDeepLinkUrl);
|
|
76
|
+
pendingDeepLinkUrl = null;
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
app.on('window-all-closed', () => {
|
|
80
|
+
if (process.platform !== 'darwin')
|
|
81
|
+
app.quit();
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
/** Register deep link protocols based on environment */
|
|
85
|
+
function registerDeepLinkProtocols() {
|
|
86
|
+
const protocol = isDev ? 'genesys-dev' : 'genesys';
|
|
87
|
+
let success = false;
|
|
88
|
+
if (process.defaultApp) {
|
|
89
|
+
// Development mode - need to specify execPath and argv
|
|
90
|
+
if (process.argv.length >= 2) {
|
|
91
|
+
success = app.setAsDefaultProtocolClient(protocol, process.execPath, [path.resolve(process.argv[1])]);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
// Production mode - simple registration
|
|
96
|
+
success = app.setAsDefaultProtocolClient(protocol);
|
|
97
|
+
}
|
|
98
|
+
if (success) {
|
|
99
|
+
logger.log(`🔗 [deep-link] Successfully registered protocol: ${protocol}://`);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
logger.warn(`⚠️ [deep-link] Failed to register protocol: ${protocol}://`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/** Extract deep link URL from command line arguments */
|
|
106
|
+
function getDeepLinkFromArgs(argv) {
|
|
107
|
+
const protocol = isDev ? 'genesys-dev://' : 'genesys://';
|
|
108
|
+
for (const arg of argv) {
|
|
109
|
+
if (arg.startsWith(protocol)) {
|
|
110
|
+
return arg;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
/** Handle deep link URL */
|
|
116
|
+
function handleDeepLink(url) {
|
|
117
|
+
logger.log('🔗 [deep-link] Handling deep link:', url);
|
|
118
|
+
try {
|
|
119
|
+
const parsedUrl = new URL(url);
|
|
120
|
+
logger.log('🔗 [deep-link] Parsed URL:', parsedUrl.toString());
|
|
121
|
+
// Send deep link to renderer process if window is ready
|
|
122
|
+
if (mainWindow && !mainWindow.isDestroyed()) {
|
|
123
|
+
mainWindow.webContents.send('deep-link', parsedUrl.toString());
|
|
124
|
+
logger.log('🔗 [deep-link] Deep link sent to renderer process');
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
// Store for later if window isn't ready
|
|
128
|
+
pendingDeepLinkUrl = url;
|
|
129
|
+
logger.log('🔗 [deep-link] Window not ready, storing deep link for later');
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
logger.error('❌ [deep-link] Failed to parse deep link URL:', error);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
const windowOptions = {
|
|
137
|
+
backgroundColor: '#13171b',
|
|
138
|
+
hasShadow: true,
|
|
139
|
+
titleBarStyle: 'hidden',
|
|
140
|
+
titleBarOverlay: false,
|
|
141
|
+
minWidth: 1024,
|
|
142
|
+
minHeight: 720,
|
|
143
|
+
};
|
|
144
|
+
async function showLocalDevError() {
|
|
145
|
+
const result = await dialog.showMessageBox(mainWindow, {
|
|
146
|
+
type: 'error',
|
|
147
|
+
buttons: ['Refresh (Ctrl+Shift+R)', 'OK'],
|
|
148
|
+
title: 'Local Development Server Not Running',
|
|
149
|
+
message: 'Failed to connect to local development server',
|
|
150
|
+
detail: 'Run "pnpm dev" on the .ai project and then refresh this page'
|
|
151
|
+
});
|
|
152
|
+
if (result.response === 0) {
|
|
153
|
+
// Refresh the page
|
|
154
|
+
try {
|
|
155
|
+
await mainWindow.loadURL(GENESYS_LOCAL_URL);
|
|
156
|
+
logger.log('Genesys.ai localhost');
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
logger.error('Failed to load local URL:', error);
|
|
160
|
+
await showLocalDevError();
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
async function showUrlLoadError(message) {
|
|
165
|
+
await dialog.showMessageBox(mainWindow, {
|
|
166
|
+
type: 'error',
|
|
167
|
+
buttons: ['OK'],
|
|
168
|
+
title: 'Connection Error',
|
|
169
|
+
message,
|
|
170
|
+
detail: 'Please check your internet connection and try again'
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
async function initMainWindow() {
|
|
174
|
+
// Create main window with title bar overlay
|
|
175
|
+
mainWindow = createWindow('main', {
|
|
176
|
+
show: false,
|
|
177
|
+
title: 'Genesys',
|
|
178
|
+
...windowOptions,
|
|
179
|
+
webPreferences: {
|
|
180
|
+
sandbox: true,
|
|
181
|
+
contextIsolation: true,
|
|
182
|
+
preload: path.join(__dirname, '../../../preload/electron/preload.js'),
|
|
183
|
+
nodeIntegration: false,
|
|
184
|
+
},
|
|
185
|
+
});
|
|
186
|
+
mainWindow.webContents.on('did-finish-load', async () => {
|
|
187
|
+
logger.log('🌐 Website loaded successfully...');
|
|
188
|
+
if (isDev && !extensionsLoaded) {
|
|
189
|
+
await loadDevExtensions();
|
|
190
|
+
}
|
|
191
|
+
mainWindow.show();
|
|
192
|
+
});
|
|
193
|
+
// Options for new windows
|
|
194
|
+
mainWindow.webContents.setWindowOpenHandler(({ url, frameName, features }) => {
|
|
195
|
+
const parsedFeatures = parseFeatures(features);
|
|
196
|
+
logger.log('Open window', url, features, parsedFeatures);
|
|
197
|
+
return {
|
|
198
|
+
action: 'allow',
|
|
199
|
+
createWindow: (options) => {
|
|
200
|
+
const newWindow = new BrowserWindow(options);
|
|
201
|
+
newWindow.setMenu(null); // Remove menu bar
|
|
202
|
+
return newWindow.webContents;
|
|
203
|
+
},
|
|
204
|
+
overrideBrowserWindowOptions: {
|
|
205
|
+
...windowOptions,
|
|
206
|
+
titleBarOverlay: (process.platform === 'darwin') ? false : {
|
|
207
|
+
color: '#13171b',
|
|
208
|
+
symbolColor: '#FFFFFF',
|
|
209
|
+
height: 44,
|
|
210
|
+
},
|
|
211
|
+
minWidth: 800,
|
|
212
|
+
minHeight: 600,
|
|
213
|
+
width: parsedFeatures.width,
|
|
214
|
+
height: parsedFeatures.height,
|
|
215
|
+
fullscreen: parsedFeatures.fullscreen,
|
|
216
|
+
title: parsedFeatures.title,
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
});
|
|
220
|
+
// Get custom URL from command line arguments
|
|
221
|
+
const customUrl = process.argv.find(arg => arg.startsWith('--url='))?.split('=')[1];
|
|
222
|
+
if (customUrl) {
|
|
223
|
+
try {
|
|
224
|
+
await mainWindow.loadURL(customUrl);
|
|
225
|
+
logger.log('Loading custom URL:', customUrl);
|
|
226
|
+
}
|
|
227
|
+
catch (error) {
|
|
228
|
+
logger.error('Failed to load custom URL:', error);
|
|
229
|
+
await showUrlLoadError('Failed to load custom URL');
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
else if (isDev) {
|
|
233
|
+
if (process.env.DEV_HOSTED) {
|
|
234
|
+
try {
|
|
235
|
+
await mainWindow.loadURL(GENESYS_URL);
|
|
236
|
+
logger.log('Genesys.ai hosted');
|
|
237
|
+
}
|
|
238
|
+
catch (error) {
|
|
239
|
+
logger.error('Failed to load hosted URL:', error);
|
|
240
|
+
await showUrlLoadError('Failed to load hosted Genesys.ai');
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
try {
|
|
245
|
+
await mainWindow.loadURL(GENESYS_LOCAL_URL);
|
|
246
|
+
logger.log('Genesys.ai localhost');
|
|
247
|
+
}
|
|
248
|
+
catch (error) {
|
|
249
|
+
logger.error('Failed to load local URL:', error);
|
|
250
|
+
await showLocalDevError();
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
mainWindow.webContents.openDevTools();
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
try {
|
|
257
|
+
await mainWindow.loadURL(GENESYS_URL);
|
|
258
|
+
}
|
|
259
|
+
catch (error) {
|
|
260
|
+
logger.error('Failed to load production URL:', error);
|
|
261
|
+
await showUrlLoadError('Failed to load Genesys.ai');
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
;
|
|
266
|
+
function checkForUpdates() {
|
|
267
|
+
autoUpdater.logger = log;
|
|
268
|
+
autoUpdater.checkForUpdatesAndNotify();
|
|
269
|
+
autoUpdater.on('update-available', () => {
|
|
270
|
+
logger.log('App update available');
|
|
271
|
+
mainWindow?.webContents.send('update_available');
|
|
272
|
+
});
|
|
273
|
+
autoUpdater.on('update-downloaded', () => {
|
|
274
|
+
logger.log('App update downloaded');
|
|
275
|
+
dialog.showMessageBox(mainWindow, {
|
|
276
|
+
type: 'info',
|
|
277
|
+
buttons: ['Restart', 'Later'],
|
|
278
|
+
title: 'SDK App Update Ready',
|
|
279
|
+
message: 'A new app version has been downloaded. Restart now to complete the update?',
|
|
280
|
+
}).then(({ response }) => {
|
|
281
|
+
if (response === 0)
|
|
282
|
+
autoUpdater.quitAndInstall();
|
|
283
|
+
});
|
|
284
|
+
});
|
|
285
|
+
autoUpdater.on('error', (error) => {
|
|
286
|
+
logger.error('Update error:', error);
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
let extensionsLoaded = false;
|
|
290
|
+
/** Load development extensions only once after website loads successfully */
|
|
291
|
+
async function loadDevExtensions() {
|
|
292
|
+
// Only load extensions in dev mode or when explicitly enabled
|
|
293
|
+
if (!isDev && !app.commandLine.hasSwitch('devtoolextensions')) {
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
if (app.commandLine.hasSwitch('devtoolextensions') && app.commandLine.getSwitchValue('devtoolextensions') === '0') {
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
try {
|
|
300
|
+
const reactDevTools = await installExtension(REACT_DEVELOPER_TOOLS);
|
|
301
|
+
logger.log(`🔧 Added Extension: ${reactDevTools}`);
|
|
302
|
+
}
|
|
303
|
+
catch (err) {
|
|
304
|
+
logger.log('❌ React DevTools installation failed:', err);
|
|
305
|
+
}
|
|
306
|
+
try {
|
|
307
|
+
const mobxDevTools = await installExtension(MOBX_DEVTOOLS);
|
|
308
|
+
logger.log(`🔧 Added Extension: ${mobxDevTools}`);
|
|
309
|
+
}
|
|
310
|
+
catch (err) {
|
|
311
|
+
logger.log('❌ MobX DevTools installation failed:', err);
|
|
312
|
+
}
|
|
313
|
+
extensionsLoaded = true;
|
|
314
|
+
logger.log('🔧 Extension loading completed');
|
|
315
|
+
}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { app, Menu } from 'electron';
|
|
2
|
+
import { buildProject, checkUpdates, openAppLog, showAbout, showInExplorer } from './actions.js';
|
|
3
|
+
export function buildAppMenu(mainWindow) {
|
|
4
|
+
const isMac = process.platform === 'darwin';
|
|
5
|
+
if (isMac) {
|
|
6
|
+
return buildMacMenu(mainWindow);
|
|
7
|
+
}
|
|
8
|
+
return buildWindowsMenu(mainWindow);
|
|
9
|
+
}
|
|
10
|
+
function buildMacMenu(mainWindow) {
|
|
11
|
+
const menuTemplate = [
|
|
12
|
+
{
|
|
13
|
+
label: app.name,
|
|
14
|
+
submenu: [
|
|
15
|
+
{
|
|
16
|
+
label: `About ${app.name}`,
|
|
17
|
+
click: () => showAbout(mainWindow)
|
|
18
|
+
},
|
|
19
|
+
{ type: 'separator' },
|
|
20
|
+
{
|
|
21
|
+
label: 'Check for Updates',
|
|
22
|
+
click: checkUpdates
|
|
23
|
+
},
|
|
24
|
+
{ type: 'separator' },
|
|
25
|
+
{ role: 'services' },
|
|
26
|
+
{ type: 'separator' },
|
|
27
|
+
{ role: 'hide' },
|
|
28
|
+
{ role: 'hideOthers' },
|
|
29
|
+
{ role: 'unhide' },
|
|
30
|
+
{ type: 'separator' },
|
|
31
|
+
{
|
|
32
|
+
label: `Quit ${app.name}`,
|
|
33
|
+
accelerator: 'Cmd+Q',
|
|
34
|
+
click: () => app.quit()
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
label: 'Project',
|
|
40
|
+
submenu: [
|
|
41
|
+
{
|
|
42
|
+
label: 'Build Project',
|
|
43
|
+
accelerator: 'Cmd+B',
|
|
44
|
+
click: () => buildProject(true)
|
|
45
|
+
},
|
|
46
|
+
{ type: 'separator' },
|
|
47
|
+
{
|
|
48
|
+
label: 'Show in Finder',
|
|
49
|
+
accelerator: 'Cmd+E',
|
|
50
|
+
click: showInExplorer
|
|
51
|
+
}
|
|
52
|
+
]
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
label: 'Edit',
|
|
56
|
+
submenu: [
|
|
57
|
+
{ label: 'Undo', role: 'undo' },
|
|
58
|
+
{ label: 'Redo', role: 'redo' },
|
|
59
|
+
{ type: 'separator' },
|
|
60
|
+
{ label: 'Cut', role: 'cut' },
|
|
61
|
+
{ label: 'Copy', role: 'copy' },
|
|
62
|
+
{ label: 'Paste', role: 'paste' },
|
|
63
|
+
{ label: 'Paste and Match Style', role: 'pasteAndMatchStyle' },
|
|
64
|
+
{ label: 'Delete', role: 'delete' },
|
|
65
|
+
{ label: 'Select All', role: 'selectAll' }
|
|
66
|
+
]
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
label: 'View',
|
|
70
|
+
submenu: [
|
|
71
|
+
{
|
|
72
|
+
label: 'Reload',
|
|
73
|
+
accelerator: 'Cmd+R',
|
|
74
|
+
click: () => mainWindow?.reload()
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
label: 'Force Reload',
|
|
78
|
+
accelerator: 'Cmd+Shift+R',
|
|
79
|
+
click: () => mainWindow?.webContents.reloadIgnoringCache()
|
|
80
|
+
},
|
|
81
|
+
{ type: 'separator' },
|
|
82
|
+
{ label: 'Actual Size', role: 'resetZoom' },
|
|
83
|
+
{ label: 'Zoom In', role: 'zoomIn' },
|
|
84
|
+
{ label: 'Zoom Out', role: 'zoomOut' },
|
|
85
|
+
{ type: 'separator' },
|
|
86
|
+
{ label: 'Toggle Full Screen', role: 'togglefullscreen' },
|
|
87
|
+
{
|
|
88
|
+
label: 'Toggle Full Screen',
|
|
89
|
+
accelerator: 'F11',
|
|
90
|
+
visible: false,
|
|
91
|
+
click: () => mainWindow?.setFullScreen(!mainWindow.isFullScreen())
|
|
92
|
+
}
|
|
93
|
+
]
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
label: 'Tools',
|
|
97
|
+
submenu: [
|
|
98
|
+
{
|
|
99
|
+
label: 'Toggle Developer Console',
|
|
100
|
+
accelerator: 'F12',
|
|
101
|
+
click: () => mainWindow?.webContents.toggleDevTools()
|
|
102
|
+
},
|
|
103
|
+
{ type: 'separator' },
|
|
104
|
+
{
|
|
105
|
+
label: 'Open App Log',
|
|
106
|
+
click: openAppLog
|
|
107
|
+
}
|
|
108
|
+
]
|
|
109
|
+
}
|
|
110
|
+
];
|
|
111
|
+
return Menu.buildFromTemplate(menuTemplate);
|
|
112
|
+
}
|
|
113
|
+
function buildWindowsMenu(mainWindow) {
|
|
114
|
+
const menuTemplate = [
|
|
115
|
+
{
|
|
116
|
+
label: 'Project',
|
|
117
|
+
submenu: [
|
|
118
|
+
{
|
|
119
|
+
label: 'Build Project',
|
|
120
|
+
accelerator: 'Ctrl+B',
|
|
121
|
+
click: () => buildProject(true)
|
|
122
|
+
},
|
|
123
|
+
{ type: 'separator' },
|
|
124
|
+
{
|
|
125
|
+
label: 'Show in Explorer',
|
|
126
|
+
accelerator: 'Ctrl+E',
|
|
127
|
+
click: showInExplorer
|
|
128
|
+
}
|
|
129
|
+
]
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
label: 'Edit',
|
|
133
|
+
submenu: [
|
|
134
|
+
{ label: 'Undo', role: 'undo' },
|
|
135
|
+
{ label: 'Redo', role: 'redo' },
|
|
136
|
+
{ type: 'separator' },
|
|
137
|
+
{ label: 'Cut', role: 'cut' },
|
|
138
|
+
{ label: 'Copy', role: 'copy' },
|
|
139
|
+
{ label: 'Paste', role: 'paste' },
|
|
140
|
+
{ label: 'Paste and Match Style', role: 'pasteAndMatchStyle' },
|
|
141
|
+
{ label: 'Delete', role: 'delete' },
|
|
142
|
+
{ label: 'Select All', role: 'selectAll' }
|
|
143
|
+
]
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
label: 'View',
|
|
147
|
+
submenu: [
|
|
148
|
+
{
|
|
149
|
+
label: 'Reload',
|
|
150
|
+
accelerator: 'Ctrl+R',
|
|
151
|
+
click: () => mainWindow?.reload()
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
label: 'Force Reload',
|
|
155
|
+
accelerator: 'Ctrl+Shift+R',
|
|
156
|
+
click: () => mainWindow?.webContents.reloadIgnoringCache()
|
|
157
|
+
},
|
|
158
|
+
{ type: 'separator' },
|
|
159
|
+
{
|
|
160
|
+
label: 'Toggle Developer Console',
|
|
161
|
+
accelerator: 'F12',
|
|
162
|
+
click: () => mainWindow?.webContents.toggleDevTools()
|
|
163
|
+
},
|
|
164
|
+
{ type: 'separator' },
|
|
165
|
+
{ label: 'Actual Size', role: 'resetZoom' },
|
|
166
|
+
{ label: 'Zoom In', role: 'zoomIn' },
|
|
167
|
+
{ label: 'Zoom Out', role: 'zoomOut' },
|
|
168
|
+
{ type: 'separator' },
|
|
169
|
+
{ label: 'Toggle Full Screen', role: 'togglefullscreen', accelerator: 'F11' }
|
|
170
|
+
]
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
label: 'Tools',
|
|
174
|
+
submenu: [
|
|
175
|
+
{
|
|
176
|
+
label: 'Check for Updates',
|
|
177
|
+
click: checkUpdates
|
|
178
|
+
},
|
|
179
|
+
{ type: 'separator' },
|
|
180
|
+
{
|
|
181
|
+
label: 'Open App Log',
|
|
182
|
+
click: openAppLog
|
|
183
|
+
}
|
|
184
|
+
]
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
label: 'Help',
|
|
188
|
+
submenu: [
|
|
189
|
+
{
|
|
190
|
+
label: `About ${app.name}`,
|
|
191
|
+
click: () => showAbout(mainWindow)
|
|
192
|
+
}
|
|
193
|
+
]
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
label: '',
|
|
197
|
+
submenu: [
|
|
198
|
+
{
|
|
199
|
+
label: `Quit ${app.name}`,
|
|
200
|
+
accelerator: 'Ctrl+Q',
|
|
201
|
+
click: () => app.quit()
|
|
202
|
+
}
|
|
203
|
+
],
|
|
204
|
+
visible: false
|
|
205
|
+
}
|
|
206
|
+
];
|
|
207
|
+
return Menu.buildFromTemplate(menuTemplate);
|
|
208
|
+
}
|