Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugfixes and API changes for updated Electron #309

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
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
21 changes: 17 additions & 4 deletions src/AtomShell/main.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const {app, BrowserWindow} = require('electron')
var net = require("net");
const { app, BrowserWindow, ipcMain, dialog } = require('electron');
const net = require("net");
const path = require("path");

function arg(name) {
for (var i = 0; i < process.argv.length; i++) {
Expand Down Expand Up @@ -70,14 +71,26 @@ var port = parseInt(arg('port'));
server.listen(port);

app.on("ready", function() {
app.on('window-all-closed', function(e) {
});
app.on('window-all-closed', function(e) { /* */ });
ipcMain.handle("dialog:openFile", (evt, opts) => dialog.showOpenDialog(evt.sender.getOwnerBrowserWindow(), opts));
ipcMain.handle("dialog:saveFile", (evt, opts) => dialog.showSaveDialog(evt.sender.getOwnerBrowserWindow(), opts));
});

// Window creation
var windows = {};

function createWindow(opts) {
// Store the user defined preload script(s), if any, to pass to our preload script.
let userPreloads = opts.webPreferences?.preload ?? [];
// Merge in the required scripts as additionalArguments and overwrite preload.
opts.webPreferences = { ...opts.webPreferences, ...{
additionalArguments: [
...opts.webPreferences?.additionalArguments ?? [],
...(Array.isArray(userPreloads) ? userPreloads : [userPreloads]).map(f => `--blink-preloadjs=${f}`)
],
preload: path.join(__dirname, 'preload.js')
}};

var win = new BrowserWindow(opts);
windows[win.id] = win;
if (opts.url) {
Expand Down
22 changes: 22 additions & 0 deletions src/AtomShell/preload.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const { contextBridge, ipcRenderer } = require('electron');

/* This will execute require on the scripts given as arguments and ignore other args because the regex turns them empty (false) */
process.argv.map(str => str.replace(/((?:^--blink-preloadjs=)|(?:^.*$))/, '')).filter(Boolean).forEach(function (filepath) {
try {
require(filepath);
} catch (err) {
console.log(err);
}
});

const dialogHandlers = {
showOpenDialog: (opts, cb) => ipcRenderer.invoke("dialog:openFile", opts).then(res => cb(res.filePaths)),
showSaveDialog: (opts, cb) => ipcRenderer.invoke("dialog:saveFile", opts).then(res => cb(res.filePath)),
};

/* If a user disables contextIsolation we'll need to handle that. */
if (process.contextIsolated) {
contextBridge.exposeInMainWorld('dialog', dialogHandlers);
} else {
window.dialog = dialogHandlers;
}
16 changes: 13 additions & 3 deletions src/AtomShell/process.jl
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ end
import Base: Process

export Electron
const _electron = artifact"electronjs_app"

mutable struct Electron <: Shell
proc::Process
Expand All @@ -56,8 +57,15 @@ end

Electron(proc, sock) = Electron(proc, sock, Dict())

const _electron = artifact"electronjs_app"
const mainjs = resolve_blink_asset("src", "AtomShell", "main.js")
"""
resolve_electron_asset(path...)

Find a file, expressed as a relative path from the folder where
the Electron artifact was extracted. Example:

resolve_electron_asset("julia.png") -> /home/<user>/.julia/artifacts/<git-tree-sha1>/julia.png
"""
resolve_electron_asset(path...) = abspath(joinpath(_electron, path...))

function electron()
if Sys.isapple()
Expand All @@ -82,11 +90,13 @@ function try_connect(args...; interval = 0.01, attempts = 500)
end
end

const mainjs = resolve_blink_asset("src", "AtomShell", "main.js")

function init(; debug = false)
electron() # Check path exists
p, dp = port(), port()
debug && inspector(dp)
dbg = debug ? "--debug=$dp" : []
dbg = debug ? "--inspect=$dp" : []
proc = (debug ? run_rdr : run)(`$(electron()) $dbg $mainjs port $p`; wait=false)
conn = try_connect(ip"127.0.0.1", p)
shell = Electron(proc, conn)
Expand Down
19 changes: 15 additions & 4 deletions src/AtomShell/window.jl
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,26 @@ function Window end
shell(win::Window) = win.shell
id(win::Window) = win.id

# Deep merge code adapted from the Discourse solutions given by
# @hhaensel (https://discourse.julialang.org/t/multi-layer-dict-merge/27261/6), and
# @MilesCranmer (https://discourse.julialang.org/t/multi-layer-dict-merge/27261/7)
recursive_merge(x::AbstractDict...) = merge(recursive_merge, x...)
#recursive_merge(x::AbstractVector...) = reduce(vcat, x)
recursive_merge(x...) = last(x)
# Whether or not we decide that vectors should be merged depends on the window_defaults.
# Currently disabled (e.g. replace Vector values instead of concatenating them)

const window_defaults = Dict(
:url => "about:blank",
:title => "Julia",
"node-integration" => false,
"use-content-size" => true,
:icon => resolve_blink_asset("deps", "julia.png")
:icon => resolve_electron_asset("julia.png"),
:webPreferences => Dict(
:nodeIntegration => false,
:useContentSize => true
)
)

raw_window(a::Electron, opts) = @js a createWindow($(merge(window_defaults, opts)))
raw_window(a::Electron, opts) = @js a createWindow($(mergewith(recursive_merge, window_defaults, opts)))

function Window(a::Shell, opts::AbstractDict = Dict(); async=false, body=nothing)
# TODO: Custom urls don't support async b/c don't load Blink.js. (Same as https://github.com/JunoLab/Blink.jl/issues/150)
Expand Down