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;
};
}
Source