|
@@ -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} from 'react-native';
|
|
5
|
+import {Modal, View, Text, StyleSheet, TextInput, TouchableOpacity, Platform, PixelRatio, Keyboard} from 'react-native';
|
6
|
6
|
|
7
|
7
|
const injectScript = `
|
8
|
8
|
(function () {
|
|
@@ -10,6 +10,8 @@ const injectScript = `
|
10
|
10
|
}());
|
11
|
11
|
`;
|
12
|
12
|
|
|
13
|
+const PlatfomIOS = Platform.OS === 'ios';
|
|
14
|
+
|
13
|
15
|
export default class RichTextEditor extends Component {
|
14
|
16
|
static propTypes = {
|
15
|
17
|
initialTitleHTML: PropTypes.string,
|
|
@@ -25,14 +27,48 @@ export default class RichTextEditor extends Component {
|
25
|
27
|
this._sendAction = this._sendAction.bind(this);
|
26
|
28
|
this.registerToolbar = this.registerToolbar.bind(this);
|
27
|
29
|
this.onBridgeMessage = this.onBridgeMessage.bind(this);
|
|
30
|
+ this._onKeyboardWillShow = this._onKeyboardWillShow.bind(this);
|
|
31
|
+ this._onKeyboardWillHide = this._onKeyboardWillHide.bind(this);
|
28
|
32
|
this.state = {
|
29
|
33
|
listeners: [],
|
30
|
34
|
showLinkDialog: false,
|
31
|
35
|
linkTitle: '',
|
32
|
|
- linkUrl: ''
|
|
36
|
+ linkUrl: '',
|
|
37
|
+ keyboardHeight: 0
|
33
|
38
|
};
|
34
|
39
|
}
|
35
|
40
|
|
|
41
|
+ componentWillMount() {
|
|
42
|
+ if(PlatfomIOS) {
|
|
43
|
+ this.keyboardEventListeners = [
|
|
44
|
+ Keyboard.addListener('keyboardWillShow', this._onKeyboardWillShow),
|
|
45
|
+ Keyboard.addListener('keyboardWillHide', this._onKeyboardWillHide)
|
|
46
|
+ ];
|
|
47
|
+ } else {
|
|
48
|
+ this.keyboardEventListeners = [
|
|
49
|
+ Keyboard.addListener('keyboardDidShow', this._onKeyboardWillShow),
|
|
50
|
+ Keyboard.addListener('keyboardDidHide', this._onKeyboardWillHide)
|
|
51
|
+ ];
|
|
52
|
+ }
|
|
53
|
+ }
|
|
54
|
+
|
|
55
|
+ componentWillUnmount() {
|
|
56
|
+ this.keyboardEventListeners.forEach((eventListener) => eventListener.remove());
|
|
57
|
+ }
|
|
58
|
+
|
|
59
|
+ _onKeyboardWillShow(event) {
|
|
60
|
+ console.log('!!!!', event);
|
|
61
|
+ const newKeyboardHeight = event.endCoordinates.height;
|
|
62
|
+ if (this.state.keyboardHeight === newKeyboardHeight) {
|
|
63
|
+ return;
|
|
64
|
+ }
|
|
65
|
+ this.setState({keyboardHeight: newKeyboardHeight});
|
|
66
|
+ }
|
|
67
|
+
|
|
68
|
+ _onKeyboardWillHide(event) {
|
|
69
|
+ this.setState({keyboardHeight: 0});
|
|
70
|
+ }
|
|
71
|
+
|
36
|
72
|
onBridgeMessage(str){
|
37
|
73
|
try {
|
38
|
74
|
const message = JSON.parse(str);
|
|
@@ -102,11 +138,8 @@ export default class RichTextEditor extends Component {
|
102
|
138
|
onRequestClose={() => this.setState({showLinkDialog: false})}
|
103
|
139
|
>
|
104
|
140
|
<View style={styles.modal}>
|
105
|
|
-
|
106
|
|
-
|
107
|
|
- <View style={styles.innerModal}>
|
108
|
|
-
|
109
|
|
- <Text>Title</Text>
|
|
141
|
+ <View style={[styles.innerModal, {marginBottom: this.state.keyboardHeight}]}>
|
|
142
|
+ <Text style={styles.inputTitle}>Title</Text>
|
110
|
143
|
<View style={styles.inputWrapper}>
|
111
|
144
|
<TextInput
|
112
|
145
|
style={{height: 20}}
|
|
@@ -114,8 +147,7 @@ export default class RichTextEditor extends Component {
|
114
|
147
|
value={this.state.linkTitle}
|
115
|
148
|
/>
|
116
|
149
|
</View>
|
117
|
|
-
|
118
|
|
- <Text style={{marginTop: 10}}>URL</Text>
|
|
150
|
+ <Text style={[styles.inputTitle ,{marginTop: 10}]}>URL</Text>
|
119
|
151
|
<View style={styles.inputWrapper}>
|
120
|
152
|
<TextInput
|
121
|
153
|
style={{height: 20}}
|
|
@@ -123,7 +155,7 @@ export default class RichTextEditor extends Component {
|
123
|
155
|
value={this.state.linkUrl}
|
124
|
156
|
/>
|
125
|
157
|
</View>
|
126
|
|
-
|
|
158
|
+ {PlatfomIOS && <View style={styles.lineSeparator}/>}
|
127
|
159
|
{this._renderModalButtons()}
|
128
|
160
|
</View>
|
129
|
161
|
</View>
|
|
@@ -140,14 +172,18 @@ export default class RichTextEditor extends Component {
|
140
|
172
|
}
|
141
|
173
|
|
142
|
174
|
_renderModalButtons() {
|
|
175
|
+ const insertDisabled = this.state.linkTitle.length <= 0;
|
|
176
|
+ const containerPlatformStyle = PlatfomIOS ? {justifyContent: 'space-between'} : {paddingTop: 15};
|
|
177
|
+ const buttonPlatformStyle = PlatfomIOS ? {flex: 1, height: 45, justifyContent: 'center'} : {};
|
143
|
178
|
return (
|
144
|
|
- <View style={{paddingTop: 10, alignSelf: 'stretch', flexDirection: 'row'}}>
|
145
|
|
- <View style={{flex: 1}}/>
|
|
179
|
+ <View style={[{alignSelf: 'stretch', flexDirection: 'row'}, containerPlatformStyle]}>
|
|
180
|
+ {!PlatfomIOS && <View style={{flex: 1}}/>}
|
146
|
181
|
<TouchableOpacity
|
147
|
182
|
onPress={() => this._hideModal()}
|
|
183
|
+ style={buttonPlatformStyle}
|
148
|
184
|
>
|
149
|
185
|
<Text style={[styles.button, {paddingRight: 10}]}>
|
150
|
|
- Cancel
|
|
186
|
+ {PlatfomIOS ? 'Cancel' : 'CANCEL'}
|
151
|
187
|
</Text>
|
152
|
188
|
</TouchableOpacity>
|
153
|
189
|
<TouchableOpacity
|
|
@@ -155,9 +191,11 @@ export default class RichTextEditor extends Component {
|
155
|
191
|
this.insertLink(this.state.linkUrl, this.state.linkTitle);
|
156
|
192
|
this._hideModal();
|
157
|
193
|
}}
|
|
194
|
+ disabled={insertDisabled}
|
|
195
|
+ style={buttonPlatformStyle}
|
158
|
196
|
>
|
159
|
|
- <Text style={styles.button}>
|
160
|
|
- OK
|
|
197
|
+ <Text style={[styles.button, {opacity: insertDisabled ? 0.5 : 1}]}>
|
|
198
|
+ {PlatfomIOS ? 'Insert' : 'INSERT'}
|
161
|
199
|
</Text>
|
162
|
200
|
</TouchableOpacity>
|
163
|
201
|
</View>
|
|
@@ -166,7 +204,7 @@ export default class RichTextEditor extends Component {
|
166
|
204
|
|
167
|
205
|
render() {
|
168
|
206
|
//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
|
169
|
|
- const pageSource = Platform.OS === 'ios' ? require('./editor.html') : { uri: 'file:///android_asset/editor.html' };
|
|
207
|
+ const pageSource = PlatfomIOS ? require('./editor.html') : { uri: 'file:///android_asset/editor.html' };
|
170
|
208
|
return (
|
171
|
209
|
<View style={{flex: 1}}>
|
172
|
210
|
<WebViewBridge
|
|
@@ -427,18 +465,34 @@ const styles = StyleSheet.create({
|
427
|
465
|
backgroundColor: 'rgba(0, 0, 0, 0.5)'
|
428
|
466
|
},
|
429
|
467
|
innerModal: {
|
430
|
|
- backgroundColor: '#ffffff',
|
431
|
|
- padding: 20,
|
|
468
|
+ backgroundColor: 'rgba(255, 255, 255, 0.9)',
|
|
469
|
+ paddingTop: 20,
|
|
470
|
+ paddingBottom: PlatfomIOS ? 0 : 20,
|
|
471
|
+ paddingLeft: 20,
|
|
472
|
+ paddingRight: 20,
|
432
|
473
|
alignSelf: 'stretch',
|
433
|
|
- margin: 40
|
|
474
|
+ margin: 40,
|
|
475
|
+ borderRadius: PlatfomIOS ? 8 : 2
|
434
|
476
|
},
|
435
|
477
|
button: {
|
436
|
|
- fontSize: 16
|
|
478
|
+ fontSize: 16,
|
|
479
|
+ color: '#4a4a4a',
|
|
480
|
+ textAlign: 'center'
|
437
|
481
|
},
|
438
|
482
|
inputWrapper: {
|
439
|
|
- marginTop: 10,
|
|
483
|
+ marginTop: 5,
|
440
|
484
|
marginBottom: 10,
|
441
|
|
- borderBottomColor: '#000000',
|
442
|
|
- borderBottomWidth: 1
|
|
485
|
+ borderBottomColor: '#4a4a4a',
|
|
486
|
+ borderBottomWidth: PlatfomIOS ? 1 / PixelRatio.get() : 0
|
|
487
|
+ },
|
|
488
|
+ inputTitle: {
|
|
489
|
+ color: '#4a4a4a'
|
|
490
|
+ },
|
|
491
|
+ lineSeparator: {
|
|
492
|
+ height: 1 / PixelRatio.get(),
|
|
493
|
+ backgroundColor: '#d5d5d5',
|
|
494
|
+ marginLeft: -20,
|
|
495
|
+ marginRight: -20,
|
|
496
|
+ marginTop: 20
|
443
|
497
|
}
|
444
|
498
|
});
|