'use client' import type { PluginDetail } from '../../types' import { Button } from '@langgenius/dify-ui/button' import { cn } from '@langgenius/dify-ui/cn' import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip' import { useQuery } from '@tanstack/react-query' import { useCallback, useMemo } from 'react' import { useTranslation } from 'react-i18next' import ActionButton from '@/app/components/base/action-button' import Badge from '@/app/components/base/badge' import { AuthCategory, PluginAuth } from '@/app/components/plugins/plugin-auth' import { OperationDropdown } from '@/app/components/plugins/plugin-detail-panel/operation-dropdown' import { BUILTIN_TOOLS_ARRAY } from '@/app/components/plugins/readme-panel/constants' import { useReadmePanelStore } from '@/app/components/plugins/readme-panel/store' import PluginVersionPicker from '@/app/components/plugins/update-plugin/plugin-version-picker' import { API_PREFIX } from '@/config' import { useGetLanguage, useLocale } from '@/context/i18n' import { userProfileQueryOptions } from '@/features/account-profile/client' import useTheme from '@/hooks/use-theme' import { useAllToolProviders } from '@/service/use-tools' import { getMarketplaceUrl } from '@/utils/var' import { AutoUpdateLine } from '../../../base/icons/src/vender/system' import Verified from '../../base/badges/verified' import DeprecationNotice from '../../base/deprecation-notice' import Icon from '../../card/base/card-icon' import Description from '../../card/base/description' import OrgInfo from '../../card/base/org-info' import Title from '../../card/base/title' import useReferenceSetting from '../../plugin-page/use-reference-setting' import { convertUTCDaySecondsToLocalSeconds, timeOfDayToDayjs, } from '../../reference-setting-modal/auto-update-setting/utils' import { PluginCategoryEnum, PluginSource } from '../../types' import { HeaderModals, PluginSourceBadge } from './components' import { useDetailHeaderState, usePluginOperations } from './hooks' type Props = Readonly<{ canDeletePlugin?: boolean canUpdatePlugin?: boolean detail: PluginDetail isReadmeView?: boolean onHide?: () => void onUpdate?: (isDelete?: boolean) => void }> const getIconSrc = ( icon: string | undefined, iconDark: string | undefined, theme: string, tenantId: string, ): string => { const iconFileName = theme === 'dark' && iconDark ? iconDark : icon if (!iconFileName) return '' return iconFileName.startsWith('http') ? iconFileName : `${API_PREFIX}/workspaces/current/plugin/icon?tenant_id=${tenantId}&filename=${iconFileName}` } const getDetailUrl = ( source: PluginSource, meta: PluginDetail['meta'], author: string, name: string, locale: string, theme: string, ): string => { if (source === PluginSource.github) { const repo = meta?.repo if (!repo) return '' return `https://github.com/${repo}` } if (source === PluginSource.marketplace) return getMarketplaceUrl(`/plugins/${author}/${name}`, { language: locale, theme }) return '' } const DetailHeader = ({ canDeletePlugin = true, canUpdatePlugin = true, detail, isReadmeView = false, onHide, onUpdate, }: Props) => { const { t } = useTranslation() const openReadmePanel = useReadmePanelStore((s) => s.openReadmePanel) const { data: timezone } = useQuery({ ...userProfileQueryOptions(), select: (data) => data.profile.timezone ?? undefined, }) const { theme } = useTheme() const locale = useGetLanguage() const currentLocale = useLocale() const detailCategory = detail.declaration?.category ?? PluginCategoryEnum.tool const { referenceSetting } = useReferenceSetting(detailCategory) const { source, tenant_id, version, latest_version, latest_unique_identifier, meta, plugin_id, status, deprecated_reason, alternative_plugin_id, } = detail const { author, category, name, label, description, icon, icon_dark, verified, tool } = detail.declaration || detail const { modalStates, versionPicker, hasNewVersion, isAutoUpgradeEnabled, isFromGitHub, isFromMarketplace, } = useDetailHeaderState(detail) const { handleUpdate, handleUpdatedFromMarketplace, handleDelete } = usePluginOperations({ detail, modalStates, versionPicker, isFromMarketplace, canDeletePlugin, canUpdatePlugin, onUpdate, }) const isTool = category === PluginCategoryEnum.tool const providerBriefInfo = tool?.identity const providerKey = `${plugin_id}/${providerBriefInfo?.name}` const { data: collectionList = [] } = useAllToolProviders(isTool) const provider = useMemo(() => { return collectionList.find((collection) => collection.name === providerKey) }, [collectionList, providerKey]) const iconSrc = getIconSrc(icon, icon_dark, theme, tenant_id) const detailUrl = getDetailUrl(source, meta, author, name, currentLocale, theme) const canViewReadme = !!detail.plugin_unique_identifier && !BUILTIN_TOOLS_ARRAY.includes(detail.id) const { auto_upgrade: autoUpgradeInfo } = referenceSetting || {} const handleViewReadme = useCallback(() => { openReadmePanel({ detail, presentation: 'drawer', }) }, [detail, openReadmePanel]) const handleVersionSelect = (state: { version: string unique_identifier: string isDowngrade?: boolean }) => { versionPicker.setTargetVersion(state) handleUpdate(state.isDowngrade) } const handleTriggerLatestUpdate = () => { if (isFromMarketplace) { versionPicker.setTargetVersion({ version: latest_version, unique_identifier: latest_unique_identifier, }) } handleUpdate() } return (