fix(annotations): address code review findings (1-8, 10)

1. toggleVote wrapped in transaction (race condition fix)
2. FeedbackPanel fetch calls now surface errors via onError/toast
3. Extracted resolveBoard/hasCollectionRole to shared board-access.js
4. AnnotationStore uses monotonic version counter for snapshots
5. PinOverlay uses object pool instead of destroy/recreate on refresh
6. canvasObjects prop memoized with useMemo
7. PinOverlay store subscription cleaned up on unmount
8. Comment content capped at 5000 chars (backend validation)
10. anchor_type validated to 'object' or 'point'
This commit is contained in:
Hiren Kangad
2026-03-10 21:16:08 +05:30
parent 303124f518
commit f7a39a1726
9 changed files with 176 additions and 133 deletions
+15 -10
View File
@@ -162,6 +162,19 @@ export default function Editor({ isPublicView }: EditorProps) {
uploadManager, onCanvasChange, showToast, setOnlineUsers, setSelectedLayerIds,
});
// Build canvas objects map for FeedbackPanel (memoized on object count changes)
const canvasObjectMap = React.useMemo(() => {
const scene = canvasRef.current?.getScene();
const map = new Map<string, { id: string; name?: string; type: string }>();
if (scene) {
for (const item of scene.items.values()) {
map.set(item.id, { id: item.id, name: item.data.name, type: item.data.type });
}
}
return map;
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [objectCount]);
// Toggle pin overlay visibility with review mode
useEffect(() => {
if (pinOverlay) {
@@ -663,16 +676,8 @@ export default function Editor({ isPublicView }: EditorProps) {
userId={user.id}
boardId={resolvedBoardId}
token={localStorage.getItem('token') || ''}
canvasObjects={(() => {
const scene = canvasRef.current?.getScene();
const map = new Map<string, { id: string; name?: string; type: string }>();
if (scene) {
for (const item of scene.items.values()) {
map.set(item.id, { id: item.id, name: item.data.name, type: item.data.type });
}
}
return map;
})()}
canvasObjects={canvasObjectMap}
onError={(msg) => showToast(msg)}
onJumpToObject={(objectId) => {
const scene = canvasRef.current?.getScene();
const vp = canvasRef.current?.getViewport();