-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #76 from alexwkleung/v0.2.0-dev-5.0
v0.2.0-dev-5.0
- Loading branch information
Showing
20 changed files
with
1,495 additions
and
1,135 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,130 +1,209 @@ | ||
import { app, shell, BrowserWindow, protocol, net, ipcMain } from 'electron' | ||
import { join } from 'path' | ||
import { dirname } from 'path' | ||
import { app, shell, BrowserWindow, protocol, net, ipcMain, dialog } from 'electron' | ||
import { join, dirname } from 'path' | ||
import { fileURLToPath } from 'url' | ||
import contextMenu from 'electron-context-menu' | ||
//import icon from '../../resources/icon.png?asset' | ||
import { isMacOS, isWindows, isLinux, isDev } from './is-main' | ||
import windowStateKeeper from 'electron-window-state' | ||
import { dialog } from 'electron' | ||
|
||
//prevent multiple instances of Iris running | ||
if(!app.requestSingleInstanceLock()) { | ||
console.log("Another instance of Iris is running. Exiting."); | ||
|
||
dialog.showErrorBox("Iris", "Another instance of Iris is running. Closing current instance."); | ||
|
||
app.quit(); | ||
} | ||
|
||
ipcMain.handle('error-dialog', (event, title, content) => { | ||
dialog.showErrorBox(title, content); | ||
}) | ||
|
||
function createWindow(): void { | ||
//esm version of __dirname | ||
const _dirname: string = dirname(fileURLToPath(import.meta.url)); | ||
|
||
//isomorphic version of __dirname for both cjs/esm compatibility (https://antfu.me/posts/isomorphic-dirname) | ||
//const _dirname: string = typeof __dirname !== 'undefined' ? __dirname : dirname(fileURLToPath(import.meta.url)); | ||
|
||
//create window state keeper | ||
const windowState: windowStateKeeper.State = windowStateKeeper({ | ||
defaultWidth: 1200, | ||
defaultHeight: 900, | ||
}) | ||
|
||
let mainWindow: BrowserWindow = {} as BrowserWindow; | ||
|
||
mainWindow = new BrowserWindow({ | ||
width: windowState.width, | ||
height: windowState.height, | ||
x: windowState.x, | ||
y: windowState.y, | ||
minWidth: 800, | ||
minHeight: 600, | ||
show: false, | ||
autoHideMenuBar: true, | ||
titleBarStyle: isMacOS() ? 'hiddenInset' : 'default', //only check macOS | ||
webPreferences: { | ||
preload: join(_dirname, '../preload/index.js'), | ||
sandbox: false, | ||
contextIsolation: true, | ||
webviewTag: false, | ||
spellcheck: false | ||
namespace MainProcess { | ||
class AppWindow { | ||
/** | ||
* Browser window | ||
* | ||
* @protected | ||
*/ | ||
protected mainWindow: BrowserWindow = {} as BrowserWindow; | ||
|
||
/** | ||
* Window state | ||
* | ||
* @private | ||
*/ | ||
private windowState: windowStateKeeper.State = {} as windowStateKeeper.State; | ||
|
||
/** | ||
* App instance | ||
* | ||
* @private | ||
*/ | ||
private appInstance(): void { | ||
//prevent multiple instances of Iris running | ||
if(!app.requestSingleInstanceLock()) { | ||
console.log("Another instance of Iris is running. Exiting."); | ||
|
||
dialog.showErrorBox("Iris", "Another instance of Iris is running. Closing current instance."); | ||
|
||
app.quit(); | ||
process.exit(0); | ||
} | ||
} | ||
}); | ||
|
||
//register windowState listener | ||
windowState.manage(mainWindow); | ||
|
||
//check if platform is darwin | ||
if(isMacOS()) { | ||
//log | ||
console.log("Platform is darwin (macOS)"); | ||
//check if platform is linux | ||
} else if(isLinux()) { | ||
//log | ||
console.log("Platform is Linux"); | ||
//check if platform is windows | ||
} else if(isWindows()) { | ||
//log | ||
console.log("Platform is Windows"); | ||
} | ||
|
||
//set min window size | ||
mainWindow.setMinimumSize(800, 600); | ||
/** | ||
* ipcMain handlers | ||
* | ||
* @private | ||
*/ | ||
private ipcMainHandlers(): void { | ||
ipcMain.handle('error-dialog', (_: Electron.IpcMainInvokeEvent, title: string, content: string) => { | ||
dialog.showErrorBox(title, content); | ||
}) | ||
|
||
ipcMain.handle('show-message-box', (_: Electron.IpcMainInvokeEvent, message: string) => { | ||
dialog.showMessageBox(this.mainWindow, { | ||
message: message | ||
}) | ||
}) | ||
} | ||
|
||
//for now, use electron-context-menu and extend it if necessary. | ||
//later on, I will implement my own custom context menu so it can be | ||
//fine-tuned based on the needs of Iris | ||
contextMenu(); | ||
/** | ||
* Call this after registering `windowState` listener | ||
* | ||
* @internal | ||
* @private | ||
*/ | ||
private mainProcLogger(): void { | ||
console.log("Current window dimensions: " + this.windowState.width + "x" + this.windowState.height); | ||
console.log("Current window coordinates: " + "(" + this.windowState.x + ", " + this.windowState.y + ")"); | ||
} | ||
|
||
mainWindow.on('ready-to-show', () => { | ||
mainWindow.show(); | ||
}); | ||
/** | ||
* Initialize main window | ||
* | ||
* @private | ||
*/ | ||
private initializeMainWindow(): void { | ||
//esm version of __dirname | ||
const _dirname: string = dirname(fileURLToPath(import.meta.url)); | ||
|
||
//isomorphic version of __dirname for both cjs/esm compatibility (https://antfu.me/posts/isomorphic-dirname) | ||
//const _dirname: string = typeof __dirname !== 'undefined' ? __dirname : dirname(fileURLToPath(import.meta.url)); | ||
|
||
this.windowState = windowStateKeeper({ | ||
defaultWidth: 1200, | ||
defaultHeight: 900, | ||
}); | ||
|
||
mainWindow.webContents.setWindowOpenHandler((details) => { | ||
shell.openExternal(details.url) | ||
return { | ||
action: 'deny' | ||
this.mainWindow = new BrowserWindow({ | ||
width: this.windowState.width, | ||
height: this.windowState.height, | ||
x: this.windowState.x, | ||
y: this.windowState.y, | ||
minWidth: 800, | ||
minHeight: 600, | ||
show: false, | ||
autoHideMenuBar: true, | ||
titleBarStyle: isMacOS() ? 'hiddenInset' : 'default', //only check macOS | ||
webPreferences: { | ||
preload: join(_dirname, '../preload/index.js'), | ||
sandbox: false, | ||
contextIsolation: true, | ||
webviewTag: false, | ||
spellcheck: false | ||
} | ||
}); | ||
|
||
//register windowState listener | ||
this.windowState.manage(this.mainWindow); | ||
|
||
//main process logger | ||
this.mainProcLogger(); | ||
|
||
//check if platform is darwin | ||
if(isMacOS()) { | ||
//log | ||
console.log("Platform is darwin (macOS)"); | ||
//check if platform is linux | ||
} else if(isLinux()) { | ||
//log | ||
console.log("Platform is Linux"); | ||
//check if platform is windows | ||
} else if(isWindows()) { | ||
//log | ||
console.log("Platform is Windows"); | ||
} | ||
}); | ||
|
||
if(isDev()) { | ||
//load dev server url in main window | ||
mainWindow.loadURL('http://localhost:5173/'); | ||
|
||
//set min window size | ||
this.mainWindow.setMinimumSize(800, 600); | ||
|
||
//for now, use electron-context-menu and extend it if necessary. | ||
//later on, I will implement my own custom context menu so it can be | ||
//fine-tuned based on the needs of Iris | ||
contextMenu(); | ||
|
||
this.mainWindow.on('ready-to-show', () => { | ||
this.mainWindow.show(); | ||
}); | ||
|
||
this.mainWindow.webContents.setWindowOpenHandler((details) => { | ||
shell.openExternal(details.url) | ||
return { | ||
action: 'deny' | ||
} | ||
}); | ||
|
||
if(isDev()) { | ||
//load dev server url in main window | ||
this.mainWindow.loadURL('http://localhost:5173/'); | ||
|
||
//open dev tools undocked by default | ||
this.mainWindow.webContents.openDevTools({ | ||
mode: 'undocked' | ||
}); | ||
} else { | ||
//this is supposed to be production build | ||
//path might change once electron-vite is removed | ||
this.mainWindow.loadFile(join(__dirname, '../renderer/index.html')); | ||
} | ||
} | ||
|
||
//open dev tools undocked by default | ||
mainWindow.webContents.openDevTools({ | ||
mode: 'undocked' | ||
/** | ||
* Initialize Electron app | ||
* | ||
* @private | ||
*/ | ||
private initializeElectronApp(): void { | ||
app.whenReady().then(() => { | ||
//initialize main window | ||
this.initializeMainWindow(); | ||
|
||
app.on('activate', () => { | ||
if(BrowserWindow.getAllWindows().length === 0) { | ||
this.initializeMainWindow(); | ||
} | ||
}); | ||
|
||
//custom protocol to handle local file system absolute paths | ||
protocol.handle('local', (request): Promise<Response> => { | ||
return net.fetch('file://' + request.url.slice('local://'.length)).catch((e) => console.error(e)) as Promise<Response> | ||
}) | ||
}); | ||
|
||
app.on('window-all-closed', () => { | ||
if(isLinux() || isWindows()) { | ||
app.quit(); | ||
} else if(isMacOS()) { | ||
return; | ||
} | ||
}); | ||
} else { | ||
//this is supposed to be production build | ||
//path might change once electron-vite is removed | ||
mainWindow.loadFile(join(__dirname, '../renderer/index.html')); | ||
} | ||
|
||
/** | ||
* Build main window | ||
* | ||
* @public | ||
*/ | ||
public buildMainWindow(): void { | ||
this.appInstance(); | ||
this.ipcMainHandlers(); | ||
this.initializeElectronApp(); | ||
} | ||
} | ||
|
||
//AppWindow object | ||
export const ElectronWindow: AppWindow = new AppWindow(); | ||
} | ||
|
||
app.whenReady().then(() => { | ||
createWindow(); | ||
//build window | ||
MainProcess.ElectronWindow.buildMainWindow(); | ||
|
||
app.on('activate', () => { | ||
if(BrowserWindow.getAllWindows().length === 0) { | ||
createWindow(); | ||
} | ||
}); | ||
|
||
//custom protocol to handle local file system absolute paths | ||
protocol.handle('local', (request): Promise<Response> => { | ||
return net.fetch('file://' + request.url.slice('local://'.length)).catch((e) => console.error(e)) as Promise<Response> | ||
}) | ||
}); | ||
|
||
app.on('window-all-closed', () => { | ||
if(isLinux() || isWindows()) { | ||
app.quit(); | ||
} else if(isMacOS()) { | ||
return; | ||
} | ||
}); |
Oops, something went wrong.