| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  | 'use client' | 
					
						
							|  |  |  | import { useMemo } from 'react' | 
					
						
							|  |  |  | import type { FilterState } from './filter-management' | 
					
						
							|  |  |  | import FilterManagement from './filter-management' | 
					
						
							|  |  |  | import List from './list' | 
					
						
							| 
									
										
										
										
											2025-04-09 18:49:27 +09:00
										 |  |  | import { useInstalledLatestVersion, useInstalledPluginList, useInvalidateInstalledPluginList } from '@/service/use-plugins' | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  | import PluginDetailPanel from '@/app/components/plugins/plugin-detail-panel' | 
					
						
							|  |  |  | import { usePluginPageContext } from './context' | 
					
						
							|  |  |  | import { useDebounceFn } from 'ahooks' | 
					
						
							|  |  |  | import Empty from './empty' | 
					
						
							|  |  |  | import Loading from '../../base/loading' | 
					
						
							| 
									
										
										
										
											2025-04-09 18:49:27 +09:00
										 |  |  | import { PluginSource } from '../types' | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | const PluginsPanel = () => { | 
					
						
							|  |  |  |   const filters = usePluginPageContext(v => v.filters) as FilterState | 
					
						
							|  |  |  |   const setFilters = usePluginPageContext(v => v.setFilters) | 
					
						
							|  |  |  |   const { data: pluginList, isLoading: isPluginListLoading } = useInstalledPluginList() | 
					
						
							| 
									
										
										
										
											2025-04-09 18:49:27 +09:00
										 |  |  |   const { data: installedLatestVersion } = useInstalledLatestVersion( | 
					
						
							|  |  |  |     pluginList?.plugins | 
					
						
							|  |  |  |       .filter(plugin => plugin.source === PluginSource.marketplace) | 
					
						
							|  |  |  |       .map(plugin => plugin.plugin_id) ?? [], | 
					
						
							|  |  |  |   ) | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  |   const invalidateInstalledPluginList = useInvalidateInstalledPluginList() | 
					
						
							|  |  |  |   const currentPluginID = usePluginPageContext(v => v.currentPluginID) | 
					
						
							|  |  |  |   const setCurrentPluginID = usePluginPageContext(v => v.setCurrentPluginID) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const { run: handleFilterChange } = useDebounceFn((filters: FilterState) => { | 
					
						
							|  |  |  |     setFilters(filters) | 
					
						
							|  |  |  |   }, { wait: 500 }) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-09 18:49:27 +09:00
										 |  |  |   const pluginListWithLatestVersion = useMemo(() => { | 
					
						
							|  |  |  |     return pluginList?.plugins.map(plugin => ({ | 
					
						
							|  |  |  |       ...plugin, | 
					
						
							|  |  |  |       latest_version: installedLatestVersion?.versions[plugin.plugin_id]?.version ?? '', | 
					
						
							|  |  |  |       latest_unique_identifier: installedLatestVersion?.versions[plugin.plugin_id]?.unique_identifier ?? '', | 
					
						
							|  |  |  |     })) || [] | 
					
						
							|  |  |  |   }, [pluginList, installedLatestVersion]) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  |   const filteredList = useMemo(() => { | 
					
						
							|  |  |  |     const { categories, searchQuery, tags } = filters | 
					
						
							| 
									
										
										
										
											2025-04-09 18:49:27 +09:00
										 |  |  |     const filteredList = pluginListWithLatestVersion.filter((plugin) => { | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  |       return ( | 
					
						
							|  |  |  |         (categories.length === 0 || categories.includes(plugin.declaration.category)) | 
					
						
							|  |  |  |         && (tags.length === 0 || tags.some(tag => plugin.declaration.tags.includes(tag))) | 
					
						
							|  |  |  |         && (searchQuery === '' || plugin.plugin_id.toLowerCase().includes(searchQuery.toLowerCase())) | 
					
						
							|  |  |  |       ) | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |     return filteredList | 
					
						
							| 
									
										
										
										
											2025-04-09 18:49:27 +09:00
										 |  |  |   }, [pluginListWithLatestVersion, filters]) | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   const currentPluginDetail = useMemo(() => { | 
					
						
							| 
									
										
										
										
											2025-04-09 18:49:27 +09:00
										 |  |  |     const detail = pluginListWithLatestVersion.find(plugin => plugin.plugin_id === currentPluginID) | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  |     return detail | 
					
						
							| 
									
										
										
										
											2025-04-09 18:49:27 +09:00
										 |  |  |   }, [currentPluginID, pluginListWithLatestVersion]) | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   const handleHide = () => setCurrentPluginID(undefined) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return ( | 
					
						
							|  |  |  |     <> | 
					
						
							| 
									
										
										
										
											2025-03-21 17:41:03 +08:00
										 |  |  |       <div className='flex flex-col items-start justify-center gap-3 self-stretch px-12 pb-3 pt-1'> | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  |         <div className='h-px self-stretch bg-divider-subtle'></div> | 
					
						
							|  |  |  |         <FilterManagement | 
					
						
							|  |  |  |           onFilterChange={handleFilterChange} | 
					
						
							|  |  |  |         /> | 
					
						
							|  |  |  |       </div> | 
					
						
							|  |  |  |       {isPluginListLoading ? <Loading type='app' /> : (filteredList?.length ?? 0) > 0 ? ( | 
					
						
							| 
									
										
										
										
											2025-03-21 17:41:03 +08:00
										 |  |  |         <div className='flex grow flex-wrap content-start items-start gap-2 self-stretch px-12'> | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  |           <div className='w-full'> | 
					
						
							|  |  |  |             <List pluginList={filteredList || []} /> | 
					
						
							|  |  |  |           </div> | 
					
						
							|  |  |  |         </div> | 
					
						
							|  |  |  |       ) : ( | 
					
						
							|  |  |  |         <Empty /> | 
					
						
							|  |  |  |       )} | 
					
						
							|  |  |  |       <PluginDetailPanel | 
					
						
							|  |  |  |         detail={currentPluginDetail} | 
					
						
							|  |  |  |         onUpdate={() => invalidateInstalledPluginList()} | 
					
						
							|  |  |  |         onHide={handleHide} | 
					
						
							|  |  |  |       /> | 
					
						
							|  |  |  |     </> | 
					
						
							|  |  |  |   ) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export default PluginsPanel |