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

IssueId #217903 feat: Implementing New Mechanics with Image Game #44

Open
wants to merge 49 commits into
base: all-1.1
Choose a base branch
from

Conversation

ajinkyapandetekdi
Copy link

@ajinkyapandetekdi ajinkyapandetekdi commented May 2, 2024

Summary by CodeRabbit

  • New Features

    • Introduced voice analysis and game progression features in the practice component.
    • Enhanced visual presentation with styled components and dynamic content display.
    • Added support for offline language models and improved loading indicators.
  • UI Updates

    • Restructured card layout, modified image rendering, and updated button styles for a better user experience.
  • Functionality Improvements

    • Added a fetchImage function for conditional image source setting.
    • Enhanced audio processing capabilities and error handling for improved user feedback.

Copy link

coderabbitai bot commented May 2, 2024

Walkthrough

The recent updates significantly enhance the Mechanics2 component by adding new functionalities, props, and user interface improvements, focusing on voice analysis and game progression features. Additionally, logic restructuring, state management updates, and refined visual presentations have been implemented. Enhancements in the VoiceAnalyser.js file support these improvements, along with modifications across various components and configurations for better performance and integration.

Changes

File Path Change Summary
src/components/Practice/Mechanics2.jsx Added new props and state handlers, improved image handling with fetchImage, enhanced rendering logic for user engagement, and integrated the VoiceAnalyser component.
src/utils/VoiceAnalyser.js Enhanced audio processing functionality, improved error handling, and updated integration with AWS S3 for audio file uploads.
.github/workflows/*.yml Renamed environment variables and added new ones for AWS integration and offline language processing across multiple workflow files.
package.json Added multiple dependencies including @ffmpeg/ffmpeg and ESLint plugins, and performed general cleanup in devDependencies.
public/index.html Introduced new JavaScript files for enhanced audio processing capabilities.
public/whisper.wasm/* Added WASM-related functionality and error handling in new JavaScript files for audio processing.
src/components/Assesment/Assesment.jsx Enhanced LanguageModal and Assesment components for better control over loading states and offline model management.
src/config/awsS3.js Enabled AWS S3 interaction by initializing and exporting S3Client.
src/routes/index.js Standardized routing logic with consistent quotation marks.
src/setupProxy.js Defined a middleware function for setting security headers in the Express app.
src/utils/AudioCompare.js Integrated a loading indicator for audio processing functionality.
src/utils/constants.js Standardized level criteria and expanded language support including offline capabilities.
src/utils/useFFmpeg.jsx Introduced a custom React hook for FFmpeg library integration.
src/views/AppContent/AppContent.jsx Minor change in how virtualId is retrieved from localStorage.
src/views/Practice/Practice.jsx Updated API request logic based on the mechanism state for better filtering.

Sequence Diagrams

New Mechanics2 Component Flow

sequenceDiagram
    participant User
    participant Mechanics2
    participant VoiceAnalyser
    participant GameProgression
    participant UI

    User->>Mechanics2: Interact with UI
    Mechanics2->>VoiceAnalyser: Analyze Voice Input
    VoiceAnalyser-->>Mechanics2: Return Analyzed Data
    Mechanics2->>GameProgression: Update Game State
    GameProgression-->>Mechanics2: Return Game State
    Mechanics2->>UI: Update UI Components
    UI-->>User: Display Updated UI
Loading

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Outside diff range and nitpick comments (3)
src/views/Practice/Practice.jsx (3)

Line range hint 62-63: Consider simplifying the boolean expressions.

- let userWon = isUserPass ? true : false;
- const meetsFluencyCriteria = livesData.meetsFluencyCriteria ? true : false;
+ let userWon = !!isUserPass;
+ const meetsFluencyCriteria = !!livesData.meetsFluencyCriteria;

The use of ternary operators here is unnecessary. You can directly convert the values to booleans using the double NOT operator (!!) for clarity and conciseness.


Line range hint 646-692: Remove unnecessary else clauses to simplify control flow.

- else {
-   // code
- }

Since the preceding blocks in these cases end with return, else is redundant and can be omitted to reduce nesting and improve code readability.

Also applies to: 670-689, 757-908, 803-908, 846-908, 854-908, 862-908, 865-908


Line range hint 404-404: Correct the misuse of const for variables that are reassigned.

- const sessionId = getLocalData("sessionId");
+ let sessionId = getLocalData("sessionId");

The variable sessionId is reassigned later, so it should be declared with let instead of const to avoid runtime errors.

Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 07379e5 and 9fae96a.

Files selected for processing (2)
  • src/utils/constants.js (2 hunks)
  • src/views/Practice/Practice.jsx (2 hunks)
Files not reviewed due to errors (1)
  • src/utils/constants.js (no review received)
Additional context used
Biome
src/views/Practice/Practice.jsx

[error] 62-62: Unnecessary use of boolean literals in conditional expression. (lint/complexity/noUselessTernary)

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with


[error] 63-63: Unnecessary use of boolean literals in conditional expression. (lint/complexity/noUselessTernary)

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with


[error] 581-583: This function expression can be turned into an arrow function. (lint/complexity/useArrowFunction)

Function expressions that don't use this can be turned into arrow functions.
Safe fix: Use an arrow function instead.


[error] 646-692: This else clause can be omitted because previous branches break early. (lint/style/noUselessElse)

Unsafe fix: Omit the else clause.


[error] 670-689: This else clause can be omitted because previous branches break early. (lint/style/noUselessElse)

Unsafe fix: Omit the else clause.


[error] 757-908: This else clause can be omitted because previous branches break early. (lint/style/noUselessElse)

Unsafe fix: Omit the else clause.


[error] 803-908: This else clause can be omitted because previous branches break early. (lint/style/noUselessElse)


[error] 846-908: This else clause can be omitted because previous branches break early. (lint/style/noUselessElse)


[error] 854-908: This else clause can be omitted because previous branches break early. (lint/style/noUselessElse)


[error] 862-908: This else clause can be omitted because previous branches break early. (lint/style/noUselessElse)


[error] 865-908: This else clause can be omitted because previous branches break early. (lint/style/noUselessElse)


[error] 404-404: Can't assign sessionId because it's a constant (lint/correctness/noConstAssign)

This is where the variable is defined as constant

Unsafe fix: Replace const with let if you assign it to a new value.

Additional comments not posted (1)
src/views/Practice/Practice.jsx (1)

Line range hint 581-583: Convert function expressions to arrow functions for better readability.
[REFACTOR_SUGGESTion]

- const isFirefox = function() {
-   return typeof navigator !== 'undefined' && navigator.userAgent.toLowerCase().includes('firefox');
- };
+ const isFirefox = () => typeof navigator !== 'undefined' && navigator.userAgent.toLowerCase().includes('firefox');

This change enhances readability and aligns with modern JavaScript practices.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Outside diff range and nitpick comments (2)
src/components/Practice/Mechanics2.jsx (1)

10-49: The addition of numerous props enhances the component's functionality but also significantly increases its complexity. Consider using a context or a custom hook to manage state if the prop list continues to grow, to improve maintainability.

src/utils/VoiceAnalyser.js (1)

Line range hint 180-187: The function expressions within the useEffect hooks should be converted to arrow functions for better readability and to align with modern JavaScript standards.

- function hasVoice(base64String) {
+ const hasVoice = (base64String) => {
Tools
Biome

[error] 90-96: This var should be declared at the root of the enclosing function. (lint/correctness/noInnerDeclarations)

The var is accessible in the whole body of the enclosing function.
To avoid confusion, it should be declared at the root of the enclosing function.

Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 9fae96a and 56e956a.

Files selected for processing (2)
  • src/components/Practice/Mechanics2.jsx (1 hunks)
  • src/utils/VoiceAnalyser.js (1 hunks)
Additional context used
Biome
src/utils/VoiceAnalyser.js

[error] 90-96: This var should be declared at the root of the enclosing function. (lint/correctness/noInnerDeclarations)

The var is accessible in the whole body of the enclosing function.
To avoid confusion, it should be declared at the root of the enclosing function.


[error] 113-116: This function expression can be turned into an arrow function. (lint/complexity/useArrowFunction)

Function expressions that don't use this can be turned into arrow functions.
Safe fix: Use an arrow function instead.


[error] 177-177: This var should be declared at the root of the enclosing function. (lint/correctness/noInnerDeclarations)

The var is accessible in the whole body of the enclosing function.
To avoid confusion, it should be declared at the root of the enclosing function.


[error] 183-186: This function expression can be turned into an arrow function. (lint/complexity/useArrowFunction)

Function expressions that don't use this can be turned into arrow functions.
Safe fix: Use an arrow function instead.


[error] 180-187: This function expression can be turned into an arrow function. (lint/complexity/useArrowFunction)

Function expressions that don't use this can be turned into arrow functions.
Safe fix: Use an arrow function instead.


[error] 364-364: This var should be declared at the root of the enclosing function. (lint/correctness/noInnerDeclarations)

The var is accessible in the whole body of the enclosing function.
To avoid confusion, it should be declared at the root of the enclosing function.


[error] 580-598: This else clause can be omitted because previous branches break early. (lint/style/noUselessElse)

Unsafe fix: Omit the else clause.


[error] 365-365: Unexpected constant condition. (lint/correctness/noConstantCondition)

Additional comments not posted (4)
src/components/Practice/Mechanics2.jsx (3)

2-7: The addition of imports Confetti, useState, VoiceAnalyser, and MainLayout aligns with the new functionalities described in the PR. Ensure that these modules are properly installed and saved in your package.json.


51-51: Introduction of the shake state using useState is a good practice for managing component-specific states. Ensure that this state variable is used effectively within the component.


53-55: The fetchImage function is a neat abstraction for fetching image URLs. However, ensure that the environment variable REACT_APP_AWS_S3_BUCKET_CONTENT_URL is correctly set in your environments to avoid runtime errors.

Verification successful

The environment variable REACT_APP_AWS_S3_BUCKET_CONTENT_URL is correctly set in the .env file.

  • The variable is defined as REACT_APP_AWS_S3_BUCKET_CONTENT_URL=https://all-dev-content-service.s3.ap-south-1.amazonaws.com.
Scripts executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify the environment variable for AWS S3 bucket URL is set.

# Test: Search for the environment variable in .env files. Expect: The variable should be present.
rg --type dotenv 'REACT_APP_AWS_S3_BUCKET_CONTENT_URL'

Length of output: 85



Script:

#!/bin/bash
# Description: Verify the environment variable for AWS S3 bucket URL is set.

# Test: Search for the environment variable in common environment configuration files.
rg 'REACT_APP_AWS_S3_BUCKET_CONTENT_URL' .env .env.* || echo "Variable not found in .env files"

Length of output: 277

src/utils/VoiceAnalyser.js (1)

85-94: Ensure that the audio file paths constructed dynamically are correctly formed and that the files are accessible at those paths to prevent runtime errors.

Comment on lines 81 to 309
</Box>
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "center",
width: "33%",
}}
>
<Typography
variant="h1"
component="h1"
sx={{
textAlign: "center",
fontSize: "50px",
fontWeight: 700,
fontFamily: "Quicksand",
marginTop: "40px",
marginBottom: "20px",
color: "#6CC227",
}}
>
Good Job.!
</Typography>
<Typography
variant="h2"
component="h2"
sx={{
textAlign: "center",
fontSize: "30px",
fontWeight: 600,
fontFamily: "Quicksand",
lineHeight: "40px",
marginBottom: "20px",
}}
>
You have good Pronunciation Skills.
</Typography>
{words && (
<Typography
variant="h3"
component="h3"
sx={{
textAlign: "center",
fontSize: "40px",
fontWeight: 700,
fontFamily: "Quicksand",
lineHeight: "40px",
marginBottom: "20px",
}}
>
{words}
</Typography>
)}
</Box>
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "center",
width: "33%",
}}
>
<img
src={discoverEndRight}
alt="timer"
className={shake && "shakeImage"}
loading="lazy"
/>
</Box>
</Box>
<Box sx={{ display: "flex", justifyContent: "center" }}>
<VoiceAnalyser
setVoiceText={setVoiceText}
setRecordedAudio={setRecordedAudio}
setVoiceAnimate={setVoiceAnimate}
storyLine={storyLine}
dontShowListen={type === "image" || isDiscover}
shake={shake || false}
originalText={words}
mechanism={'flashcard'}
{...{
contentId,
contentType,
currentLine: currentStep - 1,
playTeacherAudio,
callUpdateLearner,
isShowCase,
setEnableNext,
livesData,
setLivesData,
setOpenMessageDialog,
}}
/>
</Box>
</CardContent>
</Card>
)}
</Box>
</MainLayout>
Copy link

Choose a reason for hiding this comment

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

Tip

Codebase Verification

The verification process has revealed that while there are media queries present in the global CSS and SCSS files, the specific hardcoded values 70vw and 70vh in Mechanics2.jsx are not directly addressed or overridden by these media queries.

To ensure responsive design, it's crucial to either update these hardcoded values within the component to use relative units that adapt to different screen sizes or to implement specific media queries for the Mechanics2.jsx component.

  • Update the hardcoded values 70vw and 70vh in Mechanics2.jsx to use relative units or media queries for better responsiveness.
Analysis chain

The restructuring of the UI to accommodate new functionalities and props is well done. However, ensure that the responsive design is maintained across different devices, especially with hardcoded values like 70vw and 70vh for card dimensions.

Scripts executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Check for CSS files to ensure responsiveness is handled.

# Test: Search for media queries in CSS files. Expect: Relevant media queries should be present.
rg --type css '@media'

Length of output: 401



Script:

#!/bin/bash
# Description: Check for the usage of Mechanics2.jsx and its parent components to see if they link to CSS or SCSS files with media queries.

# Find the file path of Mechanics2.jsx
mechanics2_file_path=$(fd Mechanics2.jsx)

# Search for imports of CSS/SCSS in Mechanics2.jsx
rg --type js 'import.*\.(css|scss)' $mechanics2_file_path

# Search for the usage of Mechanics2 component in the codebase
mechanics2_usage=$(rg --files-with-matches "Mechanics2" --type js)

# Check if parent components import CSS/SCSS files with media queries
for file in $mechanics2_usage; do
  rg --type js 'import.*\.(css|scss)' $file
done

# Search for hardcoded values 70vw and 70vh in the codebase
rg '70vw|70vh'

Length of output: 949



Script:

#!/bin/bash
# Description: Check for global CSS or SCSS files imported in the main application file and verify media queries.

# Find the main application file (commonly index.js or App.js)
main_app_file=$(fd -e js -e jsx -e ts -e tsx 'index|App')

# Search for imports of CSS/SCSS in the main application file
for file in $main_app_file; do
  rg --type js 'import.*\.(css|scss)' $file
done

# Check for media queries in the imported CSS/SCSS files
rg --type css '@media'

Length of output: 3230

Comment on lines +85 to +94
let mechanism;
if(props.mechanism){
mechanism = props.mechanism
}
try {
var audio = new Audio(
recordedAudio
? recordedAudio
: props.contentId
? `${process.env.REACT_APP_AWS_S3_BUCKET_CONTENT_URL}/all-audio-files/${lang}/${props.contentId}.wav`
? `${process.env.REACT_APP_AWS_S3_BUCKET_CONTENT_URL}/all-audio-files/${lang}/${mechanism? "image/":""}${props.contentId}.wav`
Copy link

Choose a reason for hiding this comment

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

The conditional check for props.mechanism is a good addition for flexibility. However, consider refactoring the playAudio function to use an arrow function for consistency and to adhere to modern JavaScript practices.

- function playAudio(val) {
+ const playAudio = (val) => {

Committable suggestion was skipped due to low confidence.

ajinkyapandetekdi and others added 23 commits July 12, 2024 12:40
…line

IssueId #223070 feat: Implementation & integration with current code
Task #223066 feat: Added wasm configuation and tested
…line

IssueId #223067 feat: Load model and store it to indexdb for caching
Task #223068 Get Audio data from microphone and send it whisper cpp function
ajinkyapandetekdi and others added 23 commits July 19, 2024 09:22
Task #223069 & #223071 Fuzzball js integration done and added new fields in API for offline call
…line

Issueid #223075 feat: Apply Loader till model is download and stored …
…line

IssueId #223082 Create Log Out Button in Test-Rig [React]
…line

issueid #223924 fix: whisper model is not loading properly in offline-model
Copy link

sonarcloud bot commented Jul 30, 2024

Quality Gate Failed Quality Gate failed

Failed conditions
11.1% Duplication on New Code (required ≤ 3%)

See analysis details on SonarCloud

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 21

Outside diff range, codebase verification and nitpick comments (13)
public/whisper.wasm/initWhisper.js (1)

12-12: Add a comment explaining the purpose of the immediate invocation.

Providing a comment will help future developers understand the reason behind the immediate invocation of loadWhisperModule.

- loadWhisperModule();
+ // Immediately load the WASM module upon script execution
+ loadWhisperModule();
src/components/CommonComponent/ProgressOverlay.jsx (2)

1-2: Consider optimizing imports.

If Box, CircularProgress, LinearProgress, and Typography are the only components used from @mui/material, consider importing them directly to reduce bundle size.

- import { Box, CircularProgress, LinearProgress, Typography } from "@mui/material";
+ import Box from "@mui/material/Box";
+ import CircularProgress from "@mui/material/CircularProgress";
+ import LinearProgress from "@mui/material/LinearProgress";
+ import Typography from "@mui/material/Typography";

46-46: Ensure accessibility for the image.

Add an alt attribute to the img tag to improve accessibility.

- <img style={{height:'57px', paddingBottom:'10px'}} src={RunnungBoy}/>
+ <img style={{height:'57px', paddingBottom:'10px'}} src={RunnungBoy} alt="Running boy"/>
src/utils/AudioCompare.js (3)

1-6: Optimize imports.

Consider importing only the necessary components from @mui/material to reduce bundle size.

- import { Box, CircularProgress } from "@mui/material";
+ import Box from "@mui/material/Box";
+ import CircularProgress from "@mui/material/CircularProgress";

14-14: Improve state variable naming.

The state variable loader could be more descriptively named to indicate its purpose, such as isLoading.

- const [loader,setLoader] = useState(false);
+ const [isLoading, setIsLoading] = useState(false);

94-98: Enhance loading spinner accessibility.

Consider adding aria-label to the CircularProgress component for better accessibility.

- <CircularProgress size="3rem" sx={{ color: "#E15404" }} />
+ <CircularProgress size="3rem" sx={{ color: "#E15404" }} aria-label="Loading" />
src/components/Practice/Mechanics2.jsx (2)

1-7: Optimize imports.

Consider importing only the necessary components from @mui/material to reduce bundle size.

- import { Box, Card, CardContent, Typography } from "@mui/material";
+ import Box from "@mui/material/Box";
+ import Card from "@mui/material/Card";
+ import CardContent from "@mui/material/CardContent";
+ import Typography from "@mui/material/Typography";

265-290: Ensure correct prop types for VoiceAnalyser.

The VoiceAnalyser component does not currently have defined prop types or TypeScript interfaces. To ensure type safety and proper usage of props, please add prop types to the VoiceAnalyser component. This will help maintain the robustness of the component and prevent potential bugs due to incorrect prop usage.

  • Add propTypes to VoiceAnalyser for the following props:
    • originalText
    • contentId
    • mechanism
    • setVoiceAnimate
    • isNextButtonCalled
    • setIsNextButtonCalled
    • setVoiceText
    • setRecordedAudio
    • setEnableNext
    • showOnlyListen
    • setOpenMessageDialog
    • and any other props used within the component.
Analysis chain

Ensure correct prop types for VoiceAnalyser.

Ensure that all props passed to VoiceAnalyser have the correct types and default values if necessary.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the prop types for `VoiceAnalyser`.

# Test: Search for the prop types definition in `VoiceAnalyser`. Expect: Correct prop types.
rg --type js 'VoiceAnalyser.propTypes'

Length of output: 38


Script:

#!/bin/bash
# Description: Verify the prop types or TypeScript interfaces for `VoiceAnalyser`.

# Search for the `VoiceAnalyser` component definition.
rg --type js 'function VoiceAnalyser' -A 10

# Search for any prop types or TypeScript interfaces associated with `VoiceAnalyser`.
rg --type js 'VoiceAnalyser.propTypes' -A 10
rg --type js 'interface VoiceAnalyserProps' -A 10

Length of output: 1040


Script:

#!/bin/bash
# Description: Verify the usage of props in the `VoiceAnalyser` component to ensure they are handled correctly.

# Search for all prop usages within the `VoiceAnalyser` component.
rg --type js 'props\.' src/utils/VoiceAnalyser.js -A 3

Length of output: 3063

src/utils/VoiceAnalyser.js (3)

Line range hint 1-38:
Optimize import paths.

The imports from node_modules can be simplified to improve readability.

- import { Box, CircularProgress } from "../../node_modules/@mui/material/index";
- import axios from "../../node_modules/axios/index";
- import calcCER from "../../node_modules/character-error-rate/index";
+ import { Box, CircularProgress } from "@mui/material";
+ import axios from "axios";
+ import calcCER from "character-error-rate";

Line range hint 488-670:
Improve error handling in fetchASROutput.

The function should handle errors more gracefully by providing user feedback instead of just logging errors.

- console.log("err", error);
+ setApiResponse("Error fetching ASR output");
+ console.error("Error fetching ASR output:", error);

Line range hint 396-418:
Ensure proper cleanup in useEffect.

The useEffect hook should clean up the XMLHttpRequest to prevent memory leaks.

+ return () => {
+   request.abort();
+ };
src/components/Assesment/Assesment.jsx (2)

Line range hint 693-911:
Ensure proper error handling in loadModel.

The loadModel function should handle errors more gracefully by providing user feedback instead of just logging errors.

- console.log(error.message);
+ setOpenMessageDialog({ message: "Error loading model", isError: true });
+ console.error("Error loading model:", error.message);

Line range hint 693-911:
Ensure proper error handling in useEffect.

The useEffect hook should handle errors more gracefully by providing user feedback instead of just logging errors.

- console.log("err", error);
+ setOpenMessageDialog({ message: "Error fetching details", isError: true });
+ console.error("Error fetching details:", error);
Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 56e956a and 5ae94ca.

Files ignored due to path filters (2)
  • public/models/ggml-model-whisper-base.en-q5_1.bin is excluded by !**/*.bin
  • src/assets/images/boy-running.gif is excluded by !**/*.gif
Files selected for processing (20)
  • .github/workflows/all-app-sandbox.yml (1 hunks)
  • .github/workflows/all-dev-rig.yml (2 hunks)
  • .github/workflows/all-prod-rig.yml (1 hunks)
  • package.json (4 hunks)
  • public/index.html (1 hunks)
  • public/whisper.wasm/initWhisper.js (1 hunks)
  • public/whisper.wasm/libstream.worker.js (1 hunks)
  • src/components/Assesment/Assesment.jsx (11 hunks)
  • src/components/CommonComponent/CircularProgressOverlay.jsx (1 hunks)
  • src/components/CommonComponent/ProgressOverlay.jsx (1 hunks)
  • src/components/Practice/Mechanics2.jsx (1 hunks)
  • src/config/awsS3.js (1 hunks)
  • src/routes/index.js (1 hunks)
  • src/setupProxy.js (1 hunks)
  • src/utils/AudioCompare.js (8 hunks)
  • src/utils/VoiceAnalyser.js (13 hunks)
  • src/utils/constants.js (6 hunks)
  • src/utils/useFFmpeg.jsx (1 hunks)
  • src/views/AppContent/AppContent.jsx (1 hunks)
  • src/views/Practice/Practice.jsx (2 hunks)
Files skipped from review due to trivial changes (2)
  • src/routes/index.js
  • src/views/AppContent/AppContent.jsx
Additional context used
Path-based instructions (1)
public/index.html (1)

Pattern **/*.html: "Review the HTML code against the google html style guide and point out any mismatches. Ensure that:

  • The code adheres to best practices recommended by lighthouse or similar tools for performance."
Biome
public/whisper.wasm/libstream.worker.js

[error] 1-1: Redundant use strict directive.

The entire contents of JavaScript modules are automatically in strict mode, with no statement needed to initiate it.
Safe fix: Remove the redundant use strict directive.

(lint/suspicious/noRedundantUseStrict)


[error] 1-1: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 1-1: eval() exposes to security risks and performance issues.

See the MDN web docs for more details.
Refactor the code so that it doesn't need to call eval().

(lint/security/noGlobalEval)

src/utils/AudioCompare.js

[error] 40-40: Avoid redundant double-negation.

It is not necessary to use double-negation when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant double-negation

(lint/complexity/noExtraBooleanCast)

Additional comments not posted (36)
src/utils/constants.js (4)

Line range hint 11-20:
LGTM!

The changes to AllLanguages enhance the functionality by allowing for more granular control over language selection based on connectivity status.


Line range hint 31-31:
LGTM!

The addition of rnnoiseModelPath provides a new constant for the rnnoise model path.


Line range hint 21-30:
Verify the impact of changes to languages.

The changes to languages export introduce new filtering logic based on offlineLanguages. Ensure that this new logic does not affect the existing functionality and that the application handles language selection correctly based on connectivity status.


Line range hint 1-10:
Verify the impact of changes to levelGetContent.

The changes to levelGetContent standardize the mechanism to "flashcard" and change the criteria to "word" for levels P1 to P4. Ensure that these changes do not affect the existing functionality and that the application handles these levels correctly.

src/setupProxy.js (1)

1-7: LGTM!

The new file sets headers for Cross-Origin policies, which enhances security.

src/config/awsS3.js (2)

1-1: LGTM!

The import statement for S3Client from the AWS SDK is correct and necessary for the functionality.


3-9: Ensure environment variables are correctly set and credentials are securely managed.

The initialization and export of S3Client enable the application to interact with AWS S3 services. Ensure that the environment variables REACT_APP_AWS_S3_REGION, REACT_APP_AWS_ACCESS_KEY_ID, and REACT_APP_AWS_SECRET_ACCESS_KEY are correctly set and that the credentials are securely managed.

public/index.html (1)

24-25: Ensure scripts are loaded efficiently.

The defer attribute ensures that the scripts are executed after the document has been parsed, which is good for performance. However, consider using async if the scripts are independent and do not rely on each other or other scripts.

package.json (8)

10-10: Verify the necessity of @ffmpeg/ffmpeg.

Ensure that the addition of @ffmpeg/ffmpeg is necessary and that it is being used effectively in the project.


25-25: LGTM! ESLint configuration for React apps.

The addition of eslint-config-react-app enhances linting capabilities for React applications.


26-26: LGTM! ESLint plugin for import/export syntax.

The addition of eslint-plugin-import enhances linting capabilities for ES6+ import/export syntax.


27-27: LGTM! ESLint plugin for JSX accessibility rules.

The addition of eslint-plugin-jsx-a11y enhances linting capabilities for accessibility rules in JSX.


28-28: LGTM! ESLint plugin for React-specific code.

The addition of eslint-plugin-react enhances linting capabilities for React-specific code.


30-30: Verify the necessity of ffmpeg.

Ensure that the addition of ffmpeg is necessary and that it is being used effectively in the project.


31-31: Verify the necessity of fuzzball.

Ensure that the addition of fuzzball is necessary and that it is being used effectively in the project.


94-94: Verify the necessity of @mui/styles.

Ensure that the addition of @mui/styles is necessary and that it is being used effectively in the project.

.github/workflows/all-prod-rig.yml (4)

78-78: Verify the necessity of REACT_APP_ASR_OFFLINE_LANGUAGUAGES.

Ensure that the addition of REACT_APP_ASR_OFFLINE_LANGUAGUAGES is necessary and that it is being used effectively in the project.


79-79: Verify the necessity of REACT_APP_AWS_ACCESS_KEY_ID.

Ensure that the addition of REACT_APP_AWS_ACCESS_KEY_ID is necessary and that it is being used effectively in the project.


80-80: Verify the necessity of REACT_APP_AWS_SECRET_ACCESS_KEY.

Ensure that the addition of REACT_APP_AWS_SECRET_ACCESS_KEY is necessary and that it is being used effectively in the project.


77-77: Verify consistent usage of REACT_APP_LANGUAGES.

Ensure that the new variable name REACT_APP_LANGUAGES is used consistently across the codebase.

Verification successful

The new variable name REACT_APP_LANGUAGES is used consistently across the codebase.

  • src/utils/constants.js: REACT_APP_LANGUAGES is correctly used.
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the consistent usage of the new variable name `REACT_APP_LANGUAGES`.

# Test: Search for the old and new variable names. Expect: Only occurrences of the new variable name.
rg --type yaml 'REACT_APP_IS_APP_LANGUAGES'
rg --type yaml 'REACT_APP_LANGUAGES'

Length of output: 80


Script:

#!/bin/bash
# Description: Verify the consistent usage of the new variable name `REACT_APP_LANGUAGES`.

# Test: Search for the old and new variable names across all file types. Expect: Only occurrences of the new variable name.
rg 'REACT_APP_IS_APP_LANGUAGES'
rg 'REACT_APP_LANGUAGES'

Length of output: 203

.github/workflows/all-dev-rig.yml (5)

6-6: Verify the alignment of branch specification change.

Ensure that the change of branch specification from all-1.2 to all-2.0-offline aligns with the project's deployment strategy.


78-78: Verify the necessity of REACT_APP_ASR_OFFLINE_LANGUAGUAGES.

Ensure that the addition of REACT_APP_ASR_OFFLINE_LANGUAGUAGES is necessary and that it is being used effectively in the project.


79-79: Verify the necessity of REACT_APP_AWS_ACCESS_KEY_ID.

Ensure that the addition of REACT_APP_AWS_ACCESS_KEY_ID is necessary and that it is being used effectively in the project.


80-80: Verify the necessity of REACT_APP_AWS_SECRET_ACCESS_KEY.

Ensure that the addition of REACT_APP_AWS_SECRET_ACCESS_KEY is necessary and that it is being used effectively in the project.


77-77: Verify consistent usage of REACT_APP_LANGUAGES.

Ensure that the new variable name REACT_APP_LANGUAGES is used consistently across the codebase.

Verification successful

The variable REACT_APP_LANGUAGES is used consistently across the codebase.

There are no occurrences of the old variable name REACT_APP_IS_APP_LANGUAGES, and the new variable name is correctly used in src/utils/constants.js.

  • src/utils/constants.js:
    • const appLanguages = process.env.REACT_APP_LANGUAGES
    • ? JSON.parse(process.env.REACT_APP_LANGUAGES)
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the consistent usage of the new variable name `REACT_APP_LANGUAGES`.

# Test: Search for the old and new variable names. Expect: Only occurrences of the new variable name.
rg --type yaml 'REACT_APP_IS_APP_LANGUAGES'
rg --type yaml 'REACT_APP_LANGUAGES'

Length of output: 80


Script:

#!/bin/bash
# Description: Verify the consistent usage of the new variable name `REACT_APP_LANGUAGES`.

# Test: Search for the old and new variable names across all file types. Expect: Only occurrences of the new variable name.
rg 'REACT_APP_IS_APP_LANGUAGES'
rg 'REACT_APP_LANGUAGES'

Length of output: 203

.github/workflows/all-app-sandbox.yml (3)

78-78: Fix typo in environment variable name.

The variable REACT_APP_ASR_OFFLINE_LANGUAGUAGES contains a typo. It should be REACT_APP_ASR_OFFLINE_LANGUAGES.

- REACT_APP_ASR_OFFLINE_LANGUAGUAGES:  ${{ vars.REACT_APP_ASR_OFFLINE_LANGUAGUAGES }}
+ REACT_APP_ASR_OFFLINE_LANGUAGES:  ${{ vars.REACT_APP_ASR_OFFLINE_LANGUAGES }}

Likely invalid or redundant comment.


79-80: Avoid exposing sensitive information.

Storing AWS credentials directly in environment variables can be a security risk. Ensure these secrets are managed securely and consider using a secrets management service.

Verification successful

Avoid exposing sensitive information.

The AWS credentials are being accessed through environment variables in src/config/awsS3.js. While this is a common practice, it is crucial to ensure these secrets are managed securely. Consider using a secrets management service to enhance security.

  • src/config/awsS3.js: Accesses REACT_APP_AWS_ACCESS_KEY_ID and REACT_APP_AWS_SECRET_ACCESS_KEY.
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the secure handling of AWS credentials.

# Test: Search for direct usage of AWS credentials in the codebase. Expect: No occurrences of direct usage.
rg --type js 'AWS_ACCESS_KEY_ID|AWS_SECRET_ACCESS_KEY'

Length of output: 228


Script:

#!/bin/bash
# Description: Verify the secure handling and non-exposure of AWS credentials in the codebase.

# Test 1: Search for any logging or exposure of the environment variables related to AWS credentials.
rg 'console\.log.*(REACT_APP_AWS_ACCESS_KEY_ID|REACT_APP_AWS_SECRET_ACCESS_KEY)'

# Test 2: Ensure that the environment variables are not hardcoded or mishandled.
rg -l 'REACT_APP_AWS_ACCESS_KEY_ID|REACT_APP_AWS_SECRET_ACCESS_KEY'

Length of output: 172


77-77: Ensure consistency in environment variable naming.

The variable REACT_APP_LANGUAGES has been renamed from REACT_APP_IS_APP_LANGUAGES. Ensure that all references to the old variable name are updated throughout the codebase to avoid runtime errors.

Verification successful

All references to the old environment variable name REACT_APP_IS_APP_LANGUAGES have been successfully updated to REACT_APP_LANGUAGES. No occurrences of the old variable name were found in the codebase.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify all references to the old environment variable name are updated.

# Test: Search for the old variable name. Expect: No occurrences of the old variable name.
rg --type js 'REACT_APP_IS_APP_LANGUAGES'

Length of output: 41


Script:

#!/bin/bash
# Description: Verify all references to the old environment variable name are updated.

# Test: Search for the old variable name across all file types. Expect: No occurrences of the old variable name.
rg 'REACT_APP_IS_APP_LANGUAGES'

Length of output: 31

src/utils/AudioCompare.js (2)

47-47: Ensure consistent state updates.

Ensure that the state update for loader (or isLoading) is consistent throughout the component.

Verification successful

Consistent state updates for loader verified.

The state updates for loader in AudioCompare.js are consistent and logically placed within the component's lifecycle.

  • setLoader(false) is called in a useEffect hook when props.recordedAudio changes.
  • setLoader(true) and setLoader(false) are called appropriately within the handleStop function.
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify consistent state updates for the loading indicator.

# Test: Search for all occurrences of `setLoader` or `setIsLoading`. Expect: Consistent usage.
rg --type js 'setLoader|setIsLoading'

Length of output: 701


Script:

#!/bin/bash
# Extract more lines around each occurrence of `setLoader` in `AudioCompare.js` to verify logical consistency.
rg --type js 'setLoader' -A 3 -B 3 src/utils/AudioCompare.js

Length of output: 822


78-82: Handle offline model processing gracefully.

Ensure that the branching logic for offline model processing is correctly handling all possible scenarios.

Verification successful

The isOfflineModel flag is referenced in multiple files, including src/utils/AudioCompare.js, src/utils/VoiceAnalyser.js, and src/components/Assesment/Assesment.jsx. To ensure that the offline model processing is handled gracefully, we need to inspect the relevant sections in each of these files to verify consistent and correct usage of the isOfflineModel flag.


Offline model processing is handled gracefully.

The branching logic for offline model processing correctly handles all possible scenarios in the relevant sections of the code.

  • src/utils/AudioCompare.js: The code checks the isOfflineModel flag and calls the appropriate function based on its value.
  • src/utils/VoiceAnalyser.js: The code sets the mode based on the isOfflineModel flag and uses it in processing.
  • src/components/Assesment/Assesment.jsx: The code sets the isOfflineModel state, updates localStorage, and uses the flag in conditional rendering and model loading.
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the handling of offline model processing.

# Test: Search for all references to `isOfflineModel` and ensure correct handling.
rg --type js 'isOfflineModel'

Length of output: 1234


Script:

#!/bin/bash
# Inspect the relevant sections in each file to ensure correct handling of the `isOfflineModel` flag.

# Display lines around the reference in AudioCompare.js
rg --type js -A 5 -B 5 'isOfflineModel' src/utils/AudioCompare.js

# Display lines around the references in VoiceAnalyser.js
rg --type js -A 5 -B 5 'isOfflineModel' src/utils/VoiceAnalyser.js

# Display lines around the references in Assesment.jsx
rg --type js -A 5 -B 5 'isOfflineModel' src/components/Assesment/Assesment.jsx

Length of output: 3261

src/utils/VoiceAnalyser.js (2)

309-318: Refactor playAudio to use arrow function.

Refactor the playAudio function to use an arrow function for consistency and to adhere to modern JavaScript practices.

- function playAudio(val) {
+ const playAudio = (val) => {

Line range hint 68-84:
Ensure consistent state initialization.

The currentIndex state is initialized but not used in the component. Verify if it is necessary.

Verification successful

The currentIndex state is used and necessary.

The setCurrentIndex function is called within the component, confirming the need for the currentIndex state variable.

  • File: src/utils/VoiceAnalyser.js
  • Lines: 77-300
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify if the `currentIndex` state is used in the component.

# Test: Search for `setCurrentIndex` usage. Expect: No occurrences.
rg --type js -A 5 'setCurrentIndex'

Length of output: 769

src/views/Practice/Practice.jsx (3)

869-914: Ensure proper handling of mechanism state in renderMechanics.

Verify that the mechanism state is correctly set and used in the renderMechanics function.

Verification successful

The mechanism state is correctly set and used in the renderMechanics function.

  • The mechanism state is declared and initialized.
  • It is set using setMechanism based on currentGetContent.mechanism.
  • The state is used in various conditional checks to render appropriate components, including Mechanics2 for the "flashcard" mechanism.
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of `mechanism` state in `renderMechanics`.

# Test: Search for `mechanism` state usage. Expect: Correctly set and used in the `renderMechanics` function.
rg --type js -A 5 'mechanism'

Length of output: 8467


869-914: Ensure proper handling of mechanism state in rendering logic.

Verify that the mechanism state is correctly set and used in the rendering logic.

Verification successful

Ensure proper handling of mechanism state in rendering logic.

The mechanism state is correctly set and used in the rendering logic. The changes appear to be correctly implemented.

  • The mechanism state is declared and initialized.
  • The mechanism state is updated based on currentGetContent.mechanism.
  • The rendering logic includes conditional blocks to render different components based on the value of mechanism.
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of `mechanism` state in rendering logic.

# Test: Search for `mechanism` state usage. Expect: Correctly set and used in the rendering logic.
rg --type js -A 5 'mechanism'

Length of output: 8467


455-455: Ensure proper handling of mechanism state in API request.

Verify that the currentGetContent.mechanism state is correctly set and used in the API request.

Verification successful

Proper handling of mechanism state in API request verified.

The currentGetContent.mechanism state is correctly set and used within the API request in Practice.jsx. The context around its definition and updates confirms its validity.

  • currentGetContent is derived from levelGetContent.
  • The mechanism property is consistently set and used in API requests.
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of `currentGetContent.mechanism` state.

# Test: Search for `currentGetContent.mechanism` usage. Expect: Correctly set and used in the API request.
rg --type js -A 5 'currentGetContent.mechanism'

Length of output: 2007


Script:

#!/bin/bash
# Description: Gather context around the definition and updates of `currentGetContent`.

# Search for the definition and updates of `currentGetContent` in the codebase.
rg --type js -A 10 'currentGetContent'

Length of output: 7819

src/components/Assesment/Assesment.jsx (1)

Line range hint 470-658:
Ensure proper handling of isOfflineModel state in ProfileHeader.

Verify that the isOfflineModel state is correctly set and used in the ProfileHeader component.

Verification successful

The isOfflineModel state is correctly set and used in the ProfileHeader component within src/components/Assesment/Assesment.jsx.

  • The state is initialized from localStorage.
  • It is used in a useEffect hook to update the localStorage.
  • It is referenced in various parts of the component logic.
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of `isOfflineModel` state in `ProfileHeader`.

# Test: Search for `isOfflineModel` state usage. Expect: Correctly set and used in the `ProfileHeader` component.
rg --type js -A 5 'isOfflineModel'

Length of output: 3956

fontSize: 24, // Adjust the size of the emoji
}}
>
<img style={{height:'57px', paddingBottom:'10px'}} src={RunnungBoy}/>
Copy link

Choose a reason for hiding this comment

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

Fix typo in image source variable name.

The variable name RunnungBoy seems to be a typo. It should be RunningBoy.

- import RunnungBoy from '../../assets/images/boy-running.gif';
+ import RunningBoy from '../../assets/images/boy-running.gif';
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<img style={{height:'57px', paddingBottom:'10px'}} src={RunnungBoy}/>
import RunningBoy from '../../assets/images/boy-running.gif';
<img style={{height:'57px', paddingBottom:'10px'}} src={RunningBoy}/>

Comment on lines +1 to +10
const loadWhisperModule = async () => {
try {
if (typeof Module === 'undefined') {
throw new Error('Module is not defined');
}
window.whisperModule = Module;
} catch (error) {
console.error('Failed to load WASM module', error);
}
};
Copy link

Choose a reason for hiding this comment

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

Consider encapsulating the module and improving error messages.

  1. Assigning the module to a global variable (window.whisperModule) can lead to potential conflicts and difficulties in debugging. Consider encapsulating the module within a closure or a module pattern.
  2. The error message 'Module is not defined' could be more descriptive to help with debugging.
- if (typeof Module === 'undefined') {
-   throw new Error('Module is not defined');
+ if (typeof Module === 'undefined') {
+   throw new Error('WASM Module is not defined. Ensure it is properly loaded and accessible.');

Committable suggestion was skipped due to low confidence.

@@ -0,0 +1 @@
"use strict";var Module={};var ENVIRONMENT_IS_NODE=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string";if(ENVIRONMENT_IS_NODE){var nodeWorkerThreads=require("worker_threads");var parentPort=nodeWorkerThreads.parentPort;parentPort.on("message",function(data){onmessage({data:data})});var fs=require("fs");Object.assign(global,{self:global,require:require,Module:Module,location:{href:__filename},Worker:nodeWorkerThreads.Worker,importScripts:function(f){(0,eval)(fs.readFileSync(f,"utf8"))},postMessage:function(msg){parentPort.postMessage(msg)},performance:global.performance||{now:function(){return Date.now()}}})}var initializedJS=false;function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");if(ENVIRONMENT_IS_NODE){fs.writeSync(2,text+"\n");return}console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:Module["_pthread_self"]()})}var err=threadPrintErr;self.alert=threadAlert;Module["instantiateWasm"]=((info,receiveInstance)=>{var instance=new WebAssembly.Instance(Module["wasmModule"],info);receiveInstance(instance);Module["wasmModule"]=null;return instance.exports});self.onmessage=(e=>{try{if(e.data.cmd==="load"){Module["wasmModule"]=e.data.wasmModule;Module["wasmMemory"]=e.data.wasmMemory;Module["buffer"]=Module["wasmMemory"].buffer;Module["ENVIRONMENT_IS_PTHREAD"]=true;if(typeof e.data.urlOrBlob=="string"){importScripts(e.data.urlOrBlob)}else{var objectUrl=URL.createObjectURL(e.data.urlOrBlob);importScripts(objectUrl);URL.revokeObjectURL(objectUrl)}}else if(e.data.cmd==="run"){Module["__performance_now_clock_drift"]=performance.now()-e.data.time;Module["__emscripten_thread_init"](e.data.threadInfoStruct,0,0,1);Module["establishStackSpace"]();Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].threadInit();if(!initializedJS){Module["___embind_register_native_and_builtin_types"]();initializedJS=true}try{var result=Module["invokeEntryPoint"](e.data.start_routine,e.data.arg);if(Module["keepRuntimeAlive"]()){Module["PThread"].setExitStatus(result)}else{Module["__emscripten_thread_exit"](result)}}catch(ex){if(ex!="unwind"){if(ex instanceof Module["ExitStatus"]){if(Module["keepRuntimeAlive"]()){}else{Module["__emscripten_thread_exit"](ex.status)}}else{throw ex}}}}else if(e.data.cmd==="cancel"){if(Module["_pthread_self"]()){Module["__emscripten_thread_exit"](-1)}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="processThreadQueue"){if(Module["_pthread_self"]()){Module["_emscripten_current_thread_process_queued_calls"]()}}else if(e.data.cmd==="processProxyingQueue"){if(Module["_pthread_self"]()){Module["_emscripten_proxy_execute_queue"](e.data.queue)}}else{err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){err("worker.js onmessage() captured an uncaught exception: "+ex);if(ex&&ex.stack)err(ex.stack);if(Module["__emscripten_thread_crashed"]){Module["__emscripten_thread_crashed"]()}throw ex}});
Copy link

Choose a reason for hiding this comment

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

Use optional chaining for safer property access.

Using optional chaining can simplify the code and make it safer by avoiding errors when accessing nested properties.

- var ENVIRONMENT_IS_NODE=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string";
+ var ENVIRONMENT_IS_NODE=typeof process?.versions?.node=="string";

Committable suggestion was skipped due to low confidence.

Tools
Biome

[error] 1-1: Redundant use strict directive.

The entire contents of JavaScript modules are automatically in strict mode, with no statement needed to initiate it.
Safe fix: Remove the redundant use strict directive.

(lint/suspicious/noRedundantUseStrict)


[error] 1-1: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 1-1: eval() exposes to security risks and performance issues.

See the MDN web docs for more details.
Refactor the code so that it doesn't need to call eval().

(lint/security/noGlobalEval)


Remove redundant 'use strict' directive.

The entire contents of JavaScript modules are automatically in strict mode, making the 'use strict' directive redundant.

- "use strict";
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"use strict";var Module={};var ENVIRONMENT_IS_NODE=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string";if(ENVIRONMENT_IS_NODE){var nodeWorkerThreads=require("worker_threads");var parentPort=nodeWorkerThreads.parentPort;parentPort.on("message",function(data){onmessage({data:data})});var fs=require("fs");Object.assign(global,{self:global,require:require,Module:Module,location:{href:__filename},Worker:nodeWorkerThreads.Worker,importScripts:function(f){(0,eval)(fs.readFileSync(f,"utf8"))},postMessage:function(msg){parentPort.postMessage(msg)},performance:global.performance||{now:function(){return Date.now()}}})}var initializedJS=false;function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");if(ENVIRONMENT_IS_NODE){fs.writeSync(2,text+"\n");return}console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:Module["_pthread_self"]()})}var err=threadPrintErr;self.alert=threadAlert;Module["instantiateWasm"]=((info,receiveInstance)=>{var instance=new WebAssembly.Instance(Module["wasmModule"],info);receiveInstance(instance);Module["wasmModule"]=null;return instance.exports});self.onmessage=(e=>{try{if(e.data.cmd==="load"){Module["wasmModule"]=e.data.wasmModule;Module["wasmMemory"]=e.data.wasmMemory;Module["buffer"]=Module["wasmMemory"].buffer;Module["ENVIRONMENT_IS_PTHREAD"]=true;if(typeof e.data.urlOrBlob=="string"){importScripts(e.data.urlOrBlob)}else{var objectUrl=URL.createObjectURL(e.data.urlOrBlob);importScripts(objectUrl);URL.revokeObjectURL(objectUrl)}}else if(e.data.cmd==="run"){Module["__performance_now_clock_drift"]=performance.now()-e.data.time;Module["__emscripten_thread_init"](e.data.threadInfoStruct,0,0,1);Module["establishStackSpace"]();Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].threadInit();if(!initializedJS){Module["___embind_register_native_and_builtin_types"]();initializedJS=true}try{var result=Module["invokeEntryPoint"](e.data.start_routine,e.data.arg);if(Module["keepRuntimeAlive"]()){Module["PThread"].setExitStatus(result)}else{Module["__emscripten_thread_exit"](result)}}catch(ex){if(ex!="unwind"){if(ex instanceof Module["ExitStatus"]){if(Module["keepRuntimeAlive"]()){}else{Module["__emscripten_thread_exit"](ex.status)}}else{throw ex}}}}else if(e.data.cmd==="cancel"){if(Module["_pthread_self"]()){Module["__emscripten_thread_exit"](-1)}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="processThreadQueue"){if(Module["_pthread_self"]()){Module["_emscripten_current_thread_process_queued_calls"]()}}else if(e.data.cmd==="processProxyingQueue"){if(Module["_pthread_self"]()){Module["_emscripten_proxy_execute_queue"](e.data.queue)}}else{err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){err("worker.js onmessage() captured an uncaught exception: "+ex);if(ex&&ex.stack)err(ex.stack);if(Module["__emscripten_thread_crashed"]){Module["__emscripten_thread_crashed"]()}throw ex}});
var Module={};var ENVIRONMENT_IS_NODE=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string";if(ENVIRONMENT_IS_NODE){var nodeWorkerThreads=require("worker_threads");var parentPort=nodeWorkerThreads.parentPort;parentPort.on("message",function(data){onmessage({data:data})});var fs=require("fs");Object.assign(global,{self:global,require:require,Module:Module,location:{href:__filename},Worker:nodeWorkerThreads.Worker,importScripts:function(f){(0,eval)(fs.readFileSync(f,"utf8"))},postMessage:function(msg){parentPort.postMessage(msg)},performance:global.performance||{now:function(){return Date.now()}}})}var initializedJS=false;function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");if(ENVIRONMENT_IS_NODE){fs.writeSync(2,text+"\n");return}console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:Module["_pthread_self"]()})}var err=threadPrintErr;self.alert=threadAlert;Module["instantiateWasm"]=((info,receiveInstance)=>{var instance=new WebAssembly.Instance(Module["wasmModule"],info);receiveInstance(instance);Module["wasmModule"]=null;return instance.exports});self.onmessage=(e=>{try{if(e.data.cmd==="load"){Module["wasmModule"]=e.data.wasmModule;Module["wasmMemory"]=e.data.wasmMemory;Module["buffer"]=Module["wasmMemory"].buffer;Module["ENVIRONMENT_IS_PTHREAD"]=true;if(typeof e.data.urlOrBlob=="string"){importScripts(e.data.urlOrBlob)}else{var objectUrl=URL.createObjectURL(e.data.urlOrBlob);importScripts(objectUrl);URL.revokeObjectURL(objectUrl)}}else if(e.data.cmd==="run"){Module["__performance_now_clock_drift"]=performance.now()-e.data.time;Module["__emscripten_thread_init"](e.data.threadInfoStruct,0,0,1);Module["establishStackSpace"]();Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].threadInit();if(!initializedJS){Module["___embind_register_native_and_builtin_types"]();initializedJS=true}try{var result=Module["invokeEntryPoint"](e.data.start_routine,e.data.arg);if(Module["keepRuntimeAlive"]()){Module["PThread"].setExitStatus(result)}else{Module["__emscripten_thread_exit"](result)}}catch(ex){if(ex!="unwind"){if(ex instanceof Module["ExitStatus"]){if(Module["keepRuntimeAlive"]()){}else{Module["__emscripten_thread_exit"](ex.status)}}else{throw ex}}}}else if(e.data.cmd==="cancel"){if(Module["_pthread_self"]()){Module["__emscripten_thread_exit"](-1)}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="processThreadQueue"){if(Module["_pthread_self"]()){Module["_emscripten_current_thread_process_queued_calls"]()}}else if(e.data.cmd==="processProxyingQueue"){if(Module["_pthread_self"]()){Module["_emscripten_proxy_execute_queue"](e.data.queue)}}else{err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){err("worker.js onmessage() captured an uncaught exception: "+ex);if(ex&&ex.stack)err(ex.stack);if(Module["__emscripten_thread_crashed"]){Module["__emscripten_thread_crashed"]()}throw ex}});
Tools
Biome

[error] 1-1: Redundant use strict directive.

The entire contents of JavaScript modules are automatically in strict mode, with no statement needed to initiate it.
Safe fix: Remove the redundant use strict directive.

(lint/suspicious/noRedundantUseStrict)


[error] 1-1: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 1-1: eval() exposes to security risks and performance issues.

See the MDN web docs for more details.
Refactor the code so that it doesn't need to call eval().

(lint/security/noGlobalEval)


Avoid using eval.

The use of eval exposes the code to security risks and performance issues. Refactor the code to avoid using eval.

- importScripts:function(f){(0,eval)(fs.readFileSync(f,"utf8"))}
+ importScripts:function(f){(0, new Function(fs.readFileSync(f, "utf8")))()}
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"use strict";var Module={};var ENVIRONMENT_IS_NODE=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string";if(ENVIRONMENT_IS_NODE){var nodeWorkerThreads=require("worker_threads");var parentPort=nodeWorkerThreads.parentPort;parentPort.on("message",function(data){onmessage({data:data})});var fs=require("fs");Object.assign(global,{self:global,require:require,Module:Module,location:{href:__filename},Worker:nodeWorkerThreads.Worker,importScripts:function(f){(0,eval)(fs.readFileSync(f,"utf8"))},postMessage:function(msg){parentPort.postMessage(msg)},performance:global.performance||{now:function(){return Date.now()}}})}var initializedJS=false;function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");if(ENVIRONMENT_IS_NODE){fs.writeSync(2,text+"\n");return}console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:Module["_pthread_self"]()})}var err=threadPrintErr;self.alert=threadAlert;Module["instantiateWasm"]=((info,receiveInstance)=>{var instance=new WebAssembly.Instance(Module["wasmModule"],info);receiveInstance(instance);Module["wasmModule"]=null;return instance.exports});self.onmessage=(e=>{try{if(e.data.cmd==="load"){Module["wasmModule"]=e.data.wasmModule;Module["wasmMemory"]=e.data.wasmMemory;Module["buffer"]=Module["wasmMemory"].buffer;Module["ENVIRONMENT_IS_PTHREAD"]=true;if(typeof e.data.urlOrBlob=="string"){importScripts(e.data.urlOrBlob)}else{var objectUrl=URL.createObjectURL(e.data.urlOrBlob);importScripts(objectUrl);URL.revokeObjectURL(objectUrl)}}else if(e.data.cmd==="run"){Module["__performance_now_clock_drift"]=performance.now()-e.data.time;Module["__emscripten_thread_init"](e.data.threadInfoStruct,0,0,1);Module["establishStackSpace"]();Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].threadInit();if(!initializedJS){Module["___embind_register_native_and_builtin_types"]();initializedJS=true}try{var result=Module["invokeEntryPoint"](e.data.start_routine,e.data.arg);if(Module["keepRuntimeAlive"]()){Module["PThread"].setExitStatus(result)}else{Module["__emscripten_thread_exit"](result)}}catch(ex){if(ex!="unwind"){if(ex instanceof Module["ExitStatus"]){if(Module["keepRuntimeAlive"]()){}else{Module["__emscripten_thread_exit"](ex.status)}}else{throw ex}}}}else if(e.data.cmd==="cancel"){if(Module["_pthread_self"]()){Module["__emscripten_thread_exit"](-1)}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="processThreadQueue"){if(Module["_pthread_self"]()){Module["_emscripten_current_thread_process_queued_calls"]()}}else if(e.data.cmd==="processProxyingQueue"){if(Module["_pthread_self"]()){Module["_emscripten_proxy_execute_queue"](e.data.queue)}}else{err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){err("worker.js onmessage() captured an uncaught exception: "+ex);if(ex&&ex.stack)err(ex.stack);if(Module["__emscripten_thread_crashed"]){Module["__emscripten_thread_crashed"]()}throw ex}});
"use strict";var Module={};var ENVIRONMENT_IS_NODE=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string";if(ENVIRONMENT_IS_NODE){var nodeWorkerThreads=require("worker_threads");var parentPort=nodeWorkerThreads.parentPort;parentPort.on("message",function(data){onmessage({data:data})});var fs=require("fs");Object.assign(global,{self:global,require:require,Module:Module,location:{href:__filename},Worker:nodeWorkerThreads.Worker,importScripts:function(f){(0, new Function(fs.readFileSync(f, "utf8")))()},postMessage:function(msg){parentPort.postMessage(msg)},performance:global.performance||{now:function(){return Date.now()}}})}var initializedJS=false;function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");if(ENVIRONMENT_IS_NODE){fs.writeSync(2,text+"\n");return}console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:Module["_pthread_self"]()})}var err=threadPrintErr;self.alert=threadAlert;Module["instantiateWasm"]=((info,receiveInstance)=>{var instance=new WebAssembly.Instance(Module["wasmModule"],info);receiveInstance(instance);Module["wasmModule"]=null;return instance.exports});self.onmessage=(e=>{try{if(e.data.cmd==="load"){Module["wasmModule"]=e.data.wasmModule;Module["wasmMemory"]=e.data.wasmMemory;Module["buffer"]=Module["wasmMemory"].buffer;Module["ENVIRONMENT_IS_PTHREAD"]=true;if(typeof e.data.urlOrBlob=="string"){importScripts(e.data.urlOrBlob)}else{var objectUrl=URL.createObjectURL(e.data.urlOrBlob);importScripts(objectUrl);URL.revokeObjectURL(objectUrl)}}else if(e.data.cmd==="run"){Module["__performance_now_clock_drift"]=performance.now()-e.data.time;Module["__emscripten_thread_init"](e.data.threadInfoStruct,0,0,1);Module["establishStackSpace"]();Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].threadInit();if(!initializedJS){Module["___embind_register_native_and_builtin_types"]();initializedJS=true}try{var result=Module["invokeEntryPoint"](e.data.start_routine,e.data.arg);if(Module["keepRuntimeAlive"]()){Module["PThread"].setExitStatus(result)}else{Module["__emscripten_thread_exit"](result)}}catch(ex){if(ex!="unwind"){if(ex instanceof Module["ExitStatus"]){if(Module["keepRuntimeAlive"]()){}else{Module["__emscripten_thread_exit"](ex.status)}}else{throw ex}}}}else if(e.data.cmd==="cancel"){if(Module["_pthread_self"]()){Module["__emscripten_thread_exit"](-1)}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="processThreadQueue"){if(Module["_pthread_self"]()){Module["_emscripten_current_thread_process_queued_calls"]()}}else if(e.data.cmd==="processProxyingQueue"){if(Module["_pthread_self"]()){Module["_emscripten_proxy_execute_queue"](e.data.queue)}}else{err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){err("worker.js onmessage() captured an uncaught exception: "+ex);if(ex&&ex.stack)err(ex.stack);if(Module["__emscripten_thread_crashed"]){Module["__emscripten_thread_crashed"]()}throw ex}});
Tools
Biome

[error] 1-1: Redundant use strict directive.

The entire contents of JavaScript modules are automatically in strict mode, with no statement needed to initiate it.
Safe fix: Remove the redundant use strict directive.

(lint/suspicious/noRedundantUseStrict)


[error] 1-1: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 1-1: eval() exposes to security risks and performance issues.

See the MDN web docs for more details.
Refactor the code so that it doesn't need to call eval().

(lint/security/noGlobalEval)

Comment on lines +1 to +19
import React from "react";
import { Box, CircularProgress } from "@mui/material";

const CircularProgressOverlay = ({ size, color }) => (
<Box
sx={{
display: "flex",
position: "absolute",
zIndex: 999,
justifyContent: "center",
width: "100%",
alignItems: "center",
height: "100vh",
backgroundColor: "rgb(0 0 0 / 56%)",
}}
>
<CircularProgress size={size} sx={{ color: color }} />
</Box>
);
Copy link

Choose a reason for hiding this comment

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

Add PropTypes for prop validation and consider making zIndex configurable.

  1. Use PropTypes to validate the props size and color.
  2. The hardcoded zIndex value might need to be configurable to avoid conflicts with other components.
import React from "react";
+ import PropTypes from 'prop-types';

const CircularProgressOverlay = ({ size, color }) => (
  <Box
    sx={{
      display: "flex",
      position: "absolute",
      zIndex: 999,
      justifyContent: "center",
      width: "100%",
      alignItems: "center",
      height: "100vh",
      backgroundColor: "rgb(0 0 0 / 56%)",
    }}
  >
    <CircularProgress size={size} sx={{ color: color }} />
  </Box>
);

+ CircularProgressOverlay.propTypes = {
+   size: PropTypes.number.isRequired,
+   color: PropTypes.string.isRequired,
+ };

export default CircularProgressOverlay;

Committable suggestion was skipped due to low confidence.

Comment on lines +1 to +24
import { useState, useEffect } from "react";
import { createFFmpeg, fetchFile } from "@ffmpeg/ffmpeg";

let ffmpeg = null;

const useFFmpeg = () => {
const [loading, setLoading] = useState(true);

useEffect(() => {
if (!ffmpeg) {
ffmpeg = createFFmpeg({ log: false });
ffmpeg
.load()
.then(() => setLoading(false))
.catch(console.error);
} else {
setLoading(false);
}
}, []);

return { ffmpeg, loading };
};

export default useFFmpeg;
Copy link

Choose a reason for hiding this comment

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

Encapsulate the ffmpeg variable and improve error handling.

  1. Encapsulate the ffmpeg variable within the hook to avoid potential conflicts.
  2. Improve error handling by providing more context in the error message.
import { useState, useEffect } from "react";
import { createFFmpeg, fetchFile } from "@ffmpeg/ffmpeg";

- let ffmpeg = null;

const useFFmpeg = () => {
  const [loading, setLoading] = useState(true);
  const [ffmpeg, setFfmpeg] = useState(null);

  useEffect(() => {
    if (!ffmpeg) {
-     ffmpeg = createFFmpeg({ log: false });
+     const newFfmpeg = createFFmpeg({ log: false });
-     ffmpeg
+     newFfmpeg
        .load()
        .then(() => {
+         setFfmpeg(newFfmpeg);
          setLoading(false);
        })
-       .catch(console.error);
+       .catch((error) => console.error('Failed to load FFmpeg', error));
    } else {
      setLoading(false);
    }
  }, []);

  return { ffmpeg, loading };
};

export default useFFmpeg;
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { useState, useEffect } from "react";
import { createFFmpeg, fetchFile } from "@ffmpeg/ffmpeg";
let ffmpeg = null;
const useFFmpeg = () => {
const [loading, setLoading] = useState(true);
useEffect(() => {
if (!ffmpeg) {
ffmpeg = createFFmpeg({ log: false });
ffmpeg
.load()
.then(() => setLoading(false))
.catch(console.error);
} else {
setLoading(false);
}
}, []);
return { ffmpeg, loading };
};
export default useFFmpeg;
import { useState, useEffect } from "react";
import { createFFmpeg, fetchFile } from "@ffmpeg/ffmpeg";
const useFFmpeg = () => {
const [loading, setLoading] = useState(true);
const [ffmpeg, setFfmpeg] = useState(null);
useEffect(() => {
if (!ffmpeg) {
const newFfmpeg = createFFmpeg({ log: false });
newFfmpeg
.load()
.then(() => {
setFfmpeg(newFfmpeg);
setLoading(false);
})
.catch((error) => console.error('Failed to load FFmpeg', error));
} else {
setLoading(false);
}
}, []);
return { ffmpeg, loading };
};
export default useFFmpeg;

Comment on lines +9 to +50
const Mechanics2 = ({
page,
setPage,
handleNext,
background,
header,
type,
words,
image,
setVoiceText,
setRecordedAudio,
setVoiceAnimate,
storyLine,
enableNext,
showTimer,
points,
steps,
currentStep,
contentId,
contentType,
level,
isDiscover,
progressData,
showProgress,
playTeacherAudio = () => {},
callUpdateLearner,
disableScreen,
isShowCase,
handleBack,
setEnableNext,
startShowCase,
setStartShowCase,
livesData,
setLivesData,
gameOverData,
highlightWords,
matchedChar,
loading,
setOpenMessageDialog,
isNextButtonCalled,
setIsNextButtonCalled,
}) => {
Copy link

Choose a reason for hiding this comment

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

Consider breaking down large prop lists.

The Mechanics2 component has a large number of props. Consider grouping related props into objects to improve readability and maintainability.

const Mechanics2 = ({
  page,
  setPage,
  handleNext,
  background,
  header,
  type,
  words,
  image,
  setVoiceText,
  setRecordedAudio,
  setVoiceAnimate,
  storyLine,
  enableNext,
  showTimer,
  points,
  steps,
  currentStep,
  contentId,
  contentType,
  level,
  isDiscover,
  progressData,
  showProgress,
  playTeacherAudio = () => {},
  callUpdateLearner,
  disableScreen,
  isShowCase,
  handleBack,
  setEnableNext,
  startShowCase,
  setStartShowCase,
  livesData,
  setLivesData,
  gameOverData,
  highlightWords,
  matchedChar,
  loading,
  setOpenMessageDialog,
  isNextButtonCalled,
  setIsNextButtonCalled,
}) => {
  const [shake, setShake] = useState(false);

Committable suggestion was skipped due to low confidence.

Comment on lines +87 to +96
{!enableNext && (
<Box
sx={{
width: "80vw",
height: "50vh",
borderRadius: "15px",
display: "flex",
flexDirection: "column",
justifyContent: "space-between",
}}
Copy link

Choose a reason for hiding this comment

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

Ensure responsive design.

The hardcoded values for width and height should be replaced with responsive units or media queries to ensure the component adapts to different screen sizes.

<Box
  sx={{
    width: "80vw",
    height: "50vh",
    borderRadius: "15px",
    display: "flex",
    flexDirection: "column",
    justifyContent: "space-between",
  }}
>

Committable suggestion was skipped due to low confidence.

Comment on lines +159 to +263
display: "flex",
flexDirection: "column",
justifyContent: "space-between",
}}
>
{enableNext && <Confetti width={width} height={"600px"} />}
<>
<Box
sx={{
display: "flex",
justifyContent: "center",
}}
>
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "center",
width: "33%",
}}
>
<img
style={{ width: "100%" }}
src={fetchImage()}
alt="content"
loading="lazy"
/>
</Box>
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "center",
width: "33%",
}}
>
<Typography
variant="h1"
component="h1"
sx={{
textAlign: "center",
fontSize: "50px",
fontWeight: 700,
fontFamily: "Quicksand",
marginTop: "40px",
marginBottom: "20px",
color: "#6CC227",
}}
>
Good Job.!
</Typography>
<Typography
variant="h2"
component="h2"
sx={{
textAlign: "center",
fontSize: "30px",
fontWeight: 600,
fontFamily: "Quicksand",
lineHeight: "40px",
marginBottom: "20px",
}}
>
You have good Pronunciation Skills.
</Typography>
{words && (
<Typography
variant="h3"
component="h3"
sx={{
textAlign: "center",
fontSize: "40px",
fontWeight: 700,
fontFamily: "Quicksand",
lineHeight: "40px",
marginBottom: "20px",
}}
>
{words}
</Typography>
)}
</Box>
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "center",
width: "33%",
}}
>
<img
src={discoverEndRight}
alt="timer"
className={shake && "shakeImage"}
loading="lazy"
/>
</Box>
</Box>
</>
</Box>
Copy link

Choose a reason for hiding this comment

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

Improve conditional rendering.

The conditional rendering logic can be simplified and made more readable by extracting it into separate components.

{enableNext ? (
  <Box
    sx={{
      width: "80vw",
      height: "50vh",
      borderRadius: "15px",
      display: "flex",
      flexDirection: "column",
      justifyContent: "space-between",
    }}
  >
    <Confetti width={width} height={"600px"} />
    <Box
      sx={{
        display: "flex",
        justifyContent: "center",
      }}
    >
      <Box
        sx={{
          display: "flex",
          flexDirection: "column",
          alignItems: "center",
          width: "33%",
        }}
      >
        <img
          style={{ width: "100%" }}
          src={fetchImage()}
          alt="content"
          loading="lazy"
        />
      </Box>
      <Box
        sx={{
          display: "flex",
          flexDirection: "column",
          alignItems: "center",
          width: "33%",
        }}
      >
        <Typography
          variant="h1"
          component="h1"
          sx={{
            textAlign: "center",
            fontSize: "50px",
            fontWeight: 700,
            fontFamily: "Quicksand",
            marginTop: "40px",
            marginBottom: "20px",
            color: "#6CC227",
          }}
        >
          Good Job.!
        </Typography>
        <Typography
          variant="h2"
          component="h2"
          sx={{
            textAlign: "center",
            fontSize: "30px",
            fontWeight: 600,
            fontFamily: "Quicksand",
            lineHeight: "40px",
            marginBottom: "20px",
          }}
        >
          You have good Pronunciation Skills.
        </Typography>
        {words && (
          <Typography
            variant="h3"
            component="h3"
            sx={{
              textAlign: "center",
              fontSize: "40px",
              fontWeight: 700,
              fontFamily: "Quicksand",
              lineHeight: "40px",
              marginBottom: "20px",
            }}
          >
            {words}
          </Typography>
        )}
      </Box>
      <Box
        sx={{
          display: "flex",
          flexDirection: "column",
          alignItems: "center",
          width: "33%",
        }}
      >
        <img
          src={discoverEndRight}
          alt="timer"
          className={shake && "shakeImage"}
          loading="lazy"
        />
      </Box>
    </Box>
  </Box>
) : (
  <Box
    sx={{
      width: "80vw",
      height: "50vh",
      borderRadius: "15px",
      display: "flex",
      flexDirection: "column",
      justifyContent: "space-between",
    }}
  >
    <Box>
      {words && (
        <Typography
          variant="h1"
          component="h1"
          sx={{
            textAlign: "center",
            fontSize: "clamp(45px, 6vw, 100px)",
            paddingX: "140px",
            fontWeight: 700,
            fontFamily: "Quicksand",
            lineHeight: "50px",
            marginTop: "40px",
          }}
        >
          {words && words.length > 0 ? (
            <>
              <span style={{ backgroundColor: "yellow" }}>
                {words[0]}
              </span>{" "}
              -{" "}
              <span style={{ backgroundColor: "yellow" }}>
                {words[0]}
              </span>
              {words.slice(1)}
            </>
          ) : (
            ""
          )}
        </Typography>
      )}
    </Box>
    <Typography
      variant="h5"
      component="h4"
      sx={{
        mb: 2,
        fontSize: "20px",
        color: "#333F61",
        textAlign: "center",
      }}
    >
      Guess the below image
    </Typography>
    <Box
      sx={{ display: "flex", justifyContent: "center", mb: 4 }}
    >
      <img
        style={{ width: "20%" }}
        src={fetchImage()}
        alt="content"
        loading="lazy"
      />
    </Box>
  </Box>
)}

Committable suggestion was skipped due to low confidence.

Comment on lines +937 to +951
const handleRedirect = async () => {
if(localStorage.getItem('isOfflineModel') === 'true'){
const modelName = "en-model";
await openDB();
const stored = await isModelStored(modelName);
if (stored) {
console.log(`Model ${modelName} is already stored in IndexedDB`);
}
else{
alert(`you have to download en-offline model`)
await loadModel();
return;
}
await loadModelWhisper(modelName);
}
Copy link

Choose a reason for hiding this comment

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

Ensure proper error handling in handleRedirect.

The handleRedirect function should handle errors more gracefully by providing user feedback instead of just logging errors.

- alert(`you have to download en-offline model`);
+ setOpenMessageDialog({ message: "You have to download en-offline model", isError: true });
+ console.error("Error: en-offline model not downloaded");
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const handleRedirect = async () => {
if(localStorage.getItem('isOfflineModel') === 'true'){
const modelName = "en-model";
await openDB();
const stored = await isModelStored(modelName);
if (stored) {
console.log(`Model ${modelName} is already stored in IndexedDB`);
}
else{
alert(`you have to download en-offline model`)
await loadModel();
return;
}
await loadModelWhisper(modelName);
}
const handleRedirect = async () => {
if(localStorage.getItem('isOfflineModel') === 'true'){
const modelName = "en-model";
await openDB();
const stored = await isModelStored(modelName);
if (stored) {
console.log(`Model ${modelName} is already stored in IndexedDB`);
}
else{
setOpenMessageDialog({ message: "You have to download en-offline model", isError: true });
console.error("Error: en-offline model not downloaded");
await loadModel();
return;
}
await loadModelWhisper(modelName);
}

Comment on lines +49 to +174
reject(event.target.error);
};
request.onsuccess = (event) => {
db = event.target.result;
console.log("IndexedDB opened successfully");
resolve();
};
request.onupgradeneeded = (event) => {
db = event.target.result;
console.log("Creating object store for models");
if (!db.objectStoreNames.contains("models")) {
db.createObjectStore("models");
}
};
});
};

// Function to store model in IndexedDB
const storeModel = async (modelName, modelURL) => {
try {
const response = await fetch(modelURL);
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}

const reader = response.body.getReader();
const contentLength = +response.headers.get('Content-Length');
let receivedLength = 0;
const chunks = [];

while (true) {
const { done, value } = await reader.read();
if (done) break;
chunks.push(value);
receivedLength += value.length;

// Update progress
const percentage = ((receivedLength / contentLength) * 100);
setDownloadProgress(percentage.toFixed());
}

const modelData = new Uint8Array(receivedLength);
let position = 0;
for (let chunk of chunks) {
modelData.set(chunk, position);
position += chunk.length;
}

const transaction = db.transaction(["models"], "readwrite");
const store = transaction.objectStore("models");

store.put(modelData, modelName);
console.log(`Stored model ${modelName} in IndexedDB`);
} catch (error) {
console.error("Error storing model in IndexedDB:", error);
}
};

// Function to check if the model is already stored in IndexedDB
const isModelStored = (modelName) => {
return new Promise((resolve, reject) => {
const transaction = db.transaction(["models"], "readonly");
const store = transaction.objectStore("models");
const request = store.get(modelName);

request.onerror = function (event) {
console.error(
"Error checking model in IndexedDB:",
event.target.errorCode
);
reject(event.target.error);
};

request.onsuccess = function (event) {
resolve(!!event.target.result);
};
});
};

// Function to load model
const loadModel = async () => {
setLoading(true);
try {
await openDB();
const modelName = "en-model";
const modelURL = "./models/ggml-model-whisper-base.en-q5_1.bin";

const stored = await isModelStored(modelName);
if (!stored) {
await storeModel(modelName, modelURL);
} else {
console.log(`Model ${modelName} is already stored in IndexedDB`);
return;
}
} catch (error) {
console.log(error.message);
} finally {
setLoading(false);
}
};
Copy link

Choose a reason for hiding this comment

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

Ensure proper error handling in storeModel.

The storeModel function should handle errors more gracefully by providing user feedback instead of just logging errors.

- console.error("Error storing model in IndexedDB:", error);
+ setOpenMessageDialog({ message: "Error storing model in IndexedDB", isError: true });
+ console.error("Error storing model in IndexedDB:", error);
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const LanguageModal = ({
lang,
setLang,
setOpenLangModal,
setLoading,
setDownloadProgress
}) => {
const [selectedLang, setSelectedLang] = useState(lang);
const [isOfflineModel, setIsOfflineModel] = useState(
localStorage.getItem("isOfflineModel") === "true"
);
useEffect(() => {
localStorage.setItem("isOfflineModel", isOfflineModel);
}, [isOfflineModel]);
const dbName = "language-ai-models";
const dbVersion = 1;
let db;
// Open IndexedDB
const openDB = () => {
return new Promise((resolve, reject) => {
const request = window.indexedDB.open(dbName, dbVersion);
request.onerror = (event) => {
console.error("IndexedDB error:", event.target.errorCode);
reject(event.target.error);
};
request.onsuccess = (event) => {
db = event.target.result;
console.log("IndexedDB opened successfully");
resolve();
};
request.onupgradeneeded = (event) => {
db = event.target.result;
console.log("Creating object store for models");
if (!db.objectStoreNames.contains("models")) {
db.createObjectStore("models");
}
};
});
};
// Function to store model in IndexedDB
const storeModel = async (modelName, modelURL) => {
try {
const response = await fetch(modelURL);
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const reader = response.body.getReader();
const contentLength = +response.headers.get('Content-Length');
let receivedLength = 0;
const chunks = [];
while (true) {
const { done, value } = await reader.read();
if (done) break;
chunks.push(value);
receivedLength += value.length;
// Update progress
const percentage = ((receivedLength / contentLength) * 100);
setDownloadProgress(percentage.toFixed());
}
const modelData = new Uint8Array(receivedLength);
let position = 0;
for (let chunk of chunks) {
modelData.set(chunk, position);
position += chunk.length;
}
const transaction = db.transaction(["models"], "readwrite");
const store = transaction.objectStore("models");
store.put(modelData, modelName);
console.log(`Stored model ${modelName} in IndexedDB`);
} catch (error) {
console.error("Error storing model in IndexedDB:", error);
}
};
// Function to check if the model is already stored in IndexedDB
const isModelStored = (modelName) => {
return new Promise((resolve, reject) => {
const transaction = db.transaction(["models"], "readonly");
const store = transaction.objectStore("models");
const request = store.get(modelName);
request.onerror = function (event) {
console.error(
"Error checking model in IndexedDB:",
event.target.errorCode
);
reject(event.target.error);
};
request.onsuccess = function (event) {
resolve(!!event.target.result);
};
});
};
// Function to load model
const loadModel = async () => {
setLoading(true);
try {
await openDB();
const modelName = "en-model";
const modelURL = "./models/ggml-model-whisper-base.en-q5_1.bin";
const stored = await isModelStored(modelName);
if (!stored) {
await storeModel(modelName, modelURL);
} else {
console.log(`Model ${modelName} is already stored in IndexedDB`);
return;
}
} catch (error) {
console.log(error.message);
} finally {
setLoading(false);
}
};
const storeModel = async (modelName, modelURL) => {
try {
const response = await fetch(modelURL);
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const reader = response.body.getReader();
const contentLength = +response.headers.get('Content-Length');
let receivedLength = 0;
const chunks = [];
while (true) {
const { done, value } = await reader.read();
if (done) break;
chunks.push(value);
receivedLength += value.length;
// Update progress
const percentage = ((receivedLength / contentLength) * 100);
setDownloadProgress(percentage.toFixed());
}
const modelData = new Uint8Array(receivedLength);
let position = 0;
for (let chunk of chunks) {
modelData.set(chunk, position);
position += chunk.length;
}
const transaction = db.transaction(["models"], "readwrite");
const store = transaction.objectStore("models");
store.put(modelData, modelName);
console.log(`Stored model ${modelName} in IndexedDB`);
} catch (error) {
setOpenMessageDialog({ message: "Error storing model in IndexedDB", isError: true });
console.error("Error storing model in IndexedDB:", error);
}
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants