Explorar el Código

Merge pull request #8 from wix/update-offset-and-cursor-calculation-fix

Fix update offset and cursor position calculation
Igor Khudik hace 7 años
padre
commit
e3469110ef
Se han modificado 4 ficheros con 87 adiciones y 33 borrados
  1. 44
    16
      src/RichTextEditor.js
  2. 9
    0
      src/WebviewMessageHandler.js
  3. 4
    1
      src/const.js
  4. 30
    16
      src/editor.html

+ 44
- 16
src/RichTextEditor.js Ver fichero

@@ -2,7 +2,7 @@ import React, {Component, PropTypes} from 'react';
2 2
 import WebViewBridge from 'react-native-webview-bridge-updated';
3 3
 import {InjectedMessageHandler} from './WebviewMessageHandler';
4 4
 import {actions, messages} from './const';
5
-import {Modal, View, Text, StyleSheet, TextInput, TouchableOpacity, Platform, PixelRatio, Keyboard} from 'react-native';
5
+import {Modal, View, Text, StyleSheet, TextInput, TouchableOpacity, Platform, PixelRatio, Keyboard, Dimensions} from 'react-native';
6 6
 
7 7
 const injectScript = `
8 8
   (function () {
@@ -10,7 +10,7 @@ const injectScript = `
10 10
   }());
11 11
 `;
12 12
 
13
-const PlatfomIOS = Platform.OS === 'ios';
13
+const PlatformIOS = Platform.OS === 'ios';
14 14
 
15 15
 export default class RichTextEditor extends Component {
16 16
   static propTypes = {
@@ -21,7 +21,8 @@ export default class RichTextEditor extends Component {
21 21
     editorInitializedCallback: PropTypes.func,
22 22
     customCSS: PropTypes.string,
23 23
     hiddenTitle: PropTypes.bool,
24
-    enableOnChange: PropTypes.bool
24
+    enableOnChange: PropTypes.bool,
25
+    footerHeight: PropTypes.number
25 26
   };
26 27
 
27 28
   constructor(props) {
@@ -44,7 +45,7 @@ export default class RichTextEditor extends Component {
44 45
   }
45 46
 
46 47
   componentWillMount() {
47
-    if(PlatfomIOS) {
48
+    if(PlatformIOS) {
48 49
       this.keyboardEventListeners = [
49 50
         Keyboard.addListener('keyboardWillShow', this._onKeyboardWillShow),
50 51
         Keyboard.addListener('keyboardWillHide', this._onKeyboardWillHide)
@@ -67,12 +68,24 @@ export default class RichTextEditor extends Component {
67 68
     if (this.state.keyboardHeight === newKeyboardHeight) {
68 69
       return;
69 70
     }
71
+    if (newKeyboardHeight) {
72
+      this.setEditorAvailableHeightBasedOnKeyboardHeight(newKeyboardHeight);
73
+    }
70 74
     this.setState({keyboardHeight: newKeyboardHeight});
71 75
   }
72 76
 
73 77
   _onKeyboardWillHide(event) {
74 78
     this.setState({keyboardHeight: 0});
75 79
   }
80
+
81
+  setEditorAvailableHeightBasedOnKeyboardHeight(keyboardHeight) {
82
+    const {top = 0, bottom = 0} = this.props.contentInset;
83
+    const {marginTop = 0, marginBottom = 0} = this.props.style;
84
+    const spacing = marginTop + marginBottom + top + bottom;
85
+
86
+    const editorAvailableHeight = Dimensions.get('window').height - keyboardHeight - spacing;
87
+    this.setEditorHeight(editorAvailableHeight);
88
+  }
76 89
   
77 90
   onBridgeMessage(str){
78 91
     try {
@@ -189,7 +202,7 @@ export default class RichTextEditor extends Component {
189 202
             onRequestClose={() => this.setState({showLinkDialog: false})}
190 203
         >
191 204
           <View style={styles.modal}>
192
-            <View style={[styles.innerModal, {marginBottom: PlatfomIOS ? this.state.keyboardHeight : 0}]}>
205
+            <View style={[styles.innerModal, {marginBottom: PlatformIOS ? this.state.keyboardHeight : 0}]}>
193 206
               <Text style={styles.inputTitle}>Title</Text>
194 207
               <View style={styles.inputWrapper}>
195 208
                 <TextInput
@@ -209,7 +222,7 @@ export default class RichTextEditor extends Component {
209 222
                     autoCorrect={false}
210 223
                 />
211 224
               </View>
212
-              {PlatfomIOS && <View style={styles.lineSeparator}/>}
225
+              {PlatformIOS && <View style={styles.lineSeparator}/>}
213 226
               {this._renderModalButtons()}
214 227
             </View>
215 228
           </View>
@@ -228,11 +241,11 @@ export default class RichTextEditor extends Component {
228 241
 
229 242
   _renderModalButtons() {
230 243
     const insertUpdateDisabled = this.state.linkTitle.trim().length <= 0 || this.state.linkUrl.trim().length <= 0;
231
-    const containerPlatformStyle = PlatfomIOS ? {justifyContent: 'space-between'} : {paddingTop: 15};
232
-    const buttonPlatformStyle = PlatfomIOS ? {flex: 1, height: 45, justifyContent: 'center'} : {};
244
+    const containerPlatformStyle = PlatformIOS ? {justifyContent: 'space-between'} : {paddingTop: 15};
245
+    const buttonPlatformStyle = PlatformIOS ? {flex: 1, height: 45, justifyContent: 'center'} : {};
233 246
     return (
234 247
       <View style={[{alignSelf: 'stretch', flexDirection: 'row'}, containerPlatformStyle]}>
235
-        {!PlatfomIOS && <View style={{flex: 1}}/>}
248
+        {!PlatformIOS && <View style={{flex: 1}}/>}
236 249
         <TouchableOpacity
237 250
             onPress={() => this._hideModal()}
238 251
             style={buttonPlatformStyle}
@@ -266,16 +279,15 @@ export default class RichTextEditor extends Component {
266 279
   }
267 280
 
268 281
   _upperCaseButtonTextIfNeeded(buttonText) {
269
-    return PlatfomIOS ? buttonText : buttonText.toUpperCase();
282
+    return PlatformIOS ? buttonText : buttonText.toUpperCase();
270 283
   }
271 284
 
272 285
   render() {
273 286
     //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
274
-    const pageSource = PlatfomIOS ? require('./editor.html') : { uri: 'file:///android_asset/editor.html' };
287
+    const pageSource = PlatformIOS ? require('./editor.html') : { uri: 'file:///android_asset/editor.html' };
275 288
     return (
276 289
       <View style={{flex: 1}}>
277 290
         <WebViewBridge
278
-          style={{flex: 1}}
279 291
           {...this.props}
280 292
           hideKeyboardAccessoryView={true}
281 293
           keyboardDisplayRequiresUserAction={false}
@@ -504,6 +516,22 @@ export default class RichTextEditor extends Component {
504 516
 
505 517
   init() {
506 518
     this._sendAction(actions.init);
519
+    this.setPlatform();
520
+    if (this.props.footerHeight) {
521
+      this.setFooterHeight();
522
+    }
523
+  }
524
+
525
+  setEditorHeight(height) {
526
+    this._sendAction(actions.setEditorHeight, height);
527
+  }
528
+
529
+  setFooterHeight() {
530
+    this._sendAction(actions.setFooterHeight, this.props.footerHeight);
531
+  }
532
+
533
+  setPlatform() {
534
+    this._sendAction(actions.setPlatform, Platform.OS);
507 535
   }
508 536
 
509 537
   async getTitleHtml() {
@@ -587,12 +615,12 @@ const styles = StyleSheet.create({
587 615
   innerModal: {
588 616
     backgroundColor: 'rgba(255, 255, 255, 0.9)',
589 617
     paddingTop: 20,
590
-    paddingBottom: PlatfomIOS ? 0 : 20,
618
+    paddingBottom: PlatformIOS ? 0 : 20,
591 619
     paddingLeft: 20,
592 620
     paddingRight: 20,
593 621
     alignSelf: 'stretch',
594 622
     margin: 40,
595
-    borderRadius: PlatfomIOS ? 8 : 2
623
+    borderRadius: PlatformIOS ? 8 : 2
596 624
   },
597 625
   button: {
598 626
     fontSize: 16,
@@ -603,13 +631,13 @@ const styles = StyleSheet.create({
603 631
     marginTop: 5,
604 632
     marginBottom: 10,
605 633
     borderBottomColor: '#4a4a4a',
606
-    borderBottomWidth: PlatfomIOS ? 1 / PixelRatio.get() : 0
634
+    borderBottomWidth: PlatformIOS ? 1 / PixelRatio.get() : 0
607 635
   },
608 636
   inputTitle: {
609 637
     color: '#4a4a4a'
610 638
   },
611 639
   input: {
612
-    height: PlatfomIOS ? 20 : 40,
640
+    height: PlatformIOS ? 20 : 40,
613 641
     paddingTop: 0
614 642
   },
615 643
   lineSeparator: {

+ 9
- 0
src/WebviewMessageHandler.js Ver fichero

@@ -161,6 +161,15 @@ export const InjectedMessageHandler = `
161 161
         case '${actions.init}':
162 162
           zss_editor.init();
163 163
           break;
164
+        case '${actions.setEditorHeight}':
165
+          zss_editor.setEditorHeight(action.data);
166
+          break;
167
+        case '${actions.setFooterHeight}':
168
+          zss_editor.setFooterHeight(action.data);
169
+          break;
170
+        case '${actions.setPlatform}':
171
+          zss_editor.setPlatform(action.data);
172
+          break;
164 173
       }
165 174
     };
166 175
   }

+ 4
- 1
src/const.js Ver fichero

@@ -49,7 +49,10 @@ export const actions = {
49 49
   setCustomCSS: 'SET_CUSTOM_CSS',
50 50
   setTextColor: 'SET_TEXT_COLOR',
51 51
   setBackgroundColor: 'SET_BACKGROUND_COLOR',
52
-  init: 'ZSSS_INIT'
52
+  init: 'ZSSS_INIT',
53
+  setEditorHeight: 'SET_EDITOR_HEIGHT',
54
+  setFooterHeight: 'SET_FOOTER_HEIGHT',
55
+  setPlatform: 'SET_PLATFORM'
53 56
 };
54 57
 
55 58
 

+ 30
- 16
src/editor.html Ver fichero

@@ -808,7 +808,7 @@
808 808
 			zss_editor.enabledItems = {};
809 809
 
810 810
 			// Height of content window, will be set by viewController
811
-			zss_editor.contentHeight = 244;
811
+			zss_editor.editorHeight = 244;
812 812
 
813 813
 			// Sets to true when extra footer gap shows and requires to hide
814 814
 			zss_editor.updateScrollOffset = false;
@@ -902,6 +902,11 @@
902 902
 				$(window).on('touchstart', function(e) {
903 903
 					zss_editor.isDragging = false;
904 904
 				});
905
+				$(window).on('scroll', function(e) {
906
+					if (zss_editor.platform === 'ios') {
907
+						zss_editor.updateOffset();
908
+					}
909
+				});
905 910
 
906 911
 				setupTouchEndFocus('zss_editor_title');
907 912
 				setupTouchEndFocus('zss_editor_content');
@@ -965,9 +970,9 @@
965 970
 
966 971
 				var offsetY = window.document.body.scrollTop;
967 972
 
968
-				var footer = $('#zss_editor_footer');
973
+				var footer = document.getElementById('zss_editor_footer');
969 974
 
970
-				var maxOffsetY = footer.offset().top - zss_editor.contentHeight;
975
+				var maxOffsetY = footer.offsetTop + footer.offsetHeight - zss_editor.editorHeight;
971 976
 
972 977
 				if (maxOffsetY < 0)
973 978
 					maxOffsetY = 0;
@@ -1033,22 +1038,23 @@
1033 1038
 			}
1034 1039
 
1035 1040
 			zss_editor.calculateEditorHeightWithCaretPosition = function() {
1036
-
1037
-				var padding = 50;
1038
-				var c = zss_editor.getCaretYPosition();
1039
-
1041
+				var caretYPosition = zss_editor.getCaretYPosition();
1042
+				var lineHeight = 20;
1043
+				var halfLineHeight = lineHeight/2;
1040 1044
 				var offsetY = window.document.body.scrollTop;
1041
-				var height = zss_editor.contentHeight;
1042
-
1043
-				var newPos = window.pageYOffset;
1044
-
1045
-				if (c < offsetY) {
1046
-					newPos = c;
1047
-				} else if (c > (offsetY + height - padding)) {
1048
-					newPos = c - height + padding - 18;
1045
+				var editorHeight = zss_editor.editorHeight;
1046
+				var newPos;
1047
+
1048
+				var futureEditorHeight = caretYPosition + lineHeight;
1049
+				if (caretYPosition < offsetY) {
1050
+					newPos = caretYPosition;
1051
+				} else if (futureEditorHeight > editorHeight + offsetY) {
1052
+					newPos = futureEditorHeight - editorHeight + halfLineHeight;
1049 1053
 				}
1050 1054
 
1051
-				window.scrollTo(0, newPos);
1055
+				if (newPos) {
1056
+					window.scrollTo(0, newPos);
1057
+				}
1052 1058
 			}
1053 1059
 
1054 1060
 			zss_editor.backuprange = function(){
@@ -1629,6 +1635,14 @@
1629 1635
 				});
1630 1636
 			}
1631 1637
 
1638
+			zss_editor.setEditorHeight = function(editorHeight) {
1639
+				zss_editor.editorHeight = editorHeight;
1640
+			}
1641
+
1642
+			zss_editor.setPlatform = function(platform) {
1643
+				zss_editor.platform = platform;
1644
+			}
1645
+
1632 1646
 			//end
1633 1647
 		</script>
1634 1648