@@ -39,7 +39,9 @@ import { useSessionSharing } from '../hooks/useSessionSharing';
3939import SessionSharing from './collaborative/SessionSharing' ;
4040import { CollaborativeButton } from './collaborative' ;
4141import EnhancedMentionPopover from './EnhancedMentionPopover' ;
42+ import { useMatrix } from '../contexts/MatrixContext' ;
4243
44+ // Force rebuild timestamp: 2025-01-15T01:00:00Z - All .length errors fixed
4345
4446interface QueuedMessage {
4547 id : string ;
@@ -352,54 +354,66 @@ export default function ChatInput({
352354 const [ isAddCommandModalOpen , setIsAddCommandModalOpen ] = useState ( false ) ;
353355 const [ customCommands , setCustomCommands ] = useState < CustomCommand [ ] > ( [ ] ) ;
354356
355- // Check if we're in Matrix mode by looking at URL parameters
356- const isInMatrixMode = window . location . search . includes ( 'matrixMode=true ') ;
357+ // Simple Matrix detection: if sessionId looks like a Matrix room ID, it's a Matrix chat
358+ const isMatrixRoom = sessionId && sessionId . startsWith ( '! ') ;
357359
358- // Extract Matrix room ID from URL parameters if in Matrix mode
359- const urlParams = new URLSearchParams ( window . location . search ) ;
360- const matrixRoomId = urlParams . get ( 'matrixRoomId' ) ;
360+ // Get Matrix context for current user information
361+ const { currentUser } = useMatrix ( ) ;
361362
362- // Session sharing hook - use Matrix room ID as sessionId in Matrix mode
363+ // Session sharing hook - simplified approach for Matrix rooms
363364 const sessionSharing = useSessionSharing ( {
364- sessionId : isInMatrixMode && matrixRoomId ? matrixRoomId : ( sessionId || 'default' ) ,
365- sessionTitle : isInMatrixMode && matrixRoomId ? `Matrix Room ${ matrixRoomId . substring ( 0 , 8 ) } ` : `Chat Session ${ sessionId ?. substring ( 0 , 8 ) || 'Default ' } ` ,
365+ sessionId : sessionId , // Use the sessionId as-is (Matrix room ID or regular session ID)
366+ sessionTitle : isMatrixRoom && sessionId ? `Matrix Room ${ sessionId . substring ( 0 , 8 ) } ` : `Chat Session ${ sessionId ?. substring ( 0 , 8 ) || 'default ' } ` ,
366367 messages : messages , // Always sync messages
367368 onMessageSync : ( message ) => {
368- // Handle synced messages from session participants
369- console . log ( '💬 Synced message from shared session:' , message ) ;
370- // Add the synced message to local chat
369+ console . log ( '💬 ChatInput: Received message from useSessionSharing:' , message ) ;
370+
371+ // For Matrix rooms, messages from Matrix should appear normally
372+ // For regular sessions, messages should also appear normally
373+ // The key is that useSessionSharing handles both cases the same way
371374 if ( append ) {
372375 append ( message ) ;
376+ } else {
377+ console . warn ( '⚠️ ChatInput: append function is not available!' ) ;
373378 }
374379 } ,
375- initialRoomId : isInMatrixMode && matrixRoomId ? matrixRoomId : undefined , // Pass Matrix room ID for Matrix mode
380+ initialRoomId : isMatrixRoom ? sessionId : null , // Pass Matrix room ID if it's a Matrix room
376381 onParticipantJoin : ( participant ) => {
377- if ( ! isInMatrixMode ) {
378- console . log ( '👥 Participant joined session:' , participant ) ;
379- }
382+ console . log ( '👥 Participant joined session:' , participant ) ;
380383 } ,
381384 onParticipantLeave : ( userId ) => {
382- if ( ! isInMatrixMode ) {
383- console . log ( '👋 Participant left session:' , userId ) ;
384- }
385+ console . log ( '👋 Participant left session:' , userId ) ;
385386 } ,
386387 } ) ;
387388
388389 // Listen for AI responses to sync to Matrix
390+ // FIXED: Robust null checking to prevent "Cannot read properties of undefined (reading 'length')" error
391+ // Updated: Fixed all commandHistory.length accesses with safeCommandHistory
392+ // Final fix: All .length accesses now properly null-checked
389393 useEffect ( ( ) => {
390- if ( ! sessionSharing . isSessionActive || ! messages . length ) return ;
394+ if ( ! sessionSharing . isSessionActive || ! messages || ! Array . isArray ( messages ) || messages . length === 0 ) return ;
391395
392396 const lastMessage = messages [ messages . length - 1 ] ;
393397
394398 // Check if the last message is an AI response (assistant role) and not already synced
395- if ( lastMessage && lastMessage . role === 'assistant' && ! lastMessage . id ?. startsWith ( 'shared-' ) && ! lastMessage . id ?. startsWith ( 'matrix-' ) ) {
399+ // Also check if it's not from Matrix (to prevent sync loops)
400+ if ( lastMessage &&
401+ lastMessage . role === 'assistant' &&
402+ ! lastMessage . id ?. startsWith ( 'shared-' ) &&
403+ ! lastMessage . id ?. startsWith ( 'matrix-' ) &&
404+ ! lastMessage . sender ) { // Messages from Matrix have sender info, local AI responses don't
396405 console . log ( '🤖 Syncing AI response to session:' , lastMessage ) ;
397406
398- // Extract text content from the message
399- const textContent = lastMessage . content
400- . filter ( c => c . type === 'text' )
401- . map ( c => c . text )
402- . join ( '' ) ;
407+ // Extract text content from the message - with robust null checking
408+ let textContent = '' ;
409+ if ( lastMessage . content && Array . isArray ( lastMessage . content ) ) {
410+ textContent = lastMessage . content
411+ . filter ( c => c && c . type === 'text' )
412+ . map ( c => c . text || '' )
413+ . join ( '' ) ;
414+ } else if ( typeof lastMessage . content === 'string' ) {
415+ textContent = lastMessage . content ;
416+ }
403417
404418 if ( textContent . trim ( ) ) {
405419 sessionSharing . syncMessage ( {
@@ -476,14 +490,14 @@ export default function ChatInput({
476490 // Handle recipe prompt updates
477491 useEffect ( ( ) => {
478492 // If recipe is accepted and we have an initial prompt, and no messages yet, and we haven't set it before
479- if ( recipeAccepted && initialPrompt && messages . length === 0 ) {
493+ if ( recipeAccepted && initialPrompt && messages && Array . isArray ( messages ) && messages . length === 0 ) {
480494 setDisplayValue ( initialPrompt ) ;
481495 setValue ( initialPrompt ) ;
482496 setTimeout ( ( ) => {
483497 textAreaRef . current ?. focus ( ) ;
484498 } , 0 ) ;
485499 }
486- } , [ recipeAccepted , initialPrompt , messages . length ] ) ;
500+ } , [ recipeAccepted , initialPrompt , messages ] ) ;
487501
488502 // Draft functionality - load draft if no initial value or recipe
489503 useEffect ( ( ) => {
@@ -1060,11 +1074,14 @@ export default function ChatInput({
10601074 // Save current input if we're just starting to navigate history
10611075 if ( historyIndex === - 1 ) {
10621076 setSavedInput ( displayValue || '' ) ;
1063- setIsInGlobalHistory ( commandHistory . length === 0 ) ;
1077+ // Determine which history we're using - ensure commandHistory is always an array
1078+ const safeCommandHistory = commandHistory || [ ] ;
1079+ setIsInGlobalHistory ( safeCommandHistory . length === 0 ) ;
10641080 }
10651081
1066- // Determine which history we're using
1067- const currentHistory = isInGlobalHistory ? globalHistory : commandHistory ;
1082+ // Determine which history we're using - ensure commandHistory is always an array
1083+ const safeCommandHistory = commandHistory || [ ] ;
1084+ const currentHistory = isInGlobalHistory ? globalHistory : safeCommandHistory ;
10681085 let newIndex = historyIndex ;
10691086 let newValue = '' ;
10701087
@@ -1087,11 +1104,11 @@ export default function ChatInput({
10871104 // Still have items in current history
10881105 newIndex = historyIndex - 1 ;
10891106 newValue = currentHistory [ newIndex ] ;
1090- } else if ( isInGlobalHistory && commandHistory . length > 0 ) {
1107+ } else if ( isInGlobalHistory && safeCommandHistory . length > 0 ) {
10911108 // Switch to chat history
10921109 setIsInGlobalHistory ( false ) ;
1093- newIndex = commandHistory . length - 1 ;
1094- newValue = commandHistory [ newIndex ] ;
1110+ newIndex = safeCommandHistory . length - 1 ;
1111+ newValue = safeCommandHistory [ newIndex ] ;
10951112 } else {
10961113 // Return to original input
10971114 newIndex = - 1 ;
@@ -2058,8 +2075,8 @@ export default function ChatInput({
20582075 </ Tooltip >
20592076 < div className = "w-px h-4 bg-border-default mx-2" />
20602077
2061- { /* Session Sharing Component - disabled in Matrix mode */ }
2062- { ! isInMatrixMode && (
2078+ { /* Session Sharing Component - disabled for Matrix rooms */ }
2079+ { ! isMatrixRoom && (
20632080 < SessionSharing
20642081 sessionSharing = { sessionSharing }
20652082 shouldShowIconOnly = { shouldShowIconOnly }
@@ -2088,7 +2105,7 @@ export default function ChatInput({
20882105 setView = { setView }
20892106 alerts = { alerts }
20902107 recipeConfig = { recipeConfig }
2091- hasMessages = { messages . length > 0 }
2108+ hasMessages = { messages && Array . isArray ( messages ) && messages . length > 0 }
20922109 shouldShowIconOnly = { shouldShowIconOnly }
20932110 />
20942111 </ div >
0 commit comments