Skip to content

Commit

Permalink
[photosd] Handle passkey deeplinks on Linux and Windows (#2109)
Browse files Browse the repository at this point in the history
Tested on an Ubuntu 24 VM, with deb it works out of the box, with
AppImage I needed to install `appimaged` as recommended by
https://docs.appimage.org/user-guide/run-appimages.html#integrating-appimages-into-the-desktop.
  • Loading branch information
mnvr authored Jun 12, 2024
2 parents 47a965f + f529460 commit adaa81f
Showing 1 changed file with 100 additions and 83 deletions.
183 changes: 100 additions & 83 deletions desktop/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,103 @@ export const allowWindowClose = (): void => {
shouldAllowWindowClose = true;
};

/**
* The app's entry point.
*
* We call this at the end of this file.
*/
const main = () => {
const gotTheLock = app.requestSingleInstanceLock();
if (!gotTheLock) {
app.quit();
return;
}

let mainWindow: BrowserWindow | undefined;

initLogging();
logStartupBanner();
registerForEnteLinks();
// The order of the next two calls is important
setupRendererServer();
registerPrivilegedSchemes();
migrateLegacyWatchStoreIfNeeded();

/**
* Handle an open URL request, but ensuring that we have a mainWindow.
*/
const handleOpenURLEnsuringWindow = (url: string) => {
log.info(`Attempting to handle request to open URL: ${url}`);
if (mainWindow) handleEnteLinks(mainWindow, url);
else setTimeout(() => handleOpenURLEnsuringWindow(url), 1000);
};

app.on("second-instance", (_, argv: string[]) => {
// Someone tried to run a second instance, we should focus our window.
if (mainWindow) {
mainWindow.show();
if (mainWindow.isMinimized()) mainWindow.restore();
mainWindow.focus();
}
// On Windows and Linux, this is how we get deeplinks.
// See: registerForEnteLinks
const url = argv.pop();
if (url) handleOpenURLEnsuringWindow(url);
});

// Emitted once, when Electron has finished initializing.
//
// Note that some Electron APIs can only be used after this event occurs.
void app.whenReady().then(() => {
void (async () => {
// Create window and prepare for the renderer.
mainWindow = createMainWindow();

// Setup IPC and streams.
const watcher = createWatcher(mainWindow);
attachIPCHandlers();
attachFSWatchIPCHandlers(watcher);
attachLogoutIPCHandler(watcher);
registerStreamProtocol();

// Configure the renderer's environment.
const webContents = mainWindow.webContents;
setDownloadPath(webContents);
allowExternalLinks(webContents);
allowAllCORSOrigins(webContents);

// Start loading the renderer.
void mainWindow.loadURL(rendererURL);

// Continue on with the rest of the startup sequence.
Menu.setApplicationMenu(await createApplicationMenu(mainWindow));
setupTrayItem(mainWindow);
setupAutoUpdater(mainWindow);

try {
await deleteLegacyDiskCacheDirIfExists();
await deleteLegacyKeysStoreIfExists();
} catch (e) {
// Log but otherwise ignore errors during non-critical startup
// actions.
log.error("Ignoring startup error", e);
}
})();
});

// This is a macOS only event. Show our window when the user activates the
// app, e.g. by clicking on its dock icon.
app.on("activate", () => mainWindow?.show());

app.on("before-quit", () => {
if (mainWindow) saveWindowBounds(mainWindow);
allowWindowClose();
});

// On macOS, this is how we get deeplinks. See: registerForEnteLinks
app.on("open-url", (_, url) => handleOpenURLEnsuringWindow(url));
};

/**
* Log a standard startup banner.
*
Expand Down Expand Up @@ -145,6 +242,8 @@ const registerPrivilegedSchemes = () => {
* Implementation notes:
* - https://www.electronjs.org/docs/latest/tutorial/launch-app-from-url-in-another-app
* - This works only when the app is packaged.
* - On Windows and Linux, we get the deeplink in the "second-instance" event.
* - On macOS, we get the deeplink in the "open-url" event.
*/
const registerForEnteLinks = () => app.setAsDefaultProtocolClient("ente");

Expand Down Expand Up @@ -464,87 +563,5 @@ const deleteLegacyKeysStoreIfExists = async () => {
}
};

const main = () => {
const gotTheLock = app.requestSingleInstanceLock();
if (!gotTheLock) {
app.quit();
return;
}

let mainWindow: BrowserWindow | undefined;

initLogging();
logStartupBanner();
registerForEnteLinks();
// The order of the next two calls is important
setupRendererServer();
registerPrivilegedSchemes();
migrateLegacyWatchStoreIfNeeded();

app.on("second-instance", () => {
// Someone tried to run a second instance, we should focus our window.
if (mainWindow) {
mainWindow.show();
if (mainWindow.isMinimized()) mainWindow.restore();
mainWindow.focus();
}
});

// Emitted once, when Electron has finished initializing.
//
// Note that some Electron APIs can only be used after this event occurs.
void app.whenReady().then(() => {
void (async () => {
// Create window and prepare for the renderer.
mainWindow = createMainWindow();

// Setup IPC and streams.
const watcher = createWatcher(mainWindow);
attachIPCHandlers();
attachFSWatchIPCHandlers(watcher);
attachLogoutIPCHandler(watcher);
registerStreamProtocol();

// Configure the renderer's environment.
const webContents = mainWindow.webContents;
setDownloadPath(webContents);
allowExternalLinks(webContents);
allowAllCORSOrigins(webContents);

// Start loading the renderer.
void mainWindow.loadURL(rendererURL);

// Continue on with the rest of the startup sequence.
Menu.setApplicationMenu(await createApplicationMenu(mainWindow));
setupTrayItem(mainWindow);
setupAutoUpdater(mainWindow);

try {
await deleteLegacyDiskCacheDirIfExists();
await deleteLegacyKeysStoreIfExists();
} catch (e) {
// Log but otherwise ignore errors during non-critical startup
// actions.
log.error("Ignoring startup error", e);
}
})();
});

// This is a macOS only event. Show our window when the user activates the
// app, e.g. by clicking on its dock icon.
app.on("activate", () => mainWindow?.show());

app.on("before-quit", () => {
if (mainWindow) saveWindowBounds(mainWindow);
allowWindowClose();
});

const handleOpenURLWithWindow = (url: string) => {
log.info(`Attempting to handle request to open URL: ${url}`);
if (mainWindow) handleEnteLinks(mainWindow, url);
else setTimeout(() => handleOpenURLWithWindow(url), 1000);
};
app.on("open-url", (_, url) => handleOpenURLWithWindow(url));
};

// Go for it.
main();

0 comments on commit adaa81f

Please sign in to comment.