import { PluginCard } from "@/components/PluginCard" import { getDependedPlugins, getImplicitDependencies, isPluginCompatibleWithTarget, isRequiredByOther, } from "@/lib/utils" import registryData from "@/public/registry.json" import { ChevronDown, ChevronRight } from "lucide-react" interface PluginConfigProps { pluginConfig: Record pluginOptionsConfig: Record> selectedTarget: string pluginParam?: string pluginFlashCounts: Record showPlugins: boolean onToggleShow: () => void onTogglePlugin: (id: string, enabled: boolean) => void onTogglePluginOption: (pluginId: string, optionKey: string, enabled: boolean) => void onReset: () => void } export function PluginConfig({ pluginConfig, pluginOptionsConfig, selectedTarget, pluginParam, pluginFlashCounts, showPlugins, onToggleShow, onTogglePlugin, onTogglePluginOption, onReset, }: PluginConfigProps) { const pluginCount = Object.keys(pluginConfig).filter(id => pluginConfig[id] === true).length // Get explicitly selected plugins (user-selected) const explicitPlugins = Object.keys(pluginConfig).filter(id => pluginConfig[id] === true) // Compute implicit dependencies (dependencies that are not explicitly selected) const implicitDeps = getImplicitDependencies( explicitPlugins, registryData as Record }> ) // Compute all enabled plugins (explicit + implicit) const allEnabledPlugins = getDependedPlugins( explicitPlugins, registryData as Record }> ) return (
{showPlugins && (

Plugins are 3rd party add-ons. They are not maintained, endorsed, or supported by Meshtastic. Use at your own risk.

{Object.entries(registryData) .sort(([, pluginA], [, pluginB]) => { // Featured plugins first const featuredA = (pluginA as { featured?: boolean }).featured ?? false const featuredB = (pluginB as { featured?: boolean }).featured ?? false if (featuredA !== featuredB) { return featuredA ? -1 : 1 } // Then alphabetical by name return (pluginA as { name: string }).name.localeCompare((pluginB as { name: string }).name) }) .map(([slug, plugin]) => { // Check if plugin is required by another explicitly selected plugin const isRequired = isRequiredByOther( slug, explicitPlugins, registryData as Record }> ) // Plugin is implicit if it's either: // 1. Not explicitly selected but is a dependency, OR // 2. Explicitly selected but required by another explicitly selected plugin const isImplicit = implicitDeps.has(slug) || (explicitPlugins.includes(slug) && isRequired) // Check plugin compatibility with selected target const pluginIncludes = (plugin as { includes?: string[] }).includes const pluginExcludes = (plugin as { excludes?: string[] }).excludes // Legacy support: check for old "architectures" field const legacyArchitectures = (plugin as { architectures?: string[] }).architectures const hasCompatibilityConstraints = (pluginIncludes && pluginIncludes.length > 0) || (pluginExcludes && pluginExcludes.length > 0) || (legacyArchitectures && legacyArchitectures.length > 0) const isCompatible = hasCompatibilityConstraints && selectedTarget ? isPluginCompatibleWithTarget( pluginIncludes || legacyArchitectures, pluginExcludes, selectedTarget ) : true // If no constraints or no target selected, assume compatible // Mark as incompatible if plugin has compatibility constraints and target is not compatible const isIncompatible = !isCompatible && hasCompatibilityConstraints && !!selectedTarget // Check if this is the preselected plugin from URL const isPreselected = pluginParam === slug const pluginRegistry = plugin as { featured?: boolean } const isPluginEnabled = allEnabledPlugins.includes(slug) const pluginOptions = pluginOptionsConfig[slug] ?? {} return ( onTogglePlugin(slug, enabled)} disabled={isImplicit || isIncompatible || isPreselected} enabledLabel={isPreselected ? "Locked" : isImplicit ? "Required" : "Add"} incompatibleReason={isIncompatible ? "Not compatible with this target" : undefined} featured={pluginRegistry.featured ?? false} flashCount={pluginFlashCounts[slug] ?? 0} homepage={plugin.homepage} version={plugin.version} repo={plugin.repo} diagnostics={ isPluginEnabled ? { checked: pluginOptions.diagnostics ?? false, onCheckedChange: checked => onTogglePluginOption(slug, "diagnostics", checked === true), } : undefined } /> ) })}
)}
) }