import { ArchiveIcon, LogOutIcon, User2Icon, SquareUserIcon, SettingsIcon, GlobeIcon, PaletteIcon, CheckIcon } from "lucide-react"; import { observer } from "mobx-react-lite"; import { authServiceClient } from "@/grpcweb"; import useCurrentUser from "@/hooks/useCurrentUser"; import useNavigateTo from "@/hooks/useNavigateTo"; import { locales } from "@/i18n"; import { cn } from "@/lib/utils"; import { Routes } from "@/router"; import { userStore, instanceStore } from "@/store"; import { getLocaleDisplayName, useTranslate } from "@/utils/i18n"; import { THEME_OPTIONS } from "@/utils/theme"; import UserAvatar from "./UserAvatar"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, } from "./ui/dropdown-menu"; interface Props { collapsed?: boolean; } const UserMenu = observer((props: Props) => { const { collapsed } = props; const t = useTranslate(); const navigateTo = useNavigateTo(); const currentUser = useCurrentUser(); const generalSetting = userStore.state.userGeneralSetting; const currentLocale = generalSetting?.locale || "en"; const currentTheme = generalSetting?.theme || "default"; const handleLocaleChange = async (locale: Locale) => { // Update instance store immediately for instant UI feedback instanceStore.state.setPartial({ locale }); // Persist to user settings await userStore.updateUserGeneralSetting({ locale }, ["locale"]); }; const handleThemeChange = async (theme: string) => { await userStore.updateUserGeneralSetting({ theme }, ["theme"]); }; const handleSignOut = async () => { await authServiceClient.deleteSession({}); // Clear user-specific localStorage items (e.g., drafts) // Preserve app-wide settings like theme const keysToPreserve = ["memos-theme", "tag-view-as-tree", "tag-tree-auto-expand", "viewStore"]; const keysToRemove: string[] = []; for (let i = 0; i < localStorage.length; i++) { const key = localStorage.key(i); if (key && !keysToPreserve.includes(key)) { keysToRemove.push(key); } } keysToRemove.forEach((key) => localStorage.removeItem(key)); window.location.href = Routes.AUTH; }; return (
{currentUser.avatarUrl ? ( ) : ( )} {!collapsed && ( {currentUser.displayName || currentUser.username} )}
navigateTo(`/u/${encodeURIComponent(currentUser.username)}`)}> {t("common.profile")} navigateTo(Routes.ARCHIVED)}> {t("common.archived")} {t("common.language")} {locales.map((locale) => ( handleLocaleChange(locale)}> {currentLocale === locale && } {currentLocale !== locale && } {getLocaleDisplayName(locale)} ))} {t("setting.preference-section.theme")} {THEME_OPTIONS.map((option) => ( handleThemeChange(option.value)}> {currentTheme === option.value && } {currentTheme !== option.value && } {option.label} ))} navigateTo(Routes.SETTING)}> {t("common.settings")} {t("common.sign-out")}
); }); export default UserMenu;