244 lines
7.4 KiB
JavaScript
244 lines
7.4 KiB
JavaScript
"use strict";
|
|
|
|
// Compatibility shim for legacy Atom packages that do `require('remote')`.
|
|
//
|
|
// Old Electron exposed the `remote` module and Atom packages frequently used:
|
|
// const remote = require('remote')
|
|
// const dialog = remote.dialog || remote.require('dialog')
|
|
//
|
|
// Newer Electron removed `remote` by default. Pulsar may provide @electron/remote
|
|
// or alternative dialog helpers via Atom's application delegate.
|
|
|
|
function getElectron() {
|
|
try {
|
|
// Available in renderer.
|
|
return require("electron");
|
|
} catch (_) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function getRemote() {
|
|
const electron = getElectron();
|
|
if (electron && electron.remote) return electron.remote;
|
|
try {
|
|
// Some apps (incl. Pulsar/Atom forks) ship this.
|
|
return require("@electron/remote");
|
|
} catch (_) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function getAtomDialogDelegate() {
|
|
try {
|
|
if (typeof atom !== "undefined" && atom && atom.applicationDelegate) {
|
|
return atom.applicationDelegate;
|
|
}
|
|
} catch (_) {
|
|
// ignore
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function toOldCallback(result, callback) {
|
|
// Electron >= 7 showSaveDialog returns { canceled, filePath }
|
|
if (!callback) return;
|
|
if (!result || result.canceled) return callback(undefined);
|
|
return callback(result.filePath);
|
|
}
|
|
|
|
function wrapDialog(dialog) {
|
|
if (!dialog) return null;
|
|
|
|
// Ensure callback-style APIs exist.
|
|
if (typeof dialog.showSaveDialog === "function") {
|
|
const original = dialog.showSaveDialog.bind(dialog);
|
|
dialog.showSaveDialog = function showSaveDialogCompat(browserWindow, options, callback) {
|
|
// Legacy call pattern: (win, options, cb)
|
|
if (typeof options === "function") {
|
|
callback = options;
|
|
options = browserWindow;
|
|
browserWindow = undefined;
|
|
}
|
|
|
|
try {
|
|
const maybePromise = original(browserWindow, options);
|
|
if (maybePromise && typeof maybePromise.then === "function") {
|
|
return maybePromise.then((res) => {
|
|
toOldCallback(res, callback);
|
|
return res;
|
|
});
|
|
}
|
|
// Some older implementations support the callback directly.
|
|
if (typeof callback === "function") return original(browserWindow, options, callback);
|
|
return maybePromise;
|
|
} catch (err) {
|
|
if (typeof callback === "function") return callback(undefined);
|
|
throw err;
|
|
}
|
|
};
|
|
}
|
|
|
|
if (typeof dialog.showMessageBox === "function") {
|
|
const original = dialog.showMessageBox.bind(dialog);
|
|
dialog.showMessageBox = function showMessageBoxCompat(browserWindow, options, callback) {
|
|
if (typeof options === "function") {
|
|
callback = options;
|
|
options = browserWindow;
|
|
browserWindow = undefined;
|
|
}
|
|
|
|
// Legacy Atom/Electron usage sometimes expects a *synchronous* numeric response.
|
|
// Prefer sync primitives when no callback is provided.
|
|
if (typeof callback !== "function") {
|
|
try {
|
|
if (typeof dialog.showMessageBoxSync === "function") {
|
|
return dialog.showMessageBoxSync(browserWindow, options);
|
|
}
|
|
if (typeof atom !== "undefined" && atom && typeof atom.confirm === "function") {
|
|
return atom.confirm({
|
|
message: (options && (options.title || options.message)) || "",
|
|
detailedMessage: options && options.title && options.message ? options.message : undefined,
|
|
buttons: (options && options.buttons) || ["OK"],
|
|
});
|
|
}
|
|
} catch (_) {
|
|
// Fall through to async implementation.
|
|
}
|
|
}
|
|
try {
|
|
const maybePromise = original(browserWindow, options);
|
|
if (maybePromise && typeof maybePromise.then === "function") {
|
|
return maybePromise.then((res) => {
|
|
if (typeof callback === "function") {
|
|
// Electron returns { response, checkboxChecked }
|
|
callback(res && typeof res.response === "number" ? res.response : res);
|
|
}
|
|
return res;
|
|
});
|
|
}
|
|
if (typeof callback === "function") return original(browserWindow, options, callback);
|
|
return maybePromise;
|
|
} catch (err) {
|
|
if (typeof callback === "function") return callback(0);
|
|
throw err;
|
|
}
|
|
};
|
|
}
|
|
|
|
return dialog;
|
|
}
|
|
|
|
const remote = getRemote();
|
|
const electron = getElectron();
|
|
|
|
let dialog = null;
|
|
if (remote && remote.dialog) dialog = remote.dialog;
|
|
else if (electron && electron.dialog) dialog = electron.dialog;
|
|
|
|
const atomDelegate = getAtomDialogDelegate();
|
|
if (!dialog && atomDelegate) {
|
|
// Atom/Pulsar delegate methods are typically Promise-based.
|
|
dialog = {
|
|
showSaveDialog(browserWindow, options, callback) {
|
|
try {
|
|
const p = atomDelegate.showSaveDialog ? atomDelegate.showSaveDialog(options) : null;
|
|
if (p && typeof p.then === "function") {
|
|
return p.then((filePath) => {
|
|
if (typeof callback === "function") callback(filePath);
|
|
return { canceled: !filePath, filePath };
|
|
});
|
|
}
|
|
if (typeof callback === "function") callback(undefined);
|
|
return { canceled: true, filePath: undefined };
|
|
} catch (err) {
|
|
if (typeof callback === "function") callback(undefined);
|
|
return { canceled: true, filePath: undefined };
|
|
}
|
|
},
|
|
showMessageBox(browserWindow, options, callback) {
|
|
try {
|
|
const p = atomDelegate.showMessageBox ? atomDelegate.showMessageBox(options) : null;
|
|
if (p && typeof p.then === "function") {
|
|
return p.then((response) => {
|
|
if (typeof callback === "function") callback(response);
|
|
return { response };
|
|
});
|
|
}
|
|
if (typeof callback === "function") callback(0);
|
|
return { response: 0 };
|
|
} catch (err) {
|
|
if (typeof callback === "function") callback(0);
|
|
return { response: 0 };
|
|
}
|
|
},
|
|
};
|
|
}
|
|
|
|
// Absolute last-resort fallback: avoid hard crashes if no dialog backend exists.
|
|
if (!dialog) {
|
|
dialog = {
|
|
showSaveDialog(browserWindow, options, callback) {
|
|
try {
|
|
if (atomDelegate && typeof atomDelegate.showSaveDialog === "function") {
|
|
const p = atomDelegate.showSaveDialog(options);
|
|
if (p && typeof p.then === "function") {
|
|
return p.then((filePath) => {
|
|
if (typeof callback === "function") callback(filePath);
|
|
return { canceled: !filePath, filePath };
|
|
});
|
|
}
|
|
}
|
|
} catch (_) {
|
|
// ignore
|
|
}
|
|
if (typeof callback === "function") callback(undefined);
|
|
return { canceled: true, filePath: undefined };
|
|
},
|
|
showMessageBox(browserWindow, options, callback) {
|
|
try {
|
|
if (typeof atom !== "undefined" && atom && typeof atom.confirm === "function") {
|
|
const response = atom.confirm({
|
|
message: (options && (options.title || options.message)) || "",
|
|
detailedMessage: options && options.title && options.message ? options.message : undefined,
|
|
buttons: (options && options.buttons) || ["OK"],
|
|
});
|
|
if (typeof callback === "function") callback(response);
|
|
return response;
|
|
}
|
|
} catch (_) {
|
|
// ignore
|
|
}
|
|
if (typeof callback === "function") callback(0);
|
|
return 0;
|
|
},
|
|
};
|
|
}
|
|
|
|
dialog = wrapDialog(dialog);
|
|
|
|
function remoteRequire(moduleName) {
|
|
if (remote && typeof remote.require === "function") return remote.require(moduleName);
|
|
if (moduleName === "dialog") return dialog;
|
|
// Best-effort: some old code asks for 'browser-window', etc.
|
|
if (electron) {
|
|
if (moduleName === "browser-window" || moduleName === "BrowserWindow") return electron.BrowserWindow;
|
|
if (moduleName === "app") return electron.app;
|
|
}
|
|
throw new Error("remote.require not available for: " + moduleName);
|
|
}
|
|
|
|
module.exports = {
|
|
dialog,
|
|
require: remoteRequire,
|
|
getCurrentWindow: (remote && typeof remote.getCurrentWindow === "function")
|
|
? remote.getCurrentWindow.bind(remote)
|
|
: function () {
|
|
try {
|
|
return typeof atom !== "undefined" && atom.getCurrentWindow ? atom.getCurrentWindow() : undefined;
|
|
} catch (_) {
|
|
return undefined;
|
|
}
|
|
},
|
|
};
|