Source

externalCode/learnTopicSingleScreen.ts

  1. import * as React from "react";
  2. import {
  3. Course,
  4. Lesson,
  5. LearnTopic,
  6. TLearnTopicViewModel,
  7. TTranslationFunction
  8. } from "./types";
  9. import {NavigationService} from "./types";
  10. export const API_NAME = "learnTopicSingleScreenApi";
  11. /**
  12. * LearnTopicAfterContentRendererProps
  13. */
  14. type LearnTopicAfterContentRendererProps = {
  15. topic: LearnTopic,
  16. /**
  17. * App global style
  18. */
  19. global: Record<any, any>,
  20. /**
  21. * App colors
  22. */
  23. colors: Record<any, any>,
  24. navigation: NavigationService
  25. };
  26. /**
  27. * TransformTopicActionButtonsCallback
  28. */
  29. type TransformTopicActionButtonsCallback = {
  30. /**
  31. * Topic action button
  32. */
  33. TopicButton: JSX.Element,
  34. /**
  35. * Returns `true` if "Mark Complete" button should be shown
  36. */
  37. showComplete: boolean,
  38. /**
  39. * App global style
  40. */
  41. global: Record<any, any>,
  42. /**
  43. * App colors
  44. */
  45. colors: Record<any, any>,
  46. topic: TLearnTopicViewModel,
  47. /**
  48. * Returns `true` if topic is being completed
  49. */
  50. completing: boolean,
  51. /**
  52. * Learndash labels
  53. */
  54. labels: Record<any, any>,
  55. /**
  56. * Marks the topic as complete
  57. */
  58. handleComplete: Function
  59. };
  60. /**
  61. * showMarkAsCompleteProps
  62. */
  63. type showMarkAsCompleteProps = {
  64. topic: LearnTopic
  65. };
  66. /**
  67. * LearnTopicPrevNextComponentProps
  68. */
  69. type LearnTopicPrevNextComponentProps = {
  70. /**
  71. * Function to execute if previous or next button is a quiz
  72. */
  73. onQuizClick: Function,
  74. /**
  75. * Function to execute if previous or next button is a lesson
  76. */
  77. onLessonClick: Function,
  78. /**
  79. * Function to execute if previous or next button is a topic
  80. */
  81. onTopicClick: Function,
  82. /**
  83. * App global style
  84. */
  85. global: Record<any, any>,
  86. /**
  87. * App colors
  88. */
  89. colors: Record<any, any>,
  90. t: TTranslationFunction,
  91. /**
  92. * Data about previous lesson/topic/quiz
  93. */
  94. prevObject: Record<any, any>,
  95. /**
  96. * Data about next lesson/topic/quiz
  97. */
  98. nextObject: Record<any, any>,
  99. /**
  100. * Course id of lesson/topic/quiz
  101. */
  102. courseId: number,
  103. /**
  104. * Shows an alert with information that next object is locked
  105. */
  106. nextLockedAlert: Function
  107. };
  108. /**
  109. * LearnTopicHeaderProps
  110. */
  111. type LearnTopicHeaderProps = {
  112. topic: TLearnTopicViewModel,
  113. lessonOrder: number,
  114. paddingTop: number,
  115. setHeaderHeight: Function,
  116. /**
  117. * App global style
  118. */
  119. global: Record<any, any>,
  120. /**
  121. * App colors
  122. */
  123. colors: Record<any, any>,
  124. /**
  125. * Learndash labels
  126. */
  127. labels: Record<any, any>,
  128. /**
  129. * Function to execute if previous or next button is a quiz
  130. */
  131. onQuizClick: Function,
  132. /**
  133. * Function to execute if previous or next button is a lesson
  134. */
  135. onLessonClick: Function,
  136. /**
  137. * Function to execute if previous or next button is a topic
  138. */
  139. onTopicClick: Function,
  140. /**
  141. * Data about previous lesson/topic/quiz
  142. */
  143. prevObject: Record<any, any>,
  144. /**
  145. * Data about next lesson/topic/quiz
  146. */
  147. nextObject: Record<any, any>,
  148. /**
  149. * Course id of lesson/topic/quiz
  150. */
  151. courseId: number,
  152. /**
  153. * Shows an alert with information that next object is locked
  154. */
  155. nextLockedAlert: Function,
  156. /**
  157. * Returns default back button component
  158. */
  159. backToCourse: React.ComponentType,
  160. course: Course,
  161. /**
  162. * Returns `true` if data is loading
  163. */
  164. loading: boolean,
  165. /**
  166. * Returns `false` if topic doesn't have a timer set. Returns a component if a timer for the topic is set.
  167. */
  168. renderTimer: boolean | React.ComponentType,
  169. /**
  170. * Function which updates the seconds passed in the topic screen container
  171. */
  172. onTimePassed: Function,
  173. navigation: NavigationService,
  174. /**
  175. * Returns `true` if prev/next buttons should be hidden
  176. */
  177. hidePrevNext: boolean,
  178. /**
  179. * Returns `false` if hidePrevNext is `true`. Returns buttons which can navigate through previous and next screens if hidePrevNext is `false`
  180. */
  181. prevNext: boolean | React.ComponentType
  182. };
  183. /**
  184. * LearnTopicScreenHeaderProps
  185. */
  186. type LearnTopicScreenHeaderProps = {
  187. /**
  188. * Default styling for left section of the header
  189. */
  190. headerLeftStyle: Record<any, any>,
  191. /**
  192. * Default styling of lesson header
  193. */
  194. style: Record<any, any>,
  195. /**
  196. * Props which can be passed to an AuthWrapper
  197. */
  198. headerRightAuthWrapperProps: Record<any, any>,
  199. topic: TLearnTopicViewModel,
  200. lessonOrder: number,
  201. paddingTop: number,
  202. setHeaderHeight: Function,
  203. /**
  204. * App global style
  205. */
  206. global: Record<any, any>,
  207. /**
  208. * App colors
  209. */
  210. colors: Record<any, any>,
  211. labels: Record<any, any>,
  212. /**
  213. * Function to execute if previous or next button is a quiz
  214. */
  215. onQuizClick: Function,
  216. /**
  217. * Function to execute if previous or next button is a lesson
  218. */
  219. onLessonClick: Function,
  220. /**
  221. * Function to execute if previous or next button is a topic
  222. */
  223. onTopicClick: Function,
  224. /**
  225. * Data about previous lesson/topic/quiz
  226. */
  227. prevObject: Record<any, any>,
  228. /**
  229. * Data about next lesson/topic/quiz
  230. */
  231. nextObject: Record<any, any>,
  232. /**
  233. * Course id of lesson/topic/quiz
  234. */
  235. courseId: number,
  236. /**
  237. * Shows an alert with information that next object is locked
  238. */
  239. nextLockedAlert: Function,
  240. /**
  241. * Returns default back button component
  242. */
  243. backToCourse: React.ComponentType,
  244. course: Course,
  245. /**
  246. * Returns `true` if data is loading
  247. */
  248. loading: boolean,
  249. /**
  250. * Returns `false` if topic doesn't have a timer set. Returns a component if a timer for the topic is set.
  251. */
  252. renderTimer: boolean | React.ComponentType,
  253. /**
  254. * Function which updates the seconds passed in the topic screen container
  255. */
  256. onTimePassed: Function,
  257. navigation: NavigationService,
  258. /**
  259. * Returns `true` if prev/next buttons should be hidden
  260. */
  261. hidePrevNext: boolean,
  262. /**
  263. * Returns `false` if hidePrevNext is `true`. Returns buttons which can navigate through previous and next screens if hidePrevNext is `false`
  264. */
  265. prevNext: boolean | React.ComponentType
  266. };
  267. /**
  268. * LearnTopicVideoProgressionComponentProps
  269. */
  270. type LearnTopicVideoProgressionComponentProps = {
  271. /**
  272. * Default styling applied to topic video
  273. */
  274. topicVideoStyle: Record<any, any>,
  275. /**
  276. * Returns `true` if controls should be displayed
  277. */
  278. controls: boolean,
  279. /**
  280. * Returns `true` if auto play should be enabled
  281. */
  282. autoPlay: boolean,
  283. /**
  284. * Helper function which can be called when the video has finished playing
  285. */
  286. videoCallback: Function,
  287. /**
  288. * Video url
  289. */
  290. url: string,
  291. /**
  292. * Player width
  293. */
  294. width: number,
  295. /**
  296. * Player height
  297. */
  298. height: number,
  299. /**
  300. * App global style
  301. */
  302. global: Record<any, any>,
  303. /**
  304. * Returns `true` if screen is active
  305. */
  306. isNavActive: boolean,
  307. topic: TLearnTopicViewModel,
  308. /**
  309. * Returns `true` if video should be shown
  310. */
  311. showVideo: boolean,
  312. /**
  313. * Returns `true` if video has already been watched
  314. */
  315. videoWatched: boolean,
  316. /**
  317. * Dispatches an action and marks the video as watched
  318. */
  319. setVideoWatched: Function,
  320. /**
  321. * Dispatches an action to mark the topic as complete
  322. */
  323. completeTopic: Function,
  324. /**
  325. * Function which considers different conditions (such as if quizzes inside a topic are already completed) before calling the `completeTopic` function
  326. */
  327. onCompleteTopicClick: Function
  328. };
  329. /**
  330. * LearnTopicAfterMaterialsComponentProps
  331. */
  332. type LearnTopicAfterMaterialsComponentProps = {
  333. topic: TLearnTopicViewModel,
  334. lessonOrder: number,
  335. /**
  336. * App global style
  337. */
  338. global: Record<any, any>,
  339. /**
  340. * App colors
  341. */
  342. colors: Record<any, any>,
  343. labels: Record<any, any>,
  344. lesson: Lesson,
  345. t: TTranslationFunction,
  346. /**
  347. * Function to execute if previous or next button is a quiz
  348. */
  349. onQuizClick: Function,
  350. /**
  351. * Function to execute if previous or next button is a lesson
  352. */
  353. onLessonClick: Function,
  354. /**
  355. * Function to execute if previous or next button is a topic
  356. */
  357. onTopicClick: Function,
  358. /**
  359. * Data about previous lesson/topic/quiz
  360. */
  361. prevObject: Record<any, any>,
  362. /**
  363. * Data about next lesson/topic/quiz
  364. */
  365. nextObject: Record<any, any>,
  366. /**
  367. * Shows an alert with information that next object is locked
  368. */
  369. nextLockedAlert: Function,
  370. course: Course,
  371. /**
  372. * Returns `true` if data is loading
  373. */
  374. loading: boolean,
  375. navigation: NavigationService,
  376. /**
  377. * Topic material
  378. */
  379. materials: string
  380. };
  381. /**
  382. * LearnTopicActionComponentProps
  383. */
  384. type LearnTopicActionComponentProps = {
  385. /**
  386. * Returns `true` if "Mark Complete" button should be shown
  387. */
  388. showComplete: boolean,
  389. /**
  390. * App global style
  391. */
  392. global: Record<any, any>,
  393. /**
  394. * App colors
  395. */
  396. colors: Record<any, any>,
  397. t: TTranslationFunction,
  398. topicVM: TLearnTopicViewModel,
  399. /**
  400. * Helper function which considers different conditions (such as if quizzes inside a topic are already completed) before calling the `completeTopic` function
  401. */
  402. onCompleteTopicClick: Function,
  403. /**
  404. * Returns `true` if topic is being completed
  405. */
  406. completing: boolean,
  407. /**
  408. * Returns `true` if "Mark Complete" button should be disabled
  409. */
  410. completeDisabled: boolean,
  411. /**
  412. * Data about previous lesson/topic/quiz
  413. */
  414. prevObject: Record<any, any>,
  415. /**
  416. * Data about next lesson/topic/quiz
  417. */
  418. nextObject: Record<any, any>,
  419. /**
  420. * Function to execute if previous or next button is a quiz
  421. */
  422. onQuizClick: Function,
  423. /**
  424. * Function to execute if previous or next button is a lesson
  425. */
  426. onLessonClick: Function,
  427. /**
  428. * Function to execute if previous or next button is a topic
  429. */
  430. onTopicClick: Function
  431. };
  432. /**
  433. * LearnTopicOfflineComponentProps
  434. */
  435. type LearnTopicOfflineComponentProps = {
  436. /**
  437. * App global style
  438. */
  439. global: Record<any, any>,
  440. t: TTranslationFunction,
  441. /**
  442. * Default container style
  443. */
  444. containerStyle: Record<any, any>,
  445. /**
  446. * Default style of EmptyList component
  447. */
  448. emptyListStyle: Record<any, any>
  449. };
  450. /**
  451. * LearnTopicWebViewContentComponentProps
  452. */
  453. type LearnTopicWebViewContentComponentProps = {
  454. /**
  455. * Returns `true` if device is connected to an internet network
  456. */
  457. online: boolean,
  458. t: TTranslationFunction,
  459. /**
  460. * The default function used for determining how to handle webview requests.
  461. */
  462. onShouldStartLoadWithRequest: Function,
  463. /**
  464. * Default height
  465. */
  466. height: number,
  467. /**
  468. * Contains data of the web site to be loaded in the webview
  469. */
  470. source: Record<any, any>,
  471. /**
  472. * App global style
  473. */
  474. global: Record<any, any>,
  475. /**
  476. * App colors
  477. */
  478. colors: Record<any, any>,
  479. /**
  480. * Modal which shows up when the "Read More" component is pressed
  481. */
  482. ModalHeaderComponent: React.FC
  483. };
  484. /**
  485. * LearnTopicMaterialsSectionTitleProps
  486. */
  487. type LearnTopicMaterialsSectionTitleProps = {
  488. /**
  489. * App global style
  490. */
  491. global: Record<any, any>,
  492. t: TTranslationFunction
  493. };
  494. /**
  495. * AssignmentsHeaderProps
  496. */
  497. type AssignmentsHeaderProps = {
  498. /**
  499. * App global style
  500. */
  501. global: Record<any, any>,
  502. t: TTranslationFunction,
  503. /**
  504. * Total number of assignments uploaded
  505. */
  506. totalAssignments: number,
  507. /**
  508. * Number of assignments approved
  509. */
  510. approved: number
  511. };
  512. /**
  513. * AssignmentItemIconProps
  514. */
  515. type AssignmentItemIconProps = {
  516. /**
  517. * Default icon for the item
  518. */
  519. icon: number,
  520. /**
  521. * Default style for the item
  522. */
  523. styles: Record<any, any>
  524. };
  525. /**
  526. * AssignmentItemTitleProps
  527. */
  528. type AssignmentItemTitleProps = {
  529. /**
  530. * Assignment item title
  531. */
  532. title: string,
  533. /**
  534. * Default style for the item
  535. */
  536. style: Record<any, any>
  537. };
  538. /**
  539. * AssignmentItemStatusProps
  540. */
  541. type AssignmentItemStatusProps = {
  542. /**
  543. * App global style
  544. */
  545. global: Record<any, any>,
  546. /**
  547. * Assignment item status
  548. */
  549. text: string,
  550. /**
  551. * Default container style
  552. */
  553. containerStyle: Record<any, any>,
  554. /**
  555. * Default text style
  556. */
  557. textStyle: Record<any, any>
  558. };
  559. /**
  560. * AssignmentItemCommentProps
  561. */
  562. type AssignmentItemCommentProps = {
  563. /**
  564. * Opens the comments modal
  565. */
  566. pressHandler: Function,
  567. /**
  568. * Default button color
  569. */
  570. tintColor: string,
  571. /**
  572. * Default container style
  573. */
  574. containerStyle: Record<any, any> | undefined,
  575. /**
  576. * Number of comments
  577. */
  578. count: number,
  579. /**
  580. * Button size
  581. */
  582. size: string,
  583. /**
  584. * App global style
  585. */
  586. global: Record<any, any>,
  587. /**
  588. * Can be used to determine if button should use light or dark style
  589. */
  590. lightMode: boolean | undefined
  591. };
  592. /**
  593. * AssignmentItemDownloadProps
  594. */
  595. type AssignmentItemDownloadProps = {
  596. /**
  597. * Downloads the assignment item
  598. */
  599. pressHandler: Function,
  600. /**
  601. * Default button color
  602. */
  603. tintColor: string,
  604. /**
  605. * Default container style
  606. */
  607. containerStyle: Record<any, any> | undefined,
  608. /**
  609. * Number of comments
  610. */
  611. count: number,
  612. /**
  613. * Button size
  614. */
  615. size: string,
  616. /**
  617. * App global style
  618. */
  619. global: Record<any, any>,
  620. /**
  621. * Can be used to determine if button should use light or dark style
  622. */
  623. lightMode: boolean | undefined
  624. };
  625. /**
  626. * AssignmentItemDownloadProgressProps
  627. */
  628. type AssignmentItemDownloadProgressProps = {
  629. /**
  630. * Download progress
  631. */
  632. progress: number,
  633. /**
  634. * Unfilled color of the ProgressCircle component
  635. */
  636. unfilledColor: string,
  637. /**
  638. * Color of the ProgressCircle component
  639. */
  640. tintColor: string
  641. };
  642. /**
  643. * MaterialsComponentProps
  644. */
  645. type MaterialsComponentProps = {
  646. /**
  647. * App global style
  648. */
  649. global: Record<any, any>,
  650. /**
  651. * App colors
  652. */
  653. colors: Record<any, any>,
  654. t: TTranslationFunction,
  655. /**
  656. * Contents of course materials field
  657. */
  658. materials: string,
  659. /**
  660. * Default styles for different HTML tags
  661. */
  662. tagsStyles: Record<any, any>,
  663. /**
  664. * Default styles for course materials
  665. */
  666. materialsStyles: Record<any, any>,
  667. /**
  668. * Function to set a font style
  669. */
  670. baseFontStyle: Function,
  671. navigation: NavigationService,
  672. /**
  673. * Handles link press for the HTML component
  674. */
  675. onLinkPress: Function
  676. };
  677. /**
  678. * TransformLearnTopicViewModelCallback
  679. */
  680. type TransformLearnTopicViewModelCallback = {
  681. viewModel: TLearnTopicViewModel,
  682. topic: LearnTopic
  683. };
  684. /**
  685. * @class
  686. * Learn Topic Screen Hooks.
  687. * Instance name: learnTopicSingleScreenApi
  688. You can use this hook to customize the learn topic screen such as by adding a component by the topic content.
  689. * @example
  690. * externalCodeSetup.learnTopicSingleScreenApi.METHOD_NAME
  691. */
  692. export class LearnTopicSingleScreenHooksApi {
  693. afterContentRenderer: (
  694. topic: LearnTopic,
  695. global: Record<any, any>,
  696. colors: Record<any, any>,
  697. navigation: NavigationService
  698. ) => JSX.Element | null = () => null;
  699. /**
  700. * It adds a component after the topic content so you can customize the information to be displayed.
  701. * @method
  702. * @param {LearnTopicAfterContentRendererProps} renderFunction
  703. * @example
  704. * externalCodeSetup.learnTopicSingleScreenApi.setAfterContentRenderer((topicObject, global, colors, navigation) => (
  705. * <TouchableOpacity onPress={() => navigation.navigate("CoursesScreen")}>
  706. * <Text style={{fontSize: 12}}> Tap to go back to courses list</Text>
  707. * </TouchableOpacity>
  708. * ))
  709. */
  710. setAfterContentRenderer = (
  711. renderFunction: (
  712. topic: LearnTopic,
  713. global: Record<any, any>,
  714. colors: Record<any, any>,
  715. navigation: NavigationService
  716. ) => JSX.Element | null
  717. ) => {
  718. this.afterContentRenderer = renderFunction;
  719. };
  720. transformTopicActionButtons = (
  721. TopicButton: JSX.Element,
  722. showComplete: boolean,
  723. global: Record<any, any>,
  724. colors: Record<any, any>,
  725. topic: TLearnTopicViewModel,
  726. completing: boolean,
  727. labels: Record<any, any>,
  728. handleComplete: Function
  729. ) => TopicButton;
  730. /**
  731. * You can transform the default learn topic action button by replacing it with your preferred action buttons.
  732. * For example, you can add an inline button to the topic screen for marking topic completion.
  733. * @param {TransformTopicActionButtonsCallback} transformTopicActionButtons
  734. * @method
  735. * @example <caption> Add more components for topic action </caption>
  736. *
  737. * externalCodeSetup.learnTopicSingleScreenApi.setTransformTopicActionButtons((
  738. * TopicButton,
  739. * showComplete,
  740. * global,
  741. * colors,
  742. * topic,
  743. * completing,
  744. * labels,
  745. * handleComplete) => {
  746. *
  747. * const Buttons =
  748. * <View style={[global.row, { backgroundColor: "#fff" }]}>
  749. *
  750. * <View style={{ width: "45%", backgroundColor: "#fff", paddingHorizontal: 20, paddingVertical: 15 }}>
  751. * <AppTouchableOpacity
  752. * style={[
  753. * global.completeTopicButtonW,
  754. * { flex: 1, backgroundColor: colors.primaryButtonBg }
  755. * ]}
  756. * onPress={() => {
  757. * //Do function...
  758. * }}
  759. * >
  760. * <View style={global.row}>
  761. * <View style={global.linkWithArrow}>
  762. * <Text
  763. * style={{ color: "#fff", fontWeight: "bold" }}
  764. * >
  765. * Questions?
  766. * </Text>
  767. * </View>
  768. * </View>
  769. * </AppTouchableOpacity>
  770. * </View>
  771. * <View style={{ width: "45%", marginLeft: "auto" }}>
  772. * {TopicButton}
  773. * </View>
  774. * </View>
  775. *
  776. * return Buttons;
  777. * })
  778. */
  779. setTransformTopicActionButtons = (
  780. transformTopicActionButtons: (
  781. TopicButton: JSX.Element,
  782. showComplete: boolean,
  783. global: Record<any, any>,
  784. colors: Record<any, any>,
  785. topic: TLearnTopicViewModel,
  786. completing: boolean,
  787. labels: Record<any, any>,
  788. handleComplete: Function
  789. ) => JSX.Element
  790. ) => {
  791. this.transformTopicActionButtons = transformTopicActionButtons;
  792. };
  793. showMarkAsComplete = (topic: LearnTopic) => true;
  794. /**
  795. * Use this to hide or show the mark as complete component.
  796. * @method
  797. * @param {showMarkAsCompleteProps} showMarkAsComplete
  798. * @example
  799. * externalCodeSetup.learnTopicSingleScreenApi.setShowMarkAsComplete((topic) => false);
  800. */
  801. setShowMarkAsComplete = (
  802. showMarkAsComplete: (topic: LearnTopic) => boolean
  803. ) => {
  804. this.showMarkAsComplete = showMarkAsComplete;
  805. };
  806. PrevNextComponent: React.ComponentType<
  807. LearnTopicPrevNextComponentProps
  808. > | null = null;
  809. /**
  810. * 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.
  811. * @method
  812. * @param {React.ComponentType<LearnTopicPrevNextComponentProps>} PrevNextComponent
  813. * @example <caption> Remove previous and next buttons if there is no previous and next objects. Otherwise, return the default previous and next buttons </caption>
  814. *
  815. * //In custom_code/components/PrevNext.js
  816. *
  817. * import React from "react";
  818. * import { Text, View, StyleSheet } from "react-native";
  819. * import AppTouchableOpacity from "@src/components/AppTouchableOpacity";
  820. * import Icon from "@src/components/Icon";
  821. * import { shadeColor } from "@src/utils";
  822. *
  823. * export const onObjectClick = (
  824. * object,
  825. * onQuizClick,
  826. * onTopicClick,
  827. * onLessonClick
  828. * ) => {
  829. * if (!!!object) {
  830. * return false;
  831. * }
  832. * switch (object.type) {
  833. * case "quiz":
  834. * onQuizClick(object.parentType, object.parent)(object);
  835. * break;
  836. * case "topic":
  837. * onTopicClick(object, object.parent);
  838. * break;
  839. * case "lesson":
  840. * onLessonClick(object);
  841. * break;
  842. * }
  843. * };
  844. *
  845. * const PrevNext = ({
  846. * global,
  847. * colors,
  848. * t,
  849. * prevObject,
  850. * nextObject,
  851. * courseId,
  852. * onQuizClick,
  853. * onLessonClick,
  854. * onTopicClick,
  855. * nextLockedAlert
  856. * }) => {
  857. *
  858. * if (!nextObject && !prevObject) {
  859. * return null;
  860. * }
  861. *
  862. * return (
  863. * <View style={[global.row]}>
  864. * <AppTouchableOpacity
  865. * style={[
  866. * global.wrappedButton,
  867. * global.wrappedTextButton,
  868. * { marginRight: 4 }
  869. * ]}
  870. * onPress={() => {
  871. * if (prevObject !== "disabled") {
  872. * onObjectClick(prevObject, onQuizClick, onTopicClick, onLessonClick);
  873. * }
  874. * }}
  875. * >
  876. * <View style={global.row}>
  877. * <View style={global.linkWithArrow}>
  878. * <Text
  879. * style={[
  880. * global.wrappedTextButtonLabel,
  881. * {
  882. * color:
  883. * !!!prevObject || prevObject === "disabled"
  884. * ? shadeColor(colors.headerIconColor, 0.4)
  885. * : colors.headerIconColor
  886. * }
  887. * ]}
  888. * >
  889. * {t("lesson:prevButtonText")}
  890. * </Text>
  891. * </View>
  892. * </View>
  893. * </AppTouchableOpacity>
  894. *
  895. * <AppTouchableOpacity
  896. * style={[global.wrappedButton, global.wrappedTextButton]}
  897. * onPress={() => {
  898. * if (nextObject !== "disabled") {
  899. * onObjectClick(nextObject, onQuizClick, onTopicClick, onLessonClick);
  900. * } else if (typeof nextLockedAlert === "function") {
  901. * nextLockedAlert();
  902. * }
  903. * }}
  904. * >
  905. * <View style={global.row}>
  906. * <View style={global.linkWithArrow}>
  907. * <Text
  908. * style={[
  909. * global.wrappedTextButtonLabel,
  910. * {
  911. * color:
  912. * !!!nextObject || nextObject === "disabled"
  913. * ? shadeColor(colors.headerIconColor, 0.4)
  914. * : colors.headerIconColor
  915. * }
  916. * ]}
  917. * >
  918. * {t("lesson:nextButtonText")}
  919. * </Text>
  920. * </View>
  921. * </View>
  922. * </AppTouchableOpacity>
  923. * </View>
  924. * );
  925. * };
  926. *
  927. * export default PrevNext;
  928. *
  929. * //In custom_code/index.js...
  930. *
  931. * ...
  932. *
  933. * import PrevNextComponent from './components/PrevNext';
  934. * export const applyCustomCode = externalCodeSetup => {
  935. * externalCodeSetup.learnTopicSingleScreenApi.setPrevNextComponent((props) => <PrevNextComponent {...props} />);
  936. * }
  937. *
  938. */
  939. setPrevNextComponent = (
  940. PrevNextComponent: React.ComponentType<
  941. LearnTopicPrevNextComponentProps
  942. > | null
  943. ) => {
  944. this.PrevNextComponent = PrevNextComponent;
  945. };
  946. LearnTopicTitleComponent: React.ComponentType<
  947. LearnTopicHeaderProps
  948. > | null = null;
  949. /**
  950. * You can use this to replace the topic's title component.
  951. * For example, you can use this to change the subtitle's color.
  952. * @method
  953. * @param {React.ComponentType<LearnTopicHeaderProps>} LearnTopicTitleComponent
  954. * @example <caption> Change subtitle colors </caption>
  955. *
  956. * //In custom_code/components/TopicTitle.js...
  957. * import React from "react";
  958. * import {View, Text} from "react-native";
  959. * import Animated from "react-native-reanimated";
  960. *
  961. * const TopicTitle = ({
  962. * topic,
  963. * global,
  964. * colors,
  965. * paddingTop,
  966. * setHeaderHeight,
  967. * t,
  968. * labels,
  969. * lessonOrder
  970. * }) => {
  971. *
  972. * const paddingBottom = 14;
  973. *
  974. * return (
  975. * <Animated.View
  976. * style={[
  977. * {
  978. * backgroundColor: colors.bodyFrontBg,
  979. * width: "100%",
  980. * shadowOffset: {width: 0, height: 1},
  981. * shadowRadius: 1,
  982. * shadowColor: "#000",
  983. * shadowOpacity: 0.05
  984. * }
  985. * ]}
  986. * >
  987. * <View
  988. * style={[
  989. * global.row,
  990. * {
  991. * justifyContent: "space-between",
  992. * alignItems: "flex-start",
  993. * paddingTop,
  994. * paddingBottom
  995. * }
  996. * ]}
  997. * onLayout={event => {
  998. * const {height} = event.nativeEvent.layout;
  999. * typeof setHeaderHeight === "function" && setHeaderHeight(height);
  1000. * }}
  1001. * >
  1002. * <Animated.View
  1003. * style={{
  1004. * flex: 1,
  1005. * paddingHorizontal: 20
  1006. * }}
  1007. * >
  1008. * <Animated.Text
  1009. * style={[
  1010. * global.courseHeaderTitle,
  1011. * {marginBottom: 5}
  1012. * ]}
  1013. * >
  1014. * {topic.title}
  1015. * </Animated.Text>
  1016. *
  1017. * <View style={global.row}>
  1018. * <Text style={[global.courseHeaderSubTitle, {color: "red"}]}>
  1019. * {t("lessonTopic:lessoncount", {
  1020. * lesson: labels.lesson,
  1021. * current: lessonOrder + 1
  1022. * })}
  1023. * </Text>
  1024. * <View
  1025. * style={{
  1026. * width: 3,
  1027. * height: 3,
  1028. * marginTop: 2,
  1029. * marginLeft: 5,
  1030. * marginRight: 4,
  1031. * backgroundColor: "#8D8F97",
  1032. * borderRadius: 2,
  1033. * opacity: 0.45
  1034. * }}
  1035. * />
  1036. * <Text style={[global.courseHeaderSubTitle, {color: "blue"}]}>
  1037. * {t("lessonTopic:count", {
  1038. * topic: labels.topic,
  1039. * current: topic.order
  1040. * })}
  1041. * </Text>
  1042. * </View>
  1043. * </Animated.View>
  1044. * </View>
  1045. * </Animated.View>
  1046. * );
  1047. * };
  1048. *
  1049. * export default TopicTitle;
  1050. *
  1051. *
  1052. * //In custom_code/index.js...
  1053. *
  1054. * ...
  1055. *
  1056. * import TopicTitle from "./components/TopicTitle";
  1057. * export const applyCustomCode = externalCodeSetup => {
  1058. * externalCodeSetup.learnTopicSingleScreenApi.setLearnTopicTitleComponent(props => <TopicTitle {...props} />)
  1059. * }
  1060. */
  1061. setLearnTopicTitleComponent = (
  1062. LearnTopicTitleComponent: React.ComponentType<LearnTopicHeaderProps> | null
  1063. ) => {
  1064. this.LearnTopicTitleComponent = LearnTopicTitleComponent;
  1065. };
  1066. LearnTopicScreenHeader: React.ComponentType<
  1067. LearnTopicScreenHeaderProps
  1068. > | null = null;
  1069. /**
  1070. * 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.
  1071. * @method
  1072. * @param {React.ComponentType<LearnTopicScreenHeaderProps>} LearnTopicScreenHeader
  1073. * @example
  1074. *
  1075. * //In custom_code/components/LearnTopicHeader.js...
  1076. *
  1077. * import React from "react";
  1078. * import {View, Text} from "react-native";
  1079. * import Animated from "react-native-reanimated";
  1080. * import {DEVICE_WIDTH} from "@src/styles/global";
  1081. * import AuthWrapper from "@src/components/AuthWrapper";
  1082. *
  1083. * const Header = ({
  1084. * headerLeftStyle,
  1085. * style,
  1086. * global,
  1087. * backToCourse,
  1088. * renderTimer,
  1089. * headerRightAuthWrapperProps,
  1090. * prevNext,
  1091. * topic
  1092. * }) => {
  1093. * return (
  1094. * <Animated.View
  1095. * style={[
  1096. * global.row,
  1097. * global.fakeHeader,
  1098. * {
  1099. * backgroundColor: "transparent",
  1100. * paddingHorizontal: 10,
  1101. * overflow: "hidden"
  1102. * },
  1103. * {
  1104. * width: DEVICE_WIDTH
  1105. * },
  1106. * style
  1107. * ]}
  1108. * >
  1109. * <View
  1110. * style={[
  1111. * {
  1112. * alignItems: "center",
  1113. * justifyContent: "center",
  1114. * flexDirection: "row",
  1115. * flex: 1,
  1116. * height: "100%",
  1117. *
  1118. * backgroundColor: "cyan",
  1119. * borderRadius: 20
  1120. * }
  1121. * ]}
  1122. * >
  1123. * <View style={[global.headerButtonLeft, headerLeftStyle]}>
  1124. * {backToCourse}
  1125. * </View>
  1126. *
  1127. * <View>
  1128. * <Text>
  1129. * {topic.title}
  1130. * </Text>
  1131. * </View>
  1132. *
  1133. * <View style={[global.headerCustomTitle]}>
  1134. * {renderTimer}
  1135. * </View>
  1136. * <View style={[global.headerButtonRight]}>
  1137. * <AuthWrapper
  1138. * actionOnGuestLogin={"hide"}
  1139. * {...headerRightAuthWrapperProps}
  1140. * >
  1141. * {prevNext}
  1142. * </AuthWrapper>
  1143. * </View>
  1144. * </View>
  1145. * </Animated.View>
  1146. * );
  1147. * };
  1148. *
  1149. * export default Header;
  1150. *
  1151. * //In custom_code/index.js...
  1152. *
  1153. * import LearnTopicHeader from "./components/LearnTopicHeader"
  1154. * export const applyCustomCode = externalCodeSetup => {
  1155. * externalCodeSetup.learnTopicSingleScreenApi.setLearnTopicScreenHeader(props => <LearnTopicHeader {...props} />)
  1156. * }
  1157. */
  1158. setLearnTopicScreenHeader = (
  1159. LearnTopicScreenHeader: React.ComponentType<
  1160. LearnTopicScreenHeaderProps
  1161. > | null
  1162. ) => {
  1163. this.LearnTopicScreenHeader = LearnTopicScreenHeader;
  1164. };
  1165. VideoProgressionComponent: React.ComponentType<
  1166. LearnTopicVideoProgressionComponentProps
  1167. > | null = null;
  1168. /**
  1169. * You can use this hook to customize the Video Progression component in the single topic screen.
  1170. * 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
  1171. * @method
  1172. * @param {React.ComponentType<LearnTopicVideoProgressionComponentProps>} VideoProgressionComponent
  1173. * @example <caption> Execute a custom callback when video has finished playing </caption>
  1174. *
  1175. * ...
  1176. * import AppVideo from "@src/components/Video/AppVideo";
  1177. *
  1178. * export const applyCustomCode = externalCodeSetup => {
  1179. *
  1180. * externalCodeSetup.learnTopicSingleScreenApi.setVideoProgressionComponent(props => {
  1181. * const {
  1182. * topicVideoStyle,
  1183. * controls,
  1184. * autoPlay,
  1185. * videoCallback,
  1186. * url,
  1187. * width,
  1188. * height,
  1189. * global,
  1190. * isNavActive,
  1191. * topic,
  1192. * videoWatched,
  1193. * setVideoWatched,
  1194. * onCompleteTopicClick
  1195. * } = props;
  1196. *
  1197. * const customCallback = settings => event => {
  1198. *
  1199. * if (event.nativeEvent.data === "ENDED") {
  1200. *
  1201. * if (!videoWatched)
  1202. * setVideoWatched();
  1203. *
  1204. * Alert.alert(
  1205. * "Video Complete",
  1206. * "You have finished watching the video. Do you want to mark the topic as complete?",
  1207. * [
  1208. * {
  1209. * text: "Cancel",
  1210. * onPress: () => console.log("Cancel Pressed"),
  1211. * style: "cancel"
  1212. * },
  1213. * { text: "OK", onPress: () => onCompleteTopicClick() }
  1214. * ]
  1215. * );
  1216. * }
  1217. *
  1218. * }
  1219. *
  1220. * return <View style={topicVideoStyle}>
  1221. * <AppVideo
  1222. * controls={controls}
  1223. * autoPlay={autoPlay}
  1224. * // videoCallback={videoCallback()}
  1225. * videoCallback={customCallback(topic.settings)}
  1226. * url={url}
  1227. * width={width}
  1228. * height={height}
  1229. * global={global}
  1230. * isNavActive={isNavActive}
  1231. * />
  1232. * </View>
  1233. * })
  1234. * }
  1235. *
  1236. */
  1237. setVideoProgressionComponent = (
  1238. VideoProgressionComponent: React.ComponentType<
  1239. LearnTopicVideoProgressionComponentProps
  1240. > | null
  1241. ) => {
  1242. this.VideoProgressionComponent = VideoProgressionComponent;
  1243. };
  1244. AfterMaterialsComponent: React.ComponentType<
  1245. LearnTopicAfterMaterialsComponentProps
  1246. > | null = null;
  1247. /**
  1248. * 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.
  1249. * @method
  1250. * @param {React.ComponentType<LearnTopicAfterMaterialsComponentProps>} AfterMaterialsComponent
  1251. * @example
  1252. *
  1253. * //In custom_code/components/TopicBottomComponent.js...
  1254. *
  1255. * import React from "react";
  1256. * import { View, Text, TouchableOpacity } from "react-native";
  1257. *
  1258. * const TopicBottomComponent = props => {
  1259. *
  1260. * const {
  1261. * colors,
  1262. * course,
  1263. * materials,
  1264. * navigation
  1265. * } = props;
  1266. *
  1267. * const back = () => {
  1268. * navigation.navigate({
  1269. * routeName: "CoursesSingleScreen",
  1270. * params: {
  1271. * id: course.id,
  1272. * course
  1273. * },
  1274. * key: course.id.toString()
  1275. * })
  1276. * }
  1277. * return <View style={{
  1278. * backgroundColor: colors.bodyFrontBg,
  1279. * paddingHorizontal: 20,
  1280. * paddingBottom: 20,
  1281. * minHeight: 100,
  1282. * }}>
  1283. * <Text>This lesson is part of the {course.title.rendered} course </Text>
  1284. * <TouchableOpacity onPress={back}>
  1285. * <Text>
  1286. * Back To Course
  1287. * </Text>
  1288. * </TouchableOpacity>
  1289. * </View>
  1290. * }
  1291. *
  1292. * export default TopicBottomComponent;
  1293. *
  1294. * //In custom_code/index.js...
  1295. *
  1296. * ...
  1297. *
  1298. * import TopicBottomComponent from "./components/TopicBottomComponent";
  1299. * export const applyCustomCode = externalCodeSetup => {
  1300. * externalCodeSetup.learnTopicSingleScreenApi.setAfterMaterialsComponent(props => <TopicBottomComponent {...props}/>)
  1301. * }
  1302. */
  1303. setAfterMaterialsComponent = (
  1304. AfterMaterialsComponent: React.ComponentType<
  1305. LearnTopicAfterMaterialsComponentProps
  1306. > | null
  1307. ) => {
  1308. this.AfterMaterialsComponent = AfterMaterialsComponent;
  1309. };
  1310. LearnTopicActionComponent: React.ComponentType<
  1311. LearnTopicActionComponentProps
  1312. > | null = null;
  1313. /**
  1314. * You can use this hook to customize the "Mark Complete" / "Completed" button.
  1315. * For example, you can add your own loading animation when the "Mark Complete" button is pressed.
  1316. * @method
  1317. * @param {React.ComponentType<LearnTopicActionComponentProps>} LearnTopicActionComponent
  1318. * @example
  1319. *
  1320. * //In custom_code/components/LearnTopicActionComponent.js...
  1321. *
  1322. * import React from "react";
  1323. * import { View, Text, ActivityIndicator } from "react-native";
  1324. *
  1325. * import AuthWrapper from "@src/components/AuthWrapper";
  1326. * import AppTouchableOpacity from "@src/components/AppTouchableOpacity";
  1327. * import Icon from "@src/components/Icon";
  1328. * import { isColorDark } from "@src/utils";
  1329. *
  1330. * const LearnTopicActionComponent = ({
  1331. * showComplete,
  1332. * global,
  1333. * colors,
  1334. * t,
  1335. * topicVM,
  1336. * onCompleteTopicClick,
  1337. * completing,
  1338. * completeDisabled
  1339. * }) => (
  1340. * <AuthWrapper actionOnGuestLogin={"hide"}>
  1341. * {showComplete && (
  1342. * <View
  1343. * style={[
  1344. * global.row,
  1345. * {
  1346. * backgroundColor: colors.bodyFrontBg,
  1347. * borderTopColor: colors.borderColor
  1348. * },
  1349. * global.learnTopicActionButtonContainer
  1350. * ]}
  1351. * >
  1352. * <AppTouchableOpacity
  1353. * style={[
  1354. * {flex: 1},
  1355. * {
  1356. * opacity: !topicVM.completed && completeDisabled ? 0.5 : 1,
  1357. * backgroundColor: !topicVM.completed
  1358. * ? colors.primaryButtonBg
  1359. * : colors.bodyFrontBg
  1360. * },
  1361. * global.completeTopicButtonW
  1362. * ]}
  1363. * disabled={topicVM.completed || completeDisabled}
  1364. * onPress={onCompleteTopicClick}
  1365. * >
  1366. * <View style={global.row}>
  1367. * <View style={global.linkWithArrow}>
  1368. * {!topicVM.completed ? (
  1369. * completing && (
  1370. * <ActivityIndicator
  1371. * animating={true}
  1372. * color={colors.primaryButtonColor}
  1373. * size="small"
  1374. * style={global.learnTopicButtonLoadingIcon}
  1375. * />
  1376. * )
  1377. * ) : (
  1378. * <Icon
  1379. * webIcon={""}
  1380. * icon={{fontIconName: "check", weight: 200}}
  1381. * styles={global.learnTopicActionCompleteIcon}
  1382. * />
  1383. * )}
  1384. * <Text
  1385. * style={[
  1386. * {
  1387. * marginLeft: 10,
  1388. * color: !topicVM.completed
  1389. * ? colors.primaryButtonColor
  1390. * : isColorDark(colors.bodyFrontBg)
  1391. * ? "white"
  1392. * : "black"
  1393. * },
  1394. * global.completeTopicButton
  1395. * ]}
  1396. * >
  1397. * {t(
  1398. * topicVM.completed
  1399. * ? "lessonTopic:completed"
  1400. * : "lessonTopic:markAsComplete"
  1401. * )}
  1402. * </Text>
  1403. * </View>
  1404. * </View>
  1405. * </AppTouchableOpacity>
  1406. * </View>
  1407. * )}
  1408. * </AuthWrapper>
  1409. * );
  1410. *
  1411. * export default LearnTopicActionComponent;
  1412. *
  1413. * //In custom_code/index.js...
  1414. *
  1415. * ...
  1416. *
  1417. * import LearnTopicActionComponent from "./components/LearnTopicActionComponent";
  1418. * export const applyCustomCode = (externalCodeSetup: any) => {
  1419. * externalCodeSetup.learnTopicSingleScreenApi.setLearnTopicActionComponent(props => <LearnTopicActionComponent {...props} />)
  1420. * }
  1421. */
  1422. setLearnTopicActionComponent = (
  1423. LearnTopicActionComponent: React.ComponentType<
  1424. LearnTopicActionComponentProps
  1425. > | null
  1426. ) => {
  1427. this.LearnTopicActionComponent = LearnTopicActionComponent;
  1428. };
  1429. OfflineComponent: React.ComponentType<
  1430. LearnTopicOfflineComponentProps
  1431. > | null = null;
  1432. /**
  1433. * 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.
  1434. * @method
  1435. * @param {React.ComponentType<LearnTopicOfflineComponentProps>} OfflineComponent
  1436. * @example
  1437. *
  1438. * ...
  1439. *
  1440. * import EmptyList from "@src/components/EmptyList";
  1441. *
  1442. * export const applyCustomCode = (externalCodeSetup) => {
  1443. * externalCodeSetup.learnTopicSingleScreenApi.setOfflineComponent(
  1444. * ({containerStyle, t, global, emptyListStyle}) => (
  1445. * <View style={containerStyle}>
  1446. * <EmptyList
  1447. * emptyText={{
  1448. * title: t("common:contentOfflineMessage"),
  1449. * icon: {fontIconName: "wifi-slash", weight: 400}
  1450. * }}
  1451. * global={global}
  1452. * style={emptyListStyle}
  1453. * />
  1454. * </View>
  1455. * )
  1456. * );
  1457. * }
  1458. */
  1459. setOfflineComponent = (
  1460. OfflineComponent: React.ComponentType<
  1461. LearnTopicOfflineComponentProps
  1462. > | null
  1463. ) => {
  1464. this.OfflineComponent = OfflineComponent;
  1465. };
  1466. WebViewContentComponent: React.ComponentType<
  1467. LearnTopicWebViewContentComponentProps
  1468. > | null = null;
  1469. /**
  1470. * You can use this hook to replace the webview being used in the topic content.
  1471. * For example, you can choose to replace it with the default react-native webview.
  1472. * @method
  1473. * @param {React.ComponentType<LearnTopicWebViewContentComponentProps>} WebViewContentComponent
  1474. * @example
  1475. *
  1476. * ...
  1477. *
  1478. * import WebViewWithMore from "@src/components/WebViewWithMore";
  1479. * export const applyCustomCode = (externalCodeSetup) => {
  1480. * externalCodeSetup.learnTopicSingleScreenApi.setWebViewContentComponent(
  1481. * ({
  1482. * online,
  1483. * t,
  1484. * onShouldStartLoadWithRequest,
  1485. * height,
  1486. * source,
  1487. * global,
  1488. * colors,
  1489. * ModalHeaderComponent
  1490. * }) => (
  1491. * <WebViewWithMore
  1492. * online={online}
  1493. * t={t}
  1494. * onShouldStartLoadWithRequest={onShouldStartLoadWithRequest}
  1495. * height={height}
  1496. * source={source}
  1497. * global={global}
  1498. * colors={colors}
  1499. * ModalHeaderComponent={ModalHeaderComponent}
  1500. * />
  1501. * )
  1502. * );
  1503. * }
  1504. */
  1505. setWebViewContentComponent = (
  1506. WebViewContentComponent: React.ComponentType<
  1507. LearnTopicWebViewContentComponentProps
  1508. > | null
  1509. ) => {
  1510. this.WebViewContentComponent = WebViewContentComponent;
  1511. };
  1512. LearnTopicMaterialsSectionTitle: React.ComponentType<
  1513. LearnTopicMaterialsSectionTitleProps
  1514. > | null = null;
  1515. /**
  1516. * You can use this hook to customize the component that displays the "Materials" text.
  1517. * @method
  1518. * @param {React.ComponentType<LearnTopicMaterialsSectionTitleProps>} LearnTopicMaterialsSectionTitle
  1519. * @example
  1520. *
  1521. * ...
  1522. *
  1523. * export const applyCustomCode = (externalCodeSetup) => {
  1524. * externalCodeSetup.learnTopicSingleScreenApi.setLearnTopicMaterialsSectionTitle(
  1525. * ({global, t}) => (
  1526. * <Text
  1527. * style={{
  1528. * ...global.courseRoundBoxTitleAbove,
  1529. * marginBottom: 20
  1530. * }}
  1531. * >
  1532. * {t("lesson:materials")}
  1533. * </Text>
  1534. * )
  1535. * );
  1536. * }
  1537. */
  1538. setLearnTopicMaterialsSectionTitle = (
  1539. LearnTopicMaterialsSectionTitle: React.ComponentType<
  1540. LearnTopicMaterialsSectionTitleProps
  1541. > | null
  1542. ) => {
  1543. this.LearnTopicMaterialsSectionTitle = LearnTopicMaterialsSectionTitle;
  1544. };
  1545. AssignmentsHeader: React.ComponentType<AssignmentsHeaderProps> | null = null;
  1546. /**
  1547. *
  1548. * You can use this hook to customize the assignments title and the component that displays the total approved assignments.
  1549. * @method
  1550. * @param {React.ComponentType<AssignmentsHeaderProps>} AssignmentsHeader
  1551. * @example
  1552. *
  1553. * ...
  1554. *
  1555. * export const applyCustomCode = (externalCodeSetup) => {
  1556. * externalCodeSetup.learnTopicSingleScreenApi.setAssignmentsHeader(
  1557. * ({global, t, totalAssignments, approved}) => (
  1558. * <View style={{...global.row, flex: 1, marginBottom: 15}}>
  1559. * <Text style={[global.assignmentHeading, {flex: 1}]}>
  1560. * {t("assignment:heading")}
  1561. * </Text>
  1562. * {totalAssignments !== 0 && (
  1563. * <Text style={[global.assignmentDesc]}>
  1564. * {t("assignment:approvedOutOfTotal", {
  1565. * total: totalAssignments,
  1566. * approved
  1567. * })}
  1568. * </Text>
  1569. * )}
  1570. * </View>
  1571. * )
  1572. * );
  1573. * }
  1574. */
  1575. setAssignmentsHeader = (
  1576. AssignmentsHeader: React.ComponentType<AssignmentsHeaderProps> | null
  1577. ) => {
  1578. this.AssignmentsHeader = AssignmentsHeader;
  1579. };
  1580. AssignmentItemIcon: React.ComponentType<
  1581. AssignmentItemIconProps
  1582. > | null = null;
  1583. /**
  1584. * You can use this to change the icon beside the assignment title.
  1585. * For example, you can use this to remove or modify the default icon.
  1586. * @method
  1587. * @param {React.ComponentType<AssignmentItemIconProps>} AssignmentItemIcon
  1588. * @example
  1589. *
  1590. * ...
  1591. *
  1592. * import Icon from "@src/components/Icon";
  1593. * export const applyCustomCode = (externalCodeSetup) => {
  1594. * externalCodeSetup.learnTopicSingleScreenApi.setAssignmentItemIcon(
  1595. * ({icon, styles}) => <Icon icon={icon} styles={styles} />
  1596. * );
  1597. * }
  1598. */
  1599. setAssignmentItemIcon = (
  1600. AssignmentItemIcon: React.ComponentType<AssignmentItemIconProps> | null
  1601. ) => {
  1602. this.AssignmentItemIcon = AssignmentItemIcon;
  1603. };
  1604. AssignmentItemTitle: React.ComponentType<
  1605. AssignmentItemTitleProps
  1606. > | null = null;
  1607. /**
  1608. * You can use this to customize the AssignmentItemTitle component.
  1609. * For example, you can use this to change the font color or size of the title.
  1610. * @method
  1611. * @param {React.ComponentType<AssignmentItemTitleProps>} AssignmentItemTitle
  1612. * @example
  1613. *
  1614. * ...
  1615. *
  1616. * export const applyCustomCode = (externalCodeSetup) => {
  1617. * externalCodeSetup.learnTopicSingleScreenApi.setAssignmentItemTitle(({
  1618. * title,
  1619. * style
  1620. * }) => <Text style={style}>{title}</Text>)
  1621. * }
  1622. */
  1623. setAssignmentItemTitle = (
  1624. AssignmentItemTitle: React.ComponentType<AssignmentItemTitleProps> | null
  1625. ) => {
  1626. this.AssignmentItemTitle = AssignmentItemTitle;
  1627. };
  1628. AssignmentItemStatus: React.ComponentType<
  1629. AssignmentItemStatusProps
  1630. > | null = null;
  1631. /**
  1632. * You can use this to customize the AssignmentItemStatus component.
  1633. * @method
  1634. * @param {React.ComponentType<AssignmentItemStatusProps>} AssignmentItemStatus
  1635. * @example
  1636. *
  1637. * ...
  1638. *
  1639. * import {BubbleIcon} from "@src/components/BubbleIcon";
  1640. * export const applyCustomCode = (externalCodeSetup) => {
  1641. * externalCodeSetup.learnTopicSingleScreenApi.setAssignmentItemStatus(
  1642. * ({global, text, containerStyle, textStyle}) => (
  1643. * <BubbleIcon
  1644. * {...{
  1645. * global,
  1646. * text,
  1647. * containerStyle,
  1648. * textStyle
  1649. * }}
  1650. * />
  1651. * )
  1652. * );
  1653. * }
  1654. */
  1655. setAssignmentItemStatus = (
  1656. AssignmentItemStatus: React.ComponentType<AssignmentItemStatusProps> | null
  1657. ) => {
  1658. this.AssignmentItemStatus = AssignmentItemStatus;
  1659. };
  1660. AssignmentItemComment: React.ComponentType<
  1661. AssignmentItemCommentProps
  1662. > | null = null;
  1663. /**
  1664. * You can use this to customize the AssignmentItemComment button.
  1665. * @method
  1666. * @param {React.ComponentType<AssignmentItemCommentProps>} AssignmentItemComment
  1667. * @example
  1668. *
  1669. * ...
  1670. *
  1671. * import AssignmentCommentButton from "@src/components/Course/Assignment/AssignmentCommentButton";
  1672. * export const applyCustomCode = (externalCodeSetup) => {
  1673. * externalCodeSetup.learnTopicSingleScreenApi.setAssignmentItemComment(
  1674. * ({
  1675. * pressHandler,
  1676. * tintColor,
  1677. * containerStyle,
  1678. * count,
  1679. * size,
  1680. * global,
  1681. * lightMode
  1682. * }) => (
  1683. * <AssignmentCommentButton
  1684. * {...{
  1685. * pressHandler,
  1686. * tintColor,
  1687. * containerStyle,
  1688. * count,
  1689. * size,
  1690. * global,
  1691. * lightMode
  1692. * }}
  1693. * />
  1694. * )
  1695. * );
  1696. * }
  1697. */
  1698. setAssignmentItemComment = (
  1699. AssignmentItemComment: React.ComponentType<
  1700. AssignmentItemCommentProps
  1701. > | null
  1702. ) => {
  1703. this.AssignmentItemComment = AssignmentItemComment;
  1704. };
  1705. AssignmentItemDownload: React.ComponentType<
  1706. AssignmentItemDownloadProps
  1707. > | null = null;
  1708. /**
  1709. * You can use this to customize the AssignmentItemDownload button.
  1710. * For example, you can change the icon and add a confirmation modal before allowing the user to download the assignment file.
  1711. * @method
  1712. * @param {React.ComponentType<AssignmentItemDownloadProps>} AssignmentItemDownload
  1713. * @example
  1714. *
  1715. * ...
  1716. *
  1717. * import AssignmentDownloadButton from "@src/components/Course/Assignment/AssignmentDownloadButton";
  1718. * export const applyCustomCode = (externalCodeSetup) => {
  1719. * externalCodeSetup.learnTopicSingleScreenApi.setAssignmentItemDownload(
  1720. * ({pressHandler, tintColor, containerStyle, size, global, lightMode}) => (
  1721. * <AssignmentDownloadButton
  1722. * {...{
  1723. * pressHandler,
  1724. * tintColor,
  1725. * containerStyle,
  1726. * size,
  1727. * global,
  1728. * lightMode
  1729. * }}
  1730. * />
  1731. * )
  1732. * );
  1733. * }
  1734. *
  1735. */
  1736. setAssignmentItemDownload = (
  1737. AssignmentItemDownload: React.ComponentType<
  1738. AssignmentItemDownloadProps
  1739. > | null
  1740. ) => {
  1741. this.AssignmentItemDownload = AssignmentItemDownload;
  1742. };
  1743. AssignmentItemDownloadProgress: React.ComponentType<
  1744. AssignmentItemDownloadProgressProps
  1745. > | null = null;
  1746. /**
  1747. * You can use this to customize the progress indicator which is showed when the assignment item is being downloaded.
  1748. * @method
  1749. * @param {React.ComponentType<AssignmentItemDownloadProgressProps>} AssignmentItemDownloadProgress
  1750. * @example
  1751. *
  1752. * ...
  1753. *
  1754. * import AssignmentDownloadProgress from "@src/components/Course/Assignment/AssignmentDownloadProgress";
  1755. * export const applyCustomCode = (externalCodeSetup) => {
  1756. * externalCodeSetup.learnTopicSingleScreenApi.setAssignmentItemDownloadProgress(
  1757. * ({progress, unfilledColor, tintColor}) => (
  1758. * <AssignmentDownloadProgress
  1759. * {...{
  1760. * progress,
  1761. * unfilledColor,
  1762. * tintColor
  1763. * }}
  1764. * />
  1765. * )
  1766. * );
  1767. * }
  1768. *
  1769. */
  1770. setAssignmentItemDownloadProgress = (
  1771. AssignmentItemDownloadProgress: React.ComponentType<
  1772. AssignmentItemDownloadProgressProps
  1773. > | null
  1774. ) => {
  1775. this.AssignmentItemDownloadProgress = AssignmentItemDownloadProgress;
  1776. };
  1777. MaterialsComponent: React.ComponentType<
  1778. MaterialsComponentProps
  1779. > | null = null;
  1780. /**
  1781. * You can use this to customize the component that displays the materials of the topic.
  1782. * @method
  1783. * @param {React.ComponentType<MaterialsComponentProps>} MaterialsComponent
  1784. * @example
  1785. *
  1786. * ...
  1787. *
  1788. * import {
  1789. * Dimensions,
  1790. * } from "react-native";
  1791. * import HTML from "react-native-render-html";
  1792. * import {RenderListPrefix} from "@src/components/Course/CourseMaterials"
  1793. * const ent = require("ent");
  1794. * const DEVICE_WIDTH = Dimensions.get("window").width;
  1795. *
  1796. * export const applyCustomCode = (externalCodeSetup) => {
  1797. *
  1798. * externalCodeSetup.learnTopicSingleScreenApi.setMaterialsComponent((props) => {
  1799. *
  1800. * const {
  1801. * tagsStyles,
  1802. * materialsStyles,
  1803. * baseFontStyle,
  1804. * materials,
  1805. * onLinkPress,
  1806. * global,
  1807. * colors
  1808. * } = props;
  1809. *
  1810. * return (
  1811. * <HTML
  1812. * tagsStyles={{...tagsStyles, ...materialsStyles}}
  1813. * baseFontStyle={baseFontStyle(15)}
  1814. * html={ent.decode(materials)}
  1815. * imagesMaxWidth={DEVICE_WIDTH - 32}
  1816. * onLinkPress={onLinkPress}
  1817. * listsPrefixesRenderers={{
  1818. * ul: (attrib, children, styles, passProps) => (
  1819. * <RenderListPrefix
  1820. * parent={"ul"}
  1821. * colors={colors}
  1822. * global={global}
  1823. * passProps={passProps}
  1824. * />
  1825. * ),
  1826. * ol: (attrib, children, styles, passProps) => (
  1827. * <RenderListPrefix
  1828. * parent={"ol"}
  1829. * colors={colors}
  1830. * global={global}
  1831. * passProps={passProps}
  1832. * />
  1833. * )
  1834. * }}
  1835. * />
  1836. * )
  1837. * });
  1838. * }
  1839. */
  1840. setMaterialsComponent = (
  1841. MaterialsComponent: React.ComponentType<MaterialsComponentProps> | null
  1842. ) => {
  1843. this.MaterialsComponent = MaterialsComponent;
  1844. };
  1845. learnTopicViewModelFilter = (
  1846. viewModel: TLearnTopicViewModel | Record<any, any>
  1847. ) => viewModel;
  1848. /**
  1849. * Sets the callback function that can change an existing learn topic view model object.
  1850. * @method
  1851. * @param {TransformLearnTopicViewModelCallback} learnTopicViewModelFilter
  1852. * @example <caption>Remove the native blocks in a lesson topic</caption>
  1853. * externalCodeSetup.learnTopicSingleScreenApi.setLearnTopicViewModelFilter((viewModel, topic) => {
  1854. * return {
  1855. * ...viewModel,
  1856. * contentNative: []
  1857. * }
  1858. * })
  1859. */
  1860. setLearnTopicViewModelFilter = (
  1861. learnTopicViewModelFilter: (
  1862. viewModel: TLearnTopicViewModel | Record<any, any>
  1863. ) => TLearnTopicViewModel | Record<any, any>
  1864. ) => {
  1865. this.learnTopicViewModelFilter = learnTopicViewModelFilter;
  1866. };
  1867. }