Source

externalCode/pageScreen.js

import * as React from "react";

/**
 * @typedef {Function} PageRenderer
 * @param {Object} props Props which can be used to create a custom page renderer
 * @param {React.ComponentType<any>} component Default component used in the app
 */

/**
 * @typedef {Function} OnNavigationStateChangeCallback
 * @param {Object} navState Navigation state object from React Native WebView's onNavigationStateChange method
 */

/**
 * @typedef {Function} OnShouldStartLoadWithRequestCallback
 * @param {Number} index Web view page index
 * @param {Object} req Request object from React Native WebView's onShouldStartLoadWithRequest method
 * @param {Boolean} isLoading Returns `true` if component is currently loading
 * @param {Boolean} isFocused Returns `true` if webview is focused
 * @param {Object} currentUrl Data of current url
 * @param {Object} nextUrl Data of next url
 * @param {Function} isExternalDeeplink Helper function to determine if deep link url should be opened externally
 * @param {Function} onNext Helper function to render the new WebView and animate the current WebView out of view
 * @param {Boolean} openExternal Returns value of navigation state's `open_external` data
 * @param {Function} shouldOpenInExternalBrowser Helper function to determine if url should open in an external browser
 * @param {Boolean} isSameSite Returns `true` if the url to open has the same host name as app's server url
 * @param {Function} attemptDeepLink Helper function to attempt deep link
 */

/**
 * @typedef {Function} WebViewPropsParams
 * @param {String} url Returns the url of the website being loaded
 * @param {Number} index Index of the webview being loaded
 * @param {Boolean} online Returns `true` if device is connected to an internet connection
 * @param {Object} screenProps
 * @param {Object} source Source used by the web view
 */

/**
 * @typedef {Object} PageScreenTitleProps
 * @param {String} title Default title for the screen
 * @param {Function} titlePromise Promise that resolves to the component that is going to be displayed instead the placeholder
 * @param {Object} colors App colors
 * @param {Object} styles Default styles
 */

/**
 * @class
 * App Pages Screen Hooks.
 * Instance name: pageScreenHooksApi
  
   You can use this hook to customize your app page screens by adding your component for app screens to render, disabling webkit on webview and more.
 * @example
 * externalCodeSetup.pageScreenHooksApi.METHOD_NAME
 */
export class PageScreenHooksApi {
	usePageModeTemplateHeader = true;
	useWebKit = true;

	/**
	 * @deprecated
	 */
	disablePageModeTemplateHeader = () => {
		this.usePageModeTemplateHeader = false;
	};

	/**
	 * Disable web kit on webview.
	 * For more info regarding react native webkit, see {@link https://github.com/react-native-webview/react-native-webview}
	 * @method
	 * @example
	 * externalCodeSetup.pageScreenHooksApi.disableWebKit()
	 */
	disableWebKit = () => {
		this.useWebKit = false;
	};

	// Page Screen Render Component
	PageComponent = (props, component) => component;

	/**
	 * Use your own component to render the `PageScreen` component.
	 * `PageScreen` component is usually rendered whenever a custom link or a Wordpress page is opened.
	 * @method
	 * @param {PageRenderer} PageRenderer
	 * @example <caption> Restrict PageScreen access for a user </caption>
	 * externalCodeSetup.pageScreenHooksApi.setPageComponent((props, Component) => {
	 *
	 *   if (props.user.userObject.id === 1){
	 *
	 *     return <View style={{flex: 1, alignSelf: "ce-nter", justifyContent: "center"}}>
	 *       <Text> Sorry, you do not have access this page </Text>
	 *       <Button title="Tap here to return" onPress={() => props.navigation.goBack()} />
	 *     </View>
	 *   }
	 *
	 *   return Component;
	 *
	 * })
	 */
	setPageComponent = PageRenderer => {
		this.PageComponent = PageRenderer;
	};

	onNavigationStateChange = null;

	/**
	 * You can use this to add a function that is invoked when the WebView loading starts or ends.
	 * @see {@link https://github.com/react-native-webview/react-native-webview/blob/master/docs/Reference.md#onnavigationstatechange}
	 * @method
	 * @param {OnNavigationStateChangeCallback} onChange
	 * @example
	 * externalCodeSetup.pageScreenHooksApi.setOnNavigationStateChange(props => {
	 *   if (! props.loading && props.title){
	 *     Alert.alert(`Page title: ${props.title}`)
	 *   }
	 * });
	 */
	setOnNavigationStateChange = onChange => {
		this.onNavigationStateChange = onChange;
	};

	shouldStartLoadWithRequest = null;

	/**
	 * You can use this to add a function that allows custom handling of any web view requests.
	 * Return `true` from the function to continue loading the request and `false` to stop loading.
	 * @see {@link https://github.com/react-native-webview/react-native-webview/blob/master/docs/Reference.md#onshouldstartloadwithrequest}
	 * @method
	 * @param {OnShouldStartLoadWithRequestCallback} request
	 * @example <caption>Use default app's behavior when handling links in WebView </caption>
	 *
	 * externalCodeSetup.pageScreenHooksApi.setOnShouldStartLoadWithRequest(props => {
	 *
	 *   const {
	 *     index,
	 *     req,
	 *     isLoading,
	 *     isFocused,
	 *     currentUrl,
	 *     nextUrl,
	 *     isExternalDeeplink,
	 *     onNext,
	 *     openExternal,
	 *     shouldOpenInExternalBrowser,
	 *     isSameSite,
	 *     attemptDeepLink
	 *    } = props;
	 *
	 *    // If webview was not tapped, handle loading in the active webview
	 *    if (req.navigationType !== "click") {
	 *      return true;
	 *    }
	 *    // If webview is loading, handle redirection in the same webview
	 *    if (isLoading) {
	 *      return true;
	 *    }
	 *
	 *    if (!req.url) {
	 *      return true;
	 *    }
	 *
	 *    if (nextUrl.pathname === null) {
	 *      return true;
	 *    }
	 *
	 *    if (
	 *      currentUrl.pathname === nextUrl.pathname &&
	 *      currentUrl.host === nextUrl.host
	 *    ) {
	 *      return true;
	 *    }
	 *
	 *    if (! isFocused) {
	 *      return false;
	 *    }
	 *
	 *    //Use a helper function to check if url should be opened with external browser
	 *    if (isExternalDeeplink(req.url)) {
	 *      Linking.canOpenURL(req.url).then(check => {
	 *        if (check) {
	 *          Linking.openURL(req.url);
	 *        } else {
	 *          this.onNext(req.url, index);
	 *        }
	 *      });
	 *        return false;
	 *    }
	 *
	 *    if (openExternal || shouldOpenInExternalBrowser(req.url)) {
	 *      Linking.openURL(req.url).catch(err => {
	 *        console.error("An error occurred", err);
	 *        onNext(req.url, index);
	 *      });
	 *      return false;
	 *    } else if (sameSite) {
	 *      attemptDeepLink(event, req.url, index);
	 *      return false;
	 *    } else {
	 *      onNext(req.url, index);
	 *      return false;
	 *    }
	 *
	 * })
	 */
	setOnShouldStartLoadWithRequest = request => {
		this.shouldStartLoadWithRequest = request;
	};

	webViewProps = () => {};

	/**
	 * This function sets the `WebView` props to the value of the `webViewProps` argument.
	 * The `webViewProps` argument is expected to be an object that contains properties for a `WebView` component.
	 * For example, the `webViewProps` object may contain a `cacheEnabled` property that specifies if `WebView` should use browser caching.
	 * @method
	 * @param {WebViewPropsParams} webViewProps
	 * @example
	 *
	 * externalCodeSetup.pageScreenHooksApi.setWebViewProps(_ => {
	 *   return {
	 *       cacheEnabled: false,
	 *       incognito: true
	 *   }
	 * })
	 */
	setWebViewProps = webViewProps => {
		this.webViewProps = webViewProps;
	};

	PageScreenTitle = null;

	/**
	 * You can use this hook to modify the placeholder and title of the Page Screen.
	 * @method
	 * @param {React.ComponentType<PageScreenTitleProps>} PageScreenTitle
	 * @example
	 * ...
	 *
	 * import PlaceholderGradient from "@src/components/PlaceholderGradient";
	 * import {
	 *     Placeholder,
	 *     PlaceholderContainer
	 * } from "react-native-loading-placeholder";
	 *
	 * export const applyCustomCode = (externalCodeSetup) => {
	 *
	 *     externalCodeSetup.pageScreenHooksApi.setPageScreenTitle(
	 *         ({title, titlePromise, colors, styles}) => {
	 *             return (
	 *                 <PlaceholderContainer
	 *                     animatedComponent={
	 *                         <PlaceholderGradient
	 *                             base={colors.headingsColor}
	 *                             style={styles.placeholderContainer}
	 *                         />
	 *                     }
	 *                     duration={1000}
	 *                     delay={500}
	 *                     loader={titlePromise}
	 *                     replace={true}
	 *                 >
	 *                     <Placeholder style={styles.placeholder}>
	 *                         <Text ellipsizeMode="tail" numberOfLines={1} style={styles.text}>
	 *                             {title}
	 *                         </Text>
	 *                     </Placeholder>
	 *                 </PlaceholderContainer>
	 *             );
	 *         }
	 *     );
	 * }
	 *
	 */

	setPageScreenTitle = PageScreenTitle => {
		this.PageScreenTitle = PageScreenTitle;
	};
}