From 73ba7281ea37ff39f9ed68d447d97fd8249d0eac Mon Sep 17 00:00:00 2001 From: Simon Arneson Date: Mon, 22 Oct 2018 12:21:44 +0200 Subject: [PATCH 1/2] Update to use live fork (original) of webview bridge --- package.json | 2 +- src/RichTextEditor.js | 280 ++++++++++++++++++++++++------------------ 2 files changed, 163 insertions(+), 119 deletions(-) diff --git a/package.json b/package.json index 9ec89f52..5c383eac 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "main": "index.js", "license": "SEE LICENSE IN LICENSE", "dependencies": { - "react-native-webview-bridge-updated": "^1.0.0" + "react-native-webview-bridge": "0.40.1" }, "peerDependencies": { "react": "*", diff --git a/src/RichTextEditor.js b/src/RichTextEditor.js index 51e212ef..9c3dbac2 100644 --- a/src/RichTextEditor.js +++ b/src/RichTextEditor.js @@ -1,9 +1,20 @@ -import React, {Component} from 'react'; -import PropTypes from 'prop-types'; -import WebViewBridge from 'react-native-webview-bridge-updated'; -import {InjectedMessageHandler} from './WebviewMessageHandler'; -import {actions, messages} from './const'; -import {Modal, View, Text, StyleSheet, TextInput, TouchableOpacity, Platform, PixelRatio, Keyboard, Dimensions} from 'react-native'; +import React, { Component } from "react"; +import PropTypes from "prop-types"; +import WebViewBridge from "react-native-webview-bridge"; +import { InjectedMessageHandler } from "./WebviewMessageHandler"; +import { actions, messages } from "./const"; +import { + Modal, + View, + Text, + StyleSheet, + TextInput, + TouchableOpacity, + Platform, + PixelRatio, + Keyboard, + Dimensions +} from "react-native"; const injectScript = ` (function () { @@ -11,7 +22,7 @@ const injectScript = ` }()); `; -const PlatformIOS = Platform.OS === 'ios'; +const PlatformIOS = Platform.OS === "ios"; export default class RichTextEditor extends Component { static propTypes = { @@ -43,34 +54,36 @@ export default class RichTextEditor extends Component { selectionChangeListeners: [], onChange: [], showLinkDialog: false, - linkInitialUrl: '', - linkTitle: '', - linkUrl: '', + linkInitialUrl: "", + linkTitle: "", + linkUrl: "", keyboardHeight: 0 }; this._selectedTextChangeListeners = []; } componentWillMount() { - if(PlatformIOS) { + if (PlatformIOS) { this.keyboardEventListeners = [ - Keyboard.addListener('keyboardWillShow', this._onKeyboardWillShow), - Keyboard.addListener('keyboardWillHide', this._onKeyboardWillHide) + Keyboard.addListener("keyboardWillShow", this._onKeyboardWillShow), + Keyboard.addListener("keyboardWillHide", this._onKeyboardWillHide) ]; } else { this.keyboardEventListeners = [ - Keyboard.addListener('keyboardDidShow', this._onKeyboardWillShow), - Keyboard.addListener('keyboardDidHide', this._onKeyboardWillHide) + Keyboard.addListener("keyboardDidShow", this._onKeyboardWillShow), + Keyboard.addListener("keyboardDidHide", this._onKeyboardWillHide) ]; } } componentWillUnmount() { - this.keyboardEventListeners.forEach((eventListener) => eventListener.remove()); + this.keyboardEventListeners.forEach(eventListener => + eventListener.remove() + ); } _onKeyboardWillShow(event) { - console.log('!!!!', event); + console.log("!!!!", event); const newKeyboardHeight = event.endCoordinates.height; if (this.state.keyboardHeight === newKeyboardHeight) { return; @@ -78,23 +91,24 @@ export default class RichTextEditor extends Component { if (newKeyboardHeight) { this.setEditorAvailableHeightBasedOnKeyboardHeight(newKeyboardHeight); } - this.setState({keyboardHeight: newKeyboardHeight}); + this.setState({ keyboardHeight: newKeyboardHeight }); } _onKeyboardWillHide(event) { - this.setState({keyboardHeight: 0}); + this.setState({ keyboardHeight: 0 }); } setEditorAvailableHeightBasedOnKeyboardHeight(keyboardHeight) { - const {top = 0, bottom = 0} = this.props.contentInset; - const {marginTop = 0, marginBottom = 0} = this.props.style; + const { top = 0, bottom = 0 } = this.props.contentInset; + const { marginTop = 0, marginBottom = 0 } = this.props.style; const spacing = marginTop + marginBottom + top + bottom; - const editorAvailableHeight = Dimensions.get('window').height - keyboardHeight - spacing; + const editorAvailableHeight = + Dimensions.get("window").height - keyboardHeight - spacing; this.setEditorHeight(editorAvailableHeight); } - onBridgeMessage(str){ + onBridgeMessage(str) { try { const message = JSON.parse(str); @@ -155,19 +169,22 @@ export default class RichTextEditor extends Component { this.props.hiddenTitle && this.hideTitle(); this.props.enableOnChange && this.enableOnChange(); - this.props.editorInitializedCallback && this.props.editorInitializedCallback(); + this.props.editorInitializedCallback && + this.props.editorInitializedCallback(); break; case messages.LINK_TOUCHED: this.prepareInsert(); - const {title, url} = message.data; + const { title, url } = message.data; this.showLinkDialog(title, url); break; case messages.LOG: - console.log('FROM ZSS', message.data); + console.log("FROM ZSS", message.data); break; case messages.SCROLL: - this.webviewBridge.setNativeProps({contentOffset: {y: message.data}}); + this.webviewBridge.setNativeProps({ + contentOffset: { y: message.data } + }); break; case messages.TITLE_FOCUSED: this.titleFocusHandler && this.titleFocusHandler(); @@ -177,104 +194,124 @@ export default class RichTextEditor extends Component { break; case messages.SELECTION_CHANGE: { const items = message.data.items; - this.state.selectionChangeListeners.map((listener) => { + this.state.selectionChangeListeners.map(listener => { listener(items); }); break; } case messages.CONTENT_CHANGE: { const content = message.data.content; - this.state.onChange.map((listener) => listener(content)); + this.state.onChange.map(listener => listener(content)); break; } case messages.SELECTED_TEXT_CHANGED: { const selectedText = message.data; - this._selectedTextChangeListeners.forEach((listener) => { + this._selectedTextChangeListeners.forEach(listener => { listener(selectedText); }); break; } } - } catch(e) { + } catch (e) { //alert('NON JSON MESSAGE'); } } _renderLinkModal() { return ( - this.setState({showLinkDialog: false})} - > - - - Title - - this.setState({linkTitle: text})} - value={this.state.linkTitle} - /> - - URL - - this.setState({linkUrl: text})} - value={this.state.linkUrl} - keyboardType="url" - autoCapitalize="none" - autoCorrect={false} - /> - - {PlatformIOS && } - {this._renderModalButtons()} + this.setState({ showLinkDialog: false })} + > + + + Title + + this.setState({ linkTitle: text })} + value={this.state.linkTitle} + /> + URL + + this.setState({ linkUrl: text })} + value={this.state.linkUrl} + keyboardType="url" + autoCapitalize="none" + autoCorrect={false} + /> + + {PlatformIOS && } + {this._renderModalButtons()} - + + ); } _hideModal() { this.setState({ showLinkDialog: false, - linkInitialUrl: '', - linkTitle: '', - linkUrl: '' - }) + linkInitialUrl: "", + linkTitle: "", + linkUrl: "" + }); } _renderModalButtons() { - const insertUpdateDisabled = this.state.linkTitle.trim().length <= 0 || this.state.linkUrl.trim().length <= 0; - const containerPlatformStyle = PlatformIOS ? {justifyContent: 'space-between'} : {paddingTop: 15}; - const buttonPlatformStyle = PlatformIOS ? {flex: 1, height: 45, justifyContent: 'center'} : {}; + const insertUpdateDisabled = + this.state.linkTitle.trim().length <= 0 || + this.state.linkUrl.trim().length <= 0; + const containerPlatformStyle = PlatformIOS + ? { justifyContent: "space-between" } + : { paddingTop: 15 }; + const buttonPlatformStyle = PlatformIOS + ? { flex: 1, height: 45, justifyContent: "center" } + : {}; return ( - - {!PlatformIOS && } + + {!PlatformIOS && } this._hideModal()} - style={buttonPlatformStyle} + onPress={() => this._hideModal()} + style={buttonPlatformStyle} > - - {this._upperCaseButtonTextIfNeeded('Cancel')} + + {this._upperCaseButtonTextIfNeeded("Cancel")} { - if (this._linkIsNew()) { - this.insertLink(this.state.linkUrl, this.state.linkTitle); - } else { - this.updateLink(this.state.linkUrl, this.state.linkTitle); - } - this._hideModal(); - }} - disabled={insertUpdateDisabled} - style={buttonPlatformStyle} + onPress={() => { + if (this._linkIsNew()) { + this.insertLink(this.state.linkUrl, this.state.linkTitle); + } else { + this.updateLink(this.state.linkUrl, this.state.linkTitle); + } + this._hideModal(); + }} + disabled={insertUpdateDisabled} + style={buttonPlatformStyle} > - - {this._upperCaseButtonTextIfNeeded(this._linkIsNew() ? 'Insert' : 'Update')} + + {this._upperCaseButtonTextIfNeeded( + this._linkIsNew() ? "Insert" : "Update" + )} @@ -291,15 +328,19 @@ export default class RichTextEditor extends Component { render() { //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 - const pageSource = PlatformIOS ? require('./editor.html') : { uri: 'file:///android_asset/editor.html' }; + const pageSource = PlatformIOS + ? require("./editor.html") + : { uri: "file:///android_asset/editor.html" }; return ( - + {this.webviewBridge = r}} - onBridgeMessage={(message) => this.onBridgeMessage(message)} + ref={r => { + this.webviewBridge = r; + }} + onBridgeMessage={message => this.onBridgeMessage(message)} injectedJavaScript={injectScript} source={pageSource} onLoad={() => this.init()} @@ -311,19 +352,19 @@ export default class RichTextEditor extends Component { escapeJSONString = function(string) { return string - .replace(/[\\]/g, '\\\\') - .replace(/[\"]/g, '\\\"') - .replace(/[\']/g, '\\\'') - .replace(/[\/]/g, '\\/') - .replace(/[\b]/g, '\\b') - .replace(/[\f]/g, '\\f') - .replace(/[\n]/g, '\\n') - .replace(/[\r]/g, '\\r') - .replace(/[\t]/g, '\\t'); + .replace(/[\\]/g, "\\\\") + .replace(/[\"]/g, '\\"') + .replace(/[\']/g, "\\'") + .replace(/[\/]/g, "\\/") + .replace(/[\b]/g, "\\b") + .replace(/[\f]/g, "\\f") + .replace(/[\n]/g, "\\n") + .replace(/[\r]/g, "\\r") + .replace(/[\t]/g, "\\t"); }; _sendAction(action, data) { - let jsonString = JSON.stringify({type: action, data}); + let jsonString = JSON.stringify({ type: action, data }); jsonString = this.escapeJSONString(jsonString); this.webviewBridge.sendToBridge(jsonString); } @@ -331,7 +372,7 @@ export default class RichTextEditor extends Component { //------------------------------------------------------------------------------- //--------------- Public API - showLinkDialog(optionalTitle = '', optionalUrl = '') { + showLinkDialog(optionalTitle = "", optionalUrl = "") { this.setState({ linkInitialUrl: optionalUrl, linkTitle: optionalTitle, @@ -350,7 +391,10 @@ export default class RichTextEditor extends Component { registerToolbar(listener) { this.setState({ - selectionChangeListeners: [...this.state.selectionChangeListeners, listener] + selectionChangeListeners: [ + ...this.state.selectionChangeListeners, + listener + ] }); } @@ -457,11 +501,11 @@ export default class RichTextEditor extends Component { } insertLink(url, title) { - this._sendAction(actions.insertLink, {url, title}); + this._sendAction(actions.insertLink, { url, title }); } updateLink(url, title) { - this._sendAction(actions.updateLink, {url, title}); + this._sendAction(actions.updateLink, { url, title }); } insertImage(attributes) { @@ -549,7 +593,7 @@ export default class RichTextEditor extends Component { this.pendingTitleHtml = setTimeout(() => { if (this.titleReject) { - this.titleReject('timeout') + this.titleReject("timeout"); } }, 5000); }); @@ -563,7 +607,7 @@ export default class RichTextEditor extends Component { this.pendingTitleText = setTimeout(() => { if (this.titleTextReject) { - this.titleTextReject('timeout'); + this.titleTextReject("timeout"); } }, 5000); }); @@ -577,7 +621,7 @@ export default class RichTextEditor extends Component { this.pendingContentHtml = setTimeout(() => { if (this.contentReject) { - this.contentReject('timeout') + this.contentReject("timeout"); } }, 5000); }); @@ -591,7 +635,7 @@ export default class RichTextEditor extends Component { this.pendingSelectedText = setTimeout(() => { if (this.selectedTextReject) { - this.selectedTextReject('timeout') + this.selectedTextReject("timeout"); } }, 5000); }); @@ -615,33 +659,33 @@ export default class RichTextEditor extends Component { const styles = StyleSheet.create({ modal: { flex: 1, - justifyContent: 'center', - alignItems: 'center', - backgroundColor: 'rgba(0, 0, 0, 0.5)' + justifyContent: "center", + alignItems: "center", + backgroundColor: "rgba(0, 0, 0, 0.5)" }, innerModal: { - backgroundColor: 'rgba(255, 255, 255, 0.9)', + backgroundColor: "rgba(255, 255, 255, 0.9)", paddingTop: 20, paddingBottom: PlatformIOS ? 0 : 20, paddingLeft: 20, paddingRight: 20, - alignSelf: 'stretch', + alignSelf: "stretch", margin: 40, borderRadius: PlatformIOS ? 8 : 2 }, button: { fontSize: 16, - color: '#4a4a4a', - textAlign: 'center' + color: "#4a4a4a", + textAlign: "center" }, inputWrapper: { marginTop: 5, marginBottom: 10, - borderBottomColor: '#4a4a4a', + borderBottomColor: "#4a4a4a", borderBottomWidth: PlatformIOS ? 1 / PixelRatio.get() : 0 }, inputTitle: { - color: '#4a4a4a' + color: "#4a4a4a" }, input: { height: PlatformIOS ? 20 : 40, @@ -649,7 +693,7 @@ const styles = StyleSheet.create({ }, lineSeparator: { height: 1 / PixelRatio.get(), - backgroundColor: '#d5d5d5', + backgroundColor: "#d5d5d5", marginLeft: -20, marginRight: -20, marginTop: 20 From fbb230f70f05208e3fa09d058e0f9d304bcf3af8 Mon Sep 17 00:00:00 2001 From: Simon Arneson Date: Mon, 22 Oct 2018 12:26:41 +0200 Subject: [PATCH 2/2] Adhere to original linting rules --- src/RichTextEditor.js | 282 ++++++++++++++++++------------------------ 1 file changed, 119 insertions(+), 163 deletions(-) diff --git a/src/RichTextEditor.js b/src/RichTextEditor.js index 9c3dbac2..9fb63052 100644 --- a/src/RichTextEditor.js +++ b/src/RichTextEditor.js @@ -1,20 +1,9 @@ -import React, { Component } from "react"; -import PropTypes from "prop-types"; -import WebViewBridge from "react-native-webview-bridge"; -import { InjectedMessageHandler } from "./WebviewMessageHandler"; -import { actions, messages } from "./const"; -import { - Modal, - View, - Text, - StyleSheet, - TextInput, - TouchableOpacity, - Platform, - PixelRatio, - Keyboard, - Dimensions -} from "react-native"; +import React, {Component} from 'react'; +import PropTypes from 'prop-types'; +import WebViewBridge from 'react-native-webview-bridge'; +import {InjectedMessageHandler} from './WebviewMessageHandler'; +import {actions, messages} from './const'; +import {Modal, View, Text, StyleSheet, TextInput, TouchableOpacity, Platform, PixelRatio, Keyboard, Dimensions} from 'react-native'; const injectScript = ` (function () { @@ -22,7 +11,7 @@ const injectScript = ` }()); `; -const PlatformIOS = Platform.OS === "ios"; +const PlatformIOS = Platform.OS === 'ios'; export default class RichTextEditor extends Component { static propTypes = { @@ -54,36 +43,34 @@ export default class RichTextEditor extends Component { selectionChangeListeners: [], onChange: [], showLinkDialog: false, - linkInitialUrl: "", - linkTitle: "", - linkUrl: "", + linkInitialUrl: '', + linkTitle: '', + linkUrl: '', keyboardHeight: 0 }; this._selectedTextChangeListeners = []; } componentWillMount() { - if (PlatformIOS) { + if(PlatformIOS) { this.keyboardEventListeners = [ - Keyboard.addListener("keyboardWillShow", this._onKeyboardWillShow), - Keyboard.addListener("keyboardWillHide", this._onKeyboardWillHide) + Keyboard.addListener('keyboardWillShow', this._onKeyboardWillShow), + Keyboard.addListener('keyboardWillHide', this._onKeyboardWillHide) ]; } else { this.keyboardEventListeners = [ - Keyboard.addListener("keyboardDidShow", this._onKeyboardWillShow), - Keyboard.addListener("keyboardDidHide", this._onKeyboardWillHide) + Keyboard.addListener('keyboardDidShow', this._onKeyboardWillShow), + Keyboard.addListener('keyboardDidHide', this._onKeyboardWillHide) ]; } } componentWillUnmount() { - this.keyboardEventListeners.forEach(eventListener => - eventListener.remove() - ); + this.keyboardEventListeners.forEach((eventListener) => eventListener.remove()); } _onKeyboardWillShow(event) { - console.log("!!!!", event); + console.log('!!!!', event); const newKeyboardHeight = event.endCoordinates.height; if (this.state.keyboardHeight === newKeyboardHeight) { return; @@ -91,24 +78,23 @@ export default class RichTextEditor extends Component { if (newKeyboardHeight) { this.setEditorAvailableHeightBasedOnKeyboardHeight(newKeyboardHeight); } - this.setState({ keyboardHeight: newKeyboardHeight }); + this.setState({keyboardHeight: newKeyboardHeight}); } _onKeyboardWillHide(event) { - this.setState({ keyboardHeight: 0 }); + this.setState({keyboardHeight: 0}); } setEditorAvailableHeightBasedOnKeyboardHeight(keyboardHeight) { - const { top = 0, bottom = 0 } = this.props.contentInset; - const { marginTop = 0, marginBottom = 0 } = this.props.style; + const {top = 0, bottom = 0} = this.props.contentInset; + const {marginTop = 0, marginBottom = 0} = this.props.style; const spacing = marginTop + marginBottom + top + bottom; - const editorAvailableHeight = - Dimensions.get("window").height - keyboardHeight - spacing; + const editorAvailableHeight = Dimensions.get('window').height - keyboardHeight - spacing; this.setEditorHeight(editorAvailableHeight); } - onBridgeMessage(str) { + onBridgeMessage(str){ try { const message = JSON.parse(str); @@ -169,22 +155,19 @@ export default class RichTextEditor extends Component { this.props.hiddenTitle && this.hideTitle(); this.props.enableOnChange && this.enableOnChange(); - this.props.editorInitializedCallback && - this.props.editorInitializedCallback(); + this.props.editorInitializedCallback && this.props.editorInitializedCallback(); break; case messages.LINK_TOUCHED: this.prepareInsert(); - const { title, url } = message.data; + const {title, url} = message.data; this.showLinkDialog(title, url); break; case messages.LOG: - console.log("FROM ZSS", message.data); + console.log('FROM ZSS', message.data); break; case messages.SCROLL: - this.webviewBridge.setNativeProps({ - contentOffset: { y: message.data } - }); + this.webviewBridge.setNativeProps({contentOffset: {y: message.data}}); break; case messages.TITLE_FOCUSED: this.titleFocusHandler && this.titleFocusHandler(); @@ -194,124 +177,104 @@ export default class RichTextEditor extends Component { break; case messages.SELECTION_CHANGE: { const items = message.data.items; - this.state.selectionChangeListeners.map(listener => { + this.state.selectionChangeListeners.map((listener) => { listener(items); }); break; } case messages.CONTENT_CHANGE: { const content = message.data.content; - this.state.onChange.map(listener => listener(content)); + this.state.onChange.map((listener) => listener(content)); break; } case messages.SELECTED_TEXT_CHANGED: { const selectedText = message.data; - this._selectedTextChangeListeners.forEach(listener => { + this._selectedTextChangeListeners.forEach((listener) => { listener(selectedText); }); break; } } - } catch (e) { + } catch(e) { //alert('NON JSON MESSAGE'); } } _renderLinkModal() { return ( - this.setState({ showLinkDialog: false })} - > - - - Title - - this.setState({ linkTitle: text })} - value={this.state.linkTitle} - /> - - URL - - this.setState({ linkUrl: text })} - value={this.state.linkUrl} - keyboardType="url" - autoCapitalize="none" - autoCorrect={false} - /> + this.setState({showLinkDialog: false})} + > + + + Title + + this.setState({linkTitle: text})} + value={this.state.linkTitle} + /> + + URL + + this.setState({linkUrl: text})} + value={this.state.linkUrl} + keyboardType="url" + autoCapitalize="none" + autoCorrect={false} + /> + + {PlatformIOS && } + {this._renderModalButtons()} - {PlatformIOS && } - {this._renderModalButtons()} - - + ); } _hideModal() { this.setState({ showLinkDialog: false, - linkInitialUrl: "", - linkTitle: "", - linkUrl: "" - }); + linkInitialUrl: '', + linkTitle: '', + linkUrl: '' + }) } _renderModalButtons() { - const insertUpdateDisabled = - this.state.linkTitle.trim().length <= 0 || - this.state.linkUrl.trim().length <= 0; - const containerPlatformStyle = PlatformIOS - ? { justifyContent: "space-between" } - : { paddingTop: 15 }; - const buttonPlatformStyle = PlatformIOS - ? { flex: 1, height: 45, justifyContent: "center" } - : {}; + const insertUpdateDisabled = this.state.linkTitle.trim().length <= 0 || this.state.linkUrl.trim().length <= 0; + const containerPlatformStyle = PlatformIOS ? {justifyContent: 'space-between'} : {paddingTop: 15}; + const buttonPlatformStyle = PlatformIOS ? {flex: 1, height: 45, justifyContent: 'center'} : {}; return ( - - {!PlatformIOS && } + + {!PlatformIOS && } this._hideModal()} - style={buttonPlatformStyle} + onPress={() => this._hideModal()} + style={buttonPlatformStyle} > - - {this._upperCaseButtonTextIfNeeded("Cancel")} + + {this._upperCaseButtonTextIfNeeded('Cancel')} { - if (this._linkIsNew()) { - this.insertLink(this.state.linkUrl, this.state.linkTitle); - } else { - this.updateLink(this.state.linkUrl, this.state.linkTitle); - } - this._hideModal(); - }} - disabled={insertUpdateDisabled} - style={buttonPlatformStyle} + onPress={() => { + if (this._linkIsNew()) { + this.insertLink(this.state.linkUrl, this.state.linkTitle); + } else { + this.updateLink(this.state.linkUrl, this.state.linkTitle); + } + this._hideModal(); + }} + disabled={insertUpdateDisabled} + style={buttonPlatformStyle} > - - {this._upperCaseButtonTextIfNeeded( - this._linkIsNew() ? "Insert" : "Update" - )} + + {this._upperCaseButtonTextIfNeeded(this._linkIsNew() ? 'Insert' : 'Update')} @@ -328,19 +291,15 @@ export default class RichTextEditor extends Component { render() { //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 - const pageSource = PlatformIOS - ? require("./editor.html") - : { uri: "file:///android_asset/editor.html" }; + const pageSource = PlatformIOS ? require('./editor.html') : { uri: 'file:///android_asset/editor.html' }; return ( - + { - this.webviewBridge = r; - }} - onBridgeMessage={message => this.onBridgeMessage(message)} + ref={(r) => {this.webviewBridge = r}} + onBridgeMessage={(message) => this.onBridgeMessage(message)} injectedJavaScript={injectScript} source={pageSource} onLoad={() => this.init()} @@ -352,19 +311,19 @@ export default class RichTextEditor extends Component { escapeJSONString = function(string) { return string - .replace(/[\\]/g, "\\\\") - .replace(/[\"]/g, '\\"') - .replace(/[\']/g, "\\'") - .replace(/[\/]/g, "\\/") - .replace(/[\b]/g, "\\b") - .replace(/[\f]/g, "\\f") - .replace(/[\n]/g, "\\n") - .replace(/[\r]/g, "\\r") - .replace(/[\t]/g, "\\t"); + .replace(/[\\]/g, '\\\\') + .replace(/[\"]/g, '\\\"') + .replace(/[\']/g, '\\\'') + .replace(/[\/]/g, '\\/') + .replace(/[\b]/g, '\\b') + .replace(/[\f]/g, '\\f') + .replace(/[\n]/g, '\\n') + .replace(/[\r]/g, '\\r') + .replace(/[\t]/g, '\\t'); }; _sendAction(action, data) { - let jsonString = JSON.stringify({ type: action, data }); + let jsonString = JSON.stringify({type: action, data}); jsonString = this.escapeJSONString(jsonString); this.webviewBridge.sendToBridge(jsonString); } @@ -372,7 +331,7 @@ export default class RichTextEditor extends Component { //------------------------------------------------------------------------------- //--------------- Public API - showLinkDialog(optionalTitle = "", optionalUrl = "") { + showLinkDialog(optionalTitle = '', optionalUrl = '') { this.setState({ linkInitialUrl: optionalUrl, linkTitle: optionalTitle, @@ -391,10 +350,7 @@ export default class RichTextEditor extends Component { registerToolbar(listener) { this.setState({ - selectionChangeListeners: [ - ...this.state.selectionChangeListeners, - listener - ] + selectionChangeListeners: [...this.state.selectionChangeListeners, listener] }); } @@ -501,11 +457,11 @@ export default class RichTextEditor extends Component { } insertLink(url, title) { - this._sendAction(actions.insertLink, { url, title }); + this._sendAction(actions.insertLink, {url, title}); } updateLink(url, title) { - this._sendAction(actions.updateLink, { url, title }); + this._sendAction(actions.updateLink, {url, title}); } insertImage(attributes) { @@ -593,7 +549,7 @@ export default class RichTextEditor extends Component { this.pendingTitleHtml = setTimeout(() => { if (this.titleReject) { - this.titleReject("timeout"); + this.titleReject('timeout') } }, 5000); }); @@ -607,7 +563,7 @@ export default class RichTextEditor extends Component { this.pendingTitleText = setTimeout(() => { if (this.titleTextReject) { - this.titleTextReject("timeout"); + this.titleTextReject('timeout'); } }, 5000); }); @@ -621,7 +577,7 @@ export default class RichTextEditor extends Component { this.pendingContentHtml = setTimeout(() => { if (this.contentReject) { - this.contentReject("timeout"); + this.contentReject('timeout') } }, 5000); }); @@ -635,7 +591,7 @@ export default class RichTextEditor extends Component { this.pendingSelectedText = setTimeout(() => { if (this.selectedTextReject) { - this.selectedTextReject("timeout"); + this.selectedTextReject('timeout') } }, 5000); }); @@ -659,33 +615,33 @@ export default class RichTextEditor extends Component { const styles = StyleSheet.create({ modal: { flex: 1, - justifyContent: "center", - alignItems: "center", - backgroundColor: "rgba(0, 0, 0, 0.5)" + justifyContent: 'center', + alignItems: 'center', + backgroundColor: 'rgba(0, 0, 0, 0.5)' }, innerModal: { - backgroundColor: "rgba(255, 255, 255, 0.9)", + backgroundColor: 'rgba(255, 255, 255, 0.9)', paddingTop: 20, paddingBottom: PlatformIOS ? 0 : 20, paddingLeft: 20, paddingRight: 20, - alignSelf: "stretch", + alignSelf: 'stretch', margin: 40, borderRadius: PlatformIOS ? 8 : 2 }, button: { fontSize: 16, - color: "#4a4a4a", - textAlign: "center" + color: '#4a4a4a', + textAlign: 'center' }, inputWrapper: { marginTop: 5, marginBottom: 10, - borderBottomColor: "#4a4a4a", + borderBottomColor: '#4a4a4a', borderBottomWidth: PlatformIOS ? 1 / PixelRatio.get() : 0 }, inputTitle: { - color: "#4a4a4a" + color: '#4a4a4a' }, input: { height: PlatformIOS ? 20 : 40, @@ -693,9 +649,9 @@ const styles = StyleSheet.create({ }, lineSeparator: { height: 1 / PixelRatio.get(), - backgroundColor: "#d5d5d5", + backgroundColor: '#d5d5d5', marginLeft: -20, marginRight: -20, marginTop: 20 } -}); +}); \ No newline at end of file