mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
feat: add FeatureInstallPrompt component for uninstalled AI tool pages
Show an install prompt instead of the normal tool UI when an AI feature bundle is not installed. Admins see a one-click install button with SSE progress tracking and polling fallback; non-admins see a message to contact their administrator.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { TOOLS } from "@ashim/shared";
|
||||
import { PYTHON_SIDECAR_TOOLS, TOOLS } from "@ashim/shared";
|
||||
import {
|
||||
CheckCircle2,
|
||||
ChevronLeft,
|
||||
@@ -16,15 +16,18 @@ import { type BgPreviewState, ImageViewer } from "@/components/common/image-view
|
||||
import { ReviewPanel } from "@/components/common/review-panel";
|
||||
import { SideBySideComparison } from "@/components/common/side-by-side-comparison";
|
||||
import { ThumbnailStrip } from "@/components/common/thumbnail-strip";
|
||||
import { FeatureInstallPrompt } from "@/components/features/feature-install-prompt";
|
||||
import { AppLayout } from "@/components/layout/app-layout";
|
||||
import { CropCanvas } from "@/components/tools/crop-canvas";
|
||||
import type { EraserCanvasRef } from "@/components/tools/eraser-canvas";
|
||||
import { EraserCanvas } from "@/components/tools/eraser-canvas";
|
||||
import type { PreviewTransform } from "@/components/tools/rotate-settings";
|
||||
import { useAuth } from "@/hooks/use-auth";
|
||||
import { useMobile } from "@/hooks/use-mobile";
|
||||
import { formatFileSize } from "@/lib/download";
|
||||
import { ICON_MAP } from "@/lib/icon-map";
|
||||
import { getToolRegistryEntry } from "@/lib/tool-registry";
|
||||
import { useFeaturesStore } from "@/stores/features-store";
|
||||
import { useFileStore } from "@/stores/file-store";
|
||||
|
||||
/** Formats that browsers can render in <img> tags. */
|
||||
@@ -106,6 +109,13 @@ export function ToolPage() {
|
||||
() => (toolId ? getToolRegistryEntry(toolId) : undefined),
|
||||
[toolId],
|
||||
);
|
||||
const isAiTool = toolId ? (PYTHON_SIDECAR_TOOLS as readonly string[]).includes(toolId) : false;
|
||||
const getBundleForTool = useFeaturesStore((s) => s.getBundleForTool);
|
||||
const isToolInstalled = useFeaturesStore((s) => s.isToolInstalled);
|
||||
const featureBundle = toolId ? getBundleForTool(toolId) : null;
|
||||
const toolInstalled = toolId ? isToolInstalled(toolId) : true;
|
||||
const { hasPermission } = useAuth();
|
||||
const isAdmin = hasPermission("settings:write");
|
||||
const {
|
||||
files,
|
||||
entries,
|
||||
@@ -234,6 +244,14 @@ export function ToolPage() {
|
||||
);
|
||||
}
|
||||
|
||||
if (isAiTool && !toolInstalled && featureBundle) {
|
||||
return (
|
||||
<AppLayout>
|
||||
<FeatureInstallPrompt bundle={featureBundle} isAdmin={isAdmin} />
|
||||
</AppLayout>
|
||||
);
|
||||
}
|
||||
|
||||
const IconComponent =
|
||||
(ICON_MAP[tool.icon] as React.ComponentType<{ className?: string }>) ?? FileImage;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user