Application Android et IOS pour l'amicale des élèves
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

WebViewScreen.js 6.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. // @flow
  2. import * as React from 'react';
  3. import WebView from "react-native-webview";
  4. import BasicLoadingScreen from "./BasicLoadingScreen";
  5. import ErrorView from "./ErrorView";
  6. import {ERROR_TYPE} from "../../utils/WebData";
  7. import MaterialHeaderButtons, {Item} from '../Overrides/CustomHeaderButton';
  8. import {Divider, HiddenItem, OverflowMenu} from "react-navigation-header-buttons";
  9. import i18n from 'i18n-js';
  10. import {Animated, BackHandler, Linking} from "react-native";
  11. import {withCollapsible} from "../../utils/withCollapsible";
  12. import MaterialCommunityIcons from "react-native-vector-icons/MaterialCommunityIcons";
  13. import {withTheme} from "react-native-paper";
  14. import type {CustomTheme} from "../../managers/ThemeManager";
  15. import {StackNavigationProp} from "@react-navigation/stack";
  16. import {Collapsible} from "react-navigation-collapsible";
  17. type Props = {
  18. navigation: StackNavigationProp,
  19. theme: CustomTheme,
  20. url: string,
  21. customJS: string,
  22. collapsibleStack: Collapsible,
  23. onMessage: Function,
  24. onScroll: Function,
  25. showAdvancedControls: boolean,
  26. }
  27. const AnimatedWebView = Animated.createAnimatedComponent(WebView);
  28. /**
  29. * Class defining a webview screen.
  30. */
  31. class WebViewScreen extends React.PureComponent<Props> {
  32. static defaultProps = {
  33. customJS: '',
  34. showAdvancedControls: true,
  35. };
  36. webviewRef: Object;
  37. canGoBack: boolean;
  38. constructor() {
  39. super();
  40. this.webviewRef = React.createRef();
  41. this.canGoBack = false;
  42. }
  43. /**
  44. * Creates refresh button after mounting
  45. */
  46. componentDidMount() {
  47. this.props.navigation.setOptions({
  48. headerRight: this.props.showAdvancedControls
  49. ? this.getAdvancedButtons
  50. : this.getBasicButton,
  51. });
  52. this.props.navigation.addListener(
  53. 'focus',
  54. () =>
  55. BackHandler.addEventListener(
  56. 'hardwareBackPress',
  57. this.onBackButtonPressAndroid
  58. )
  59. );
  60. this.props.navigation.addListener(
  61. 'blur',
  62. () =>
  63. BackHandler.removeEventListener(
  64. 'hardwareBackPress',
  65. this.onBackButtonPressAndroid
  66. )
  67. );
  68. }
  69. onBackButtonPressAndroid = () => {
  70. if (this.canGoBack) {
  71. this.onGoBackClicked();
  72. return true;
  73. }
  74. return false;
  75. };
  76. /**
  77. * Gets a header refresh button
  78. *
  79. * @return {*}
  80. */
  81. getBasicButton = () => {
  82. return (
  83. <MaterialHeaderButtons>
  84. <Item
  85. title="refresh"
  86. iconName="refresh"
  87. onPress={this.onRefreshClicked}/>
  88. <Item
  89. title={i18n.t("general.openInBrowser")}
  90. iconName="open-in-new"
  91. onPress={this.onOpenClicked}/>
  92. </MaterialHeaderButtons>
  93. );
  94. };
  95. getAdvancedButtons = () => {
  96. return (
  97. <MaterialHeaderButtons>
  98. <Item
  99. title="refresh"
  100. iconName="refresh"
  101. onPress={this.onRefreshClicked}
  102. />
  103. <OverflowMenu
  104. style={{marginHorizontal: 10}}
  105. OverflowIcon={
  106. <MaterialCommunityIcons
  107. name="dots-vertical"
  108. size={26}
  109. color={this.props.theme.colors.text}
  110. />}
  111. >
  112. <HiddenItem
  113. title={i18n.t("general.goBack")}
  114. onPress={this.onGoBackClicked}/>
  115. <HiddenItem
  116. title={i18n.t("general.goForward")}
  117. onPress={this.onGoForwardClicked}/>
  118. <Divider/>
  119. <HiddenItem
  120. title={i18n.t("general.openInBrowser")}
  121. onPress={this.onOpenClicked}/>
  122. </OverflowMenu>
  123. </MaterialHeaderButtons>
  124. );
  125. }
  126. /**
  127. * Callback to use when refresh button is clicked. Reloads the webview.
  128. */
  129. onRefreshClicked = () => this.webviewRef.current.getNode().reload(); // Need to call getNode() as we are working with animated components
  130. onGoBackClicked = () => this.webviewRef.current.getNode().goBack();
  131. onGoForwardClicked = () => this.webviewRef.current.getNode().goForward();
  132. onOpenClicked = () => Linking.openURL(this.props.url);
  133. injectJavaScript = (script: string) => {
  134. this.webviewRef.current.getNode().injectJavaScript(script);
  135. }
  136. /**
  137. * Gets the loading indicator
  138. *
  139. * @return {*}
  140. */
  141. getRenderLoading = () => <BasicLoadingScreen isAbsolute={true}/>;
  142. getJavascriptPadding(padding: number) {
  143. return (
  144. "document.getElementsByTagName('body')[0].style.paddingTop = '" + padding + "px';" +
  145. "true;"
  146. );
  147. }
  148. onScroll = (event: Object) => {
  149. if (this.props.onScroll)
  150. this.props.onScroll(event);
  151. }
  152. render() {
  153. const {containerPaddingTop, onScrollWithListener} = this.props.collapsibleStack;
  154. return (
  155. <AnimatedWebView
  156. ref={this.webviewRef}
  157. source={{uri: this.props.url}}
  158. startInLoadingState={true}
  159. injectedJavaScript={this.props.customJS}
  160. javaScriptEnabled={true}
  161. renderLoading={this.getRenderLoading}
  162. renderError={() => <ErrorView
  163. errorCode={ERROR_TYPE.CONNECTION_ERROR}
  164. onRefresh={this.onRefreshClicked}
  165. />}
  166. onNavigationStateChange={navState => {
  167. this.canGoBack = navState.canGoBack;
  168. }}
  169. onMessage={this.props.onMessage}
  170. onLoad={() => this.injectJavaScript(this.getJavascriptPadding(containerPaddingTop))}
  171. // Animations
  172. onScroll={onScrollWithListener(this.onScroll)}
  173. />
  174. );
  175. }
  176. }
  177. export default withCollapsible(withTheme(WebViewScreen));