diff --git a/packages/react/src/components/layout/InlayContainer.tsx b/packages/react/src/components/layout/InlayContainer.tsx index 787e85a04..b76b51697 100644 --- a/packages/react/src/components/layout/InlayContainer.tsx +++ b/packages/react/src/components/layout/InlayContainer.tsx @@ -1,4 +1,4 @@ -import { DetailedHTMLProps, HTMLAttributes, Suspense, useState } from "react"; +import { DetailedHTMLProps, HTMLAttributes, Suspense } from "react"; import { Loading } from "../common/Loading"; import { Link, Outlet, useLocation, useNavigate } from "react-router-dom"; import { Button } from "@/shadcn/ui/button"; diff --git a/packages/react/src/components/settings/SettingsItem.tsx b/packages/react/src/components/settings/SettingsItem.tsx new file mode 100644 index 000000000..9893f160e --- /dev/null +++ b/packages/react/src/components/settings/SettingsItem.tsx @@ -0,0 +1,15 @@ +import { Children, ReactNode } from "react"; + +interface SettingsItemProps { + label: string; + children: ReactNode; +} + +export function SettingsItem({ label, children }: SettingsItemProps) { + return ( +
+

{label}

+ {Children.only(children)} +
+ ); +} diff --git a/packages/react/src/locales/en/ui.yml b/packages/react/src/locales/en/ui.yml index 5036b6856..4bb23ae92 100644 --- a/packages/react/src/locales/en/ui.yml +++ b/packages/react/src/locales/en/ui.yml @@ -331,6 +331,11 @@ views: ignoredTopicsMsg: Hide videos with these topics from the Home and Favorites pages theme: Theme moreSettings: More Settings + user: User & Account + homepage: Homepage & Filters + blockedChannels: Blocked Channels + languageSearch: Search language... + languageNotfound: No language found app: update_available: An update is available update_btn: Update diff --git a/packages/react/src/routes/router.tsx b/packages/react/src/routes/router.tsx index 615d0ce0a..423e068fc 100644 --- a/packages/react/src/routes/router.tsx +++ b/packages/react/src/routes/router.tsx @@ -8,6 +8,7 @@ import React from "react"; const Login = React.lazy(() => import("./login")); const Settings = React.lazy(() => import("./settings")); +const SettingsLang = React.lazy(() => import("./settings/lang")); const About = React.lazy(() => import("./about")); const AboutGeneral = React.lazy(() => import("./about/general")); const AboutChangelog = React.lazy(() => import("./about/changelog")); @@ -82,6 +83,10 @@ const router = createBrowserRouter([ path: "settings", element: , children: [ + { + path: "lang", + element: , + }, // Add children routes similar to above pattern ], }, diff --git a/packages/react/src/routes/settings.tsx b/packages/react/src/routes/settings.tsx deleted file mode 100644 index 9025eb7e9..000000000 --- a/packages/react/src/routes/settings.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { Outlet } from "react-router-dom"; - -export default function Settings() { - return ( -
- Settings -
- ); -} diff --git a/packages/react/src/routes/settings/index.tsx b/packages/react/src/routes/settings/index.tsx new file mode 100644 index 000000000..b927058c0 --- /dev/null +++ b/packages/react/src/routes/settings/index.tsx @@ -0,0 +1,43 @@ +import { + InlayContainer, + InlayContainerRoutes, +} from "@/components/layout/InlayContainer"; +import { useMemo } from "react"; +import { useTranslation } from "react-i18next"; + +export default function Settings() { + const { t } = useTranslation(); + + const routes: InlayContainerRoutes[] = useMemo( + () => [ + { + icon: "i-heroicons:language", + href: "/settings/lang", + label: t("views.settings.languageSettings"), + }, + { + icon: "i-heroicons:moon", + href: "/settings/themes", + label: t("views.settings.theme"), + }, + { + icon: "i-heroicons:user", + href: "/settings/user", + label: t("views.settings.user"), + }, + { + icon: "i-heroicons:funnel", + href: "/settings/homepage", + label: t("views.settings.homepage"), + }, + { + icon: "i-heroicons:eye-slash", + href: "/settings/blocked", + label: t("views.settings.blockedChannels"), + }, + ], + [t], + ); + + return ; +} diff --git a/packages/react/src/routes/settings/lang.tsx b/packages/react/src/routes/settings/lang.tsx new file mode 100644 index 000000000..be4eee6ff --- /dev/null +++ b/packages/react/src/routes/settings/lang.tsx @@ -0,0 +1,124 @@ +import { SettingsItem } from "@/components/settings/SettingsItem"; +import { TL_LANGS } from "@/lib/consts"; +import { langs } from "@/lib/i18n"; +import { cn } from "@/lib/utils"; +import { Button } from "@/shadcn/ui/button"; +import { Checkbox } from "@/shadcn/ui/checkbox"; +import { + Command, + CommandEmpty, + CommandGroup, + CommandInput, + CommandItem, +} from "@/shadcn/ui/command"; +import { Label } from "@/shadcn/ui/label"; +import { Popover, PopoverContent, PopoverTrigger } from "@/shadcn/ui/popover"; +import { Switch } from "@/shadcn/ui/switch"; +import { clipLanguageAtom, englishNameAtom } from "@/store/settings"; +import { useAtom } from "jotai"; +import { useState } from "react"; +import { useTranslation } from "react-i18next"; + +export default function SettingsLang() { + const [useENName, setUseENName] = useAtom(englishNameAtom); + const [clipLangs, setClipLangs] = useAtom(clipLanguageAtom); + const [langOpen, setLangOpen] = useState(false); + const { i18n, t } = useTranslation(); + + return ( +
+ +
+ + + + + + + + + {t("views.settings.languageNotfound")} + + + {langs.map(({ val, display }) => ( + { + i18n.changeLanguage(val); + setLangOpen(false); + }} + > +
+ {display} + + ))} + + + + +
+
+ {langs.find(({ val }) => i18n.language === val)?.credit} +
+
+ + +
+ +
+ +
+ + +
+ {TL_LANGS.map(({ text, value }, index) => ( + + ))} +
+
+
+ ); +} diff --git a/packages/react/src/store/i18n.ts b/packages/react/src/store/i18n.ts index a7532b3de..455e2673e 100644 --- a/packages/react/src/store/i18n.ts +++ b/packages/react/src/store/i18n.ts @@ -1,7 +1,7 @@ import dayjs from "dayjs"; import { atom, useSetAtom } from "jotai"; import type { i18n } from "i18next"; -import { useCallback, useEffect } from "react"; +import { useEffect } from "react"; import { useTranslation } from "react-i18next"; export const localeAtom = atom({ diff --git a/packages/react/src/store/settings.ts b/packages/react/src/store/settings.ts index a09fcd548..3f5039ba9 100644 --- a/packages/react/src/store/settings.ts +++ b/packages/react/src/store/settings.ts @@ -1,5 +1,7 @@ import { atom } from "jotai"; +export const englishNameAtom = atom(false); +export const clipLanguageAtom = atom([]); export const redirectModeAtom = atom(false); export const hideThumbnailAtom = atom(false); export const hidePlaceholderAtom = atom(false);