'use client' import { AlertDialog, AlertDialogActions, AlertDialogCancelButton, AlertDialogConfirmButton, AlertDialogContent, AlertDialogDescription, AlertDialogTitle, } from '@langgenius/dify-ui/alert-dialog' import { cn } from '@langgenius/dify-ui/cn' import { ScrollArea } from '@langgenius/dify-ui/scroll-area' import { toast } from '@langgenius/dify-ui/toast' import { useBoolean } from 'ahooks' import * as React from 'react' import { useState } from 'react' import { useTranslation } from 'react-i18next' import Divider from '@/app/components/base/divider' import Link from '@/next/link' import { usePathname, useSelectedLayoutSegments } from '@/next/navigation' import { useGetInstalledApps, useUninstallApp, useUpdateAppPinStatus } from '@/service/use-explore' import Item from './app-nav-item' import NoApps from './no-apps' const SideBar = () => { const { t } = useTranslation() const pathname = usePathname() const segments = useSelectedLayoutSegments() const lastSegment = segments.slice(-1)[0] const isDiscoverySelected = pathname === '/' || lastSegment === 'apps' const { data, isPending } = useGetInstalledApps() const installedApps = data?.installed_apps ?? [] const { mutateAsync: uninstallApp, isPending: isUninstalling } = useUninstallApp() const { mutateAsync: updatePinStatus } = useUpdateAppPinStatus() const [isFold, { toggle: toggleIsFold }] = useBoolean(false) const [showConfirm, setShowConfirm] = useState(false) const [currId, setCurrId] = useState('') const handleDelete = async () => { const id = currId await uninstallApp(id) setShowConfirm(false) toast.success(t(($) => $['api.remove'], { ns: 'common' })) } const handleUpdatePinStatus = async (id: string, isPinned: boolean) => { await updatePinStatus({ appId: id, isPinned }) toast.success(t(($) => $['api.success'], { ns: 'common' })) } const pinnedAppsCount = installedApps.filter(({ is_pinned }) => is_pinned).length const webAppsLabelId = React.useId() const installedAppItems = installedApps.map( ( { id, is_pinned, uninstallable, app: { name, icon_type, icon, icon_url, icon_background } }, index, ) => ( handleUpdatePinStatus(id, !is_pinned)} uninstallable={uninstallable} onDelete={(id) => { setCurrId(id) setShowConfirm(true) }} /> {index === pinnedAppsCount - 1 && index !== installedApps.length - 1 && } ), ) return (
$['sidebar.title'], { ns: 'explore' }) : undefined} className={cn( isDiscoverySelected ? 'bg-state-base-active' : 'hover:bg-state-base-hover', 'flex h-8 w-full items-center justify-start gap-2 rounded-lg px-1', )} >
{!isFold && (
{t(($) => $['sidebar.title'], { ns: 'explore' })}
)}
{!isPending && installedApps.length === 0 && !isFold && (
)} {installedApps.length > 0 && (
{!isFold && (

{t(($) => $['sidebar.webApps'], { ns: 'explore' })}

)} {!isFold ? (
{installedAppItems}
) : (
{installedAppItems}
)}
)}
{t(($) => $['sidebar.delete.title'], { ns: 'explore' })} {t(($) => $['sidebar.delete.content'], { ns: 'explore' })}
{t(($) => $['operation.cancel'], { ns: 'common' })} {t(($) => $['operation.confirm'], { ns: 'common' })}
) } export default React.memo(SideBar)