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:
parent
771840605a
commit
0d6b62d1c7
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
})
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}, []);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 => {})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}, []);
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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)) {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
}
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in New Issue