-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.js
More file actions
214 lines (182 loc) · 5.9 KB
/
Copy pathmain.js
File metadata and controls
214 lines (182 loc) · 5.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
const { app, BrowserWindow, Menu, ipcMain, dialog } = require('electron');
const path = require('path');
const fs = require('fs');
// Keep a global reference of the window object
let mainWindow;
// Custom file format
const VOID_FILE_EXTENSION = '.void';
function createWindow() {
// Create the browser window with a dark background to avoid white flash
mainWindow = new BrowserWindow({
width: 1280,
height: 800,
minWidth: 800,
minHeight: 600,
backgroundColor: '#000000',
show: false, // Don't show until ready-to-show
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
contextIsolation: true,
nodeIntegration: false,
enableRemoteModule: false,
},
// Remove default frame for custom UI
frame: false,
// Set default icon
icon: path.join(__dirname, 'src/assets/images/ui/icon.png')
});
// Load the index.html of the app
mainWindow.loadFile(path.join(__dirname, 'src/index.html'));
// Show window when ready (prevents white flash)
mainWindow.once('ready-to-show', () => {
mainWindow.show();
});
// Open DevTools in development
if (process.env.NODE_ENV === 'development') {
mainWindow.webContents.openDevTools();
}
// Handle close event
mainWindow.on('close', async (e) => {
e.preventDefault(); // Prevent immediate closing
// Check if there are unsaved changes
const result = await mainWindow.webContents.executeJavaScript('window.voidApp && window.voidApp.hasUnsavedChanges()');
if (result) {
const { response } = await dialog.showMessageBox(mainWindow, {
type: 'question',
buttons: ['Save', "Don't Save", 'Cancel'],
title: 'Unsaved Changes',
message: 'Do you want to save your changes before closing?',
defaultId: 0,
cancelId: 2
});
if (response === 0) { // Save
// Trigger save
const saveResult = await mainWindow.webContents.executeJavaScript('window.voidApp.saveProject()');
if (saveResult.success) {
mainWindow.destroy();
}
} else if (response === 1) { // Don't Save
mainWindow.destroy();
}
// If response is 2 (Cancel), do nothing and keep the window open
} else {
mainWindow.destroy();
}
});
// Window events
mainWindow.on('closed', () => {
mainWindow = null;
});
}
// App ready event
app.whenReady().then(() => {
createWindow();
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();
}
});
// IPC handlers for file operations
ipcMain.handle('save-project', async (event, projectData) => {
const { filePath } = await dialog.showSaveDialog(mainWindow, {
title: 'Save VOIDSKETCH Project',
defaultPath: 'untitled' + VOID_FILE_EXTENSION,
filters: [{ name: 'VOIDSKETCH Files', extensions: ['void'] }]
});
if (!filePath) {
return { success: false, error: 'No file path selected' };
}
try {
// Ensure the directory exists
const directory = path.dirname(filePath);
if (!fs.existsSync(directory)) {
fs.mkdirSync(directory, { recursive: true });
}
fs.writeFileSync(filePath, JSON.stringify(projectData, null, 2));
return { success: true, filePath };
} catch (error) {
return { success: false, error: error.message };
}
});
ipcMain.handle('open-project', async () => {
const { filePaths } = await dialog.showOpenDialog(mainWindow, {
title: 'Open VOIDSKETCH Project',
filters: [{ name: 'VOIDSKETCH Files', extensions: ['void'] }],
properties: ['openFile']
});
if (filePaths && filePaths.length > 0) {
try {
const data = fs.readFileSync(filePaths[0], 'utf8');
return { success: true, data: JSON.parse(data), filePath: filePaths[0] };
} catch (error) {
return { success: false, error: error.message };
}
}
return { success: false };
});
ipcMain.handle('export-gif', async (event, gifData) => {
const { filePath } = await dialog.showSaveDialog(mainWindow, {
title: 'Export Animation as GIF',
defaultPath: 'voidsketch-animation.gif',
filters: [{ name: 'GIF Images', extensions: ['gif'] }]
});
if (filePath) {
try {
// Handle binary data from renderer
const buffer = Buffer.from(gifData instanceof Uint8Array ? gifData : new Uint8Array(gifData));
// Ensure the directory exists
const directory = path.dirname(filePath);
if (!fs.existsSync(directory)) {
fs.mkdirSync(directory, { recursive: true });
}
fs.writeFileSync(filePath, buffer);
return { success: true, filePath };
} catch (error) {
return { success: false, error: error.message };
}
}
return { success: false };
});
ipcMain.handle('export-png', async (event, pngDataUrl) => {
const { filePath } = await dialog.showSaveDialog(mainWindow, {
title: 'Export Canvas as PNG',
defaultPath: 'voidsketch-frame.png',
filters: [{ name: 'PNG Images', extensions: ['png'] }]
});
if (filePath) {
try {
// Convert data URL to buffer
const base64Data = pngDataUrl.replace(/^data:image\/png;base64,/, '');
const buffer = Buffer.from(base64Data, 'base64');
fs.writeFileSync(filePath, buffer);
return { success: true, filePath };
} catch (error) {
return { success: false, error: error.message };
}
}
return { success: false };
});
// Window control handlers
ipcMain.handle('minimize-window', () => {
mainWindow.minimize();
return { success: true };
});
ipcMain.handle('maximize-window', () => {
if (mainWindow.isMaximized()) {
mainWindow.unmaximize();
} else {
mainWindow.maximize();
}
return { success: true, isMaximized: mainWindow.isMaximized() };
});
ipcMain.handle('close-window', () => {
mainWindow.close();
return { success: true };
});