mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
fix: show tool name instead of bundle name on AI feature install prompt
The install prompt and error messages were showing the underlying AI bundle name (e.g. "Background Removal") instead of the actual tool name (e.g. "Passport Photo"). Now the UI shows the correct tool name and description while still installing the correct bundle behind the scenes. Closes #130
This commit is contained in:
@@ -47,9 +47,15 @@ interface FeatureInstallPromptProps {
|
|||||||
bundle: FeatureBundleState;
|
bundle: FeatureBundleState;
|
||||||
isAdmin: boolean;
|
isAdmin: boolean;
|
||||||
toolName?: string;
|
toolName?: string;
|
||||||
|
toolDescription?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function FeatureInstallPrompt({ bundle, isAdmin, toolName }: FeatureInstallPromptProps) {
|
export function FeatureInstallPrompt({
|
||||||
|
bundle,
|
||||||
|
isAdmin,
|
||||||
|
toolName,
|
||||||
|
toolDescription,
|
||||||
|
}: FeatureInstallPromptProps) {
|
||||||
const { installBundle, clearError, installing, errors, startTimes, queued } = useFeaturesStore();
|
const { installBundle, clearError, installing, errors, startTimes, queued } = useFeaturesStore();
|
||||||
const progress = installing[bundle.id] ?? null;
|
const progress = installing[bundle.id] ?? null;
|
||||||
const error = errors[bundle.id] ?? null;
|
const error = errors[bundle.id] ?? null;
|
||||||
@@ -57,6 +63,7 @@ export function FeatureInstallPrompt({ bundle, isAdmin, toolName }: FeatureInsta
|
|||||||
const isQueued = queued.includes(bundle.id);
|
const isQueued = queued.includes(bundle.id);
|
||||||
const startTime = startTimes[bundle.id] ?? null;
|
const startTime = startTimes[bundle.id] ?? null;
|
||||||
const displayName = toolName || bundle.name;
|
const displayName = toolName || bundle.name;
|
||||||
|
const displayDescription = toolDescription || bundle.description;
|
||||||
|
|
||||||
const [messageIndex, setMessageIndex] = useState(() =>
|
const [messageIndex, setMessageIndex] = useState(() =>
|
||||||
Math.floor(Math.random() * PROGRESS_MESSAGES.length),
|
Math.floor(Math.random() * PROGRESS_MESSAGES.length),
|
||||||
@@ -103,7 +110,7 @@ export function FeatureInstallPrompt({ bundle, isAdmin, toolName }: FeatureInsta
|
|||||||
<Download className="h-16 w-16 text-muted-foreground" />
|
<Download className="h-16 w-16 text-muted-foreground" />
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<h2 className="text-xl font-semibold text-foreground">{displayName}</h2>
|
<h2 className="text-xl font-semibold text-foreground">{displayName}</h2>
|
||||||
<p className="text-muted-foreground max-w-md">{bundle.description}</p>
|
<p className="text-muted-foreground max-w-md">{displayDescription}</p>
|
||||||
<p className="text-sm text-muted-foreground">
|
<p className="text-sm text-muted-foreground">
|
||||||
This feature requires an additional download (~{bundle.estimatedSize})
|
This feature requires an additional download (~{bundle.estimatedSize})
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ export function usePipelineProcessor() {
|
|||||||
const parsed = parseApiError(body, xhr.status);
|
const parsed = parseApiError(body, xhr.status);
|
||||||
if (typeof parsed === "object" && parsed.type === "feature_not_installed") {
|
if (typeof parsed === "object" && parsed.type === "feature_not_installed") {
|
||||||
setError(
|
setError(
|
||||||
`Feature "${parsed.featureName}" is not installed. Enable it in Settings → AI Features.`,
|
`The "${parsed.featureName}" feature is not installed. Enable it in Settings → AI Features.`,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
setError(parsed as string);
|
setError(parsed as string);
|
||||||
@@ -279,7 +279,7 @@ export function usePipelineProcessor() {
|
|||||||
} else {
|
} else {
|
||||||
const parsed = parseApiError(body, response.status);
|
const parsed = parseApiError(body, response.status);
|
||||||
if (typeof parsed === "object" && parsed.type === "feature_not_installed") {
|
if (typeof parsed === "object" && parsed.type === "feature_not_installed") {
|
||||||
errorMsg = `Feature "${parsed.featureName}" is not installed. Enable it in Settings → AI Features.`;
|
errorMsg = `The "${parsed.featureName}" feature is not installed. Enable it in Settings → AI Features.`;
|
||||||
} else {
|
} else {
|
||||||
errorMsg = parsed as string;
|
errorMsg = parsed as string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { PYTHON_SIDECAR_TOOLS } from "@snapotter/shared";
|
import { PYTHON_SIDECAR_TOOLS, TOOLS } from "@snapotter/shared";
|
||||||
import { useCallback, useEffect, useRef, useState } from "react";
|
import { useCallback, useEffect, useRef, useState } from "react";
|
||||||
import { formatHeaders, parseApiError } from "@/lib/api";
|
import { formatHeaders, parseApiError } from "@/lib/api";
|
||||||
import { generateId } from "@/lib/utils";
|
import { generateId } from "@/lib/utils";
|
||||||
@@ -47,6 +47,7 @@ export function useToolProcessor(toolId: string) {
|
|||||||
|
|
||||||
const isAiTool = AI_PYTHON_TOOLS.has(toolId);
|
const isAiTool = AI_PYTHON_TOOLS.has(toolId);
|
||||||
const isMediumTool = MEDIUM_TOOLS.has(toolId);
|
const isMediumTool = MEDIUM_TOOLS.has(toolId);
|
||||||
|
const toolName = TOOLS.find((t) => t.id === toolId)?.name ?? toolId;
|
||||||
const processingTimerRef = useRef<ReturnType<typeof setInterval> | null>(null);
|
const processingTimerRef = useRef<ReturnType<typeof setInterval> | null>(null);
|
||||||
|
|
||||||
// Clean up on unmount
|
// Clean up on unmount
|
||||||
@@ -280,7 +281,7 @@ export function useToolProcessor(toolId: string) {
|
|||||||
const parsed = parseApiError(body, xhr.status);
|
const parsed = parseApiError(body, xhr.status);
|
||||||
if (typeof parsed === "object" && parsed.type === "feature_not_installed") {
|
if (typeof parsed === "object" && parsed.type === "feature_not_installed") {
|
||||||
setError(
|
setError(
|
||||||
`Feature "${parsed.featureName}" is not installed. Enable it in Settings → AI Features.`,
|
`${toolName} requires the "${parsed.featureName}" feature. Enable it in Settings → AI Features.`,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
setError(parsed as string);
|
setError(parsed as string);
|
||||||
@@ -324,7 +325,7 @@ export function useToolProcessor(toolId: string) {
|
|||||||
});
|
});
|
||||||
xhr.send(formData);
|
xhr.send(formData);
|
||||||
},
|
},
|
||||||
[toolId, isAiTool, isMediumTool, setProcessing, setError],
|
[toolId, isAiTool, isMediumTool, setProcessing, setError, toolName],
|
||||||
);
|
);
|
||||||
|
|
||||||
const processAllFiles = useCallback(
|
const processAllFiles = useCallback(
|
||||||
@@ -407,7 +408,7 @@ export function useToolProcessor(toolId: string) {
|
|||||||
const body = JSON.parse(text);
|
const body = JSON.parse(text);
|
||||||
const parsed = parseApiError(body, response.status);
|
const parsed = parseApiError(body, response.status);
|
||||||
if (typeof parsed === "object" && parsed.type === "feature_not_installed") {
|
if (typeof parsed === "object" && parsed.type === "feature_not_installed") {
|
||||||
errorMsg = `Feature "${parsed.featureName}" is not installed. Enable it in Settings → AI Features.`;
|
errorMsg = `${toolName} requires the "${parsed.featureName}" feature. Enable it in Settings → AI Features.`;
|
||||||
} else {
|
} else {
|
||||||
errorMsg = parsed as string;
|
errorMsg = parsed as string;
|
||||||
}
|
}
|
||||||
@@ -465,7 +466,7 @@ export function useToolProcessor(toolId: string) {
|
|||||||
setProgress(IDLE_PROGRESS);
|
setProgress(IDLE_PROGRESS);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[toolId, processFiles, setProcessing, setError],
|
[toolId, processFiles, setProcessing, setError, toolName],
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -292,7 +292,12 @@ export function ToolPage() {
|
|||||||
if (isAiTool && !toolInstalled && featureBundle) {
|
if (isAiTool && !toolInstalled && featureBundle) {
|
||||||
return (
|
return (
|
||||||
<AppLayout>
|
<AppLayout>
|
||||||
<FeatureInstallPrompt bundle={featureBundle} isAdmin={isAdmin} toolName={tool?.name} />
|
<FeatureInstallPrompt
|
||||||
|
bundle={featureBundle}
|
||||||
|
isAdmin={isAdmin}
|
||||||
|
toolName={tool?.name}
|
||||||
|
toolDescription={tool?.description}
|
||||||
|
/>
|
||||||
</AppLayout>
|
</AppLayout>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user