mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
Merge branch 'refactor/remove-lite-variant'
This commit is contained in:
@@ -1,58 +1,17 @@
|
||||
import type { Tool } from "@stirling-image/shared";
|
||||
import * as icons from "lucide-react";
|
||||
import { FileImage, Sparkles, Star } from "lucide-react";
|
||||
import { FileImage, Star } from "lucide-react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { toast } from "sonner";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
interface ToolCardProps {
|
||||
tool: Tool;
|
||||
variantUnavailable?: boolean;
|
||||
}
|
||||
|
||||
export function ToolCard({ tool, variantUnavailable }: ToolCardProps) {
|
||||
export function ToolCard({ tool }: ToolCardProps) {
|
||||
const iconsMap = icons as unknown as Record<string, React.ComponentType<{ className?: string }>>;
|
||||
const IconComponent = iconsMap[tool.icon] || FileImage;
|
||||
|
||||
if (variantUnavailable) {
|
||||
return (
|
||||
<div className="group flex items-center gap-3 relative">
|
||||
<button
|
||||
type="button"
|
||||
className="opacity-0 group-hover:opacity-100 transition-opacity absolute -left-5"
|
||||
title="Add to favourites"
|
||||
>
|
||||
<Star className="h-3 w-3 text-muted-foreground hover:text-yellow-500" />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() =>
|
||||
toast("This tool requires the full image.", {
|
||||
description:
|
||||
"Pull stirlingimage/stirling-image:latest for all features including AI tools.",
|
||||
action: {
|
||||
label: "Learn more",
|
||||
onClick: () =>
|
||||
window.open(
|
||||
"https://stirling-image.github.io/stirling-image/guide/docker-tags",
|
||||
"_blank",
|
||||
),
|
||||
},
|
||||
})
|
||||
}
|
||||
className="flex items-center gap-3 py-2 px-3 rounded-lg w-full transition-colors hover:bg-muted/50 opacity-50 cursor-pointer"
|
||||
>
|
||||
<IconComponent className="h-5 w-5 text-muted-foreground" />
|
||||
<span className="text-sm font-medium text-foreground">{tool.name}</span>
|
||||
<span className="flex items-center gap-0.5 text-[10px] px-1.5 py-0.5 rounded bg-amber-100 text-amber-700 font-medium">
|
||||
<Sparkles className="h-2.5 w-2.5" />
|
||||
AI
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="group flex items-center gap-3 relative">
|
||||
<button
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { CATEGORIES, TOOLS } from "@stirling-image/shared";
|
||||
import { Info } from "lucide-react";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { useSettingsStore } from "@/stores/settings-store";
|
||||
import { SearchBar } from "../common/search-bar";
|
||||
@@ -7,15 +6,12 @@ import { ToolCard } from "../common/tool-card";
|
||||
|
||||
export function ToolPanel() {
|
||||
const [search, setSearch] = useState("");
|
||||
const { variant, disabledTools, experimentalEnabled, variantUnavailableTools, loaded, fetch } =
|
||||
useSettingsStore();
|
||||
const { disabledTools, experimentalEnabled, loaded, fetch } = useSettingsStore();
|
||||
|
||||
useEffect(() => {
|
||||
fetch();
|
||||
}, [fetch]);
|
||||
|
||||
const unavailableSet = useMemo(() => new Set(variantUnavailableTools), [variantUnavailableTools]);
|
||||
|
||||
const visibleTools = useMemo(() => {
|
||||
if (!loaded) return [];
|
||||
return TOOLS.filter((t) => {
|
||||
@@ -49,27 +45,6 @@ export function ToolPanel() {
|
||||
<SearchBar value={search} onChange={setSearch} />
|
||||
</div>
|
||||
<div className="px-3 pb-4 flex-1">
|
||||
{variant === "lite" && (
|
||||
<div className="mb-3 p-2.5 rounded-lg bg-amber-50 dark:bg-amber-950/30 border border-amber-200 dark:border-amber-800 text-amber-800 dark:text-amber-300">
|
||||
<div className="flex items-start gap-2">
|
||||
<Info className="h-4 w-4 mt-0.5 shrink-0" />
|
||||
<div className="text-xs leading-relaxed">
|
||||
<p className="font-medium">Lite mode</p>
|
||||
<p className="mt-0.5 text-amber-700 dark:text-amber-400">
|
||||
AI tools are unavailable. Use the{" "}
|
||||
<code className="font-mono text-[10px] bg-amber-100 dark:bg-amber-900/50 px-1 py-0.5 rounded">
|
||||
latest
|
||||
</code>{" "}
|
||||
or{" "}
|
||||
<code className="font-mono text-[10px] bg-amber-100 dark:bg-amber-900/50 px-1 py-0.5 rounded">
|
||||
full
|
||||
</code>{" "}
|
||||
tag for all features.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{CATEGORIES.filter((cat) => groupedTools.has(cat.id)).map((category) => (
|
||||
<div key={category.id} className="mb-4">
|
||||
<h3 className="text-xs font-semibold uppercase text-muted-foreground tracking-wider mb-2">
|
||||
@@ -77,11 +52,7 @@ export function ToolPanel() {
|
||||
</h3>
|
||||
<div className="space-y-0.5">
|
||||
{groupedTools.get(category.id)?.map((tool) => (
|
||||
<ToolCard
|
||||
key={tool.id}
|
||||
tool={tool}
|
||||
variantUnavailable={unavailableSet.has(tool.id)}
|
||||
/>
|
||||
<ToolCard key={tool.id} tool={tool} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user