Attempt to fix note resizing with React keys and Muuri sync

This commit is contained in:
2026-01-24 19:52:13 +01:00
parent d59ec592eb
commit 8e35780717
48 changed files with 3369 additions and 279 deletions

View File

@@ -86,6 +86,8 @@ interface NoteCardProps {
isDragOver?: boolean
onDragStart?: (noteId: string) => void
onDragEnd?: () => void
onResize?: () => void
onSizeChange?: (newSize: 'small' | 'medium' | 'large') => void
}
// Helper function to get initials from name
@@ -116,7 +118,15 @@ function getAvatarColor(name: string): string {
return colors[hash % colors.length]
}
export function NoteCard({ note, onEdit, isDragging, isDragOver, onDragStart, onDragEnd }: NoteCardProps) {
export function NoteCard({
note,
onEdit,
onDragStart,
onDragEnd,
isDragging,
onResize,
onSizeChange
}: NoteCardProps) {
const router = useRouter()
const searchParams = useSearchParams()
const { refreshLabels } = useLabels()
@@ -138,7 +148,14 @@ export function NoteCard({ note, onEdit, isDragging, isDragOver, onDragStart, on
setShowNotebookMenu(false)
// No need for router.refresh() - triggerRefresh() is already called in moveNoteToNotebookOptimistic
}
const colorClasses = NOTE_COLORS[note.color as NoteColor] || NOTE_COLORS.default
// Optimistic UI state for instant feedback
const [optimisticNote, addOptimisticNote] = useOptimistic(
note,
(state, newProps: Partial<Note>) => ({ ...state, ...newProps })
)
const colorClasses = NOTE_COLORS[optimisticNote.color as NoteColor] || NOTE_COLORS.default
// Check if this note is currently open in the editor
const isNoteOpenInEditor = searchParams.get('note') === note.id
@@ -148,12 +165,6 @@ export function NoteCard({ note, onEdit, isDragging, isDragOver, onDragStart, on
comparisonNotes && comparisonNotes.length > 0 ? comparisonNotes : null
)
// Optimistic UI state for instant feedback
const [optimisticNote, addOptimisticNote] = useOptimistic(
note,
(state, newProps: Partial<Note>) => ({ ...state, ...newProps })
)
const currentUserId = session?.user?.id
const canManageCollaborators = currentUserId && note.userId && currentUserId === note.userId
const isSharedNote = currentUserId && note.userId && currentUserId !== note.userId
@@ -226,10 +237,15 @@ export function NoteCard({ note, onEdit, isDragging, isDragOver, onDragStart, on
}
const handleSizeChange = async (size: 'small' | 'medium' | 'large') => {
startTransition(async () => {
addOptimisticNote({ size })
await updateSize(note.id, size)
})
// Notify parent of size change so it can update its state
onSizeChange?.(size)
// Trigger layout refresh
onResize?.()
setTimeout(() => onResize?.(), 300)
// Update server in background
updateSize(note.id, size)
}
const handleCheckItem = async (checkItemId: string) => {
@@ -267,12 +283,23 @@ export function NoteCard({ note, onEdit, isDragging, isDragOver, onDragStart, on
if (isDeleting) return null
const getMinHeight = (size?: string) => {
switch (size) {
case 'medium': return '200px'
case 'large': return '300px'
default: return '150px' // small
}
}
return (
<Card
data-testid="note-card"
data-draggable="true"
data-note-id={note.id}
data-size={note.size}
data-size={optimisticNote.size}
style={{ minHeight: getMinHeight(optimisticNote.size) }}
draggable={true}
onDragStart={(e) => {
e.dataTransfer.setData('text/plain', note.id)
@@ -560,7 +587,7 @@ export function NoteCard({ note, onEdit, isDragging, isDragOver, onDragStart, on
isPinned={optimisticNote.isPinned}
isArchived={optimisticNote.isArchived}
currentColor={optimisticNote.color}
currentSize={optimisticNote.size}
currentSize={optimisticNote.size as 'small' | 'medium' | 'large'}
onTogglePin={handleTogglePin}
onToggleArchive={handleToggleArchive}
onColorChange={handleColorChange}