From 098e56a8950efbef79e551e12622ae7c8cd90c03 Mon Sep 17 00:00:00 2001 From: Mohamed Bassem Date: Sat, 8 Nov 2025 18:52:30 +0000 Subject: feat(extension): Allow writing notes directly in the extension (#2104) * feat(extension): add notes editor to bookmark hoarded screen Adds the ability to directly add and edit notes for bookmarks in the browser extension's hoarded screen (the page shown after saving a bookmark). Changes: - Created Textarea UI component for the browser extension - Created NoteEditor component that uses useUpdateBookmark hook - Added Notes section to BookmarkSavedPage, displayed between the header and tags - Notes auto-save when the user clicks away from the textarea (onBlur) - Shows saving state and error messages to the user This brings feature parity with the web app's notes functionality. * add explicit button * more fixes --------- Co-authored-by: Claude --- .../src/components/NoteEditor.tsx | 105 +++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 apps/browser-extension/src/components/NoteEditor.tsx (limited to 'apps/browser-extension/src/components/NoteEditor.tsx') diff --git a/apps/browser-extension/src/components/NoteEditor.tsx b/apps/browser-extension/src/components/NoteEditor.tsx new file mode 100644 index 00000000..15f1515b --- /dev/null +++ b/apps/browser-extension/src/components/NoteEditor.tsx @@ -0,0 +1,105 @@ +import { useEffect, useState } from "react"; +import { Check, Save } from "lucide-react"; + +import { + useAutoRefreshingBookmarkQuery, + useUpdateBookmark, +} from "@karakeep/shared-react/hooks/bookmarks"; + +import { Button } from "./ui/button"; +import { Textarea } from "./ui/textarea"; + +export function NoteEditor({ bookmarkId }: { bookmarkId: string }) { + const { data: bookmark } = useAutoRefreshingBookmarkQuery({ bookmarkId }); + const [error, setError] = useState(null); + const [isSaving, setIsSaving] = useState(false); + const [noteValue, setNoteValue] = useState(""); + const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false); + + // Update local state when bookmark changes, but only if there are no unsaved changes + // This prevents overwriting user's edits while they're typing + useEffect(() => { + if (bookmark && !hasUnsavedChanges) { + setNoteValue(bookmark.note ?? ""); + } + }, [bookmark?.note, bookmark, hasUnsavedChanges]); + + const updateBookmarkMutator = useUpdateBookmark({ + onSuccess: () => { + setError(null); + setIsSaving(false); + setHasUnsavedChanges(false); + }, + onError: (e) => { + setError(e.message || "Failed to save note"); + setIsSaving(false); + }, + }); + + const handleSave = () => { + if (!bookmark || noteValue === bookmark.note || isSaving) { + return; + } + setIsSaving(true); + setError(null); + updateBookmarkMutator.mutate({ + bookmarkId: bookmark.id, + note: noteValue, + }); + }; + + if (!bookmark) { + return null; + } + + return ( +
+