Feat: Settings for learning lang (#641)

* refactor settings

* refactor constants

* add settings for native/learning language

* setup langugage for transcribe

* use 2 letter code for echogarden

* AI commands support multiple language

* update languages constant

* fix sentry error

* fix context menu

* show camdict when only learning English

* add en-GB

* recording assess support multiple languages

* fix ai command

* refactor
This commit is contained in:
an-lee
2024-05-29 15:13:52 +08:00
committed by GitHub
parent ef0bfa6544
commit d8231ca97c
33 changed files with 679 additions and 420 deletions

View File

@@ -1,5 +1,8 @@
import { useContext } from "react";
import { MediaPlayerProviderContext } from "@renderer/context";
import {
AppSettingsProviderContext,
MediaPlayerProviderContext,
} from "@renderer/context";
import { TabsContent, Separator } from "@renderer/components/ui";
import { t } from "i18next";
import { TimelineEntry } from "echogarden/dist/utilities/Timeline";
@@ -38,6 +41,7 @@ const SelectedWords = (props: {
const { selectedIndices, caption } = props;
const { transcription, ipaMappings } = useContext(MediaPlayerProviderContext);
const { learningLanguage } = useContext(AppSettingsProviderContext);
const word = selectedIndices
.map((index) => caption.timeline[index]?.text || "")
@@ -92,8 +96,12 @@ const SelectedWords = (props: {
})}
</div>
<Separator className="my-2" />
<CamdictLookupResult word={word} />
{learningLanguage.startsWith("en") && (
<>
<Separator className="my-2" />
<CamdictLookupResult word={word} />
</>
)}
<Separator className="my-2" />
<AiLookupResult

View File

@@ -5,9 +5,12 @@ export * from "./appearance";
export * from "./hotkeys";
export * from "./hotkeys-settings";
export * from "./language-settings";
export * from "./native-language-settings";
export * from "./learning-language-settings";
export * from "./default-engine-settings";
export * from "./openai-settings";
export * from "./language-settings";
export * from "./library-settings";
export * from "./whisper-settings";
export * from "./google-generative-ai-settings";

View File

@@ -0,0 +1,56 @@
import { t } from "i18next";
import {
Select,
SelectTrigger,
SelectItem,
SelectValue,
SelectContent,
} from "@renderer/components/ui";
import { AppSettingsProviderContext } from "@renderer/context";
import { useContext } from "react";
import { LANGUAGES } from "@/constants";
export const LearningLanguageSettings = () => {
const { learningLanguage, switchLearningLanguage } = useContext(
AppSettingsProviderContext
);
return (
<div className="flex items-start justify-between py-4">
<div className="">
<div className="mb-2">{t("learningLanguage")}</div>
<div className="text-sm text-muted-foreground mb-2">
{LANGUAGES.find((lang) => lang.code === learningLanguage)?.name}
</div>
</div>
<div className="">
<div className="flex items-center justify-end space-x-2 mb-2">
<Select
value={learningLanguage}
onValueChange={(value) => {
switchLearningLanguage(value);
}}
>
<SelectTrigger className="text-xs">
<SelectValue>
{LANGUAGES.find((lang) => lang.code === learningLanguage)?.name}
</SelectValue>
</SelectTrigger>
<SelectContent>
{LANGUAGES.map((lang) => (
<SelectItem
className="text-xs"
value={lang.code}
key={lang.code}
>
{lang.name}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
</div>
</div>
);
};

View File

@@ -0,0 +1,56 @@
import { t } from "i18next";
import {
Select,
SelectTrigger,
SelectItem,
SelectValue,
SelectContent,
} from "@renderer/components/ui";
import { AppSettingsProviderContext } from "@renderer/context";
import { useContext } from "react";
import { LANGUAGES } from "@/constants";
export const NativeLanguageSettings = () => {
const { nativeLanguage, switchNativeLanguage } = useContext(
AppSettingsProviderContext
);
return (
<div className="flex items-start justify-between py-4">
<div className="">
<div className="mb-2">{t("nativeLanguage")}</div>
<div className="text-sm text-muted-foreground mb-2">
{LANGUAGES.find((lang) => lang.code === nativeLanguage)?.name}
</div>
</div>
<div className="">
<div className="flex items-center justify-end space-x-2 mb-2">
<Select
value={nativeLanguage}
onValueChange={(value) => {
switchNativeLanguage(value);
}}
>
<SelectTrigger className="text-xs">
<SelectValue>
{LANGUAGES.find((lang) => lang.code === nativeLanguage)?.name}
</SelectValue>
</SelectTrigger>
<SelectContent>
{LANGUAGES.map((lang) => (
<SelectItem
className="text-xs"
value={lang.code}
key={lang.code}
>
{lang.name}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
</div>
</div>
);
};

View File

@@ -14,6 +14,8 @@ import {
GoogleGenerativeAiSettings,
ResetSettings,
ResetAllSettings,
NativeLanguageSettings,
LearningLanguageSettings,
} from "@renderer/components";
import { useState } from "react";
import { Tooltip } from "react-tooltip";
@@ -29,6 +31,10 @@ export const Preferences = () => {
<div className="font-semibold mb-4 capitilized">
{t("basicSettings")}
</div>
<NativeLanguageSettings />
<Separator />
<LearningLanguageSettings />
<Separator />
<WhisperSettings />
<Separator />
<DefaultEngineSettings />
@@ -108,8 +114,9 @@ export const Preferences = () => {
key={tab.value}
variant={activeTab === tab.value ? "default" : "ghost"}
size="sm"
className={`capitilized w-full justify-start mb-2 ${activeTab === tab.value ? "" : "hover:bg-muted"
}`}
className={`capitilized w-full justify-start mb-2 ${
activeTab === tab.value ? "" : "hover:bg-muted"
}`}
onClick={() => setActiveTab(tab.value)}
>
<span className="text-sm">{tab.label}</span>

View File

@@ -21,12 +21,12 @@ export const RecordingDetail = (props: { recording: RecordingType }) => {
}>();
const [isPlaying, setIsPlaying] = useState(false);
const { EnjoyApp } = useContext(AppSettingsProviderContext);
const { EnjoyApp, learningLanguage } = useContext(AppSettingsProviderContext);
const [assessing, setAssessing] = useState(false);
const assess = () => {
setAssessing(true);
EnjoyApp.recordings.assess(recording.id).finally(() => {
EnjoyApp.recordings.assess(recording.id, learningLanguage).finally(() => {
setAssessing(false);
});
};

View File

@@ -15,7 +15,7 @@ import { t } from "i18next";
import { md5 } from "js-md5";
export const LookupWidget = () => {
const { EnjoyApp } = useContext(AppSettingsProviderContext);
const { EnjoyApp, learningLanguage } = useContext(AppSettingsProviderContext);
const [open, setOpen] = useState(false);
const [selected, setSelected] = useState<{
word: string;
@@ -82,8 +82,12 @@ export const LookupWidget = () => {
{selected?.word}
</div>
<div className="px-4">
<CamdictLookupResult word={selected?.word} />
<Separator className="my-2" />
{learningLanguage.startsWith("en") && (
<>
<CamdictLookupResult word={selected?.word} />
<Separator className="my-2" />
</>
)}
<AiLookupResult
word={selected?.word}
context={selected?.context}