mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
feat: add download badge to uninstalled AI tools in tool grid
Show a download icon on AI tools that are not yet installed, and fetch feature status on mount in both the sidebar tool panel and fullscreen grid page.
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
import type { Tool } from "@ashim/shared";
|
||||
import { FileImage, Star } from "lucide-react";
|
||||
import { PYTHON_SIDECAR_TOOLS } from "@ashim/shared";
|
||||
import { Download, FileImage, Star } from "lucide-react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { ICON_MAP } from "@/lib/icon-map";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { useFeaturesStore } from "@/stores/features-store";
|
||||
|
||||
interface ToolCardProps {
|
||||
tool: Tool;
|
||||
@@ -12,6 +14,10 @@ export function ToolCard({ tool }: ToolCardProps) {
|
||||
const IconComponent =
|
||||
(ICON_MAP[tool.icon] as React.ComponentType<{ className?: string }>) ?? FileImage;
|
||||
|
||||
const isAiTool = (PYTHON_SIDECAR_TOOLS as readonly string[]).includes(tool.id);
|
||||
const isInstalled = useFeaturesStore((s) => s.isToolInstalled)(tool.id);
|
||||
const showDownloadBadge = isAiTool && !isInstalled;
|
||||
|
||||
return (
|
||||
<div className="group flex items-center gap-3 relative">
|
||||
<button
|
||||
@@ -36,6 +42,7 @@ export function ToolCard({ tool }: ToolCardProps) {
|
||||
Experimental
|
||||
</span>
|
||||
)}
|
||||
{showDownloadBadge && <Download className="h-3.5 w-3.5 text-muted-foreground" />}
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { CATEGORIES, TOOLS } from "@ashim/shared";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { useFeaturesStore } from "@/stores/features-store";
|
||||
import { useSettingsStore } from "@/stores/settings-store";
|
||||
import { SearchBar } from "../common/search-bar";
|
||||
import { ToolCard } from "../common/tool-card";
|
||||
@@ -7,11 +8,16 @@ import { ToolCard } from "../common/tool-card";
|
||||
export function ToolPanel() {
|
||||
const [search, setSearch] = useState("");
|
||||
const { disabledTools, experimentalEnabled, loaded, fetch } = useSettingsStore();
|
||||
const fetchFeatures = useFeaturesStore((s) => s.fetch);
|
||||
|
||||
useEffect(() => {
|
||||
fetch();
|
||||
}, [fetch]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchFeatures();
|
||||
}, [fetchFeatures]);
|
||||
|
||||
const visibleTools = useMemo(() => {
|
||||
if (!loaded) return [];
|
||||
return TOOLS.filter((t) => {
|
||||
|
||||
@@ -7,6 +7,7 @@ import { GemLogo } from "@/components/common/gem-logo";
|
||||
import { apiGet } from "@/lib/api";
|
||||
import { ICON_MAP } from "@/lib/icon-map";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { useFeaturesStore } from "@/stores/features-store";
|
||||
|
||||
export function FullscreenGridPage() {
|
||||
const [search, setSearch] = useState("");
|
||||
@@ -14,6 +15,11 @@ export function FullscreenGridPage() {
|
||||
const navigate = useNavigate();
|
||||
const [disabledTools, setDisabledTools] = useState<string[]>([]);
|
||||
const [experimentalEnabled, setExperimentalEnabled] = useState(false);
|
||||
const fetchFeatures = useFeaturesStore((s) => s.fetch);
|
||||
|
||||
useEffect(() => {
|
||||
fetchFeatures();
|
||||
}, [fetchFeatures]);
|
||||
|
||||
useEffect(() => {
|
||||
apiGet<{ settings: Record<string, string> }>("/v1/settings")
|
||||
|
||||
Reference in New Issue
Block a user