Route shared URL opening through VS Code host instead of webview window APIs Add a VS Code runtime URL-open API and bridge handler using vscode.env.openExternal Keep shared URL helper behavior unchanged for desktop and web
87 lines
2.0 KiB
TypeScript
87 lines
2.0 KiB
TypeScript
import { getRegisteredRuntimeAPIs } from '@/contexts/runtimeAPIRegistry';
|
|
|
|
/**
|
|
* Utility for opening external URLs with Tauri shell support.
|
|
* In desktop runtime, uses tauri.shell.open() for proper system browser handling.
|
|
* Falls back to window.open() for web runtime.
|
|
*/
|
|
|
|
type TauriShell = {
|
|
shell?: {
|
|
open?: (url: string) => Promise<unknown>;
|
|
};
|
|
};
|
|
|
|
const parseUrlSafely = (value: string): URL | null => {
|
|
try {
|
|
return new URL(value);
|
|
} catch {
|
|
return null;
|
|
}
|
|
};
|
|
|
|
export const isExternalHttpUrl = (url: string): boolean => {
|
|
const parsed = parseUrlSafely(url.trim());
|
|
if (!parsed) {
|
|
return false;
|
|
}
|
|
return parsed.protocol === 'http:' || parsed.protocol === 'https:';
|
|
};
|
|
|
|
/**
|
|
* Opens an external URL in the system browser.
|
|
* In Tauri desktop runtime, uses tauri.shell.open() for proper handling.
|
|
* Falls back to window.open() for web runtime.
|
|
*
|
|
* @param url - The URL to open
|
|
* @returns Promise<boolean> - true if the URL was opened successfully
|
|
*/
|
|
export const openExternalUrl = async (url: string): Promise<boolean> => {
|
|
if (typeof window === 'undefined') {
|
|
return false;
|
|
}
|
|
|
|
const target = url.trim();
|
|
if (!target) {
|
|
return false;
|
|
}
|
|
|
|
const parsed = parseUrlSafely(target);
|
|
if (!parsed) {
|
|
return false;
|
|
}
|
|
|
|
if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
|
|
return false;
|
|
}
|
|
|
|
const normalizedTarget = parsed.toString();
|
|
|
|
const runtimeApis = getRegisteredRuntimeAPIs();
|
|
if (runtimeApis?.runtime?.isVSCode && runtimeApis.vscode?.openExternalUrl) {
|
|
try {
|
|
await runtimeApis.vscode.openExternalUrl(normalizedTarget);
|
|
return true;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
const tauri = (window as unknown as { __TAURI__?: TauriShell }).__TAURI__;
|
|
if (tauri?.shell?.open) {
|
|
try {
|
|
await tauri.shell.open(normalizedTarget);
|
|
return true;
|
|
} catch {
|
|
// Fall through to window.open
|
|
}
|
|
}
|
|
|
|
try {
|
|
window.open(normalizedTarget, '_blank', 'noopener,noreferrer');
|
|
return true;
|
|
} catch {
|
|
return false;
|
|
}
|
|
};
|