Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit0eb7dd2

Browse files
added events in chat component
1 parent86dec70 commit0eb7dd2

File tree

4 files changed

+229
-6
lines changed

4 files changed

+229
-6
lines changed

‎client/packages/lowcoder/src/comps/comps/chatBoxComponent/chatBoxComp.tsx‎

Lines changed: 111 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { ScrollBar, Section, sectionNames } from "lowcoder-design";
22
importstyled,{css}from"styled-components";
33
import{UICompBuilder}from"../../generators";
44
import{NameConfig,NameConfigHidden,withExposingConfigs}from"../../generators/withExposing";
5+
import{withMethodExposing}from"../../generators/withMethodExposing";
56
import{TextStyle,TextStyleType,AnimationStyle,AnimationStyleType}from"comps/controls/styleControlConstants";
67
import{hiddenPropertyView}from"comps/utils/propertyUtils";
78
importReact,{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+
consthandleJoinUser=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+
returntrue;
350+
}catch(error){
351+
console.error('[ChatBox] 💥 Error joining as user:',error);
352+
returnfalse;
353+
}
354+
};
355+
333356
// Main view component
334357
constChatBoxView=React.memo((props:ToViewReturn<ChatCompChildrenType>)=>{
335358
const[currentMessage,setCurrentMessage]=useState<string>("");
@@ -345,18 +368,52 @@ const ChatBoxView = React.memo((props: ToViewReturn<ChatCompChildrenType>) => {
345368
constchatAreaRef=useRef<HTMLDivElement>(null);
346369
constsearchTimeoutRef=useRef<NodeJS.Timeout|null>(null);
347370

371+
// Helper function to trigger custom events
372+
consttriggerEvent=(eventName:string)=>{
373+
if(props.onEvent){
374+
props.onEvent(eventName);
375+
}
376+
};
377+
348378
// Initialize chat manager
349379
constmodeValue=props.modeas'local'|'collaborative'|'hybrid';
350380

381+
// Only auto-connect if userId and userName are provided in configuration
382+
constshouldAutoConnect=!!(props.userId.value&&props.userName.value);
383+
351384
constchatManager=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+
}elseif(chatManager.error){
413+
triggerEvent("error");
414+
}
415+
},[chatManager.isConnected,chatManager.error]);
416+
360417
// Load joined rooms when connected
361418
useEffect(()=>{
362419
constloadRooms=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
constupdatedJoinedRooms=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+
constlastMessage=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+
returnawaithandleJoinUser(comp,values?.[0],values?.[1]);
1438+
},
1439+
},
1440+
]);
1441+
13351442
exportconstChatBoxComp=withExposingConfigs(ChatBoxTmpComp,[
13361443
newNameConfig("chatName","Chat name displayed in header"),
13371444
newNameConfig("userId","Unique identifier for current user"),

‎client/packages/lowcoder/src/comps/comps/chatBoxComponent/chatControllerComp.tsx‎

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,10 @@ const handleJoinRoom = async (
6969
constchatManager=comp.children.chatManager.getView()asunknownasUseChatManagerReturn;
7070
try{
7171
constsuccess=awaitchatManager.joinRoom(roomId);
72-
if(!success){
72+
if(success){
73+
// Note: Event will be triggered by the component's useEffect hooks
74+
console.log('[ChatController] ✅ Successfully joined room:',roomId);
75+
}else{
7376
console.error('[ChatBox] ❌ Failed to join room:',roomId);
7477
}
7578
}catch(error){
@@ -87,6 +90,10 @@ const handleLeaveRoom = async (
8790
console.log('[ChatBox] 🚪 Attempting to leave room:',roomId);
8891

8992
constsuccess=awaitchatManager.leaveRoom(roomId);
93+
if(success){
94+
// Note: Event will be triggered by the component's useEffect hooks
95+
console.log('[ChatController] ✅ Successfully left room:',roomId);
96+
}
9097
returnsuccess;
9198
}catch(error){
9299
console.error('[ChatBox] 💥 Error leaving room:',error);
@@ -113,6 +120,10 @@ const handleSendMessage = async (
113120
constchatManager=comp.children.chatManager.getView()asunknownasUseChatManagerReturn;
114121
if(currentMessage.trim()){
115122
constsuccess=awaitchatManager.sendMessage(currentMessage.trim());
123+
if(success){
124+
// Note: Event will be triggered by the component's useEffect hooks
125+
console.log('[ChatController] ✅ Message sent successfully');
126+
}
116127
returnsuccess;
117128
}
118129
}catch(error){
@@ -194,6 +205,13 @@ const ChatBoxView = React.memo((
194205
const[currentRoomParticipants,setCurrentRoomParticipants]=useState<Array<{id:string;name:string}>>([]);
195206
consthandleClickEvent=useCompClickEventHandler({onEvent:props.onEvent});
196207

208+
// Helper function to trigger custom events
209+
consttriggerEvent=(eventName:string)=>{
210+
if(props.onEvent){
211+
props.onEvent(eventName);
212+
}
213+
};
214+
197215
// Initialize chat manager
198216
constmodeValue=props.modeas'local'|'collaborative'|'hybrid';
199217

@@ -259,6 +277,15 @@ const ChatBoxView = React.memo((
259277
}
260278
},[props.userId.value,props.userName.value]);
261279

280+
// Chat event handlers
281+
useEffect(()=>{
282+
if(chatManager.isConnected){
283+
triggerEvent("connected");
284+
}elseif(chatManager.error){
285+
triggerEvent("error");
286+
}
287+
},[chatManager.isConnected,chatManager.error]);
288+
262289
// Refresh joined rooms periodically
263290
useEffect(()=>{
264291
if(!chatManager.isConnected)return;
@@ -324,6 +351,11 @@ const ChatBoxView = React.memo((
324351
dispatch(
325352
changeChildAction("currentRoom",currentRoomasany,false)
326353
);
354+
355+
// Trigger room joined event when currentRoom changes to a new room
356+
if(currentRoom){
357+
triggerEvent("roomJoined");
358+
}
327359
},[currentRoom]);
328360

329361
// Update typingUsers state
@@ -335,6 +367,31 @@ const ChatBoxView = React.memo((
335367
);
336368
},[typingUsers]);
337369

370+
// Message events
371+
useEffect(()=>{
372+
if(messages.length>0){
373+
constlastMessage=messages[messages.length-1];
374+
if(lastMessage){
375+
if(lastMessage.authorId===props.userId.value){
376+
// Message sent by current user
377+
triggerEvent("messageSent");
378+
}else{
379+
// Message received from another user
380+
triggerEvent("messageReceived");
381+
}
382+
}
383+
}
384+
},[messages,props.userId.value]);
385+
386+
// Typing events
387+
useEffect(()=>{
388+
if(typingUsers&&typingUsers.length>0){
389+
triggerEvent("typingStarted");
390+
}else{
391+
triggerEvent("typingStopped");
392+
}
393+
},[typingUsers]);
394+
338395
return(
339396
<BackgroundColorContext.Providervalue={props.style.background}>
340397
{/* <DrawerWrapper> */}
@@ -510,6 +567,25 @@ ChatControllerComp = withMethodExposing(ChatControllerComp, [
510567
handleSendMessage(comp,values?.[0]);
511568
},
512569
},
570+
{
571+
method:{
572+
name:"getRoomParticipants",
573+
description:"Get participants of a room with their ID and name",
574+
params:[
575+
{
576+
name:"roomId",
577+
type:"string",
578+
},
579+
],
580+
},
581+
execute:async(comp:ConstructorToComp<typeofChatControllerComp>,values:any)=>{
582+
constchatManager=comp.children.chatManager.getView()asany;
583+
if(chatManager&&chatManager.getRoomParticipants){
584+
returnawaitchatManager.getRoomParticipants(values?.[0]);
585+
}
586+
return[];
587+
},
588+
},
513589
{
514590
method:{
515591
name:"joinUser",

‎client/packages/lowcoder/src/comps/comps/chatBoxComponent/chatUtils.tsx‎

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,21 @@ import React, { useContext, useMemo } from "react";
1616
import{trans}from"i18n";
1717

1818
// Event options for the chat component
19-
constEventOptions=[clickEvent,doubleClickEvent]asconst;
19+
constEventOptions=[
20+
clickEvent,
21+
doubleClickEvent,
22+
{label:trans("chatBox.connected"),value:"connected",description:trans("chatBox.connectedDesc")},
23+
{label:trans("chatBox.disconnected"),value:"disconnected",description:trans("chatBox.disconnectedDesc")},
24+
{label:trans("chatBox.messageReceived"),value:"messageReceived",description:trans("chatBox.messageReceivedDesc")},
25+
{label:trans("chatBox.messageSent"),value:"messageSent",description:trans("chatBox.messageSentDesc")},
26+
{label:trans("chatBox.userJoined"),value:"userJoined",description:trans("chatBox.userJoinedDesc")},
27+
{label:trans("chatBox.userLeft"),value:"userLeft",description:trans("chatBox.userLeftDesc")},
28+
{label:trans("chatBox.typingStarted"),value:"typingStarted",description:trans("chatBox.typingStartedDesc")},
29+
{label:trans("chatBox.typingStopped"),value:"typingStopped",description:trans("chatBox.typingStoppedDesc")},
30+
{label:trans("chatBox.roomJoined"),value:"roomJoined",description:trans("chatBox.roomJoinedDesc")},
31+
{label:trans("chatBox.roomLeft"),value:"roomLeft",description:trans("chatBox.roomLeftDesc")},
32+
{label:trans("chatBox.error"),value:"error",description:trans("chatBox.errorDesc")},
33+
]asconst;
2034

2135
// Define the component's children map
2236
exportconstchatCompChildrenMap={

‎client/packages/lowcoder/src/i18n/locales/en.ts‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1482,6 +1482,32 @@ export const en = {
14821482
"conversationHistory":"Full conversation history as JSON array",
14831483
"databaseNameExposed":"Database name for SQL queries (ChatDB_<componentName>)"
14841484
},
1485+
1486+
"chatBox":{
1487+
// Event Labels & Descriptions
1488+
"connected":"Connected",
1489+
"connectedDesc":"Triggered when the chat connects to the server",
1490+
"disconnected":"Disconnected",
1491+
"disconnectedDesc":"Triggered when the chat disconnects from the server",
1492+
"messageReceived":"Message Received",
1493+
"messageReceivedDesc":"Triggered when a new message is received from another user",
1494+
"messageSent":"Message Sent",
1495+
"messageSentDesc":"Triggered when the current user sends a message",
1496+
"userJoined":"User Joined",
1497+
"userJoinedDesc":"Triggered when a new user joins the current room",
1498+
"userLeft":"User Left",
1499+
"userLeftDesc":"Triggered when a user leaves the current room",
1500+
"typingStarted":"Typing Started",
1501+
"typingStartedDesc":"Triggered when someone starts typing in the current room",
1502+
"typingStopped":"Typing Stopped",
1503+
"typingStoppedDesc":"Triggered when someone stops typing in the current room",
1504+
"roomJoined":"Room Joined",
1505+
"roomJoinedDesc":"Triggered when the current user joins a room",
1506+
"roomLeft":"Room Left",
1507+
"roomLeftDesc":"Triggered when the current user leaves a room",
1508+
"error":"Error",
1509+
"errorDesc":"Triggered when an error occurs in the chat system"
1510+
},
14851511
// eighth part
14861512

14871513
"comp":{

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp