feat: initial commit
This commit is contained in:
@@ -0,0 +1,174 @@
|
||||
import { join, resolve } from "node:path";
|
||||
|
||||
import {
|
||||
BrowserWindow,
|
||||
Menu,
|
||||
MenuItem,
|
||||
app,
|
||||
ipcMain,
|
||||
nativeImage,
|
||||
} from "electron";
|
||||
|
||||
import { setBadgeCount } from "./badges";
|
||||
import { config } from "./config";
|
||||
import { updateTrayMenu } from "./tray";
|
||||
|
||||
// global reference to main window
|
||||
export let mainWindow: BrowserWindow;
|
||||
|
||||
// currently in-use build
|
||||
export const BUILD_URL = new URL(
|
||||
app.commandLine.hasSwitch("force-server")
|
||||
? app.commandLine.getSwitchValue("force-server")
|
||||
: (MAIN_WINDOW_VITE_DEV_SERVER_URL ?? "https://beta.revolt.chat"),
|
||||
);
|
||||
|
||||
// internal window state
|
||||
let shouldQuit = false;
|
||||
|
||||
// load the window icon
|
||||
const windowIcon = nativeImage.createFromPath(
|
||||
resolve(process.resourcesPath, "icon.png"),
|
||||
);
|
||||
|
||||
console.info(resolve(process.resourcesPath, "icon.png"));
|
||||
|
||||
// windowIcon.setTemplateImage(true);
|
||||
|
||||
/**
|
||||
* Create the main application window
|
||||
*/
|
||||
export function createMainWindow() {
|
||||
// create the window
|
||||
mainWindow = new BrowserWindow({
|
||||
minWidth: 300,
|
||||
minHeight: 300,
|
||||
width: 800,
|
||||
height: 600,
|
||||
backgroundColor: "#191919",
|
||||
frame: !config.customFrame,
|
||||
icon: windowIcon,
|
||||
webPreferences: {
|
||||
// relative to `.vite/build`
|
||||
preload: join(__dirname, "preload.js"),
|
||||
contextIsolation: true,
|
||||
nodeIntegration: false,
|
||||
spellcheck: true,
|
||||
},
|
||||
});
|
||||
|
||||
// maximise the window if it was maximised before
|
||||
if (config.windowState.isMaximised) {
|
||||
mainWindow.maximize();
|
||||
}
|
||||
|
||||
// load the entrypoint
|
||||
mainWindow.loadURL(BUILD_URL.toString());
|
||||
|
||||
// minimise window to tray
|
||||
mainWindow.on("close", (event) => {
|
||||
if (!shouldQuit && config.minimiseToTray) {
|
||||
event.preventDefault();
|
||||
mainWindow.hide();
|
||||
}
|
||||
});
|
||||
|
||||
// update tray menu when window is shown/hidden
|
||||
mainWindow.on("show", updateTrayMenu);
|
||||
mainWindow.on("hide", updateTrayMenu);
|
||||
|
||||
// keep track of window state
|
||||
function generateState() {
|
||||
config.windowState = {
|
||||
isMaximised: mainWindow.isMaximized(),
|
||||
};
|
||||
}
|
||||
|
||||
mainWindow.on("maximize", generateState);
|
||||
mainWindow.on("unmaximize", generateState);
|
||||
|
||||
// rebind zoom controls to be more sensible
|
||||
mainWindow.webContents.on("before-input-event", (event, input) => {
|
||||
if (input.control && input.key === "=") {
|
||||
// zoom in (+)
|
||||
event.preventDefault();
|
||||
mainWindow.webContents.setZoomLevel(
|
||||
mainWindow.webContents.getZoomLevel() + 1,
|
||||
);
|
||||
} else if (input.control && input.key === "-") {
|
||||
// zoom out (-)
|
||||
event.preventDefault();
|
||||
mainWindow.webContents.setZoomLevel(
|
||||
mainWindow.webContents.getZoomLevel() - 1,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// configure spellchecker context menu
|
||||
mainWindow.webContents.on("context-menu", (_, params) => {
|
||||
const menu = new Menu();
|
||||
|
||||
// add all suggestions
|
||||
for (const suggestion of params.dictionarySuggestions) {
|
||||
menu.append(
|
||||
new MenuItem({
|
||||
label: suggestion,
|
||||
click: () => mainWindow.webContents.replaceMisspelling(suggestion),
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
// allow users to add the misspelled word to the dictionary
|
||||
if (params.misspelledWord) {
|
||||
menu.append(
|
||||
new MenuItem({
|
||||
label: "Add to dictionary",
|
||||
click: () =>
|
||||
mainWindow.webContents.session.addWordToSpellCheckerDictionary(
|
||||
params.misspelledWord,
|
||||
),
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
// add an option to toggle spellchecker
|
||||
menu.append(
|
||||
new MenuItem({
|
||||
label: "Toggle spellcheck",
|
||||
click() {
|
||||
config.spellchecker = !config.spellchecker;
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
// show menu if we've generated enough entries
|
||||
if (menu.items.length > 0) {
|
||||
menu.popup();
|
||||
}
|
||||
});
|
||||
|
||||
// push world events to the window
|
||||
ipcMain.on("minimise", () => mainWindow.minimize());
|
||||
ipcMain.on("maximise", () =>
|
||||
mainWindow.isMaximized() ? mainWindow.unmaximize() : mainWindow.maximize(),
|
||||
);
|
||||
ipcMain.on("close", () => mainWindow.close());
|
||||
|
||||
// mainWindow.webContents.openDevTools();
|
||||
|
||||
let i = 0;
|
||||
setInterval(() => setBadgeCount((++i % 30) + 1), 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Quit the entire app
|
||||
*/
|
||||
export function quitApp() {
|
||||
shouldQuit = true;
|
||||
mainWindow.close();
|
||||
}
|
||||
|
||||
// Ensure global app quit works properly
|
||||
app.on("before-quit", () => {
|
||||
shouldQuit = true;
|
||||
});
|
||||
Reference in New Issue
Block a user