This commit is contained in:
XiaoBa 2025-03-21 15:06:38 +08:00 committed by GitHub
commit b4597c4f66
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 55 additions and 7 deletions

View File

@ -8,6 +8,8 @@ import Sidebar from '@/app/components/explore/sidebar'
import { useAppContext } from '@/context/app-context' import { useAppContext } from '@/context/app-context'
import { fetchMembers } from '@/service/common' import { fetchMembers } from '@/service/common'
import type { InstalledApp } from '@/models/explore' import type { InstalledApp } from '@/models/explore'
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
import { useStore } from '@/app/components/app/store'
export type IExploreProps = { export type IExploreProps = {
children: React.ReactNode children: React.ReactNode
@ -23,6 +25,10 @@ const Explore: FC<IExploreProps> = ({
const [hasEditPermission, setHasEditPermission] = useState(false) const [hasEditPermission, setHasEditPermission] = useState(false)
const [installedApps, setInstalledApps] = useState<InstalledApp[]>([]) const [installedApps, setInstalledApps] = useState<InstalledApp[]>([])
const media = useBreakpoints()
const isMobile = media === MediaType.mobile
const setAppSiderbarExpand = useStore(state => state.setAppSiderbarExpand)
useEffect(() => { useEffect(() => {
document.title = `${t('explore.title')} - Dify`; document.title = `${t('explore.title')} - Dify`;
(async () => { (async () => {
@ -39,6 +45,12 @@ const Explore: FC<IExploreProps> = ({
return router.replace('/datasets') return router.replace('/datasets')
}, [isCurrentWorkspaceDatasetOperator]) }, [isCurrentWorkspaceDatasetOperator])
useEffect(() => {
const localeMode = localStorage.getItem('app-detail-collapse-or-expand') || 'expand'
const mode = isMobile ? 'collapse' : 'expand'
setAppSiderbarExpand(isMobile ? mode : localeMode)
}, [isMobile, setAppSiderbarExpand])
return ( return (
<div className='flex h-full bg-background-body border-t border-divider-regular overflow-hidden'> <div className='flex h-full bg-background-body border-t border-divider-regular overflow-hidden'>
<ExploreContext.Provider <ExploreContext.Provider

View File

@ -9,7 +9,7 @@ import AppIcon from '@/app/components/base/app-icon'
import type { AppIconType } from '@/types/app' import type { AppIconType } from '@/types/app'
export type IAppNavItemProps = { export type IAppNavItemProps = {
isMobile: boolean expand: boolean
name: string name: string
id: string id: string
icon_type: AppIconType | null icon_type: AppIconType | null
@ -24,7 +24,7 @@ export type IAppNavItemProps = {
} }
export default function AppNavItem({ export default function AppNavItem({
isMobile, expand,
name, name,
id, id,
icon_type, icon_type,
@ -52,8 +52,8 @@ export default function AppNavItem({
router.push(url) // use Link causes popup item always trigger jump. Can not be solved by e.stopPropagation(). router.push(url) // use Link causes popup item always trigger jump. Can not be solved by e.stopPropagation().
}} }}
> >
{isMobile && <AppIcon size='tiny' iconType={icon_type} icon={icon} background={icon_background} imageUrl={icon_url} />} {!expand && <AppIcon size='tiny' iconType={icon_type} icon={icon} background={icon_background} imageUrl={icon_url} />}
{!isMobile && ( {expand && (
<> <>
<div className='flex items-center space-x-2 w-0 grow'> <div className='flex items-center space-x-2 w-0 grow'>
<AppIcon size='tiny' iconType={icon_type} icon={icon} background={icon_background} imageUrl={icon_url} /> <AppIcon size='tiny' iconType={icon_type} icon={icon} background={icon_background} imageUrl={icon_url} />

View File

@ -1,10 +1,13 @@
'use client' 'use client'
import type { FC } from 'react' import type { FC } from 'react'
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react'
import { useShallow } from 'zustand/react/shallow'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { useContext } from 'use-context-selector' import { useContext } from 'use-context-selector'
import { useSelectedLayoutSegments } from 'next/navigation' import { useSelectedLayoutSegments } from 'next/navigation'
import Link from 'next/link' import Link from 'next/link'
import { RiLayoutRight2Line } from '@remixicon/react'
import { LayoutRight2LineMod } from '../../base/icons/src/public/knowledge'
import Toast from '../../base/toast' import Toast from '../../base/toast'
import Item from './app-nav-item' import Item from './app-nav-item'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
@ -13,6 +16,7 @@ import ExploreContext from '@/context/explore-context'
import Confirm from '@/app/components/base/confirm' import Confirm from '@/app/components/base/confirm'
import Divider from '@/app/components/base/divider' import Divider from '@/app/components/base/divider'
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints' import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
import { useStore as useAppStore } from '@/app/components/app/store'
const SelectedDiscoveryIcon = () => ( const SelectedDiscoveryIcon = () => (
<svg width="16" height="16" viewBox="0 0 16 16" fill="current" xmlns="http://www.w3.org/2000/svg"> <svg width="16" height="16" viewBox="0 0 16 16" fill="current" xmlns="http://www.w3.org/2000/svg">
@ -52,6 +56,15 @@ const SideBar: FC<IExploreSideBarProps> = ({
const isChatSelected = lastSegment === 'chat' const isChatSelected = lastSegment === 'chat'
const { installedApps, setInstalledApps } = useContext(ExploreContext) const { installedApps, setInstalledApps } = useContext(ExploreContext)
const { appSidebarExpand, setAppSiderbarExpand } = useAppStore(useShallow(state => ({
appSidebarExpand: state.appSidebarExpand,
setAppSiderbarExpand: state.setAppSiderbarExpand,
})))
const expand = appSidebarExpand === 'expand'
const handleToggle = (state: string) => {
setAppSiderbarExpand(state === 'expand' ? 'collapse' : 'expand')
}
const media = useBreakpoints() const media = useBreakpoints()
const isMobile = media === MediaType.mobile const isMobile = media === MediaType.mobile
@ -82,6 +95,13 @@ const SideBar: FC<IExploreSideBarProps> = ({
fetchInstalledAppList() fetchInstalledAppList()
} }
useEffect(() => {
if (appSidebarExpand) {
localStorage.setItem('app-detail-collapse-or-expand', appSidebarExpand)
setAppSiderbarExpand(appSidebarExpand)
}
}, [appSidebarExpand, setAppSiderbarExpand])
useEffect(() => { useEffect(() => {
fetchInstalledAppList() fetchInstalledAppList()
}, []) }, [])
@ -92,7 +112,7 @@ const SideBar: FC<IExploreSideBarProps> = ({
const pinnedAppsCount = installedApps.filter(({ is_pinned }) => is_pinned).length const pinnedAppsCount = installedApps.filter(({ is_pinned }) => is_pinned).length
return ( return (
<div className='w-fit sm:w-[216px] shrink-0 pt-6 px-4 border-r border-divider-burn cursor-pointer'> <div className={`w-fit shrink-0 pt-6 px-4 border-gray-200 cursor-pointer ${expand ? 'sm:w-[216px]' : ''}`}>
<div className={cn(isDiscoverySelected ? 'text-text-accent' : 'text-text-tertiary')}> <div className={cn(isDiscoverySelected ? 'text-text-accent' : 'text-text-tertiary')}>
<Link <Link
href='/explore/apps' href='/explore/apps'
@ -101,7 +121,7 @@ const SideBar: FC<IExploreSideBarProps> = ({
style={isDiscoverySelected ? { boxShadow: '0px 1px 2px rgba(16, 24, 40, 0.05)' } : {}} style={isDiscoverySelected ? { boxShadow: '0px 1px 2px rgba(16, 24, 40, 0.05)' } : {}}
> >
{isDiscoverySelected ? <SelectedDiscoveryIcon /> : <DiscoveryIcon />} {isDiscoverySelected ? <SelectedDiscoveryIcon /> : <DiscoveryIcon />}
{!isMobile && <div className='text-sm'>{t('explore.sidebar.discovery')}</div>} {expand && <div className='text-sm'>{t('explore.sidebar.discovery')}</div>}
</Link> </Link>
</div> </div>
{installedApps.length > 0 && ( {installedApps.length > 0 && (
@ -115,7 +135,7 @@ const SideBar: FC<IExploreSideBarProps> = ({
{installedApps.map(({ id, is_pinned, uninstallable, app: { name, icon_type, icon, icon_url, icon_background } }, index) => ( {installedApps.map(({ id, is_pinned, uninstallable, app: { name, icon_type, icon, icon_url, icon_background } }, index) => (
<React.Fragment key={id}> <React.Fragment key={id}>
<Item <Item
isMobile={isMobile} expand={expand}
name={name} name={name}
icon_type={icon_type} icon_type={icon_type}
icon={icon} icon={icon}
@ -146,6 +166,22 @@ const SideBar: FC<IExploreSideBarProps> = ({
onCancel={() => setShowConfirm(false)} onCancel={() => setShowConfirm(false)}
/> />
)} )}
{
!isMobile && (
<div>
<div
className='flex items-center justify-center w-6 h-6 text-gray-500 cursor-pointer'
onClick={() => handleToggle(appSidebarExpand)}
>
{
expand
? <RiLayoutRight2Line className='w-5 h-5 text-components-menu-item-text' />
: <LayoutRight2LineMod className='w-5 h-5 text-components-menu-item-text' />
}
</div>
</div>
)
}
</div> </div>
) )
} }