diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 78faa4f6..75475864 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -610,6 +610,8 @@ PODS: - RNSound/Core (= 0.11.2) - RNSound/Core (0.11.2): - React-Core + - RNSVG (15.3.0): + - React-Core - RNVectorIcons (9.2.0): - React-Core - SocketRocket (0.6.1) @@ -703,6 +705,7 @@ DEPENDENCIES: - RNReanimated (from `../node_modules/react-native-reanimated`) - RNScreens (from `../node_modules/react-native-screens`) - RNSound (from `../node_modules/react-native-sound`) + - RNSVG (from `../node_modules/react-native-svg`) - RNVectorIcons (from `../node_modules/react-native-vector-icons`) - Yoga (from `../node_modules/react-native/ReactCommon/yoga`) @@ -846,6 +849,8 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native-screens" RNSound: :path: "../node_modules/react-native-sound" + RNSVG: + :path: "../node_modules/react-native-svg" RNVectorIcons: :path: "../node_modules/react-native-vector-icons" Yoga: @@ -933,6 +938,7 @@ SPEC CHECKSUMS: RNReanimated: 738543ef6ec0024ea0bc9f4ab3ac99af6f068448 RNScreens: 3c5b9f4a9dcde752466854b6109b79c0e205dad3 RNSound: 1081cf2576b404ca804daf4934bb644cb506ff98 + RNSVG: a48668fd382115bc89761ce291a81c4ca5f2fd2e RNVectorIcons: fcc2f6cb32f5735b586e66d14103a74ce6ad61f8 SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17 Yoga: 065f0b74dba4832d6e328238de46eb72c5de9556 diff --git a/package-lock.json b/package-lock.json index a519303b..cf92b07b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,6 +26,7 @@ "prop-types": "^15.8.1", "react": "18.2.0", "react-native": "0.71.8", + "react-native-circular-progress": "^1.4.0", "react-native-collapsible": "^1.6.1", "react-native-device-info": "^10.7.0", "react-native-draggable-flatlist": "^4.0.1", @@ -41,6 +42,7 @@ "react-native-screens": "^3.20.0", "react-native-sound": "^0.11.2", "react-native-sqlite-storage": "^6.0.1", + "react-native-svg": "^15.3.0", "react-native-vector-icons": "^9.2.0", "react-native-webview": "^13.6.2", "react-redux": "^8.0.5", @@ -5090,6 +5092,11 @@ "readable-stream": "^3.4.0" } }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -5585,6 +5592,52 @@ "semver": "bin/semver" } }, + "node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "dependencies": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/css-tree/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", @@ -5783,6 +5836,57 @@ "node": ">=0.10.0" } }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -5826,6 +5930,17 @@ "once": "^1.4.0" } }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/envinfo": { "version": "7.11.0", "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.11.0.tgz", @@ -10460,6 +10575,11 @@ "tmpl": "1.0.5" } }, + "node_modules/mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" + }, "node_modules/memoize-one": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", @@ -11368,6 +11488,17 @@ "node": ">=4" } }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, "node_modules/nullthrows": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz", @@ -12133,6 +12264,19 @@ "react": "18.2.0" } }, + "node_modules/react-native-circular-progress": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/react-native-circular-progress/-/react-native-circular-progress-1.4.0.tgz", + "integrity": "sha512-JnJE2pvyDVBdIJN49SziDMBmwn6cYTdrWVzpWFzVXzSzouZ9+0+N1nlGFM2zw3gqrJzjL+KktPTUf99IpU5yAg==", + "dependencies": { + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-native": ">=0.50.0", + "react-native-svg": ">=7.0.0" + } + }, "node_modules/react-native-codegen": { "version": "0.71.6", "resolved": "https://registry.npmjs.org/react-native-codegen/-/react-native-codegen-0.71.6.tgz", @@ -12345,6 +12489,19 @@ "react-native": ">=0.14.0" } }, + "node_modules/react-native-svg": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-15.3.0.tgz", + "integrity": "sha512-mBHu/fdlzUbpGX8SZFxgbKvK/sgqLfDLP8uh8G7Us+zJgdjO8OSEeqHQs+kPRdQmdLJQiqPJX2WXgCl7ToTWqw==", + "dependencies": { + "css-select": "^5.1.0", + "css-tree": "^1.1.3" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, "node_modules/react-native-vector-icons": { "version": "9.2.0", "resolved": "https://registry.npmjs.org/react-native-vector-icons/-/react-native-vector-icons-9.2.0.tgz", diff --git a/package.json b/package.json index e3c02a58..6407b9f4 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "prop-types": "^15.8.1", "react": "18.2.0", "react-native": "0.71.8", + "react-native-circular-progress": "^1.4.0", "react-native-collapsible": "^1.6.1", "react-native-device-info": "^10.7.0", "react-native-draggable-flatlist": "^4.0.1", @@ -43,6 +44,7 @@ "react-native-screens": "^3.20.0", "react-native-sound": "^0.11.2", "react-native-sqlite-storage": "^6.0.1", + "react-native-svg": "^15.3.0", "react-native-vector-icons": "^9.2.0", "react-native-webview": "^13.6.2", "react-redux": "^8.0.5", diff --git a/src/ReaderScreen/components/footer.jsx b/src/ReaderScreen/components/footer.jsx index 51f12bea..d657680c 100644 --- a/src/ReaderScreen/components/footer.jsx +++ b/src/ReaderScreen/components/footer.jsx @@ -4,8 +4,9 @@ import { Icon } from "@rneui/themed"; import { useSelector } from "react-redux"; import PropTypes from "prop-types"; import { styles, getHeaderStyles } from "../styles"; -import { colors, constant } from "../../common"; +import { colors } from "../../common"; import { useAnimationHeadFoot } from "../hooks"; +import { onPress } from "../utils"; function Footer({ navigation, shabadID }) { const { navigate } = navigation; @@ -17,19 +18,6 @@ function Footer({ navigation, shabadID }) { const nextBani = currentBaniIndex !== -1 ? baniList[currentBaniIndex + 1] : null; const animationPosition = useAnimationHeadFoot(); - function onPress(bani) { - if (!bani.folder) { - navigate(constant.READER, { - key: `Reader-${bani.id}`, - params: { id: bani.id, title: bani.gurmukhi }, - }); - } else { - navigate(constant.FOLDERSCREEN, { - key: `Folder-${bani.gurmukhi}`, - params: { data: bani.folder, title: bani.gurmukhi }, - }); - } - } return ( currentBaniIndex !== -1 && ( - {previousBani && ( + {previousBani ? ( { - onPress(previousBani); + onPress(previousBani, navigate); }} > @@ -51,20 +39,22 @@ function Footer({ navigation, shabadID }) { name="arrow-back" size={30} onPress={() => { - onPress(previousBani); + onPress(previousBani, navigate); }} color={colors.WHITE_COLOR} /> {previousBani.gurmukhi} + ) : ( + {} )} {nextBani && ( { - onPress(nextBani); + onPress(nextBani, navigate); }} > diff --git a/src/ReaderScreen/components/nextBaniModal.jsx b/src/ReaderScreen/components/nextBaniModal.jsx new file mode 100644 index 00000000..fa974265 --- /dev/null +++ b/src/ReaderScreen/components/nextBaniModal.jsx @@ -0,0 +1,111 @@ +import React, { useEffect, useState } from "react"; +import { Modal, View, Text, Pressable } from "react-native"; +import { AnimatedCircularProgress } from "react-native-circular-progress"; +import PropTypes from "prop-types"; +import { useSelector } from "react-redux"; +import { styles } from "../styles"; +import { onPress } from "../utils"; +import { colors } from "../../common"; +import { getModalStyles } from "../styles/styles"; + +function BaniTransitionModal({ shabadID, navigation, setModalVisible }) { + const [progress, setprogress] = useState(5); + const [modalVisible, toggleModal] = useState(false); + const baniList = useSelector((state) => state.baniList); + const isNightMode = useSelector((state) => state.isNightMode); + const { textStyle, backColor } = getModalStyles(isNightMode); + const currentBaniIndex = baniList.findIndex((item) => item.id === shabadID); + + const nextBani = currentBaniIndex !== -1 ? baniList[currentBaniIndex + 1] : null; + const { navigate } = navigation; + + useEffect(() => { + let progressInterval; // Declare progressInterval in the outer scope for better control + + if (modalVisible) { + progressInterval = setInterval(() => { + setprogress((prevprogress) => { + if (prevprogress <= 1) { + clearInterval(progressInterval); // Ensure progressInterval is cleared when condition is met + return prevprogress; // Return current value without decrement + } + return prevprogress - 1; // Decrease the progress value + }); + }, 1000); + } else { + clearInterval(progressInterval); // Clear progressInterval when modal is not visible + } + + return () => clearInterval(progressInterval); + }, [modalVisible]); + + useEffect(() => { + const showModalTimer = setTimeout(() => { + toggleModal(true); + }, 5000); // 5000 milliseconds equals 5 seconds + + return () => clearTimeout(showModalTimer); + }, []); + + useEffect(() => { + if (!modalVisible) { + return () => {}; + } + + const timer = setTimeout(() => { + onPress(nextBani, navigate); + toggleModal(false); + setModalVisible(false); + }, 5000); // 5000 milliseconds equals 5 seconds + + return () => clearTimeout(timer); + }, [modalVisible]); + + return ( + { + toggleModal(!modalVisible); + setModalVisible(!modalVisible); + }} + > + + + + {() => ( + + {progress} {/* Displays the percentage */} + + )} + + Next Bani + {nextBani.gurmukhi} + { + toggleModal(!modalVisible); + setModalVisible(!modalVisible); + }} + > + Stay on this bani + + + + + ); +} +BaniTransitionModal.propTypes = { + shabadID: PropTypes.number.isRequired, + navigation: PropTypes.shape().isRequired, + setModalVisible: PropTypes.func.isRequired, +}; + +export default BaniTransitionModal; diff --git a/src/ReaderScreen/reader.jsx b/src/ReaderScreen/reader.jsx index 20b80dee..d13d9cbd 100644 --- a/src/ReaderScreen/reader.jsx +++ b/src/ReaderScreen/reader.jsx @@ -9,11 +9,13 @@ import { Header, AutoScrollComponent, Footer } from "./components"; import { useBookmarks, useFetchShabad } from "./hooks"; import { styles, nightColors } from "./styles"; import { script, loadHTML } from "./utils"; +import BaniTransitionModal from "./components/nextBaniModal"; function Reader({ navigation, route }) { const webViewRef = useRef(null); const headerRef = useRef(null); const { webView } = styles; + const [isModalVisible, setModalVisible] = useState(false); const isNightMode = useSelector((state) => state.isNightMode); const bookmarkPosition = useSelector((state) => state.bookmarkPosition); @@ -92,6 +94,9 @@ function Reader({ navigation, route }) { // Handle save event, where event is expected to be "save-" const position = env.split("-")[1]; dispatch(actions.setPosition(position, shabadID)); + } else if (env.includes("end")) { + console.log("end"); + setModalVisible(true); } }; return ( @@ -151,6 +156,13 @@ function Reader({ navigation, route }) { {isAutoScroll && }