import { CogIcon, DatabaseIcon, HeartHandshakeIcon, KeyIcon, LibraryIcon, LucideIcon, Settings2Icon, TagsIcon, UserIcon, UsersIcon, WebhookIcon, } from "lucide-react"; import { useEffect, useMemo, useState } from "react"; import { useLocation } from "react-router-dom"; import MobileHeader from "@/components/MobileHeader"; import AISection from "@/components/Settings/AISection"; import InstanceSection from "@/components/Settings/InstanceSection"; import MemberSection from "@/components/Settings/MemberSection"; import MemoRelatedSettings from "@/components/Settings/MemoRelatedSettings"; import MyAccountSection from "@/components/Settings/MyAccountSection"; import PreferencesSection from "@/components/Settings/PreferencesSection"; import SectionMenuItem from "@/components/Settings/SectionMenuItem"; import SSOSection from "@/components/Settings/SSOSection"; import StorageSection from "@/components/Settings/StorageSection"; import TagsSection from "@/components/Settings/TagsSection"; import WebhookSection from "@/components/Settings/WebhookSection"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { useInstance } from "@/contexts/InstanceContext"; import useCurrentUser from "@/hooks/useCurrentUser"; import useMediaQuery from "@/hooks/useMediaQuery"; import { InstanceSetting_Key } from "@/types/proto/api/v1/instance_service_pb"; import { User_Role } from "@/types/proto/api/v1/user_service_pb"; import { useTranslate } from "@/utils/i18n"; type SettingSection = "my-account" | "preference" | "webhook" | "member" | "system" | "memo" | "storage" | "sso" | "tags" | "ai"; const BASIC_SECTIONS: SettingSection[] = ["my-account", "preference", "webhook"]; const ADMIN_SECTIONS: SettingSection[] = ["member", "system", "memo", "tags", "storage", "sso", "ai"]; const SECTION_ICON_MAP: Record = { "my-account": UserIcon, preference: CogIcon, webhook: WebhookIcon, member: UsersIcon, system: Settings2Icon, memo: LibraryIcon, storage: DatabaseIcon, tags: TagsIcon, sso: KeyIcon, ai: HeartHandshakeIcon, }; const SECTION_COMPONENT_MAP: Record = { "my-account": MyAccountSection, preference: PreferencesSection, webhook: WebhookSection, member: MemberSection, system: InstanceSection, memo: MemoRelatedSettings, storage: StorageSection, tags: TagsSection, sso: SSOSection, ai: AISection, }; const Setting = () => { const t = useTranslate(); const sm = useMediaQuery("sm"); const location = useLocation(); const user = useCurrentUser(); const { profile, fetchSetting } = useInstance(); const [selectedSection, setSelectedSection] = useState("my-account"); const isHost = user?.role === User_Role.ADMIN; const settingsSectionList = useMemo(() => { return isHost ? [...BASIC_SECTIONS, ...ADMIN_SECTIONS] : [...BASIC_SECTIONS]; }, [isHost]); useEffect(() => { const hash = location.hash.slice(1) as SettingSection; const nextSection = settingsSectionList.includes(hash) ? hash : "my-account"; setSelectedSection(nextSection); }, [location.hash, settingsSectionList]); useEffect(() => { if (!isHost) { return; } // Fetch admin-only settings that are not eagerly loaded by InstanceContext. fetchSetting(InstanceSetting_Key.STORAGE); fetchSetting(InstanceSetting_Key.TAGS); fetchSetting(InstanceSetting_Key.AI); }, [isHost, fetchSetting]); const handleSectionSelectorItemClick = (section: SettingSection) => { window.location.hash = section; }; const ActiveSection = SECTION_COMPONENT_MAP[selectedSection]; return (
{!sm && }
{sm && (
{t("common.basic")}
{BASIC_SECTIONS.map((item) => ( handleSectionSelectorItemClick(item)} /> ))}
{isHost && ( <> {t("common.admin")}
{ADMIN_SECTIONS.map((item) => ( handleSectionSelectorItemClick(item)} /> ))} {t("setting.version")}: v{profile.version}
)}
)}
{!sm && (
)}
); }; export default Setting;