Skip to content
37 changes: 34 additions & 3 deletions src/components/Assesment/Assesment.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import panda from "../../assets/images/panda.svg";
import cryPanda from "../../assets/images/cryPanda.svg";
import { uniqueId } from "../../services/utilService";
import { end } from "../../services/telementryService";
import { useMediaCache } from "../Hooks/useMediaCache";

export const LanguageModal = ({ lang, setLang, setOpenLangModal }) => {
const [selectedLang, setSelectedLang] = useState(lang);
Expand Down Expand Up @@ -552,6 +553,36 @@ const Assesment = ({ discoverStart }) => {
username = userDetails.student_name;
setLocalData("profileName", username);
}

const { cacheMedia } = useMediaCache();
const [mediaUrls, setMediaUrls] = useState({});
const mediaFiles = [
{ key: "desktopLevel1", url: desktopLevel1 },
{ key: "desktopLevel2", url: desktopLevel2 },
{ key: "desktopLevel3", url: desktopLevel3 },
{ key: "desktopLevel4", url: desktopLevel4 },
{ key: "desktopLevel5", url: desktopLevel5 },
{ key: "desktopLevel6", url: desktopLevel6 },
{ key: "desktopLevel7", url: desktopLevel7 },
{ key: "desktopLevel8", url: desktopLevel8 },
{ key: "desktopLevel9", url: desktopLevel9 },
{ key: "assessmentBackground", url: assessmentBackground },
{ key: "HelpLogo", url: HelpLogo },
];

useEffect(() => {
const cacheAllMedia = async () => {
const urls = {};
for (const media of mediaFiles) {
const cachedUrl = await cacheMedia(media.key, media.url);
urls[media.key] = cachedUrl;
}
setMediaUrls(urls);
};

cacheAllMedia();
}, []);

// const [searchParams, setSearchParams] = useSearchParams();
// const [profileName, setProfileName] = useState(username);
const [openMessageDialog, setOpenMessageDialog] = useState("");
Expand Down Expand Up @@ -714,7 +745,7 @@ const Assesment = ({ discoverStart }) => {
const sectionStyle = {
width: "100vw",
height: "100vh",
backgroundImage: `url(${images?.[`desktopLevel${level || 1}`]})`,
backgroundImage: `url(${mediaUrls?.desktopLevel1})`,
backgroundRepeat: "round",
backgroundSize: "auto",
position: "relative",
Expand Down Expand Up @@ -803,7 +834,7 @@ const Assesment = ({ discoverStart }) => {
<MainLayout
showNext={false}
showTimer={false}
cardBackground={assessmentBackground}
cardBackground={mediaUrls?.assessmentBackground}
backgroundImage={practicebg}
{...{
setOpenLangModal,
Expand Down Expand Up @@ -865,7 +896,7 @@ const Assesment = ({ discoverStart }) => {
textAlign: "center",
}}
>
<img src={HelpLogo} alt="help_video_link" />
<img src={mediaUrls?.HelpLogo} alt="help_video_link" />
</Box>
)}
<Box
Expand Down
31 changes: 27 additions & 4 deletions src/components/AssesmentEnd/AssesmentEnd.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ 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";

const AssesmentEnd = () => {
Expand All @@ -25,9 +25,32 @@ const AssesmentEnd = () => {
const [previousLevel, setPreviousLevel] = useState("");
const [points, setPoints] = useState(0);

const [audioSrc, setAudioSrc] = useState(null);

useEffect(() => {
const preloadAudio = async () => {
try {
const response = await fetch(LevelCompleteAudio);
const audioBlob = await response.blob();
const audioUrl = URL.createObjectURL(audioBlob);
setAudioSrc(audioUrl);
} catch (error) {
console.error("Error loading audio:", error);
}
};
preloadAudio();

return () => {
// Cleanup blob URL to prevent memory leaks
if (audioSrc) {
URL.revokeObjectURL(audioSrc);
}
};
}, []);

useEffect(() => {
(async () => {
let audio = new Audio(LevelCompleteAudio);
let audio = new Audio(audioSrc);
audio.play();
const virtualId = getLocalData("virtualId");
const lang = getLocalData("lang");
Expand All @@ -40,9 +63,9 @@ 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);
}
const getPointersDetails = await axios.get(
`${process.env.REACT_APP_LEARNER_AI_ORCHESTRATION_HOST}/${config.URLS.GET_POINTER}/${virtualId}/${sessionId}?language=${lang}`
Expand Down
48 changes: 34 additions & 14 deletions src/components/DiscoverEnd/DiscoverEnd.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,8 @@ 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";

const sectionStyle = {
backgroundImage: `url(${textureImage})`,
Expand All @@ -32,12 +28,36 @@ const sectionStyle = {
const SpeakSentenceComponent = () => {
const [shake, setShake] = useState(true);
const [level, setLevel] = useState("");
const [audioSrc, setAudioSrc] = useState(null);

useEffect(() => {
const preloadAudio = async () => {
try {
const response = await fetch(LevelCompleteAudio);
const audioBlob = await response.blob();
const audioUrl = URL.createObjectURL(audioBlob);
setAudioSrc(audioUrl);
} catch (error) {
console.error("Error loading audio:", error);
}
};
preloadAudio();

return () => {
// Cleanup blob URL to prevent memory leaks
if (audioSrc) {
URL.revokeObjectURL(audioSrc);
}
};
}, []);

useEffect(() => {

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

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 +152,7 @@ const SpeakSentenceComponent = () => {
</Typography>

<Box
onClick={() => handleProfileBack()}
onClick={() => handleProfileBack()}
sx={{
display: "flex",
justifyContent: "center",
Expand Down
29 changes: 28 additions & 1 deletion src/components/DiscoverSentance/DiscoverSentance.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,36 @@ const SpeakSentenceComponent = () => {
const [openMessageDialog, setOpenMessageDialog] = useState("");
const [totalSyllableCount, setTotalSyllableCount] = useState("");
const [isNextButtonCalled, setIsNextButtonCalled] = useState(false);
const [audioSrc, setAudioSrc] = useState(null);

useEffect(() => {
const preloadAudio = async () => {
try {
const response = await fetch(LevelCompleteAudio);
const audioBlob = await response.blob();
const audioUrl = URL.createObjectURL(audioBlob);
setAudioSrc(audioUrl);
} catch (error) {
console.error("Error loading audio:", error);
}
};
preloadAudio();

return () => {
// Cleanup blob URL to prevent memory leaks
if (audioSrc) {
URL.revokeObjectURL(audioSrc);
}
};
}, []);

const callConfettiAndPlay = () => {
let audio = new Audio(LevelCompleteAudio);
let audio;
if (audioSrc) {
audio = new Audio(audioSrc);
} else {
audio = new Audio(LevelCompleteAudio);
}
audio.play();
callConfetti();
};
Expand Down
82 changes: 82 additions & 0 deletions src/components/Hooks/useMediaCache.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { useEffect } from "react";

export function useMediaCache(dbName = "MediaCacheDB", storeName = "media") {
useEffect(() => {
// Initialize IndexedDB
const openDB = indexedDB.open(dbName, 1);
openDB.onupgradeneeded = () => {
const db = openDB.result;
if (!db.objectStoreNames.contains(storeName)) {
db.createObjectStore(storeName, { keyPath: "key" }); // Ensure keyPath matches the stored object structure
}
};

openDB.onerror = (e) => {
console.error("IndexedDB initialization error:", e.target.error);
};
}, [dbName, storeName]);

// Save media to IndexedDB
const saveMedia = async (key, blob) => {
return new Promise((resolve, reject) => {
const openDB = indexedDB.open(dbName, 1);
openDB.onsuccess = () => {
const db = openDB.result;
const tx = db.transaction(storeName, "readwrite");
const store = tx.objectStore(storeName);

// Put media object into the store
const putRequest = store.put({ key, blob });

putRequest.onsuccess = () => resolve(true);
putRequest.onerror = () => reject(putRequest.error);
tx.oncomplete = () => db.close(); // Close the connection
};

openDB.onerror = () => reject(openDB.error);
});
};

// Fetch media from IndexedDB
const getMedia = async (key) => {
return new Promise((resolve, reject) => {
const openDB = indexedDB.open(dbName, 1);
openDB.onsuccess = () => {
const db = openDB.result;
const tx = db.transaction(storeName, "readonly");
const store = tx.objectStore(storeName);

// Get the media object
const getRequest = store.get(key);

getRequest.onsuccess = () => resolve(getRequest.result?.blob || null);
getRequest.onerror = () => reject(getRequest.error);
tx.oncomplete = () => db.close(); // Close the connection
};

openDB.onerror = () => reject(openDB.error);
});
};

// Cache media
const cacheMedia = async (key, url) => {
try {
const cachedBlob = await getMedia(key);
if (cachedBlob) {
// console.log(`Media for key "${key}" found in cache.`);
return URL.createObjectURL(cachedBlob);
} else {
console.log(`Fetching media for key "${key}" from URL.`);
const response = await fetch(url);
const blob = await response.blob();
await saveMedia(key, blob);
return URL.createObjectURL(blob);
}
} catch (error) {
console.error(`Error caching media for key "${key}":`, error);
throw error;
}
};

return { cacheMedia };
}
Loading