'use client' 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 { AlertDialog, AlertDialogActions, AlertDialogCancelButton, AlertDialogConfirmButton, AlertDialogContent, AlertDialogDescription, AlertDialogTitle, } from '@/app/components/base/ui/alert-dialog' import { ScrollArea } from '@/app/components/base/ui/scroll-area' import { toast } from '@/app/components/base/ui/toast' import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints' import Link from '@/next/link' import { useSelectedLayoutSegments } from '@/next/navigation' import { useGetInstalledApps, useUninstallApp, useUpdateAppPinStatus } from '@/service/use-explore' import { cn } from '@/utils/classnames' import Item from './app-nav-item' import NoApps from './no-apps' const expandedSidebarScrollAreaClassNames = { content: 'space-y-0.5', scrollbar: 'data-[orientation=vertical]:my-2 data-[orientation=vertical]:[margin-inline-end:-0.75rem]', viewport: 'overscroll-contain', } as const const SideBar = () => { const { t } = useTranslation() const segments = useSelectedLayoutSegments() const lastSegment = segments.slice(-1)[0] const isDiscoverySelected = lastSegment === 'apps' const { data, isPending } = useGetInstalledApps() const installedApps = data?.installed_apps ?? [] const { mutateAsync: uninstallApp, isPending: isUninstalling } = useUninstallApp() const { mutateAsync: updatePinStatus } = useUpdateAppPinStatus() const media = useBreakpoints() const isMobile = media === MediaType.mobile 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 shouldUseExpandedScrollArea = !isMobile && !isFold 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 (
{!isMobile && !isFold &&
{t('sidebar.title', { ns: 'explore' })}
}
{!isPending && installedApps.length === 0 && !isMobile && !isFold && (
)} {installedApps.length > 0 && (
{!isMobile && !isFold &&

{t('sidebar.webApps', { ns: 'explore' })}

} {shouldUseExpandedScrollArea ? (
{installedAppItems}
) : (
{installedAppItems}
)}
)} {!isMobile && (
)}
{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)