zhangchao 4 years ago
parent
commit
79e605c540
3 changed files with 16 additions and 45 deletions
  1. 13
    37
      src/RichTextEditor.js
  2. 1
    1
      src/WebviewMessageHandler.js
  3. 2
    7
      src/editor.html

+ 13
- 37
src/RichTextEditor.js View File

1
 import React, {Component} from 'react';
1
 import React, {Component} from 'react';
2
 import PropTypes from 'prop-types';
2
 import PropTypes from 'prop-types';
3
-// import WebViewBridge from 'react-native-webview-bridge-updated';
4
 import WebView from 'react-native-webview';
3
 import WebView from 'react-native-webview';
5
 import {MessageConverter} from './WebviewMessageHandler';
4
 import {MessageConverter} from './WebviewMessageHandler';
6
 import {actions, messages} from './const';
5
 import {actions, messages} from './const';
7
 import {Modal, View, Text, StyleSheet, TextInput, TouchableOpacity, Platform, PixelRatio, Keyboard, Dimensions} from 'react-native';
6
 import {Modal, View, Text, StyleSheet, TextInput, TouchableOpacity, Platform, PixelRatio, Keyboard, Dimensions} from 'react-native';
8
 
7
 
9
-// const injectScript = `
10
-//   (function () {
11
-//     ${InjectedMessageHandler}
12
-//   }());
13
-// `;
14
-
15
 const PlatformIOS = Platform.OS === 'ios';
8
 const PlatformIOS = Platform.OS === 'ios';
16
 
9
 
17
 export default class RichTextEditor extends Component {
10
 export default class RichTextEditor extends Component {
43
     this.state = {
36
     this.state = {
44
       selectionChangeListeners: [],
37
       selectionChangeListeners: [],
45
       onChange: [],
38
       onChange: [],
46
-      showLinkDialog: false,
39
+      isShowLinkDialog: false,
47
       linkInitialUrl: '',
40
       linkInitialUrl: '',
48
       linkTitle: '',
41
       linkTitle: '',
49
       linkUrl: '',
42
       linkUrl: '',
160
 
153
 
161
           break;
154
           break;
162
         case messages.LINK_TOUCHED:
155
         case messages.LINK_TOUCHED:
163
-          this.prepareInsert();
164
           const {title, url} = message.data;
156
           const {title, url} = message.data;
165
           this.showLinkDialog(title, url);
157
           this.showLinkDialog(title, url);
166
           break;
158
           break;
202
   }
194
   }
203
 
195
 
204
   _renderLinkModal() {
196
   _renderLinkModal() {
197
+    const {linkOption} = this.props;
205
     return (
198
     return (
206
         <Modal
199
         <Modal
207
             animationType={"fade"}
200
             animationType={"fade"}
208
             transparent
201
             transparent
209
-            visible={this.state.showLinkDialog}
210
-            onRequestClose={() => this.setState({showLinkDialog: false})}
202
+            visible={this.state.isShowLinkDialog}
203
+            onRequestClose={() => this.setState({isShowLinkDialog: false})}
211
         >
204
         >
212
           <View style={styles.modal}>
205
           <View style={styles.modal}>
213
             <View style={[styles.innerModal, {marginBottom: PlatformIOS ? this.state.keyboardHeight : 0}]}>
206
             <View style={[styles.innerModal, {marginBottom: PlatformIOS ? this.state.keyboardHeight : 0}]}>
214
-              <Text style={styles.inputTitle}>Title</Text>
207
+              <Text style={styles.inputTitle}>{linkOption.titleText}</Text>
215
               <View style={styles.inputWrapper}>
208
               <View style={styles.inputWrapper}>
216
                 <TextInput
209
                 <TextInput
217
                     style={styles.input}
210
                     style={styles.input}
219
                     value={this.state.linkTitle}
212
                     value={this.state.linkTitle}
220
                 />
213
                 />
221
               </View>
214
               </View>
222
-              <Text style={[styles.inputTitle ,{marginTop: 10}]}>URL</Text>
215
+              <Text style={[styles.inputTitle ,{marginTop: 10}]}>{linkOption.urlText}</Text>
223
               <View style={styles.inputWrapper}>
216
               <View style={styles.inputWrapper}>
224
                 <TextInput
217
                 <TextInput
225
                     style={styles.input}
218
                     style={styles.input}
240
 
233
 
241
   _hideModal() {
234
   _hideModal() {
242
     this.setState({
235
     this.setState({
243
-      showLinkDialog: false,
236
+      isShowLinkDialog: false,
244
       linkInitialUrl: '',
237
       linkInitialUrl: '',
245
       linkTitle: '',
238
       linkTitle: '',
246
       linkUrl: ''
239
       linkUrl: ''
251
     const insertUpdateDisabled = this.state.linkTitle.trim().length <= 0 || this.state.linkUrl.trim().length <= 0;
244
     const insertUpdateDisabled = this.state.linkTitle.trim().length <= 0 || this.state.linkUrl.trim().length <= 0;
252
     const containerPlatformStyle = PlatformIOS ? {justifyContent: 'space-between'} : {paddingTop: 15};
245
     const containerPlatformStyle = PlatformIOS ? {justifyContent: 'space-between'} : {paddingTop: 15};
253
     const buttonPlatformStyle = PlatformIOS ? {flex: 1, height: 45, justifyContent: 'center'} : {};
246
     const buttonPlatformStyle = PlatformIOS ? {flex: 1, height: 45, justifyContent: 'center'} : {};
247
+    const { linkOption } = this.props;
254
     return (
248
     return (
255
       <View style={[{alignSelf: 'stretch', flexDirection: 'row'}, containerPlatformStyle]}>
249
       <View style={[{alignSelf: 'stretch', flexDirection: 'row'}, containerPlatformStyle]}>
256
         {!PlatformIOS && <View style={{flex: 1}}/>}
250
         {!PlatformIOS && <View style={{flex: 1}}/>}
259
             style={buttonPlatformStyle}
253
             style={buttonPlatformStyle}
260
         >
254
         >
261
           <Text style={[styles.button, {paddingRight: 10}]}>
255
           <Text style={[styles.button, {paddingRight: 10}]}>
262
-            {this._upperCaseButtonTextIfNeeded('Cancel')}
256
+            {linkOption.cancelText}
263
           </Text>
257
           </Text>
264
         </TouchableOpacity>
258
         </TouchableOpacity>
265
         <TouchableOpacity
259
         <TouchableOpacity
275
             style={buttonPlatformStyle}
269
             style={buttonPlatformStyle}
276
         >
270
         >
277
           <Text style={[styles.button, {opacity: insertUpdateDisabled ? 0.5 : 1}]}>
271
           <Text style={[styles.button, {opacity: insertUpdateDisabled ? 0.5 : 1}]}>
278
-            {this._upperCaseButtonTextIfNeeded(this._linkIsNew() ? 'Insert' : 'Update')}
272
+            {this._linkIsNew() ? linkOption.insertText : linkOption.updateText}
279
           </Text>
273
           </Text>
280
         </TouchableOpacity>
274
         </TouchableOpacity>
281
       </View>
275
       </View>
286
     return !this.state.linkInitialUrl;
280
     return !this.state.linkInitialUrl;
287
   }
281
   }
288
 
282
 
289
-  _upperCaseButtonTextIfNeeded(buttonText) {
290
-    return PlatformIOS ? buttonText : buttonText.toUpperCase();
291
-  }
292
-
293
   render() {
283
   render() {
294
     //in release build, external html files in Android can't be required, so they must be placed in the assets folder and accessed via uri
284
     //in release build, external html files in Android can't be required, so they must be placed in the assets folder and accessed via uri
295
     const pageSource = PlatformIOS ? require('./editor.html') : { uri: 'file:///android_asset/editor.html' };
285
     const pageSource = PlatformIOS ? require('./editor.html') : { uri: 'file:///android_asset/editor.html' };
301
           keyboardDisplayRequiresUserAction={false}
291
           keyboardDisplayRequiresUserAction={false}
302
           ref={(r) => {this.webview = r}}
292
           ref={(r) => {this.webview = r}}
303
           onMessage={(message) => this.onMessage(message)}
293
           onMessage={(message) => this.onMessage(message)}
304
-          // injectedJavaScript={injectScript}
305
           source={pageSource}
294
           source={pageSource}
306
           onLoad={() => this.init()}
295
           onLoad={() => this.init()}
307
         />
296
         />
310
     );
299
     );
311
   }
300
   }
312
 
301
 
313
-  escapeJSONString = function(string) {
314
-    return string
315
-      .replace(/[\\]/g, '\\\\')
316
-      .replace(/[\"]/g, '\\\"')
317
-      .replace(/[\']/g, '\\\'')
318
-      .replace(/[\/]/g, '\\/')
319
-      .replace(/[\b]/g, '\\b')
320
-      .replace(/[\f]/g, '\\f')
321
-      .replace(/[\n]/g, '\\n')
322
-      .replace(/[\r]/g, '\\r')
323
-      .replace(/[\t]/g, '\\t');
324
-  };
325
-
326
   _sendAction(action, data) {
302
   _sendAction(action, data) {
327
     let jsToBeExecutedOnPage = MessageConverter({ type: action, data });
303
     let jsToBeExecutedOnPage = MessageConverter({ type: action, data });
328
-
329
-    console.log(jsToBeExecutedOnPage)
304
+    console.log(jsToBeExecutedOnPage + ';true;')
330
     this.webview.injectJavaScript(jsToBeExecutedOnPage + ';true;');
305
     this.webview.injectJavaScript(jsToBeExecutedOnPage + ';true;');
331
   }
306
   }
332
 
307
 
334
   //--------------- Public API
309
   //--------------- Public API
335
 
310
 
336
   showLinkDialog(optionalTitle = '', optionalUrl = '') {
311
   showLinkDialog(optionalTitle = '', optionalUrl = '') {
312
+    this.prepareInsert();
337
     this.setState({
313
     this.setState({
338
       linkInitialUrl: optionalUrl,
314
       linkInitialUrl: optionalUrl,
339
       linkTitle: optionalTitle,
315
       linkTitle: optionalTitle,
340
       linkUrl: optionalUrl,
316
       linkUrl: optionalUrl,
341
-      showLinkDialog: true
317
+      isShowLinkDialog: true
342
     });
318
     });
343
   }
319
   }
344
 
320
 

+ 1
- 1
src/WebviewMessageHandler.js View File

57
     case `${actions.insertOrderedList}`:
57
     case `${actions.insertOrderedList}`:
58
       return `zss_editor.setOrderedList();`;
58
       return `zss_editor.setOrderedList();`;
59
     case `${actions.insertLink}`:
59
     case `${actions.insertLink}`:
60
-      return `zss_editor.insertLink('${action.data.url}, ${action.data.title}');`;
60
+      return `zss_editor.insertLink('${action.data.url}', '${action.data.title}');`;
61
     case `${actions.updateLink}`:
61
     case `${actions.updateLink}`:
62
       return `zss_editor.updateLink('${action.data.url}, ${action.data.title}');`;
62
       return `zss_editor.updateLink('${action.data.url}, ${action.data.title}');`;
63
     case `${actions.insertImage}`:
63
     case `${actions.insertImage}`:

+ 2
- 7
src/editor.html View File

1255
 			// Needs addClass method
1255
 			// Needs addClass method
1256
 
1256
 
1257
 			zss_editor.insertLink = function(url, title) {
1257
 			zss_editor.insertLink = function(url, title) {
1258
-
1259
 				zss_editor.restorerange();
1258
 				zss_editor.restorerange();
1260
-				var sel = document.getSelection();
1259
+				var sel = window.getSelection();
1261
 				sel.deleteFromDocument();
1260
 				sel.deleteFromDocument();
1262
-				document.execCommand('insertHTML',false,'<a href="'+encodeHtmlEntities(url)+'">'+encodeHtmlEntities(title)+'</a>');
1263
-
1261
+				zss_editor.insertHTML('<a href="'+ url +'">'+ title +'</a>');
1264
 				zss_editor.enabledEditingItems();
1262
 				zss_editor.enabledEditingItems();
1265
 			}
1263
 			}
1266
 
1264
 
1267
 			zss_editor.updateLink = function(url, title) {
1265
 			zss_editor.updateLink = function(url, title) {
1268
-
1269
 				zss_editor.restorerange();
1266
 				zss_editor.restorerange();
1270
-
1271
 				if (zss_editor.currentEditingLink) {
1267
 				if (zss_editor.currentEditingLink) {
1272
 					var c = zss_editor.currentEditingLink;
1268
 					var c = zss_editor.currentEditingLink;
1273
 					c.attr('href', url);
1269
 					c.attr('href', url);
1274
 					c.text(title);
1270
 					c.text(title);
1275
 				}
1271
 				}
1276
 				zss_editor.enabledEditingItems();
1272
 				zss_editor.enabledEditingItems();
1277
-
1278
 			}//end
1273
 			}//end
1279
 
1274
 
1280
 			zss_editor.updateImage = function(url, alt) {
1275
 			zss_editor.updateImage = function(url, alt) {