From c6b2c325a58cdd5530683aa6743b69a0be3566a9 Mon Sep 17 00:00:00 2001 From: Hiren Kangad Date: Thu, 12 Mar 2026 18:48:55 +0530 Subject: [PATCH] feat(review): wire FeedbackPanel with draft pin, expandRequest, and point-aware jump-to-object MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Pass expandRequest, focusedThreadId, draftPin, onCreatePointThread to FeedbackPanel - Lift thread detail state via onThreadDetailChange → setOpenThreadDetailId - Jump-to-object centers on pin location for point-pinned threads - Pan-only by default; zoom in if object appears <50px on screen - Show toast when jumping to deleted object --- frontend/src/pages/Editor.tsx | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/frontend/src/pages/Editor.tsx b/frontend/src/pages/Editor.tsx index 5479888..08ae71d 100644 --- a/frontend/src/pages/Editor.tsx +++ b/frontend/src/pages/Editor.tsx @@ -990,15 +990,38 @@ export default function Editor({ isPublicView }: EditorProps) { token={localStorage.getItem('refboard_token') || ''} canvasObjects={canvasObjectMap} onError={(msg) => showToast(msg)} - expandThreadId={focusedThreadId} - onJumpToObject={(objectId) => { + expandRequest={expandRequest} + focusedThreadId={focusedThreadId} + draftPin={draftPin} + onCreatePointThread={handleCreatePointThread} + onThreadDetailChange={setOpenThreadDetailId} + onJumpToObject={(objectId, thread) => { const scene = canvasRef.current?.getScene(); const vp = canvasRef.current?.getViewport(); if (!scene || !vp) return; const item = scene.items.get(objectId); - if (!item) return; + if (!item) { + showToast('This item has been deleted'); + return; + } const b = getItemWorldBounds(item); - vp.animate({ time: 300, position: { x: b.x + b.w / 2, y: b.y + b.h / 2 }, ease: 'easeOutQuad' }); + + // For point-pinned threads, center on pin location + let centerX = b.x + b.w / 2; + let centerY = b.y + b.h / 2; + if (thread?.anchor_type === 'point' && thread.pin_x != null && thread.pin_y != null) { + centerX = b.x + thread.pin_x * b.w; + centerY = b.y + thread.pin_y * b.h; + } + + // Pan only by default; zoom in if object is too small on screen + const screenW = b.w * vp.scale.x; + if (screenW < 50) { + const targetScale = Math.min((vp.screenWidth * 0.6) / b.w, 5); + vp.animate({ time: 300, position: { x: centerX, y: centerY }, scale: targetScale, ease: 'easeOutQuad' }); + } else { + vp.animate({ time: 300, position: { x: centerX, y: centerY }, ease: 'easeOutQuad' }); + } selectionRef.current?.selectOnly(objectId); }} />