Source

externalCode/blocks.js

import * as React from "react";

/**
 * Types
 */

/**
 * @typedef {Object} BlockProps
 * @property {Object} block Block data from API
 * @property {Function} calcFontSize Used to calculate font size based on the fixed value you assign and percent set on branding options
 * @property {Object} colors App colors
 * @property {Object} fontFamilyStyle App font style
 * @property {Object} global App global style
 * @property {Function} handleLinkClicks Link click handler
 * @property {Function} htmlHandleClicks Link click handler for webview
 * @property {boolean} isNavActive Returns true if current screen is visible
 * @property {boolean} lastItem Returns true if component is last block
 * @property {NavigationService} navigation
 * @property {ToUserBasedOnSettings} toUserBasedOnSettings
 * @property {number} viewWidth Default window width used by blocks
 * @property {Function} wrapHtml Function that will wrap string in an HTML template
 * @property {ReactStyles} wrapStyle Default wrap style used by blocks
 */

/**
 * A custom block render function
 * @typedef {Function} CustomBlockRenderCallback
 * @param {BlockProps} renderer
 * @return {React.ComponentType<any>} React Component
 */

/**
 * Block props
 * @typedef {Function} CustomBlockPropsCallback
 * @param {BlockProps} renderer
 * @return {Object} New props
 */

/**
 * @typedef {"core/image" | "core/video" | "core/audio" | "core/gallery" | "core/paragraph" | "core/heading" | "core/quote" | "core/table" | "core/list" | "core/html" | "core/cover" | "core/media-text" | "core/buttons" | "core/button" | "core/columns" | "core/embed" | "bbapp/courses" | "bbapp/topics" | "bbapp/forums" | "bbapp/groups" | "bbapp/members" | "bbapp/activity" | "bbapp/notifications" | "bbapp/qlinks" | "bbapp/h5p" | "tincanny/content" | "core/code" | "core/pullquote" | "core/preformatted" | "core/verse" | "core/file" | "core/more" | "core/nextpage" | "core/separator" | "core/spacer" | "core/group"} BlockTypes
 */

/**
 * @class
 * Blocks Hooks.
 * Instance name: blocksApi
  
  Enables you to make modifications to the different blocks and replace default behaviour in your app pages in terms of appearance as well as functionality.
 * @example
 * externalCodeSetup.blocksApi.METHOD_NAME
 */
export class BlocksApi {
	/**
	 * @private
	 * @property {Object<string, CustomBlockRenderCallback>} customBlockRenders
	 */
	customBlockRenders = {};

	/**
	 * @deprecated
	 * @private
	 * @property {?number} profileBlockBgImage
	 */
	profileBlockBgImage = null;

	/**
	 * @deprecated
	 * Changes the Profile Block cover image
	 * @method
	 * @param {number} image - Image resourse (via request('...src'))
	 */
	setProfileBlockBgImage = image => {
		this.profileBlockBgImage = image;
	};

	/**
	 * Replaces the Gutenberg blocks that match with blockType using the render function.
	 * @method
	 * @param {BlockTypes} blockType Block identifier
	 * @param {CustomBlockRenderCallback} renderer Render function
	 * @example <caption>User would like to customize the component when Video block is used</caption>
	 *
	 * externalCodeSetup.blocksApi.addCustomBlockRender("core/video", (props) => {
	 *   const { block } = props;
	 *   const VideoComponent =
	 *   <>
	 *       <WebView
	 *           source={{
	 *               html: `<video width="980" playsinline controls autoplay src="${block.content}" ></video>`
	 *           }}
	 *           useWebKit={true}
	 *           originWhitelist={['*']}
	 *           allowsInlineMediaPlayback={true}
	 *           style={{
	 *               height: 250,
	 *               width: "auto",
	 *           }}/>
	 *
	 *      <View>
	 *           <Text> Watch our awesome video! </Text>
	 *      </View>
	 *   </>
	 *   return VideoComponent;
	 * });
	 */
	addCustomBlockRender = (blockType, renderer) => {
		this.customBlockRenders[blockType] = renderer;
	};

	blockProps = {};
	/**
	 * You can use this hook to modify the properties of the Gutenberg blocks.
	 * For example, you can modify the width of the video block to let it occupy the full width on any device.
	 * @method
	 * @param {BlockTypes} blockType Block identifier
	 * @param {CustomBlockPropsCallback} props
	 * @example <caption>Extend the width of video blocks used in lesson single screen </caption>
	 *
	 * import { Platform } from 'react-native'
	 * import {DEVICE_WIDTH} from "@src/styles/global";
	 * export const applyCustomCode = externalCodeSetup => {
	 *
	 *   if (! Platform.isPad){
	 *      externalCodeSetup.cssApi.addGlobalStyle("lessonSingleScreenBlockContainer", { paddingHorizontal: 0 }, true);
	 *      externalCodeSetup.cssApi.addGlobalStyle("videoBlockContainer", { paddingHorizontal: 0 });
	 *
	 *      externalCodeSetup.blocksApi.setBlockProps("core/embed", (props) => {
	 *
	 *         const {block} = props;
	 *
	 *         if (block.data.provider === "vimeo" || block.data.provider === "youtube"){
	 *            return {
	 *               ...props,
	 *               viewWidth: DEVICE_WIDTH
	 *            }
	 *         }
	 *
	 *         return props;
	 *      });
	 *
	 *   }
	 * }
	 */
	setBlockProps = (blockType, blockProps) => {
		this.blockProps[blockType] = blockProps;
	};

	addedBlockAssetsToDownload = null;

	/**
	 * You can use this hook to add custom assets to the download queue, particularly when downloading a course.
	 * To learn how to create custom app Gutenberg blocks, visit the following link: {@link https://www.buddyboss.com/resources/dev-docs/app-development/extending-the-buddyboss-app-plugin/registering-custom-app-gutenberg-blocks}
	 * @method
	 * @param {AddedBlockAssetsToDownloadCallback} addedBlockAssetsToDownload
	 * @example
	 *
	 * import React, {useEffect} from "react";
	 * import {Text, View, StyleSheet} from "react-native";
	 * import Video from "react-native-video";
	 *
	 * // Use BuddyBoss HOC to fetch local assets.
	 * // Alternatively, you can create your own function by utilizing RNFetchBlob.fs.exists(path) and fetching the downloaded asset like:
	 * // const {
	 * //         fs: {dirs}
	 * // } = RNFetchBlob;
	 * // const DIR_PATH = dirs.DocumentDir;
	 * import withLocalAssets from "@src/components/hocs/withLocalAssets";
	 *
	 * const LocalVideoPlayer = withLocalAssets(props => {
	 *     const {block} = props;
	 *
	 *     const downloadVideo =
	 *         block.data.data_source.request_params.download_media.download_video;
	 *
	 *     const downloadAudio =
	 *         block.data.data_source.request_params.download_media.download_audio;
	 *
	 *     const downloadSubtitles =
	 *         block.data.data_source.request_params.download_media.download_subtitles;
	 *
	 *
	 *     useEffect(
	 *         () => {
	 *             props.fetchLocalAsset(downloadVideo);
	 *         },
	 *         [downloadVideo]
	 *     );
	 *
	 *     const customVideoUri = props.localAsset;
	 *
	 *     return (
	 *         <>
	 *             <View style={{flex: 1}}>
	 *                 {!props.localAsset ? (
	 *                     <Text>Streaming video...</Text>
	 *                 ) : (
	 *                     <Text>Local video</Text>
	 *                 )}
	 *
	 *                 <View style={styles.container}>
	 *                     <Video
	 *                         source={{uri: customVideoUri}}
	 *                         style={styles.video}
	 *                         controls={true}
	 *                         resizeMode="contain"
	 *                     />
	 *                 </View>
	 *             </View>
	 *         </>
	 *     );
	 * });
	 *
	 * const styles = StyleSheet.create({
	 *     container: {
	 *         flex: 1,
	 *         justifyContent: "center",
	 *         alignItems: "center",
	 *         backgroundColor: "#000"
	 *     },
	 *     video: {
	 *         width: "100%",
	 *         height: 300
	 *     }
	 * });
	 *
	 * export const applyCustomCode = externalCodeSetup => {
	 *
	 *
	 *     // Add custom block renderer hook
	 *     externalCodeSetup.blocksApi.addCustomBlockRender(
	 *         "ari/ari-video-player",
	 *         props => <LocalVideoPlayer {...props} />
	 *     );
	 *
	 *
	 *     externalCodeSetup.blocksApi.setAddedBlockAssetsToDownload(() => {
	 *         return [
	 *             {
	 *                 blockType: "ari/ari-video-player", // blockNamespace
	 *
	 *                 // Add the different paths to the download urls
	 *                 // For example, if the block has a "data" object with a "data_source" property, then we can access it here
	 *                 // This accepts an array of strings, where each string is the path to the asset we want to download
	 *                 // If the object being accessed contains a string, then that string will be downloaded
	 *                 // If the object being accessed contains an array of download urls, then all of them will be downloaded
	 *                 downloadableAssets: [
	 *                     "data.data_source.request_params.download_media.download_video",
	 *                     "data.data_source.request_params.media_content"
	 *                 ]
	 *             }
	 *         ];
	 *     });
	 *  };
	 */
	setAddedBlockAssetsToDownload = addedBlockAssetsToDownload => {
		this.addedBlockAssetsToDownload = addedBlockAssetsToDownload;
	};
}