|
@@ -32,6 +32,7 @@ export default class RichTextEditor extends Component {
|
32
|
32
|
this.state = {
|
33
|
33
|
listeners: [],
|
34
|
34
|
showLinkDialog: false,
|
|
35
|
+ linkInitialUrl: '',
|
35
|
36
|
linkTitle: '',
|
36
|
37
|
linkUrl: '',
|
37
|
38
|
keyboardHeight: 0
|
|
@@ -107,6 +108,17 @@ export default class RichTextEditor extends Component {
|
107
|
108
|
}
|
108
|
109
|
}
|
109
|
110
|
break;
|
|
111
|
+ case messages.SELECTED_TEXT_RESPONSE:
|
|
112
|
+ if (this.selectedTextResolve) {
|
|
113
|
+ this.selectedTextResolve(message.data);
|
|
114
|
+ this.selectedTextResolve = undefined;
|
|
115
|
+ this.selectedTextReject = undefined;
|
|
116
|
+ if (this.pendingSelectedText) {
|
|
117
|
+ clearTimeout(this.pendingSelectedText);
|
|
118
|
+ this.pendingSelectedText = undefined;
|
|
119
|
+ }
|
|
120
|
+ }
|
|
121
|
+ break;
|
110
|
122
|
case messages.ZSS_INITIALIZED:
|
111
|
123
|
if (this.props.customCSS) {
|
112
|
124
|
this.setCustomCSS(this.props.customCSS);
|
|
@@ -117,6 +129,11 @@ export default class RichTextEditor extends Component {
|
117
|
129
|
this.setContentHTML(this.props.initialContentHTML);
|
118
|
130
|
this.props.editorInitializedCallback && this.props.editorInitializedCallback();
|
119
|
131
|
|
|
132
|
+ break;
|
|
133
|
+ case messages.LINK_TOUCHED:
|
|
134
|
+ this.prepareInsert();
|
|
135
|
+ const {title, url} = message.data;
|
|
136
|
+ this.showLinkDialog(title, url);
|
120
|
137
|
break;
|
121
|
138
|
case messages.LOG:
|
122
|
139
|
console.log('FROM ZSS', message.data);
|
|
@@ -180,13 +197,14 @@ export default class RichTextEditor extends Component {
|
180
|
197
|
_hideModal() {
|
181
|
198
|
this.setState({
|
182
|
199
|
showLinkDialog: false,
|
|
200
|
+ linkInitialUrl: '',
|
183
|
201
|
linkTitle: '',
|
184
|
202
|
linkUrl: ''
|
185
|
203
|
})
|
186
|
204
|
}
|
187
|
205
|
|
188
|
206
|
_renderModalButtons() {
|
189
|
|
- const insertDisabled = this.state.linkTitle.trim().length <= 0 || this.state.linkUrl.trim().length <= 0;
|
|
207
|
+ const insertUpdateDisabled = this.state.linkTitle.trim().length <= 0 || this.state.linkUrl.trim().length <= 0;
|
190
|
208
|
const containerPlatformStyle = PlatfomIOS ? {justifyContent: 'space-between'} : {paddingTop: 15};
|
191
|
209
|
const buttonPlatformStyle = PlatfomIOS ? {flex: 1, height: 45, justifyContent: 'center'} : {};
|
192
|
210
|
return (
|
|
@@ -197,25 +215,37 @@ export default class RichTextEditor extends Component {
|
197
|
215
|
style={buttonPlatformStyle}
|
198
|
216
|
>
|
199
|
217
|
<Text style={[styles.button, {paddingRight: 10}]}>
|
200
|
|
- {PlatfomIOS ? 'Cancel' : 'CANCEL'}
|
|
218
|
+ {this._upperCaseButtonTextIfNeeded('Cancel')}
|
201
|
219
|
</Text>
|
202
|
220
|
</TouchableOpacity>
|
203
|
221
|
<TouchableOpacity
|
204
|
222
|
onPress={() => {
|
205
|
|
- this.insertLink(this.state.linkUrl, this.state.linkTitle);
|
|
223
|
+ if (this._linkIsNew()) {
|
|
224
|
+ this.insertLink(this.state.linkUrl, this.state.linkTitle);
|
|
225
|
+ } else {
|
|
226
|
+ this.updateLink(this.state.linkUrl, this.state.linkTitle);
|
|
227
|
+ }
|
206
|
228
|
this._hideModal();
|
207
|
229
|
}}
|
208
|
|
- disabled={insertDisabled}
|
|
230
|
+ disabled={insertUpdateDisabled}
|
209
|
231
|
style={buttonPlatformStyle}
|
210
|
232
|
>
|
211
|
|
- <Text style={[styles.button, {opacity: insertDisabled ? 0.5 : 1}]}>
|
212
|
|
- {PlatfomIOS ? 'Insert' : 'INSERT'}
|
|
233
|
+ <Text style={[styles.button, {opacity: insertUpdateDisabled ? 0.5 : 1}]}>
|
|
234
|
+ {this._upperCaseButtonTextIfNeeded(this._linkIsNew() ? 'Insert' : 'Update')}
|
213
|
235
|
</Text>
|
214
|
236
|
</TouchableOpacity>
|
215
|
237
|
</View>
|
216
|
238
|
);
|
217
|
239
|
}
|
218
|
240
|
|
|
241
|
+ _linkIsNew() {
|
|
242
|
+ return !this.state.linkInitialUrl;
|
|
243
|
+ }
|
|
244
|
+
|
|
245
|
+ _upperCaseButtonTextIfNeeded(buttonText) {
|
|
246
|
+ return PlatfomIOS ? buttonText : buttonText.toLowerCase();
|
|
247
|
+ }
|
|
248
|
+
|
219
|
249
|
render() {
|
220
|
250
|
//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
|
221
|
251
|
const pageSource = PlatfomIOS ? require('./editor.html') : { uri: 'file:///android_asset/editor.html' };
|
|
@@ -259,8 +289,11 @@ export default class RichTextEditor extends Component {
|
259
|
289
|
//-------------------------------------------------------------------------------
|
260
|
290
|
//--------------- Public API
|
261
|
291
|
|
262
|
|
- showLinkDialog() {
|
|
292
|
+ showLinkDialog(optionalTitle = '', optionalUrl = '') {
|
263
|
293
|
this.setState({
|
|
294
|
+ linkInitialUrl: optionalUrl,
|
|
295
|
+ linkTitle: optionalTitle,
|
|
296
|
+ linkUrl: optionalUrl,
|
264
|
297
|
showLinkDialog: true
|
265
|
298
|
});
|
266
|
299
|
}
|
|
@@ -364,10 +397,13 @@ export default class RichTextEditor extends Component {
|
364
|
397
|
}
|
365
|
398
|
|
366
|
399
|
insertLink(url, title) {
|
367
|
|
-
|
368
|
400
|
this._sendAction(actions.insertLink, {url, title});
|
369
|
401
|
}
|
370
|
402
|
|
|
403
|
+ updateLink(url, title) {
|
|
404
|
+ this._sendAction(actions.updateLink, {url, title});
|
|
405
|
+ }
|
|
406
|
+
|
371
|
407
|
insertImage(url, alt) {
|
372
|
408
|
this._sendAction(actions.insertImage, {url, alt});
|
373
|
409
|
this.prepareInsert(); //This must be called BEFORE insertImage. But WebViewBridge uses a stack :/
|
|
@@ -471,6 +507,20 @@ export default class RichTextEditor extends Component {
|
471
|
507
|
});
|
472
|
508
|
}
|
473
|
509
|
|
|
510
|
+ async getSelectedText() {
|
|
511
|
+ return new Promise((resolve, reject) => {
|
|
512
|
+ this.selectedTextResolve = resolve;
|
|
513
|
+ this.selectedTextReject = reject;
|
|
514
|
+ this._sendAction(actions.getSelectedText);
|
|
515
|
+
|
|
516
|
+ this.pendingSelectedText = setTimeout(() => {
|
|
517
|
+ if (this.selectedTextReject) {
|
|
518
|
+ this.selectedTextReject('timeout')
|
|
519
|
+ }
|
|
520
|
+ }, 5000);
|
|
521
|
+ });
|
|
522
|
+ }
|
|
523
|
+
|
474
|
524
|
setTitleFocusHandler(callbackHandler) {
|
475
|
525
|
this.titleFocusHandler = callbackHandler;
|
476
|
526
|
this._sendAction(actions.setTitleFocusHandler);
|