From a9b492cef5a6b9749fddc513be7e2a9acad483fd Mon Sep 17 00:00:00 2001 From: Omar Moustafa Date: Sun, 21 Sep 2025 16:15:03 +0400 Subject: [PATCH 1/3] feat(search): implement search history for search pipe (#1382) * add persistent search history storage * display previous searches in sidebar * allow selecting, renaming, and deleting history items * update lockb --- pipes/search/bun.lockb | Bin 351060 -> 296622 bytes pipes/search/package.json | 1 + pipes/search/src/app/page.tsx | 49 ++- pipes/search/src/components/search-chat.tsx | 110 +++--- pipes/search/src/components/sidebar.tsx | 329 ++++++++++++++++++ .../src/components/ui/dropdown-menu.tsx | 200 +++++++++++ .../src/lib/hooks/use-search-history.tsx | 308 +++++++++++----- 7 files changed, 832 insertions(+), 165 deletions(-) create mode 100644 pipes/search/src/components/sidebar.tsx create mode 100644 pipes/search/src/components/ui/dropdown-menu.tsx diff --git a/pipes/search/bun.lockb b/pipes/search/bun.lockb index de1916b1ad112f4cbb14d564332cac29c2d06fd5..db5be4ec7cb5c44afe65ba8a96ae8973a026e925 100755 GIT binary patch delta 65772 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

pbO&ro0F<S|L`vqbW0cEYH69EZ50ltZV@>aiz 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 delta 100868 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 z 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 diff --git a/pipes/search/package.json b/pipes/search/package.json index 01f7c6559a..4e6363d0d5 100644 --- a/pipes/search/package.json +++ b/pipes/search/package.json @@ -14,6 +14,7 @@ "@radix-ui/react-avatar": "^1.1.3", "@radix-ui/react-checkbox": "^1.1.3", "@radix-ui/react-dialog": "^1.1.6", + "@radix-ui/react-dropdown-menu": "^2.1.16", "@radix-ui/react-label": "^2.1.1", "@radix-ui/react-popover": "^1.1.3", "@radix-ui/react-progress": "^1.1.1", diff --git a/pipes/search/src/app/page.tsx b/pipes/search/src/app/page.tsx index bf53129b8d..14014511dd 100644 --- a/pipes/search/src/app/page.tsx +++ b/pipes/search/src/app/page.tsx @@ -3,29 +3,46 @@ import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"; import { useSettings } from "@/lib/hooks/use-settings"; import { Terminal } from "lucide-react"; import { SearchChat } from "@/components/search-chat"; +import { Sidebar } from "@/components/sidebar"; +import { useSearchHistory } from "@/lib/hooks/use-search-history"; +import { cn } from "@/lib/utils"; export default function SearchPage() { const { settings } = useSettings(); + const { isCollapsed } = useSearchHistory(); const aiDisabled = settings?.aiProviderType === "screenpipe-cloud" && !settings?.user?.token; return ( -

- {aiDisabled && ( - - - heads up! - - your ai provider is set to 'screenpipe-cloud' and you - don't have logged in
- please login to use this pipe, go to app > settings > login -
-
- )} -

search your screen history

- +
+ +
+
+ {aiDisabled && ( + + + heads up! + + your ai provider is set to 'screenpipe-cloud' and you + don't have logged in
+ please login to use this pipe, go to app > settings > + login +
+
+ )} +

search your screen history

+ +
+
); } diff --git a/pipes/search/src/components/search-chat.tsx b/pipes/search/src/components/search-chat.tsx index 9ac568856a..688cb96754 100644 --- a/pipes/search/src/components/search-chat.tsx +++ b/pipes/search/src/components/search-chat.tsx @@ -34,9 +34,7 @@ import { Square, Clock, Check, - Plus, AlertCircle, - Bot, Settings, Copy, SparklesIcon, @@ -75,31 +73,14 @@ import { Checkbox } from "@/components/ui/checkbox"; import { IconCode } from "@/components/ui/icons"; import { CodeBlock } from "@/components/ui/codeblock"; import { SqlAutocompleteInput } from "@/components/sql-autocomplete-input"; -import { cn, removeDuplicateSelections } from "@/lib/utils"; +import { removeDuplicateSelections } from "@/lib/utils"; import { ExampleSearch, ExampleSearchCards, } from "@/components/example-search-cards"; import { useDebounce } from "@/lib/hooks/use-debounce"; import { useHealthCheck } from "@/lib/hooks/use-health-check"; -import { - SearchHistory, - useSearchHistory, -} from "@/lib/hooks/use-search-history"; -import { - CommandInput, - CommandList, - CommandEmpty, - CommandGroup, - CommandItem, - Command, -} from "./ui/command"; -import { type Speaker } from "@screenpipe/browser"; -import { - Popover, - PopoverContent, - PopoverTrigger, -} from "@/components/ui/popover"; +import { useSearchHistory } from "@/lib/hooks/use-search-history"; import { useSettings } from "@/lib/hooks/use-settings"; import { SearchFilterGenerator } from "./search-filter-generator"; import { @@ -109,6 +90,7 @@ import { import { AIPresetsDialog } from "./ai-presets-dialog"; import { usePipeSettings } from "@/lib/hooks/use-pipe-settings"; import type { Settings as AppSettings } from "@screenpipe/js"; +import { type Speaker } from "@screenpipe/browser"; import { DEFAULT_PROMPT } from "./ai-presets-dialog"; import { AIPresetsSelector } from "./ai-presets-selector"; @@ -229,12 +211,12 @@ export function SearchChat() { const { searches, currentSearchId, - setCurrentSearchId, addSearch, - deleteSearch, - isCollapsed, - toggleCollapse, + addAIResponse, + addUserMessage, + setCurrentSearchId, } = useSearchHistory(); + // Search state const { health, isServerDown } = useHealthCheck(); const [query, setQuery] = useState(""); @@ -262,6 +244,7 @@ export function SearchChat() { [key: number]: Speaker; }>({}); const [openSpeakers, setOpenSpeakers] = useState(false); + // Chat state const [chatMessages, setChatMessages] = useState>([]); @@ -705,9 +688,15 @@ export function SearchChat() { userMessage, { id: generateId(), role: "assistant", content: "" }, ]); + + const currentInput = floatingInput; setFloatingInput(""); setIsAiLoading(true); + if (currentSearchId && currentInput) { + addUserMessage(currentSearchId, currentInput); + } + const preset = getPreset(); if (!preset) { @@ -773,7 +762,7 @@ export function SearchChat() { ) )} - User query: ${floatingInput}`, + User query: ${currentInput}`, }, ]; @@ -815,6 +804,10 @@ export function SearchChat() { ]); scrollToBottom(); } + + if (currentSearchId && fullResponse) { + addAIResponse(currentSearchId, fullResponse); + } } catch (error: any) { if (error.toString().includes("unauthorized")) { toast({ @@ -874,7 +867,7 @@ export function SearchChat() { setChatMessages([]); scrollToBottom(); setResults([]); - setSimilarityThreshold(1); // Reset similarity threshold to 1 + setSimilarityThreshold(1); try { // if browserUrl contains special characters like :, /, etc, wrap in double quotes @@ -914,8 +907,10 @@ export function SearchChat() { setResults(response.data); setTotalResults(response.pagination.total); - // Save search to history - // await onAddSearch(searchParams, response.data); + if (newOffset === 0) { + const searchId = addSearch(searchParams, response.data); + setCurrentSearchId(searchId); + } } catch (error) { console.error("search error:", error); toast({ @@ -1242,12 +1237,36 @@ export function SearchChat() { )); }; - // Add effect to restore search when currentSearchId changes useEffect(() => { - // if (currentSearchId) { + console.log(`currentSearchId changed: ${currentSearchId}`); + + if (currentSearchId === null) { + // reset to defaults + setQuery(""); + setContentType("all"); + setLimit(500); + setStartDate(new Date(Date.now() - 24 * 3600000)); + setEndDate(new Date()); + setAppName(""); + setWindowName(""); + setBrowserUrl(""); + setIncludeFrames(false); + setMinLength(50); + setMaxLength(10000); + setSelectedSpeakers({}); + setFrameName(""); + + setResults([]); + setTotalResults(0); + setHasSearched(false); + setShowExamples(true); + setChatMessages([]); + + return; + } + const selectedSearch = searches.find((s) => s.id === currentSearchId); if (selectedSearch) { - // Restore search parameters setQuery(selectedSearch.searchParams.q || ""); setContentType(selectedSearch.searchParams.content_type); setLimit(selectedSearch.searchParams.limit); @@ -1259,13 +1278,11 @@ export function SearchChat() { setMinLength(selectedSearch.searchParams.min_length); setMaxLength(selectedSearch.searchParams.max_length); - // Restore results setResults(selectedSearch.results); setTotalResults(selectedSearch.results.length); setHasSearched(true); setShowExamples(false); - // Restore messages if any if (selectedSearch.messages) { setChatMessages( selectedSearch.messages.map((msg) => ({ @@ -1275,20 +1292,13 @@ export function SearchChat() { })) ); } + } else { + console.log("no search found with id:", currentSearchId); } - // } }, [currentSearchId, searches]); - const handleNewSearch = () => { - // setCurrentSearchId(null); - location.reload(); - // Add any other reset logic you need - }; - - // Add this effect near other useEffect hooks useEffect(() => { const handleKeyDown = (e: KeyboardEvent) => { - // Check for Cmd+Shift (macOS) or Ctrl+Shift (Windows/Linux) if ( e.shiftKey && ((currentPlatform === "macos" && e.metaKey) || @@ -1309,18 +1319,6 @@ export function SearchChat() { return (
-
- {/* */} - -
-
{/* Add the new SearchFilterGenerator component */} {/* Content Type Checkboxes and Code Button */}
- {/* Remove MultiSelectCombobox from here */} - {/* Add browser URL input */} void; + onDelete: () => void; + onRename: (newTitle: string) => void; +} + +const SearchHistoryItem = ({ + search, + isActive, + onClick, + onDelete, + onRename, +}: SearchHistoryItemProps) => { + const [isMenuOpen, setIsMenuOpen] = React.useState(false); + const [isRenameDialogOpen, setIsRenameDialogOpen] = React.useState(false); + const [tempTitle, setTempTitle] = React.useState(""); + + const getDisplayText = () => + search.title || + search.query || + search.searchParams?.app_name || + search.searchParams?.window_name || + "Untitled"; + + const handleRenameClick = (e: React.MouseEvent) => { + e.stopPropagation(); + setTempTitle(getDisplayText()); + setIsRenameDialogOpen(true); + setIsMenuOpen(false); + }; + + const handleRenameSubmit = () => { + const val = tempTitle.trim() || "Untitled"; + onRename(val); + setIsRenameDialogOpen(false); + setTempTitle(""); + }; + + return ( + <> +
{ + if (!isRenameDialogOpen) onClick(); + }} + > + +
+
{getDisplayText()}
+
+ +
+ + + + + e.stopPropagation()} + > + + rename + + { + e.stopPropagation(); + onDelete(); + }} + className="flex items-center gap-2 text-red-600 focus:text-red-700 focus:bg-red-50" + > + delete + + + +
+
+ + {/* Rename Dialog */} + + + + rename search + + give this search a new name to help you find it later + + +
+ setTempTitle(e.target.value)} + placeholder="Enter conversation name..." + className="w-full" + onKeyDown={(e) => { + if (e.key === "Enter") handleRenameSubmit(); + }} + autoFocus + /> +
+ + + + +
+
+ + ); +}; + +interface SidebarProps { + className?: string; +} + +export function Sidebar({ className }: SidebarProps) { + const { + searches, + currentSearchId, + setCurrentSearchId, + deleteSearch, + clearHistory, + isCollapsed, + toggleCollapse, + renameSearch, + } = useSearchHistory(); + + const list = Array.isArray(searches) ? searches : []; + + const handleNewSearch = React.useCallback(() => { + setCurrentSearchId(null); + }, [setCurrentSearchId]); + + const handleSearchSelect = React.useCallback( + (searchId: string) => setCurrentSearchId(searchId), + [setCurrentSearchId] + ); + + const handleRename = React.useCallback( + (id: string, newTitle: string) => renameSearch(id, newTitle), + [renameSearch] + ); + + const SidebarContent = () => ( +
+ {/* Header */} +
+ + +
+ + {/* Search History */} +
+ +
+ {list.length === 0 ? ( +
+ +
no searches yet
+
+ your search history will appear here +
+ +
+ ) : ( +
+ {list.map((search) => ( + handleSearchSelect(search.id)} + onDelete={() => deleteSearch(search.id)} + onRename={(title) => handleRename(search.id, title)} + /> + ))} +
+ )} +
+
+
+ + {/* Footer */} + {searches.length > 0 && ( +
+ +
+ )} +
+ ); + + return ( + <> + + + + + ); +} diff --git a/pipes/search/src/components/ui/dropdown-menu.tsx b/pipes/search/src/components/ui/dropdown-menu.tsx new file mode 100644 index 0000000000..f753477768 --- /dev/null +++ b/pipes/search/src/components/ui/dropdown-menu.tsx @@ -0,0 +1,200 @@ +"use client" + +import * as React from "react" +import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu" +import { Check, ChevronRight, Circle } from "lucide-react" + +import { cn } from "@/lib/utils" + +const DropdownMenu = DropdownMenuPrimitive.Root + +const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger + +const DropdownMenuGroup = DropdownMenuPrimitive.Group + +const DropdownMenuPortal = DropdownMenuPrimitive.Portal + +const DropdownMenuSub = DropdownMenuPrimitive.Sub + +const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup + +const DropdownMenuSubTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, children, ...props }, ref) => ( + + {children} + + +)) +DropdownMenuSubTrigger.displayName = + DropdownMenuPrimitive.SubTrigger.displayName + +const DropdownMenuSubContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DropdownMenuSubContent.displayName = + DropdownMenuPrimitive.SubContent.displayName + +const DropdownMenuContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, sideOffset = 4, ...props }, ref) => ( + + + +)) +DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName + +const DropdownMenuItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, ...props }, ref) => ( + +)) +DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName + +const DropdownMenuCheckboxItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, checked, ...props }, ref) => ( + + + + + + + {children} + +)) +DropdownMenuCheckboxItem.displayName = + DropdownMenuPrimitive.CheckboxItem.displayName + +const DropdownMenuRadioItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + + + + {children} + +)) +DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName + +const DropdownMenuLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, ...props }, ref) => ( + +)) +DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName + +const DropdownMenuSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName + +const DropdownMenuShortcut = ({ + className, + ...props +}: React.HTMLAttributes) => { + return ( + + ) +} +DropdownMenuShortcut.displayName = "DropdownMenuShortcut" + +export { + DropdownMenu, + DropdownMenuTrigger, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuCheckboxItem, + DropdownMenuRadioItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuShortcut, + DropdownMenuGroup, + DropdownMenuPortal, + DropdownMenuSub, + DropdownMenuSubContent, + DropdownMenuSubTrigger, + DropdownMenuRadioGroup, +} diff --git a/pipes/search/src/lib/hooks/use-search-history.tsx b/pipes/search/src/lib/hooks/use-search-history.tsx index 4673e3e220..189886623f 100644 --- a/pipes/search/src/lib/hooks/use-search-history.tsx +++ b/pipes/search/src/lib/hooks/use-search-history.tsx @@ -1,127 +1,251 @@ "use client"; -import { useEffect, useState } from 'react'; -import localforage from 'localforage'; +import { useEffect, useSyncExternalStore } from "react"; +import localforage from "localforage"; export interface SearchHistory { + id: string; + title?: string; + query: string; + timestamp: string; + searchParams: { + q?: string; + content_type: string; + limit: number; + offset: number; + start_time: string; + end_time: string; + app_name?: string; + window_name?: string; + include_frames: boolean; + min_length: number; + max_length: number; + }; + results: any[]; + messages: { id: string; - query: string; + type: "search" | "ai"; + content: string; timestamp: string; - searchParams: { - q?: string; - content_type: string; - limit: number; - offset: number; - start_time: string; - end_time: string; - app_name?: string; - window_name?: string; - include_frames: boolean; - min_length: number; - max_length: number; - }; - results: any[]; - messages: { - id: string; - type: 'search' | 'ai'; - content: string; - timestamp: string; - }[]; - } + }[]; +} + +const STORAGE_KEY = "screenpipe-search-history"; + +type StoreState = { + searches: SearchHistory[]; + currentSearchId: string | null; + isCollapsed: boolean; + loaded: boolean; +}; -const HISTORY_KEY = 'screenpipe-search-history'; +const store = { + state: { + searches: [] as SearchHistory[], + currentSearchId: null as string | null, + isCollapsed: true, + loaded: false, + } as StoreState, + listeners: new Set<() => void>(), + set(partial: Partial) { + store.state = { ...store.state, ...partial }; + store.listeners.forEach((l) => l()); + }, + subscribe(listener: () => void) { + store.listeners.add(listener); + return () => store.listeners.delete(listener); + }, + getSnapshot() { + return store.state; + }, +}; + +// helper: normalize/migrate any legacy or corrupt shapes to an array +function normalizeSearches(raw: any): SearchHistory[] { + if (!raw) return []; + if (Array.isArray(raw)) return raw.filter((s) => s && typeof s === "object"); + if (typeof raw === "object") { + // legacy map/object-of-id -> value + return Object.values(raw).filter( + (s) => s && typeof s === "object" + ) as SearchHistory[]; + } + return []; +} + +// persist helpers +async function persist() { + try { + await localforage.setItem(STORAGE_KEY, store.state.searches); + } catch (e) { + console.error("persist history failed", e); + } +} + +async function loadOnce() { + if (store.state.loaded) return; + try { + const data = await localforage.getItem(STORAGE_KEY); + const normalized = normalizeSearches(data); + store.set({ searches: normalized, loaded: true }); + } catch (e) { + console.error("load history failed", e); + store.set({ loaded: true, searches: [] }); + } +} export function useSearchHistory() { - const [searches, setSearches] = useState([]); - const [currentSearchId, setCurrentSearchId] = useState(null); - const [isLoading, setIsLoading] = useState(true); - const [isCollapsed, setIsCollapsed] = useState(true); + const snapshot = useSyncExternalStore( + store.subscribe, + store.getSnapshot, + store.getSnapshot + ); useEffect(() => { - loadSearches(); + loadOnce(); }, []); - const loadSearches = async () => { - try { - const stored = await localforage.getItem(HISTORY_KEY); - setSearches(stored || []); - } catch (error) { - console.error('failed to load search history:', error); - } - setIsLoading(false); - }; + const safeSearches = Array.isArray(snapshot.searches) + ? snapshot.searches + : normalizeSearches(snapshot.searches); - const saveSearches = async (updated: SearchHistory[]) => { - try { - await localforage.setItem(HISTORY_KEY, updated); - setSearches(updated); - } catch (error) { - console.error('failed to save search history:', error); - } + const setCurrentSearchId = (id: string | null) => { + store.set({ currentSearchId: id }); }; - const addSearch = async (searchParams: any, results: any[]) => { - const timestamp = new Date().toISOString(); + const addSearch = (searchParams: any, results: any[]) => { + const ts = new Date().toISOString(); + const derivedTitle = + searchParams.q || + searchParams.app_name || + searchParams.window_name || + "Untitled"; const newSearch: SearchHistory = { id: crypto.randomUUID(), - query: searchParams.q || '', - timestamp, - searchParams, - results, - messages: [{ - id: crypto.randomUUID(), - type: 'search' as const, - content: searchParams.q || '', - timestamp - }] + title: derivedTitle, + query: searchParams.q || "", + timestamp: ts, + searchParams: { + q: searchParams.q, + content_type: searchParams.contentType, + limit: searchParams.limit, + offset: searchParams.offset, + start_time: searchParams.startTime, + end_time: searchParams.endTime, + app_name: searchParams.appName, + window_name: searchParams.windowName, + include_frames: searchParams.includeFrames, + min_length: searchParams.minLength, + max_length: searchParams.maxLength, + }, + results: Array.isArray(results) ? results : [], + messages: [ + { + id: crypto.randomUUID(), + type: "search", + content: searchParams.q || "", + timestamp: ts, + }, + ], }; - - const updated = [newSearch, ...searches]; - await saveSearches(updated); - setCurrentSearchId(newSearch.id); + const current = Array.isArray(store.state.searches) + ? store.state.searches + : normalizeSearches(store.state.searches); + store.set({ + searches: [newSearch, ...current], + currentSearchId: newSearch.id, + }); + persist(); return newSearch.id; }; - const addAIResponse = async (searchId: string, response: string) => { - const timestamp = new Date().toISOString(); - const updated = searches.map(search => { - if (search.id === searchId) { - return { - ...search, - messages: [...search.messages, { - id: crypto.randomUUID(), - type: 'ai' as const, - content: response, - timestamp - }] - }; - } - return search; + const addAIResponse = (searchId: string, response: string) => { + const ts = new Date().toISOString(); + const updated = store.state.searches.map((s) => + s.id === searchId + ? { + ...s, + messages: [ + ...s.messages, + { + id: crypto.randomUUID(), + type: "ai" as const, + content: response, + timestamp: ts, + }, + ], + } + : s + ); + store.set({ searches: updated }); + persist(); + }; + + const addUserMessage = (searchId: string, message: string) => { + const ts = new Date().toISOString(); + const updated = store.state.searches.map((s) => + s.id === searchId + ? { + ...s, + messages: [ + ...s.messages, + { + id: crypto.randomUUID(), + type: "search" as const, + content: message, + timestamp: ts, + }, + ], + } + : s + ); + store.set({ searches: updated }); + persist(); + }; + + const deleteSearch = (id: string) => { + const updated = store.state.searches.filter((s) => s.id !== id); + store.set({ + searches: updated, + currentSearchId: + store.state.currentSearchId === id ? null : store.state.currentSearchId, }); - await saveSearches(updated); + persist(); + }; + + const clearHistory = () => { + store.set({ searches: [], currentSearchId: null }); + persist(); }; - const deleteSearch = async (id: string) => { - const updated = searches.filter(s => s.id !== id); - await saveSearches(updated); - if (currentSearchId === id) { - setCurrentSearchId(null); - } + const resetHistoryState = () => { + store.set({ currentSearchId: null }); }; - const toggleCollapse = () => { - setIsCollapsed(!isCollapsed); + const toggleCollapse = () => + store.set({ isCollapsed: !store.state.isCollapsed }); + + const renameSearch = (id: string, title: string) => { + const updated = store.state.searches.map((s) => + s.id === id ? { ...s, title } : s + ); + store.set({ searches: updated }); + persist(); }; return { - searches, - currentSearchId, + searches: safeSearches, + currentSearchId: snapshot.currentSearchId, + isCollapsed: snapshot.isCollapsed, setCurrentSearchId, addSearch, addAIResponse, + addUserMessage, deleteSearch, - isLoading, - isCollapsed, - toggleCollapse + clearHistory, + resetHistoryState, + toggleCollapse, + renameSearch, + isLoading: !snapshot.loaded, }; -} +} From a94421e0d02a16f128e12cdb8ff647fb3a7198c9 Mon Sep 17 00:00:00 2001 From: Omar Moustafa Date: Sat, 8 Nov 2025 13:51:31 +0400 Subject: [PATCH 2/3] fix typos --- pipes/search/src/app/page.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pipes/search/src/app/page.tsx b/pipes/search/src/app/page.tsx index 14014511dd..177c13ab44 100644 --- a/pipes/search/src/app/page.tsx +++ b/pipes/search/src/app/page.tsx @@ -32,10 +32,10 @@ export default function SearchPage() { heads up! - your ai provider is set to 'screenpipe-cloud' and you - don't have logged in
- please login to use this pipe, go to app > settings > - login + your AI provider is set to 'screenpipe-cloud', and you + aren't logged in.
+ please log in to use this pipe. go to app > settings > + log in.
)} From 1d7ca981a193b36985af4174983d233a89f7773a Mon Sep 17 00:00:00 2001 From: Omar Moustafa Date: Sat, 8 Nov 2025 13:54:43 +0400 Subject: [PATCH 3/3] refactor --- pipes/search/src/components/search-chat.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pipes/search/src/components/search-chat.tsx b/pipes/search/src/components/search-chat.tsx index 688cb96754..d5267906b6 100644 --- a/pipes/search/src/components/search-chat.tsx +++ b/pipes/search/src/components/search-chat.tsx @@ -244,7 +244,6 @@ export function SearchChat() { [key: number]: Speaker; }>({}); const [openSpeakers, setOpenSpeakers] = useState(false); - // Chat state const [chatMessages, setChatMessages] = useState>([]); @@ -1278,11 +1277,13 @@ export function SearchChat() { setMinLength(selectedSearch.searchParams.min_length); setMaxLength(selectedSearch.searchParams.max_length); + // Restore results setResults(selectedSearch.results); setTotalResults(selectedSearch.results.length); setHasSearched(true); setShowExamples(false); + // Restore messages if any if (selectedSearch.messages) { setChatMessages( selectedSearch.messages.map((msg) => ({