diff --git a/ElectronClient/app/gui/NoteText.jsx b/ElectronClient/app/gui/NoteText.jsx index 502e91fb2..71173f004 100644 --- a/ElectronClient/app/gui/NoteText.jsx +++ b/ElectronClient/app/gui/NoteText.jsx @@ -36,6 +36,7 @@ const ResourceFetcher = require('lib/services/ResourceFetcher'); const { toSystemSlashes, safeFilename } = require('lib/path-utils'); const { clipboard } = require('electron'); const SearchEngine = require('lib/services/SearchEngine'); +const NoteTextViewer = require('./NoteTextViewer.min'); require('brace/mode/markdown'); // https://ace.c9.io/build/kitchen-sink.html @@ -79,6 +80,8 @@ class NoteTextComponent extends React.Component { localSearch: Object.assign({}, this.localSearchDefaultState), }; + this.webviewRef_ = React.createRef(); + this.lastLoadedNoteId_ = null; this.webviewListeners_ = null; @@ -260,6 +263,8 @@ class NoteTextComponent extends React.Component { } this.titleField_keyDown = this.titleField_keyDown.bind(this); + this.webview_ipcMessage = this.webview_ipcMessage.bind(this); + this.webview_domReady = this.webview_domReady.bind(this); } // Note: @@ -460,7 +465,7 @@ class NoteTextComponent extends React.Component { // If we are loading nothing (noteId == null), make sure to // set webviewReady to false too because the webview component // is going to be removed in render(). - const webviewReady = this.webview_ && this.state.webviewReady && (noteId || props.newNote); + const webviewReady = !!this.webviewRef_.current && this.state.webviewReady && (!!noteId || !!props.newNote); // Scroll back to top when loading new note if (loadingNewNote) { @@ -765,7 +770,7 @@ class NoteTextComponent extends React.Component { }); } - if (this.webview_) this.webview_.send('setPercentScroll', p); + if (this.webviewRef_.current) this.webviewRef_.current.wrappedInstance.send('setPercentScroll', p); } editor_scroll() { @@ -781,7 +786,7 @@ class NoteTextComponent extends React.Component { } webview_domReady() { - if (!this.webview_) return; + if (!this.webviewRef_.current) return; this.setState({ webviewReady: true, @@ -790,19 +795,6 @@ class NoteTextComponent extends React.Component { // if (Setting.value('env') === 'dev') this.webview_.openDevTools(); } - webview_ref(element) { - if (this.webview_) { - if (this.webview_ === element) return; - this.destroyWebview(); - } - - if (!element) { - this.destroyWebview(); - } else { - this.initWebview(element); - } - } - editor_ref(element) { if (this.editor_ === element) return; @@ -875,35 +867,6 @@ class NoteTextComponent extends React.Component { } } - initWebview(wv) { - if (!this.webviewListeners_) { - this.webviewListeners_ = { - 'dom-ready': this.webview_domReady.bind(this), - 'ipc-message': this.webview_ipcMessage.bind(this), - }; - } - - for (let n in this.webviewListeners_) { - if (!this.webviewListeners_.hasOwnProperty(n)) continue; - const fn = this.webviewListeners_[n]; - wv.addEventListener(n, fn); - } - - this.webview_ = wv; - } - - destroyWebview() { - if (!this.webview_) return; - - for (let n in this.webviewListeners_) { - if (!this.webviewListeners_.hasOwnProperty(n)) continue; - const fn = this.webviewListeners_[n]; - this.webview_.removeEventListener(n, fn); - } - - this.webview_ = null; - } - aceEditor_change(body) { shared.noteComponent_change(this, 'body', body); this.scheduleHtmlUpdate(); @@ -1091,7 +1054,7 @@ class NoteTextComponent extends React.Component { } printTo_(target, options) { - if (this.props.selectedNoteIds.length !== 1 || !this.webview_) { + if (this.props.selectedNoteIds.length !== 1 || !this.webviewRef_.current) { throw new Error(_('Only one note can be printed or exported to PDF at a time.')); } @@ -1113,7 +1076,7 @@ class NoteTextComponent extends React.Component { setTimeout(() => { if (target === 'pdf') { - this.webview_.printToPDF({}, (error, data) => { + this.webviewRef_.current.wrappedInstance.printToPDF({}, (error, data) => { restoreSettings(); if (error) { @@ -1123,7 +1086,7 @@ class NoteTextComponent extends React.Component { } }); } else if (target === 'printer') { - this.webview_.print(); + this.webviewRef_.current.wrappedInstance.print(); restoreSettings(); } }, 100); @@ -1637,7 +1600,7 @@ class NoteTextComponent extends React.Component { if (this.props.selectedNoteIds.length > 1) { return this.renderMultiNotes(rootStyle); - } else if (!note || !!note.encryption_applied || (note && !this.props.newNote && this.props.noteId && note.id !== this.props.noteId)) { // note.id !== props.noteId is when the note has not been loaded yet, and the previous one is still in the state + } else if (!note || !!note.encryption_applied) { //|| (note && !this.props.newNote && this.props.noteId && note.id !== this.props.noteId)) { // note.id !== props.noteId is when the note has not been loaded yet, and the previous one is still in the state return this.renderNoNotes(rootStyle); } @@ -1741,7 +1704,7 @@ class NoteTextComponent extends React.Component { const htmlHasChanged = this.lastSetHtml_ !== html; if (htmlHasChanged) { let options = {codeTheme: theme.codeThemeCss}; - this.webview_.send('setHtml', html, options); + this.webviewRef_.current.wrappedInstance.send('setHtml', html, options); this.lastSetHtml_ = html; } @@ -1767,7 +1730,7 @@ class NoteTextComponent extends React.Component { if (htmlHasChanged || keywordHash !== this.lastSetMarkers_ || !ObjectUtils.fieldsEqual(this.lastSetMarkersOptions_, markerOptions)) { this.lastSetMarkers_ = keywordHash; this.lastSetMarkersOptions_ = Object.assign({}, markerOptions); - this.webview_.send('setMarkers', keywords, markerOptions); + this.webviewRef_.current.wrappedInstance.send('setMarkers', keywords, markerOptions); } } @@ -1799,32 +1762,13 @@ class NoteTextComponent extends React.Component { const titleBarDate = {time.formatMsToLocal(note.user_updated_time)} - const viewer = { this.webview_ref(elem); } } + const viewer = - // const markers = [{ - // startRow: 2, - // startCol: 3, - // endRow: 2, - // endCol: 6, - // type: 'text', - // className: 'test-marker' - // }]; - - // markers={markers} - // editorProps={{$useWorker: false}} - - // #note-editor .test-marker { - // background-color: red; - // color: yellow; - // position: absolute; - // } - const editorRootStyle = Object.assign({}, editorStyle); delete editorRootStyle.width; delete editorRootStyle.height; @@ -1846,6 +1790,7 @@ class NoteTextComponent extends React.Component { showPrintMargin={false} onSelectionChange={this.aceEditor_selectionChange} onFocus={this.aceEditor_focus} + readOnly={visiblePanes.indexOf('editor') < 0} // Disable warning: "Automatically scrolling cursor into view after // selection change this will be disabled in the next version set diff --git a/ElectronClient/app/gui/NoteTextViewer.jsx b/ElectronClient/app/gui/NoteTextViewer.jsx new file mode 100644 index 000000000..a0360de40 --- /dev/null +++ b/ElectronClient/app/gui/NoteTextViewer.jsx @@ -0,0 +1,99 @@ +const React = require('react'); +const { connect } = require('react-redux'); +const { themeStyle } = require('../theme.js'); +const { _ } = require('lib/locale.js'); + +class NoteTextViewerComponent extends React.Component { + + constructor() { + super(); + + this.initialized_ = false; + + this.webviewRef_ = React.createRef(); + this.webviewListeners_ = null; + + this.webview_domReady = this.webview_domReady.bind(this); + this.webview_ipcMessage = this.webview_ipcMessage.bind(this); + } + + webview_domReady(event) { + this.props.onDomReady(event); + } + + webview_ipcMessage(event) { + this.props.onIpcMessage(event); + } + + initWebview() { + const wv = this.webviewRef_.current; + + if (!this.webviewListeners_) { + this.webviewListeners_ = { + 'dom-ready': this.webview_domReady.bind(this), + 'ipc-message': this.webview_ipcMessage.bind(this), + }; + } + + for (let n in this.webviewListeners_) { + if (!this.webviewListeners_.hasOwnProperty(n)) continue; + const fn = this.webviewListeners_[n]; + wv.addEventListener(n, fn); + } + } + + destroyWebview() { + const wv = this.webviewRef_.current; + if (!wv || !this.initialized_) return; + + for (let n in this.webviewListeners_) { + if (!this.webviewListeners_.hasOwnProperty(n)) continue; + const fn = this.webviewListeners_[n]; + wv.removeEventListener(n, fn); + } + } + + componentDidUpdate() { + if (!this.initialized_ && this.webviewRef_.current) { + this.initWebview(); + this.initialized_ = true; + } + } + + componentWillUnmount() { + this.destroyWebview(); + } + + send(channel, arg0 = null, arg1 = null, arg2 = null, arg3 = null) { + return this.webviewRef_.current.send(channel, arg0, arg1, arg2, arg3); + } + + printToPDF(options, callback) { + return this.webviewRef_.current.printToPDF(options, callback); + } + + print(options = {}) { + return this.webviewRef_.current.print(options); + } + + render() { + return + } + +} + +const mapStateToProps = (state) => { + return { + theme: state.settings.theme, + }; +}; + +const NoteTextViewer = connect(mapStateToProps, null, null, { withRef: true })(NoteTextViewerComponent); + +module.exports = NoteTextViewer; \ No newline at end of file diff --git a/ReactNativeClient/lib/WelcomeUtils.js b/ReactNativeClient/lib/WelcomeUtils.js index 9af5fc27c..2a3d8e6cb 100644 --- a/ReactNativeClient/lib/WelcomeUtils.js +++ b/ReactNativeClient/lib/WelcomeUtils.js @@ -19,6 +19,8 @@ class WelcomeUtils { const tempDir = Setting.value('resourceDir'); // TODO: Update mobile root.js + // TODO: Update CLI + // TODO: Test CLI for (let i = 0; i < folderAssets.length; i++) { const folderAsset = folderAssets[i];