fix: remove orphaned debug statements causing build errors

- Remove incomplete console.log cleanup artifacts across 17 files
- Fix orphaned object literals left from previous debug removal
- Prefix unused callback parameters with underscores
- Update Drawfast shape to side-by-side INPUT/OUTPUT layout (900x500)
- Remove unused overlay toggle from Drawfast controls

Files fixed: AutomergeToTLStore, TLStoreToAutomerge, useAutomergeSyncRepo,
FathomMeetingsPanel, NetworkGraphPanel, sessionPersistence, quartzSync,
testClientConfig, useCollaboration, Board, DrawfastShapeUtil,
FathomMeetingsBrowserShapeUtil, MapShapeUtil, FathomMeetingsTool,
HolonTool, overrides, githubSetupValidator

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Jeff Emmett 2025-12-24 19:38:27 -05:00
parent 771840605a
commit 0d6b62d1c7
17 changed files with 145 additions and 418 deletions

View File

@ -442,20 +442,6 @@ export function applyAutomergePatchesToTLStore(
// put / remove the records in the store
// Log patch application for debugging
// DEBUG: Log shape updates being applied to store
toPut.forEach(record => {
if (record.typeName === 'shape' && (record as any).props?.w) {
w: (record as any).props.w,
h: (record as any).props.h,
x: (record as any).x,
y: (record as any).y
})
}
})
if (failedRecords.length > 0) {
}
if (failedRecords.length > 0) {
console.error("Failed to sanitize records:", failedRecords)
}

View File

@ -462,44 +462,6 @@ export function applyTLStoreChangesToAutomerge(
originalX = (record as any).x
originalY = (record as any).y
}
// DEBUG: Log richText, meta.text, and Obsidian note properties before sanitization
if (record.typeName === 'shape') {
if (record.type === 'geo' && (record.props as any)?.richText) {
hasRichText: !!(record.props as any).richText,
richTextType: typeof (record.props as any).richText,
richTextContent: Array.isArray((record.props as any).richText) ? 'array' : (record.props as any).richText?.content ? 'object with content' : 'object without content'
})
}
if (record.type === 'geo' && (record.meta as any)?.text !== undefined) {
hasMetaText: !!(record.meta as any).text,
metaTextValue: (record.meta as any).text,
metaTextType: typeof (record.meta as any).text
})
}
if (record.type === 'note' && (record.props as any)?.richText) {
hasRichText: !!(record.props as any).richText,
richTextType: typeof (record.props as any).richText,
richTextContent: Array.isArray((record.props as any).richText) ? 'array' : (record.props as any).richText?.content ? 'object with content' : 'object without content',
richTextContentLength: Array.isArray((record.props as any).richText?.content) ? (record.props as any).richText.content.length : 'not array'
})
}
if (record.type === 'arrow' && (record.props as any)?.text !== undefined) {
hasText: !!(record.props as any).text,
textValue: (record.props as any).text,
textType: typeof (record.props as any).text
})
}
if (record.type === 'ObsNote') {
hasTitle: !!(record.props as any).title,
hasContent: !!(record.props as any).content,
hasTags: Array.isArray((record.props as any).tags),
title: (record.props as any).title,
contentLength: (record.props as any).content?.length || 0,
tagsCount: Array.isArray((record.props as any).tags) ? (record.props as any).tags.length : 0
})
}
}
const sanitizedRecord = sanitizeRecord(record)
// CRITICAL: Restore original coordinates if they were valid
@ -513,89 +475,11 @@ export function applyTLStoreChangesToAutomerge(
}
}
// DEBUG: Log richText, meta.text, and Obsidian note properties after sanitization
if (sanitizedRecord.typeName === 'shape') {
if (sanitizedRecord.type === 'geo' && (sanitizedRecord.props as any)?.richText) {
hasRichText: !!(sanitizedRecord.props as any).richText,
richTextType: typeof (sanitizedRecord.props as any).richText,
richTextContent: Array.isArray((sanitizedRecord.props as any).richText) ? 'array' : (sanitizedRecord.props as any).richText?.content ? 'object with content' : 'object without content'
})
}
if (sanitizedRecord.type === 'geo' && (sanitizedRecord.meta as any)?.text !== undefined) {
hasMetaText: !!(sanitizedRecord.meta as any).text,
metaTextValue: (sanitizedRecord.meta as any).text,
metaTextType: typeof (sanitizedRecord.meta as any).text
})
}
if (sanitizedRecord.type === 'note' && (sanitizedRecord.props as any)?.richText) {
hasRichText: !!(sanitizedRecord.props as any).richText,
richTextType: typeof (sanitizedRecord.props as any).richText,
richTextContent: Array.isArray((sanitizedRecord.props as any).richText) ? 'array' : (sanitizedRecord.props as any).richText?.content ? 'object with content' : 'object without content',
richTextContentLength: Array.isArray((sanitizedRecord.props as any).richText?.content) ? (sanitizedRecord.props as any).richText.content.length : 'not array'
})
}
if (sanitizedRecord.type === 'arrow' && (sanitizedRecord.props as any)?.text !== undefined) {
hasText: !!(sanitizedRecord.props as any).text,
textValue: (sanitizedRecord.props as any).text,
textType: typeof (sanitizedRecord.props as any).text
})
}
if (sanitizedRecord.type === 'ObsNote') {
hasTitle: !!(sanitizedRecord.props as any).title,
hasContent: !!(sanitizedRecord.props as any).content,
hasTags: Array.isArray((sanitizedRecord.props as any).tags),
title: (sanitizedRecord.props as any).title,
contentLength: (sanitizedRecord.props as any).content?.length || 0,
tagsCount: Array.isArray((sanitizedRecord.props as any).tags) ? (sanitizedRecord.props as any).tags.length : 0
})
}
}
// CRITICAL: Create a deep copy to ensure all properties (including richText and text) are preserved
// This prevents Automerge from treating the object as read-only
// Note: sanitizedRecord.props is already a deep copy from sanitizeRecord, but we need to deep copy the entire record
const recordToSave = JSON.parse(JSON.stringify(sanitizedRecord))
// DEBUG: Log richText, meta.text, and Obsidian note properties after deep copy
if (recordToSave.typeName === 'shape') {
if (recordToSave.type === 'geo' && recordToSave.props?.richText) {
hasRichText: !!recordToSave.props.richText,
richTextType: typeof recordToSave.props.richText,
richTextContent: Array.isArray(recordToSave.props.richText) ? 'array' : recordToSave.props.richText?.content ? 'object with content' : 'object without content',
richTextContentLength: Array.isArray(recordToSave.props.richText?.content) ? recordToSave.props.richText.content.length : 'not array'
})
}
if (recordToSave.type === 'geo' && recordToSave.meta?.text !== undefined) {
hasMetaText: !!recordToSave.meta.text,
metaTextValue: recordToSave.meta.text,
metaTextType: typeof recordToSave.meta.text
})
}
if (recordToSave.type === 'note' && recordToSave.props?.richText) {
hasRichText: !!recordToSave.props.richText,
richTextType: typeof recordToSave.props.richText,
richTextContent: Array.isArray(recordToSave.props.richText) ? 'array' : recordToSave.props.richText?.content ? 'object with content' : 'object without content',
richTextContentLength: Array.isArray(recordToSave.props.richText?.content) ? recordToSave.props.richText.content.length : 'not array'
})
}
if (recordToSave.type === 'arrow' && recordToSave.props?.text !== undefined) {
hasText: !!recordToSave.props.text,
textValue: recordToSave.props.text,
textType: typeof recordToSave.props.text
})
}
if (recordToSave.type === 'ObsNote') {
hasTitle: !!recordToSave.props.title,
hasContent: !!recordToSave.props.content,
hasTags: Array.isArray(recordToSave.props.tags),
title: recordToSave.props.title,
contentLength: recordToSave.props.content?.length || 0,
tagsCount: Array.isArray(recordToSave.props.tags) ? recordToSave.props.tags.length : 0,
allPropsKeys: Object.keys(recordToSave.props || {})
})
}
}
// Replace the entire record - Automerge will handle merging with concurrent changes
doc.store[record.id] = recordToSave
})

View File

@ -158,19 +158,6 @@ export function useAutomergeSync(config: AutomergeSyncConfig): TLStoreWithStatus
const deletedRecordIds = data.deleted || []
const deletedShapes = deletedRecordIds.filter(id => id.startsWith('shape:'))
// Log incoming sync data for debugging
if (shapeRecords.length > 0) {
shapeRecords.forEach((shape: any) => {
x: shape.x,
y: shape.y,
w: shape.props?.w,
h: shape.props?.h
})
})
}
if (deletedShapes.length > 0) {
}
// Apply changes to the Automerge document
// This will trigger patches which will update the TLDraw store
// NOTE: We do NOT increment pendingLocalChanges here because these are REMOTE changes
@ -621,17 +608,6 @@ export function useAutomergeSync(config: AutomergeSyncConfig): TLStoreWithStatus
return
}
// Log significant changes for debugging
const shapePatches = payload.patches.filter((p: any) => {
const id = p.path?.[1]
return id && typeof id === 'string' && id.startsWith('shape:')
})
if (shapePatches.length > 0) {
patchCount: patchCount,
shapePatches: shapePatches.length
})
}
}
handle.on('change', changeHandler)

View File

@ -149,12 +149,6 @@ export function FathomMeetingsPanel({ onClose, onMeetingSelect, shapeMode = fals
// Handler for individual data type buttons - creates shapes directly
const handleDataButtonClick = async (meeting: FathomMeeting, dataType: 'summary' | 'transcript' | 'actionItems' | 'video') => {
// Log to verify the correct meeting is being used
recording_id: meeting.recording_id,
title: meeting.title,
dataType
})
if (!onMeetingSelect) {
// Fallback for non-browser mode
const options = {

View File

@ -296,7 +296,7 @@ export function NetworkGraphPanel({ onExpand }: NetworkGraphPanelProps) {
}, [disconnect]);
// Handle node click
const handleNodeClick = useCallback((node: any) => {
const handleNodeClick = useCallback((_node: any) => {
// Could open a profile modal or navigate to user
}, []);

View File

@ -59,10 +59,6 @@ export const loadSession = (): StoredSession | null => {
}
const parsed = JSON.parse(stored) as StoredSession;
username: parsed.username,
authed: parsed.authed,
timestamp: new Date(parsed.timestamp).toISOString()
});
// Check if session is not too old (7 days)
const maxAge = 7 * 24 * 60 * 60 * 1000; // 7 days in milliseconds

View File

@ -102,20 +102,4 @@ export function logGitHubSetupStatus(): void {
const status = validateGitHubSetup()
if (status.isValid) {
} else {
status.issues.forEach(issue => {})
}
if (status.warnings.length > 0) {
status.warnings.forEach(warning => {})
}
if (status.suggestions.length > 0) {
status.suggestions.forEach(suggestion => {})
}
if (!status.isValid) {
getGitHubSetupInstructions().forEach(instruction => {})
}
}

View File

@ -40,13 +40,7 @@ export class QuartzSync {
try {
const { githubToken, githubRepo } = this.config
const [owner, repo] = githubRepo.split('/')
owner,
repo,
noteTitle: note.title,
noteFilePath: note.filePath
})
// Get the current file content to check if it exists
const filePath = `content/${note.filePath}`
let sha: string | undefined
@ -225,13 +219,6 @@ ${note.content}`
* Prioritizes GitHub integration for Quartz sites
*/
async smartSync(note: QuartzNote): Promise<boolean> {
hasGitHubToken: !!this.config.githubToken,
hasGitHubRepo: !!this.config.githubRepo,
hasCloudflareApiKey: !!this.config.cloudflareApiKey,
hasCloudflareAccountId: !!this.config.cloudflareAccountId,
hasQuartzUrl: !!this.config.quartzUrl
})
// Check if GitHub integration is available and preferred
if (this.config.githubToken && this.config.githubRepo) {
try {
@ -241,12 +228,7 @@ ${note.content}`
}
} catch (error) {
console.warn('⚠️ GitHub sync failed, trying other methods:', error)
console.warn('⚠️ GitHub sync error details:', {
message: error instanceof Error ? error.message : 'Unknown error',
stack: error instanceof Error ? error.stack : 'No stack trace'
})
}
} else {
}
// Fallback to other methods

View File

@ -6,18 +6,10 @@
import { getClientConfig, isGitHubConfigured, getGitHubConfig } from './clientConfig'
export function testClientConfig() {
const config = getClientConfig()
hasGithubToken: !!config.githubToken,
hasQuartzRepo: !!config.quartzRepo,
githubTokenLength: config.githubToken?.length || 0,
quartzRepo: config.quartzRepo
})
const isConfigured = isGitHubConfigured()
const githubConfig = getGitHubConfig()
return {
config,
isConfigured,

View File

@ -74,13 +74,13 @@ export function useCollaboration({
};
}, [sessionId, serverUrl]);
const createSession = useCallback(async (name: string): Promise<string> => {
const createSession = useCallback(async (_name: string): Promise<string> => {
// TODO: Create new Y.js document and return session ID
const newSessionId = `session-${Date.now()}`;
return newSessionId;
}, []);
const joinSession = useCallback(async (sessionIdToJoin: string): Promise<void> => {
const joinSession = useCallback(async (_sessionIdToJoin: string): Promise<void> => {
// TODO: Join existing Y.js session
}, []);
@ -96,15 +96,15 @@ export function useCollaboration({
// awareness.setLocalStateField('cursor', coordinate);
}, []);
const broadcastRouteChange = useCallback((route: Route) => {
const broadcastRouteChange = useCallback((_route: Route) => {
// TODO: Update Y.js shared route array
}, []);
const broadcastWaypointChange = useCallback((waypoint: Waypoint) => {
const broadcastWaypointChange = useCallback((_waypoint: Waypoint) => {
// TODO: Update Y.js shared waypoint array
}, []);
const broadcastLayerChange = useCallback((layer: MapLayer) => {
const broadcastLayerChange = useCallback((_layer: MapLayer) => {
// TODO: Update Y.js shared layer array
}, []);

View File

@ -376,25 +376,6 @@ export function Board() {
? false // Don't restrict while loading/transitioning - assume can edit
: permission === 'view' // Only restrict if explicitly view (protected board)
// Debug logging for permission issues
permission,
permissionLoading,
sessionAuthed: session.authed,
sessionLoading: session.loading,
sessionUsername: session.username,
authJustChanged,
isReadOnly,
reason: session.loading
? 'auth loading - allowing edit temporarily'
: authJustChanged
? 'auth just changed - allowing edit until effects run'
: permissionLoading
? 'permission loading - allowing edit temporarily'
: permission === 'view'
? 'protected board - user not an editor (view-only)'
: 'open board or user is editor (can edit)'
})
// Handler for when user tries to edit in read-only mode
const handleEditAttempt = () => {
if (isReadOnly) {
@ -681,29 +662,6 @@ export function Board() {
// Debug: Log page information
const allPages = store.store.allRecords().filter((r: any) => r.typeName === 'page')
// CRITICAL DEBUG: Check if shapes exist in editor but aren't returned by getCurrentPageShapes
if (storeShapesOnCurrentPage.length > 0 && editorShapes.length === 0) {
const sampleShape = storeShapesOnCurrentPage[0]
const shapeInEditor = editor.getShape(sampleShape.id as TLShapeId)
if (shapeInEditor) {
id: shapeInEditor.id,
type: shapeInEditor.type,
parentId: shapeInEditor.parentId,
pageId: editor.getCurrentPageId(),
matches: shapeInEditor.parentId === editor.getCurrentPageId()
})
}
}
// Debug: Log shape parent IDs to see if there's a mismatch
if (storeShapes.length > 0 && editorShapes.length === 0) {
const parentIdCounts = new Map<string, number>()
storeShapes.forEach((s: any) => {
const pid = s.parentId || 'no-parent'
parentIdCounts.set(pid, (parentIdCounts.get(pid) || 0) + 1)
})
}
// REMOVED: Aggressive force refresh that was causing coordinate loss
// If shapes are in store but editor doesn't see them, it's likely a different issue
// Forcing refresh by re-putting was resetting coordinates to 0,0
@ -929,11 +887,6 @@ export function Board() {
} catch (error) {
console.error(`❌ Board: Error switching to page ${pageWithMostShapes}:`, error)
}
} else if (pageWithMostShapes) {
pageId,
shapeCount: count,
isCurrent: pageId === currentPageId
})))
}
}
}
@ -1428,8 +1381,6 @@ export function Board() {
const isAuthenticated = checkAuthFromStorage();
const initialReadOnly = !isAuthenticated;
editor.updateInstanceState({ isReadonly: initialReadOnly })
? '🔒 Board is in read-only mode (not authenticated)'
: '🔓 Board is editable (authenticated)')
// Also ensure the current tool is appropriate for the mode
if (!initialReadOnly) {

View File

@ -35,8 +35,8 @@ export class DrawfastShape extends BaseBoxShapeUtil<IDrawfastShape> {
getDefaultProps(): IDrawfastShape["props"] {
return {
w: 512,
h: 512,
w: 900,
h: 500,
prompt: "",
generatedImageUrl: null,
overlayMode: true,
@ -160,16 +160,6 @@ export class DrawfastShape extends BaseBoxShapeUtil<IDrawfastShape> {
})
}
const handleToggleOverlay = () => {
editor.updateShape<IDrawfastShape>({
id: shape.id,
type: 'Drawfast',
props: {
overlayMode: !shape.props.overlayMode,
},
})
}
const handleToggleAutoGenerate = () => {
editor.updateShape<IDrawfastShape>({
id: shape.id,
@ -361,107 +351,151 @@ export class DrawfastShape extends BaseBoxShapeUtil<IDrawfastShape> {
backgroundColor: '#1a1a2e',
overflow: 'hidden',
}}>
{/* Drawing Area / Result Display */}
{/* Main content area - INPUT and OUTPUT side by side */}
<div style={{
flex: 1,
position: 'relative',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#fff',
flexDirection: 'row',
overflow: 'hidden',
}}>
{/* Generated Image (if available and overlay mode) */}
{shape.props.generatedImageUrl && shape.props.overlayMode && (
<img
src={shape.props.generatedImageUrl}
alt="AI Generated"
style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
objectFit: 'contain',
pointerEvents: 'none',
opacity: 0.9,
zIndex: 10,
}}
/>
)}
{/* Instructions when empty */}
{!shape.props.generatedImageUrl && (
{/* INPUT - Drawing Area (Left Side) */}
<div style={{
flex: 1,
position: 'relative',
display: 'flex',
flexDirection: 'column',
backgroundColor: '#fff',
overflow: 'hidden',
borderRight: '2px solid #333',
}}>
{/* INPUT Label */}
<div style={{
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
textAlign: 'center',
color: '#666',
fontSize: '14px',
padding: '20px',
pointerEvents: 'none',
zIndex: 5,
padding: '4px 8px',
backgroundColor: '#2a2a3e',
color: '#888',
fontSize: '10px',
fontWeight: 600,
textTransform: 'uppercase',
letterSpacing: '0.5px',
borderBottom: '1px solid #333',
}}>
<div style={{ fontSize: '32px', marginBottom: '8px' }}></div>
<div>Draw inside this frame</div>
<div style={{ fontSize: '12px', marginTop: '4px', color: '#999' }}>
Use the pencil, pen, or other tools to sketch
</div>
📝 Input (Draw Here)
</div>
)}
{/* Loading indicator */}
{(shape.props.isGenerating || liveImageState.isGenerating) && (
{/* Drawing canvas area */}
<div style={{
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
zIndex: 20,
backgroundColor: 'rgba(0,0,0,0.7)',
padding: '16px 24px',
borderRadius: '8px',
color: 'white',
flex: 1,
position: 'relative',
display: 'flex',
alignItems: 'center',
gap: '12px',
justifyContent: 'center',
}}>
{/* Instructions when empty */}
<div style={{
width: 24,
height: 24,
border: '3px solid rgba(255,255,255,0.3)',
borderTopColor: DrawfastShape.PRIMARY_COLOR,
borderRadius: '50%',
animation: 'spin 1s linear infinite',
}} />
Generating...
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
textAlign: 'center',
color: '#666',
fontSize: '14px',
padding: '20px',
pointerEvents: 'none',
zIndex: 5,
}}>
<div style={{ fontSize: '32px', marginBottom: '8px' }}></div>
<div>Draw inside this frame</div>
<div style={{ fontSize: '12px', marginTop: '4px', color: '#999' }}>
Use the pencil, pen, or other tools to sketch
</div>
</div>
</div>
)}
</div>
{/* Side-by-side result (when not overlay mode) */}
{shape.props.generatedImageUrl && !shape.props.overlayMode && (
<div style={{
height: '40%',
borderTop: '2px solid #333',
backgroundColor: '#111',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}>
<img
src={shape.props.generatedImageUrl}
alt="AI Generated"
style={{
maxWidth: '100%',
maxHeight: '100%',
objectFit: 'contain',
}}
/>
</div>
)}
{/* OUTPUT - Generated Image (Right Side) */}
<div style={{
flex: 1,
position: 'relative',
display: 'flex',
flexDirection: 'column',
backgroundColor: '#111',
overflow: 'hidden',
}}>
{/* OUTPUT Label */}
<div style={{
padding: '4px 8px',
backgroundColor: '#2a2a3e',
color: '#888',
fontSize: '10px',
fontWeight: 600,
textTransform: 'uppercase',
letterSpacing: '0.5px',
borderBottom: '1px solid #333',
}}>
Output (AI Generated)
</div>
{/* Output content area */}
<div style={{
flex: 1,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
position: 'relative',
}}>
{/* Generated Image */}
{shape.props.generatedImageUrl ? (
<img
src={shape.props.generatedImageUrl}
alt="AI Generated"
style={{
maxWidth: '100%',
maxHeight: '100%',
objectFit: 'contain',
}}
/>
) : (
<div style={{
textAlign: 'center',
color: '#555',
fontSize: '12px',
padding: '20px',
}}>
<div style={{ fontSize: '24px', marginBottom: '8px', opacity: 0.5 }}>🖼</div>
<div>Generated image will appear here</div>
</div>
)}
{/* Loading indicator */}
{(shape.props.isGenerating || liveImageState.isGenerating) && (
<div style={{
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
zIndex: 20,
backgroundColor: 'rgba(0,0,0,0.8)',
padding: '16px 24px',
borderRadius: '8px',
color: 'white',
display: 'flex',
alignItems: 'center',
gap: '12px',
}}>
<div style={{
width: 24,
height: 24,
border: '3px solid rgba(255,255,255,0.3)',
borderTopColor: DrawfastShape.PRIMARY_COLOR,
borderRadius: '50%',
animation: 'spin 1s linear infinite',
}} />
Generating...
</div>
)}
</div>
</div>
</div>
{/* Controls */}
<div style={{
@ -597,23 +631,6 @@ export class DrawfastShape extends BaseBoxShapeUtil<IDrawfastShape> {
/>
Real-time
</label>
{/* Overlay toggle */}
<button
onClick={handleToggleOverlay}
onPointerDown={(e) => e.stopPropagation()}
style={{
padding: '4px 8px',
borderRadius: '4px',
border: '1px solid #444',
backgroundColor: shape.props.overlayMode ? DrawfastShape.PRIMARY_COLOR : '#2a2a3e',
color: '#fff',
fontSize: '10px',
cursor: 'pointer',
}}
>
{shape.props.overlayMode ? 'Overlay' : 'Side-by-side'}
</button>
</div>
</div>
</div>

View File

@ -106,13 +106,6 @@ export class FathomMeetingsBrowserShape extends BaseBoxShapeUtil<IFathomMeetings
return
}
// Log to verify the correct meeting is being received
recording_id: meetingRecordingId,
title: meetingTitle,
options,
fullMeetingObject: meeting
})
// Get API key from user identity
const apiKey = getFathomApiKey(session.username)
if (!apiKey) {

View File

@ -656,14 +656,6 @@ function MapComponent({ shape, editor, isSelected }: { shape: IMapShape; editor:
);
const currentCollaboratorIds = new Set(collaboratorsWithLocation.map((c: CollaboratorPresence) => c.id));
// Debug logging
if (collaboratorsWithLocation.length > 0) {
total: allCollaborators.length,
withLocation: collaboratorsWithLocation.length,
users: collaboratorsWithLocation.map(c => ({ id: c.id.slice(0, 8), name: c.name, loc: c.location })),
});
}
// Remove old collaborator markers that are no longer sharing
collaboratorMarkersRef.current.forEach((marker, id) => {
if (!currentCollaboratorIds.has(id)) {

View File

@ -231,12 +231,7 @@ export class FathomMeetingsIdle extends StateNode {
// This ensures the shape appears exactly where the user clicked
const finalX = baseX
const finalY = baseY
clickPosition: { x: clickX, y: clickY },
shapePosition: { x: finalX, y: finalY },
shapeSize: { w: shapeWidth, h: shapeHeight }
})
const browserShape = this.editor.createShape({
type: 'FathomMeetingsBrowser',
x: finalX,

View File

@ -179,24 +179,9 @@ export class HolonIdle extends StateNode {
// ALWAYS use click position directly when provided - user clicked where they want it
// Skip collision detection entirely for user clicks to ensure it appears exactly where clicked
let finalX = baseX
let finalY = baseY
if (clickX !== undefined && clickY !== undefined) {
// User clicked - ALWAYS use that exact position, no collision detection
// This ensures the shape appears exactly where the user clicked
finalX = baseX
finalY = baseY
clickPosition: { x: clickX, y: clickY },
shapePosition: { x: finalX, y: finalY },
shapeSize: { w: shapeWidth, h: shapeHeight }
})
} else {
// For fallback (no click), use base position directly
finalX = baseX
finalY = baseY
}
const finalX = baseX
const finalY = baseY
// Default coordinates (can be changed by user)
const defaultLat = 40.7128 // NYC
const defaultLng = -74.0060

View File

@ -480,7 +480,7 @@ export const overrides: TLUiOverrides = {
onSelect: async () => {
try {
// Create a simple modal/prompt for AI response
const answer = await askCanvasAI(editor, undefined, (partial, done) => {
const answer = await askCanvasAI(editor, undefined, (_partial, done) => {
// Log streaming response to console for now
if (!done) {
}
@ -500,7 +500,7 @@ export const overrides: TLUiOverrides = {
readonlyOk: true,
onSelect: async () => {
try {
await indexCanvasForSearch(editor, (progress) => {
await indexCanvasForSearch(editor, (_progress) => {
})
} catch (error) {
console.error("Canvas indexing error:", error)
@ -514,7 +514,7 @@ export const overrides: TLUiOverrides = {
readonlyOk: true,
onSelect: async () => {
try {
await explainViewport(editor, (partial, done) => {
await explainViewport(editor, (_partial, done) => {
if (!done) {
}
})