From 2602248e7a552a19be0ac4e005f2c8183e18995a Mon Sep 17 00:00:00 2001 From: CREDO23 Date: Tue, 7 Apr 2026 17:43:40 +0200 Subject: [PATCH] feat: handle multi-option suggestions in suggestion page UI --- surfsense_web/app/desktop/suggestion/page.tsx | 68 ++++++++++++++----- 1 file changed, 50 insertions(+), 18 deletions(-) diff --git a/surfsense_web/app/desktop/suggestion/page.tsx b/surfsense_web/app/desktop/suggestion/page.tsx index 8d9095320..e98da9a1c 100644 --- a/surfsense_web/app/desktop/suggestion/page.tsx +++ b/surfsense_web/app/desktop/suggestion/page.tsx @@ -14,6 +14,10 @@ type SSEEvent = | { type: "data-thinking-step"; data: { id: string; title: string; status: string; items: string[] }; + } + | { + type: "data-suggestions"; + data: { options: string[] }; }; interface AgentStep { @@ -70,10 +74,11 @@ function StepIcon({ status }: { status: string }) { export default function SuggestionPage() { const api = useElectronAPI(); - const [suggestion, setSuggestion] = useState(""); + const [options, setOptions] = useState([]); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); const [steps, setSteps] = useState([]); + const [expandedOption, setExpandedOption] = useState(null); const abortRef = useRef(null); const isDesktop = !!api?.onAutocompleteContext; @@ -99,9 +104,10 @@ export default function SuggestionPage() { abortRef.current = controller; setIsLoading(true); - setSuggestion(""); + setOptions([]); setError(null); setSteps([]); + setExpandedOption(null); let token = getBearerToken(); if (!token) { @@ -165,8 +171,8 @@ export default function SuggestionPage() { try { const parsed: SSEEvent = JSON.parse(data); - if (parsed.type === "text-delta") { - setSuggestion((prev) => prev + parsed.delta); + if (parsed.type === "data-suggestions") { + setOptions(parsed.data.options); } else if (parsed.type === "error") { setError(friendlyError(parsed.errorText)); } else if (parsed.type === "data-thinking-step") { @@ -226,7 +232,7 @@ export default function SuggestionPage() { ); } - const showLoading = isLoading && !suggestion; + const showLoading = isLoading && options.length === 0; if (showLoading) { return ( @@ -258,29 +264,55 @@ export default function SuggestionPage() { ); } - const handleAccept = () => { - if (suggestion) { - api?.acceptSuggestion?.(suggestion); - } + const handleSelect = (text: string) => { + api?.acceptSuggestion?.(text); }; const handleDismiss = () => { api?.dismissSuggestion?.(); }; - if (!suggestion) return null; + const TRUNCATE_LENGTH = 120; + + if (options.length === 0) return null; return (
-

{suggestion}

+
+ {options.map((option, index) => { + const isExpanded = expandedOption === index; + const needsTruncation = option.length > TRUNCATE_LENGTH; + const displayText = + needsTruncation && !isExpanded + ? option.slice(0, TRUNCATE_LENGTH) + "…" + : option; + + return ( + + )} + + ); + })} +
-