@@ -2,6 +2,7 @@ import { ScrollBar, Section, sectionNames } from "lowcoder-design";
22import styled , { css } from "styled-components" ;
33import { UICompBuilder } from "../../generators" ;
44import { NameConfig , NameConfigHidden , withExposingConfigs } from "../../generators/withExposing" ;
5+ import { withMethodExposing } from "../../generators/withMethodExposing" ;
56import { TextStyle , TextStyleType , AnimationStyle , AnimationStyleType } from "comps/controls/styleControlConstants" ;
67import { hiddenPropertyView } from "comps/utils/propertyUtils" ;
78import React , { useContext , useEffect , useRef , useMemo , useState } from "react" ;
@@ -330,6 +331,28 @@ const ChatPropertyView = React.memo((props: {
330331 ) ;
331332} ) ;
332333
334+ // Handler for joinUser method
335+ const handleJoinUser = async (
336+ comp : any ,
337+ userId : string ,
338+ userName : string ,
339+ ) => {
340+ try {
341+ // Update the component's internal state with user credentials
342+ comp . children . userId . getView ( ) . onChange ( userId ) ;
343+ comp . children . userName . getView ( ) . onChange ( userName ) ;
344+
345+ console . log ( '[ChatBox] 👤 User joined as:' , { userId, userName } ) ;
346+
347+ // The chat manager will automatically reconnect with new credentials
348+ // due to the useEffect that watches for userId/userName changes
349+ return true ;
350+ } catch ( error ) {
351+ console . error ( '[ChatBox] 💥 Error joining as user:' , error ) ;
352+ return false ;
353+ }
354+ } ;
355+
333356// Main view component
334357const ChatBoxView = React . memo ( ( props : ToViewReturn < ChatCompChildrenType > ) => {
335358 const [ currentMessage , setCurrentMessage ] = useState < string > ( "" ) ;
@@ -345,18 +368,52 @@ const ChatBoxView = React.memo((props: ToViewReturn<ChatCompChildrenType>) => {
345368 const chatAreaRef = useRef < HTMLDivElement > ( null ) ;
346369 const searchTimeoutRef = useRef < NodeJS . Timeout | null > ( null ) ;
347370
371+ // Helper function to trigger custom events
372+ const triggerEvent = ( eventName : string ) => {
373+ if ( props . onEvent ) {
374+ props . onEvent ( eventName ) ;
375+ }
376+ } ;
377+
348378 // Initialize chat manager
349379 const modeValue = props . mode as 'local' | 'collaborative' | 'hybrid' ;
350380
381+ // Only auto-connect if userId and userName are provided in configuration
382+ const shouldAutoConnect = ! ! ( props . userId . value && props . userName . value ) ;
383+
351384 const chatManager = useChatManager ( {
352- userId : props . userId . value || "user_1" ,
353- userName : props . userName . value || "User" ,
385+ userId : props . userId . value ,
386+ userName : props . userName . value ,
354387 applicationId : props . applicationId . value || "lowcoder_app" ,
355388 roomId : props . roomId . value || "general" ,
356389 mode : modeValue , // Use mode from props
357- autoConnect : true ,
390+ autoConnect : shouldAutoConnect , // Only auto-connect if credentials are provided
358391 } ) ;
359392
393+ // Handle reconnection when userId or userName changes (for public users)
394+ useEffect ( ( ) => {
395+ if ( props . userId . value && props . userName . value ) {
396+ if ( chatManager . isConnected ) {
397+ // Disconnect and let the chat manager reconnect with new credentials
398+ chatManager . disconnect ( ) . then ( ( ) => {
399+ console . log ( '[ChatBox] 🔄 Reconnecting with new user credentials' ) ;
400+ } ) ;
401+ } else {
402+ // If not connected and we have credentials, trigger connection
403+ console . log ( '[ChatBox] 🔌 Connecting with user credentials' ) ;
404+ }
405+ }
406+ } , [ props . userId . value , props . userName . value ] ) ;
407+
408+ // Chat event handlers
409+ useEffect ( ( ) => {
410+ if ( chatManager . isConnected ) {
411+ triggerEvent ( "connected" ) ;
412+ } else if ( chatManager . error ) {
413+ triggerEvent ( "error" ) ;
414+ }
415+ } , [ chatManager . isConnected , chatManager . error ] ) ;
416+
360417 // Load joined rooms when connected
361418 useEffect ( ( ) => {
362419 const loadRooms = async ( ) => {
@@ -515,6 +572,9 @@ const ChatBoxView = React.memo((props: ToViewReturn<ChatCompChildrenType>) => {
515572 setSearchQuery ( "" ) ;
516573 setShowSearchResults ( false ) ;
517574
575+ // Trigger room joined event
576+ triggerEvent ( "roomJoined" ) ;
577+
518578 console . log ( '[ChatBox] 📋 Room join completed successfully' ) ;
519579 } else {
520580 console . log ( '[ChatBox] ❌ Failed to join room:' , roomId ) ;
@@ -535,6 +595,9 @@ const ChatBoxView = React.memo((props: ToViewReturn<ChatCompChildrenType>) => {
535595 const updatedJoinedRooms = joinedRooms . filter ( ( room : any ) => room . id !== roomId ) ;
536596 setJoinedRooms ( updatedJoinedRooms ) ;
537597
598+ // Trigger room left event
599+ triggerEvent ( "roomLeft" ) ;
600+
538601 // If user left the current room, switch to another joined room or clear chat
539602 if ( currentRoom ?. id === roomId ) {
540603 if ( updatedJoinedRooms . length > 0 ) {
@@ -652,6 +715,26 @@ const ChatBoxView = React.memo((props: ToViewReturn<ChatCompChildrenType>) => {
652715 stopTyping
653716 } = chatManager ;
654717
718+ // Message received event
719+ useEffect ( ( ) => {
720+ if ( messages . length > 0 ) {
721+ const lastMessage = messages [ messages . length - 1 ] ;
722+ if ( lastMessage && lastMessage . authorId !== props . userId . value ) {
723+ triggerEvent ( "messageReceived" ) ;
724+ }
725+ }
726+ } , [ messages ] ) ;
727+
728+ // Typing events
729+ useEffect ( ( ) => {
730+ if ( typingUsers && typingUsers . length > 0 ) {
731+ triggerEvent ( "typingStarted" ) ;
732+ } else {
733+ triggerEvent ( "typingStopped" ) ;
734+ }
735+ } , [ typingUsers ] ) ;
736+
737+
655738 useEffect ( ( ) => {
656739 if ( chatAreaRef . current ) {
657740 chatAreaRef . current . scrollTop = chatAreaRef . current . scrollHeight ;
@@ -716,7 +799,8 @@ const ChatBoxView = React.memo((props: ToViewReturn<ChatCompChildrenType>) => {
716799
717800 if ( success ) {
718801 setCurrentMessage ( "" ) ;
719- handleClickEvent ( ) ;
802+ handleClickEvent ( ) ;
803+ triggerEvent ( "messageSent" ) ;
720804 }
721805 }
722806 } ;
@@ -1332,6 +1416,29 @@ ChatBoxTmpComp = class extends ChatBoxTmpComp {
13321416 }
13331417} ;
13341418
1419+ // Add method exposing
1420+ ChatBoxTmpComp = withMethodExposing ( ChatBoxTmpComp , [
1421+ {
1422+ method : {
1423+ name : "joinUser" ,
1424+ description : "Allow users to join the chat server with their own credentials" ,
1425+ params : [
1426+ {
1427+ name : "userId" ,
1428+ type : "string" ,
1429+ } ,
1430+ {
1431+ name : "userName" ,
1432+ type : "string" ,
1433+ } ,
1434+ ] ,
1435+ } ,
1436+ execute : async ( comp : any , values : any ) => {
1437+ return await handleJoinUser ( comp , values ?. [ 0 ] , values ?. [ 1 ] ) ;
1438+ } ,
1439+ } ,
1440+ ] ) ;
1441+
13351442export const ChatBoxComp = withExposingConfigs ( ChatBoxTmpComp , [
13361443 new NameConfig ( "chatName" , "Chat name displayed in header" ) ,
13371444 new NameConfig ( "userId" , "Unique identifier for current user" ) ,
0 commit comments