diff --git a/ElectronClient/app/gui/NoteRevisionViewer.jsx b/ElectronClient/app/gui/NoteRevisionViewer.jsx index a7fb6d4a8..6fc3eafa1 100644 --- a/ElectronClient/app/gui/NoteRevisionViewer.jsx +++ b/ElectronClient/app/gui/NoteRevisionViewer.jsx @@ -7,13 +7,15 @@ const HelpButton = require('./HelpButton.min'); const BaseModel = require('lib/BaseModel'); const Revision = require('lib/models/Revision'); const Note = require('lib/models/Note'); +const urlUtils = require('lib/urlUtils'); const Setting = require('lib/models/Setting'); const RevisionService = require('lib/services/RevisionService'); const shared = require('lib/components/shared/note-screen-shared.js'); const MarkupToHtml = require('lib/renderers/MarkupToHtml'); const { time } = require('lib/time-utils.js'); const ReactTooltip = require('react-tooltip'); -const { substrWithEllipsis } = require('lib/string-utils'); +const { urlDecode, substrWithEllipsis } = require('lib/string-utils'); +const { bridge } = require('electron').remote.require('./bridge'); class NoteRevisionViewerComponent extends React.PureComponent { constructor() { @@ -32,6 +34,7 @@ class NoteRevisionViewerComponent extends React.PureComponent { this.revisionList_onChange = this.revisionList_onChange.bind(this); this.importButton_onClick = this.importButton_onClick.bind(this); this.backButton_click = this.backButton_click.bind(this); + this.webview_ipcMessage = this.webview_ipcMessage.bind(this); } style() { @@ -121,11 +124,42 @@ class NoteRevisionViewerComponent extends React.PureComponent { codeTheme: theme.codeThemeCss, userCss: this.props.customCss ? this.props.customCss : '', resources: await shared.attachedResources(noteBody), + postMessageSyntax: 'ipcProxySendToHost', }); this.viewerRef_.current.wrappedInstance.send('setHtml', result.html, { cssFiles: result.cssFiles }); } + async webview_ipcMessage(event) { + // For the revision view, we only suppport a minimal subset of the IPC messages. + // For example, we don't need interactive checkboxes or sync between viewer and editor view. + // We try to get most links work though, except for internal (joplin://) links. + + const msg = event.channel ? event.channel : ''; + const args = event.args; + + if (msg !== 'percentScroll') console.info(`Got ipc-message: ${msg}`, args); + + try { + if (msg.indexOf('joplin://') === 0) { + throw new Error(_('Unsupported link or message: %s', msg)); + } else if (urlUtils.urlProtocol(msg)) { + if (msg.indexOf('file://') === 0) { + require('electron').shell.openExternal(urlDecode(msg)); + } else { + require('electron').shell.openExternal(msg); + } + } else if (msg.indexOf('#') === 0) { + // This is an internal anchor, which is handled by the WebView so skip this case + } else { + console.warn(`Unsupported message in revision view: ${msg}`); + } + } catch (error) { + console.warn(error); + bridge().showErrorMessageBox(error.message); + } + } + render() { const theme = themeStyle(this.props.theme); const style = this.style(); @@ -149,7 +183,7 @@ class NoteRevisionViewerComponent extends React.PureComponent { const titleInput = (