fix: remove CSS transform scaling from pinned shapes
Pinned shapes should only stay fixed in screen position, not fixed in visual size. The CSS transform: scale() was causing shapes to appear differently sized when pinned. Now pinned shapes: - Stay at a fixed screen position (don't move when panning) - Scale normally with zoom (get bigger/smaller like other shapes) - Don't change appearance when pin is toggled 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
cc1928852f
commit
72c2e52ae7
|
|
@ -1,43 +0,0 @@
|
|||
---
|
||||
id: task-053
|
||||
title: Fix user identity caching on logout/login
|
||||
status: Done
|
||||
assignee: []
|
||||
created_date: '2025-12-15 23:40'
|
||||
updated_date: '2025-12-15 23:40'
|
||||
labels:
|
||||
- bug-fix
|
||||
- auth
|
||||
- presence
|
||||
dependencies: []
|
||||
priority: high
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
Fixed issues with user identity state not being properly cleared/restored during logout and login cycles, causing duplicate cursors and stale presence data in the social network graph.
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
<!-- AC:BEGIN -->
|
||||
- [x] #1 Crypto keys and tldraw user IDs persist across logout (account data)
|
||||
- [x] #2 Session-specific data cleared on logout (permissions, graph cache)
|
||||
- [x] #3 No duplicate cursors when logging out and back in
|
||||
- [x] #4 Tools load properly after login from logged-out state
|
||||
- [x] #5 CryptIDDropdown and NetworkGraph reset state on logout
|
||||
<!-- AC:END -->
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
<!-- SECTION:NOTES:BEGIN -->
|
||||
Implemented in commits df80a3f and related changes to Board.tsx.
|
||||
|
||||
Key changes:
|
||||
- sessionPersistence.ts: Added session-logged-in and session-cleared events, preserve tldraw user IDs and crypto keys on logout
|
||||
- Board.tsx: Check localStorage directly for auth in onMount, listen for session events
|
||||
- CryptIDDropdown.tsx: Clear connections state on logout
|
||||
- useNetworkGraph.ts: Clear graph cache on logout
|
||||
|
||||
The root cause was clearing tldraw-user-id-* keys on logout, which created new presence IDs on each login while old presence records persisted in Automerge.
|
||||
<!-- SECTION:NOTES:END -->
|
||||
|
|
@ -64,8 +64,6 @@ export interface StandardizedToolWrapperProps {
|
|||
onTagsChange?: (tags: string[]) => void
|
||||
/** Whether tags can be edited */
|
||||
tagsEditable?: boolean
|
||||
/** Zoom level when the shape was pinned (for constant visual size) */
|
||||
pinnedAtZoom?: number
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -92,67 +90,13 @@ export const StandardizedToolWrapper: React.FC<StandardizedToolWrapperProps> = (
|
|||
tags = [],
|
||||
onTagsChange,
|
||||
tagsEditable = true,
|
||||
pinnedAtZoom,
|
||||
}) => {
|
||||
const [isHoveringHeader, setIsHoveringHeader] = useState(false)
|
||||
const [isEditingTags, setIsEditingTags] = useState(false)
|
||||
const [editingTagInput, setEditingTagInput] = useState('')
|
||||
const [zoomScale, setZoomScale] = useState(1)
|
||||
const tagInputRef = useRef<HTMLInputElement>(null)
|
||||
const isDarkMode = useIsDarkMode()
|
||||
|
||||
// Calculate zoom compensation scale when pinned
|
||||
useEffect(() => {
|
||||
if (!isPinnedToView || !editor) {
|
||||
setZoomScale(1)
|
||||
return
|
||||
}
|
||||
|
||||
// Get pinnedAtZoom from shape meta if not passed as prop
|
||||
let originalZoom = pinnedAtZoom
|
||||
if (!originalZoom && shapeId) {
|
||||
const shape = editor.getShape(shapeId)
|
||||
originalZoom = (shape?.meta as any)?.pinnedAtZoom
|
||||
}
|
||||
|
||||
if (!originalZoom) {
|
||||
setZoomScale(1)
|
||||
return
|
||||
}
|
||||
|
||||
const updateScale = () => {
|
||||
const currentZoom = editor.getCamera().z
|
||||
// Scale inversely to zoom to maintain constant visual size
|
||||
const scale = originalZoom / currentZoom
|
||||
setZoomScale(scale)
|
||||
}
|
||||
|
||||
// Initial scale calculation
|
||||
updateScale()
|
||||
|
||||
// Listen for camera changes
|
||||
const handleChange = () => {
|
||||
updateScale()
|
||||
}
|
||||
|
||||
// Use requestAnimationFrame for smooth updates
|
||||
let rafId: number | null = null
|
||||
const throttledUpdate = () => {
|
||||
if (rafId) return
|
||||
rafId = requestAnimationFrame(() => {
|
||||
updateScale()
|
||||
rafId = null
|
||||
})
|
||||
}
|
||||
|
||||
editor.on('change' as any, throttledUpdate)
|
||||
|
||||
return () => {
|
||||
editor.off('change' as any, throttledUpdate)
|
||||
if (rafId) cancelAnimationFrame(rafId)
|
||||
}
|
||||
}, [isPinnedToView, editor, shapeId, pinnedAtZoom])
|
||||
|
||||
// Handle Esc key to exit maximize mode
|
||||
useEffect(() => {
|
||||
if (!isMaximized || !onMaximize) return
|
||||
|
|
@ -229,11 +173,6 @@ export const StandardizedToolWrapper: React.FC<StandardizedToolWrapperProps> = (
|
|||
? `${primaryColor}15` // 15% opacity
|
||||
: `${primaryColor}10` // 10% opacity
|
||||
|
||||
// Calculate transform for pinned shapes
|
||||
const pinnedTransform = isPinnedToView && zoomScale !== 1
|
||||
? `scale(${zoomScale})`
|
||||
: undefined
|
||||
|
||||
const wrapperStyle: React.CSSProperties = {
|
||||
width: typeof width === 'number' ? `${width}px` : width,
|
||||
height: isMinimized ? 40 : (typeof height === 'number' ? `${height}px` : height), // Minimized height is just the header
|
||||
|
|
@ -251,9 +190,6 @@ export const StandardizedToolWrapper: React.FC<StandardizedToolWrapperProps> = (
|
|||
pointerEvents: 'auto',
|
||||
transition: isPinnedToView ? 'box-shadow 0.2s ease' : 'height 0.2s ease, box-shadow 0.2s ease',
|
||||
boxSizing: 'border-box',
|
||||
// Apply zoom compensation transform for pinned shapes
|
||||
transform: pinnedTransform,
|
||||
transformOrigin: 'top left',
|
||||
}
|
||||
|
||||
const headerStyle: React.CSSProperties = {
|
||||
|
|
|
|||
Loading…
Reference in New Issue