Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

All 1.3.1 dev #249

Merged
merged 34 commits into from
Jan 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
f324858
Issueid #231942 feat: audio delay right after completing level in pra…
ajinkyapandetekdi Dec 17, 2024
5a40064
Issueid #231942 feat: audio delay right after completing level in pra…
ajinkyapandetekdi Dec 17, 2024
a63217d
Merge pull request #231 from ajinkyapandetekdi/all-1.3-feedback-change
gouravmore Dec 17, 2024
c660319
Issueid #231949 feat: Show loading until next content is not loaded
ajinkyapandetekdi Dec 17, 2024
15b6002
Issueid #231949 feat: Show loading until next content is not loaded
ajinkyapandetekdi Dec 18, 2024
ce83cc2
Issueid #231949 feat: Show loading until next content is not loaded
ajinkyapandetekdi Dec 19, 2024
f29d6d3
Issueid #231949 feat: Show loading until next content is not loaded
ajinkyapandetekdi Dec 19, 2024
3a2f7fe
Merge pull request #236 from Sunbird-ALL/main
gouravmore Dec 19, 2024
06257e6
Merge remote-tracking branch 'origin/release-1.3-apicall-optimisation…
gouravmore Dec 19, 2024
6731267
Issueid #231949 feat: Show loading until next content is not loaded
ajinkyapandetekdi Dec 19, 2024
7fc647e
Issueid #231949 feat: Show loading until next content is not loaded
ajinkyapandetekdi Dec 19, 2024
588a916
Merge pull request #232 from ajinkyapandetekdi/all-1.3-feedback-change
gouravmore Dec 20, 2024
958c4ef
Issue #232165 fix: Performance improvements
gouravmore Dec 22, 2024
03895ff
Issue #232165 fix: ALL-1.3 Performance improvements
gouravmore Dec 22, 2024
5d738ca
#00000 zoom icon visble event after image is not there
ajinkyapandetekdi Dec 31, 2024
4c4d63d
Merge pull request #240 from Sunbird-ALL/release-1.3-apicall-optimisa…
gouravmore Jan 2, 2025
ecfc492
Update all-dev-tn.yml
gouravmore Jan 2, 2025
c0d07ce
Merge pull request #241 from Sunbird-ALL/all-1.3-feedback-change
gouravmore Jan 2, 2025
f1958f4
#00000 zoom icon visble event after image is not there
ajinkyapandetekdi Jan 2, 2025
b9648b7
Merge pull request #238 from ajinkyapandetekdi/all-1.3-zoom-model
gouravmore Jan 2, 2025
01c71e8
Merge pull request #239 from Sunbird-ALL/all-1.3-feedback-change
gouravmore Jan 2, 2025
afa7073
issueid #231942 fix: audio delay right after completing level in prac…
ajinkyapandetekdi Jan 3, 2025
2126a0b
issueid #231942 fix: audio delay right after completing level in prac…
ajinkyapandetekdi Jan 3, 2025
adcb97b
Merge pull request #242 from ajinkyapandetekdi/audio-chache
gouravmore Jan 3, 2025
6398cdb
Merge pull request #243 from Sunbird-ALL/all-1.3-feedback-change
gouravmore Jan 3, 2025
21a8e23
Issueid #232740 fix: While switching the iframe telemetry events are …
ajinkyapandetekdi Jan 3, 2025
d65b3cd
Merge pull request #244 from ajinkyapandetekdi/audio-chache
gouravmore Jan 3, 2025
f23c9a7
Merge pull request #245 from Sunbird-ALL/all-1.3-feedback-change
gouravmore Jan 3, 2025
17240c5
Issueid #232843 fix: Audio sync issue for low network - Showcase [liv…
ajinkyapandetekdi Jan 6, 2025
7e0e930
Merge pull request #246 from ajinkyapandetekdi/audio-issue-slow-net
gouravmore Jan 6, 2025
64624c4
Issueid #232821 fix: Unexpected API Call: /pointer/getPoints/43477152…
ajinkyapandetekdi Jan 6, 2025
7795733
Merge pull request #248 from ajinkyapandetekdi/audio-issue-slow-net
gouravmore Jan 6, 2025
c1e540e
Merge branch 'all-1.3.1-dev' into all-1.3-feedback-change
gouravmore Jan 6, 2025
2db6ecc
Merge pull request #247 from Sunbird-ALL/all-1.3-feedback-change
gouravmore Jan 6, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/all-dev-tn-new.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: ALL new tn dev Deployment
on:
push:
branches:
- all-1.3-tn-dev-hotfix
- all-1.3-feedback-change

jobs:
deploy:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/all-dev-tn.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: ALL tn dev Deployment
on:
push:
branches:
- all-1.2-tn-dev
- all-1.3.1-dev

jobs:
deploy:
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ lerna-debug.log*
.env
#build
build

*.env*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

Expand Down
16 changes: 15 additions & 1 deletion src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import FingerprintJS from "@fingerprintjs/fingerprintjs";
import routes from "./routes";
import { AppContent } from "./views";
import theme from "./assets/styles/theme";
import { initialize } from "./services/telementryService";
import { initialize, end } from "./services/telementryService";
import { startEvent } from "./services/callTelemetryIntract";
import "@project-sunbird/telemetry-sdk/index.js";
import { getParameter } from "./utils/constants";
Expand Down Expand Up @@ -72,6 +72,20 @@ const App = () => {
setFp();
}, []);

useEffect(() => {
const handleBeforeUnload = (event) => {
window.telemetry && window.telemetry.syncEvents && window.telemetry.syncEvents();
};

// Add the event listener
window.addEventListener("beforeunload", handleBeforeUnload);

// Cleanup the event listener on component unmount
return () => {
window.removeEventListener("beforeunload", handleBeforeUnload);
};
}, []);

useEffect(() => {
let virtualId;

Expand Down
12 changes: 7 additions & 5 deletions src/components/Assesment/Assesment.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -598,10 +598,12 @@ const Assesment = ({ discoverStart }) => {
}

localStorage.setItem("lang", lang || "ta");
const getPointersDetails = await axios.get(
`${process.env.REACT_APP_LEARNER_AI_ORCHESTRATION_HOST}/${config.URLS.GET_POINTER}/${usernameDetails?.data?.result?.virtualID}/${session_id}?language=${lang}`
);
setPoints(getPointersDetails?.data?.result?.totalLanguagePoints || 0);
if (process.env.REACT_APP_IS_APP_IFRAME !== "true" && localStorage.getItem("contentSessionId") !== null) {
const getPointersDetails = await axios.get(
`${process.env.REACT_APP_LEARNER_AI_ORCHESTRATION_HOST}/${config.URLS.GET_POINTER}/${usernameDetails?.data?.result?.virtualID}/${session_id}?language=${lang}`
);
setPoints(getPointersDetails?.data?.result?.totalLanguagePoints || 0);
}

dispatch(setVirtualId(usernameDetails?.data?.result?.virtualID));
})();
Expand Down Expand Up @@ -635,7 +637,7 @@ const Assesment = ({ discoverStart }) => {
localStorage.setItem("sessionId", sessionId);
}

if (virtualId) {
if (process.env.REACT_APP_IS_APP_IFRAME !== "true" && virtualId && localStorage.getItem("contentSessionId") !== null) {
const getPointersDetails = await axios.get(
`${process.env.REACT_APP_LEARNER_AI_ORCHESTRATION_HOST}/${config.URLS.GET_POINTER}/${virtualId}/${sessionId}?language=${lang}`
);
Expand Down
26 changes: 16 additions & 10 deletions src/components/AssesmentEnd/AssesmentEnd.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,23 @@ import { useEffect, useState } from "react";
import LevelCompleteAudio from "../../assets/audio/levelComplete.wav";
import { ProfileHeader } from "../Assesment/Assesment";
import desktopLevel5 from "../../assets/images/assesmentComplete.png";
import config from '../../utils/urlConstants.json';
import config from "../../utils/urlConstants.json";
import { uniqueId } from "../../services/utilService";
import usePreloadAudio from "../../hooks/usePreloadAudio";

const AssesmentEnd = () => {
const [shake, setShake] = useState(true);
const [level, setLevel] = useState("");
const [previousLevel, setPreviousLevel] = useState("");
const [points, setPoints] = useState(0);
const levelCompleteAudioSrc = usePreloadAudio(LevelCompleteAudio);

useEffect(() => {
(async () => {
let audio = new Audio(LevelCompleteAudio);
audio.play();
if (levelCompleteAudioSrc) {
let audio = new Audio(levelCompleteAudioSrc);
audio.play();
}
const virtualId = getLocalData("virtualId");
const lang = getLocalData("lang");
const previous_level = getLocalData("previous_level");
Expand All @@ -40,19 +44,21 @@ const AssesmentEnd = () => {
setLevel(data.data.milestone_level);
setLocalData("userLevel", data.data.milestone_level?.replace("m", ""));
let sessionId = getLocalData("sessionId");
if (!sessionId){
if (!sessionId) {
sessionId = uniqueId();
localStorage.setItem("sessionId", sessionId)
localStorage.setItem("sessionId", sessionId);
}
if (process.env.REACT_APP_IS_APP_IFRAME !== "true" && localStorage.getItem("contentSessionId") !== null) {
const getPointersDetails = await axios.get(
`${process.env.REACT_APP_LEARNER_AI_ORCHESTRATION_HOST}/${config.URLS.GET_POINTER}/${virtualId}/${sessionId}?language=${lang}`
);
setPoints(getPointersDetails?.data?.result?.totalLanguagePoints || 0);
}
const getPointersDetails = await axios.get(
`${process.env.REACT_APP_LEARNER_AI_ORCHESTRATION_HOST}/${config.URLS.GET_POINTER}/${virtualId}/${sessionId}?language=${lang}`
);
setPoints(getPointersDetails?.data?.result?.totalLanguagePoints || 0);
})();
setTimeout(() => {
setShake(false);
}, 4000);
}, []);
}, [levelCompleteAudioSrc]);

const navigate = useNavigate();
let newLevel = level.replace("m", "");
Expand Down
27 changes: 13 additions & 14 deletions src/components/DiscoverEnd/DiscoverEnd.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,9 @@ import back from "../../assets/images/back-arrow.svg";
import discoverEndLeft from "../../assets/images/discover-end-left.svg";
import discoverEndRight from "../../assets/images/discover-end-right.svg";
import textureImage from "../../assets/images/textureImage.png";
import {
LetsStart,
getLocalData,
setLocalData,
} from "../../utils/constants";
import config from '../../utils/urlConstants.json';
import { LetsStart, getLocalData, setLocalData } from "../../utils/constants";
import config from "../../utils/urlConstants.json";
import usePreloadAudio from "../../hooks/usePreloadAudio";

const sectionStyle = {
backgroundImage: `url(${textureImage})`,
Expand All @@ -32,12 +29,14 @@ const sectionStyle = {
const SpeakSentenceComponent = () => {
const [shake, setShake] = useState(true);
const [level, setLevel] = useState("");
const levelCompleteAudioSrc = usePreloadAudio(LevelCompleteAudio);

useEffect(() => {

(async () => {
let audio = new Audio(LevelCompleteAudio);
audio.play();
if (levelCompleteAudioSrc) {
let audio = new Audio(levelCompleteAudioSrc);
audio.play();
}
const virtualId = getLocalData("virtualId");
const lang = getLocalData("lang");
const getMilestoneDetails = await axios.get(
Expand All @@ -50,14 +49,14 @@ const SpeakSentenceComponent = () => {
setTimeout(() => {
setShake(false);
}, 4000);
}, []);
}, [levelCompleteAudioSrc]);

const handleProfileBack = () => {
try {
if (process.env.REACT_APP_IS_APP_IFRAME === 'true') {
navigate("/")
if (process.env.REACT_APP_IS_APP_IFRAME === "true") {
navigate("/");
} else {
navigate("/discover-start")
navigate("/discover-start");
}
} catch (error) {
console.error("Error posting message:", error);
Expand Down Expand Up @@ -132,7 +131,7 @@ const SpeakSentenceComponent = () => {
</Typography>

<Box
onClick={() => handleProfileBack()}
onClick={handleProfileBack}
sx={{
display: "flex",
justifyContent: "center",
Expand Down
65 changes: 35 additions & 30 deletions src/components/DiscoverSentance/DiscoverSentance.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import LevelCompleteAudio from "../../assets/audio/levelComplete.wav";
import config from "../../utils/urlConstants.json";
import { MessageDialog } from "../Assesment/Assesment";
import { Log } from "../../services/telementryService";
import usePreloadAudio from "../../hooks/usePreloadAudio";

const SpeakSentenceComponent = () => {
const [currentQuestion, setCurrentQuestion] = useState(0);
Expand All @@ -37,10 +38,13 @@ const SpeakSentenceComponent = () => {
const [totalSyllableCount, setTotalSyllableCount] = useState("");
const [isNextButtonCalled, setIsNextButtonCalled] = useState(false);

const levelCompleteAudioSrc = usePreloadAudio(LevelCompleteAudio);

const callConfettiAndPlay = () => {
let audio = new Audio(LevelCompleteAudio);
let audio = new Audio(levelCompleteAudioSrc);
audio.play();
callConfetti();
window.telemetry?.syncEvents && window.telemetry.syncEvents();
};

useEffect(() => {
Expand Down Expand Up @@ -118,35 +122,18 @@ const SpeakSentenceComponent = () => {
try {
const lang = getLocalData("lang");

if (!(localStorage.getItem("contentSessionId") !== null)) {
const pointsRes = await axios.post(
`${process.env.REACT_APP_LEARNER_AI_ORCHESTRATION_HOST}/${config.URLS.ADD_POINTER}`,
{
userId: localStorage.getItem("virtualId"),
sessionId: localStorage.getItem("sessionId"),
points: 1,
language: lang,
milestone: "m0",
}
);
setPoints(pointsRes?.data?.result?.totalLanguagePoints || 0);
} else {
send(1);
// setPoints(localStorage.getItem("currentLessonScoreCount"));
}

await axios.post(
`${process.env.REACT_APP_LEARNER_AI_ORCHESTRATION_HOST}/${config.URLS.ADD_LESSON}`,
{
userId: localStorage.getItem("virtualId"),
sessionId: localStorage.getItem("sessionId"),
milestone: `discoveryList/discovery/${currentCollectionId}`,
lesson: localStorage.getItem("storyTitle"),
progress: ((currentQuestion + 1) * 100) / questions.length,
language: lang,
milestoneLevel: "m0",
}
);
// await axios.post(
// `${process.env.REACT_APP_LEARNER_AI_ORCHESTRATION_HOST}/${config.URLS.ADD_LESSON}`,
// {
// userId: localStorage.getItem("virtualId"),
// sessionId: localStorage.getItem("sessionId"),
// milestone: `discoveryList/discovery/${currentCollectionId}`,
// lesson: localStorage.getItem("storyTitle"),
// progress: ((currentQuestion + 1) * 100) / questions.length,
// language: lang,
// milestoneLevel: "m0",
// }
// );

if (currentQuestion < questions.length - 1) {
setCurrentQuestion(currentQuestion + 1);
Expand All @@ -164,6 +151,24 @@ const SpeakSentenceComponent = () => {
language: localStorage.getItem("lang"),
}
);

if (!(localStorage.getItem("contentSessionId") !== null)) {
const pointsRes = await axios.post(
`${process.env.REACT_APP_LEARNER_AI_ORCHESTRATION_HOST}/${config.URLS.ADD_POINTER}`,
{
userId: localStorage.getItem("virtualId"),
sessionId: localStorage.getItem("sessionId"),
points: 1,
language: lang,
milestone: "m0",
}
);
setPoints(pointsRes?.data?.result?.totalLanguagePoints || 0);
} else {
send(5);
// setPoints(localStorage.getItem("currentLessonScoreCount"));
}

setInitialAssesment(false);
const { data: getSetData } = getSetResultRes;
const data = JSON.stringify(getSetData?.data);
Expand Down
68 changes: 57 additions & 11 deletions src/components/Layouts.jsx/MainLayout.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -163,27 +163,70 @@ const MainLayout = (props) => {
}
};

const [audioCache, setAudioCache] = useState({});

useEffect(() => {
const preloadAudio = async () => {
try {
const urls = [LevelCompleteAudio, gameLoseAudio];
const cache = {};

for (const url of urls) {
const response = await fetch(url);
const audioBlob = await response.blob();
const audioUrl = URL.createObjectURL(audioBlob);
cache[url] = audioUrl;
}

setAudioCache(cache);
} catch (error) {
console.error("Error preloading audio:", error);
}
};

preloadAudio();

// Cleanup cached audio URLs on unmount
return () => {
Object.values(audioCache).forEach((audioUrl) =>
URL.revokeObjectURL(audioUrl)
);
};
Comment on lines +190 to +194
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix potential memory leak due to stale audioCache in cleanup function

The cleanup function in the useEffect depends on audioCache, but since audioCache is not included in the dependency array, the cleanup function may reference a stale value of audioCache. This can lead to the preloaded audio URLs not being revoked properly, resulting in memory leaks.

Apply this diff to fix the issue by using a ref to store the audioCache, ensuring the cleanup function has access to the latest values:

+ const audioCacheRef = useRef({});
...
  useEffect(() => {
    const preloadAudio = async () => {
      try {
        const urls = [LevelCompleteAudio, gameLoseAudio];
        const cache = {};

        for (const url of urls) {
          const response = await fetch(url);
          const audioBlob = await response.blob();
          const audioUrl = URL.createObjectURL(audioBlob);
          cache[url] = audioUrl;
        }

        setAudioCache(cache);
+       audioCacheRef.current = cache;
      } catch (error) {
        console.error("Error preloading audio:", error);
      }
    };

    preloadAudio();

    // Cleanup cached audio URLs on unmount
    return () => {
-     Object.values(audioCache).forEach((audioUrl) =>
+     Object.values(audioCacheRef.current).forEach((audioUrl) =>
        URL.revokeObjectURL(audioUrl)
      );
    };
  }, []);

Committable suggestion skipped: line range outside the PR's diff.

}, []);

useEffect(() => {
if (isShowCase && gameOverData) {
setShake(gameOverData ? gameOverData.userWon : true);
setShake(gameOverData.userWon ?? true);

let audio = "";
let audioSrc;
if (gameOverData) {
audio = new Audio(
gameOverData.userWon ? LevelCompleteAudio : gameLoseAudio
);
audioSrc = gameOverData.userWon
? audioCache[LevelCompleteAudio]
: audioCache[gameLoseAudio];
} else {
audioSrc = audioCache[LevelCompleteAudio];
}

if (audioSrc) {
const audio = new Audio(audioSrc);
audio.play().catch((error) => {
console.error("Error playing audio:", error);
});

if (!gameOverData?.userWon) {
callConfettiSnow();
}
} else {
audio = new Audio(LevelCompleteAudio);
}
audio.play();
setTimeout(() => {

const shakeTimeout = setTimeout(() => {
setShake(false);
}, 4000);

return () => {
clearTimeout(shakeTimeout);
};
}
}, [startShowCase, isShowCase, gameOverData]);
}, [startShowCase, isShowCase, gameOverData, audioCache]);

let currentPracticeStep = progressData?.currentPracticeStep;
let currentPracticeProgress = progressData?.currentPracticeProgress || 0;
Expand Down Expand Up @@ -752,7 +795,7 @@ const MainLayout = (props) => {
>
<Stack justifyContent="center" alignItems="center">
<img
src={gameLost}
src={`https://raw.githubusercontent.com/Sunbird-ALL/all-learner-ai-app/refs/heads/all-1.3/src/assets/images/gameLost.svg`}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Replace hardcoded image URL with imported asset

The src attribute is using a hardcoded URL pointing to GitHub's raw content, which is not optimal for production use. This can lead to performance issues and potential broken links if the repository changes.

Apply this diff to replace the hardcoded URL with an imported asset:

+ import gameLost from "../../assets/images/gameLost.svg";
...
- src={`https://raw.githubusercontent.com/Sunbird-ALL/all-learner-ai-app/refs/heads/all-1.3/src/assets/images/gameLost.svg`}
+ src={gameLost}

Committable suggestion skipped: line range outside the PR's diff.

alt="gameLost"
style={{ height: 340 }}
/>
Expand Down Expand Up @@ -1196,6 +1239,9 @@ MainLayout.propTypes = {
storedData: PropTypes.array,
resetStoredData: PropTypes.func,
pageName: PropTypes.string,
gameOverData: PropTypes.shape({
userWon: PropTypes.bool,
}),
};

export default MainLayout;
Loading
Loading