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

platform reload #243

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
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: 1 addition & 1 deletion constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ exports.WAKEUP = toPath(new URL(BIN + WAKEUP_EXEC, swapURL))
exports.RUNTIME = toPath(new URL(BIN + RUNTIME_EXEC, swapURL))
exports.DESKTOP_RUNTIME = toPath(new URL(BIN + DESKTOP_EXEC, swapURL))

exports.BARE_RESTART_EXIT_CODE = 75
exports.RESTART_EXIT_CODE = 75

function electronModuleURL () {
const u = pathToFileURL(process.execPath)
Expand Down
3 changes: 1 addition & 2 deletions decal.html
Original file line number Diff line number Diff line change
Expand Up @@ -546,8 +546,7 @@ <h1 id="header">Unknown app</h1>
}
if (name === 'action') {
const cta = this.shadowRoot.querySelector('#cta')
const code = (value === 'reload') ? 64 : 0
const handler = (value === 'quit' || value === 'reload') ?
const handler = (value === 'quit') ?
() => Pear.exit(code) :
() => {}
cta.addEventListener('click', handler)
Expand Down
6 changes: 2 additions & 4 deletions electron-main.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,8 @@ async function electronMain (cmd) {

electron.ipcMain.on('send-to', (e, id, channel, message) => { electron.webContents.fromId(id)?.send(channel, message) })

const app = await gui.app()
app.unloading().then(async () => {
await app.close()
}) // note: would be unhandled rejection on failure, but should never fail
await gui.app()

}

function configureElectron () {
Expand Down
87 changes: 64 additions & 23 deletions gui/gui.js
Original file line number Diff line number Diff line change
Expand Up @@ -374,16 +374,35 @@ class App {
state = null
ipc = null
id = null
session = null
handle = null
closing = null
closed = false
appReady = false
static root = unixPathResolve(resolve(__dirname, '..'))

constructor (state, ipc) {
constructor (state, ipc, gui) {
this.state = state
this.ipc = ipc
this.gui = gui
this.contextMenu = null

this.ipc.messages({ type: 'pear/reload' }).once('data', async () => {
const lockWait = ipc.waitForLock()
await this.ipc.close()
console.log('ipc closed')
console.log('waiting for lock')
await lockWait
console.log('sidecar closed')
const id = 'todo'
this.state.id = id
this.session.setUserAgent(`Pear ${id}`)
console.log('now trigger app start and update electron + useragent with new startid')
console.log('then tell views to location.reload')
//location.reload()
})


electron.app.on('browser-window-focus', () => { this.menu.devtoolsReloaderUnlisten() })

electron.app.on('child-process-gone', (e, details) => {
Expand Down Expand Up @@ -436,6 +455,7 @@ class App {
})
})
this.menu = new Menu(this)

}

async report ({ err }) {
Expand Down Expand Up @@ -577,7 +597,7 @@ class App {
}
}
},
afterNativeWindowClose: () => this.close(),
afterClose: () => this.close(),
afterNativeViewCreated: devtools && ((app) => {
if (trace) return
app.view.webContents.openDevTools({ mode: 'detach' })
Expand Down Expand Up @@ -612,7 +632,9 @@ class App {
}
})
this.id = ctrl.id
this.session = ctrl.session
await this.starting
this.unloading() // note: would be unhandled rejection on failure, but should never fail
} catch (err) {
await this.report({ err })
this.close()
Expand All @@ -626,7 +648,12 @@ class App {
return { fork, length, key: key ? key.toString('hex') : null }
}

unloading () { return this.ipc.unloading() }
async unloading () {
const action = await this.ipc.unloading()
for (const ctrl of PearGUI.ctrls()) ctrl.unload(action)
if (action.type === 'teardown') await this.ipc.close()
return action
}

close (maxWait = 5500) {
if (this.closing) return this.closing
Expand Down Expand Up @@ -862,16 +889,17 @@ class GuiCtrl {

async close () {
if (this.closed) return true
console.log('this.unload', this.unload)
if (this.unload) {
this.unload({ type: 'close' })
await this.unloader
}
let closer = null
if (this.win) {
closer = once(this.win, 'closed')
this.win.close()
}
await closer
// let closer = null
// if (this.win) {
// closer = once(this.win, 'closed')
// this.win.close()
// }
// await closer
this.constructor[kMap].delete(this.id)
this.id = null
this.win = null
Expand Down Expand Up @@ -917,21 +945,25 @@ class GuiCtrl {
async unloading () {
if (!this.#unloading) this.#unloading = this._unloading()
try {
return await this.#unloading
const xxx = await this.#unloading
console.log('???', xxx)
return xxx
} finally {
console.log('UNLDD')
this.#unloading = null
}
}

async _unloading () {
const { webContents } = (this.view || this.win)
const until = new Promise((resolve) => { this.unload = resolve })
webContents.once('will-navigate', (e, url) => {
const willNavListener = (e, url) => {
if (!url.startsWith(this.sidecar)) return // handled by the other will-navigate handler
e.preventDefault()
const type = (!e.frame || e.frame.url === url) ? 'reload' : 'nav'
this.unload({ type, url })
})
}
webContents.once('will-navigate', willNavListener)

const closeListener = (e) => {
e.preventDefault()
Expand All @@ -940,16 +972,20 @@ class GuiCtrl {
}
}
if (this.win) this.win.once('close', closeListener)
webContents.removeListener('will-navigate', willNavListener)
this.unloader = new Promise((resolve) => { this.unloaded = resolve })
const action = await until
console.log('ACTION', action)
if (this.win) this.win.removeListener('close', closeListener)
this.unload = null
return action
}

completeUnload (action) {
async completeUnload (action) {
this.unloaded()
if (action.type === 'close') this.close()
console.log('complete unload', action)
// await this.close()
// if (action.type === 'close') this.close()
}

setWindowButtonPosition (point) {
Expand Down Expand Up @@ -1025,11 +1061,8 @@ class Window extends GuiCtrl {
this.win.on('close', () => {
this.closing = true
})

this.win.on('closed', () => {
if (typeof options.afterNativeWindowClose === 'function') {
options.afterNativeWindowClose(this)
}
if (typeof options.afterClose === 'function') options.afterClose(this)
if (this.win) {
if (this.opening) this.opening = false
this.win.closed = true
Expand Down Expand Up @@ -1408,7 +1441,10 @@ class PearGUI extends ReadyResource {
})
this.worker = new Worker()
this.pipes = new Freelist()
this.ipc.once('close', () => this.close())
this.ipc.once('close', () => {
console.log('IPC CLOSED')
// this.close()
})

electron.ipcMain.on('exit', (e, code) => { process.exit(code) })

Expand Down Expand Up @@ -1439,14 +1475,17 @@ class PearGUI extends ReadyResource {
messages.on('end', () => event.reply('messages', null))
})

electron.ipcMain.handle('waitForLock', () => this.ipc.waitForLock())
electron.ipcMain.handle('close', () => this._close())

electron.ipcMain.handle('getMediaAccessStatus', (evt, ...args) => this.getMediaAccessStatus(...args))
electron.ipcMain.handle('askForMediaAccess', (evt, ...args) => this.askForMediaAccess(...args))
electron.ipcMain.handle('desktopSources', (evt, ...args) => this.desktopSources(...args))
electron.ipcMain.handle('chrome', (evt, ...args) => this.chrome(...args))
electron.ipcMain.handle('ctrl', (evt, ...args) => this.ctrl(...args))
electron.ipcMain.handle('parent', (evt, ...args) => this.parent(...args))
electron.ipcMain.handle('open', (evt, ...args) => this.open(...args))
electron.ipcMain.handle('close', (evt, ...args) => this.guiClose(...args))
electron.ipcMain.handle('guiClose', (evt, ...args) => this.guiClose(...args))
electron.ipcMain.handle('show', (evt, ...args) => this.show(...args))
electron.ipcMain.handle('hide ', (evt, ...args) => this.hide(...args))
electron.ipcMain.handle('minimize', (evt, ...args) => this.minimize(...args))
Expand Down Expand Up @@ -1529,8 +1568,8 @@ class PearGUI extends ReadyResource {
}

async app () {
const app = new App(this.state, this.ipc)
this.once('close', async () => { app.quit() })
const app = new App(this.state, this.ipc, this)
// this.once('close', async () => { app.quit() })
await app.start()
return app
}
Expand All @@ -1540,7 +1579,9 @@ class PearGUI extends ReadyResource {
}

async _close () {
console.log('calling ipc close')
await this.ipc.close()
console.log('ipc close done')
}

static async ctrl (type, entry, { state, parentId = 0, ua, sessname = null, appkin }, options = {}, openOptions = {}) {
Expand Down Expand Up @@ -1617,7 +1658,7 @@ class PearGUI extends ReadyResource {
}
}

async askForMediaAccess ({ id, media }) {
async askForMediaAccess ({ media }) {
if (isLinux || isWindows) return false
if (media === 'screen') {
return electron.systemPreferences.getMediaAccessStatus(media)
Expand Down
41 changes: 36 additions & 5 deletions gui/preload.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,19 @@ module.exports = class PearGUI extends ReadyResource {
})

const onteardown = async (fn) => {
if (state.isDecal) return
await this.ready()
const action = await this.ipc.unloading({ id }) // only resolves when unloading occurs
await fn()
await this.ipc.completeUnload({ id, action })
if (action.type === 'teardown') {
console.log('onteardown ipc close')
await this.ipc.closeIPC()
console.log('onteardown ipc closed')
}
if (action.type === 'reload') location.reload()
else if (action.type === 'nav') location.href = action.url
}
const gui = this
API = class extends API {
constructor (ipc, state, onteardown) {
super(ipc, state, onteardown)
Expand All @@ -45,6 +50,18 @@ module.exports = class PearGUI extends ReadyResource {
desktopSources: (options = {}) => ipc.desktopSources(options)
}

// if (state.isDecal === false) ipc.messages({ type: 'pear/reload' }).once('data', async () => {
// const lockWait = ipc.waitForLock()
// await gui.close()
// console.log('ipc closed')
// console.log('waiting for lock')
// await lockWait
// console.log('sidecar closed')
// console.log('now wait trigger app start and update electron with new startid')
// console.log('ok so call location.reload')
// //location.reload()
// })

const kGuiCtrl = Symbol('gui:ctrl')

class Parent extends EventEmitter {
Expand Down Expand Up @@ -213,13 +230,26 @@ module.exports = class PearGUI extends ReadyResource {
this.View = View
}

reload = async function (opts) {
if (opts?.platform) return this._reload(opts)
location.reload()
}

exit = (code) => {
process.exitCode = code
electron.ipcRenderer.sendSync('exit', code)
}
}
this.api = new API(this.ipc, state, onteardown)
}

_close () {

// NEED TO TELL PARENT PROCESS TO CLOSE ITS IPC AS WELL SOMEHOW

console.trace('PRELOAD _close')
return this.ipc.closeIPC()
}
}

class IPC {
Expand All @@ -230,7 +260,7 @@ class IPC {
ctrl (...args) { return electron.ipcRenderer.invoke('ctrl', ...args) }
parent (...args) { return electron.ipcRenderer.invoke('parent', ...args) }
open (...args) { return electron.ipcRenderer.invoke('open', ...args) }
close (...args) { return electron.ipcRenderer.invoke('close', ...args) }
close (...args) { return electron.ipcRenderer.invoke('guiClose', ...args) }
show (...args) { return electron.ipcRenderer.invoke('show', ...args) }
hide (...args) { return electron.ipcRenderer.invoke('hide', ...args) }
minimize (...args) { return electron.ipcRenderer.invoke('minimize', ...args) }
Expand Down Expand Up @@ -307,14 +337,14 @@ class IPC {
stream.emit('error', new Error('Worker PipeError (from electron-main): ' + stack))
})
electron.ipcRenderer.on('workerClose', () => { stream.destroy() })
stream.once('close', () => {
electron.ipcRenderer.send('workerPipeClose', id)
})
stream.once('close', () => { electron.ipcRenderer.send('workerPipeClose', id) })

electron.ipcRenderer.on('workerPipeData', (e, data) => { stream.push(data) })
return stream
}

waitForLock () { return electron.ipcRenderer.invoke('waitForLock') }
closeIPC () { return electron.ipcRenderer.invoke('close') }
ref () {}
unref () {}

Expand All @@ -340,4 +370,5 @@ class IPC {
electron.ipcRenderer.on('iteratePreferences', (e, data) => { stream.push(data) })
return stream
}

}
19 changes: 7 additions & 12 deletions lib/api.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict'
const Worker = require('./worker')
const { BARE_RESTART_EXIT_CODE } = require('../constants')
const { RESTART_EXIT_CODE } = require('../constants')
const noop = () => {}
const teardown = global.Bare ? require('./teardown') : noop
const program = global.Bare || global.process
Expand Down Expand Up @@ -97,22 +97,17 @@ class API {
versions = () => this.#reftrack(this.#ipc.versions())

restart = async (opts = {}) => {
const restart = this.#reftrack(this.#ipc.restart({ ...opts, hard: true }))
const restart = this.#reftrack(this.#ipc.restart({ ...opts }))
return restart
}

reload = async (opts = {}) => {
if (!opts.platform) {
// TODO: use Pear.shutdown when it lands instead
if (this.#state.type === 'terminal') Bare.exit(BARE_RESTART_EXIT_CODE)
else global.location.reload()

return
}

return this.#reftrack(this.#ipc.restart({ ...opts, hard: false }))
async _reload (opts = {}) {
if (opts.platform) return this.#reftrack(this.#ipc.restart({ ...opts, reload: true }))
this.exit(RESTART_EXIT_CODE)
}

reload = (opts = {}) => this._reload(opts)

updates = (listener) => this.messages({ type: 'pear/updates' }, listener)

wakeups = (listener) => this.messages({ type: 'pear/wakeup' }, listener)
Expand Down
Loading
Loading