Browse Source

#WOA-2970|#WOA-2603|Fix update offset and cursor position calculation

ihork 8 years ago
parent
commit
e8997991c9
4 changed files with 78 additions and 32 deletions
  1. 35
    15
      src/RichTextEditor.js
  2. 6
    0
      src/WebviewMessageHandler.js
  3. 3
    1
      src/const.js
  4. 34
    16
      src/editor.html

+ 35
- 15
src/RichTextEditor.js View File

2
 import WebViewBridge from 'react-native-webview-bridge-updated';
2
 import WebViewBridge from 'react-native-webview-bridge-updated';
3
 import {InjectedMessageHandler} from './WebviewMessageHandler';
3
 import {InjectedMessageHandler} from './WebviewMessageHandler';
4
 import {actions, messages} from './const';
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
 const injectScript = `
7
 const injectScript = `
8
   (function () {
8
   (function () {
10
   }());
10
   }());
11
 `;
11
 `;
12
 
12
 
13
-const PlatfomIOS = Platform.OS === 'ios';
13
+const PlatformIOS = Platform.OS === 'ios';
14
 
14
 
15
 export default class RichTextEditor extends Component {
15
 export default class RichTextEditor extends Component {
16
   static propTypes = {
16
   static propTypes = {
43
   }
43
   }
44
 
44
 
45
   componentWillMount() {
45
   componentWillMount() {
46
-    if(PlatfomIOS) {
46
+    if(PlatformIOS) {
47
       this.keyboardEventListeners = [
47
       this.keyboardEventListeners = [
48
         Keyboard.addListener('keyboardWillShow', this._onKeyboardWillShow),
48
         Keyboard.addListener('keyboardWillShow', this._onKeyboardWillShow),
49
         Keyboard.addListener('keyboardWillHide', this._onKeyboardWillHide)
49
         Keyboard.addListener('keyboardWillHide', this._onKeyboardWillHide)
66
     if (this.state.keyboardHeight === newKeyboardHeight) {
66
     if (this.state.keyboardHeight === newKeyboardHeight) {
67
       return;
67
       return;
68
     }
68
     }
69
+    if (newKeyboardHeight) {
70
+      this.setEditorAvailableHeightBasedOnKeyboardHeight(newKeyboardHeight);
71
+    }
69
     this.setState({keyboardHeight: newKeyboardHeight});
72
     this.setState({keyboardHeight: newKeyboardHeight});
70
   }
73
   }
71
 
74
 
72
   _onKeyboardWillHide(event) {
75
   _onKeyboardWillHide(event) {
73
     this.setState({keyboardHeight: 0});
76
     this.setState({keyboardHeight: 0});
74
   }
77
   }
78
+
79
+  setEditorAvailableHeightBasedOnKeyboardHeight(keyboardHeight) {
80
+    const {top = 0, bottom = 0} = this.props.contentInset;
81
+    const {marginTop = 0, marginBottom = 0} = this.props.style;
82
+    const spacing = marginTop + marginBottom + top + bottom;
83
+
84
+    const editorAvailableHeight = Dimensions.get('window').height - keyboardHeight - spacing;
85
+    this.setEditorHeight(editorAvailableHeight);
86
+  }
75
   
87
   
76
   onBridgeMessage(str){
88
   onBridgeMessage(str){
77
     try {
89
     try {
177
             onRequestClose={() => this.setState({showLinkDialog: false})}
189
             onRequestClose={() => this.setState({showLinkDialog: false})}
178
         >
190
         >
179
           <View style={styles.modal}>
191
           <View style={styles.modal}>
180
-            <View style={[styles.innerModal, {marginBottom: PlatfomIOS ? this.state.keyboardHeight : 0}]}>
192
+            <View style={[styles.innerModal, {marginBottom: PlatformIOS ? this.state.keyboardHeight : 0}]}>
181
               <Text style={styles.inputTitle}>Title</Text>
193
               <Text style={styles.inputTitle}>Title</Text>
182
               <View style={styles.inputWrapper}>
194
               <View style={styles.inputWrapper}>
183
                 <TextInput
195
                 <TextInput
197
                     autoCorrect={false}
209
                     autoCorrect={false}
198
                 />
210
                 />
199
               </View>
211
               </View>
200
-              {PlatfomIOS && <View style={styles.lineSeparator}/>}
212
+              {PlatformIOS && <View style={styles.lineSeparator}/>}
201
               {this._renderModalButtons()}
213
               {this._renderModalButtons()}
202
             </View>
214
             </View>
203
           </View>
215
           </View>
216
 
228
 
217
   _renderModalButtons() {
229
   _renderModalButtons() {
218
     const insertUpdateDisabled = this.state.linkTitle.trim().length <= 0 || this.state.linkUrl.trim().length <= 0;
230
     const insertUpdateDisabled = this.state.linkTitle.trim().length <= 0 || this.state.linkUrl.trim().length <= 0;
219
-    const containerPlatformStyle = PlatfomIOS ? {justifyContent: 'space-between'} : {paddingTop: 15};
220
-    const buttonPlatformStyle = PlatfomIOS ? {flex: 1, height: 45, justifyContent: 'center'} : {};
231
+    const containerPlatformStyle = PlatformIOS ? {justifyContent: 'space-between'} : {paddingTop: 15};
232
+    const buttonPlatformStyle = PlatformIOS ? {flex: 1, height: 45, justifyContent: 'center'} : {};
221
     return (
233
     return (
222
       <View style={[{alignSelf: 'stretch', flexDirection: 'row'}, containerPlatformStyle]}>
234
       <View style={[{alignSelf: 'stretch', flexDirection: 'row'}, containerPlatformStyle]}>
223
-        {!PlatfomIOS && <View style={{flex: 1}}/>}
235
+        {!PlatformIOS && <View style={{flex: 1}}/>}
224
         <TouchableOpacity
236
         <TouchableOpacity
225
             onPress={() => this._hideModal()}
237
             onPress={() => this._hideModal()}
226
             style={buttonPlatformStyle}
238
             style={buttonPlatformStyle}
254
   }
266
   }
255
 
267
 
256
   _upperCaseButtonTextIfNeeded(buttonText) {
268
   _upperCaseButtonTextIfNeeded(buttonText) {
257
-    return PlatfomIOS ? buttonText : buttonText.toUpperCase();
269
+    return PlatformIOS ? buttonText : buttonText.toUpperCase();
258
   }
270
   }
259
 
271
 
260
   render() {
272
   render() {
261
     //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
273
     //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
262
-    const pageSource = PlatfomIOS ? require('./editor.html') : { uri: 'file:///android_asset/editor.html' };
274
+    const pageSource = PlatformIOS ? require('./editor.html') : { uri: 'file:///android_asset/editor.html' };
263
     return (
275
     return (
264
       <View style={{flex: 1}}>
276
       <View style={{flex: 1}}>
265
         <WebViewBridge
277
         <WebViewBridge
266
-          style={{flex: 1}}
267
           {...this.props}
278
           {...this.props}
268
           hideKeyboardAccessoryView={true}
279
           hideKeyboardAccessoryView={true}
269
           keyboardDisplayRequiresUserAction={false}
280
           keyboardDisplayRequiresUserAction={false}
492
 
503
 
493
   init() {
504
   init() {
494
     this._sendAction(actions.init);
505
     this._sendAction(actions.init);
506
+    this.setPlatform();
507
+  }
508
+
509
+  setEditorHeight(height) {
510
+    this._sendAction(actions.setEditorHeight, height);
511
+  }
512
+
513
+  setPlatform() {
514
+    this._sendAction(actions.setPlatform, Platform.OS);
495
   }
515
   }
496
 
516
 
497
   async getTitleHtml() {
517
   async getTitleHtml() {
571
   innerModal: {
591
   innerModal: {
572
     backgroundColor: 'rgba(255, 255, 255, 0.9)',
592
     backgroundColor: 'rgba(255, 255, 255, 0.9)',
573
     paddingTop: 20,
593
     paddingTop: 20,
574
-    paddingBottom: PlatfomIOS ? 0 : 20,
594
+    paddingBottom: PlatformIOS ? 0 : 20,
575
     paddingLeft: 20,
595
     paddingLeft: 20,
576
     paddingRight: 20,
596
     paddingRight: 20,
577
     alignSelf: 'stretch',
597
     alignSelf: 'stretch',
578
     margin: 40,
598
     margin: 40,
579
-    borderRadius: PlatfomIOS ? 8 : 2
599
+    borderRadius: PlatformIOS ? 8 : 2
580
   },
600
   },
581
   button: {
601
   button: {
582
     fontSize: 16,
602
     fontSize: 16,
587
     marginTop: 5,
607
     marginTop: 5,
588
     marginBottom: 10,
608
     marginBottom: 10,
589
     borderBottomColor: '#4a4a4a',
609
     borderBottomColor: '#4a4a4a',
590
-    borderBottomWidth: PlatfomIOS ? 1 / PixelRatio.get() : 0
610
+    borderBottomWidth: PlatformIOS ? 1 / PixelRatio.get() : 0
591
   },
611
   },
592
   inputTitle: {
612
   inputTitle: {
593
     color: '#4a4a4a'
613
     color: '#4a4a4a'
594
   },
614
   },
595
   input: {
615
   input: {
596
-    height: PlatfomIOS ? 20 : 40,
616
+    height: PlatformIOS ? 20 : 40,
597
     paddingTop: 0
617
     paddingTop: 0
598
   },
618
   },
599
   lineSeparator: {
619
   lineSeparator: {

+ 6
- 0
src/WebviewMessageHandler.js View File

161
         case '${actions.init}':
161
         case '${actions.init}':
162
           zss_editor.init();
162
           zss_editor.init();
163
           break;
163
           break;
164
+        case '${actions.setEditorHeight}':
165
+          zss_editor.setEditorHeight(action.data);
166
+          break;
167
+        case '${actions.setPlatform}':
168
+          zss_editor.setPlatform(action.data);
169
+          break;
164
       }
170
       }
165
     };
171
     };
166
   }
172
   }

+ 3
- 1
src/const.js View File

49
   setCustomCSS: 'SET_CUSTOM_CSS',
49
   setCustomCSS: 'SET_CUSTOM_CSS',
50
   setTextColor: 'SET_TEXT_COLOR',
50
   setTextColor: 'SET_TEXT_COLOR',
51
   setBackgroundColor: 'SET_BACKGROUND_COLOR',
51
   setBackgroundColor: 'SET_BACKGROUND_COLOR',
52
-  init: 'ZSSS_INIT'
52
+  init: 'ZSSS_INIT',
53
+  setEditorHeight: 'SET_EDITOR_HEIGHT',
54
+  setPlatform: 'SET_PLATFORM'
53
 };
55
 };
54
 
56
 
55
 
57
 

+ 34
- 16
src/editor.html View File

808
 			zss_editor.enabledItems = {};
808
 			zss_editor.enabledItems = {};
809
 
809
 
810
 			// Height of content window, will be set by viewController
810
 			// Height of content window, will be set by viewController
811
-			zss_editor.contentHeight = 244;
811
+			zss_editor.editorHeight = 244;
812
 
812
 
813
 			// Sets to true when extra footer gap shows and requires to hide
813
 			// Sets to true when extra footer gap shows and requires to hide
814
 			zss_editor.updateScrollOffset = false;
814
 			zss_editor.updateScrollOffset = false;
901
 				$(window).on('touchstart', function(e) {
901
 				$(window).on('touchstart', function(e) {
902
 					zss_editor.isDragging = false;
902
 					zss_editor.isDragging = false;
903
 				});
903
 				});
904
+				$(window).on('scroll', function(e) {
905
+					if (zss_editor.platform === 'ios') {
906
+						zss_editor.updateOffset();
907
+					}
908
+				});
904
 
909
 
905
 				setupTouchEndFocus('zss_editor_title');
910
 				setupTouchEndFocus('zss_editor_title');
906
 				setupTouchEndFocus('zss_editor_content');
911
 				setupTouchEndFocus('zss_editor_content');
952
 
957
 
953
 				var offsetY = window.document.body.scrollTop;
958
 				var offsetY = window.document.body.scrollTop;
954
 
959
 
955
-				var footer = $('#zss_editor_footer');
960
+				var footer = document.getElementById('zss_editor_footer');
956
 
961
 
957
-				var maxOffsetY = footer.offset().top - zss_editor.contentHeight;
962
+				var maxOffsetY = footer.offsetTop + footer.offsetHeight - zss_editor.editorHeight;
958
 
963
 
959
 				if (maxOffsetY < 0)
964
 				if (maxOffsetY < 0)
960
 					maxOffsetY = 0;
965
 					maxOffsetY = 0;
1020
 			}
1025
 			}
1021
 
1026
 
1022
 			zss_editor.calculateEditorHeightWithCaretPosition = function() {
1027
 			zss_editor.calculateEditorHeightWithCaretPosition = function() {
1023
-
1024
-				var padding = 50;
1025
-				var c = zss_editor.getCaretYPosition();
1026
-
1028
+				var caretYPosition = zss_editor.getCaretYPosition();
1029
+				var lineHeight = 20;
1030
+				var halfLineHeight = lineHeight/2;
1027
 				var offsetY = window.document.body.scrollTop;
1031
 				var offsetY = window.document.body.scrollTop;
1028
-				var height = zss_editor.contentHeight;
1029
-
1030
-				var newPos = window.pageYOffset;
1031
-
1032
-				if (c < offsetY) {
1033
-					newPos = c;
1034
-				} else if (c > (offsetY + height - padding)) {
1035
-					newPos = c - height + padding - 18;
1032
+				var editorHeight = zss_editor.editorHeight;
1033
+				var newPos;
1034
+
1035
+				var futureEditorHeight = caretYPosition + lineHeight;
1036
+				if (caretYPosition < offsetY) {
1037
+					newPos = caretYPosition;
1038
+				} else if (futureEditorHeight > editorHeight + offsetY) {
1039
+					newPos = futureEditorHeight - editorHeight + halfLineHeight;
1036
 				}
1040
 				}
1037
 
1041
 
1038
-				window.scrollTo(0, newPos);
1042
+				if (newPos) {
1043
+					window.scrollTo(0, newPos);
1044
+				}
1039
 			}
1045
 			}
1040
 
1046
 
1041
 			zss_editor.backuprange = function(){
1047
 			zss_editor.backuprange = function(){
1604
 				});
1610
 				});
1605
 			}
1611
 			}
1606
 
1612
 
1613
+			zss_editor.setEditorHeight = function(editorHeight) {
1614
+				zss_editor.editorHeight = editorHeight;
1615
+			}
1616
+
1617
+			zss_editor.setPlatform = function(platform) {
1618
+				zss_editor.platform = platform;
1619
+			}
1620
+
1607
 			//end
1621
 			//end
1608
 		</script>
1622
 		</script>
1609
 
1623
 
1696
 				padding-left: 10px;
1710
 				padding-left: 10px;
1697
 				padding-right: 10px;
1711
 				padding-right: 10px;
1698
 			}
1712
 			}
1713
+
1714
+			#zss_editor_footer {
1715
+				height: 10px;
1716
+			}
1699
 		</style>
1717
 		</style>
1700
 
1718
 
1701
 		<style type="text/css">
1719
 		<style type="text/css">