mirror of
https://github.com/langgenius/dify.git
synced 2026-06-21 01:41:08 +08:00
Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: yyh <yuanyouhuilyz@gmail.com> Co-authored-by: Joel <iamjoel007@gmail.com> Co-authored-by: hjlarry <hjlarry@163.com> Co-authored-by: fatelei <fatelei@gmail.com> Co-authored-by: Asuka Minato <i@asukaminato.eu.org> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Xiyuan Chen <52963600+GareArc@users.noreply.github.com> Co-authored-by: gigglewang <gigglewang@dify.ai> Co-authored-by: Yunlu Wen <yunlu.wen@dify.ai> Co-authored-by: chariri <w@chariri.moe> Co-authored-by: Evan <2869018789@qq.com> Co-authored-by: yyh <92089059+lyzno1@users.noreply.github.com>
156 lines
6.0 KiB
TypeScript
156 lines
6.0 KiB
TypeScript
'use client'
|
|
|
|
import type { ReactNode } from 'react'
|
|
import type { Theme } from '@/app/components/base/theme-selector'
|
|
import { Avatar } from '@langgenius/dify-ui/avatar'
|
|
import { cn } from '@langgenius/dify-ui/cn'
|
|
import {
|
|
DropdownMenuGroup,
|
|
DropdownMenuItem,
|
|
DropdownMenuLinkItem,
|
|
DropdownMenuRadioGroup,
|
|
DropdownMenuRadioItem,
|
|
DropdownMenuRadioItemIndicator,
|
|
DropdownMenuSeparator,
|
|
DropdownMenuSub,
|
|
DropdownMenuSubContent,
|
|
DropdownMenuSubTrigger,
|
|
} from '@langgenius/dify-ui/dropdown-menu'
|
|
import { useTheme } from 'next-themes'
|
|
import { useTranslation } from 'react-i18next'
|
|
import PremiumBadge from '@/app/components/base/premium-badge'
|
|
import { ACCOUNT_SETTING_TAB } from '@/app/components/header/account-setting/constants'
|
|
import { useAppContext } from '@/context/app-context'
|
|
import { useModalContext } from '@/context/modal-context'
|
|
import { useProviderContext } from '@/context/provider-context'
|
|
import Link from '@/next/link'
|
|
import { ExternalLinkIndicator, MenuItemContent } from './menu-item-content'
|
|
|
|
const mainNavMenuGroupClassName = 'p-1'
|
|
const mainNavMenuItemClassName = 'mx-0 h-8 gap-1 px-3 py-1'
|
|
const mainNavMenuSubPopupClassName = 'w-60 max-h-[360px] bg-components-panel-bg-blur! p-1! backdrop-blur-[5px]'
|
|
|
|
type MainNavRadioItemContentProps = {
|
|
iconClassName?: string
|
|
label: ReactNode
|
|
}
|
|
|
|
function MainNavRadioItemContent({
|
|
iconClassName,
|
|
label,
|
|
}: MainNavRadioItemContentProps) {
|
|
const labelTitle = typeof label === 'string' ? label : undefined
|
|
|
|
return (
|
|
<>
|
|
{iconClassName && <span aria-hidden className={cn('size-4 shrink-0 text-text-tertiary', iconClassName)} />}
|
|
<span className="min-w-0 grow truncate px-1 system-md-regular text-text-secondary" title={labelTitle}>{label}</span>
|
|
<DropdownMenuRadioItemIndicator />
|
|
</>
|
|
)
|
|
}
|
|
|
|
function AppearanceSubmenu() {
|
|
const { t } = useTranslation()
|
|
const { theme, setTheme } = useTheme()
|
|
|
|
return (
|
|
<DropdownMenuSub>
|
|
<DropdownMenuSubTrigger className={mainNavMenuItemClassName}>
|
|
<MenuItemContent
|
|
iconClassName="i-ri-sun-line"
|
|
label={t('account.appearanceLabel', { ns: 'common' })}
|
|
/>
|
|
</DropdownMenuSubTrigger>
|
|
<DropdownMenuSubContent
|
|
placement="right-start"
|
|
sideOffset={6}
|
|
popupClassName={mainNavMenuSubPopupClassName}
|
|
>
|
|
<DropdownMenuRadioGroup value={theme || 'system'} onValueChange={value => setTheme(value as Theme)}>
|
|
<DropdownMenuRadioItem value="light" closeOnClick className={mainNavMenuItemClassName}>
|
|
<MainNavRadioItemContent iconClassName="i-ri-sun-line" label={t('account.appearanceLight', { ns: 'common' })} />
|
|
</DropdownMenuRadioItem>
|
|
<DropdownMenuRadioItem value="dark" closeOnClick className={mainNavMenuItemClassName}>
|
|
<MainNavRadioItemContent iconClassName="i-ri-moon-line" label={t('account.appearanceDark', { ns: 'common' })} />
|
|
</DropdownMenuRadioItem>
|
|
<DropdownMenuRadioItem value="system" closeOnClick className={mainNavMenuItemClassName}>
|
|
<MainNavRadioItemContent iconClassName="i-ri-computer-line" label={t('account.appearanceSystem', { ns: 'common' })} />
|
|
</DropdownMenuRadioItem>
|
|
</DropdownMenuRadioGroup>
|
|
</DropdownMenuSubContent>
|
|
</DropdownMenuSub>
|
|
)
|
|
}
|
|
|
|
type MainNavMenuContentProps = {
|
|
onLogout: () => Promise<void>
|
|
}
|
|
|
|
export function MainNavMenuContent({
|
|
onLogout,
|
|
}: MainNavMenuContentProps) {
|
|
const { t } = useTranslation()
|
|
const { userProfile } = useAppContext()
|
|
const { isEducationAccount } = useProviderContext()
|
|
const { setShowAccountSettingModal } = useModalContext()
|
|
|
|
return (
|
|
<>
|
|
<DropdownMenuGroup className={mainNavMenuGroupClassName}>
|
|
<div className="flex items-center gap-3 rounded-xl bg-gradient-to-b from-background-section-burn to-background-section p-3">
|
|
<div className="flex min-w-0 grow flex-col gap-1">
|
|
<div className="flex min-w-0 items-center gap-1">
|
|
<div className="min-w-0 flex-1 truncate body-md-medium text-text-primary" title={userProfile.name}>{userProfile.name}</div>
|
|
{isEducationAccount && (
|
|
<PremiumBadge size="s" color="blue" className="shrink-0 px-2!">
|
|
<span aria-hidden className="mr-1 i-ri-graduation-cap-fill h-3 w-3" />
|
|
<span className="system-2xs-medium">EDU</span>
|
|
</PremiumBadge>
|
|
)}
|
|
</div>
|
|
<div className="truncate system-xs-regular text-text-tertiary" title={userProfile.email}>{userProfile.email}</div>
|
|
</div>
|
|
<Avatar avatar={userProfile.avatar_url} name={userProfile.name} size="lg" className="shrink-0" />
|
|
</div>
|
|
</DropdownMenuGroup>
|
|
<DropdownMenuGroup className={mainNavMenuGroupClassName}>
|
|
<DropdownMenuLinkItem
|
|
className={cn('justify-between', mainNavMenuItemClassName)}
|
|
render={<Link href="/account" />}
|
|
>
|
|
<MenuItemContent
|
|
iconClassName="i-ri-account-circle-line"
|
|
label={t('account.account', { ns: 'common' })}
|
|
trailing={<ExternalLinkIndicator />}
|
|
/>
|
|
</DropdownMenuLinkItem>
|
|
<DropdownMenuItem
|
|
className={mainNavMenuItemClassName}
|
|
onClick={() => setShowAccountSettingModal({ payload: ACCOUNT_SETTING_TAB.LANGUAGE })}
|
|
>
|
|
<MenuItemContent
|
|
iconClassName="i-ri-equalizer-2-line"
|
|
label={t('settings.preferences', { ns: 'common' })}
|
|
/>
|
|
</DropdownMenuItem>
|
|
<AppearanceSubmenu />
|
|
</DropdownMenuGroup>
|
|
<DropdownMenuSeparator className="my-0! bg-divider-subtle" />
|
|
<DropdownMenuGroup className={mainNavMenuGroupClassName}>
|
|
<DropdownMenuItem
|
|
className={mainNavMenuItemClassName}
|
|
onClick={() => {
|
|
void onLogout()
|
|
}}
|
|
>
|
|
<MenuItemContent
|
|
iconClassName="i-ri-shut-down-line"
|
|
label={t('userProfile.logout', { ns: 'common' })}
|
|
/>
|
|
</DropdownMenuItem>
|
|
</DropdownMenuGroup>
|
|
</>
|
|
)
|
|
}
|