1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 | import React from 'react';
|
9 | import { View, ActivityIndicator, StyleSheet, WebView } from 'react-native';
|
10 | import PropTypes from 'prop-types';
|
11 | import renderIf from 'render-if';
|
12 |
|
13 |
|
14 | const INDEX_FILE = require(`./assets/dist/reactQuillViewer-index.html`);
|
15 |
|
16 | const MESSAGE_PREFIX = 'react-native-webview-quilljs';
|
17 |
|
18 | export default class WebViewQuillViewer extends React.Component {
|
19 | constructor() {
|
20 | super();
|
21 | this.webview = null;
|
22 | this.state = {
|
23 | webViewNotLoaded: true,
|
24 | };
|
25 | }
|
26 |
|
27 | createWebViewRef = (webview) => {
|
28 | this.webview = webview;
|
29 | };
|
30 |
|
31 | handleMessage = (event) => {
|
32 | let msgData;
|
33 | try {
|
34 | msgData = JSON.parse(event.nativeEvent.data);
|
35 | if (msgData.hasOwnProperty('prefix') && msgData.prefix === MESSAGE_PREFIX) {
|
36 |
|
37 | this.sendMessage('MESSAGE_ACKNOWLEDGED');
|
38 |
|
39 |
|
40 | switch (msgData.type) {
|
41 | case 'VIEWER_LOADED':
|
42 | this.viewerLoaded();
|
43 | break;
|
44 | case 'VIEWER_SENT':
|
45 | this.props.getViewerCallback(msgData.payload.viewer);
|
46 | break;
|
47 | default:
|
48 | console.warn(`WebViewQuillViewer Error: Unhandled message type received "${msgData.type}"`);
|
49 | }
|
50 | }
|
51 | } catch (err) {
|
52 | console.warn(err);
|
53 | return;
|
54 | }
|
55 | };
|
56 |
|
57 | onWebViewLoaded = () => {
|
58 | console.log('Webview loaded');
|
59 | this.setState({ webViewNotLoaded: false });
|
60 | this.sendMessage('LOAD_VIEWER');
|
61 | if (this.props.hasOwnProperty('backgroundColor')) {
|
62 | this.sendMessage('SET_BACKGROUND_COLOR', {
|
63 | backgroundColor: this.props.backgroundColor
|
64 | });
|
65 | };
|
66 | if(this.props.hasOwnProperty('onLoad')){
|
67 | this.props.onLoad();
|
68 | }
|
69 | if(this.props.hasOwnProperty('getViewerCallback')){
|
70 | this.sendMessage('SEND_VIEWER');
|
71 | }
|
72 | };
|
73 |
|
74 | viewerLoaded = () => {
|
75 |
|
76 | if (this.props.hasOwnProperty('contentToDisplay')) {
|
77 | console.log(this.props.contentToDisplay);
|
78 | this.sendMessage('SET_CONTENTS', {
|
79 | ops: this.props.contentToDisplay
|
80 | });
|
81 | }
|
82 | if (this.props.hasOwnProperty('htmlContentToDisplay')) {
|
83 | this.sendMessage('SET_HTML_CONTENTS', {
|
84 | html: this.props.htmlContentToDisplay
|
85 | });
|
86 | }
|
87 | };
|
88 |
|
89 | sendContentToViewer = (delta) => {
|
90 | this.sendMessage('SET_CONTENTS', {
|
91 | ops: delta.ops
|
92 | });
|
93 | };
|
94 |
|
95 | sendMessage = (type, payload) => {
|
96 |
|
97 | if (this.webview) {
|
98 | console.log(`WebViewQuillViewer: sending message ${type}`);
|
99 | this.webview.postMessage(
|
100 | JSON.stringify({
|
101 | prefix: MESSAGE_PREFIX,
|
102 | type,
|
103 | payload
|
104 | }),
|
105 | '*'
|
106 | );
|
107 | }
|
108 | };
|
109 |
|
110 | showLoadingIndicator = () => {
|
111 | return (
|
112 | <View style={styles.activityOverlayStyle}>
|
113 | <View style={styles.activityIndicatorContainer}>
|
114 | <ActivityIndicator size="large" animating={this.state.webViewNotLoaded} color="green" />
|
115 | </View>
|
116 | </View>
|
117 | );
|
118 | };
|
119 |
|
120 | onError = (error) => {
|
121 | Alert.alert('WebView onError', error, [ { text: 'OK', onPress: () => console.log('OK Pressed') } ]);
|
122 | };
|
123 |
|
124 | renderError = (error) => {
|
125 | Alert.alert('WebView renderError', error, [ { text: 'OK', onPress: () => console.log('OK Pressed') } ]);
|
126 | };
|
127 |
|
128 | render = () => {
|
129 | return (
|
130 | <View
|
131 | style={{
|
132 | flex: 1,
|
133 | backgroundColor: 'pink'
|
134 | }}
|
135 | >
|
136 | <WebView
|
137 | style={{ ...StyleSheet.absoluteFillObject }}
|
138 | ref={this.createWebViewRef}
|
139 | source={INDEX_FILE}
|
140 | onLoadEnd={this.onWebViewLoaded}
|
141 | onMessage={this.handleMessage}
|
142 | startInLoadingState={true}
|
143 | renderLoading={this.showLoadingIndicator}
|
144 | renderError={this.renderError}
|
145 | javaScriptEnabled={true}
|
146 | onError={this.onError}
|
147 | scalesPageToFit={false}
|
148 | mixedContentMode={'always'}
|
149 | />
|
150 | </View>
|
151 | );
|
152 | };
|
153 | }
|
154 |
|
155 | WebViewQuillViewer.propTypes = {
|
156 | backgroundColor: PropTypes.string,
|
157 | onLoad: PropTypes.func
|
158 | };
|
159 |
|
160 |
|
161 | WebViewQuillViewer.defaultProps = {
|
162 | theme: 'bubble'
|
163 | };
|
164 |
|
165 | const styles = StyleSheet.create({
|
166 | activityOverlayStyle: {
|
167 | ...StyleSheet.absoluteFillObject,
|
168 | marginHorizontal: 20,
|
169 | marginVertical: 60,
|
170 | display: 'flex',
|
171 | justifyContent: 'center',
|
172 | alignContent: 'center',
|
173 | borderRadius: 5
|
174 | },
|
175 | activityIndicatorContainer: {
|
176 | backgroundColor: 'white',
|
177 | padding: 10,
|
178 | borderRadius: 50,
|
179 | alignSelf: 'center',
|
180 | shadowColor: '#000000',
|
181 | shadowOffset: {
|
182 | width: 0,
|
183 | height: 3
|
184 | },
|
185 | shadowRadius: 5,
|
186 | shadowOpacity: 1.0
|
187 | }
|
188 | });
|