1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-08-24 20:19:10 +02:00

Compare commits

...

1 Commits

Author SHA1 Message Date
Laurent Cozic
30931aba2c Update NoteBodyViewer to prepare switch to WebKit 2020-10-12 18:00:10 +01:00
6 changed files with 43 additions and 25 deletions

View File

@@ -200,6 +200,7 @@ ReactNativeClient/lib/commands/historyBackward.js
ReactNativeClient/lib/commands/historyForward.js
ReactNativeClient/lib/commands/synchronize.js
ReactNativeClient/lib/components/BackButtonDialogBox.js
ReactNativeClient/lib/components/NoteBodyViewer.js
ReactNativeClient/lib/components/screens/UpgradeSyncTargetScreen.js
ReactNativeClient/lib/errorUtils.js
ReactNativeClient/lib/eventManager.js

1
.gitignore vendored
View File

@@ -194,6 +194,7 @@ ReactNativeClient/lib/commands/historyBackward.js
ReactNativeClient/lib/commands/historyForward.js
ReactNativeClient/lib/commands/synchronize.js
ReactNativeClient/lib/components/BackButtonDialogBox.js
ReactNativeClient/lib/components/NoteBodyViewer.js
ReactNativeClient/lib/components/screens/UpgradeSyncTargetScreen.js
ReactNativeClient/lib/errorUtils.js
ReactNativeClient/lib/eventManager.js

View File

@@ -13,7 +13,7 @@ import {
Image,
} from 'react-native';
import { renderFormatButtons } from './renderButtons';
import { NoteBodyViewer } from 'lib/components/note-body-viewer.js';
const NoteBodyViewer = require('lib/components/NoteBodyViewer').default;
const styles = StyleSheet.create({
buttonContainer: {

View File

@@ -255,6 +255,8 @@ PODS:
- React
- RNSecureRandom (1.0.0-rc.0):
- React
- RNShare (3.3.3):
- React
- RNVectorIcons (6.6.0):
- React
- Yoga (1.14.0)
@@ -303,6 +305,7 @@ DEPENDENCIES:
- RNFS (from `../node_modules/react-native-fs`)
- RNQuickAction (from `../node_modules/react-native-quick-actions`)
- RNSecureRandom (from `../node_modules/react-native-securerandom`)
- RNShare (from `../node_modules/react-native-share`)
- RNVectorIcons (from `../node_modules/react-native-vector-icons`)
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
@@ -391,6 +394,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native-quick-actions"
RNSecureRandom:
:path: "../node_modules/react-native-securerandom"
RNShare:
:path: "../node_modules/react-native-share"
RNVectorIcons:
:path: "../node_modules/react-native-vector-icons"
Yoga:
@@ -438,6 +443,7 @@ SPEC CHECKSUMS:
RNFS: 416676c3a9ae404454bade10e3d78147c7c33a40
RNQuickAction: 6d404a869dc872cde841ad3147416a670d13fa93
RNSecureRandom: 1f19ad1492f7ed416b8fc79e92216a1f73f13a4c
RNShare: f4ec422e27904e0dc9310038d1110460a59ad30d
RNVectorIcons: 0bb4def82230be1333ddaeee9fcba45f0b288ed4
Yoga: f2a7cd4280bfe2cca5a7aed98ba0eb3d1310f18b

View File

@@ -1,35 +1,37 @@
import Async from 'react-async';
import Setting from 'lib/models/Setting';
import shim from 'lib/shim';
const Async = require('react-async').default;
const React = require('react');
const Component = React.Component;
const { Platform, View, Text, ToastAndroid } = require('react-native');
const { WebView } = require('react-native-webview');
const { themeStyle } = require('lib/components/global-style.js');
const Setting = require('lib/models/Setting').default;
const BackButtonDialogBox = require('lib/components/BackButtonDialogBox').default;
const { _ } = require('lib/locale.js');
const { reg } = require('lib/registry.js');
const shim = require('lib/shim').default;
const { assetsToHeaders } = require('lib/joplin-renderer');
const shared = require('lib/components/shared/note-screen-shared.js');
const markupLanguageUtils = require('lib/markupLanguageUtils');
const { dialogs } = require('lib/dialogs.js');
const BackButtonDialogBox = require('lib/components/BackButtonDialogBox').default;
const Resource = require('lib/models/Resource.js');
const Share = require('react-native-share').default;
class NoteBodyViewer extends Component {
export default class NoteBodyViewer extends Component {
private forceUpdate_:boolean = false;
private isMounted_:boolean = false;
private markupToHtml_:any;
constructor() {
super();
this.state = {
resources: {},
webViewLoaded: false,
bodyHtml: '',
};
this.forceUpdate_ = false;
this.isMounted_ = false;
this.markupToHtml_ = markupLanguageUtils.newMarkupToHtml();
this.reloadNote = this.reloadNote.bind(this);
@@ -88,22 +90,23 @@ class NoteBodyViewer extends Component {
const resourceDownloadMode = Setting.value('sync.resourceDownloadMode');
const injectedJs = [];
injectedJs.push('try {');
injectedJs.push(shim.injectedJs('webviewLib'));
// Note that this postMessage function accepts two arguments, for compatibility with the desktop version, but
// the ReactNativeWebView actually supports only one, so the second arg is ignored (and currently not needed for the mobile app).
injectedJs.push('window.joplinPostMessage_ = (msg, args) => { return window.ReactNativeWebView.postMessage(msg); };');
injectedJs.push('webviewLib.initialize({ postMessage: msg => { return window.ReactNativeWebView.postMessage(msg); } });');
injectedJs.push(`
const readyStateCheckInterval = shim.setInterval(function() {
const readyStateCheckInterval = setInterval(function() {
if (document.readyState === "complete") {
shim.clearInterval(readyStateCheckInterval);
clearInterval(readyStateCheckInterval);
if ("${resourceDownloadMode}" === "manual") webviewLib.setupResourceManualDownload();
const hash = "${this.props.noteHash}";
// Gives it a bit of time before scrolling to the anchor
// so that images are loaded.
if (hash) {
shim.setTimeout(() => {
setTimeout(() => {
const e = document.getElementById(hash);
if (!e) {
console.warn('Cannot find hash', hash);
@@ -115,6 +118,11 @@ class NoteBodyViewer extends Component {
}
}, 10);
`);
injectedJs.push('} catch (e) {');
injectedJs.push(' window.ReactNativeWebView.postMessage("error:" + e.message + ": " + JSON.stringify(e))');
injectedJs.push(' true;');
injectedJs.push('}');
injectedJs.push('true;');
html =
`
@@ -173,8 +181,8 @@ class NoteBodyViewer extends Component {
}, 100);
}
shouldComponentUpdate(nextProps, nextState) {
const safeGetNoteProp = (props, propName) => {
shouldComponentUpdate(nextProps:any, nextState:any) {
const safeGetNoteProp = (props:any, propName:string) => {
if (!props) return null;
if (!props.note) return null;
return props.note[propName];
@@ -210,7 +218,7 @@ class NoteBodyViewer extends Component {
return this.forceUpdate_;
}
async onResourceLongPress(msg) {
async onResourceLongPress(msg:string) {
try {
const resourceId = msg.split(':')[1];
const resource = await Resource.load(resourceId);
@@ -256,7 +264,7 @@ class NoteBodyViewer extends Component {
// https://github.com/react-native-community/react-native-webview/issues/312#issuecomment-503754654
const webViewStyle = { backgroundColor: this.props.webViewStyle.backgroundColor };
const webViewStyle:any = { backgroundColor: this.props.webViewStyle.backgroundColor };
// On iOS, the onLoadEnd() event is never fired so always
// display the webview (don't do the little trick
// to avoid the white flash).
@@ -267,7 +275,9 @@ class NoteBodyViewer extends Component {
return (
<View style={this.props.style}>
<Async promiseFn={this.reloadNote} watchFn={this.watchFn}>
{({ data, error, isPending }) => {
{(args:any) => {
const { data, error, isPending } = args;
if (error) {
console.error(error);
return <Text>{error.message}</Text>;
@@ -286,7 +296,7 @@ class NoteBodyViewer extends Component {
allowFileAccess={true}
onLoadEnd={() => this.onLoadEnd()}
onError={() => reg.logger().error('WebView error')}
onMessage={event => {
onMessage={(event:any) => {
// Since RN 58 (or 59) messages are now escaped twice???
let msg = unescape(unescape(event.nativeEvent.data));
@@ -296,13 +306,15 @@ class NoteBodyViewer extends Component {
const newBody = shared.toggleCheckbox(msg, this.props.note.body);
if (this.props.onCheckboxChange) this.props.onCheckboxChange(newBody);
} else if (msg.indexOf('markForDownload:') === 0) {
msg = msg.split(':');
const resourceId = msg[1];
const splittedMsg = msg.split(':');
const resourceId = splittedMsg[1];
if (this.props.onMarkForDownload) this.props.onMarkForDownload({ resourceId: resourceId });
} else if (msg.startsWith('longclick:')) {
this.onResourceLongPress(msg);
} else if (msg.startsWith('joplin:')) {
this.props.onJoplinLinkClick(msg);
} else if (msg.startsWith('error:')) {
console.error('Webview injected script error: ' + msg);
}
}}
/>
@@ -310,7 +322,7 @@ class NoteBodyViewer extends Component {
}}
</Async>
<BackButtonDialogBox
ref={dialogbox => {
ref={(dialogbox:any) => {
this.dialogbox = dialogbox;
}}
/>
@@ -318,5 +330,3 @@ class NoteBodyViewer extends Component {
);
}
}
module.exports = { NoteBodyViewer };

View File

@@ -32,7 +32,7 @@ const { BaseScreenComponent } = require('lib/components/base-screen.js');
const { themeStyle, editorFont } = require('lib/components/global-style.js');
const { dialogs } = require('lib/dialogs.js');
const DialogBox = require('react-native-dialogbox').default;
const { NoteBodyViewer } = require('lib/components/note-body-viewer.js');
const NoteBodyViewer = require('lib/components/NoteBodyViewer').default;
const { DocumentPicker, DocumentPickerUtil } = require('react-native-document-picker');
const ImageResizer = require('react-native-image-resizer').default;
const shared = require('lib/components/shared/note-screen-shared.js');