From 47e943a63dcfbe2ee0d391870c0963aaf7de13dc Mon Sep 17 00:00:00 2001 From: Brett Bender Date: Mon, 18 Oct 2021 20:22:30 -0700 Subject: [PATCH 1/3] via IPC, have webview insert and focus on a dummy element at top of content --- .../gui/NoteEditor/NoteBody/CodeMirror/CodeMirror.tsx | 2 +- packages/app-desktop/gui/NoteTextViewer.tsx | 4 ++++ packages/app-desktop/gui/note-viewer/index.html | 9 +++++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/CodeMirror.tsx b/packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/CodeMirror.tsx index fca3a238749..3ff277deef7 100644 --- a/packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/CodeMirror.tsx +++ b/packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/CodeMirror.tsx @@ -146,7 +146,7 @@ function CodeMirror(props: NoteBodyEditorProps, ref: any) { if (props.visiblePanes.indexOf('editor') >= 0) { editorRef.current.focus(); } else { - webviewRef.current.wrappedInstance.focus(); + webviewRef.current.wrappedInstance.send('doFocus'); } } else { commandProcessed = false; diff --git a/packages/app-desktop/gui/NoteTextViewer.tsx b/packages/app-desktop/gui/NoteTextViewer.tsx index 8d9413e012a..9f0a57d3045 100644 --- a/packages/app-desktop/gui/NoteTextViewer.tsx +++ b/packages/app-desktop/gui/NoteTextViewer.tsx @@ -146,6 +146,10 @@ class NoteTextViewerComponent extends React.Component { send(channel: string, arg0: any = null, arg1: any = null) { const win = this.webviewRef_.current.contentWindow; + if (channel === 'doFocus') { + win.postMessage({ target: 'webview', name: 'doFocus', data: {} }, '*'); + } + if (channel === 'setHtml') { win.postMessage({ target: 'webview', name: 'setHtml', data: { html: arg0, options: arg1 } }, '*'); } diff --git a/packages/app-desktop/gui/note-viewer/index.html b/packages/app-desktop/gui/note-viewer/index.html index dda543036bd..a92e27a60a7 100644 --- a/packages/app-desktop/gui/note-viewer/index.html +++ b/packages/app-desktop/gui/note-viewer/index.html @@ -197,6 +197,15 @@ let checkAllImageLoadedIID_ = null; + ipc.doFocus = (event) => { + // JIT insert a dummy element to focus, if we haven't already + if (! document.getElementById('focus_dummy')) { + const focusDummy = "" + contentElement.insertAdjacentHTML("afterbegin", focusDummy); + } + contentElement.firstElementChild.firstElementChild.focus(); + } + ipc.setHtml = (event) => { const html = event.html; From 7b6dd583effb7adfdce45929cec8df76d95bb81b Mon Sep 17 00:00:00 2001 From: Brett Bender Date: Tue, 19 Oct 2021 17:04:46 -0700 Subject: [PATCH 2/3] * name IPC message 'focus' * add a comment explaining why we can't simply focus the container * give the dummy anchor a unique/prefixed ID to avoid collision w/user content --- .../gui/NoteEditor/NoteBody/CodeMirror/CodeMirror.tsx | 4 +++- packages/app-desktop/gui/NoteTextViewer.tsx | 4 ++-- packages/app-desktop/gui/note-viewer/index.html | 6 +++--- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/CodeMirror.tsx b/packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/CodeMirror.tsx index 3ff277deef7..7fe38e573ff 100644 --- a/packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/CodeMirror.tsx +++ b/packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/CodeMirror.tsx @@ -146,7 +146,9 @@ function CodeMirror(props: NoteBodyEditorProps, ref: any) { if (props.visiblePanes.indexOf('editor') >= 0) { editorRef.current.focus(); } else { - webviewRef.current.wrappedInstance.send('doFocus'); + // If we just call wrappedInstance.focus() then the iframe is focused, + // but not its content, such that scrolling up / down with arrow keys fails + webviewRef.current.wrappedInstance.send('focus'); } } else { commandProcessed = false; diff --git a/packages/app-desktop/gui/NoteTextViewer.tsx b/packages/app-desktop/gui/NoteTextViewer.tsx index 9f0a57d3045..d211fa72450 100644 --- a/packages/app-desktop/gui/NoteTextViewer.tsx +++ b/packages/app-desktop/gui/NoteTextViewer.tsx @@ -146,8 +146,8 @@ class NoteTextViewerComponent extends React.Component { send(channel: string, arg0: any = null, arg1: any = null) { const win = this.webviewRef_.current.contentWindow; - if (channel === 'doFocus') { - win.postMessage({ target: 'webview', name: 'doFocus', data: {} }, '*'); + if (channel === 'focus') { + win.postMessage({ target: 'webview', name: 'focus', data: {} }, '*'); } if (channel === 'setHtml') { diff --git a/packages/app-desktop/gui/note-viewer/index.html b/packages/app-desktop/gui/note-viewer/index.html index a92e27a60a7..9e2d2fd4721 100644 --- a/packages/app-desktop/gui/note-viewer/index.html +++ b/packages/app-desktop/gui/note-viewer/index.html @@ -197,10 +197,10 @@ let checkAllImageLoadedIID_ = null; - ipc.doFocus = (event) => { + ipc.focus = (event) => { // JIT insert a dummy element to focus, if we haven't already - if (! document.getElementById('focus_dummy')) { - const focusDummy = "" + if (! document.getElementById('joplin-content-focus-dummy')) { + const focusDummy = "" contentElement.insertAdjacentHTML("afterbegin", focusDummy); } contentElement.firstElementChild.firstElementChild.focus(); From 757cb36947e2245d6f9c4305cc14d771e4460b03 Mon Sep 17 00:00:00 2001 From: Brett Bender Date: Tue, 19 Oct 2021 18:50:55 -0700 Subject: [PATCH 3/3] use ID to element to focus, makes intentions slightly clearer --- packages/app-desktop/gui/note-viewer/index.html | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/app-desktop/gui/note-viewer/index.html b/packages/app-desktop/gui/note-viewer/index.html index 9e2d2fd4721..fc87080c621 100644 --- a/packages/app-desktop/gui/note-viewer/index.html +++ b/packages/app-desktop/gui/note-viewer/index.html @@ -198,12 +198,14 @@ let checkAllImageLoadedIID_ = null; ipc.focus = (event) => { - // JIT insert a dummy element to focus, if we haven't already - if (! document.getElementById('joplin-content-focus-dummy')) { - const focusDummy = "" + const dummyID = 'joplin-content-focus-dummy'; + if (! document.getElementById(dummyID)) { + const focusDummy = ''; contentElement.insertAdjacentHTML("afterbegin", focusDummy); } - contentElement.firstElementChild.firstElementChild.focus(); + const scrollTop = contentElement.scrollTop; + document.getElementById(dummyID).focus(); + contentElement.scrollTop = scrollTop; } ipc.setHtml = (event) => {