-
Notifications
You must be signed in to change notification settings - Fork 568
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
Fix: only focus editor if search field is not focused #2531
Conversation
|
8f6ed5d
to
80510a7
Compare
@belcherj I updated this to directly check I'm not sold about triggering |
lib/note-content-editor.tsx
Outdated
this.focusEditor(); | ||
if (document?.activeElement?.id !== 'search-field') { | ||
this.focusEditor(); | ||
} |
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.
there are many ways this can go wrong, far more than the one way it can go right.
we should maybe formalize the rules for changing focus and then see if a more elegant solution drops out. maybe there's some global (Redux) state value tracking what context we're in that changes when we enter
or blur
the search field…
maybe we only care about the initial load? that is, we should grab this.focusEditor()
unless the search bar has already been focused, something we could grab from Redux or from a window-global value - a latch that only turns on the first time the search field is focused.
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.
Okay, I will revisit. I agree that we should change the focus as little as possible. It's pretty annoying when the editor fails to get focus, but we really only want to force-focus the editor if there's not another input element focused (in practice this means the search field, although I suppose it might be interesting to keep focus on the tag bar through a note selection change).
That being said:
there are many ways this can go wrong,
I'm curious if you found any bugs with this implementation or know of a case where checking the activeElement
would fail.
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 not sure that we only care about initial load, as @belcherj pointed out, right now it also refocuses the editor after you change notes.
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.
it's not about activeElement
as much as it's !== 'search-field'
since it's the kind of thing that can end up feeling like spooky action at a distance when we start working with focus on something else, like sort direction or the tag list.
I didn't try this out and I didn't find or see an immediate error with it; just noting that this could be hard to find when the next PR dealing with focus comes around.
to my understanding, re-focusing the editor after changing notes has been intentional since you might want to be opening up a note and then start typing. they keyboard shortcuts still allow you to navigate the note list even when the focus is being taken.
is it only on boot or is it on every note change we care about preserving focus? is there some kind of even that "resets" focus and then the first time to get it keeps it? it sounds as we talk like we might be wanting a global focus latch with a first-come-first-keep rule about it. I'm definitely not sure of this of course.
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 wanted provide the context that once #2707 merges, the current aggressive focus capture of the editor also creates an issue for the History Revision Selector.
Specifically, opening and closing the Revision Selector (or any dialog) should move focus back to the previously focused element, which may or may not be the editor. If one is using a keyboard or screen reader to open the Revision Selector, the previously focused element will be the button to trigger opening the Revision Selector.
I chose not to address this issue in #2707, as I perceive it to be a bit complex. I do plan on creating a new Issue to capture the details.
I'm not sure if the issue I outlined should be addressed within this PR, but figured another example of focus competition could prove beneficial for planning the approach used in this PR.
lib/note-content-editor.tsx
Outdated
@@ -1188,7 +1190,7 @@ const mapStateToProps: S.MapState<StateProps> = (state) => ({ | |||
note: state.data.notes.get(state.ui.openedNote), | |||
notes: state.data.notes, | |||
searchQuery: state.ui.searchQuery, | |||
selectedSearchMatchIndex: state.ui.selectedSearchMatchIndex, | |||
selectedSearchMatchIndex: state.ui.selectedSearchMatchIndex ?? 0, |
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.
Setting the default to 0 as when we were comparing indexes in componentDidUpdate the initial render was comparing null to 0 which was unexpected.
lib/note-content-editor.tsx
Outdated
prevProps.selectedSearchMatchIndex !== this.props.selectedSearchMatchIndex | ||
prevProps.selectedSearchMatchIndex !== | ||
this.props.selectedSearchMatchIndex && | ||
prevProps.noteId !== this.props.noteId |
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.
If you performed a search then toggled through the search results and then performed a new search the focus would come back to the editor instead of finishing typing the search term.
With help from @codebykat I believe this was only intended for when a new note is selected so I added the additional check.
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 logic is for deciding when to reset the search selection, isn't it? What does it have to do with the editor focus?
I think the search selection should be updated whenever the search match index changes, not only when changing to a different note.
The actual problem here, which is perhaps being masked, seems to be that setSearchSelection
makes another call to this.focusEditor();
. That seems like something it should not do?
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.
You're right that is what this does. At first I didn't see any other time than note switches where this would be needed, but that was naive and I did of course find other times.
You're right again that the problem stems from the call to this.focusEditor();
in setSearchSelection
. I had first thought to remove that all together but I'm sure especially if using the keyboard shortcuts to toggle through search matches you would want the focus to end up there so you could immediately edit the text.
I've changed my approach to this now. Instead of calling this.focusEditor();
in setSearchSelection
I've moved it to set focus in setNextSearchSelection
and setPrevSearchSelection
.
The only weird thing I've seen so far with this is that now the behavior is different if you are using the keyboard shortcuts to toggle through search results or if you are using the search results bar at the bottom to toggle through. If using the search results bar you don't get the focus anymore. The visual selection is still there though.
I think this may be OK as if you are using the keyboard shortcuts you wouldn't want to then have to click to edit, but if you are clicking the next and previous buttons it would likely be OK to click to where you want to edit.
Would love others thoughts on that part as well.
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 makes sense and I agree with you - I think leaving the focus on the buttons is best when using the buttons.
b2f31ee
to
1dbfddf
Compare
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.
So I admit I'm deeply confused by the state of this PR, maybe because I don't remember the context surrounding it. But I just can't follow why this should solve the problem, if it does in fact solve the problem.
Why do we need to focus the editor within setSearchSelection
?
Why would we want to avoid updating the search match highlights when the selected search index changes, regardless of whether we have changed notes?
@sandymcfadden I'm sorry if I led you astray here 😅
lib/note-content-editor.tsx
Outdated
prevProps.selectedSearchMatchIndex !== this.props.selectedSearchMatchIndex | ||
prevProps.selectedSearchMatchIndex !== | ||
this.props.selectedSearchMatchIndex && | ||
prevProps.noteId !== this.props.noteId |
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 logic is for deciding when to reset the search selection, isn't it? What does it have to do with the editor focus?
I think the search selection should be updated whenever the search match index changes, not only when changing to a different note.
The actual problem here, which is perhaps being masked, seems to be that setSearchSelection
makes another call to this.focusEditor();
. That seems like something it should not do?
lib/note-content-editor.tsx
Outdated
if (document?.activeElement?.id !== 'search-field') { | ||
this.focusEditor(); | ||
} | ||
this.focusEditor(); |
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.
Doesn't this go back to focusing the editor on load without any checks?
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.
It does, but I don't think this check is necessary. In most cases, I think we want the editor to have focus on load. We just don't want it to unexpectedly take focus if we've clicked the search field.
I believe the focus was getting taken not from the initial on load, but the logic check to see if the selected search index had changed was always executing on first load because it was comparing null
to 0
for the prevProps.selectedSearchMatchIndex
and props.selectedSearchMatchIndex
.
I could be wrong about this as I was having a hard time replicating the focus loss as it was happening to you.
I've resolved that by setting the default to be null
. That fixed another bug as well where the first time you pressed CtrlOrCmd + g
to go through the search results it would select the second instance instead of the first.
There were certainly some things I was missing here and I apologize for the confusion. I've updated things now and I think addressed your questions in the other comments. |
…lection index to be null
This is testing well for me, I can't reproduce the focus issue with searches, changing to different notes, reloading and quickly searching, etc. I say we ✅ approved (geez I wish GitHub allowed us to change author of a PR) |
Fix
Fixes #2530
This one is a bit hard to reproduce as it's a race condition, but it happens fairly frequently to me on local dev.
Also Fixes #2613
If you search for a term and toggle through the results and then search again the focus is brought to the editor.
Test
Release Notes