Skip to content

Commit 7961a91

Browse files
committed
#WOA-2354|Resolved|Improve link dialog
1 parent 3bb2868 commit 7961a91

File tree

5 files changed

+91
-41
lines changed

5 files changed

+91
-41
lines changed

src/RichTextEditor.js

Lines changed: 58 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ export default class RichTextEditor extends Component {
3232
this.state = {
3333
listeners: [],
3434
showLinkDialog: false,
35+
linkInitialUrl: '',
3536
linkTitle: '',
3637
linkUrl: '',
3738
keyboardHeight: 0
@@ -107,6 +108,17 @@ export default class RichTextEditor extends Component {
107108
}
108109
}
109110
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;
110122
case messages.ZSS_INITIALIZED:
111123
if (this.props.customCSS) {
112124
this.setCustomCSS(this.props.customCSS);
@@ -117,6 +129,11 @@ export default class RichTextEditor extends Component {
117129
this.setContentHTML(this.props.initialContentHTML);
118130
this.props.editorInitializedCallback && this.props.editorInitializedCallback();
119131

132+
break;
133+
case messages.LINK_TOUCHED:
134+
this.prepareInsert();
135+
const {title, url} = message.data;
136+
this.showLinkDialog(title, url);
120137
break;
121138
case messages.LOG:
122139
console.log('FROM ZSS', message.data);
@@ -180,13 +197,14 @@ export default class RichTextEditor extends Component {
180197
_hideModal() {
181198
this.setState({
182199
showLinkDialog: false,
200+
linkInitialUrl: '',
183201
linkTitle: '',
184202
linkUrl: ''
185203
})
186204
}
187205

188206
_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;
190208
const containerPlatformStyle = PlatfomIOS ? {justifyContent: 'space-between'} : {paddingTop: 15};
191209
const buttonPlatformStyle = PlatfomIOS ? {flex: 1, height: 45, justifyContent: 'center'} : {};
192210
return (
@@ -197,25 +215,37 @@ export default class RichTextEditor extends Component {
197215
style={buttonPlatformStyle}
198216
>
199217
<Text style={[styles.button, {paddingRight: 10}]}>
200-
{PlatfomIOS ? 'Cancel' : 'CANCEL'}
218+
{this._upperCaseButtonTextIfNeeded('Cancel')}
201219
</Text>
202220
</TouchableOpacity>
203221
<TouchableOpacity
204222
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+
}
206228
this._hideModal();
207229
}}
208-
disabled={insertDisabled}
230+
disabled={insertUpdateDisabled}
209231
style={buttonPlatformStyle}
210232
>
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')}
213235
</Text>
214236
</TouchableOpacity>
215237
</View>
216238
);
217239
}
218240

241+
_linkIsNew() {
242+
return !this.state.linkInitialUrl;
243+
}
244+
245+
_upperCaseButtonTextIfNeeded(buttonText) {
246+
return PlatfomIOS ? buttonText : buttonText.toLowerCase();
247+
}
248+
219249
render() {
220250
//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
221251
const pageSource = PlatfomIOS ? require('./editor.html') : { uri: 'file:///android_asset/editor.html' };
@@ -259,8 +289,11 @@ export default class RichTextEditor extends Component {
259289
//-------------------------------------------------------------------------------
260290
//--------------- Public API
261291

262-
showLinkDialog() {
292+
showLinkDialog(optionalTitle = '', optionalUrl = '') {
263293
this.setState({
294+
linkInitialUrl: optionalUrl,
295+
linkTitle: optionalTitle,
296+
linkUrl: optionalUrl,
264297
showLinkDialog: true
265298
});
266299
}
@@ -364,10 +397,13 @@ export default class RichTextEditor extends Component {
364397
}
365398

366399
insertLink(url, title) {
367-
368400
this._sendAction(actions.insertLink, {url, title});
369401
}
370402

403+
updateLink(url, title) {
404+
this._sendAction(actions.updateLink, {url, title});
405+
}
406+
371407
insertImage(url, alt) {
372408
this._sendAction(actions.insertImage, {url, alt});
373409
this.prepareInsert(); //This must be called BEFORE insertImage. But WebViewBridge uses a stack :/
@@ -471,6 +507,20 @@ export default class RichTextEditor extends Component {
471507
});
472508
}
473509

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+
474524
setTitleFocusHandler(callbackHandler) {
475525
this.titleFocusHandler = callbackHandler;
476526
this._sendAction(actions.setTitleFocusHandler);

src/RichTextToolbar.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,9 @@ export default class RichTextToolbar extends Component {
167167
if(this.props.onPressAddLink) {
168168
this.props.onPressAddLink();
169169
} else {
170-
this.state.editor.showLinkDialog();
170+
this.state.editor.getSelectedText().then(selectedText => {
171+
this.state.editor.showLinkDialog(selectedText);
172+
});
171173
}
172174
break;
173175
case actions.insertImage:

src/WebviewMessageHandler.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ export const InjectedMessageHandler = `
7373
case '${actions.insertLink}':
7474
zss_editor.insertLink(action.data.url, action.data.title);
7575
break;
76+
case '${actions.updateLink}':
77+
zss_editor.updateLink(action.data.url, action.data.title);
78+
break;
7679
case '${actions.insertImage}':
7780
zss_editor.insertImage(action.data.url, action.data.alt);
7881
break;
@@ -118,6 +121,10 @@ export const InjectedMessageHandler = `
118121
case '${actions.setContentFocusHandler}':
119122
zss_editor.setContentFocusHandler();
120123
break;
124+
case '${actions.getSelectedText}':
125+
var selectedText = getSelection().toString();
126+
WebViewBridge.send(JSON.stringify({type: '${messages.SELECTED_TEXT_RESPONSE}', data: selectedText}));
127+
break;
121128
case '${actions.focusContent}':
122129
zss_editor.focusContent();
123130
break;

src/const.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export const actions = {
44
getTitleHtml: 'GET_TITLE_HTML',
55
getTitleText: 'GET_TITLE_TEXT',
66
getContentHtml: 'GET_CONTENT_HTML',
7+
getSelectedText: 'GET_SELECTED_TEXT',
78
blurTitleEditor: 'BLUR_TITLE_EDITOR',
89
blurContentEditor: 'BLUR_CONTENT_EDITOR',
910
focusTitle: 'FOCUS_TITLE',
@@ -27,6 +28,7 @@ export const actions = {
2728
insertBulletsList: 'unorderedList',
2829
insertOrderedList: 'orderedList',
2930
insertLink: 'INST_LINK',
31+
updateLink: 'UPDATE_LINK',
3032
insertImage: 'INST_IMAGE',
3133
setSubscript: 'subscript',
3234
setSuperscript: 'superscript',
@@ -56,5 +58,7 @@ export const messages = {
5658
LOG: 'LOG',
5759
TITLE_FOCUSED: 'TITLE_FOCUSED',
5860
CONTENT_FOCUSED: 'CONTENT_FOCUSED',
59-
SELECTION_CHANGE: 'SELECTION_CHANGE'
61+
SELECTION_CHANGE: 'SELECTION_CHANGE',
62+
SELECTED_TEXT_RESPONSE: 'SELECTED_TEXT_RESPONSE',
63+
LINK_TOUCHED: 'LINK_TOUCHED'
6064
};

src/editor.html

Lines changed: 18 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -851,6 +851,20 @@
851851
}
852852
}
853853

854+
function setCurrentEditingLinkOnTouch() {
855+
$('#zss_editor_content').delegate('a', 'touchend', function(event) {
856+
var anchor = $(event.currentTarget);
857+
858+
zss_editor.currentEditingLink = anchor;
859+
860+
var link = {
861+
title: anchor.text(),
862+
url: anchor.attr('href')
863+
};
864+
WebViewBridge.send(JSON.stringify({type: 'LINK_TOUCHED', data: link}))
865+
});
866+
}
867+
854868
function preventLinkFollowingOnTouch() {
855869
$('#zss_editor_content').delegate('a', 'touchend', function(event) {
856870
event.preventDefault();
@@ -886,6 +900,7 @@
886900
setupTouchEndFocus('zss_editor_title');
887901
setupTouchEndFocus('zss_editor_content');
888902

903+
setCurrentEditingLinkOnTouch();
889904
preventLinkFollowingOnTouch();
890905

891906
whenPastingInsertAsPlainText('zss_editor_title');
@@ -1219,24 +1234,8 @@
12191234

12201235
zss_editor.restorerange();
12211236
var sel = document.getSelection();
1222-
console.log(sel);
1223-
if (sel.toString().length != 0) {
1224-
if (sel.rangeCount) {
1225-
1226-
var el = document.createElement("a");
1227-
el.setAttribute("href", url);
1228-
el.setAttribute("title", title);
1229-
1230-
var range = sel.getRangeAt(0).cloneRange();
1231-
range.surroundContents(el);
1232-
sel.removeAllRanges();
1233-
sel.addRange(range);
1234-
}
1235-
}
1236-
else
1237-
{
1238-
document.execCommand("insertHTML",false,"<a href='"+url+"'>"+title+"</a>");
1239-
}
1237+
sel.deleteFromDocument();
1238+
document.execCommand("insertHTML",false,"<a href='"+url+"'>"+title+"</a>");
12401239

12411240
zss_editor.enabledEditingItems();
12421241
}
@@ -1248,7 +1247,7 @@
12481247
if (zss_editor.currentEditingLink) {
12491248
var c = zss_editor.currentEditingLink;
12501249
c.attr('href', url);
1251-
c.attr('title', title);
1250+
c.text(title);
12521251
}
12531252
zss_editor.enabledEditingItems();
12541253

@@ -1493,18 +1492,6 @@
14931492
items.push('fonts');
14941493
}
14951494

1496-
// Link
1497-
if (nodeName == 'a') {
1498-
zss_editor.currentEditingLink = t;
1499-
var title = t.attr('title');
1500-
items.push('link:'+t.attr('href'));
1501-
if (t.attr('title') !== undefined) {
1502-
items.push('link-title:'+t.attr('title'));
1503-
}
1504-
1505-
} else {
1506-
zss_editor.currentEditingLink = null;
1507-
}
15081495
// Blockquote
15091496
if (nodeName == 'blockquote') {
15101497
items.push('indent');

0 commit comments

Comments
 (0)