Skip to content

Commit

Permalink
Merge pull request #76 from alexwkleung/v0.2.0-dev-5.0
Browse files Browse the repository at this point in the history
v0.2.0-dev-5.0
  • Loading branch information
alexwkleung authored Dec 11, 2023
2 parents 4657403 + bd0401d commit 7690a37
Show file tree
Hide file tree
Showing 20 changed files with 1,495 additions and 1,135 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

<p align="center">
<img src="https://img.shields.io/github/downloads/alexwkleung/Iris/total"></img>
<img src="https://img.shields.io/github/package-json/v/alexwkleung/Iris"></img>
<img src="https://img.shields.io/github/package-json/v/alexwkleung/Iris/main"></img>
<img src="https://img.shields.io/github/license/alexwkleung/Iris"></img>
</p>

Expand All @@ -27,7 +27,7 @@

Iris is written in TypeScript and Rust.

The app currently in early development and may not be 100% stable for daily use.
The app is currently in early development and may not be 100% stable for daily use.

Only macOS installers are supplied in the early development phase. Other platforms will be supported in the official release.

Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"name": "iris",
"version": "0.2.0-dev-4.3",
"version": "0.2.0-dev-5.0",
"productName": "Iris",
"description": "Iris is a comfortable Markdown note-taking app",
"description": "A comfortable note-taking app powered by Markdown",
"main": "./out/main/index.js",
"author": "alexwkleung",
"license": "MIT",
Expand Down
303 changes: 191 additions & 112 deletions src/main/index.ts
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;
}
});
Loading

0 comments on commit 7690a37

Please sign in to comment.