@nualang/nualang-ui-components 0.1.1207 → 0.1.1209

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -86,7 +86,7 @@ const PlanFeaturesListItem = (0, _system.styled)("li")(({
86
86
  theme
87
87
  }) => ({
88
88
  display: "flex",
89
- marginTop: theme.spacing(3)
89
+ marginTop: theme.spacing(2)
90
90
  }));
91
91
  const PlanFeaturesListItemLabel = (0, _system.styled)(_material.Typography)(() => ({
92
92
  display: "flex",
@@ -116,7 +116,7 @@ const Badge = (0, _system.styled)(_material.Typography)(({
116
116
  color: theme.palette.common.black,
117
117
  fontSize: theme.typography.pxToRem(10),
118
118
  borderRadius: "9px",
119
- padding: "3px",
119
+ padding: theme.spacing(0.25, 1),
120
120
  display: "flex",
121
121
  alignItems: "center",
122
122
  marginBottom: "2px"
@@ -188,7 +188,7 @@ function SubscriptionPlan({
188
188
  currency
189
189
  }) {
190
190
  const [displayPlan, setDisplayPlan] = (0, _react.useState)(plan);
191
- const [buyNowDisabled, setBuyNowDisabled] = (0, _react.useState)(true);
191
+ const [buyNowDisabled, setBuyNowDisabled] = (0, _react.useState)(plan?.planVersions?.length > 0 ? true : false);
192
192
  const [anchorEl, setAnchorEl] = (0, _react.useState)(null);
193
193
  const open = Boolean(anchorEl);
194
194
  const [disableRippleEff, setDisableRippleEff] = (0, _react.useState)(false);
@@ -307,8 +307,9 @@ function SubscriptionPlan({
307
307
  onClick: () => plan.button.onClick(),
308
308
  bgPrimary: plan.bgPrimary,
309
309
  children: plan.button.buttonText
310
- }), plan.planVersions && displayPlan && billingPeriod && currency && /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
311
- children: [displayPlan.subButton && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
310
+ }), displayPlan && billingPeriod && currency && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_material.Box, {
311
+ mt: 2,
312
+ children: [plan.planVersions && displayPlan.subButton && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
312
313
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(PlanButton, {
313
314
  id: "plan-button",
314
315
  fullWidth: true,
@@ -10,7 +10,6 @@ var _DefaultColourButton = _interopRequireDefault(require("../../Misc/DefaultCol
10
10
  var _styles = require("@mui/material/styles");
11
11
  var _mui = require("tss-react/mui");
12
12
  var _useMediaQuery = _interopRequireDefault(require("@mui/material/useMediaQuery"));
13
- var _Star = _interopRequireDefault(require("@mui/icons-material/Star"));
14
13
  var _Search = _interopRequireDefault(require("@mui/icons-material/Search"));
15
14
  var _InputBase = _interopRequireDefault(require("@mui/material/InputBase"));
16
15
  var _InputAdornment = _interopRequireDefault(require("@mui/material/InputAdornment"));
@@ -91,7 +90,8 @@ const SearchIconWrapper = (0, _styles.styled)("div")(({
91
90
  justifyContent: "center"
92
91
  }));
93
92
  const StyledInputBase = (0, _styles.styled)(_InputBase.default)(({
94
- theme
93
+ theme,
94
+ isUpgradePossible
95
95
  }) => ({
96
96
  color: "inherit",
97
97
  width: "100%",
@@ -100,9 +100,9 @@ const StyledInputBase = (0, _styles.styled)(_InputBase.default)(({
100
100
  paddingLeft: `calc(1em + ${theme.spacing(4)})`,
101
101
  transition: theme.transitions.create("width"),
102
102
  [theme.breakpoints.up("lg")]: {
103
- width: "30ch",
103
+ width: isUpgradePossible ? "20ch" : "30ch",
104
104
  "&:focus": {
105
- width: "35ch"
105
+ width: isUpgradePossible ? "25ch" : "35ch"
106
106
  }
107
107
  }
108
108
  }
@@ -111,7 +111,8 @@ function AppSearch({
111
111
  t,
112
112
  navigate,
113
113
  searchText,
114
- setSearchText
114
+ setSearchText,
115
+ isUpgradePossible
115
116
  }) {
116
117
  const [debouncedSearchText, setDebouncedSearchText] = (0, _react.useState)("");
117
118
  const [prevDebouncedSearchText, setPrevDebouncedSearchText] = (0, _react.useState)("");
@@ -146,6 +147,7 @@ function AppSearch({
146
147
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Search.default, {})
147
148
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(StyledInputBase, {
148
149
  autoFocus: true,
150
+ isUpgradePossible: isUpgradePossible,
149
151
  placeholder: t("app_search_placeholder"),
150
152
  value: searchText,
151
153
  onChange: ev => {
@@ -283,6 +285,7 @@ function App({
283
285
  };
284
286
  const isSearchActive = searchText || isMobileSearchExpanded;
285
287
  const isTeacher = user && user["custom:role"] === "teach";
288
+ const isUpgradePossible = subscription && !subscription.isPaidUser && subscription.isUpgradePossible;
286
289
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
287
290
  className: classes.root,
288
291
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Header.default, {
@@ -307,7 +310,8 @@ function App({
307
310
  t: t,
308
311
  navigate: navigate,
309
312
  searchText: searchText,
310
- setSearchText: setSearchText
313
+ setSearchText: setSearchText,
314
+ isUpgradePossible: isUpgradePossible
311
315
  })]
312
316
  }) : /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
313
317
  children: [isLgScreen ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_jsxRuntime.Fragment, {
@@ -316,7 +320,8 @@ function App({
316
320
  t: t,
317
321
  navigate: navigate,
318
322
  searchText: searchText,
319
- setSearchText: setSearchText
323
+ setSearchText: setSearchText,
324
+ isUpgradePossible: isUpgradePossible
320
325
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_material.Box, {
321
326
  flexGrow: 1
322
327
  })]
@@ -353,16 +358,6 @@ function App({
353
358
  }),
354
359
  size: isLgScreen ? "medium" : "small",
355
360
  children: t("skip_navigation")
356
- }), subscription && !subscription.isPaidUser && subscription.isUpgradePossible && authenticated && /*#__PURE__*/(0, _jsxRuntime.jsx)(_DefaultColourButton.default, {
357
- variant: "contained",
358
- startIcon: isLgScreen ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_Star.default, {}) : null,
359
- href: upgradePlanURL,
360
- size: isLgScreen ? "medium" : "small",
361
- sx: {
362
- fontSize: isLgScreen ? null : 12,
363
- mr: 1
364
- },
365
- children: t("upgrade_plan")
366
361
  }), isTeacher && (isLgScreen ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_material.Button, {
367
362
  variant: "contained",
368
363
  onClick: handleClickCreate,
@@ -381,7 +376,16 @@ function App({
381
376
  onClick: handleClickCreate,
382
377
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Add.default, {})
383
378
  })
384
- })), isLgScreen && /*#__PURE__*/(0, _jsxRuntime.jsx)(_WhatsNew.default, {
379
+ })), isUpgradePossible && authenticated && /*#__PURE__*/(0, _jsxRuntime.jsx)(_DefaultColourButton.default, {
380
+ variant: "contained",
381
+ href: upgradePlanURL,
382
+ size: isLgScreen ? "medium" : "small",
383
+ sx: {
384
+ fontSize: isLgScreen ? null : 12,
385
+ ml: 1
386
+ },
387
+ children: t("upgrade_plan")
388
+ }), isLgScreen && /*#__PURE__*/(0, _jsxRuntime.jsx)(_WhatsNew.default, {
385
389
  t: t,
386
390
  whatsNewMarkdown: whatsNewMarkdown,
387
391
  whatsNewDate: whatsNewDate
@@ -223,10 +223,14 @@ function CreatePhrase({
223
223
 
224
224
  const autoFillTranslation = async () => {
225
225
  try {
226
- const activePrompt = `Translate the following phrase "${phrase}" from ${learnLang} to ${forLang}. Provide all the acceptable translations if the phrase has multiple interpretations. Format the response as a valid JSON array with each translation as a string inside the array.`;
227
226
  let chatGptResponse = await makeChatGptApiRequest({
228
227
  model: "gpt-3.5-turbo",
229
- prompt: activePrompt
228
+ promptKey: "autoFillTranslation",
229
+ promptVariables: {
230
+ learnLang,
231
+ forLang,
232
+ phrase
233
+ }
230
234
  });
231
235
  chatGptResponse = chatGptResponse.replaceAll("```", '').replaceAll("json", '');
232
236
  const translations = JSON.parse(chatGptResponse);
@@ -138,16 +138,21 @@ function GenerateBotDialog({
138
138
  setIsBotGenerating(true);
139
139
  setErrorMessage("");
140
140
  let response;
141
- let promptWithTopic;
142
- let promptWithTopicPhrases;
143
- const topicPrompt = `The questions should be about the topic: '${values.botTopic}'. Focus primarily on the topic to ensure the questions are aligned with it. If there is no relevance or similarity between the topic and the provided phrases, only use the topic for generating questions.`;
144
- const topicGoalPrompt = `These questions must specifically target the goal: '${topicGoal}’. The questions should only focus on the goal '${topicGoal}’. Avoid generating questions that ask about unrelated details.`;
145
- bot.selectedTemplate === "nualang.quiz.0.0.1" ? promptWithTopic = `Create ${values.botLengthNumber} questions in ${learnLang} about the topic ${values.botTopic}. Have atleast one correct answer for each question. The questions should be appropriate for ${["en-US"].includes(siteLanguage) ? "ACTFL" : "CEFR"} ${bot & bot.difficulty} level learners. Questions and answers must be unique from one another. Return an array with ${values.botLengthNumber} objects inside it. Each object should have the keys questions and answer. The key question should equal to the question that is generated about the topic. The key answer should equal to the corresponding answer to the question, make sure that the answer text is inside brackets like this answer: "(questionAnswer)" if there is more than one correct answer the value of the answer key should be formatted like this answer: "(answer1|answer2)". Use this array as template: ${sampleQuestionArray} Your response should be in JSON.` : promptWithTopic = `Create ${values.botLengthNumber} open ended questions in ${learnLang} about the topic ${values.botTopic}. The questions should be appropriate for ${["en-US"].includes(siteLanguage) ? "ACTFL" : "CEFR"} ${bot & bot.difficulty} level learners. Each question must be unique. Return an array with ${values.botLengthNumber} objects inside it. Each object should have the key text. The key text should equal to the question that is generated about the topic. Your response should be in JSON.`;
146
- bot.selectedTemplate === "nualang.quiz.0.0.1" ? promptWithTopicPhrases = `Create ${values.botLengthNumber} questions in ${learnLang}${values.botTopic.trim() === "" ? " using the following phrases as context to assist in the generations of questions." : "."} ${topicGoal.trim() !== "" ? topicGoalPrompt : ""} ${values.botTopic.trim() !== "" ? topicPrompt : ""} The questions should be appropriate for ${["en-US"].includes(siteLanguage) ? "ACTFL" : "CEFR"} ${bot & bot.difficulty} level learners. Include at least one correct answer for each question. Phrases for context: ${phrases}. Questions must be unique from one another. Return an array with ${values.botLengthNumber} objects inside it. Each object should have the keys questions and answer. The key question should equal to the question that is generated about the topic. The key answer should equal to the corresponding answer to the question, make sure that the answer text is inside brackets like this answer: "(questionAnswer)" if there is more than one correct answer the value of the answer key should be formatted like this answer: "(answer1|answer2)". Use this array as template: ${sampleQuestionArray} Your response should be in JSON.` : promptWithTopicPhrases = `Create ${values.botLengthNumber} questions in ${learnLang}${values.botTopic.trim() === "" ? " using the following phrases as context to assist in the generations of questions." : "."} ${topicGoal.trim() !== "" ? topicGoalPrompt : ""} ${values.botTopic.trim() !== "" ? topicPrompt : ""} The questions should be appropriate for ${["en-US"].includes(siteLanguage) ? "ACTFL" : "CEFR"} ${bot & bot.difficulty} level learners. Phrases for context: ${phrases}. Questions must be unique from one another. Return an array with ${values.botLengthNumber} objects inside it. Each object should have the key text. The key text should equal to the question that is generated about the topic. Your response should be in JSON.`;
147
- const activePrompt = usePhrasesContext && phrases.length > 0 ? promptWithTopicPhrases : promptWithTopic;
148
141
  let chatGptResponse = await makeChatGptApiRequest({
149
142
  model: "gpt-3.5-turbo",
150
- prompt: activePrompt
143
+ promptKey: "generateBot",
144
+ promptVariables: {
145
+ botTopic: values.botTopic,
146
+ topicGoal: topicGoal,
147
+ selectedTemplate: bot.selectedTemplate,
148
+ botLengthNumber: values.botLengthNumber,
149
+ learnLang: learnLang,
150
+ siteLanguage: siteLanguage,
151
+ difficulty: bot.difficulty,
152
+ sampleQuestionArray: sampleQuestionArray,
153
+ phrases: phrases,
154
+ usePhrasesContext: usePhrasesContext
155
+ }
151
156
  });
152
157
  response = chatGptResponse;
153
158
  const jsonResponse = removeExtraTextFromChatGptResponse(response);
@@ -111,12 +111,21 @@ function GeneratePhrases({
111
111
  try {
112
112
  setIsGenerating(true);
113
113
  setErrorMessage(null);
114
- const goalPrompt = `The generated phrases must specifically target the following linguistic goal: '${values.topicGoal}'. Avoid generating phrases that do not align with this goal. `;
115
- const prompt = phraseType === "sentences" ? isPhrases ? `The context is a language learning application. Here is a list of phrases or sentences in ${learnLang} and their translations in ${forLang}:\n\n${JSON.stringify(phrases)}\n\nNow, generate ${values.phraseAmount} more unique sentences in ${learnLang} and their translations in ${forLang} on the topic of '${values.phrasesTopic}' in the same JSON format as the ones that I have passed to you. The 'idx' field should contain an index integer which follows on incrementally from the existing phrases. The 'image' field should contain an empty string. Do not include a 'voices' field. ${values.topicGoal.trim() ? goalPrompt : ""}The sentences should be unique and not already in the list. The sentences should be appropriate for ${["en-US"].includes(siteLanguage) ? "ACTFL" : "CEFR"} ${difficulty} level. Ensure the formatting of the JSON response is correct and follows this structure.` : `The context is a language learning application. Generate ${values.phraseAmount} unique phrases or sentences in ${learnLang} and their translations in ${forLang} on the topic of '${values.phrasesTopic}'. Return the sentences inside a JSON array of ${values.phraseAmount} objects, each with the following fields: 'phrase', 'translations', 'idx', and 'image'. Each field is required and cannot be omitted. The 'idx' field represents the index of the phrases, starting from 0 and going up by 1 up until the last phrase. The 'image' field should contain an empty string. The 'translations' field should be an array of at least one translation of the sentence in ${forLang}, but it can contain more translations as long as they are grammatically correct. ${values.topicGoal.trim() ? goalPrompt : ""}The sentences should be appropriate for the ${["en-US"].includes(siteLanguage) ? "ACTFL" : "CEFR"} ${difficulty} level. The sentences should be unique. Ensure the formatting of the JSON response is correct and follows this structure.` : isPhrases ? `The context is a language learning application. Here is a list of words or very short lexical phrases in ${learnLang} and their translations in ${forLang}:\n\n${JSON.stringify(phrases)}\n\nNow, generate ${values.phraseAmount} more unique words or very short lexical phrases and their translations in ${learnLang} on the topic of '${values.phrasesTopic}'. The input may resemble a script or contain dialogue, but do not generate words or very short lexical phrases formatted as scripts or sentences. Focus only on single words or very short lexical phrases. The 'idx' field should contain an index integer which follows on incrementally from the existing phrases. The 'image' field should contain an empty string. Do not include a 'voices' field. ${values.topicGoal.trim() ? goalPrompt : ""}The words or lexical phrases should be unique and not already in the list. The words or lexical phrases should be ${["en-US"].includes(siteLanguage) ? "ACTFL" : "CEFR"} ${difficulty} level. Ensure the formatting of the JSON response is correct and follows this structure.` : `The context is a language learning application. Generate ${values.phraseAmount} unique words or very short lexical phrases in ${learnLang} and their translations in ${forLang} on the topic of '${values.phrasesTopic}'. Return the unique words or very short lexical phrases inside a JSON array of ${values.phraseAmount} objects, each with the following fields: 'phrase', 'translations', 'idx', and 'image'. Each field is required and cannot be omitted. The 'idx' field represents the index of the phrases, starting from 0 and going up by 1 up until the last phrase. The 'image' field should contain an empty string. The 'translations' field should be an array of at least one translation of the phrase in ${forLang}, but it can contain more translations as long as they are grammatically correct. ${values.topicGoal.trim() ? goalPrompt : ""}The input may resemble a script or contain dialogue, but do not interpret or format the input as a script or sentences. Focus only on generating single words or very short lexical phrases. The words or very short lexical phrases should be appropriate for the ${["en-US"].includes(siteLanguage) ? "ACTFL" : "CEFR"} ${difficulty} level. The words or very short lexical phrases should be unique. Ensure the formatting of the JSON response is correct and follows this structure.`;
116
- // console.log("prompt: ", prompt);
117
114
  const chatGptResponse = await makeChatGptApiRequest({
118
115
  model: "gpt-3.5-turbo",
119
- prompt
116
+ promptKey: "generatePhrases",
117
+ promptVariables: {
118
+ topicGoal: values.topicGoal,
119
+ learnLang,
120
+ forLang,
121
+ phraseAmount: values.phraseAmount,
122
+ phrasesTopic: values.phrasesTopic,
123
+ siteLanguage,
124
+ difficulty,
125
+ phraseType,
126
+ isPhrases,
127
+ phrases
128
+ }
120
129
  });
121
130
  const phrasesArray = extractPhrasesArray(chatGptResponse);
122
131
  const parsedPhrases = JSON.parse(phrasesArray);
@@ -87,10 +87,18 @@ function GenerateQuestion({
87
87
  try {
88
88
  setIsMessageGenerating(true);
89
89
  setErrorMessage(null);
90
- const prompt = `Here is a script: ${JSON.stringify(script)}. Refer to Actor 1 as ${values.actor1.name} and Actor 2 as ${values.actor2.name} in the question and the answers. The purpose of this script is to test the reader's ability to read in ${finalLearnLang}. The reader's native language is ${finalForLang}. Please generate a new comprehension question based on the script that is completely unique to any existing questions, preferably referring to a unique part of the script if possible, and provide it in JSON format with the keys 'question' and 'answers'. The 'question' key has the value of the string contraining the question text. The 'answers' key is an array of objects, where each answer object contains 'text', 'correct', and 'type' keys. The type should always be 'multichoice'. There are four possible question types, 'factual', 'inference', 'truefalse' and 'vocabulary'. For factual questions, ensure the new question is explicitly answered by the script, to test the reader's understanding of the script. For inference questions, ensure the new question requires the reader to make an assumption based on the script. For true/false questions, ensure the new question can be answered with a true or false response. For vocabulary questions, ensure the new question tests the reader's understanding of a specific ${finalLearnLang} word or phrase used in the script, to test whether the reader can understand it. Vocabulary questions do not necessarily have to take the context of the conversation into account, they are merely to test the reader's ${finalLearnLang} vocabulary. The question type for this particular question to generate is ${questionType}. The question and answers should be generated in ${questionLanguage}.`;
91
90
  const chatGptResponse = await makeChatGptApiRequest({
92
91
  model: "gpt-3.5-turbo",
93
- prompt
92
+ promptKey: "generateAnswer",
93
+ promptVariables: {
94
+ script,
95
+ actor1: values.actor1,
96
+ actor2: values.actor2,
97
+ finalLearnLang: finalLearnLang,
98
+ finalForLang: finalForLang,
99
+ questionType,
100
+ questionLanguage
101
+ }
94
102
  });
95
103
  const jsonResponse = extractJsonObject(chatGptResponse);
96
104
  const newQuestion = JSON.parse(jsonResponse);
@@ -181,8 +181,6 @@ function GenerateRoleplayDialog({
181
181
  setErrorMessage("");
182
182
  let response;
183
183
  const roleplayDifficulty = values.roleplayDifficulty;
184
- // console.log("Roleplay Difficulty:", roleplayDifficulty);
185
-
186
184
  const basePrompt = usePdfContext ? `Create an informative conversation between 2 people ${values?.actor1?.name && values?.actor2?.name ? `'${values.actor1.name}' and '${values.actor2.name}' ` : ""} about the topic '${values.roleplayTopic}' in the language ${learnLang}. The conversation should be ${i18nLanguage === "en-US" ? "ACTFL" : "CEFR"} level '${t(roleplayDifficulty)}.'` : `Create a conversation between 2 people ${values?.actor1?.name && values?.actor2?.name ? `'${values.actor1.name}' and '${values.actor2?.name}' ` : ""} about the topic '${values.roleplayTopic}' in the language ${learnLang}. The conversation should be ${i18nLanguage === "en-US" ? "ACTFL" : "CEFR"} level '${t(roleplayDifficulty)}.'`;
187
185
  const topicGoalPrompt = topicGoal ? ` The conversation should be guided by the following goal: '${topicGoal}'.` : "";
188
186
  const promptWithPhrases = usePhrasesContext ? ` Additionally, use the following phrases as part of the conversation, where appropriate to the topic '${values.roleplayTopic}': ${phrases.map(phrase => phrase.phrase).join(", ")}. Only use these phrases if they fit naturally into the conversation.` : "";
@@ -192,10 +190,6 @@ function GenerateRoleplayDialog({
192
190
  const promptWithoutQuestions = usePdfContext ? `${finalPrompt} The conversation should be returned as a single JSON array. The array must contain exactly ${values.roleplayLengthNumber} exchanges (lines). Each piece of dialogue should be represented as an object with the keys 'actor' and 'text'. The 'actor' key should be set to 1 if the dialogue is spoken by the first actor, and 2 if it is spoken by the second actor. The 'text' key should be set to the dialogue text spoken by that actor. Please ensure the entire output is formatted as a single, well-formed JSON array.` : `${finalPrompt} The conversation should be returned as a single JSON array. The array must contain exactly ${values.roleplayLengthNumber} exchanges (lines). Each piece of dialogue should be represented as an object with the keys 'actor' and 'text'. The 'actor' key should be set to 1 if the dialogue is spoken by the first actor, and 2 if it is spoken by the second actor. The 'text' key should be set to the dialogue text spoken by that actor. Please ensure the entire output is formatted as a single, well-formed JSON array.`;
193
191
  const promptWithQuestions = usePdfContext ? `${finalPrompt} The conversation should be returned as a single JSON array. The array must contain exactly ${values.roleplayLengthNumber} exchanges (lines), followed by ${values?.questionsAmount} comprehension questions related to the conversation, the question should be generated in ${questionLang}. Each piece of dialogue should be represented as an object with the keys 'actor' and 'text'. The 'actor' key should be set to 1 if the dialogue is spoken by the first actor, and 2 if it is spoken by the second actor. The 'text' key should be set to the dialogue text spoken by that actor. Each comprehension question should also be represented as an object within the same array, with the keys 'question' and 'answers'. The 'answers' key should be an array of 3 objects, each containing 'text', 'correct' (true or false), and 'type' ('correct' or 'incorrect'), the answers should be generated in ${questionLang}. Please ensure the entire output is formatted as a single, well-formed JSON array.` : `${finalPrompt} The conversation should be returned as a single JSON array. The array must contain exactly ${values.roleplayLengthNumber} exchanges (lines), followed by ${values?.questionsAmount} comprehension questions related to the conversation, the question should be generated in ${questionLang}. Each piece of dialogue should be represented as an object with the keys 'actor' and 'text'. The 'actor' key should be set to 1 if the dialogue is spoken by the first actor, and 2 if it is spoken by the second actor. The 'text' key should be set to the dialogue text spoken by that actor. Each comprehension question should also be represented as an object within the same array, with the keys 'question' and 'answers'. The 'answers' key should be an array of 3 objects, each containing 'text', 'correct' (true or false), and 'type' ('correct' or 'incorrect'), the answers should be generated in ${questionLang}. Please ensure the entire output is formatted as a single, well-formed JSON array.`;
194
192
  const activePrompt = generateQuestions ? promptWithQuestions : promptWithoutQuestions;
195
-
196
- // console.log("Final Prompt Sent to API:", activePrompt);
197
-
198
- // Call the API and handle the response as before
199
193
  if (usePdfContext) {
200
194
  const getAiQueryResponse = await makeCandooAIQuery({
201
195
  modelName: "gpt-4",
@@ -218,7 +212,23 @@ function GenerateRoleplayDialog({
218
212
  } else {
219
213
  let chatGptResponse = await makeChatGptApiRequest({
220
214
  model: "gpt-3.5-turbo",
221
- prompt: activePrompt
215
+ promptKey: "generateRoleplay",
216
+ promptVariables: {
217
+ learnLang: learnLang,
218
+ i18nLanguage: i18nLanguage,
219
+ roleplayDifficulty: t(values.roleplayDifficulty),
220
+ usePdfContext: usePdfContext,
221
+ topicGoal: topicGoal,
222
+ usePhrasesContext: usePhrasesContext,
223
+ phrases: phrases,
224
+ questionLang: questionLang,
225
+ generateQuestions: generateQuestions,
226
+ actor1: values.actor1,
227
+ actor2: values.actor2,
228
+ roleplayTopic: values.roleplayTopic,
229
+ roleplayLengthNumber: values.roleplayLengthNumber,
230
+ questionsAmount: values.questionsAmount
231
+ }
222
232
  });
223
233
  let isComplete = false;
224
234
  while (!isComplete) {
@@ -236,7 +246,6 @@ function GenerateRoleplayDialog({
236
246
  }
237
247
 
238
248
  // Log the full response for debugging
239
- // console.log("Full API Response:", response);
240
249
 
241
250
  const jsonResponse = removeExtraTextFromChatGptResponse(response);
242
251
  const roleplayScript = fixMissingComma(jsonResponse);
@@ -21,6 +21,9 @@ const useStyles = (0, _mui.makeStyles)()(theme => ({
21
21
  margin: theme.spacing(1)
22
22
  },
23
23
  language: {
24
+ [theme.breakpoints.down("lg")]: {
25
+ display: "none"
26
+ },
24
27
  marginTop: "auto",
25
28
  marginBottom: "auto",
26
29
  marginLeft: theme.spacing(1),
@@ -114,7 +117,7 @@ function LanguageSelector({
114
117
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Translate.default, {})
115
118
  })
116
119
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_material.Hidden, {
117
- smDown: true,
120
+ mdDown: true,
118
121
  implementation: "js",
119
122
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
120
123
  className: classes.language,
@@ -155,11 +155,21 @@ function useRecognition(props = {}) {
155
155
  const initRecording = async (gcloudParams, onData, onError) => {
156
156
  try {
157
157
  await setupAudioContext();
158
+ const {
159
+ mediaDevices
160
+ } = navigator;
161
+ const [availableMicrophones, activeMicrophone, sampleRate] = await (0, _index.getMicrophoneInfo)(mediaDevices);
162
+ let sampleRateToUse = sampleRate;
163
+ if (sampleRate && sampleRate < 8000) {
164
+ sampleRateToUse = 8000;
165
+ } else if (sampleRate && sampleRate > 48000) {
166
+ sampleRateToUse = 48000;
167
+ }
158
168
  const handleSuccess = function (stream) {
159
169
  const gcloudConfig = {
160
170
  config: {
161
171
  encoding: "LINEAR16",
162
- sampleRateHertz: 16000,
172
+ sampleRateHertz: sampleRateToUse || 16000,
163
173
  languageCode: gcloudParams.languageCode || "en-US",
164
174
  profanityFilter: true,
165
175
  enableWordTimeOffsets: false,
@@ -172,7 +182,6 @@ function useRecognition(props = {}) {
172
182
  interimResults: gcloudParams.interimResults // If you want interim results, set this to true
173
183
  };
174
184
  socket.emit("startGoogleCloudStream", gcloudConfig, version); // init socket Google Speech Connection
175
-
176
185
  streamRef.current = stream;
177
186
  audioInputRef.current = audioContextRef.current.createMediaStreamSource(stream);
178
187
  serverErrorRef.current = null;
@@ -446,7 +446,7 @@ const getMachineInfo = userAgent => {
446
446
  exports.getMachineInfo = getMachineInfo;
447
447
  const getMicrophoneInfo = async mediaDevices => {
448
448
  try {
449
- await mediaDevices.getUserMedia({
449
+ const stream = await mediaDevices.getUserMedia({
450
450
  audio: true
451
451
  });
452
452
  const devices = await mediaDevices.enumerateDevices();
@@ -454,7 +454,13 @@ const getMicrophoneInfo = async mediaDevices => {
454
454
  const availableMicrophoneNames = microphones?.filter(device => device.deviceId !== "default").map(device => device.label).join(", ") || "No available microphones detected";
455
455
  const activeMicrophone = microphones?.length > 0 ? microphones.find(mic => mic.deviceId === "default") || microphones[0] : null;
456
456
  const activeMicrophoneName = activeMicrophone?.label.split("Default - ").pop() || "No active microphone detected";
457
- return [availableMicrophoneNames, activeMicrophoneName];
457
+
458
+ // Create an AudioContext with the stream from the active microphone
459
+ const sampleRate = stream.getAudioTracks()[0].getSettings().sampleRate;
460
+
461
+ // Stop the audio stream to release the microphone
462
+ stream.getTracks().forEach(track => track.stop());
463
+ return [availableMicrophoneNames, activeMicrophoneName, sampleRate];
458
464
  } catch (error) {
459
465
  console.error("Error accessing the microphone:", error);
460
466
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nualang/nualang-ui-components",
3
- "version": "0.1.1207",
3
+ "version": "0.1.1209",
4
4
  "main": "dist/index.js",
5
5
  "files": [
6
6
  "dist",