From 8aa0c1763a1379a8c82f6304e2edbf24053ac7cc Mon Sep 17 00:00:00 2001 From: Arjun <6592213+arkml@users.noreply.github.com> Date: Mon, 25 May 2026 13:19:34 +0530 Subject: [PATCH] tools row in home --- .../renderer/src/components/home-view.tsx | 127 +++++++++++++++++- 1 file changed, 125 insertions(+), 2 deletions(-) diff --git a/apps/x/apps/renderer/src/components/home-view.tsx b/apps/x/apps/renderer/src/components/home-view.tsx index 3cc0899d..bfcc0a33 100644 --- a/apps/x/apps/renderer/src/components/home-view.tsx +++ b/apps/x/apps/renderer/src/components/home-view.tsx @@ -1,6 +1,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react' -import { ArrowRight, Bot, Calendar, Clock, FileText, Mail, MessageSquare, Mic, Plus, Video } from 'lucide-react' +import { ArrowRight, Bot, Calendar, Clock, FileText, Mail, MessageSquare, Mic, Plug, Plus, Video } from 'lucide-react' import { extractConferenceLink } from '@/lib/calendar-event' +import { SettingsDialog } from '@/components/settings-dialog' interface TreeNode { path: string @@ -53,6 +54,7 @@ type RawCalEvent = { } type EmailThread = { threadId: string; subject: string; from: string } +type ToolkitPreview = { slug: string; logo: string; name: string; description: string } function greeting(): string { const h = new Date().getHours() @@ -152,6 +154,54 @@ function triggerMeetingCapture(event: CalEvent, openConference: boolean) { } const CARD = 'rounded-xl border border-border bg-card p-4' +const TOOLKIT_PREVIEW_LIMIT = 8 + +let cachedToolkitPreviews: ToolkitPreview[] | null = null +let cachedToolkitLogosLoaded = false + +function ToolkitPreviewIcon({ + toolkit, + onInvalid, +}: { + toolkit: ToolkitPreview + onInvalid: (slug: string) => void +}) { + const [loaded, setLoaded] = useState(false) + + if (!loaded) { + return ( + { + const img = event.currentTarget + if (img.naturalWidth > 1 && img.naturalHeight > 1) { + setLoaded(true) + } else { + onInvalid(toolkit.slug) + } + }} + onError={() => onInvalid(toolkit.slug)} + /> + ) + } + + return ( +
+ onInvalid(toolkit.slug)} + /> +
+ ) +} export function HomeView({ tree, @@ -168,6 +218,9 @@ export function HomeView({ }: HomeViewProps) { const [events, setEvents] = useState([]) const [emails, setEmails] = useState([]) + const [toolkitPreviews, setToolkitPreviews] = useState(cachedToolkitPreviews ?? []) + const [toolkitLogosLoaded, setToolkitLogosLoaded] = useState(cachedToolkitLogosLoaded) + const [connectionsSettingsOpen, setConnectionsSettingsOpen] = useState(false) const loadEvents = useCallback(async () => { try { @@ -207,7 +260,40 @@ export function HomeView({ } }, []) - useEffect(() => { void loadEvents(); void loadEmails() }, [loadEvents, loadEmails]) + const loadConnectorLogos = useCallback(async () => { + if (cachedToolkitLogosLoaded) return + try { + const configured = await window.ipc.invoke('composio:is-configured', null) + if (!configured.configured) return + const toolkits = await window.ipc.invoke('composio:list-toolkits', {}) + const previews = toolkits.items + .filter((toolkit) => Boolean(toolkit.meta.logo)) + .slice(0, TOOLKIT_PREVIEW_LIMIT) + .map((toolkit) => ({ + slug: toolkit.slug, + logo: toolkit.meta.logo, + name: toolkit.name, + description: toolkit.meta.description, + })) + cachedToolkitPreviews = previews + setToolkitPreviews(previews) + } catch { + cachedToolkitPreviews = [] + } finally { + cachedToolkitLogosLoaded = true + setToolkitLogosLoaded(true) + } + }, []) + + const removeToolkitPreview = useCallback((slug: string) => { + setToolkitPreviews((prev) => { + const next = prev.filter((toolkit) => toolkit.slug !== slug) + cachedToolkitPreviews = next + return next + }) + }, []) + + useEffect(() => { void loadEvents(); void loadEmails(); void loadConnectorLogos() }, [loadEvents, loadEmails, loadConnectorLogos]) // Upcoming (not-yet-ended) events, soonest first. const upcoming = useMemo(() => { @@ -437,6 +523,43 @@ export function HomeView({ )} + {/* Tool connections */} +
+
+
+ +
+
+
+ Connect your tools. + Bring context from the apps you already use. +
+
+ {toolkitLogosLoaded && toolkitPreviews.map((toolkit) => ( + + ))} + +
+
+
+
+ + {/* Open chat CTA */} {onOpenChat && (