1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-03-03 15:32:30 +02:00
joplin/ReactNativeClient/lib/components/note-body-viewer.js

131 lines
3.6 KiB
JavaScript
Raw Normal View History

2018-03-09 17:49:35 +00:00
const React = require("react");
const Component = React.Component;
const { Platform, WebView, View, Linking } = require("react-native");
const { globalStyle } = require("lib/components/global-style.js");
const Resource = require("lib/models/Resource.js");
const Setting = require("lib/models/Setting.js");
const { reg } = require("lib/registry.js");
const MdToHtml = require("lib/MdToHtml.js");
2017-07-30 21:51:18 +02:00
class NoteBodyViewer extends Component {
constructor() {
super();
this.state = {
resources: {},
2017-08-21 22:46:31 +02:00
webViewLoaded: false,
2018-03-09 17:49:35 +00:00
};
2017-08-21 22:46:31 +02:00
this.isMounted_ = false;
2017-07-30 21:51:18 +02:00
}
2017-08-21 22:46:31 +02:00
componentWillMount() {
this.mdToHtml_ = new MdToHtml({ supportsResourceLinks: false });
2017-08-21 22:46:31 +02:00
this.isMounted_ = true;
}
componentWillUnmount() {
this.mdToHtml_ = null;
2017-08-21 22:46:31 +02:00
this.isMounted_ = false;
}
onLoadEnd() {
if (this.state.webViewLoaded) return;
// Need to display after a delay to avoid a white flash before
// the content is displayed.
setTimeout(() => {
if (!this.isMounted_) return;
this.setState({ webViewLoaded: true });
2017-09-10 17:57:06 +01:00
}, 100);
2017-08-21 22:46:31 +02:00
}
2017-07-30 21:51:18 +02:00
render() {
const note = this.props.note;
const style = this.props.style;
const onCheckboxChange = this.props.onCheckboxChange;
const mdOptions = {
onResourceLoaded: () => {
this.forceUpdate();
},
2018-03-09 17:49:35 +00:00
paddingBottom: "3.8em", // Extra bottom padding to make it possible to scroll past the action button (so that it doesn't overlap the text)
};
2018-03-09 17:49:35 +00:00
let html = this.mdToHtml_.render(note ? note.body : "", this.props.webViewStyle, mdOptions);
2018-02-04 17:12:24 +00:00
2018-03-09 17:49:35 +00:00
html =
`
2018-02-04 17:12:24 +00:00
<!DOCTYPE html>
<html>
<head>
</head>
<body>
2018-03-09 17:49:35 +00:00
` +
html +
`
2018-02-04 17:12:24 +00:00
</body>
</html>
`;
2017-08-21 22:46:31 +02:00
2018-03-09 17:49:35 +00:00
let webViewStyle = {};
2017-11-19 15:19:36 +00:00
// On iOS, the onLoadEnd() event is never fired so always
// display the webview (don't do the little trick
// to avoid the white flash).
2018-03-09 17:49:35 +00:00
if (Platform.OS !== "ios") {
2017-11-19 15:19:36 +00:00
webViewStyle.opacity = this.state.webViewLoaded ? 1 : 0.01;
}
2017-07-30 21:51:18 +02:00
// On iOS scalesPageToFit work like this:
//
// Find the widest image, resize it *and everything else* by x% so that
// the image fits within the viewport. The problem is that it means if there's
// a large image, everything is going to be scaled to a very small size, making
// the text unreadable.
//
// On Android:
//
// Find the widest elements and scale them (and them only) to fit within the viewport
// It means it's going to scale large images, but the text will remain at the normal
// size.
//
// That means we can use scalesPageToFix on Android but not on iOS.
// The weird thing is that on iOS, scalesPageToFix=false along with a CSS
// rule "img { max-width: 100% }", works like scalesPageToFix=true on Android.
// So we use scalesPageToFix=false on iOS along with that CSS rule.
2017-11-20 19:01:19 +00:00
// `baseUrl` is where the images will be loaded from. So images must use a path relative to resourceDir.
2017-11-21 19:47:29 +00:00
const source = {
html: html,
2018-03-09 17:49:35 +00:00
baseUrl: "file://" + Setting.value("resourceDir") + "/",
2017-11-21 19:47:29 +00:00
};
2017-11-20 19:01:19 +00:00
2017-07-30 21:51:18 +02:00
return (
<View style={style}>
<WebView
2018-03-09 17:49:35 +00:00
scalesPageToFit={Platform.OS !== "ios"}
2017-08-21 22:46:31 +02:00
style={webViewStyle}
2017-11-20 19:01:19 +00:00
source={source}
2017-08-21 22:46:31 +02:00
onLoadEnd={() => this.onLoadEnd()}
2018-03-09 17:49:35 +00:00
onError={e => reg.logger().error("WebView error", e)}
onMessage={event => {
2017-07-30 21:51:18 +02:00
let msg = event.nativeEvent.data;
2018-03-09 17:49:35 +00:00
if (msg.indexOf("checkboxclick:") === 0) {
const newBody = this.mdToHtml_.handleCheckboxClick(msg, note.body);
2017-07-30 21:51:18 +02:00
if (onCheckboxChange) onCheckboxChange(newBody);
2018-03-09 17:49:35 +00:00
} else if (msg.indexOf("bodyscroll:") === 0) {
//msg = msg.split(':');
//this.bodyScrollTop_ = Number(msg[1]);
2017-07-30 21:51:18 +02:00
} else {
Linking.openURL(msg);
}
}}
/>
</View>
);
}
}
2018-03-09 17:49:35 +00:00
module.exports = { NoteBodyViewer };