From 67208114bfbc363ed5937642dd211da26d61643e Mon Sep 17 00:00:00 2001 From: harshinde Date: Sat, 1 Aug 2026 17:38:58 +0530 Subject: [PATCH 1/8] feat: add comments panel and collab protocol support --- .../components/comments/AddCommentDialog.tsx | 150 ++++++ .../components/comments/CommentMapOverlay.tsx | 150 ++++++ .../src/components/comments/CommentThread.tsx | 224 +++++++++ .../src/components/comments/CommentsPanel.tsx | 446 ++++++++++++++++++ .../src/components/comments/useCommentTool.ts | 164 +++++++ .../src/components/layout/DesktopShell.tsx | 49 +- .../layout/RemoteCursorsOverlay.tsx | 4 +- .../src/components/layout/TopToolbar.tsx | 9 + .../src/hooks/useCollaboration.ts | 227 +++------ .../src/hooks/useRegisterCommentsPanel.ts | 26 + .../src/lib/build-project-snapshot.ts | 1 + .../geolibre-desktop/src/lib/collab-client.ts | 19 +- .../src/lib/collab-protocol.ts | 23 +- .../src/lib/project-broadcast-changed.ts | 5 +- package-lock.json | 115 ++--- packages/core/src/project.ts | 106 +++++ packages/core/src/store.ts | 48 ++ packages/core/src/types.ts | 28 ++ tests/collab-protocol.test.ts | 36 +- tests/comments.test.ts | 122 +++++ workers/collab/src/protocol.ts | 15 +- workers/collab/src/session.ts | 63 +++ 22 files changed, 1774 insertions(+), 256 deletions(-) create mode 100644 apps/geolibre-desktop/src/components/comments/AddCommentDialog.tsx create mode 100644 apps/geolibre-desktop/src/components/comments/CommentMapOverlay.tsx create mode 100644 apps/geolibre-desktop/src/components/comments/CommentThread.tsx create mode 100644 apps/geolibre-desktop/src/components/comments/CommentsPanel.tsx create mode 100644 apps/geolibre-desktop/src/components/comments/useCommentTool.ts create mode 100644 apps/geolibre-desktop/src/hooks/useRegisterCommentsPanel.ts create mode 100644 tests/comments.test.ts diff --git a/apps/geolibre-desktop/src/components/comments/AddCommentDialog.tsx b/apps/geolibre-desktop/src/components/comments/AddCommentDialog.tsx new file mode 100644 index 000000000..c433043a1 --- /dev/null +++ b/apps/geolibre-desktop/src/components/comments/AddCommentDialog.tsx @@ -0,0 +1,150 @@ +import { useState } from "react"; +import { + Button, + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, + Input, + Textarea, +} from "@geolibre/ui"; +import { MapPin, Layers, MessageSquare, Send, User } from "lucide-react"; +import type { PendingCommentState } from "./useCommentTool"; + +interface AddCommentDialogProps { + pendingComment: PendingCommentState; + onSubmit: (body: string, authorName?: string) => void; + onCancel: () => void; +} + +export function AddCommentDialog({ + pendingComment, + onSubmit, + onCancel, +}: AddCommentDialogProps) { + const savedName = typeof localStorage !== "undefined" ? localStorage.getItem("geolibre_author_name") : null; + const hasSavedName = !!savedName && savedName.trim().length > 0; + + const [text, setText] = useState(""); + const [authorName, setAuthorName] = useState(savedName ?? ""); + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + if (!text.trim()) return; + + const finalName = authorName.trim() || savedName?.trim() || "Author"; + if (typeof localStorage !== "undefined" && finalName) { + try { + localStorage.setItem("geolibre_author_name", finalName); + } catch { + // ignore storage errors + } + } + + onSubmit(text.trim(), finalName); + setText(""); + }; + + const anchor = pendingComment.anchor; + const lngLat = anchor.lngLat; + + return ( + { if (!open) onCancel(); }}> + + + + + Add Review Comment + + + Post an anchored note on this project for team review or offline reference. + + + +
+
+ {anchor.type === "feature" ? ( + <> + + + Anchored to Feature #{String(anchor.featureId)} ({anchor.layerId}) + + + ) : ( + <> + + + Anchored to ({lngLat ? `${lngLat[1].toFixed(4)}, ${lngLat[0].toFixed(4)}` : "Map Point"}) + + + )} +
+ + {/* Prompt for name 1 time if not saved in localStorage */} + {!hasSavedName ? ( +
+ + setAuthorName(e.target.value)} + placeholder="e.g. Alex or Sarah" + className="text-xs h-8" + autoFocus + /> +
+ ) : ( +
+ Posting as {savedName} + +
+ )} + +
+ +