Source

externalCode/lessonSingleScreen.ts

import * as React from "react";
import {
	Course,
	TCourseViewModel,
	TLessonViewModel,
	TTranslationFunction
} from "./types";
import {NavigationProp} from "@react-navigation/native";

export const API_NAME = "lessonSingleScreenApi";
/**
 * PrevNextComponentProps
 */
type PrevNextComponentProps = {
	/**
	 * Function to execute if previous or next button is a quiz
	 */
	onQuizClick: Function,
	/**
	 * Function to execute if previous or next button is a lesson
	 */
	onLessonClick: Function,
	/**
	 * Function to execute if previous or next button is a topic
	 */
	onTopicClick: Function,
	/**
	 * App global style
	 */
	global: Record<any, any>,
	/**
	 * App colors
	 */
	colors: Record<any, any>,
	t: TTranslationFunction,
	/**
	 * Data about previous lesson/topic/quiz
	 */
	prevObject: Record<any, any>,
	/**
	 * Data about next lesson/topic/quiz
	 */
	nextObject: Record<any, any>,
	/**
	 * Course id of lesson/topic/quiz
	 */
	courseId: number,
	/**
	 * Shows an alert with information that next object is locked
	 */
	nextLockedAlert: Function
};

/**
 * PrevNextPlaceholderProps
 */
type PrevNextPlaceholderProps = {
	/**
	 * App global style
	 */
	global: Record<any, any>
};

/**
 * LessonHeaderProps
 */
type LessonHeaderProps = {
	/**
	 * App global style
	 */
	global: Record<any, any>,
	/**
	 * App colors
	 */
	colors: Record<any, any>,
	lesson: TLessonViewModel,
	/**
	 * Learndash labels
	 */
	labels: Record<string, string>,
	t: TTranslationFunction,
	paddingTop: number,
	/**
	 * Function to execute if previous or next button is a quiz
	 */
	onQuizClick: Function,
	/**
	 * Function to execute if previous or next button is a lesson
	 */
	onLessonClick: Function,
	/**
	 * Function to execute if previous or next button is a topic
	 */
	onTopicClick: Function,
	/**
	 * Data about previous lesson/topic/quiz
	 */
	prevObject: Record<any, any>,
	/**
	 * Data about next lesson/topic/quiz
	 */
	nextObject: Record<any, any>,

	/**
	 * Course id of lesson/topic/quiz
	 */
	courseId: number,
	/**
	 * Shows an alert with information that next object is locked
	 */
	nextLockedAlert: Function,
	/**
	 * Returns default back button component
	 */
	backToCourse: React.ComponentType,
	/**
	 * Returns `true` if screen is still loading
	 */
	loading: boolean,
	course: TCourseViewModel,
	/**
	 * Returns `false` lesson doesn't have a timer set. Will return a component if timer for the lesson is set.
	 */
	renderTimer: boolean | React.ComponentType,
	/**
	 * Function which updates the seconds passed in the lesson screen container
	 */
	onTimePassed: Function,
	navigation: NavigationProp<any, any>,
	/**
	 * Returns `true` if prev/next buttons should be hidden
	 */
	hidePrevNext: boolean,
	/**
	 * Returns `false` if hidePrevNext is `true`. Will return buttons which can navigate through previous and next screens if hidePrevNext is `false`
	 */
	prevNext: boolean | React.ComponentType
};

/**
 * LessonScreenHeaderProps
 */
type LessonScreenHeaderProps = {
	/**
	 * Default styling for left section of the header
	 */
	headerLeftStyle: Record<any, any>,
	/**
	 * Default styling of lesson header
	 */
	style: Record<any, any>,
	/**
	 * Props which can be passed to an AuthWrapper
	 */
	headerRightAuthWrapperProps: Record<any, any>,

	/**
	 * App global style
	 */
	global: Record<any, any>,
	/**
	 * App colors
	 */
	colors: Record<any, any>,
	lesson: TLessonViewModel,
	/**
	 * Learndash labels
	 */
	labels: Record<string, string>,
	t: TTranslationFunction,
	paddingTop: number,
	/**
	 * Function to execute if previous or next button is a quiz
	 */
	onQuizClick: Function,
	/**
	 * Function to execute if previous or next button is a lesson
	 */
	onLessonClick: Function,
	/**
	 * Function to execute if previous or next button is a topic
	 */
	onTopicClick: Function,
	/**
	 * Data about previous lesson/topic/quiz
	 */
	prevObject: Record<any, any>,
	/**
	 * Data about next lesson/topic/quiz
	 */
	nextObject: Record<any, any>,

	/**
	 * Course id of lesson/topic/quiz
	 */
	courseId: number,
	/**
	 * Shows an alert with information that next object is locked
	 */
	nextLockedAlert: Function,
	/**
	 * Returns default back button component
	 */
	backToCourse: React.ComponentType,
	/**
	 * Returns `true` if screen is still loading
	 */
	loading: boolean,
	course: TCourseViewModel,
	/**
	 * Returns `false` lesson doesn't have a timer set. Will return a component if timer for the lesson is set.
	 */
	renderTimer: boolean | React.ComponentType,
	/**
	 * Function which updates the seconds passed in the lesson screen container
	 */
	onTimePassed: Function,
	navigation: NavigationProp<any, any>,
	/**
	 * Returns `true` if prev/next buttons should be hidden
	 */
	hidePrevNext: boolean,
	/**
	 * Returns `false` if hidePrevNext is `true`. Will return buttons which can navigate through previous and next screens if hidePrevNext is `false`
	 */
	prevNext: boolean | React.ComponentType
};

/**
 * TransformLessonActionButtonsCallback
 */
type TransformLessonActionButtonsCallback = {
	/**
	 * Lesson action button
	 */
	LessonButton: React.ComponentType,
	/**
	 * Returns `true` if "Mark Complete" button should be shown
	 */
	showComplete: boolean,
	/**
	 * App global style
	 */
	global: Record<any, any>,
	/**
	 * App colors
	 */
	colors: Record<any, any>,

	lesson: TLessonViewModel,
	/**
	 * Returns `true` if lesson is being completed
	 */
	completing: boolean,
	/**
	 * Learndash labels
	 */
	labels: Record<string, string>
};

/**
 * VideoProgressionComponentProps
 */
type VideoProgressionComponentProps = {
	/**
	 * Default styling applied to lesson video
	 */
	lessonVideoStyle: Record<any, any>,
	/**
	 * Returns `true` if controls should be displayed
	 */
	controls: boolean,
	/**
	 * Returns `true` if auto play should be enabled
	 */
	autoplay: boolean,
	/**
	 * Helper function which can be called when the video has finished playing
	 */
	videoCallback: Function,
	/**
	 * Video url
	 */
	url: string,
	/**
	 * Player width
	 */
	width: number,
	/**
	 * Player height
	 */
	height: number,

	/**
	 * App global style
	 */
	global: Record<any, any>,
	/**
	 * Returns `true` if screen is active
	 */
	isNavActive: boolean,
	lesson: TLessonViewModel,
	/**
	 * Returns `true` if video should be shown
	 */
	showVideo: boolean,
	/**
	 * Returns `true` if video has already been watched
	 */
	videoWatched: boolean,
	/**
	 * Helper function which dispatches an action and marks the video as watched
	 */
	setVideoWatched: boolean,
	/**
	 * Helper function which dispatches an action to mark the lesson as complete
	 */
	completeLesson: Function,
	/**
	 * Helper function which considers different conditions (such as if topics inside a lesson are already completed) before calling the `completeLesson` function
	 */
	onCompleteButtonClick: Function
};

/**
 * AfterMaterialsComponentProps
 */
type AfterMaterialsComponentProps = {
	/**
	 * App global style
	 */
	global: Record<any, any>,
	/**
	 * App colors
	 */
	colors: Record<any, any>,
	lesson: TLessonViewModel,
	/**
	 * Learndash labels
	 */
	labels: Record<string, string>,
	t: TTranslationFunction,
	/**
	 * Function to execute if previous or next button is a quiz
	 */
	onQuizClick: Function,
	/**
	 * Function to execute if previous or next button is a lesson
	 */
	onLessonClick: Function,
	/**
	 * Function to execute if previous or next button is a topic
	 */
	onTopicClick: Function,
	/**
	 * Data about previous lesson/topic/quiz
	 */
	prevObject: Record<any, any>,
	/**
	 * Data about next lesson/topic/quiz
	 */
	nextObject: Record<any, any>,
	/**
	 * Shows an alert with information that next object is locked
	 */
	nextLockedAlert: Function,

	/**
	 *  Returns `true` if screen is still loading
	 */
	loading: boolean,
	course: Course,
	navigation: NavigationProp<any, any>,
	/**
	 * Lesson materials
	 */
	materials: undefined | string
};

/**
 * LessonActionComponentProps
 */
type LessonActionComponentProps = {
	/**
	 * App global style
	 */
	global: Record<any, any>,
	/**
	 * App colors
	 */
	colors: Record<any, any>,

	lesson: TLessonViewModel,
	/**
	 * Learndash labels
	 */
	labels: Record<string, string>,
	t: TTranslationFunction,

	/**
	 * Helper function which considers different conditions (such as if topics inside a lesson are already completed) before calling the `completeLesson` function
	 */
	onCompleteButtonClick: Function,
	/**
	 * Returns `true` if "Mark Complete" button should be shown
	 */
	showComplete: boolean,
	/**
	 * Returns `true` if lesson is being completed
	 */
	completing: boolean,
	/**
	 * Returns `true` if "Mark Complete" button should be disabled
	 */
	completeDisabled: boolean,
	/**
	 * Data about previous lesson/topic/quiz
	 */
	prevObject: Record<any, any>,
	/**
	 * Data about next lesson/topic/quiz
	 */
	nextObject: Record<any, any>,
	/**
	 * Function to execute if previous or next button is a quiz
	 */
	onQuizClick: Function,
	/**
	 * Function to execute if previous or next button is a lesson
	 */
	onLessonClick: Function,
	/**
	 * Function to execute if previous or next button is a topic
	 */
	onTopicClick: Function
};

/**
 * OfflineComponentProps
 */
type OfflineComponentProps = {
	/**
	 * App global style
	 */
	global: Record<any, any>,
	t: TTranslationFunction,

	/**
	 * Default container style
	 */
	containerStyle: Record<any, any>,

	/**
	 * Default style of EmptyList component
	 */
	emptyListStyle: Record<any, any>
};

/**
 * WebViewContentComponentProps
 */
type WebViewContentComponentProps = {
	/**
	 * Returns `true` if device is connected to an internet network
	 */
	online: boolean,
	t: TTranslationFunction,
	/**
	 * The default function used for determining how to handle webview requests.
	 */
	onShouldStartLoadWithRequest: Function,
	/**
	 * Default height
	 */
	height: number,
	/**
	 * Contains data of the web site to be loaded in the webview
	 */
	source: Record<any, any>,
	/**
	 * App global style
	 */
	global: Record<any, any>,
	/**
	 * App colors
	 */
	colors: Record<any, any>,
	/**
	 * Modal which shows up when the "Read More" component is pressed
	 */
	ModalHeaderComponent: React.FC
};

/**
 * LessonMaterialsSectionTitleProps
 */
type LessonMaterialsSectionTitleProps = {
	/**
	 * App global style
	 */
	global: Record<any, any>,
	t: TTranslationFunction
};

/**
 * AssignmentsHeaderProps
 */
type AssignmentsHeaderProps = {
	/**
	 * App global style
	 */
	global: Record<any, any>,
	t: TTranslationFunction,
	/**
	 * Total number of assignments uploaded
	 */
	totalAssignments: number,
	/**
	 * Number of assignments approved
	 */
	approved: number
};

/**
 * AssignmentItemIconProps
 */
type AssignmentItemIconProps = {
	/**
	 * Default icon for the item
	 */
	icon: number,
	/**
	 * Default style for the item
	 */
	styles: Record<any, any>
};

/**
 * AssignmentItemTitleProps
 */
type AssignmentItemTitleProps = {
	/**
	 * Assignment item title
	 */
	title: string,
	/**
	 * Default style for the item
	 */
	style: Record<any, any>
};

/**
 * AssignmentItemStatusProps
 */
type AssignmentItemStatusProps = {
	/**
	 * App global style
	 */
	global: Record<any, any>,
	/**
	 * Assignment item status
	 */
	text: string,
	/**
	 * Default container style
	 */
	containerStyle: Record<any, any>,
	/**
	 * Default text style
	 */
	textStyle: Record<any, any>
};
/**
 * AssignmentItemCommentProps
 */
type AssignmentItemCommentProps = {
	/**
	 * Opens the comments modal
	 */
	pressHandler: Function,
	/**
	 * Default button color
	 */
	tintColor: string,
	/**
	 * Default container style
	 */
	containerStyle: Record<any, any> | undefined,
	/**
	 * Number of comments
	 */
	count: number,
	/**
	 * Button size
	 */
	size: string,
	/**
	 * App global style
	 */
	global: Record<any, any>,
	/**
	 * Can be used to determine if button should use light or dark style
	 */
	lightMode: boolean | undefined
};

/**
 * AssignmentItemDownloadProps
 */
type AssignmentItemDownloadProps = {
	/**
	 * Downloads the assignment item
	 */
	pressHandler: Function,

	/**
	 * Default button color
	 */
	tintColor: string,
	/**
	 * Default container style
	 */
	containerStyle: Record<any, any> | undefined,
	/**
	 * Number of comments
	 */
	count: number,
	/**
	 * Button size
	 */
	size: string,
	/**
	 * App global style
	 */
	global: Record<any, any>,
	/**
	 * Can be used to determine if button should use light or dark style
	 */
	lightMode: boolean | undefined
};

/**
 * AssignmentItemDownloadProgressProps
 */
type AssignmentItemDownloadProgressProps = {
	/**
	 * Download progress
	 */
	progress: number,
	/**
	 * Unfilled color of the ProgressCircle component
	 */
	unfilledColor: string,
	/**
	 * Color of the ProgressCircle component
	 */
	tintColor: string
};

/**
 * MaterialsComponentProps
 */
type MaterialsComponentProps = {
	/**
	 * App global style
	 */
	global: Record<any, any>,
	/**
	 * App colors
	 */
	colors: Record<any, any>,

	t: TTranslationFunction,

	/**
	 * Contents of course materials field
	 */
	materials: string,
	/**
	 * Default styles for different HTML tags
	 */
	tagsStyles: Record<any, any>,
	/**
	 * Default styles for course materials
	 */
	materialsStyles: Record<any, any>,
	/**
	 * Function to set a font style
	 */
	baseFontStyle: Function,
	navigation: NavigationProp<any, any>,
	/**
	 * Handles link press for the HTML component
	 */
	onLinkPress: Function
};

/**
 * TransformLessonViewModelCallback
 */
type TransformLessonViewModelCallback = {
	viewModel: TLessonViewModel,
	lesson: Record<any, any>
};

/**
 * @class
 * Lesson Screen Hooks.
 * Instance name: lessonSingleScreenApi
 
   You can use this hook to customize the lesson screen such as by adding a custom call to action button and other actions.
 * @example
 * externalCodeSetup.lessonSingleScreenApi.METHOD_NAME
 */
export class LessonSingleScreenHooksApi {
	/**
	 * @deprecated
	 * Filters navigation onPress function that is used to navigate to Topic
	 */
	//@ts-ignore
	topicNavigationFilter = (onPress, navigation, topic, lessonId, courseId) =>
		onPress;

	/**
	 * @deprecated
	 */
	//@ts-ignore
	setTopicNavigationFilter = topicNavigationFilter => {
		this.topicNavigationFilter = topicNavigationFilter;
	};

	PrevNextComponent: React.ComponentType<PrevNextComponentProps> | null = null;

	/**
	 * You can use this to replace the previous and next buttons on the lessons single screen if you want to change the default option which always displays the prev/next buttons.
	 * @method
	 * @param {React.ComponentType<PrevNextComponentProps>} PrevNextComponent
	 * @example <caption> Hide the previous and next buttons if you're only using one lesson in a course </caption>
	 *
	 * //In custom_code/components/PrevNext.js
	 *
	 * import React from "react";
	 * import PrevNext from "@src/components/Course/PrevNext";
	 *
	 *  const PrevNextComponent = props => {
	 *
	 *    const { onQuizClick,
	 *            onLessonClick,
	 *            onTopicClick,
	 *            global,
	 *            colors,
	 *            t,
	 *            prevObject,
	 *            nextObject,
	 *            courseId,
	 *            nextLockedAlert } = props;
	 *
	 *    if (! nextObject && ! prevObject){
	 *        return null;
	 *    }
	 *
	 *    return (
	 *        <PrevNext
	 *            {...{ onQuizClick, onLessonClick, onTopicClick }}
	 *            global={global}
	 *            colors={colors}
	 *            t={t}
	 *            prevObject={prevObject}
	 *            nextObject={nextObject}
	 *            courseId={courseId}
	 *            nextLockedAlert={nextLockedAlert}
	 *        />
	 *    );
	 * };
	 * export default PrevNextComponent;
	 *
	 * //In custom_code/index.js...
	 *
	 * ...
	 *
	 * import PrevNextComponent from './components/PrevNext';
	 * export const applyCustomCode = externalCodeSetup => {
	 *  externalCodeSetup.lessonSingleScreenApi.setPrevNextComponent(props => <PrevNextComponent {...props} />)
	 * }
	 *
	 * @example <caption> Hide previous and next buttons </caption>
	 *
	 * ...
	 *
	 * export const applyCustomCode = externalCodeSetup => {
	 *  externalCodeSetup.lessonSingleScreenApi.setPrevNextComponent(() => null)
	 * }
	 *
	 */

	setPrevNextComponent = (
		PrevNextComponent: React.ComponentType<PrevNextComponentProps> | null
	) => {
		this.PrevNextComponent = PrevNextComponent;
	};

	PrevNextPlaceholder: React.ComponentType<
		PrevNextPlaceholderProps
	> | null = null;

	/**
	 * You can use this to replace the previous and next buttons' placeholders on the lessons single screen.
	 * The previous and next buttons' placeholders appear while the app is still loading the lesson.
	 * @method
	 * @param {React.ComponentType<PrevNextPlaceholderProps>} PrevNextPlaceholder
	 * @example <caption> Change placeholder color </caption>
	 *
	 * externalCodeSetup.lessonSingleScreenApi.setPrevNextPlaceholder((props) => {
	 *
	 *    const {global} = props;
	 *
	 *    return <>
	 *      <View
	 *        style={[
	 *          global.wrappedButton,
	 *          global.wrappedTextButton,
	 *          { marginRight: 4, width: 64, backgroundColor: "blue" }
	 *        ]}
	 *      />
	 *      <View
	 *        style={[
	 *          global.wrappedButton,
	 *          global.wrappedTextButton,
	 *          { width: 65 , backgroundColor: "red"}
	 *        ]}
	 *      />
	 *    </>
	 * })
	 *
	 * @example <caption> Hide the placeholder even while the screen is still loading </caption>
	 *
	 * externalCodeSetup.lessonSingleScreenApi.setPrevNextPlaceholder(() => null)
	 *
	 */
	setPrevNextPlaceholder = (
		PrevNextPlaceholder: React.ComponentType<PrevNextPlaceholderProps> | null
	) => {
		this.PrevNextPlaceholder = PrevNextPlaceholder;
	};

	transformLessonActionButtons: (
		LessonButton: JSX.Element,
		showComplete: boolean,
		global: Record<any, any>,
		colors: Record<any, any>,
		lesson: TLessonViewModel,
		completing: boolean,
		labels: Record<string, string>
	) => JSX.Element = LessonButton => LessonButton;
	/**
	 * You can transform the default lesson action button by replacing it with your preferred action buttons.
	 * @param {TransformLessonActionButtonsCallback} transformLessonActionButtons
	 * @method
	 * @example <caption> Add more components for lesson action </caption>
	 *
	 * externalCodeSetup.lessonSingleScreenApi.setTransformLessonActionButtons((
	 *  LessonButton,
	 *  showComplete,
	 *  global,
	 *  colors,
	 *  lesson,
	 *  completing,
	 *  labels) => {
	 *
	 *    const Buttons =
	 *      <View style={[global.row, {backgroundColor: "#fff"}]}>
	 *
	 *        <View style={{ width:"45%", backgroundColor: "#fff", paddingHorizontal: 20, paddingVertical: 15 }}>
	 *          <AppTouchableOpacity
	 *            style={[
	 *              global.completeLessonButtonW,
	 *              { flex: 1, backgroundColor: colors.primaryButtonBg }
	 *            ]}
	 *            onPress={() => {
	 *              //Do function...
	 *            }}
	 *          >
	 *            <View style={global.row}>
	 *              <View style={global.linkWithArrow}>
	 *                <Text
	 *                  style={{color: "#fff", fontWeight: "bold"}}
	 *                >
	 *                  Questions?
	 *                </Text>
	 *              </View>
	 *            </View>
	 *          </AppTouchableOpacity>
	 *        </View>
	 *        <View style={{ width: "45%", marginLeft: "auto" }}>
	 *          {LessonButton}
	 *        </View>
	 *      </View>
	 *
	 *    return Buttons;
	 * })
	 */

	setTransformLessonActionButtons = (
		transformLessonActionButtons: (
			LessonButton: JSX.Element,
			showComplete: boolean,
			global: Record<any, any>,
			colors: Record<any, any>,
			lesson: TLessonViewModel,
			completing: boolean,
			labels: Record<string, string>
		) => JSX.Element
	) => {
		this.transformLessonActionButtons = transformLessonActionButtons;
	};

	LessonTitleComponent: React.ComponentType<LessonHeaderProps> | null = null;

	/**
	 * You can use this to replace the lesson's title component.
	 * For example, you can use this to change the title's background or add an ellipsis feature to it.
	 * @method
	 * @param {React.ComponentType<LessonHeaderProps>} LessonTitleComponent
	 * @example <caption> Change component's background and add ellipsis to text </caption>
	 *
	 * //In custom_code/components/LessonTitle.js...
	 *
	 * import React from "react";
	 * import {View, Text} from "react-native";
	 * import Animated from "react-native-reanimated";
	 *
	 * const LessonTitle = (props) => {
	 *
	 *  const {
	 *    global,
	 *    colors,
	 *    paddingTop,
	 *    lesson,
	 *    t,
	 *    labels
	 *  } = props;
	 *
	 *  const paddingBottom = 14;
	 *
	 *  let backgroundColor = colors.bodyFrontBg;
	 *  if (lesson.title.includes("Android")){
	 *    backgroundColor = "red"
	 *  }
	 *
	 *  return (
	 *    <Animated.View
	 *      style={[
	 *        {
	 *          backgroundColor: backgroundColor,
	 *          width: "100%",
	 *          shadowOffset: {width: 0, height: 1},
	 *          shadowRadius: 1,
	 *          shadowColor: "#000",
	 *          shadowOpacity: 0.05
	 *        }
	 *     ]}
	 *    >
	 *    <View
	 *      style={[
	 *        global.row,
	 *        {
	 *          justifyContent: "space-between",
	 *          alignItems: "flex-start",
	 *          paddingTop,
	 *          paddingBottom
	 *        }
	 *      ]}
	 *    >
	 *      <Animated.View
	 *        style={{
	 *          flex: 1,
	 *          paddingHorizontal: 20
	 *        }}
	 *      >
	 *        <Animated.Text
	 *          style={[
	 *            global.courseHeaderTitle,
	 *            {marginBottom: 5}
	 *          ]}
	 *          numberOfLines={1} //Adds ellipsis to lesson title
	 *        >
	 *          {lesson.title}
	 *        </Animated.Text>
	 *        <Text style={global.courseHeaderSubTitle}>
	 *          {t("lesson:count", {
	 *            label: labels.lesson,
	 *            current: lesson.order,
	 *            total: lesson.total
	 *          })}
	 *        </Text>
	 *      </Animated.View>
	 *    </View>
	 *    </Animated.View>
	 *  );
	 * };
	 *
	 * export default LessonTitle;
	 *
	 * //In custom_code/index.js...
	 *
	 * ...
	 * import LessonTitle from "./components/LessonTitle"
	 * export const applyCustomCode = externalCodeSetup => {
	 *  externalCodeSetup.lessonSingleScreenApi.setLessonTitleComponent(props => <LessonTitle {...props} />)
	 * }
	 *
	 * @example <caption> Add screen header components to lesson title </caption>
	 *
	 * // In custom_code/components/LessonTitle.js...
	 * import React from "react";
	 * import { useSelector } from "react-redux";
	 * import { View, Text, StyleSheet } from "react-native";
	 * import Animated from "react-native-reanimated";
	 * import PrevNext from "@src/components/Course/PrevNext";
	 * import Icon from "@src/components/Icon";
	 * import TimeCounter from "@src/components/TimeCounterAutoPause";
	 *
	 * const LessonTitle = (props) => {
	 *
	 *   const {
	 *     title,
	 *     global,
	 *     colors,
	 *     paddingTop,
	 *     lesson,
	 *     t,
	 *     labels,
	 *     onQuizClick,
	 *     onLessonClick,
	 *     onTopicClick,
	 *     prevObject,
	 *     nextObject,
	 *     courseId,
	 *     nextLockedAlert,
	 *     backToCourse,
	 *     course,
	 *     loading,
	 *     renderTimer,
	 *     onTimePassed,
	 *     navigation
	 *   } = props;
	 *
	 *   const paddingBottom = 14;
	 *
	 *   const renderDefaultTimer = false
	 *
	 *   const isLessonCompleting = useSelector(state => state.singleLesson.completing == lesson.id);
	 *
	 *   const CustomTimer = () => {
	 *
	 *     if (loading || !lesson.requireTimer || isLessonCompleting)
	 *       return null;
	 *
	 *     return <View
	 *       style={{
	 *         flexDirection: "row",
	 *         alignItems: "center"
	 *       }}
	 *     >
	 *       <Text>My Custom Timer</Text>
	 *       <Icon
	 *         icon={{fontIconName: "stopwatch", weight: 400}}
	 *         webIcon={"IconArrowBack"}
	 *         tintColor={colors.textIconColor}
	 *         styles={{
	 *           marginRight: 6,
	 *           height: 20,
	 *           width: 20
	 *         }}
	 *       />
	 *       <TimeCounter
	 *         paused={!navigation.isActive}
	 *         onTimePassed={onTimePassed}
	 *         initialSeconds={0}
	 *         textProps={{ style: global.timer }}
	 *       />
	 *     </View>
	 *   }
	 *
	 *   return (
	 *     <Animated.View
	 *       style={[
	 *         {
	 *           backgroundColor: colors.bodyFrontBg,
	 *           width: "100%",
	 *           shadowOffset: { width: 0, height: 1 },
	 *           shadowRadius: 1,
	 *           shadowColor: "#000",
	 *           shadowOpacity: 0.05,
	 *           marginTop: 50
	 *         }
	 *       ]}
	 *     >
	 *       <View
	 *         style={[
	 *           global.row,
	 *           {
	 *             justifyContent: "space-between",
	 *             alignItems: "flex-start",
	 *             paddingTop,
	 *             paddingBottom
	 *           }
	 *         ]}
	 *       >
	 *         <Animated.View
	 *           style={{
	 *             flex: 1,
	 *             paddingHorizontal: 20
	 *           }}
	 *         >
	 *          //ScreenHeader components
	 *           <View style={{ flexDirection: "row", marginLeft: -20 }}>
	 *             {backToCourse}
	 *
	 *             <PrevNext
	 *               {...{ onQuizClick, onLessonClick, onTopicClick }}
	 *               global={global}
	 *               colors={colors}
	 *               t={t}
	 *               prevObject={prevObject}
	 *               nextObject={nextObject}
	 *               courseId={courseId}
	 *               nextLockedAlert={nextLockedAlert}
	 *             />
	 *
	 *             {renderDefaultTimer ? renderTimer : <CustomTimer />}
	 *
	 *           </View>
	 *           //End ScreenHeader components
	 *
	 *           <Animated.Text
	 *             style={[
	 *               global.courseHeaderTitle,
	 *               { marginBottom: 5 }
	 *             ]}
	 *             numberOfLines={1} //Adds ellipsis to lesson title
	 *           >
	 *             {lesson.title}
	 *           </Animated.Text>
	 *
	 *           <Text style={global.courseHeaderSubTitle}>
	 *             {t("lesson:count", {
	 *               label: labels.lesson,
	 *               current: lesson.order,
	 *               total: lesson.total
	 *             })}
	 *           </Text>
	 *         </Animated.View>
	 *       </View>
	 *     </Animated.View>
	 *   );
	 * };
	 *
	 * export default LessonTitle;
	 *
	 * //In custom_code/index.js...
	 *
	 * ...
	 * import LessonTitle from "./components/LessonTitle"
	 * export const applyCustomCode = externalCodeSetup => {
	 *  externalCodeSetup.lessonSingleScreenApi.setLessonTitleComponent(props => <LessonTitle {...props} />)
	 * }
	 */
	setLessonTitleComponent = (
		LessonTitleComponent: React.ComponentType<LessonHeaderProps> | null
	) => {
		this.LessonTitleComponent = LessonTitleComponent;
	};

	LessonScreenHeader: React.ComponentType<
		LessonScreenHeaderProps
	> | null = null;
	/**
	 * You can use this hook to customize the header of the Lesson Single Screen which by default, contains the back-to-course button and the previous/next buttons.
	 * @method
	 * @param {React.ComponentType<LessonScreenHeaderProps>} LessonScreenHeader
	 * @example
	 *
	 * //In custom_code/components/LessonScreenHeader.js...
	 *
	 * import React from "react";
	 * import {View} from "react-native";
	 * import Animated from "react-native-reanimated";
	 * import {DEVICE_WIDTH} from "@src/styles/global";
	 * import AuthWrapper from "@src/components/AuthWrapper";
	 *
	 * const Header = ({
	 *     headerLeftStyle,
	 *     style,
	 *     global,
	 *     backToCourse,
	 *     renderTimer,
	 *     headerRightAuthWrapperProps,
	 *     prevNext
	 * }) => {
	 *   return (
	 *     <Animated.View
	 *       style={[
	 *         global.row,
	 *         global.fakeHeader,
	 *         {
	 *           backgroundColor: "transparent",
	 *           paddingHorizontal: 10,
	 *           overflow: "hidden"
	 *         },
	 *         {
	 *           width: DEVICE_WIDTH
	 *         },
	 *         style
	 *       ]}
	 *     >
	 *       <View
	 *         style={[
	 *           {
	 *             alignItems: "center",
	 *             justifyContent: "center",
	 *             flexDirection: "row",
	 *             flex: 1,
	 *             height: "100%"
	 *           }
	 *         ]}
	 *       >
	 *         <View style={[global.headerButtonLeft, headerLeftStyle]}>
	 *           {backToCourse}
	 *         </View>
	 *         <View style={[global.headerCustomTitle]}>
	 *           {renderTimer}
	 *         </View>
	 *         <View style={[global.headerButtonRight]}>
	 *           <AuthWrapper
	 *             actionOnGuestLogin={"hide"}
	 *             {...headerRightAuthWrapperProps}
	 *           >
	 *             {prevNext}
	 *           </AuthWrapper>
	 *         </View>
	 *       </View>
	 *     </Animated.View>
	 *   );
	 * };
	 *
	 * export default Header;
	 *
	 * //In custom_code/index.js...
	 *
	 * import LessonScreenHeader from "./components/LessonScreenHeader";
	 * export const applyCustomCode = externalCodeSetup => {
	 *  externalCodeSetup.lessonSingleScreenApi.setLessonScreenHeader(props => <LessonScreenHeader {...props}/>)
	 * }
	 */
	setLessonScreenHeader = (
		LessonScreenHeader: React.ComponentType<LessonScreenHeaderProps> | null
	) => {
		this.LessonScreenHeader = LessonScreenHeader;
	};

	VideoProgressionComponent: React.ComponentType<
		VideoProgressionComponentProps
	> | null = null;
	/**
	 * You can use this hook to customize the Video Progression component in the single lesson screen.
	 * For example, you can use this to change the size of the video player or add a custom function when the video finishes playing on a lesson.
	 * @method
	 * @param {React.ComponentType<VideoProgressionComponentProps>} VideoProgressionComponent
	 * @example <caption> Execute a custom callback when video has finished playing </caption>
	 *
	 * ...
	 * import AppVideo from "@src/components/Video/AppVideo";
	 *
	 * export const applyCustomCode = externalCodeSetup => {
	 *
	 *   externalCodeSetup.lessonSingleScreenApi.setVideoProgressionComponent(props => {
	 *     const {
	 *       lessonVideoStyle,
	 *       controls,
	 *       autoPlay,
	 *       videoCallback,
	 *       url,
	 *       width,
	 *       height,
	 *       global,
	 *       isNavActive,
	 *       lesson,
	 *       videoWatched,
	 *       setVideoWatched,
	 *       onCompleteButtonClick
	 *     } = props;
	 *
	 *     const customCallback = settings => event => {
	 *
	 *       if (event.nativeEvent.data === "ENDED") {
	 *
	 *         if (!videoWatched)
	 *           setVideoWatched();
	 *
	 *         Alert.alert(
	 *           "Video Complete",
	 *           "You have finished watching the video. Do you want to mark the lesson as complete?",
	 *           [
	 *             {
	 *               text: "Cancel",
	 *               onPress: () => console.log("Cancel Pressed"),
	 *               style: "cancel"
	 *             },
	 *             { text: "OK", onPress: () => onCompleteButtonClick() }
	 *           ]
	 *         );
	 *       }
	 *
	 *     }
	 *
	 *     return <View style={lessonVideoStyle}>
	 *       <Text>Please finish watching the video below to proceed...</Text>
	 *       <AppVideo
	 *         controls={controls}
	 *         autoPlay={autoPlay}
	 *         // videoCallback={videoCallback()}
	 *         videoCallback={customCallback(lesson.settings)}
	 *         url={url}
	 *         width={width}
	 *         height={height}
	 *         global={global}
	 *         isNavActive={isNavActive}
	 *       />
	 *     </View>
	 *   })
	 * }
	 *
	 */
	setVideoProgressionComponent = (
		VideoProgressionComponent: React.ComponentType<
			VideoProgressionComponentProps
		> | null
	) => {
		this.VideoProgressionComponent = VideoProgressionComponent;
	};

	AfterMaterialsComponent: React.ComponentType<
		AfterMaterialsComponentProps
	> | null = null;
	/**
	 * You can use this hook to add a component at the bottom of the lesson single screen just after the component that displays the materials.
	 * @method
	 * @param {React.ComponentType<AfterMaterialsComponentProps>} AfterMaterialsComponent
	 * @example
	 *
	 * //In custom_code/components/LessonBottomComponent.js...
	 *
	 * import React from "react";
	 * import { View, Text, TouchableOpacity } from "react-native";
	 * const LessonBottomComponent = props => {
	 *
	 *     const {
	 *         colors,
	 *         course,
	 *         navigation
	 *     } = props;
	 *
	 *     const back = () => {
	 *         navigation.navigate({
	 *             routeName: "CoursesSingleScreen",
	 *             params: {
	 *                 id: course.id,
	 *                 course
	 *             },
	 *             key: course.id.toString()
	 *         })
	 *     }
	 *     return <View style={{
	 *         backgroundColor: colors.bodyFrontBg,
	 *         paddingHorizontal: 20,
	 *         paddingBottom: 20,
	 *         minHeight: 100,
	 *     }}>
	 *         <Text>This lesson is part of the {course.title.rendered} course </Text>
	 *         <TouchableOpacity onPress={back}>
	 *             <Text>
	 *                 Back To Course
	 *             </Text>
	 *         </TouchableOpacity>
	 *     </View>
	 * }
	 *
	 *  export default LessonBottomComponent;
	 *
	 *  //In custom_code/index.js...
	 *
	 *  ...
	 *
	 * import LessonBottomComponent from "./components/LessonBottomComponent";
	 * export const applyCustomCode = externalCodeSetup => {
	 *   externalCodeSetup.lessonSingleScreenApi.setAfterMaterialsComponent(props => <LessonBottomComponent {...props}/>)
	 * }
	 */
	setAfterMaterialsComponent = (
		AfterMaterialsComponent: React.ComponentType<
			AfterMaterialsComponentProps
		> | null
	) => {
		this.AfterMaterialsComponent = AfterMaterialsComponent;
	};

	LessonActionComponent: React.ComponentType<
		LessonActionComponentProps
	> | null = null;
	/**
	 * You can use this hook to customize the "Mark Complete" / "Completed" button.
	 * For example, you can add your own loading animation when the "Mark Complete" button is pressed.
	 * @method
	 * @param {React.ComponentType<LessonActionComponentProps>} LessonActionComponent
	 * @example <caption> Add a "Completing..." text when marking the lesson complete </caption>
	 *
	 * //In custom_code/components/LessonActionComponent.js...
	 * import React from "react";
	 * import { View, Text, ActivityIndicator } from "react-native";
	 *
	 * import AuthWrapper from "@src/components/AuthWrapper";
	 * import AppTouchableOpacity from "@src/components/AppTouchableOpacity";
	 * import Icon from "@src/components/Icon";
	 * import { isColorDark } from "@src/utils";
	 *
	 * const LessonActionComponent = ({
	 *     showComplete,
	 *     global,
	 *     colors,
	 *     t,
	 *     lesson,
	 *     onCompleteButtonClick,
	 *     completing,
	 *     completeDisabled,
	 *     labels
	 * }) => (<AuthWrapper actionOnGuestLogin={"hide"}>
	 *     {showComplete && (
	 *         <View
	 *             style={[
	 *                 global.row,
	 *                 {
	 *                     backgroundColor: colors.bodyFrontBg,
	 *                     borderTopColor: colors.borderColor
	 *                 },
	 *                 global.lessonActionButtonContainer
	 *             ]}
	 *         >
	 *             <AppTouchableOpacity
	 *                 style={[
	 *                     { flex: 1 },
	 *                     {
	 *                         opacity: !lesson.completed && completeDisabled ? 0.5 : 1,
	 *                         backgroundColor: !lesson.completed
	 *                             ? colors.primaryButtonBg
	 *                             : colors.bodyFrontBg
	 *                     },
	 *                     global.completeLessonButtonW
	 *                 ]}
	 *                 disabled={lesson.completed || completeDisabled}
	 *                 onPress={onCompleteButtonClick}
	 *             >
	 *                 <View style={global.row}>
	 *                     <View style={global.linkWithArrow}>
	 *                         {!lesson.completed ? (
	 *                             completing && (
	 *                                 <>
	 *                                     <Text style={{color: "#fff"}}>Completing...</Text>
	 *                                     <ActivityIndicator
	 *                                         animating={true}
	 *                                         color={colors.primaryButtonColor}
	 *                                         size="small"
	 *                                         style={global.lessonButtonLoadingIcon}
	 *                                     />
	 *                                 </>
	 *                             )
	 *                         ) : (
	 *                             <Icon
	 *                                 webIcon={""}
	 *                                 icon={{fontIconName: "check", weight: 200}}
	 *                                 styles={global.lessonActionCompleteIcon}
	 *                             />
	 *                         )}
	 *                         <Text
	 *                             style={[
	 *                                 {
	 *                                     marginLeft: 10,
	 *                                     color: !lesson.completed
	 *                                         ? colors.primaryButtonColor
	 *                                         : isColorDark(colors.bodyFrontBg)
	 *                                             ? "white"
	 *                                             : "black"
	 *                                 },
	 *                                 !lesson.completed
	 *                                     ? global.completeLessonButton
	 *                                     : global.completeButton
	 *                             ]}
	 *                         >
	 *                             {t(
	 *                                 lesson.completed
	 *                                     ? "lesson:completed"
	 *                                     : "lesson:completeLesson",
	 *                                 { label: labels.lesson.toLowerCase() }
	 *                             )}
	 *                         </Text>
	 *                     </View>
	 *                 </View>
	 *             </AppTouchableOpacity>
	 *         </View>
	 *     )}
	 * </AuthWrapper>)
	 *
	 * export default LessonActionComponent;
	 *
	 * //In custom_code/index.js...
	 *
	 * ...
	 *
	 * import LessonActionComponent from "./components/LessonActionComponent";
	 * export const applyCustomCode = (externalCodeSetup: any) => {
	 *     externalCodeSetup.lessonSingleScreenApi.setLessonActionComponent(props => <LessonActionComponent {...props} />)
	 * }
	 *
	 */
	setLessonActionComponent = (
		LessonActionComponent: React.ComponentType<
			LessonActionComponentProps
		> | null
	) => {
		this.LessonActionComponent = LessonActionComponent;
	};

	lessonViewModelFilter = (
		viewModel: TLessonViewModel | Record<any, any>,
		lesson: Record<any, any>
	) => viewModel;

	/**
	 * Sets the callback function that can change an existing lesson view model object.
	 * @method
	 * @param {TransformLessonViewModelCallback} lessonViewModelFilter
	 * @example <caption>Remove the native blocks in a lesson</caption>
	 * externalCodeSetup.lessonSingleScreenApi.setLessonViewModelFilter((viewModel, lesson) => {
	 *     return {
	 *         ...viewModel,
	 *         contentNative: []
	 *     }
	 * })
	 */
	setLessonViewModelFilter = (
		lessonViewModelFilter: (
			viewModel: TLessonViewModel | Record<any, any>,
			lesson: Record<any, any>
		) => TLessonViewModel | Record<any, any>
	) => {
		this.lessonViewModelFilter = lessonViewModelFilter;
	};

	OfflineComponent: React.ComponentType<OfflineComponentProps> | null = null;

	/**
	 * You can use this hook to customize the component that displays a "This content is not available offline" message if a webview is used for rendering the lesson content while the device is offline.
	 * @method
	 * @param {React.ComponentType<OfflineComponentProps>} OfflineComponent
	 * @example
	 *
	 * ...
	 *
	 * import EmptyList from "@src/components/EmptyList";
	 *
	 * export const applyCustomCode = (externalCodeSetup) => {
	 *     externalCodeSetup.lessonSingleScreenApi.setOfflineComponent(
	 *         ({containerStyle, t, global, emptyListStyle}) => (
	 *             <View style={containerStyle}>
	 *                 <EmptyList
	 *                     emptyText={{
	 *                         title: t("common:contentOfflineMessage"),
	 *                         icon: {fontIconName: "wifi-slash", weight: 400}
	 *                     }}
	 *                     global={global}
	 *                     style={emptyListStyle}
	 *                 />
	 *             </View>
	 *         )
	 *     );
	 * }
	 */
	setOfflineComponent = (
		OfflineComponent: React.ComponentType<OfflineComponentProps> | null
	) => {
		this.OfflineComponent = OfflineComponent;
	};

	WebViewContentComponent: React.ComponentType<
		WebViewContentComponentProps
	> | null = null;

	/**
	 * You can use this hook to replace the webview being used in the lesson content.
	 * For example, you can choose to replace it with the default react-native webview.
	 * @method
	 * @param {React.ComponentType<WebViewContentComponentProps>} WebViewContentComponent
	 * @example
	 *
	 * ...
	 *
	 * import WebViewWithMore from "@src/components/WebViewWithMore";
	 * export const applyCustomCode = (externalCodeSetup) => {
	 *     externalCodeSetup.lessonSingleScreenApi.setWebViewContentComponent(
	 *         ({
	 *             online,
	 *             t,
	 *             onShouldStartLoadWithRequest,
	 *             height,
	 *             source,
	 *             global,
	 *             colors,
	 *             ModalHeaderComponent
	 *         }) => (
	 *             <WebViewWithMore
	 *                 online={online}
	 *                 t={t}
	 *                 onShouldStartLoadWithRequest={onShouldStartLoadWithRequest}
	 *                 height={height}
	 *                 source={source}
	 *                 global={global}
	 *                 colors={colors}
	 *                 ModalHeaderComponent={ModalHeaderComponent}
	 *             />
	 *         )
	 *     );
	 * }
	 */
	setWebViewContentComponent = (
		WebViewContentComponent: React.ComponentType<
			WebViewContentComponentProps
		> | null
	) => {
		this.WebViewContentComponent = WebViewContentComponent;
	};

	LessonMaterialsSectionTitle: React.ComponentType<
		LessonMaterialsSectionTitleProps
	> | null = null;

	/**
	 * You can use this hook to customize the component that displays the "Materials" text.
	 * @method
	 * @param {React.ComponentType<LessonMaterialsSectionTitleProps>} LessonMaterialsSectionTitle
	 * @example
	 *
	 * ...
	 *
	 * export const applyCustomCode = (externalCodeSetup) => {
	 *   externalCodeSetup.lessonSingleScreenApi.setLessonMaterialsSectionTitle(
	 *       ({global, t}) => (
	 *           <Text
	 *               style={{
	 *                   ...global.courseRoundBoxTitleAbove,
	 *                   marginBottom: 20
	 *               }}
	 *           >
	 *               {t("lesson:materials")}
	 *            </Text>
	 *       )
	 *   );
	 * }
	 */
	setLessonMaterialsSectionTitle = (
		LessonMaterialsSectionTitle: React.ComponentType<
			LessonMaterialsSectionTitleProps
		> | null
	) => {
		this.LessonMaterialsSectionTitle = LessonMaterialsSectionTitle;
	};

	AssignmentsHeader: React.ComponentType<AssignmentsHeaderProps> | null = null;

	/**
	 *
	 * You can use this hook to customize the assignments title and the component that displays the total approved assignments.
	 * @method
	 * @param {React.ComponentType<AssignmentsHeaderProps>} AssignmentsHeader
	 * @example
	 *
	 * ...
	 *
	 * export const applyCustomCode = (externalCodeSetup) => {
	 *     externalCodeSetup.lessonSingleScreenApi.setAssignmentsHeader(
	 *         ({global, t, totalAssignments, approved}) => (
	 *             <View style={{...global.row, flex: 1, marginBottom: 15}}>
	 *                 <Text style={[global.assignmentHeading, {flex: 1}]}>
	 *                     {t("assignment:heading")}
	 *                 </Text>
	 *                 {totalAssignments !== 0 && (
	 *                     <Text style={[global.assignmentDesc]}>
	 *                         {t("assignment:approvedOutOfTotal", {
	 *                             total: totalAssignments,
	 *                             approved
	 *                         })}
	 *                     </Text>
	 *                 )}
	 *             </View>
	 *         )
	 *     );
	 * }
	 */
	setAssignmentsHeader = (
		AssignmentsHeader: React.ComponentType<AssignmentsHeaderProps> | null
	) => {
		this.AssignmentsHeader = AssignmentsHeader;
	};

	AssignmentItemIcon: React.ComponentType<
		AssignmentItemIconProps
	> | null = null;

	/**
	 * You can use this to change the icon beside the assignment title.
	 * For example, you can use this to remove or modify the default icon.
	 * @method
	 * @param {React.ComponentType<AssignmentItemIconProps>} AssignmentItemIcon
	 * @example
	 *
	 * ...
	 *
	 * import Icon from "@src/components/Icon";
	 * export const applyCustomCode = (externalCodeSetup) => {
	 *     externalCodeSetup.lessonSingleScreenApi.setAssignmentItemIcon(
	 *         ({icon, styles}) => <Icon icon={icon} styles={styles} />
	 *     );
	 * }
	 */
	setAssignmentItemIcon = (
		AssignmentItemIcon: React.ComponentType<AssignmentItemIconProps> | null
	) => {
		this.AssignmentItemIcon = AssignmentItemIcon;
	};

	AssignmentItemTitle: React.ComponentType<
		AssignmentItemTitleProps
	> | null = null;

	/**
	 * You can use this to customize the AssignmentItemTitle component.
	 * For example, you can use this to change the font color or size of the title.
	 * @method
	 * @param {React.ComponentType<AssignmentItemTitleProps>} AssignmentItemTitle
	 * @example
	 *
	 * ...
	 *
	 * export const applyCustomCode = (externalCodeSetup) => {
	 *     externalCodeSetup.lessonSingleScreenApi.setAssignmentItemTitle(({
	 *         title,
	 *         style
	 *     }) => <Text style={style}>{title}</Text>)
	 * }
	 */
	setAssignmentItemTitle = (
		AssignmentItemTitle: React.ComponentType<AssignmentItemTitleProps> | null
	) => {
		this.AssignmentItemTitle = AssignmentItemTitle;
	};

	AssignmentItemStatus: React.ComponentType<
		AssignmentItemStatusProps
	> | null = null;

	/**
	 * You can use this to customize the AssignmentItemStatus component.
	 * @method
	 * @param {React.ComponentType<AssignmentItemStatusProps>} AssignmentItemStatus
	 * @example
	 *
	 * ...
	 *
	 * import {BubbleIcon} from "@src/components/BubbleIcon";
	 * export const applyCustomCode = (externalCodeSetup) => {
	 *     externalCodeSetup.lessonSingleScreenApi.setAssignmentItemStatus(
	 *         ({global, text, containerStyle, textStyle}) => (
	 *             <BubbleIcon
	 *                 {...{
	 *                     global,
	 *                     text,
	 *                     containerStyle,
	 *                     textStyle
	 *                 }}
	 *             />
	 *         )
	 *     );
	 * }
	 */
	setAssignmentItemStatus = (
		AssignmentItemStatus: React.ComponentType<AssignmentItemStatusProps> | null
	) => {
		this.AssignmentItemStatus = AssignmentItemStatus;
	};

	AssignmentItemComment: React.ComponentType<
		AssignmentItemCommentProps
	> | null = null;

	/**
	 * You can use this to customize the AssignmentItemComment button.
	 * @method
	 * @param {React.ComponentType<AssignmentItemCommentProps>} AssignmentItemComment
	 * @example
	 *
	 * ...
	 *
	 * import AssignmentCommentButton from "@src/components/Course/Assignment/AssignmentCommentButton";
	 * export const applyCustomCode = (externalCodeSetup) => {
	 *     externalCodeSetup.lessonSingleScreenApi.setAssignmentItemComment(
	 *         ({
	 *             pressHandler,
	 *             tintColor,
	 *             containerStyle,
	 *             count,
	 *             size,
	 *             global,
	 *             lightMode
	 *         }) => (
	 *             <AssignmentCommentButton
	 *                 {...{
	 *                     pressHandler,
	 *                     tintColor,
	 *                     containerStyle,
	 *                     count,
	 *                     size,
	 *                     global,
	 *                     lightMode
	 *                 }}
	 *             />
	 *         )
	 *     );
	 * }
	 */
	setAssignmentItemComment = (
		AssignmentItemComment: React.ComponentType<
			AssignmentItemCommentProps
		> | null
	) => {
		this.AssignmentItemComment = AssignmentItemComment;
	};

	AssignmentItemDownload: React.ComponentType<
		AssignmentItemDownloadProps
	> | null = null;

	/**
	 * You can use this to customize the AssignmentItemDownload button.
	 * For example, you can change the icon and add a confirmation modal before allowing the user to download the assignment file.
	 * @method
	 * @param {React.ComponentType<AssignmentItemDownloadProps>} AssignmentItemDownload
	 * @example
	 *
	 * ...
	 *
	 * import AssignmentDownloadButton from "@src/components/Course/Assignment/AssignmentDownloadButton";
	 * export const applyCustomCode = (externalCodeSetup) => {
	 *     externalCodeSetup.lessonSingleScreenApi.setAssignmentItemDownload(
	 *         ({pressHandler, tintColor, containerStyle, size, global, lightMode}) => (
	 *             <AssignmentDownloadButton
	 *                 {...{
	 *                     pressHandler,
	 *                     tintColor,
	 *                     containerStyle,
	 *                     size,
	 *                     global,
	 *                     lightMode
	 *                 }}
	 *             />
	 *         )
	 *     );
	 * }
	 *
	 */
	setAssignmentItemDownload = (
		AssignmentItemDownload: React.ComponentType<
			AssignmentItemDownloadProps
		> | null
	) => {
		this.AssignmentItemDownload = AssignmentItemDownload;
	};

	AssignmentItemDownloadProgress: React.ComponentType<
		AssignmentItemDownloadProgressProps
	> | null = null;

	/**
	 * You can use this to customize the progress indicator which is showed when the assignment item is being downloaded.
	 * @method
	 * @param {React.ComponentType<AssignmentItemDownloadProgressProps>} AssignmentItemDownloadProgress
	 * @example
	 *
	 * ...
	 *
	 * import AssignmentDownloadProgress from "@src/components/Course/Assignment/AssignmentDownloadProgress";
	 * export const applyCustomCode = (externalCodeSetup) => {
	 *     externalCodeSetup.lessonSingleScreenApi.setAssignmentItemDownloadProgress(
	 *         ({progress, unfilledColor, tintColor}) => (
	 *             <AssignmentDownloadProgress
	 *                 {...{
	 *                     progress,
	 *                     unfilledColor,
	 *                     tintColor
	 *                 }}
	 *             />
	 *         )
	 *     );
	 * }
	 *
	 */
	setAssignmentItemDownloadProgress = (
		AssignmentItemDownloadProgress: React.ComponentType<
			AssignmentItemDownloadProgressProps
		> | null
	) => {
		this.AssignmentItemDownloadProgress = AssignmentItemDownloadProgress;
	};

	MaterialsComponent: React.ComponentType<
		MaterialsComponentProps
	> | null = null;

	/**
	 * You can use this to customize the component that displays the materials of the lesson.
	 * @method
	 * @param {React.ComponentType<MaterialsComponentProps>} MaterialsComponent
	 * @example
	 *
	 * ...
	 *
	 * import {
	 *   Dimensions,
	 * } from "react-native";
	 * import HTML from "react-native-render-html";
	 * import {RenderListPrefix} from "@src/components/Course/CourseMaterials"
	 * const ent = require("ent");
	 * const DEVICE_WIDTH = Dimensions.get("window").width;
	 *
	 * export const applyCustomCode = (externalCodeSetup) => {
	 *
	 *     externalCodeSetup.lessonSingleScreenApi.setMaterialsComponent((props) => {
	 *
	 *         const {
	 *             tagsStyles,
	 *             materialsStyles,
	 *             baseFontStyle,
	 *             materials,
	 *             onLinkPress,
	 *             global,
	 *             colors
	 *         } = props;
	 *
	 *         return (
	 *                 <HTML
	 *                     tagsStyles={{...tagsStyles, ...materialsStyles}}
	 *                     baseFontStyle={baseFontStyle(15)}
	 *                     html={ent.decode(materials)}
	 *                     imagesMaxWidth={DEVICE_WIDTH - 32}
	 *                     onLinkPress={onLinkPress}
	 *                     listsPrefixesRenderers={{
	 *                         ul: (attrib, children, styles, passProps) => (
	 *                             <RenderListPrefix
	 *                                 parent={"ul"}
	 *                                 colors={colors}
	 *                                 global={global}
	 *                                 passProps={passProps}
	 *                             />
	 *                         ),
	 *                         ol: (attrib, children, styles, passProps) => (
	 *                             <RenderListPrefix
	 *                                 parent={"ol"}
	 *                                 colors={colors}
	 *                                 global={global}
	 *                                 passProps={passProps}
	 *                             />
	 *                         )
	 *                     }}
	 *                 />
	 *             )
	 *     });
	 * }
	 */
	setMaterialsComponent = (
		MaterialsComponent: React.ComponentType<MaterialsComponentProps> | null
	) => {
		this.MaterialsComponent = MaterialsComponent;
	};
}