import React from "react";
import {
Course,
NavigationService,
TQuizViewModel,
TTranslationFunction
} from "./types";
import {NavigationProp} from "@react-navigation/native";
export const API_NAME = "quizApi";
/**
* QuestionClosedRenderMode
*/
type QuestionClosedRenderMode = "webview" | "htmlparser";
/**
* OverrideQuestionHTMLWrapperCallback
*/
type OverrideQuestionHTMLWrapperCallback = {
/**
* Default HTML wrapper
*/
HTML: string,
/**
* HTML that contains the input element
*/
inputHTML: string,
/**
* CSS passed to webview by default
*/
css: string
};
/**
* QuizPrevNextComponentProps
*/
type QuizPrevNextComponentProps = {
/**
* 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,
/**
* Props which can be passed to an AuthWrapper
*/
headerRightAuthWrapperProps: Record<any, any>
};
/**
* QuizTitleComponentProps
*/
type QuizTitleComponentProps = {
quiz: TQuizViewModel,
currentSwiperPosition: number,
/**
* App global style
*/
global: Record<any, any>,
/**
* Learndash labels
*/
labels: Record<any, any>,
/**
* Current questions in the quiz
*/
questions: Record<any, any>[],
quizOrder: number,
quizTotalCount: number,
/**
* App colors
*/
colors: Record<any, any>,
/**
* Helper function which can be called to set header height
*/
setHeaderHeight: Function,
/**
* Returns `false` if quiz doesn't have a timer set. Will return a component if timer for the quiz is set.
*/
renderQuizTimer: boolean | React.ComponentType,
t: TTranslationFunction,
navigation: NavigationService,
/**
* 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,
/**
* Course id of lesson/topic/quiz
*/
courseId: number,
/**
* Data about previous lesson/topic/quiz
*/
prevObject: Record<any, any>,
/**
* Data about next lesson/topic/quiz
*/
nextObject: Record<any, any>,
course: Course,
/**
* Shows an alert with information that next object is locked
*/
nextLockedAlert: Function,
/**
* Returns `true` if screen is currently showing the results of the quiz
*/
isResultsVisible: boolean,
/**
* Returns default back button component
*/
backToCourse: React.ComponentType,
/**
* Returns `true` if question numbering should be hidden
*/
hideQuestionNumbering: boolean,
/**
* 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
};
/**
* QuizScreenHeaderProps
*/
type QuizScreenHeaderProps = {
quiz: TQuizViewModel,
currentSwiperPosition: number,
/**
* App global style
*/
global: Record<any, any>,
/**
* Learndash labels
*/
labels: Record<any, any>,
/**
* Current questions in the quiz
*/
questions: Record<any, any>[],
quizOrder: number,
quizTotalCount: number,
/**
* App colors
*/
colors: Record<any, any>,
/**
* Helper function which can be called to set header height
*/
setHeaderHeight: Function,
/**
* Returns `false` if quiz doesn't have a timer set. Will return a component if timer for the quiz is set.
*/
renderQuizTimer: boolean | React.ComponentType,
t: TTranslationFunction,
navigation: NavigationService,
/**
* 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,
/**
* Course id of lesson/topic/quiz
*/
courseId: number,
/**
* Data about previous lesson/topic/quiz
*/
prevObject: Record<any, any>,
/**
* Data about next lesson/topic/quiz
*/
nextObject: Record<any, any>,
course: Course,
/**
* Shows an alert with information that next object is locked
*/
nextLockedAlert: Function,
/**
* Returns `true` if screen is currently showing the results of the quiz
*/
isResultsVisible: boolean,
/**
* Returns default back button component
*/
backToCourse: React.ComponentType,
/**
* Returns `true` if question numbering should be hidden
*/
hideQuestionNumbering: boolean,
/**
* 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,
/**
* Default styling for left section of the header
*/
headerLeftStyle: Record<any, any>,
/**
* Default styling of lesson header
*/
style: Record<any, any>
};
/**
* QuizMaterialsComponentProps
*/
type QuizMaterialsComponentProps = {
/**
* 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
};
/**
* QuizStartButtonProps
*/
type QuizStartButtonProps = {
/**
* Returns `true` if quiz start button should be visible.
*/
showStart: boolean,
/**
* App global style
*/
global: Record<any, any>,
/**
* Default styles for the button.
*/
styles: Record<any, any>,
quiz: TQuizViewModel,
/**
* Returns `true` if quiz is currently loading.
*/
quizStartLoading: boolean,
/**
* Checks form and sets state as invalid if applicable.
*/
checkForm: Function,
/**
* Starts the quiz.
*/
startQuiz: Function,
t: TTranslationFunction,
/**
* Learndash labels
*/
labels: Record<any, any>,
/**
* Returns `true` if quiz can be resumed.
*/
isResumeQuiz: boolean | null
};
/**
* QWebViewContentComponentProps
*/
type QWebViewContentComponentProps = {
/**
* 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
};
/**
* QuizOfflineComponentProps
*/
type QuizOfflineComponentProps = {
/**
* App global style
*/
global: Record<any, any>,
t: TTranslationFunction,
/**
* Default wrapper style
*/
wrapperCompsStyle: Record<any, any>,
/**
* Renders the navigation component
*/
renderNav: Function,
/**
* Default styles for the offline component
*/
styles: Record<any, any>
};
/**
* QuizTimerProps
*/
type QuizTimerProps = {
/**
* Returns `true` if timer should be visible
*/
showTimer: boolean,
item: TQuizViewModel,
/**
* App global style
*/
global: Record<any, any>,
/**
* App colors
*/
colors: Record<any, any>,
styles: Record<any, any>,
timerRef: Record<any, any>,
/**
* Updates the timer value
*/
onTimePassed: Function,
/**
* Submits the quiz
*/
onTimeOver: Function
};
/**
* QuestionOverviewButtonsProps
*/
type QuestionOverviewButtonsProps = {
style: Record<any, any>,
/**
* App global style
*/
global: Record<any, any>,
t: TTranslationFunction,
/**
* Learndash labels
*/
labels: Record<any, any>,
/**
* Marks a question for review
*/
onReviewPress: Function,
/**
* Shows summary of the quiz
*/
onSummaryPress: Function,
/**
* Returns `true` if the summary button should be disabled
*/
disableSummaryButton: boolean
};
/**
* @class
* Quiz Hooks.
* Instance name: quizApi
You can use these hooks to customize the quiz questions for your app.
* @example
* externalCodeSetup.quizApi.METHOD_NAME
*/
export class QuizApi {
questionClosedRenderMode: "webview" | "htmlparser" = "htmlparser";
/**
* It overrides the Closed Question type render mode. The default mode is `htmlparser`. If the question is not rendering correctly, you can try setting it to `webview` mode.
* @method
* @param {QuestionClosedRenderMode} questionClosedRenderMode Available values: `webview` | `htmlparser`
* @example
* externalCodeSetup.quizApi.setQuestionClosedRenderMode("webview")
*/
setQuestionClosedRenderMode = (
questionClosedRenderMode: "webview" | "htmlparser"
) => {
this.questionClosedRenderMode = questionClosedRenderMode;
};
wrapQuestionHtmlFilter: (
HTML: string,
inputHTML: string,
css: string
) => string = (HTML, inputHTML, css) => HTML;
/**
* We use an HTML wrapper for "Fill in the blank" questions to accept input answers.
* You can use this to change the HTML output.
* @method
* @param {OverrideQuestionHTMLWrapperCallback} wrapQuestionHtmlFilter
* @example <caption>Add additional details below the input field</caption>
* externalCodeSetup.quizApi.setWrapQuestionHtmlFilter((HTMLWrapper, inputHtml, css) => {
*
* const disableZoom = true;
* const myNewHtml =
* `
* <!DOCTYPE html>
* <html>
* <head>
* <title>Topic Content</title>
* <meta http-equiv="content-type" content="text/html; charset=utf-8">
* <meta name="viewport" content="width=device-width, initial-scale=1 ${disableZoom ? "maximum-scale=1.0" : ""} ">
* <style type="text/css">
* ${css}
* .content {
* width: 100%;
* overflow: hidden;
* padding-bottom: 4px;
* }
* </style>
* </head>
* <body>
* <div class="content">
* ` +
* inputHtml +
* `
* <p> Please use UPPERCASE characters only</p>
* </div>
* </body>
* </html>
* `;
* return myNewHtml;
* })
*/
setWrapQuestionHtmlFilter = (
wrapQuestionHtmlFilter: (
HTML: string,
inputHTML: string,
css: string
) => string
) => {
this.wrapQuestionHtmlFilter = wrapQuestionHtmlFilter;
};
PrevNextComponent: React.ComponentType<
QuizPrevNextComponentProps
> | null = null;
/**
* You can use this to replace the previous and next buttons on the quiz screen.
* @method
* @param {React.ComponentType<QuizPrevNextComponentProps>} PrevNextComponent
* @example <caption> Change colors of 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
* }) => {
*
* return (
* <View style={[global.row]}>
* <AppTouchableOpacity
* style={[
* global.wrappedButton,
* global.wrappedTextButton,
* { marginRight: 4, backgroundColor: "purple" }
* ]}
* 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)
* : "red"
* }
* ]}
* >
* {t("lesson:prevButtonText")}
* </Text>
* </View>
* </View>
* </AppTouchableOpacity>
*
* <AppTouchableOpacity
* style={[global.wrappedButton, global.wrappedTextButton, {backgroundColor: "purple"}]}
* 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)
* : "blue"
* }
* ]}
* >
* {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.quizApi.setPrevNextComponent((props) => <PrevNextComponent {...props} />);
* }
*
*/
setPrevNextComponent = (
PrevNextComponent: React.ComponentType<QuizPrevNextComponentProps> | null
) => {
this.PrevNextComponent = PrevNextComponent;
};
QuizTitleComponent: React.ComponentType<
QuizTitleComponentProps
> | null = null;
/**
* You can use this to replace the quiz's title component.
* For example, you can use this to add more details to the quiz's title.
* @method
* @param {React.ComponentType<QuizTitleComponentProps>} QuizTitleComponent
* @example <caption> Add more quiz details to component </caption>
*
* //In custom_code/components/QuizTitle.js...
*
* import React from "react";
* import {View, Text} from "react-native";
* import Animated from "react-native-reanimated";
* const QuizTitle = ({
* quiz,
* global,
* colors,
* paddingTop = 14,
* setHeaderHeight,
* t,
* labels,
* questions,
* currentSwiperPosition,
* quizOrder,
* quizTotalCount
* }) => {
*
* 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}
* ]}
* >
* {quiz.title}
* </Animated.Text>
*
* {
* !quiz.hideQuestionPositionOverview &&
* !quiz.hideQuestionNumbering &&
* currentSwiperPosition > 0 ? (
* <Text style={global.courseHeaderSubTitle}>
* {t("quiz:questionCount", {
* question: labels.question,
* current: currentSwiperPosition,
* total: questions
* ? questions.size
* : ""
* })}
* </Text>
* ) : (
* <Text style={global.courseHeaderSubTitle}>
* {`Quiz ${quizOrder + 1} of ${quizTotalCount}`}
* </Text>
* )
* }
*
* <Text style={global.courseHeaderSubTitle}>
* Author: {quiz.author.name}
* </Text>
* <Text style={global.courseHeaderSubTitle}>
* Completed: {quiz.completed.toString()}
* </Text>
*
* </Animated.View>
* </View>
* </Animated.View>
* );
* };
*
* export default QuizTitle;
*
* //In custom_code/index.js...
*
* ...
* import QuizTitle from "./components/QuizTitle";
* export const applyCustomCode = externalCodeSetup => {
* externalCodeSetup.quizApi.setQuizTitleComponent(props => <QuizTitle {...props} />)
* }
*
*/
setQuizTitleComponent = (
QuizTitleComponent: React.ComponentType<QuizTitleComponentProps> | null
) => {
this.QuizTitleComponent = QuizTitleComponent;
};
QuizScreenHeader: React.ComponentType<QuizScreenHeaderProps> | null = null;
/**
* You can use this hook to customize the header of the Quiz Single Screen which by default, contains the back-to-course button and the previous/next buttons.
* @method
* @param {React.ComponentType<QuizScreenHeaderProps>} QuizScreenHeader
* @example <caption> Add a timer on the quiz screen header </caption>
*
* //In custom_code/components/QuizScreenHeader.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,
* colors,
* backToCourse,
* headerRightAuthWrapperProps,
* prevNext,
* quiz,
* renderQuizTimer
* }) => {
* 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: "gray",
* borderRadius: 20
* }
* ]}
* >
* <View style={[global.headerButtonLeft, headerLeftStyle]}>
* {backToCourse}
* </View>
*
* <View style={[global.headerCustomTitle]}>
* {renderQuizTimer(quiz, global, colors)}
* </View>
*
* <View style={[global.headerButtonRight]}>
* <AuthWrapper
* actionOnGuestLogin={"hide"}
* {...headerRightAuthWrapperProps}
* >
* {prevNext}
* </AuthWrapper>
* </View>
* </View>
* </Animated.View>
* );
* };
*
* export default Header;
*
* //In custom_code/index.js...
*
* import QuizScreenHeader from "./components/QuizScreenHeader";
* export const applyCustomCode = externalCodeSetup => {
* externalCodeSetup.quizApi.setQuizScreenHeader(props => <QuizScreenHeader {...props} />)
* }
*
*/
setQuizScreenHeader = (
QuizScreenHeader: React.ComponentType<QuizScreenHeaderProps> | null
) => {
this.QuizScreenHeader = QuizScreenHeader;
};
MaterialsComponent: React.ComponentType<
QuizMaterialsComponentProps
> | null = null;
/**
* You can use this to customize the component that displays the materials of the lesson.
* @method
* @param {React.ComponentType<QuizMaterialsComponentProps>} 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.quizApi.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<QuizMaterialsComponentProps> | null
) => {
this.MaterialsComponent = MaterialsComponent;
};
QuizStartButton: React.ComponentType<QuizStartButtonProps> | null = null;
/**
* You can use this to customize the "Start Quiz" button that appears when opening the QuizSingleScreen.
* @method
* @param {React.ComponentType<QuizStartButtonProps>} QuizStartButton
* @example
*
* import AppButton from "@src/components/AppButton";
*
* export const applyCustomCode = (externalCodeSetup) => {
* externalCodeSetup.quizApi.setQuizStartButton(props => {
* const {
* showStart,
* styles,
* global,
* quiz,
* checkForm,
* startQuiz,
* quizStartLoading,
* isResumeQuiz,
* t,
* labels
* } = props;
*
* return showStart ? (
* <View
* style={[
* styles.buttonWrap,
* {paddingBottom: styles.containerPadding},
* global.quizStartButtonContainer
* ]}
* >
* <AppButton
* style={[
* styles.button,
* {
* backgroundColor: styles.buttonBackground
* },
* global.quizStartButton
* ]}
* onPress={() => {
* if (quiz.formActivated && !checkForm(quiz)) {
* return false;
* } else if (!quizStartLoading) {
* startQuiz(quiz);
* }
* }}
* label={t(isResumeQuiz ? "quiz:continue" : "quiz:start", {
* quiz: labels.quiz
* })}
* labelStyle={global.quizStartButtonLabel}
* global={global}
* loading={quizStartLoading}
* loadingStyle={global.quizStartButtonLoading}
* />
* </View>
* ) : (
* <></>
* );
*
* });
* }
*/
setQuizStartButton = (
QuizStartButton: React.ComponentType<QuizStartButtonProps> | null
) => {
this.QuizStartButton = QuizStartButton;
};
WebViewContentComponent: React.ComponentType<
QWebViewContentComponentProps
> | null = null;
/**
* You can use this hook to replace the webview being used in the quiz content.
* For example, you can choose to replace it with the default react-native webview.
* @method
* @param {React.ComponentType<QWebViewContentComponentProps>} WebViewContentComponent
* @example
*
* ...
*
* import WebViewWithMore from "@src/components/WebViewWithMore";
* export const applyCustomCode = (externalCodeSetup) => {
* externalCodeSetup.quizApi.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<
QWebViewContentComponentProps
> | null
) => {
this.WebViewContentComponent = WebViewContentComponent;
};
OfflineComponent: React.ComponentType<
QuizOfflineComponentProps
> | null = null;
/**
* You can use this hook to customize the component that displays a "Come back later. Quizzes are not available offline" message.
* The component is visible when attempting to start a quiz while the device is offline.
* @method
* @param {React.ComponentType<QuizOfflineComponentProps>} OfflineComponent
* @example
*
* ...
*
* import Icon from "@src/components/Icon";
*
* export const applyCustomCode = (externalCodeSetup) => {
* externalCodeSetup.quizApi.setOfflineComponent(
* ({global, t, wrapperCompsStyle, renderNav, styles}) => (
* <View style={[wrapperCompsStyle, styles.wrapper]} key={"intro"}>
* {renderNav()}
* <View style={styles.container}>
* <Icon
* tintColor={"#DCDDDF"}
* icon={{fontIconName: "wifi-slash", weight: 400}}
* styles={global.emptyIcon}
* />
* <Text style={[global.emptyTitle, styles.title]}>
* {t("quiz:offlineAlertTitle")}
* </Text>
* <Text style={[global.emptyDesc, styles.message]}>
* {t("quiz:offlineAlertMessage")}
* </Text>
* </View>
* </View>
* )
* );
* }
*/
setOfflineComponent = (
OfflineComponent: React.ComponentType<QuizOfflineComponentProps> | null
) => {
this.OfflineComponent = OfflineComponent;
};
QuizTimer: React.ComponentType<QuizTimerProps> | null = null;
/**
* You can use this hook to customize the QuizTimer component.
* @method
* @param {React.ComponentType<QuizTimerProps>} QuizTimer
* @example
*
* ...
*
* import Icon from "@src/components/Icon";
* import TimeCountDown from "@src/components/TimerCountDown";
*
* export const applyCustomCode = (externalCodeSetup: ExternalCodeSetup) => {
* externalCodeSetup.quizApi.setQuizTimer(
* ({
* showTimer,
* item,
* global,
* colors,
* styles,
* timerRef,
* onTimePassed,
* onTimeOver
* }) =>
* showTimer ? (
* <View style={styles.container}>
* <Icon
* icon={{fontIconName: "stopwatch", weight: 400}}
* webIcon={"IconArrowBack"}
* tintColor={colors.textIconColor}
* styles={styles.icon}
* />
* <TimeCountDown
* ref={timerRef}
* paused={false}
* onTimePassed={onTimePassed}
* onTimeOver={onTimeOver}
* secondsLimit={item.timeLimit}
* textProps={{style: global.timer}}
* />
* <Text>The timer</Text>
* </View>
* ) : (
* <></>
* )
* );
* }
*/
setQuizTimer = (QuizTimer: React.ComponentType<QuizTimerProps> | null) => {
this.QuizTimer = QuizTimer;
};
QuestionOverviewButtons: React.ComponentType<
QuestionOverviewButtonsProps
> | null = null;
/**
* You can use this hook to customize the "Review Question" and "Quiz summary" buttons in the QuizSingleScreen.
* @method
* @param {QuestionOverviewButtonsProps} QuestionOverviewButtons
* @example
*
* ...
*
* import QuestionOverviewButtons from "@src/components/QuestionOverview/QuestionOverviewButtons";
*
* export const applyCustomCode = (externalCodeSetup) => {
* externalCodeSetup.questionApiHooks.setQuestionOverviewButtons(
* ({
* style,
* global,
* t,
* labels,
* onReviewPress,
* onSummaryPress,
* disableSummaryButton
* }) => (
* <QuestionOverviewButtons
* style={style}
* global={global}
* reviewQuestionLabel={t("quiz:reviewQuestionLabel", {
* question: labels.question
* })}
* summaryQuestionLabel={t("quiz:quizSummaryLabel", {
* quiz: labels.quiz
* })}
* onReviewPress={onReviewPress}
* onSummaryPress={onSummaryPress}
* disableSummaryButton={disableSummaryButton}
* />
* )
* );
* }
*/
setQuestionOverviewButtons = (
QuestionOverviewButtons: React.ComponentType<
QuestionOverviewButtonsProps
> | null
) => {
this.QuestionOverviewButtons = QuestionOverviewButtons;
};
}
Source