-
Notifications
You must be signed in to change notification settings - Fork 301
Bugfix/open new file after close #1246
Bugfix/open new file after close #1246
Conversation
main/src/menu.ts
Outdated
@@ -23,20 +23,39 @@ export const buildMenu = (mainWindow, loadInit) => { | |||
// for VIM as it sees escape keys. | |||
const normalizePath = (fileName) => fileName.split("\\").join("/") | |||
|
|||
const executeVimCommand = (command) => mainWindow.webContents.send("menu-item-click", command) | |||
const ensureWindow = (currentWindow: BrowserWindow) => { | |||
return !!currentWindow ? currentWindow : createWindow([], process.cwd()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm wondering if this should return a Promise
? In other words - I'm not sure if we will properly handle all of the commands we send if we are sending them immediately when the window is created. I believe we might need to wait for the window to be fully initialized before we send some of these commands.
An example of this would be menu-item-click
and open-files
- these are listened for in the NeovimEditor
class, which might take a bit of time after opening to be initialized and start listening for those commands.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bryphe thats definitely the case the issue I encountered, my thought though is that the initialisation just triggers an event which then sets off other async processes but the createWindow function itself from what I can see is sync, I'm not entirely sure how to make it wait, an arbitrary timeout would be a messy/hacky solution, I thought maybe of having the ipcMain process send an event when neovim is initialised and then responding to it in an event handler in the main process sort of the reverse of what we've been doing for the most part so outside in, not sure if thats possible
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah ok, luckily for us, there is a way we can make createWindow
async - or at least return a Promise
- to help us out here.
I thought maybe of having the ipcMain process send an event when neovim is initialised and then responding to it in an event handler in the main process sort of the reverse of what we've been doing for the most part so outside in, not sure if thats possible
Yes, definitely - this is a good idea!
We already hook an event today to figure out when the initialization happens:
Line 141 in c01ae06
mainWindow.webContents.send("init", { |
What we could do is the following:
- From
createWindow
, we return aPromise
- In that
did-finish-load
handler (or our handler we add), we resolve the promise we returned - We gate the command handlers on the
createWindow
promise (usingawait
)
That should be enough to make things work. If the timing still isn't quite right, we could send an explicit event from the browser process -> to the main process letting it know that we're completely initialized.
As you mentioned, though, we might want to explicitly send a message up from the renderer process. We could do that somewhere here:
Line 139 in c01ae06
Performance.endMeasure("Oni.Start.Activate") |
And have the main process listen for that event, in order to resolve the promise.
Hope that helps give you some ideas - let me know if you have any questions on the specifics. I think we can get this working though 👍
@bryphe I've taken a different tack to what you suggested as I'm not sure I follow unfortunately specifically re the promise. What i've done is create an optional third argument for the window function which are delayed events, so that in the menu I pass the delayed events in case a window doesn't exist then call them once an As things stand the did finish load handler is inside the create window function but moreover the |
@@ -151,6 +151,7 @@ const start = async (args: string[]): Promise<void> => { | |||
checkForUpdates() | |||
|
|||
Performance.endMeasure("Oni.Start") | |||
ipcRenderer.send("Oni.started", "started") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This approach looks great to me - thanks @Akin909 !
main/src/main.ts
Outdated
@@ -144,6 +153,14 @@ export function createWindow(commandLineArguments, workingDirectory) { | |||
}) | |||
}) | |||
|
|||
ipcMain.on("Oni.started", (evt) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at this - I'm wondering, will this be called for every window? In other words, if createWindow
is called multiple times, will this event get registered multiple times, and send the delayedEvent
multiple times to mainWindow
?
I'm wondering if this should be ipcMain.once
instead of ipcMain.on
to protect against this. The existing rebuild-menu
event might have the same issue, too, but it seems less critical. For this event, it seems like if we call createWindow
with a delayed event, and then we call it again with no delayedEvent, the listener in the first createWindow
call would send us that original delayedEvent
again, to the new window.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah @bryphe right on the money 👍 I had noticed this quirk yesterday and wasn't sure what it was and wracking my brain as to what to do did not realise there was a once
method which fully resolves that so that delayed events are only called once (what I was getting was open file of a closed window click open new file which works but then close that window and click again and the same command would execute, using once
however resolves that).
oni.sh
Outdated
@@ -14,15 +14,15 @@ self=$0 | |||
OPEN_DIRECTORY="$PWD" | |||
|
|||
# test if $self is a symlink | |||
if [ -L $self ] ; then | |||
if [ -L "$self" ] ; then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the purpose of these changes to oni.sh
? Are they related to the menu changes, or fixing a different bug? Just curious.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bryphe potential overzealousness on my part I use shellcheck
to lint shell scripts and an error it flagged on multiple lines was that those variable were not quoted which helps prevent word splitting and globbing the link is to a wiki page where the rationale for that is explained, I initially made that change because I thought that script wasn't working and was what had led to the file args not being passed to oni on open. I'm more than happy to take them out since its not really (as far as I can tell related to the mac os no file args issue)
Seems like a reasonable approach to me, thanks @Akin909 !
I think the way you have it set up is fine - the only concern I have is that since we are hooking the |
Just tested this out - looks like it's working great. Thanks for reverting the Looks like we may finally be able to close #484 with this 👍 Thanks for the contribution, @Akin909 ! Bringing it in now. |
This PR handles cases where the
mainWindow
has been closed and user attempts to run a menubar function likenew file
orcopy
(relates #1193). Note that for commands that require an initialised oni it will not carry out those commands such assplit window
etc. it just defaults to opening a window so there is no error.It replicates
vscode
's functionality which simply opens a new window which seems the easiest solution to me. A more adventurous possible solution to this could be passing thecreateWindow
function a third argument of events(and their arguments) to execute once the app has loaded 😟Update: tried the alternative method I mentioned above but it does not work unfortunately