preserve coordinates
This commit is contained in:
parent
7b15c9af4a
commit
0bea258d39
|
|
@ -360,9 +360,15 @@ export function sanitizeRecord(record: any): TLRecord {
|
||||||
// For shapes, only ensure basic required fields exist
|
// For shapes, only ensure basic required fields exist
|
||||||
if (sanitized.typeName === 'shape') {
|
if (sanitized.typeName === 'shape') {
|
||||||
// Ensure required shape fields exist
|
// Ensure required shape fields exist
|
||||||
// CRITICAL: Check for non-number, null, undefined, or NaN values
|
// CRITICAL: Only set defaults if coordinates are truly missing or invalid
|
||||||
if (typeof sanitized.x !== 'number' || sanitized.x === null || isNaN(sanitized.x)) sanitized.x = 0
|
// DO NOT overwrite valid coordinates (including 0, which is a valid position)
|
||||||
if (typeof sanitized.y !== 'number' || sanitized.y === null || isNaN(sanitized.y)) sanitized.y = 0
|
// Only set to 0 if the value is undefined, null, or NaN
|
||||||
|
if (sanitized.x === undefined || sanitized.x === null || (typeof sanitized.x === 'number' && isNaN(sanitized.x))) {
|
||||||
|
sanitized.x = 0
|
||||||
|
}
|
||||||
|
if (sanitized.y === undefined || sanitized.y === null || (typeof sanitized.y === 'number' && isNaN(sanitized.y))) {
|
||||||
|
sanitized.y = 0
|
||||||
|
}
|
||||||
if (typeof sanitized.rotation !== 'number') sanitized.rotation = 0
|
if (typeof sanitized.rotation !== 'number') sanitized.rotation = 0
|
||||||
if (typeof sanitized.isLocked !== 'boolean') sanitized.isLocked = false
|
if (typeof sanitized.isLocked !== 'boolean') sanitized.isLocked = false
|
||||||
if (typeof sanitized.opacity !== 'number') sanitized.opacity = 1
|
if (typeof sanitized.opacity !== 'number') sanitized.opacity = 1
|
||||||
|
|
|
||||||
|
|
@ -368,45 +368,9 @@ export function useAutomergeStoreV2({
|
||||||
if (existingStoreShapes.length > 0) {
|
if (existingStoreShapes.length > 0) {
|
||||||
console.log(`✅ Store already populated from patches (${existingStoreShapes.length} shapes) - using patch-based loading like dev`)
|
console.log(`✅ Store already populated from patches (${existingStoreShapes.length} shapes) - using patch-based loading like dev`)
|
||||||
|
|
||||||
// CRITICAL: Force editor to see shapes by refreshing them multiple times
|
// REMOVED: Aggressive shape refresh that was causing coordinate loss
|
||||||
// Sometimes the editor needs multiple updates to detect shapes
|
// Shapes should be visible through normal patch application
|
||||||
const refreshShapes = (attempt: number) => {
|
// If shapes aren't visible, it's likely a different issue that refresh won't fix
|
||||||
// CRITICAL: Preserve x and y coordinates when refreshing shapes
|
|
||||||
const shapesToRefresh = existingStoreShapes.map(s => {
|
|
||||||
const shapeFromStore = store.get(s.id)
|
|
||||||
if (shapeFromStore && shapeFromStore.typeName === 'shape') {
|
|
||||||
// Preserve original x and y from the store shape data
|
|
||||||
// Type assertion needed because s is TLRecord but we know it's a shape
|
|
||||||
const sAny = s as any
|
|
||||||
const shapeFromStoreAny = shapeFromStore as any
|
|
||||||
const originalX = sAny.x !== undefined && typeof sAny.x === 'number' && !isNaN(sAny.x) ? sAny.x : shapeFromStoreAny.x
|
|
||||||
const originalY = sAny.y !== undefined && typeof sAny.y === 'number' && !isNaN(sAny.y) ? sAny.y : shapeFromStoreAny.y
|
|
||||||
|
|
||||||
// Ensure x and y are preserved
|
|
||||||
if (typeof originalX === 'number' && !isNaN(originalX) && typeof originalY === 'number' && !isNaN(originalY)) {
|
|
||||||
return { ...shapeFromStore, x: originalX, y: originalY } as TLRecord
|
|
||||||
}
|
|
||||||
return shapeFromStore
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}).filter((s): s is TLRecord => s !== null && s.typeName === 'shape')
|
|
||||||
|
|
||||||
if (shapesToRefresh.length > 0) {
|
|
||||||
store.mergeRemoteChanges(() => {
|
|
||||||
// Re-put shapes to trigger editor update
|
|
||||||
store.put(shapesToRefresh)
|
|
||||||
})
|
|
||||||
console.log(`📊 Refreshed ${shapesToRefresh.length} existing shapes (attempt ${attempt}) to ensure editor visibility`)
|
|
||||||
|
|
||||||
// Try multiple times to ensure editor picks them up
|
|
||||||
if (attempt < 3) {
|
|
||||||
setTimeout(() => refreshShapes(attempt + 1), 200)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start refreshing after a short delay
|
|
||||||
setTimeout(() => refreshShapes(1), 100)
|
|
||||||
|
|
||||||
setStoreWithStatus({
|
setStoreWithStatus({
|
||||||
store,
|
store,
|
||||||
|
|
@ -435,45 +399,8 @@ export function useAutomergeStoreV2({
|
||||||
if (currentShapes.length > 0) {
|
if (currentShapes.length > 0) {
|
||||||
console.log(`✅ Patches applied successfully: ${currentShapes.length} shapes loaded via patches`)
|
console.log(`✅ Patches applied successfully: ${currentShapes.length} shapes loaded via patches`)
|
||||||
|
|
||||||
// CRITICAL: Force editor to see shapes by refreshing them multiple times
|
// REMOVED: Aggressive shape refresh that was causing coordinate loss
|
||||||
// Sometimes the editor needs multiple updates to detect shapes
|
// Shapes loaded via patches should be visible without forced refresh
|
||||||
const refreshShapes = (attempt: number) => {
|
|
||||||
// CRITICAL: Preserve x and y coordinates when refreshing shapes
|
|
||||||
const shapesToRefresh = currentShapes.map(s => {
|
|
||||||
const shapeFromStore = store.get(s.id)
|
|
||||||
if (shapeFromStore && shapeFromStore.typeName === 'shape') {
|
|
||||||
// Preserve original x and y from the store shape data
|
|
||||||
// Type assertion needed because s is TLRecord but we know it's a shape
|
|
||||||
const sAny = s as any
|
|
||||||
const shapeFromStoreAny = shapeFromStore as any
|
|
||||||
const originalX = sAny.x !== undefined && typeof sAny.x === 'number' && !isNaN(sAny.x) ? sAny.x : shapeFromStoreAny.x
|
|
||||||
const originalY = sAny.y !== undefined && typeof sAny.y === 'number' && !isNaN(sAny.y) ? sAny.y : shapeFromStoreAny.y
|
|
||||||
|
|
||||||
// Ensure x and y are preserved
|
|
||||||
if (typeof originalX === 'number' && !isNaN(originalX) && typeof originalY === 'number' && !isNaN(originalY)) {
|
|
||||||
return { ...shapeFromStore, x: originalX, y: originalY } as TLRecord
|
|
||||||
}
|
|
||||||
return shapeFromStore
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}).filter((s): s is TLRecord => s !== null && s.typeName === 'shape')
|
|
||||||
|
|
||||||
if (shapesToRefresh.length > 0) {
|
|
||||||
store.mergeRemoteChanges(() => {
|
|
||||||
// Re-put shapes to trigger editor update
|
|
||||||
store.put(shapesToRefresh)
|
|
||||||
})
|
|
||||||
console.log(`📊 Refreshed ${shapesToRefresh.length} shapes (attempt ${attempt}) to ensure editor visibility`)
|
|
||||||
|
|
||||||
// Try multiple times to ensure editor picks them up
|
|
||||||
if (attempt < 3) {
|
|
||||||
setTimeout(() => refreshShapes(attempt + 1), 200)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start refreshing after a short delay
|
|
||||||
setTimeout(() => refreshShapes(1), 100)
|
|
||||||
|
|
||||||
setStoreWithStatus({
|
setStoreWithStatus({
|
||||||
store,
|
store,
|
||||||
|
|
@ -534,46 +461,8 @@ export function useAutomergeStoreV2({
|
||||||
})
|
})
|
||||||
console.log(`✅ Applied ${allRecords.length} records directly to store (fallback for missed patches - works in dev and production)`)
|
console.log(`✅ Applied ${allRecords.length} records directly to store (fallback for missed patches - works in dev and production)`)
|
||||||
|
|
||||||
// CRITICAL: Force editor to see shapes by refreshing them multiple times
|
// REMOVED: Aggressive shape refresh that was causing coordinate loss
|
||||||
// Sometimes the editor needs multiple updates to detect shapes
|
// Shapes loaded directly should be visible without forced refresh
|
||||||
const refreshShapes = (attempt: number) => {
|
|
||||||
const shapes = store.allRecords().filter((r: any) => r.typeName === 'shape')
|
|
||||||
// CRITICAL: Preserve x and y coordinates when refreshing shapes
|
|
||||||
const shapesToRefresh = shapes.map(s => {
|
|
||||||
const shapeFromStore = store.get(s.id)
|
|
||||||
if (shapeFromStore && shapeFromStore.typeName === 'shape') {
|
|
||||||
// Preserve original x and y from the store shape data
|
|
||||||
// Type assertion needed because s is TLRecord but we know it's a shape
|
|
||||||
const sAny = s as any
|
|
||||||
const shapeFromStoreAny = shapeFromStore as any
|
|
||||||
const originalX = sAny.x !== undefined && typeof sAny.x === 'number' && !isNaN(sAny.x) ? sAny.x : shapeFromStoreAny.x
|
|
||||||
const originalY = sAny.y !== undefined && typeof sAny.y === 'number' && !isNaN(sAny.y) ? sAny.y : shapeFromStoreAny.y
|
|
||||||
|
|
||||||
// Ensure x and y are preserved
|
|
||||||
if (typeof originalX === 'number' && !isNaN(originalX) && typeof originalY === 'number' && !isNaN(originalY)) {
|
|
||||||
return { ...shapeFromStore, x: originalX, y: originalY } as TLRecord
|
|
||||||
}
|
|
||||||
return shapeFromStore
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}).filter((s): s is TLRecord => s !== null && s.typeName === 'shape')
|
|
||||||
|
|
||||||
if (shapesToRefresh.length > 0) {
|
|
||||||
store.mergeRemoteChanges(() => {
|
|
||||||
// Re-put shapes to trigger editor update
|
|
||||||
store.put(shapesToRefresh)
|
|
||||||
})
|
|
||||||
console.log(`📊 Refreshed ${shapesToRefresh.length} shapes (attempt ${attempt}) to ensure editor visibility`)
|
|
||||||
|
|
||||||
// Try multiple times to ensure editor picks them up
|
|
||||||
if (attempt < 3) {
|
|
||||||
setTimeout(() => refreshShapes(attempt + 1), 200)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start refreshing after a short delay
|
|
||||||
setTimeout(() => refreshShapes(1), 100)
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`❌ Error applying records directly:`, error)
|
console.error(`❌ Error applying records directly:`, error)
|
||||||
|
|
|
||||||
|
|
@ -282,34 +282,12 @@ export function Board() {
|
||||||
console.log(`📊 Board: Shape parent ID distribution:`, Array.from(parentIdCounts.entries()))
|
console.log(`📊 Board: Shape parent ID distribution:`, Array.from(parentIdCounts.entries()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// CRITICAL: If shapes are in store but editor sees 0, force refresh
|
// REMOVED: Aggressive force refresh that was causing coordinate loss
|
||||||
// This handles the case where old bulk loading code doesn't refresh shapes
|
// If shapes are in store but editor doesn't see them, it's likely a different issue
|
||||||
if (storeShapes.length > 0 && editorShapes.length === 0 && storeShapesOnCurrentPage.length > 0 && store.store) {
|
// Forcing refresh by re-putting was resetting coordinates to 0,0
|
||||||
console.warn(`⚠️ Board: ${storeShapes.length} shapes in store (${storeShapesOnCurrentPage.length} on current page) but editor sees 0. Forcing refresh...`)
|
if (storeShapes.length > 0 && editorShapes.length === 0 && storeShapesOnCurrentPage.length > 0) {
|
||||||
|
console.warn(`⚠️ Board: ${storeShapes.length} shapes in store (${storeShapesOnCurrentPage.length} on current page) but editor sees 0. This may indicate a sync issue.`)
|
||||||
// Force refresh by re-putting shapes with mergeRemoteChanges
|
// Don't force refresh - it was causing coordinate loss
|
||||||
// CRITICAL: Preserve x and y coordinates when refreshing shapes
|
|
||||||
const shapesToRefresh = storeShapesOnCurrentPage.map((s: any) => {
|
|
||||||
const shapeFromStore = store.store!.get(s.id)
|
|
||||||
if (shapeFromStore && shapeFromStore.typeName === 'shape') {
|
|
||||||
// Preserve original x and y from the store shape data
|
|
||||||
const originalX = s.x !== undefined && typeof s.x === 'number' && !isNaN(s.x) ? s.x : (shapeFromStore as any).x
|
|
||||||
const originalY = s.y !== undefined && typeof s.y === 'number' && !isNaN(s.y) ? s.y : (shapeFromStore as any).y
|
|
||||||
|
|
||||||
// Ensure x and y are preserved
|
|
||||||
if (typeof originalX === 'number' && !isNaN(originalX) && typeof originalY === 'number' && !isNaN(originalY)) {
|
|
||||||
return { ...shapeFromStore, x: originalX, y: originalY } as TLRecord
|
|
||||||
}
|
|
||||||
return shapeFromStore
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}).filter((s): s is TLRecord => s !== null && s.typeName === 'shape')
|
|
||||||
if (shapesToRefresh.length > 0) {
|
|
||||||
store.store.mergeRemoteChanges(() => {
|
|
||||||
store.store!.put(shapesToRefresh)
|
|
||||||
})
|
|
||||||
console.log(`🔄 Board: Forced refresh of ${shapesToRefresh.length} shapes to make editor see them`)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if there are shapes in store on current page that editor can't see
|
// Check if there are shapes in store on current page that editor can't see
|
||||||
|
|
@ -343,39 +321,9 @@ export function Board() {
|
||||||
// Shapes don't exist in editor - might be a sync issue
|
// Shapes don't exist in editor - might be a sync issue
|
||||||
console.error(`📊 Board: ${missingShapes.length} shapes are in store but don't exist in editor - possible sync issue`)
|
console.error(`📊 Board: ${missingShapes.length} shapes are in store but don't exist in editor - possible sync issue`)
|
||||||
|
|
||||||
// Try to force a refresh by updating the store
|
// REMOVED: Force refresh that was causing coordinate loss
|
||||||
// This might help if shapes are stuck in a validation error state
|
// Re-putting shapes was resetting coordinates to 0,0
|
||||||
console.log(`📊 Board: Attempting to refresh store to make shapes visible`)
|
console.log(`📊 Board: ${missingShapes.length} shapes are in store but not visible in editor - this may indicate a sync issue`)
|
||||||
try {
|
|
||||||
// Force a store update by reading and re-putting the shapes
|
|
||||||
if (!store.store) return
|
|
||||||
|
|
||||||
const currentStore = store.store
|
|
||||||
const shapesToRefresh = missingShapes.slice(0, 10) // Limit to first 10 to avoid performance issues
|
|
||||||
// CRITICAL: Preserve x and y coordinates when refreshing shapes
|
|
||||||
const refreshedShapes = shapesToRefresh.map((s: any) => {
|
|
||||||
const shapeFromStore = currentStore.get(s.id)
|
|
||||||
if (shapeFromStore && shapeFromStore.typeName === 'shape') {
|
|
||||||
// Preserve original x and y from the store shape data
|
|
||||||
const originalX = s.x !== undefined && typeof s.x === 'number' && !isNaN(s.x) ? s.x : (shapeFromStore as any).x
|
|
||||||
const originalY = s.y !== undefined && typeof s.y === 'number' && !isNaN(s.y) ? s.y : (shapeFromStore as any).y
|
|
||||||
|
|
||||||
// Ensure x and y are preserved
|
|
||||||
if (typeof originalX === 'number' && !isNaN(originalX) && typeof originalY === 'number' && !isNaN(originalY)) {
|
|
||||||
return { ...shapeFromStore, x: originalX, y: originalY } as TLRecord
|
|
||||||
}
|
|
||||||
return shapeFromStore
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}).filter((s): s is TLRecord => s !== null && s.typeName === 'shape')
|
|
||||||
|
|
||||||
if (refreshedShapes.length > 0) {
|
|
||||||
console.log(`📊 Board: Refreshing ${refreshedShapes.length} shapes in store`)
|
|
||||||
currentStore.put(refreshedShapes)
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error(`📊 Board: Error refreshing shapes:`, error)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if shapes are outside viewport
|
// Check if shapes are outside viewport
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue