@@ -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 ) ;
0 commit comments