notifications

This commit is contained in:
2026-02-27 22:12:49 +11:00
parent 687b42872c
commit 3493508b8a
5 changed files with 101 additions and 6 deletions

2
cinny

Submodule cinny updated: 58966aec19...f8af51b75c

View File

@@ -75,6 +75,17 @@ let tray = null;
let isQuitting = false;
let apiServer = null;
// Set app name for notifications and system tray
app.setName('Paarrot');
// On Windows, this controls the app name shown in toast notifications.
// In dev mode, use process.execPath so Windows can find the shortcut for electron.exe.
// In production, use the proper app ID.
if (process.platform === 'win32') {
const isDevelopment = process.env.NODE_ENV === 'development' || !app.isPackaged;
app.setAppUserModelId(isDevelopment ? process.execPath : 'com.paarrot.app');
}
// Configure auto-updater
autoUpdater.autoDownload = false;
autoUpdater.autoInstallOnAppQuit = true;
@@ -275,7 +286,7 @@ function createWindow() {
// Set up session handlers BEFORE loading the app
// Auto-approve media permissions including screen capture
mainWindow.webContents.session.setPermissionRequestHandler((webContents, permission, callback) => {
const allowedPermissions = ['media', 'microphone', 'camera', 'display-capture'];
const allowedPermissions = ['media', 'microphone', 'camera', 'display-capture', 'notifications'];
if (allowedPermissions.includes(permission)) {
console.log(`Paarrot: Auto-approving permission: ${permission}`);
@@ -424,11 +435,27 @@ function createWindow() {
});
// Open external links in default browser
mainWindow.webContents.setWindowOpenHandler(({ url }) => {
mainWindow.webContents.setWindowOpenHandler(({ url, features }) => {
if (url.startsWith('http://') || url.startsWith('https://')) {
shell.openExternal(url);
return { action: 'deny' };
}
// Allow blank windows for screen share pop-outs with custom features
if (url === '' || url === 'about:blank') {
return {
action: 'allow',
overrideBrowserWindowOptions: {
frame: false,
resizable: true,
backgroundColor: '#000000',
webPreferences: {
contextIsolation: true,
nodeIntegration: false,
backgroundThrottling: false,
}
}
};
}
return { action: 'allow' };
});
@@ -738,6 +765,42 @@ ipcMain.handle('get-desktop-sources', async (event, opts) => {
}
});
// Desktop notification handler
ipcMain.handle('show-notification', async (event, { title, body, icon }) => {
try {
console.log('Electron notification handler called:', { title, body });
const { Notification } = require('electron');
if (!Notification.isSupported()) {
console.error('Notifications not supported on this system');
return { success: false, error: 'Notifications not supported on this system' };
}
const notification = new Notification({
title: title || 'Paarrot',
body: body || '',
icon: icon || getIconPath(process.platform === 'win32' ? 'icon.ico' : 'icon.png'),
silent: false,
});
notification.on('click', () => {
console.log('Notification clicked');
if (mainWindow) {
mainWindow.show();
mainWindow.focus();
}
});
notification.show();
console.log('Notification shown successfully');
return { success: true };
} catch (error) {
console.error('Failed to show notification:', error);
return { success: false, error: error.message };
}
});
console.log('Paarrot Electron main process started');
console.log('Development mode:', isDev);
console.log('Platform:', process.platform);

View File

@@ -150,6 +150,11 @@ contextBridge.exposeInMainWorld('electron', {
sendResponse: (channel, result) => {
ipcRenderer.invoke(channel, result);
}
},
// Desktop notifications
notification: {
show: (options) => ipcRenderer.invoke('show-notification', options)
}
});

30
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "paarrot",
"version": "4.11.20",
"version": "4.11.26",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "paarrot",
"version": "4.11.20",
"version": "4.11.26",
"license": "AGPL-3.0-only",
"dependencies": {
"body-parser": "2.2.2",
@@ -21,6 +21,7 @@
"@actions/github": "6.0.0",
"@electron/rebuild": "4.0.3",
"concurrently": "9.2.1",
"cross-env": "10.1.0",
"electron": "40.6.0",
"electron-builder": "26.8.1",
"node-fetch": "3.3.2",
@@ -529,6 +530,13 @@
"tslib": "^2.4.0"
}
},
"node_modules/@epic-web/invariant": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@epic-web/invariant/-/invariant-1.0.0.tgz",
"integrity": "sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA==",
"dev": true,
"license": "MIT"
},
"node_modules/@fastify/busboy": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.0.0.tgz",
@@ -2789,6 +2797,24 @@
"optional": true,
"peer": true
},
"node_modules/cross-env": {
"version": "10.1.0",
"resolved": "https://registry.npmjs.org/cross-env/-/cross-env-10.1.0.tgz",
"integrity": "sha512-GsYosgnACZTADcmEyJctkJIoqAhHjttw7RsFrVoJNXbsWWqaq6Ym+7kZjq6mS45O0jij6vtiReppKQEtqWy6Dw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@epic-web/invariant": "^1.0.0",
"cross-spawn": "^7.0.6"
},
"bin": {
"cross-env": "dist/bin/cross-env.js",
"cross-env-shell": "dist/bin/cross-env-shell.js"
},
"engines": {
"node": ">=20"
}
},
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",

View File

@@ -10,7 +10,7 @@
"scripts": {
"dev": "concurrently \"npm run dev:vite\" \"npm run dev:electron\"",
"dev:vite": "cd cinny && npm start",
"dev:electron": "wait-on http://localhost:8080 && NODE_ENV=development electron .",
"dev:electron": "wait-on http://localhost:8080 && cross-env NODE_ENV=development electron .",
"build": "node -e \"require('fs').copyFileSync('config.json', 'cinny/config.json')\" && cd cinny && npm run build && cd .. && electron-builder --publish never",
"build:linux": "npm run build -- --linux",
"build:win": "npm run build -- --win",
@@ -35,6 +35,7 @@
"@actions/github": "6.0.0",
"@electron/rebuild": "4.0.3",
"concurrently": "9.2.1",
"cross-env": "10.1.0",
"electron": "40.6.0",
"electron-builder": "26.8.1",
"node-fetch": "3.3.2",