86 lines
2.6 KiB
TypeScript
86 lines
2.6 KiB
TypeScript
import type { GitStatus, MaimaiVersion, PluginInfo, PluginLoadProgress, PluginStatsData } from './types'
|
|
import { PluginCard } from './PluginCard'
|
|
|
|
interface InstalledTabProps {
|
|
plugins: PluginInfo[]
|
|
searchQuery: string
|
|
categoryFilter: string
|
|
showCompatibleOnly: boolean
|
|
gitStatus: GitStatus | null
|
|
maimaiVersion: MaimaiVersion | null
|
|
pluginStats: Record<string, PluginStatsData>
|
|
loadProgress: PluginLoadProgress | null
|
|
onInstall: (plugin: PluginInfo) => void
|
|
onUpdate: (plugin: PluginInfo) => void
|
|
onUninstall: (plugin: PluginInfo) => void
|
|
checkPluginCompatibility: (plugin: PluginInfo) => boolean
|
|
needsUpdate: (plugin: PluginInfo) => boolean
|
|
getStatusBadge: (plugin: PluginInfo) => React.JSX.Element | null
|
|
getIncompatibleReason: (plugin: PluginInfo) => string | null
|
|
}
|
|
|
|
export function InstalledTab({
|
|
plugins,
|
|
searchQuery,
|
|
categoryFilter,
|
|
showCompatibleOnly,
|
|
gitStatus,
|
|
maimaiVersion,
|
|
pluginStats,
|
|
loadProgress,
|
|
onInstall,
|
|
onUpdate,
|
|
onUninstall,
|
|
checkPluginCompatibility,
|
|
needsUpdate,
|
|
getStatusBadge,
|
|
getIncompatibleReason,
|
|
}: InstalledTabProps) {
|
|
const filteredPlugins = plugins.filter((plugin) => {
|
|
if (!plugin.manifest) {
|
|
return false
|
|
}
|
|
|
|
if (!plugin.installed) {
|
|
return false
|
|
}
|
|
|
|
const matchesSearch =
|
|
searchQuery === '' ||
|
|
plugin.manifest.name?.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
|
plugin.manifest.description?.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
|
(plugin.manifest.keywords &&
|
|
plugin.manifest.keywords.some((keyword) => keyword.toLowerCase().includes(searchQuery.toLowerCase())))
|
|
|
|
const matchesCategory =
|
|
categoryFilter === 'all' ||
|
|
(plugin.manifest.categories && plugin.manifest.categories.includes(categoryFilter))
|
|
|
|
const matchesCompatibility = !showCompatibleOnly || !maimaiVersion || checkPluginCompatibility(plugin)
|
|
|
|
return matchesSearch && matchesCategory && matchesCompatibility
|
|
})
|
|
|
|
return (
|
|
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4 gap-5">
|
|
{filteredPlugins.map((plugin) => (
|
|
<PluginCard
|
|
key={plugin.id}
|
|
plugin={plugin}
|
|
gitStatus={gitStatus}
|
|
maimaiVersion={maimaiVersion}
|
|
pluginStats={pluginStats}
|
|
loadProgress={loadProgress}
|
|
onInstall={onInstall}
|
|
onUpdate={onUpdate}
|
|
onUninstall={onUninstall}
|
|
checkPluginCompatibility={checkPluginCompatibility}
|
|
needsUpdate={needsUpdate}
|
|
getStatusBadge={getStatusBadge}
|
|
getIncompatibleReason={getIncompatibleReason}
|
|
/>
|
|
))}
|
|
</div>
|
|
)
|
|
}
|