From 77fb193598af939c9c1ebcc89b3f116429408a8c Mon Sep 17 00:00:00 2001 From: Haileyesus Date: Mon, 9 Mar 2026 12:59:52 +0300 Subject: [PATCH] fix: resolve type error in MobileNav and PluginTabContent components --- src/components/app/MobileNav.tsx | 46 +++++++++++++++---- .../plugins/view/PluginTabContent.tsx | 19 +++++--- 2 files changed, 49 insertions(+), 16 deletions(-) diff --git a/src/components/app/MobileNav.tsx b/src/components/app/MobileNav.tsx index b5fabd7c..ea49f009 100644 --- a/src/components/app/MobileNav.tsx +++ b/src/components/app/MobileNav.tsx @@ -1,13 +1,35 @@ -import { useState, useRef, useEffect, Dispatch, SetStateAction } from 'react'; -import { MessageSquare, Folder, Terminal, GitBranch, ClipboardCheck, Ellipsis, Puzzle, Box, Database, Globe, Wrench, Zap, BarChart3 } from 'lucide-react'; +import { useState, useRef, useEffect, type Dispatch, type SetStateAction } from 'react'; +import { + MessageSquare, + Folder, + Terminal, + GitBranch, + ClipboardCheck, + Ellipsis, + Puzzle, + Box, + Database, + Globe, + Wrench, + Zap, + BarChart3, + type LucideIcon, +} from 'lucide-react'; import { useTasksSettings } from '../../contexts/TasksSettingsContext'; import { usePlugins } from '../../contexts/PluginsContext'; import { AppTab } from '../../types/app'; -const PLUGIN_ICON_MAP = { +const PLUGIN_ICON_MAP: Record = { Puzzle, Box, Database, Globe, Terminal, Wrench, Zap, BarChart3, Folder, MessageSquare, GitBranch, }; +type CoreTabId = Exclude; +type CoreNavItem = { + id: CoreTabId; + icon: LucideIcon; + label: string; +}; + type MobileNavProps = { activeTab: AppTab; setActiveTab: Dispatch>; @@ -19,7 +41,7 @@ export default function MobileNav({ activeTab, setActiveTab, isInputFocused }: M const shouldShowTasksTab = Boolean(tasksEnabled && isTaskMasterInstalled); const { plugins } = usePlugins(); const [moreOpen, setMoreOpen] = useState(false); - const moreRef = useRef(null); + const moreRef = useRef(null); const enabledPlugins = plugins.filter((p) => p.enabled); const hasPlugins = enabledPlugins.length > 0; @@ -28,8 +50,9 @@ export default function MobileNav({ activeTab, setActiveTab, isInputFocused }: M // Close the menu on outside tap useEffect(() => { if (!moreOpen) return; - const handleTap = (e) => { - if (moreRef.current && !moreRef.current.contains(e.target)) { + const handleTap = (e: PointerEvent) => { + const target = e.target; + if (moreRef.current && target instanceof Node && !moreRef.current.contains(target)) { setMoreOpen(false); } }; @@ -38,18 +61,21 @@ export default function MobileNav({ activeTab, setActiveTab, isInputFocused }: M }, [moreOpen]); // Close menu when a plugin tab is selected - const selectPlugin = (name) => { - setActiveTab(`plugin:${name}`); + const selectPlugin = (name: string) => { + const pluginTab = `plugin:${name}` as AppTab; + setActiveTab(pluginTab); setMoreOpen(false); }; - const coreItems = [ + const baseCoreItems: CoreNavItem[] = [ { id: 'chat', icon: MessageSquare, label: 'Chat' }, { id: 'shell', icon: Terminal, label: 'Shell' }, { id: 'files', icon: Folder, label: 'Files' }, { id: 'git', icon: GitBranch, label: 'Git' }, - ...(shouldShowTasksTab ? [{ id: 'tasks', icon: ClipboardCheck, label: 'Tasks' }] : []), ]; + const coreItems: CoreNavItem[] = shouldShowTasksTab + ? [...baseCoreItems, { id: 'tasks', icon: ClipboardCheck, label: 'Tasks' }] + : baseCoreItems; return (
(buildContext(isDarkMode, selectedProject, selectedSession)); const contextCallbacksRef = useRef void>>(new Set()); - + const moduleRef = useRef(null); const plugin = plugins.find(p => p.name === pluginName); @@ -65,6 +71,7 @@ export default function PluginTabContent({ let active = true; const container = containerRef.current; const entryFile = plugin?.entry ?? 'index.js'; + const contextCallbacks = contextCallbacksRef.current; (async () => { try { @@ -86,8 +93,8 @@ export default function PluginTabContent({ get context(): PluginContext { return contextRef.current; }, onContextChange(cb: (ctx: PluginContext) => void): () => void { - contextCallbacksRef.current.add(cb); - return () => contextCallbacksRef.current.delete(cb); + contextCallbacks.add(cb); + return () => contextCallbacks.delete(cb); }, async rpc(method: string, path: string, body?: unknown): Promise { @@ -125,7 +132,7 @@ export default function PluginTabContent({ return () => { active = false; try { moduleRef.current?.unmount?.(container); } catch { /* ignore */ } - contextCallbacksRef.current.clear(); + contextCallbacks.clear(); moduleRef.current = null; }; }, [pluginName, plugin?.entry, plugin?.enabled]); // re-mount when plugin or enabled state changes