chore: Initial commit of Opencord base state

This commit is contained in:
Jannis Braun
2026-02-18 02:49:21 +01:00
commit 4fd17084a5
124 changed files with 17955 additions and 0 deletions
+194
View File
@@ -0,0 +1,194 @@
import {
app,
BrowserWindow,
Tray,
Menu,
Notification,
nativeImage,
ipcMain,
shell,
} from 'electron';
import path from 'path';
let mainWindow: BrowserWindow | null = null;
let tray: Tray | null = null;
let isQuitting = false;
const SERVER_URL = process.env.OPENCORD_URL || 'http://localhost:3000';
function createWindow(): void {
mainWindow = new BrowserWindow({
width: 1280,
height: 800,
minWidth: 940,
minHeight: 500,
title: 'Opencord',
titleBarStyle: process.platform === 'darwin' ? 'hiddenInset' : 'default',
backgroundColor: '#313338',
show: false,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
contextIsolation: true,
nodeIntegration: false,
sandbox: true,
},
});
mainWindow.loadURL(SERVER_URL);
mainWindow.once('ready-to-show', () => {
mainWindow?.show();
});
mainWindow.on('close', (event) => {
if (!isQuitting) {
event.preventDefault();
mainWindow?.hide();
}
});
mainWindow.on('closed', () => {
mainWindow = null;
});
// Open external links in default browser
mainWindow.webContents.setWindowOpenHandler(({ url }) => {
if (url.startsWith('http://') || url.startsWith('https://')) {
shell.openExternal(url);
}
return { action: 'deny' };
});
}
function createTray(): void {
// Create a 16x16 tray icon (blue circle for Opencord)
const size = 16;
const canvas = Buffer.alloc(size * size * 4);
const cx = size / 2;
const cy = size / 2;
const r = size / 2 - 1;
for (let y = 0; y < size; y++) {
for (let x = 0; x < size; x++) {
const idx = (y * size + x) * 4;
const dist = Math.sqrt((x - cx) ** 2 + (y - cy) ** 2);
if (dist <= r) {
canvas[idx] = 0x58; // R (blurple)
canvas[idx + 1] = 0x65; // G
canvas[idx + 2] = 0xf2; // B
canvas[idx + 3] = 0xff; // A
} else {
canvas[idx] = 0;
canvas[idx + 1] = 0;
canvas[idx + 2] = 0;
canvas[idx + 3] = 0;
}
}
}
const icon = nativeImage.createFromBuffer(canvas, { width: size, height: size });
tray = new Tray(icon);
const contextMenu = Menu.buildFromTemplate([
{
label: 'Show Opencord',
click: () => {
mainWindow?.show();
mainWindow?.focus();
},
},
{
label: 'Hide',
click: () => {
mainWindow?.hide();
},
},
{ type: 'separator' },
{
label: 'Quit',
click: () => {
isQuitting = true;
app.quit();
},
},
]);
tray.setToolTip('Opencord');
tray.setContextMenu(contextMenu);
tray.on('click', () => {
if (mainWindow?.isVisible()) {
mainWindow.hide();
} else {
mainWindow?.show();
mainWindow?.focus();
}
});
}
function showNotification(title: string, body: string): void {
if (Notification.isSupported()) {
const notification = new Notification({
title,
body,
silent: false,
});
notification.on('click', () => {
mainWindow?.show();
mainWindow?.focus();
});
notification.show();
}
}
function registerIpcHandlers(): void {
ipcMain.on('show-notification', (_event, data: { title: string; body: string }) => {
showNotification(data.title, data.body);
});
ipcMain.on('set-badge-count', (_event, count: number) => {
if (app.setBadgeCount) {
app.setBadgeCount(count);
}
});
ipcMain.on('minimize-window', () => {
mainWindow?.minimize();
});
ipcMain.on('maximize-window', () => {
if (mainWindow?.isMaximized()) {
mainWindow.unmaximize();
} else {
mainWindow?.maximize();
}
});
ipcMain.on('close-window', () => {
mainWindow?.close();
});
}
app.on('ready', () => {
registerIpcHandlers();
createWindow();
createTray();
});
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
if (mainWindow === null) {
createWindow();
} else {
mainWindow.show();
}
});
app.on('before-quit', () => {
isQuitting = true;
});