Files

273 lines
10 KiB
JavaScript

import { contextBridge, ipcRenderer, webUtils } from "electron";
const NATIVE_DEEP_LINK_EVENT = "openwork:deep-link-native";
const NATIVE_MENU_OPEN_SETTINGS_EVENT = "openwork:native-menu:open-settings";
const NATIVE_MENU_TOGGLE_SIDEBAR_EVENT = "openwork:native-menu:toggle-sidebar";
const NATIVE_MENU_CHECK_UPDATES_EVENT = "openwork:native-menu:check-updates";
const NATIVE_MENU_ZOOM_EVENT = "openwork:native-menu:zoom";
const AUTOMATION_RUNNER_CREDENTIAL_REJECTED_EVENT = "openwork:automation-runner:credential-rejected";
function normalizePlatform(value) {
if (value === "darwin" || value === "linux") return value;
if (value === "win32") return "windows";
return "linux";
}
function applyShellDocumentMarkers() {
try {
const root = document?.documentElement;
if (!root) return false;
root.dataset.openworkShell = "electron";
root.classList.add("openwork-electron");
if (process.platform === "darwin") {
root.classList.add("openwork-platform-mac");
} else if (process.platform === "win32") {
root.classList.add("openwork-platform-windows");
} else if (process.platform === "linux") {
root.classList.add("openwork-platform-linux");
}
return true;
} catch {
return false;
}
}
function notifyMenuOverlayDismiss() {
ipcRenderer.send("openwork:menu-overlay:dismiss");
}
function installMenuOverlayDismissListeners() {
try {
const target = window;
target.addEventListener("pointerdown", notifyMenuOverlayDismiss, { capture: true });
target.addEventListener("wheel", notifyMenuOverlayDismiss, { capture: true, passive: true });
target.addEventListener("keydown", notifyMenuOverlayDismiss, { capture: true });
return true;
} catch {
return false;
}
}
let desktopBootstrap = null;
let desktopDistribution = null;
try {
desktopBootstrap = ipcRenderer.sendSync("openwork:desktop-bootstrap-sync");
desktopDistribution = ipcRenderer.sendSync("openwork:desktop-distribution-sync");
} catch {
desktopBootstrap = null;
desktopDistribution = null;
}
contextBridge.exposeInMainWorld("__OPENWORK_ELECTRON__", {
invokeDesktop(command, ...args) {
return ipcRenderer.invoke("openwork:desktop", command, ...args);
},
automationRunner: {
onCredentialRejected(callback) {
const handler = () => callback();
ipcRenderer.on(AUTOMATION_RUNNER_CREDENTIAL_REJECTED_EVENT, handler);
return () => ipcRenderer.removeListener(AUTOMATION_RUNNER_CREDENTIAL_REJECTED_EVENT, handler);
},
},
fileSystem: {
getPathForFile(file) {
return webUtils.getPathForFile(file);
},
},
shell: {
openExternal(url) {
return ipcRenderer.invoke("openwork:shell:openExternal", url);
},
relaunch() {
return ipcRenderer.invoke("openwork:shell:relaunch");
},
},
system: {
getArchitectureInfo() {
return ipcRenderer.invoke("openwork:system:architecture");
},
getMicrophoneStatus() {
return ipcRenderer.invoke("openwork:system:microphoneStatus");
},
askMicrophoneAccess() {
return ipcRenderer.invoke("openwork:system:askMicrophoneAccess");
},
},
migration: {
readSnapshot() {
return ipcRenderer.invoke("openwork:migration:read");
},
ackSnapshot() {
return ipcRenderer.invoke("openwork:migration:ack");
},
},
brandIcon: {
apply(url) {
return ipcRenderer.invoke("openwork:desktop", "__applyBrandIcon", url ?? null);
},
getState() {
return ipcRenderer.invoke("openwork:desktop", "__getBrandIconState");
},
},
dev: {
evalRelaunch() {
return ipcRenderer.invoke("openwork:desktop", "__evalRelaunch");
},
},
nuke: {
preview(options) {
return ipcRenderer.invoke("openwork:desktop", "nukeOpenworkAndOpencodeConfigPreview", options);
},
execute(options) {
return ipcRenderer.invoke("openwork:desktop", "nukeOpenworkAndOpencodeConfigAndExit", options);
},
},
updater: {
getChannel() {
return ipcRenderer.invoke("openwork:updater:getChannel");
},
setChannel(channel) {
return ipcRenderer.invoke("openwork:updater:setChannel", channel);
},
check(channel, targetVersion) {
return ipcRenderer.invoke("openwork:updater:check", channel, targetVersion);
},
download() {
return ipcRenderer.invoke("openwork:updater:download");
},
installAndRestart() {
return ipcRenderer.invoke("openwork:updater:installAndRestart");
},
/** Subscribe to incremental download progress from electron-updater. */
onDownloadProgress(callback) {
const handler = (_event, data) => callback(data);
ipcRenderer.on("openwork:updater:download-progress", handler);
return () => {
ipcRenderer.removeListener("openwork:updater:download-progress", handler);
};
},
},
recovery: {
recordHealthy() {
return ipcRenderer.invoke("openwork:recovery:recordHealthy");
},
list(policy) {
return ipcRenderer.invoke("openwork:recovery:list", policy);
},
restorePrevious() {
return ipcRenderer.invoke("openwork:recovery:restorePrevious");
},
use(id) {
return ipcRenderer.invoke("openwork:recovery:use", id);
},
},
browser: {
show(bounds) { return ipcRenderer.invoke("openwork:browser:show", bounds); },
hide() { return ipcRenderer.invoke("openwork:browser:hide"); },
openUrl(url, provider) { return ipcRenderer.invoke("openwork:browser:openUrl", url, provider); },
navigate(url) { return ipcRenderer.invoke("openwork:browser:navigate", url); },
back() { return ipcRenderer.invoke("openwork:browser:back"); },
forward() { return ipcRenderer.invoke("openwork:browser:forward"); },
reload() { return ipcRenderer.invoke("openwork:browser:reload"); },
setBounds(bounds) { return ipcRenderer.invoke("openwork:browser:bounds", bounds); },
getState() { return ipcRenderer.invoke("openwork:browser:state"); },
createTab(url) { return ipcRenderer.invoke("openwork:browser:createTab", url); },
closeTab(tabId) { return ipcRenderer.invoke("openwork:browser:closeTab", tabId); },
closeAllTabs() { return ipcRenderer.invoke("openwork:browser:closeAllTabs"); },
selectTab(tabId) { return ipcRenderer.invoke("openwork:browser:selectTab", tabId); },
reorderTabs(tabIds) { return ipcRenderer.invoke("openwork:browser:reorderTabs", tabIds); },
listTabs() { return ipcRenderer.invoke("openwork:browser:listTabs"); },
setProxy(proxy) { return ipcRenderer.invoke("openwork:browser:setProxy", proxy); },
getProxy() { return ipcRenderer.invoke("openwork:browser:getProxy"); },
showTabContextMenu(tabId, point) { return ipcRenderer.invoke("openwork:browser:tabContextMenu", tabId, point); },
destroy() { return ipcRenderer.invoke("openwork:browser:destroy"); },
onStateChange(callback) {
const handler = (_event, state) => callback(state);
ipcRenderer.on("openwork:browser:state", handler);
return () => ipcRenderer.removeListener("openwork:browser:state", handler);
},
onPanelOpened(callback) {
const handler = () => callback();
ipcRenderer.on("openwork:browser:panel-opened", handler);
return () => ipcRenderer.removeListener("openwork:browser:panel-opened", handler);
},
onPanelClosed(callback) {
const handler = () => callback();
ipcRenderer.on("openwork:browser:panel-closed", handler);
return () => ipcRenderer.removeListener("openwork:browser:panel-closed", handler);
},
},
terminal: {
create(options) { return ipcRenderer.invoke("openwork:terminal:create", options); },
write(terminalId, data) { return ipcRenderer.invoke("openwork:terminal:write", terminalId, data); },
resize(terminalId, cols, rows) { return ipcRenderer.invoke("openwork:terminal:resize", terminalId, cols, rows); },
kill(terminalId) { return ipcRenderer.invoke("openwork:terminal:kill", terminalId); },
onData(callback) {
const handler = (_event, payload) => callback(payload);
ipcRenderer.on("openwork:terminal:data", handler);
return () => ipcRenderer.removeListener("openwork:terminal:data", handler);
},
onExit(callback) {
const handler = (_event, payload) => callback(payload);
ipcRenderer.on("openwork:terminal:exit", handler);
return () => ipcRenderer.removeListener("openwork:terminal:exit", handler);
},
},
meta: {
desktopBootstrap,
distribution: desktopDistribution,
initialDeepLinks: [],
platform: normalizePlatform(process.platform),
version: process.versions.electron,
evalFatalBootstrapFailure: process.env.OPENWORK_EVAL_FATAL_DESKTOP_BOOTSTRAP_FAILURE ?? null,
},
});
if (
process.env.OPENWORK_EVAL_FATAL_DESKTOP_BOOTSTRAP_FAILURE
&& (process.env.OPENWORK_EVAL_RECOVERY_CANDIDATES || process.env.OPENWORK_EVAL_RECOVERY_RELEASES)
) {
contextBridge.exposeInMainWorld("__openworkRecoveryControl", {
snapshot() {
return ipcRenderer.invoke("openwork:recovery:evalSnapshot");
},
select(id) {
return ipcRenderer.invoke("openwork:recovery:use", id);
},
});
}
ipcRenderer.on(NATIVE_DEEP_LINK_EVENT, (_event, urls) => {
if (typeof window === "undefined") return;
window.dispatchEvent(new CustomEvent(NATIVE_DEEP_LINK_EVENT, { detail: urls }));
});
ipcRenderer.on(NATIVE_MENU_OPEN_SETTINGS_EVENT, () => {
if (typeof window === "undefined") return;
window.dispatchEvent(new Event(NATIVE_MENU_OPEN_SETTINGS_EVENT));
});
ipcRenderer.on(NATIVE_MENU_TOGGLE_SIDEBAR_EVENT, () => {
if (typeof window === "undefined") return;
window.dispatchEvent(new Event(NATIVE_MENU_TOGGLE_SIDEBAR_EVENT));
});
ipcRenderer.on(NATIVE_MENU_CHECK_UPDATES_EVENT, () => {
if (typeof window === "undefined") return;
window.dispatchEvent(new Event(NATIVE_MENU_CHECK_UPDATES_EVENT));
});
ipcRenderer.on(NATIVE_MENU_ZOOM_EVENT, (_event, action) => {
if (typeof window === "undefined") return;
window.dispatchEvent(new CustomEvent(NATIVE_MENU_ZOOM_EVENT, { detail: action }));
});
if (!applyShellDocumentMarkers() && typeof document !== "undefined") {
document.addEventListener("DOMContentLoaded", applyShellDocumentMarkers, { once: true });
}
if (!installMenuOverlayDismissListeners() && typeof document !== "undefined") {
document.addEventListener("DOMContentLoaded", installMenuOverlayDismissListeners, { once: true });
}