@@ -12,6 +12,9 @@ const config: ForgeConfig = {
|
||||
asar: true,
|
||||
icon: './assets/flowy',
|
||||
appBundleId: 'live.flowy.llink',
|
||||
protocols: [
|
||||
{ name: 'llink', schemes: ['llink'] },
|
||||
],
|
||||
extendInfo: {
|
||||
NSMicrophoneUsageDescription: 'llink needs microphone access to record audio messages.',
|
||||
NSCameraUsageDescription: 'llink needs camera access to record video messages.',
|
||||
|
||||
@@ -25,6 +25,21 @@ if (process.platform === 'darwin' && !app.isPackaged) {
|
||||
app.dock?.setIcon(path.join(__dirname, '../../assets/icon.png'));
|
||||
}
|
||||
|
||||
// Single-instance lock: on Windows/Linux, clicking a llink:// URL launches a new
|
||||
// process. The lock makes the losing instance quit and fires `second-instance` on
|
||||
// the primary, so we focus the existing window instead of spawning a duplicate.
|
||||
// macOS uses `open-url` instead and doesn't need this, but the lock is harmless.
|
||||
if (!app.requestSingleInstanceLock()) {
|
||||
app.quit();
|
||||
}
|
||||
|
||||
// Register llink:// as the default handler for this app. macOS also gets this
|
||||
// declaratively via CFBundleURLTypes (forge.config.ts `protocols`); Windows relies
|
||||
// on this runtime call (Squirrel doesn't register protocols on install).
|
||||
if (!app.isDefaultProtocolClient('llink')) {
|
||||
app.setAsDefaultProtocolClient('llink');
|
||||
}
|
||||
|
||||
let mainWindow: BrowserWindow | null = null;
|
||||
let autoplayWindow: BrowserWindow | null = null;
|
||||
let huddleWindow: BrowserWindow | null = null;
|
||||
@@ -438,6 +453,8 @@ ipcMain.on('app:set-dock-badge', (_event, count: number) => {
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle('app:get-version', () => app.getVersion());
|
||||
|
||||
ipcMain.handle('link:fetch-metadata', async (_event, url: string) => {
|
||||
if (typeof url !== 'string') return null;
|
||||
try {
|
||||
@@ -517,5 +534,27 @@ app.on('activate', () => {
|
||||
}
|
||||
});
|
||||
|
||||
function focusMainWindow() {
|
||||
if (!mainWindow) return;
|
||||
if (mainWindow.isMinimized()) mainWindow.restore();
|
||||
if (!mainWindow.isVisible()) mainWindow.show();
|
||||
mainWindow.focus();
|
||||
}
|
||||
|
||||
// macOS delivers llink:// URLs via this event, both when the app is already
|
||||
// running and on cold start (after `ready`). We prevent the default to silence
|
||||
// Electron's warning and focus the window — OS-level focus alone won't restore
|
||||
// a hidden or minimized window. Cold start is handled by createWindow().
|
||||
app.on('open-url', (event) => {
|
||||
event.preventDefault();
|
||||
focusMainWindow();
|
||||
});
|
||||
|
||||
// Windows/Linux: the OS launches a second process with the URL in argv; the
|
||||
// single-instance lock diverts it here on the primary instance.
|
||||
app.on('second-instance', () => {
|
||||
focusMainWindow();
|
||||
});
|
||||
|
||||
// In this file you can include the rest of your app's specific main process
|
||||
// code. You can also put them in separate files and import them here.
|
||||
|
||||
Reference in New Issue
Block a user