From bbfce5028f780e8df399c5a12146fd964a8a4201 Mon Sep 17 00:00:00 2001 From: Anish Sarkar <104695310+AnishSarkar22@users.noreply.github.com> Date: Fri, 10 Apr 2026 12:52:27 +0530 Subject: [PATCH] feat: enhance MemoryContent and TeamMemoryManager components with new input handling, improved export options --- .../components/MemoryContent.tsx | 173 ++++++++++++------ .../settings/team-memory-manager.tsx | 172 +++++++++++------ 2 files changed, 231 insertions(+), 114 deletions(-) diff --git a/surfsense_web/app/dashboard/[search_space_id]/user-settings/components/MemoryContent.tsx b/surfsense_web/app/dashboard/[search_space_id]/user-settings/components/MemoryContent.tsx index 19b4c3e5b..0615467f0 100644 --- a/surfsense_web/app/dashboard/[search_space_id]/user-settings/components/MemoryContent.tsx +++ b/surfsense_web/app/dashboard/[search_space_id]/user-settings/components/MemoryContent.tsx @@ -1,7 +1,7 @@ "use client"; import { useAtomValue } from "jotai"; -import { Download, Info, Send } from "lucide-react"; +import { ArrowUp, ChevronDown, ClipboardCopy, Download, Info, Pen } from "lucide-react"; import { useCallback, useEffect, useRef, useState } from "react"; import { toast } from "sonner"; import { z } from "zod"; @@ -9,8 +9,14 @@ import { activeSearchSpaceIdAtom } from "@/atoms/search-spaces/search-space-quer import { PlateEditor } from "@/components/editor/plate-editor"; import { Alert, AlertDescription } from "@/components/ui/alert"; import { Button } from "@/components/ui/button"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; import { Spinner } from "@/components/ui/spinner"; -import { Textarea } from "@/components/ui/textarea"; + import { baseApiService } from "@/lib/apis/base-api.service"; const MEMORY_HARD_LIMIT = 25_000; @@ -26,7 +32,8 @@ export function MemoryContent() { const [saving, setSaving] = useState(false); const [editQuery, setEditQuery] = useState(""); const [editing, setEditing] = useState(false); - const textareaRef = useRef(null); + const [showInput, setShowInput] = useState(false); + const textareaRef = useRef(null); const fetchMemory = useCallback(async () => { try { @@ -70,6 +77,7 @@ export function MemoryContent() { }); setMemory(data.memory_md); setEditQuery(""); + setShowInput(false); toast.success("Memory updated"); } catch { toast.error("Failed to edit memory"); @@ -78,7 +86,12 @@ export function MemoryContent() { } }; - const handleExport = () => { + const openInput = () => { + setShowInput(true); + requestAnimationFrame(() => textareaRef.current?.focus()); + }; + + const handleDownload = () => { if (!memory) return; try { const blob = new Blob([memory], { type: "text/markdown;charset=utf-8" }); @@ -91,14 +104,27 @@ export function MemoryContent() { document.body.removeChild(a); URL.revokeObjectURL(url); } catch { - toast.error("Failed to export memory"); + toast.error("Failed to download memory"); } }; - const handleKeyDown = (e: React.KeyboardEvent) => { + const handleCopyMarkdown = async () => { + if (!memory) return; + try { + await navigator.clipboard.writeText(memory); + toast.success("Copied to clipboard"); + } catch { + toast.error("Failed to copy memory"); + } + }; + + const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); handleEdit(); + } else if (e.key === "Escape") { + setShowInput(false); + setEditQuery(""); } }; @@ -143,62 +169,95 @@ export function MemoryContent() { -
- +
+
+ +
+ + {showInput ? ( +
+
+ setEditQuery(e.target.value)} + onKeyDown={handleKeyDown} + placeholder="Tell SurfSense what to remember or forget..." + disabled={editing} + className="flex-1 bg-transparent text-sm outline-none placeholder:text-muted-foreground/70" + /> + +
+
+ ) : ( + + )}
-
- - {charCount.toLocaleString()} / {MEMORY_HARD_LIMIT.toLocaleString()} characters +
+ + {charCount.toLocaleString()} / {MEMORY_HARD_LIMIT.toLocaleString()} + characters + chars {charCount > 15_000 && charCount <= MEMORY_HARD_LIMIT && " - Approaching limit"} {charCount > MEMORY_HARD_LIMIT && " - Exceeds limit"} -
- -
-