Browse Source

Use es6 class instead of createClass

Kai Guo 4 years ago
parent
commit
a8bb6334c0
2 changed files with 144 additions and 98 deletions
  1. 129
    98
      src/WebView.windows.tsx
  2. 15
    0
      src/WebViewTypes.ts

+ 129
- 98
src/WebView.windows.tsx View File

17
   requireNativeComponent,
17
   requireNativeComponent,
18
   StyleSheet,
18
   StyleSheet,
19
   Image,
19
   Image,
20
+  ImageSourcePropType,
20
   findNodeHandle,
21
   findNodeHandle,
21
 } from 'react-native';
22
 } from 'react-native';
22
 import {
23
 import {
24
+  createOnShouldStartLoadWithRequest,
25
+} from './WebViewShared';
26
+import {
27
+  NativeWebViewWindows,
28
+  WindowsWebViewProps,
29
+  WebViewProgressEvent,
23
   WebViewNavigationEvent,
30
   WebViewNavigationEvent,
31
+  WebViewErrorEvent,
32
+  WebViewHttpErrorEvent,
33
+  WebViewMessageEvent,
24
   RNCWebViewUIManagerWindows,
34
   RNCWebViewUIManagerWindows,
35
+  State,
25
 } from './WebViewTypes';
36
 } from './WebViewTypes';
26
 
37
 
27
 const UIManager = NotTypedUIManager as RNCWebViewUIManagerWindows;
38
 const UIManager = NotTypedUIManager as RNCWebViewUIManagerWindows;
28
-var keyMirror = require('fbjs/lib/keyMirror');
29
 const { resolveAssetSource } = Image;
39
 const { resolveAssetSource } = Image;
30
-
31
-const createReactClass = require('create-react-class');
32
-
33
-var RCT_WEBVIEW_REF = 'webview';
34
-
35
-var WebViewState = keyMirror({
36
-  IDLE: null,
37
-  LOADING: null,
38
-  ERROR: null,
39
-});
40
-
41
-/**
42
- * Renders a native WebView.
43
- */
44
-var WebView = createReactClass({
45
-  getInitialState: function() {
46
-    return {
47
-      viewState: WebViewState.IDLE,
48
-      lastErrorEvent: null,
49
-      startInLoadingState: true,
50
-    };
51
-  },
52
-
53
-  getDefaultProps: function() {
54
-    return {
55
-      javaScriptEnabled: true,
56
-    };
57
-  },
58
-
59
-  componentDidMount: function() {
60
-    if (this.props.startInLoadingState) {
61
-      this.setState({viewState: WebViewState.LOADING});
62
-    }
63
-  },
64
-
65
-  render: function() {
66
-    var otherView = null;
67
-
68
-    if (this.state.viewState === WebViewState.LOADING) {
40
+const RCTWebView: typeof NativeWebViewWindows = requireNativeComponent(
41
+  'RCTWebView',
42
+);
43
+
44
+export default class WebView extends React.Component<WindowsWebViewProps, State> {
45
+
46
+  static defaultProps = {
47
+    javaScriptEnabled: true,
48
+  };
49
+
50
+  state: State = {
51
+    viewState: this.props.startInLoadingState ? 'LOADING' : 'IDLE',
52
+    lastErrorEvent: null,
53
+  }
54
+
55
+  webViewRef = React.createRef<NativeWebViewWindows>();
56
+
57
+  render = () => {
58
+    const {
59
+      nativeConfig = {},
60
+      onMessage,
61
+      onShouldStartLoadWithRequest: onShouldStartLoadWithRequestProp,
62
+      originWhitelist,
63
+      renderError,
64
+      renderLoading,
65
+      style,
66
+      containerStyle,
67
+      ...otherProps
68
+    } = this.props;
69
+
70
+    let otherView = null;
71
+
72
+    if (this.state.viewState === 'LOADING') {
69
       otherView = this.props.renderLoading && this.props.renderLoading();
73
       otherView = this.props.renderLoading && this.props.renderLoading();
70
-    } else if (this.state.viewState === WebViewState.ERROR) {
71
-      var errorEvent = this.state.lastErrorEvent;
74
+    } else if (this.state.viewState === 'ERROR') {
75
+      const errorEvent = this.state.lastErrorEvent;
72
       otherView =
76
       otherView =
73
         this.props.renderError &&
77
         this.props.renderError &&
74
         this.props.renderError(
78
         this.props.renderError(
76
           errorEvent.code,
80
           errorEvent.code,
77
           errorEvent.description,
81
           errorEvent.description,
78
         );
82
         );
79
-    } else if (this.state.viewState !== WebViewState.IDLE) {
83
+    } else if (this.state.viewState !== 'IDLE') {
80
       console.error(
84
       console.error(
81
-        'RCTWebView invalid state encountered: ' + this.state.loading,
85
+        'RCTWebView invalid state encountered: ' + this.state.viewState,
82
       );
86
       );
83
     }
87
     }
84
 
88
 
85
-    var webViewStyles = [styles.container, this.props.style];
89
+    let webViewStyles = [styles.container, this.props.style];
86
     if (
90
     if (
87
-      this.state.viewState === WebViewState.LOADING ||
88
-      this.state.viewState === WebViewState.ERROR
91
+      this.state.viewState === 'LOADING' ||
92
+      this.state.viewState === 'ERROR'
89
     ) {
93
     ) {
90
       // if we're in either LOADING or ERROR states, don't show the webView
94
       // if we're in either LOADING or ERROR states, don't show the webView
91
       webViewStyles.push(styles.hidden);
95
       webViewStyles.push(styles.hidden);
92
     }
96
     }
93
 
97
 
94
-    var source = this.props.source || {};
95
-    if (this.props.html) {
96
-      source.html = this.props.html;
97
-    } else if (this.props.url) {
98
-      source.uri = this.props.url;
99
-    }
98
+    const onShouldStartLoadWithRequest = createOnShouldStartLoadWithRequest(
99
+      this.onShouldStartLoadWithRequestCallback,
100
+      // casting cause it's in the default props
101
+      originWhitelist as readonly string[],
102
+      onShouldStartLoadWithRequestProp,
103
+    );
104
+
105
+    const NativeWebView
106
+    = (nativeConfig.component as typeof NativeWebViewWindows | undefined)
107
+    || RCTWebView;
100
 
108
 
101
-    var webView = (
102
-      <RCTWebView
103
-        ref={RCT_WEBVIEW_REF}
109
+    const webView = (
110
+      <NativeWebView
111
+        ref={this.webViewRef}
104
         key="webViewKey"
112
         key="webViewKey"
105
-        style={webViewStyles}
106
-        source={resolveAssetSource(source)}
107
-        injectedJavaScript={this.props.injectedJavaScript}
108
-        javaScriptEnabled={this.props.javaScriptEnabled}
109
-        indexedDbEnabled={this.props.indexedDbEnabled}
110
-        contentInset={this.props.contentInset}
111
-        automaticallyAdjustContentInsets={
112
-          this.props.automaticallyAdjustContentInsets
113
-        }
114
-        onLoadingStart={this.onLoadingStart}
115
-        onLoadingFinish={this.onLoadingFinish}
113
+        {...otherProps}
114
+        messagingEnabled={typeof onMessage === 'function'}
116
         onLoadingError={this.onLoadingError}
115
         onLoadingError={this.onLoadingError}
117
-        goBack={this.goBack}
118
-        goForward={this.goForward}
119
-        reload={this.reload}
120
-        testID={this.props.testID}
116
+        onLoadingFinish={this.onLoadingFinish}
117
+        onLoadingProgress={this.onLoadingProgress}
118
+        onLoadingStart={this.onLoadingStart}
119
+        onHttpError={this.onHttpError}
120
+        onMessage={this.onMessage}
121
+        onScroll={this.props.onScroll}
122
+        onShouldStartLoadWithRequest={onShouldStartLoadWithRequest}
123
+        source={resolveAssetSource(this.props.source as ImageSourcePropType)}
124
+        style={webViewStyles}
125
+        {...nativeConfig.props}
121
       />
126
       />
122
     );
127
     );
123
 
128
 
127
         {otherView}
132
         {otherView}
128
       </View>
133
       </View>
129
     );
134
     );
130
-  },
135
+  }
131
 
136
 
132
-  goForward: function() {
137
+  goForward = () => {
133
     UIManager.dispatchViewManagerCommand(
138
     UIManager.dispatchViewManagerCommand(
134
       this.getWebViewHandle(),
139
       this.getWebViewHandle(),
135
       UIManager.getViewManagerConfig('RCTWebView').Commands.goForward,
140
       UIManager.getViewManagerConfig('RCTWebView').Commands.goForward,
136
       undefined,
141
       undefined,
137
     );
142
     );
138
-  },
143
+  }
139
 
144
 
140
-  goBack: function() {
145
+  goBack = () => {
141
     UIManager.dispatchViewManagerCommand(
146
     UIManager.dispatchViewManagerCommand(
142
       this.getWebViewHandle(),
147
       this.getWebViewHandle(),
143
       UIManager.getViewManagerConfig('RCTWebView').Commands.goBack,
148
       UIManager.getViewManagerConfig('RCTWebView').Commands.goBack,
144
       undefined,
149
       undefined,
145
     );
150
     );
146
-  },
151
+  }
147
 
152
 
148
-  reload: function() {
153
+  reload = () => {
149
     UIManager.dispatchViewManagerCommand(
154
     UIManager.dispatchViewManagerCommand(
150
       this.getWebViewHandle(),
155
       this.getWebViewHandle(),
151
       UIManager.getViewManagerConfig('RCTWebView').Commands.reload,
156
       UIManager.getViewManagerConfig('RCTWebView').Commands.reload,
152
       undefined,
157
       undefined,
153
     );
158
     );
154
-  },
159
+  }
155
 
160
 
156
   /**
161
   /**
157
    * We return an event with a bunch of fields including:
162
    * We return an event with a bunch of fields including:
158
    *  url, title, loading, canGoBack, canGoForward
163
    *  url, title, loading, canGoBack, canGoForward
159
    */
164
    */
160
-  updateNavigationState: function(event: WebViewNavigationEvent) {
165
+  updateNavigationState = (event: WebViewNavigationEvent) => {
161
     if (this.props.onNavigationStateChange) {
166
     if (this.props.onNavigationStateChange) {
162
       this.props.onNavigationStateChange(event.nativeEvent);
167
       this.props.onNavigationStateChange(event.nativeEvent);
163
     }
168
     }
164
-  },
169
+  }
165
 
170
 
166
-  getWebViewHandle: function() {
171
+  getWebViewHandle = () => {
167
     // eslint-disable-next-line react/no-string-refs
172
     // eslint-disable-next-line react/no-string-refs
168
-    return findNodeHandle(this.refs[RCT_WEBVIEW_REF]);
169
-  },
173
+    return findNodeHandle(this.webViewRef.current);
174
+  }
170
 
175
 
171
-  onLoadingStart: function(event: WebViewNavigationEvent) {
172
-    var onLoadStart = this.props.onLoadStart;
176
+  onLoadingStart = (event: WebViewNavigationEvent) => {
177
+    const { onLoadStart } = this.props;
173
     onLoadStart && onLoadStart(event);
178
     onLoadStart && onLoadStart(event);
174
     this.updateNavigationState(event);
179
     this.updateNavigationState(event);
175
-  },
180
+  }
176
 
181
 
177
-  onLoadingError: function(event: WebViewNavigationEvent) {
182
+  onLoadingProgress = (event: WebViewProgressEvent) => {
183
+    const { onLoadProgress } = this.props;
184
+    if (onLoadProgress) {
185
+      onLoadProgress(event);
186
+    }
187
+  };
188
+
189
+  onLoadingError = (event: WebViewErrorEvent) => {
178
     event.persist(); // persist this event because we need to store it
190
     event.persist(); // persist this event because we need to store it
179
-    var {onError, onLoadEnd} = this.props;
191
+    const {onError, onLoadEnd} = this.props;
180
     onError && onError(event);
192
     onError && onError(event);
181
     onLoadEnd && onLoadEnd(event);
193
     onLoadEnd && onLoadEnd(event);
182
     console.error('Encountered an error loading page', event.nativeEvent);
194
     console.error('Encountered an error loading page', event.nativeEvent);
183
-    // $FlowFixMe : Not sure what the issue here is, disabling to get flow check turned on
184
     this.setState({
195
     this.setState({
185
       lastErrorEvent: event.nativeEvent,
196
       lastErrorEvent: event.nativeEvent,
186
-      viewState: WebViewState.ERROR,
197
+      viewState: 'ERROR',
187
     });
198
     });
188
-  },
199
+  }
189
 
200
 
190
-  onLoadingFinish: function(event: WebViewNavigationEvent) {
191
-    var {onLoad, onLoadEnd} = this.props;
201
+  onLoadingFinish =(event: WebViewNavigationEvent) => {
202
+    const {onLoad, onLoadEnd} = this.props;
192
     onLoad && onLoad(event);
203
     onLoad && onLoad(event);
193
     onLoadEnd && onLoadEnd(event);
204
     onLoadEnd && onLoadEnd(event);
194
     this.setState({
205
     this.setState({
195
-      viewState: WebViewState.IDLE,
206
+      viewState: 'IDLE',
196
     });
207
     });
197
     this.updateNavigationState(event);
208
     this.updateNavigationState(event);
198
-  },
199
-});
209
+  }
210
+
211
+  onMessage = (event: WebViewMessageEvent) => {
212
+    const { onMessage } = this.props;
213
+    if (onMessage) {
214
+      onMessage(event);
215
+    }
216
+  };
217
+
218
+  onHttpError = (event: WebViewHttpErrorEvent) => {
219
+    const { onHttpError } = this.props;
220
+    if (onHttpError) {
221
+      onHttpError(event);
222
+    }
223
+  }
224
+
225
+  onShouldStartLoadWithRequestCallback = (
226
+    _shouldStart: boolean,
227
+    _url: string,
228
+    _lockIdentifier: number,
229
+  ) => {
230
+  };
200
 
231
 
201
-var RCTWebView = requireNativeComponent('RCTWebView');
232
+}
202
 
233
 
203
-var styles = StyleSheet.create({
234
+const styles = StyleSheet.create({
204
   container: {
235
   container: {
205
     flex: 1,
236
     flex: 1,
206
   },
237
   },

+ 15
- 0
src/WebViewTypes.ts View File

74
   typeof NativeWebViewAndroidComponent;
74
   typeof NativeWebViewAndroidComponent;
75
 export class NativeWebViewAndroid extends NativeWebViewAndroidBase {}
75
 export class NativeWebViewAndroid extends NativeWebViewAndroidBase {}
76
 
76
 
77
+// eslint-disable-next-line react/prefer-stateless-function
78
+declare class NativeWebViewWindowsComponent extends Component<
79
+  WindowsNativeWebViewProps
80
+> {}
81
+declare const NativeWebViewWindowsBase: Constructor<NativeMethodsMixin> &
82
+  typeof NativeWebViewWindowsComponent;
83
+export class NativeWebViewWindows extends NativeWebViewWindowsBase {}
84
+
77
 export interface ContentInsetProp {
85
 export interface ContentInsetProp {
78
   top?: number;
86
   top?: number;
79
   left?: number;
87
   left?: number;
310
   onContentProcessDidTerminate?: (event: WebViewTerminatedEvent) => void;
318
   onContentProcessDidTerminate?: (event: WebViewTerminatedEvent) => void;
311
 }
319
 }
312
 
320
 
321
+export interface WindowsNativeWebViewProps extends CommonNativeWebViewProps {
322
+  testID?:string
323
+}
324
+
313
 export interface IOSWebViewProps extends WebViewSharedProps {
325
 export interface IOSWebViewProps extends WebViewSharedProps {
314
   /**
326
   /**
315
    * Does not store any data within the lifetime of the WebView.
327
    * Does not store any data within the lifetime of the WebView.
754
   allowsFullscreenVideo?: boolean;
766
   allowsFullscreenVideo?: boolean;
755
 }
767
 }
756
 
768
 
769
+export interface WindowsWebViewProps extends WebViewSharedProps{
770
+}
771
+
757
 export interface WebViewSharedProps extends ViewProps {
772
 export interface WebViewSharedProps extends ViewProps {
758
   /**
773
   /**
759
    * Loads static html or a uri (with optional headers) in the WebView.
774
    * Loads static html or a uri (with optional headers) in the WebView.