No Description

WebViewShared.tsx 2.3KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. import escapeStringRegexp from 'escape-string-regexp';
  2. import React from 'react';
  3. import { Linking, View, ActivityIndicator, Text } from 'react-native';
  4. import {
  5. WebViewNavigationEvent,
  6. OnShouldStartLoadWithRequest,
  7. } from './WebViewTypes';
  8. import styles from './WebView.styles';
  9. const defaultOriginWhitelist = ['http://*', 'https://*'];
  10. const extractOrigin = (url: string): string => {
  11. const result = /^[A-Za-z][A-Za-z0-9+\-.]+:(\/\/)?[^/]*/.exec(url);
  12. return result === null ? '' : result[0];
  13. };
  14. const originWhitelistToRegex = (originWhitelist: string): string =>
  15. `^${escapeStringRegexp(originWhitelist).replace(/\\\*/g, '.*')}`;
  16. const passesWhitelist = (
  17. compiledWhitelist: readonly string[],
  18. url: string,
  19. ) => {
  20. const origin = extractOrigin(url);
  21. return compiledWhitelist.some(x => new RegExp(x).test(origin));
  22. };
  23. const compileWhitelist = (
  24. originWhitelist: readonly string[],
  25. ): readonly string[] =>
  26. ['about:blank', ...(originWhitelist || [])].map(originWhitelistToRegex);
  27. const createOnShouldStartLoadWithRequest = (
  28. loadRequest: (
  29. shouldStart: boolean,
  30. url: string,
  31. lockIdentifier: number,
  32. ) => void,
  33. originWhitelist: readonly string[],
  34. onShouldStartLoadWithRequest?: OnShouldStartLoadWithRequest,
  35. ) => {
  36. return ({ nativeEvent }: WebViewNavigationEvent) => {
  37. let shouldStart = true;
  38. const { url, lockIdentifier } = nativeEvent;
  39. if (!passesWhitelist(compileWhitelist(originWhitelist), url)) {
  40. Linking.openURL(url);
  41. shouldStart = false;
  42. }
  43. if (onShouldStartLoadWithRequest) {
  44. shouldStart = onShouldStartLoadWithRequest(nativeEvent);
  45. }
  46. loadRequest(shouldStart, url, lockIdentifier);
  47. };
  48. };
  49. const defaultRenderLoading = () => (
  50. <View style={styles.loadingOrErrorView}>
  51. <ActivityIndicator />
  52. </View>
  53. );
  54. const defaultRenderError = (
  55. errorDomain: string | undefined,
  56. errorCode: number,
  57. errorDesc: string,
  58. ) => (
  59. <View style={styles.loadingOrErrorView}>
  60. <Text style={styles.errorTextTitle}>Error loading page</Text>
  61. <Text style={styles.errorText}>{`Domain: ${errorDomain}`}</Text>
  62. <Text style={styles.errorText}>{`Error Code: ${errorCode}`}</Text>
  63. <Text style={styles.errorText}>{`Description: ${errorDesc}`}</Text>
  64. </View>
  65. );
  66. export {
  67. defaultOriginWhitelist,
  68. createOnShouldStartLoadWithRequest,
  69. defaultRenderLoading,
  70. defaultRenderError,
  71. };