Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions app/common/typed-ipc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export type MainMessage = {
"update-badge": (messageCount: number) => void;
"update-menu": (properties: MenuProperties) => void;
"update-taskbar-icon": (data: string, text: string) => void;
"update-org-urls": (urls: string[]) => void;
};

export type MainCall = {
Expand Down Expand Up @@ -78,6 +79,7 @@ export type RendererMessage = {
"update-realm-icon": (serverURL: string, iconURL: string) => void;
"update-realm-name": (serverURL: string, realmName: string) => void;
"webview-reload": () => void;
"navigate-to-org-url": (url: string) => void;
zoomActualSize: () => void;
zoomIn: () => void;
zoomOut: () => void;
Expand Down
4 changes: 4 additions & 0 deletions app/main/handle-external-link.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import * as ConfigUtil from "../common/config-util.ts";
import * as LinkUtil from "../common/link-util.ts";
import * as t from "../common/translation-util.ts";

import {isConfiguredOrgUrl} from "./org-url-cache.ts";
import {send} from "./typed-ipc-main.ts";

function isUploadsUrl(server: string, url: URL): boolean {
Expand Down Expand Up @@ -159,6 +160,9 @@ export default function handleExternalLink(
}
},
});
} else if (isConfiguredOrgUrl(url)) {
// URL belongs to a configured organization - navigate there in-app
send(mainContents, "navigate-to-org-url", url.href);
} else {
(async () => LinkUtil.openBrowser(url))();
}
Expand Down
5 changes: 5 additions & 0 deletions app/main/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {appUpdater, shouldQuitForUpdate} from "./autoupdater.ts";
import * as BadgeSettings from "./badge-settings.ts";
import handleExternalLink from "./handle-external-link.ts";
import * as AppMenu from "./menu.ts";
import {updateOrgUrls} from "./org-url-cache.ts";
import {_getServerSettings, _isOnline, _saveServerIcon} from "./request.ts";
import {sentryInit} from "./sentry.ts";
import {setAutoLaunch} from "./startup.ts";
Expand Down Expand Up @@ -456,6 +457,10 @@ function createMainWindow(): BrowserWindow {
ConfigUtil.setConfigItem("lastActiveTab", index);
});

ipcMain.on("update-org-urls", (_event, urls: string[]) => {
updateOrgUrls(urls);
});

ipcMain.on("focus-this-webview", (event) => {
send(page, "focus-webview-with-id", event.sender.id);
mainWindow.show();
Expand Down
12 changes: 12 additions & 0 deletions app/main/org-url-cache.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Cache of configured organization origins for cross-org link handling
// This is updated by the renderer process when orgs change

let cachedOrgOrigins: string[] = [];

export function updateOrgUrls(urls: string[]): void {
cachedOrgOrigins = urls.map((url) => new URL(url).origin);
}

export function isConfiguredOrgUrl(url: URL): boolean {
return cachedOrgOrigins.includes(url.origin);
}
27 changes: 27 additions & 0 deletions app/renderer/js/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,8 @@ export class ServerManagerView {

async initTabs(): Promise<void> {
const servers = DomainUtil.getDomains();
// Sync org URLs to main process for cross-org link handling
this.syncOrgUrlsToMain();
if (servers.length > 0) {
for (const [i, server] of servers.entries()) {
const tab = this.initServer(server, i);
Expand Down Expand Up @@ -489,6 +491,12 @@ export class ServerManagerView {
return currentIndex;
}

// Sync configured org URLs to main process for cross-org link handling
syncOrgUrlsToMain(): void {
const urls = DomainUtil.getDomains().map((server) => server.url);
ipcRenderer.send("update-org-urls", urls);
}

async getCurrentActiveServer(): Promise<string> {
const tab = this.tabs[this.activeTabIndex];
return tab instanceof ServerTab ? (await tab.webview).properties.url : "";
Expand Down Expand Up @@ -1009,6 +1017,25 @@ export class ServerManagerView {
await this.activateLastTab(index);
});

ipcRenderer.on("navigate-to-org-url", async (event, urlString: string) => {
// Handle cross-organization link navigation, no-op if the url doesn't
// point to a connected organization.
const url = new URL(urlString);
const servers = DomainUtil.getDomains();
const orgIndex = servers.findIndex(
(s) => new URL(s.url).origin === url.origin,
);

if (orgIndex !== -1) {
await this.activateTab(orgIndex);
const tab = this.tabs[orgIndex];
if (tab instanceof ServerTab) {
const webview = await tab.webview;
await webview.getWebContents().loadURL(urlString);
}
}
});

ipcRenderer.on("open-org-tab", async () => {
await this.openSettings("AddServer");
});
Expand Down