UNPKG

6.09 kBJavaScriptView Raw
1/********************************************
2 * WebViewQuillViewer.js
3 * A Delta viewer suitable for viewing output from a Quill.js
4 * editor. The Delta format is discussed here: https://quilljs.com/docs/delta/
5 * This component is useful for applications that must avoid using native code
6 *
7 */
8import React from 'react';
9import {
10 View,
11 ActivityIndicator,
12 StyleSheet,
13 WebView,
14 Platform
15} from 'react-native';
16import PropTypes from 'prop-types';
17import renderIf from 'render-if';
18import AssetUtils from 'expo-asset-utils';
19
20// path to the file that the webview will load
21const VIEWER_INDEX_FILE_PATH = require(`./assets/dist/reactQuillViewer-index.html`);
22// const INDEX_FILE_ASSET_URI = Asset.fromModule(require(VIEWER_INDEX_FILE_PATH)).uri;
23const MESSAGE_PREFIX = 'react-native-webview-quilljs';
24
25export default class WebViewQuillViewer extends React.Component {
26 constructor() {
27 super();
28 this.webview = null;
29 this.state = {
30 webViewNotLoaded: true // flag to show activity indicator
31 };
32 this.viewerIndexFileAsset = undefined;
33 }
34
35 componentDidMount = async () => {
36 try {
37 this.viewerIndexFileAsset = await AssetUtils.resolveAsync(VIEWER_INDEX_FILE_PATH);
38 console.log(this.viewerIndexFileAsset);
39 } catch (error) {
40 console.log({ error });
41 debugger;
42 }
43 };
44
45 createWebViewRef = (webview) => {
46 this.webview = webview;
47 };
48
49 handleMessage = (event) => {
50 let msgData;
51 try {
52 msgData = JSON.parse(event.nativeEvent.data);
53 if (
54 msgData.hasOwnProperty('prefix') &&
55 msgData.prefix === MESSAGE_PREFIX
56 ) {
57 // console.log(`WebViewQuillEditor: received message ${msgData.type}`);
58 this.sendMessage('MESSAGE_ACKNOWLEDGED');
59 // console.log(`WebViewQuillEditor: sent MESSAGE_ACKNOWLEDGED`);
60
61 switch (msgData.type) {
62 case 'VIEWER_LOADED':
63 this.viewerLoaded();
64 break;
65 case 'VIEWER_SENT':
66 this.props.getViewerCallback(msgData.payload.viewer);
67 break;
68 default:
69 console.warn(
70 `WebViewQuillViewer Error: Unhandled message type received "${
71 msgData.type
72 }"`
73 );
74 }
75 }
76 } catch (err) {
77 console.warn(err);
78 return;
79 }
80 };
81
82 onWebViewLoaded = () => {
83 console.log('Webview loaded');
84 this.setState({ webViewNotLoaded: false });
85 this.sendMessage('LOAD_VIEWER');
86 if (this.props.hasOwnProperty('backgroundColor')) {
87 this.sendMessage('SET_BACKGROUND_COLOR', {
88 backgroundColor: this.props.backgroundColor
89 });
90 }
91 if (this.props.hasOwnProperty('onLoad')) {
92 this.props.onLoad();
93 }
94 if (this.props.hasOwnProperty('getViewerCallback')) {
95 this.sendMessage('SEND_VIEWER');
96 }
97 };
98
99 viewerLoaded = () => {
100 // send the content to the viewer if we have it
101 if (this.props.hasOwnProperty('contentToDisplay')) {
102 console.log(this.props.contentToDisplay);
103 this.sendMessage('SET_CONTENTS', {
104 ops: this.props.contentToDisplay
105 });
106 }
107 if (this.props.hasOwnProperty('htmlContentToDisplay')) {
108 this.sendMessage('SET_HTML_CONTENTS', {
109 html: this.props.htmlContentToDisplay
110 });
111 }
112 };
113
114 sendContentToViewer = (delta) => {
115 this.sendMessage('SET_CONTENTS', {
116 ops: delta.ops
117 });
118 };
119
120 sendMessage = (type, payload) => {
121 // only send message when webview is loaded
122 if (this.webview) {
123 console.log(`WebViewQuillViewer: sending message ${type}`);
124 this.webview.postMessage(
125 JSON.stringify({
126 prefix: MESSAGE_PREFIX,
127 type,
128 payload
129 }),
130 '*'
131 );
132 }
133 };
134
135 showLoadingIndicator = () => {
136 return (
137 <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
138 <ActivityIndicator color="green" />
139 </View>
140 );
141 };
142
143 onError = (error) => {
144 Alert.alert('WebView onError', error, [
145 { text: 'OK', onPress: () => console.log('OK Pressed') }
146 ]);
147 };
148
149 renderError = (error) => {
150 Alert.alert('WebView renderError', error, [
151 { text: 'OK', onPress: () => console.log('OK Pressed') }
152 ]);
153 };
154
155 render = () => {
156 return (
157 <View style={{ flex: 1, overflow: 'hidden' }}>
158 {this.viewerIndexFileAsset ? (
159 <WebView
160 style={{ ...StyleSheet.absoluteFillObject }}
161 ref={this.createWebViewRef}
162 source={{ uri: this.viewerIndexFileAsset.uri }}
163 onLoadEnd={this.onWebViewLoaded}
164 onMessage={this.handleMessage}
165 startInLoadingState={true}
166 renderLoading={this.showLoadingIndicator}
167 renderError={this.renderError}
168 javaScriptEnabled={true}
169 onError={this.onError}
170 scalesPageToFit={false}
171 mixedContentMode={'always'}
172 />
173 ) : (
174 <View
175 style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}
176 >
177 <ActivityIndicator color="blue" />
178 </View>
179 )}
180 </View>
181 );
182 };
183}
184
185WebViewQuillViewer.propTypes = {
186 backgroundColor: PropTypes.string,
187 onLoad: PropTypes.func
188};
189
190// Specifies the default values for props:
191WebViewQuillViewer.defaultProps = {
192 theme: 'bubble'
193};
194
195const styles = StyleSheet.create({
196 activityOverlayStyle: {
197 ...StyleSheet.absoluteFillObject,
198 marginHorizontal: 20,
199 marginVertical: 60,
200 display: 'flex',
201 justifyContent: 'center',
202 alignContent: 'center',
203 borderRadius: 5
204 },
205 activityIndicatorContainer: {
206 backgroundColor: 'white',
207 padding: 10,
208 borderRadius: 50,
209 alignSelf: 'center',
210 shadowColor: '#000000',
211 shadowOffset: {
212 width: 0,
213 height: 3
214 },
215 shadowRadius: 5,
216 shadowOpacity: 1.0
217 }
218});