Class

LessonSingleScreenHooksApi

LessonSingleScreenHooksApi()

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.

Constructor

# new LessonSingleScreenHooksApi()

Example
externalCodeSetup.lessonSingleScreenApi.METHOD_NAME

Members

# setTopicNavigationFilter

Deprecated:
  • Yes

# topicNavigationFilter

Deprecated:
  • Filters navigation onPress function that is used to navigate to Topic

Methods

# setAfterMaterialsComponent(AfterMaterialsComponent)

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.

Parameters:
Name Type Description
AfterMaterialsComponent React.ComponentType.<AfterMaterialsComponentProps>
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}/>)
}

# setLessonScreenHeader(LessonScreenHeader)

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.

Parameters:
Name Type Description
LessonScreenHeader React.ComponentType.<LessonScreenHeaderProps>
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}/>)
}

# setLessonTitleComponent(LessonTitleComponent)

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.

Parameters:
Name Type Description
LessonTitleComponent React.ComponentType.<LessonTitleComponentProps>
Examples

Change component's background and add ellipsis to text

//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} />)
}

Add screen header components to lesson title

// 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={require("@src/assets/img/stopwatch.png")}
        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} />)
}

# setPrevNextComponent(PrevNextComponentnullable)

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.

Parameters:
Name Type Attributes Description
PrevNextComponent React.ComponentType.<PrevNextComponentProps> <nullable>
Examples

Hide the previous and next buttons if you're only using one lesson in a course

//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} />)
}

Hide previous and next buttons

...

export const applyCustomCode = externalCodeSetup => {
 externalCodeSetup.lessonSingleScreenApi.setPrevNextComponent(() => null)
}

# setPrevNextPlaceholder(PrevNextPlaceholdernullable)

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.

Parameters:
Name Type Attributes Description
PrevNextPlaceholder React.ComponentType.<PrevNextPlaceholderProps> <nullable>
Examples

Change placeholder color

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"}
       ]}
     />
   </>
})

Hide the placeholder even while the screen is still loading

externalCodeSetup.lessonSingleScreenApi.setPrevNextPlaceholder(() => null)

# setTransformLessonActionButtons(transformLessonActionButtons)

You can transform the default lesson action button by replacing it with your preferred action buttons.

Parameters:
Name Type Description
transformLessonActionButtons TransformLessonActionButtonsCallback
Example

Add more components for lesson action

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

# setVideoProgressionComponent(VideoProgressionComponent)

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.

Parameters:
Name Type Description
VideoProgressionComponent React.ComponentType.<VideoProgressionComponentProps>
Example

Execute a custom callback when video has finished playing

...
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>
  })
}