import * as React from "react";
import {
Course,
Lesson,
LearnTopic,
TLearnTopicViewModel,
TTranslationFunction
} from "./types";
import {NavigationService} from "./types";
export const API_NAME = "learnTopicSingleScreenApi";
/**
* LearnTopicAfterContentRendererProps
*/
type LearnTopicAfterContentRendererProps = {
topic: LearnTopic,
/**
* App global style
*/
global: Record<any, any>,
/**
* App colors
*/
colors: Record<any, any>,
navigation: NavigationService
};
/**
* TransformTopicActionButtonsCallback
*/
type TransformTopicActionButtonsCallback = {
/**
* Topic action button
*/
TopicButton: JSX.Element,
/**
* Returns `true` if "Mark Complete" button should be shown
*/
showComplete: boolean,
/**
* App global style
*/
global: Record<any, any>,
/**
* App colors
*/
colors: Record<any, any>,
topic: TLearnTopicViewModel,
/**
* Returns `true` if topic is being completed
*/
completing: boolean,
/**
* Learndash labels
*/
labels: Record<any, any>,
/**
* Marks the topic as complete
*/
handleComplete: Function
};
/**
* showMarkAsCompleteProps
*/
type showMarkAsCompleteProps = {
topic: LearnTopic
};
/**
* LearnTopicPrevNextComponentProps
*/
type LearnTopicPrevNextComponentProps = {
/**
* 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
};
/**
* LearnTopicHeaderProps
*/
type LearnTopicHeaderProps = {
topic: TLearnTopicViewModel,
lessonOrder: number,
paddingTop: number,
setHeaderHeight: Function,
/**
* App global style
*/
global: Record<any, any>,
/**
* App colors
*/
colors: Record<any, any>,
/**
* Learndash labels
*/
labels: 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,
/**
* 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,
course: Course,
/**
* Returns `true` if data is loading
*/
loading: boolean,
/**
* Returns `false` if topic doesn't have a timer set. Returns a component if a timer for the topic is set.
*/
renderTimer: boolean | React.ComponentType,
/**
* Function which updates the seconds passed in the topic screen container
*/
onTimePassed: Function,
navigation: NavigationService,
/**
* Returns `true` if prev/next buttons should be hidden
*/
hidePrevNext: boolean,
/**
* Returns `false` if hidePrevNext is `true`. Returns buttons which can navigate through previous and next screens if hidePrevNext is `false`
*/
prevNext: boolean | React.ComponentType
};
/**
* LearnTopicScreenHeaderProps
*/
type LearnTopicScreenHeaderProps = {
/**
* 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>,
topic: TLearnTopicViewModel,
lessonOrder: number,
paddingTop: number,
setHeaderHeight: Function,
/**
* App global style
*/
global: Record<any, any>,
/**
* App colors
*/
colors: Record<any, any>,
labels: 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,
/**
* 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,
course: Course,
/**
* Returns `true` if data is loading
*/
loading: boolean,
/**
* Returns `false` if topic doesn't have a timer set. Returns a component if a timer for the topic is set.
*/
renderTimer: boolean | React.ComponentType,
/**
* Function which updates the seconds passed in the topic screen container
*/
onTimePassed: Function,
navigation: NavigationService,
/**
* Returns `true` if prev/next buttons should be hidden
*/
hidePrevNext: boolean,
/**
* Returns `false` if hidePrevNext is `true`. Returns buttons which can navigate through previous and next screens if hidePrevNext is `false`
*/
prevNext: boolean | React.ComponentType
};
/**
* LearnTopicVideoProgressionComponentProps
*/
type LearnTopicVideoProgressionComponentProps = {
/**
* Default styling applied to topic video
*/
topicVideoStyle: 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,
topic: TLearnTopicViewModel,
/**
* Returns `true` if video should be shown
*/
showVideo: boolean,
/**
* Returns `true` if video has already been watched
*/
videoWatched: boolean,
/**
* Dispatches an action and marks the video as watched
*/
setVideoWatched: Function,
/**
* Dispatches an action to mark the topic as complete
*/
completeTopic: Function,
/**
* Function which considers different conditions (such as if quizzes inside a topic are already completed) before calling the `completeTopic` function
*/
onCompleteTopicClick: Function
};
/**
* LearnTopicAfterMaterialsComponentProps
*/
type LearnTopicAfterMaterialsComponentProps = {
topic: TLearnTopicViewModel,
lessonOrder: number,
/**
* App global style
*/
global: Record<any, any>,
/**
* App colors
*/
colors: Record<any, any>,
labels: Record<any, any>,
lesson: Lesson,
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,
course: Course,
/**
* Returns `true` if data is loading
*/
loading: boolean,
navigation: NavigationService,
/**
* Topic material
*/
materials: string
};
/**
* LearnTopicActionComponentProps
*/
type LearnTopicActionComponentProps = {
/**
* Returns `true` if "Mark Complete" button should be shown
*/
showComplete: boolean,
/**
* App global style
*/
global: Record<any, any>,
/**
* App colors
*/
colors: Record<any, any>,
t: TTranslationFunction,
topicVM: TLearnTopicViewModel,
/**
* Helper function which considers different conditions (such as if quizzes inside a topic are already completed) before calling the `completeTopic` function
*/
onCompleteTopicClick: Function,
/**
* Returns `true` if topic 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
};
/**
* LearnTopicOfflineComponentProps
*/
type LearnTopicOfflineComponentProps = {
/**
* 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>
};
/**
* LearnTopicWebViewContentComponentProps
*/
type LearnTopicWebViewContentComponentProps = {
/**
* 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
};
/**
* LearnTopicMaterialsSectionTitleProps
*/
type LearnTopicMaterialsSectionTitleProps = {
/**
* 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: NavigationService,
/**
* Handles link press for the HTML component
*/
onLinkPress: Function
};
/**
* TransformLearnTopicViewModelCallback
*/
type TransformLearnTopicViewModelCallback = {
viewModel: TLearnTopicViewModel,
topic: LearnTopic
};
/**
* @class
* Learn Topic Screen Hooks.
* Instance name: learnTopicSingleScreenApi
You can use this hook to customize the learn topic screen such as by adding a component by the topic content.
* @example
* externalCodeSetup.learnTopicSingleScreenApi.METHOD_NAME
*/
export class LearnTopicSingleScreenHooksApi {
afterContentRenderer: (
topic: LearnTopic,
global: Record<any, any>,
colors: Record<any, any>,
navigation: NavigationService
) => JSX.Element | null = () => null;
/**
* It adds a component after the topic content so you can customize the information to be displayed.
* @method
* @param {LearnTopicAfterContentRendererProps} renderFunction
* @example
* externalCodeSetup.learnTopicSingleScreenApi.setAfterContentRenderer((topicObject, global, colors, navigation) => (
* <TouchableOpacity onPress={() => navigation.navigate("CoursesScreen")}>
* <Text style={{fontSize: 12}}> Tap to go back to courses list</Text>
* </TouchableOpacity>
* ))
*/
setAfterContentRenderer = (
renderFunction: (
topic: LearnTopic,
global: Record<any, any>,
colors: Record<any, any>,
navigation: NavigationService
) => JSX.Element | null
) => {
this.afterContentRenderer = renderFunction;
};
transformTopicActionButtons = (
TopicButton: JSX.Element,
showComplete: boolean,
global: Record<any, any>,
colors: Record<any, any>,
topic: TLearnTopicViewModel,
completing: boolean,
labels: Record<any, any>,
handleComplete: Function
) => TopicButton;
/**
* You can transform the default learn topic action button by replacing it with your preferred action buttons.
* For example, you can add an inline button to the topic screen for marking topic completion.
* @param {TransformTopicActionButtonsCallback} transformTopicActionButtons
* @method
* @example <caption> Add more components for topic action </caption>
*
* externalCodeSetup.learnTopicSingleScreenApi.setTransformTopicActionButtons((
* TopicButton,
* showComplete,
* global,
* colors,
* topic,
* completing,
* labels,
* handleComplete) => {
*
* const Buttons =
* <View style={[global.row, { backgroundColor: "#fff" }]}>
*
* <View style={{ width: "45%", backgroundColor: "#fff", paddingHorizontal: 20, paddingVertical: 15 }}>
* <AppTouchableOpacity
* style={[
* global.completeTopicButtonW,
* { 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" }}>
* {TopicButton}
* </View>
* </View>
*
* return Buttons;
* })
*/
setTransformTopicActionButtons = (
transformTopicActionButtons: (
TopicButton: JSX.Element,
showComplete: boolean,
global: Record<any, any>,
colors: Record<any, any>,
topic: TLearnTopicViewModel,
completing: boolean,
labels: Record<any, any>,
handleComplete: Function
) => JSX.Element
) => {
this.transformTopicActionButtons = transformTopicActionButtons;
};
showMarkAsComplete = (topic: LearnTopic) => true;
/**
* Use this to hide or show the mark as complete component.
* @method
* @param {showMarkAsCompleteProps} showMarkAsComplete
* @example
* externalCodeSetup.learnTopicSingleScreenApi.setShowMarkAsComplete((topic) => false);
*/
setShowMarkAsComplete = (
showMarkAsComplete: (topic: LearnTopic) => boolean
) => {
this.showMarkAsComplete = showMarkAsComplete;
};
PrevNextComponent: React.ComponentType<
LearnTopicPrevNextComponentProps
> | null = null;
/**
* You can use this to replace the previous and next buttons on the learn topic single screen if you want to change the default option which always displays the prev/next buttons.
* @method
* @param {React.ComponentType<LearnTopicPrevNextComponentProps>} PrevNextComponent
* @example <caption> Remove previous and next buttons if there is no previous and next objects. Otherwise, return the default previous and next buttons </caption>
*
* //In custom_code/components/PrevNext.js
*
* import React from "react";
* import { Text, View, StyleSheet } from "react-native";
* import AppTouchableOpacity from "@src/components/AppTouchableOpacity";
* import Icon from "@src/components/Icon";
* import { shadeColor } from "@src/utils";
*
* export const onObjectClick = (
* object,
* onQuizClick,
* onTopicClick,
* onLessonClick
* ) => {
* if (!!!object) {
* return false;
* }
* switch (object.type) {
* case "quiz":
* onQuizClick(object.parentType, object.parent)(object);
* break;
* case "topic":
* onTopicClick(object, object.parent);
* break;
* case "lesson":
* onLessonClick(object);
* break;
* }
* };
*
* const PrevNext = ({
* global,
* colors,
* t,
* prevObject,
* nextObject,
* courseId,
* onQuizClick,
* onLessonClick,
* onTopicClick,
* nextLockedAlert
* }) => {
*
* if (!nextObject && !prevObject) {
* return null;
* }
*
* return (
* <View style={[global.row]}>
* <AppTouchableOpacity
* style={[
* global.wrappedButton,
* global.wrappedTextButton,
* { marginRight: 4 }
* ]}
* onPress={() => {
* if (prevObject !== "disabled") {
* onObjectClick(prevObject, onQuizClick, onTopicClick, onLessonClick);
* }
* }}
* >
* <View style={global.row}>
* <View style={global.linkWithArrow}>
* <Text
* style={[
* global.wrappedTextButtonLabel,
* {
* color:
* !!!prevObject || prevObject === "disabled"
* ? shadeColor(colors.headerIconColor, 0.4)
* : colors.headerIconColor
* }
* ]}
* >
* {t("lesson:prevButtonText")}
* </Text>
* </View>
* </View>
* </AppTouchableOpacity>
*
* <AppTouchableOpacity
* style={[global.wrappedButton, global.wrappedTextButton]}
* onPress={() => {
* if (nextObject !== "disabled") {
* onObjectClick(nextObject, onQuizClick, onTopicClick, onLessonClick);
* } else if (typeof nextLockedAlert === "function") {
* nextLockedAlert();
* }
* }}
* >
* <View style={global.row}>
* <View style={global.linkWithArrow}>
* <Text
* style={[
* global.wrappedTextButtonLabel,
* {
* color:
* !!!nextObject || nextObject === "disabled"
* ? shadeColor(colors.headerIconColor, 0.4)
* : colors.headerIconColor
* }
* ]}
* >
* {t("lesson:nextButtonText")}
* </Text>
* </View>
* </View>
* </AppTouchableOpacity>
* </View>
* );
* };
*
* export default PrevNext;
*
* //In custom_code/index.js...
*
* ...
*
* import PrevNextComponent from './components/PrevNext';
* export const applyCustomCode = externalCodeSetup => {
* externalCodeSetup.learnTopicSingleScreenApi.setPrevNextComponent((props) => <PrevNextComponent {...props} />);
* }
*
*/
setPrevNextComponent = (
PrevNextComponent: React.ComponentType<
LearnTopicPrevNextComponentProps
> | null
) => {
this.PrevNextComponent = PrevNextComponent;
};
LearnTopicTitleComponent: React.ComponentType<
LearnTopicHeaderProps
> | null = null;
/**
* You can use this to replace the topic's title component.
* For example, you can use this to change the subtitle's color.
* @method
* @param {React.ComponentType<LearnTopicHeaderProps>} LearnTopicTitleComponent
* @example <caption> Change subtitle colors </caption>
*
* //In custom_code/components/TopicTitle.js...
* import React from "react";
* import {View, Text} from "react-native";
* import Animated from "react-native-reanimated";
*
* const TopicTitle = ({
* topic,
* global,
* colors,
* paddingTop,
* setHeaderHeight,
* t,
* labels,
* lessonOrder
* }) => {
*
* const paddingBottom = 14;
*
* return (
* <Animated.View
* style={[
* {
* backgroundColor: colors.bodyFrontBg,
* 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
* }
* ]}
* onLayout={event => {
* const {height} = event.nativeEvent.layout;
* typeof setHeaderHeight === "function" && setHeaderHeight(height);
* }}
* >
* <Animated.View
* style={{
* flex: 1,
* paddingHorizontal: 20
* }}
* >
* <Animated.Text
* style={[
* global.courseHeaderTitle,
* {marginBottom: 5}
* ]}
* >
* {topic.title}
* </Animated.Text>
*
* <View style={global.row}>
* <Text style={[global.courseHeaderSubTitle, {color: "red"}]}>
* {t("lessonTopic:lessoncount", {
* lesson: labels.lesson,
* current: lessonOrder + 1
* })}
* </Text>
* <View
* style={{
* width: 3,
* height: 3,
* marginTop: 2,
* marginLeft: 5,
* marginRight: 4,
* backgroundColor: "#8D8F97",
* borderRadius: 2,
* opacity: 0.45
* }}
* />
* <Text style={[global.courseHeaderSubTitle, {color: "blue"}]}>
* {t("lessonTopic:count", {
* topic: labels.topic,
* current: topic.order
* })}
* </Text>
* </View>
* </Animated.View>
* </View>
* </Animated.View>
* );
* };
*
* export default TopicTitle;
*
*
* //In custom_code/index.js...
*
* ...
*
* import TopicTitle from "./components/TopicTitle";
* export const applyCustomCode = externalCodeSetup => {
* externalCodeSetup.learnTopicSingleScreenApi.setLearnTopicTitleComponent(props => <TopicTitle {...props} />)
* }
*/
setLearnTopicTitleComponent = (
LearnTopicTitleComponent: React.ComponentType<LearnTopicHeaderProps> | null
) => {
this.LearnTopicTitleComponent = LearnTopicTitleComponent;
};
LearnTopicScreenHeader: React.ComponentType<
LearnTopicScreenHeaderProps
> | null = null;
/**
* You can use this hook to customize the header of the Learn Topic Single Screen which by default, contains the back-to-course button and the previous/next buttons.
* @method
* @param {React.ComponentType<LearnTopicScreenHeaderProps>} LearnTopicScreenHeader
* @example
*
* //In custom_code/components/LearnTopicHeader.js...
*
* import React from "react";
* import {View, Text} 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,
* topic
* }) => {
* 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%",
*
* backgroundColor: "cyan",
* borderRadius: 20
* }
* ]}
* >
* <View style={[global.headerButtonLeft, headerLeftStyle]}>
* {backToCourse}
* </View>
*
* <View>
* <Text>
* {topic.title}
* </Text>
* </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 LearnTopicHeader from "./components/LearnTopicHeader"
* export const applyCustomCode = externalCodeSetup => {
* externalCodeSetup.learnTopicSingleScreenApi.setLearnTopicScreenHeader(props => <LearnTopicHeader {...props} />)
* }
*/
setLearnTopicScreenHeader = (
LearnTopicScreenHeader: React.ComponentType<
LearnTopicScreenHeaderProps
> | null
) => {
this.LearnTopicScreenHeader = LearnTopicScreenHeader;
};
VideoProgressionComponent: React.ComponentType<
LearnTopicVideoProgressionComponentProps
> | null = null;
/**
* You can use this hook to customize the Video Progression component in the single topic 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 topic
* @method
* @param {React.ComponentType<LearnTopicVideoProgressionComponentProps>} 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.learnTopicSingleScreenApi.setVideoProgressionComponent(props => {
* const {
* topicVideoStyle,
* controls,
* autoPlay,
* videoCallback,
* url,
* width,
* height,
* global,
* isNavActive,
* topic,
* videoWatched,
* setVideoWatched,
* onCompleteTopicClick
* } = 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 topic as complete?",
* [
* {
* text: "Cancel",
* onPress: () => console.log("Cancel Pressed"),
* style: "cancel"
* },
* { text: "OK", onPress: () => onCompleteTopicClick() }
* ]
* );
* }
*
* }
*
* return <View style={topicVideoStyle}>
* <AppVideo
* controls={controls}
* autoPlay={autoPlay}
* // videoCallback={videoCallback()}
* videoCallback={customCallback(topic.settings)}
* url={url}
* width={width}
* height={height}
* global={global}
* isNavActive={isNavActive}
* />
* </View>
* })
* }
*
*/
setVideoProgressionComponent = (
VideoProgressionComponent: React.ComponentType<
LearnTopicVideoProgressionComponentProps
> | null
) => {
this.VideoProgressionComponent = VideoProgressionComponent;
};
AfterMaterialsComponent: React.ComponentType<
LearnTopicAfterMaterialsComponentProps
> | null = null;
/**
* You can use this hook to add a component at the bottom of the topic single screen just after the component that displays the materials.
* @method
* @param {React.ComponentType<LearnTopicAfterMaterialsComponentProps>} AfterMaterialsComponent
* @example
*
* //In custom_code/components/TopicBottomComponent.js...
*
* import React from "react";
* import { View, Text, TouchableOpacity } from "react-native";
*
* const TopicBottomComponent = props => {
*
* const {
* colors,
* course,
* materials,
* 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 TopicBottomComponent;
*
* //In custom_code/index.js...
*
* ...
*
* import TopicBottomComponent from "./components/TopicBottomComponent";
* export const applyCustomCode = externalCodeSetup => {
* externalCodeSetup.learnTopicSingleScreenApi.setAfterMaterialsComponent(props => <TopicBottomComponent {...props}/>)
* }
*/
setAfterMaterialsComponent = (
AfterMaterialsComponent: React.ComponentType<
LearnTopicAfterMaterialsComponentProps
> | null
) => {
this.AfterMaterialsComponent = AfterMaterialsComponent;
};
LearnTopicActionComponent: React.ComponentType<
LearnTopicActionComponentProps
> | 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<LearnTopicActionComponentProps>} LearnTopicActionComponent
* @example
*
* //In custom_code/components/LearnTopicActionComponent.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 LearnTopicActionComponent = ({
* showComplete,
* global,
* colors,
* t,
* topicVM,
* onCompleteTopicClick,
* completing,
* completeDisabled
* }) => (
* <AuthWrapper actionOnGuestLogin={"hide"}>
* {showComplete && (
* <View
* style={[
* global.row,
* {
* backgroundColor: colors.bodyFrontBg,
* borderTopColor: colors.borderColor
* },
* global.learnTopicActionButtonContainer
* ]}
* >
* <AppTouchableOpacity
* style={[
* {flex: 1},
* {
* opacity: !topicVM.completed && completeDisabled ? 0.5 : 1,
* backgroundColor: !topicVM.completed
* ? colors.primaryButtonBg
* : colors.bodyFrontBg
* },
* global.completeTopicButtonW
* ]}
* disabled={topicVM.completed || completeDisabled}
* onPress={onCompleteTopicClick}
* >
* <View style={global.row}>
* <View style={global.linkWithArrow}>
* {!topicVM.completed ? (
* completing && (
* <ActivityIndicator
* animating={true}
* color={colors.primaryButtonColor}
* size="small"
* style={global.learnTopicButtonLoadingIcon}
* />
* )
* ) : (
* <Icon
* webIcon={""}
* icon={{fontIconName: "check", weight: 200}}
* styles={global.learnTopicActionCompleteIcon}
* />
* )}
* <Text
* style={[
* {
* marginLeft: 10,
* color: !topicVM.completed
* ? colors.primaryButtonColor
* : isColorDark(colors.bodyFrontBg)
* ? "white"
* : "black"
* },
* global.completeTopicButton
* ]}
* >
* {t(
* topicVM.completed
* ? "lessonTopic:completed"
* : "lessonTopic:markAsComplete"
* )}
* </Text>
* </View>
* </View>
* </AppTouchableOpacity>
* </View>
* )}
* </AuthWrapper>
* );
*
* export default LearnTopicActionComponent;
*
* //In custom_code/index.js...
*
* ...
*
* import LearnTopicActionComponent from "./components/LearnTopicActionComponent";
* export const applyCustomCode = (externalCodeSetup: any) => {
* externalCodeSetup.learnTopicSingleScreenApi.setLearnTopicActionComponent(props => <LearnTopicActionComponent {...props} />)
* }
*/
setLearnTopicActionComponent = (
LearnTopicActionComponent: React.ComponentType<
LearnTopicActionComponentProps
> | null
) => {
this.LearnTopicActionComponent = LearnTopicActionComponent;
};
OfflineComponent: React.ComponentType<
LearnTopicOfflineComponentProps
> | 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 topic content while the device is offline.
* @method
* @param {React.ComponentType<LearnTopicOfflineComponentProps>} OfflineComponent
* @example
*
* ...
*
* import EmptyList from "@src/components/EmptyList";
*
* export const applyCustomCode = (externalCodeSetup) => {
* externalCodeSetup.learnTopicSingleScreenApi.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<
LearnTopicOfflineComponentProps
> | null
) => {
this.OfflineComponent = OfflineComponent;
};
WebViewContentComponent: React.ComponentType<
LearnTopicWebViewContentComponentProps
> | null = null;
/**
* You can use this hook to replace the webview being used in the topic content.
* For example, you can choose to replace it with the default react-native webview.
* @method
* @param {React.ComponentType<LearnTopicWebViewContentComponentProps>} WebViewContentComponent
* @example
*
* ...
*
* import WebViewWithMore from "@src/components/WebViewWithMore";
* export const applyCustomCode = (externalCodeSetup) => {
* externalCodeSetup.learnTopicSingleScreenApi.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<
LearnTopicWebViewContentComponentProps
> | null
) => {
this.WebViewContentComponent = WebViewContentComponent;
};
LearnTopicMaterialsSectionTitle: React.ComponentType<
LearnTopicMaterialsSectionTitleProps
> | null = null;
/**
* You can use this hook to customize the component that displays the "Materials" text.
* @method
* @param {React.ComponentType<LearnTopicMaterialsSectionTitleProps>} LearnTopicMaterialsSectionTitle
* @example
*
* ...
*
* export const applyCustomCode = (externalCodeSetup) => {
* externalCodeSetup.learnTopicSingleScreenApi.setLearnTopicMaterialsSectionTitle(
* ({global, t}) => (
* <Text
* style={{
* ...global.courseRoundBoxTitleAbove,
* marginBottom: 20
* }}
* >
* {t("lesson:materials")}
* </Text>
* )
* );
* }
*/
setLearnTopicMaterialsSectionTitle = (
LearnTopicMaterialsSectionTitle: React.ComponentType<
LearnTopicMaterialsSectionTitleProps
> | null
) => {
this.LearnTopicMaterialsSectionTitle = LearnTopicMaterialsSectionTitle;
};
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.learnTopicSingleScreenApi.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.learnTopicSingleScreenApi.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.learnTopicSingleScreenApi.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.learnTopicSingleScreenApi.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.learnTopicSingleScreenApi.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.learnTopicSingleScreenApi.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.learnTopicSingleScreenApi.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 topic.
* @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.learnTopicSingleScreenApi.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;
};
learnTopicViewModelFilter = (
viewModel: TLearnTopicViewModel | Record<any, any>
) => viewModel;
/**
* Sets the callback function that can change an existing learn topic view model object.
* @method
* @param {TransformLearnTopicViewModelCallback} learnTopicViewModelFilter
* @example <caption>Remove the native blocks in a lesson topic</caption>
* externalCodeSetup.learnTopicSingleScreenApi.setLearnTopicViewModelFilter((viewModel, topic) => {
* return {
* ...viewModel,
* contentNative: []
* }
* })
*/
setLearnTopicViewModelFilter = (
learnTopicViewModelFilter: (
viewModel: TLearnTopicViewModel | Record<any, any>
) => TLearnTopicViewModel | Record<any, any>
) => {
this.learnTopicViewModelFilter = learnTopicViewModelFilter;
};
}
Source