Skip to content

Commit c26d9b1

Browse files
committed
add rooms in the chatbox UI + fix controller issues
1 parent c1030f6 commit c26d9b1

14 files changed

Lines changed: 1251 additions & 340 deletions

File tree

client/packages/lowcoder/src/comps/comps/chatBoxComponentv2/README.md

Lines changed: 646 additions & 214 deletions
Large diffs are not rendered by default.

client/packages/lowcoder/src/comps/comps/chatBoxComponentv2/chatBoxComp.tsx

Lines changed: 149 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,22 +42,82 @@ const ChatEvents = [
4242
description:
4343
"Triggered when the user stops typing. Wire this to chatController.stopTyping().",
4444
},
45+
{
46+
label: "Room Switch",
47+
value: "roomSwitch",
48+
description:
49+
"User clicked a room they are already a member of. Read chatBox.pendingRoomId, then call chatController.switchRoom({{chatBox1.pendingRoomId}}).",
50+
},
51+
{
52+
label: "Room Join",
53+
value: "roomJoin",
54+
description:
55+
"User wants to join a room from search results. Read chatBox.pendingRoomId, then call chatController.joinRoom({{chatBox1.pendingRoomId}}).",
56+
},
57+
{
58+
label: "Room Leave",
59+
value: "roomLeave",
60+
description:
61+
"User clicked leave on a room. Read chatBox.pendingRoomId, then call chatController.leaveRoom({{chatBox1.pendingRoomId}}).",
62+
},
63+
{
64+
label: "Room Create",
65+
value: "roomCreate",
66+
description:
67+
"User submitted the create-room form. Read chatBox.newRoomName, newRoomType, newRoomDescription, newRoomLlmQuery, then call chatController.createRoom(...).",
68+
},
69+
{
70+
label: "Invite Send",
71+
value: "inviteSend",
72+
description:
73+
"User sent a room invite. Read chatBox.inviteTargetUserId, then call chatController.sendInvite(currentRoomId, {{chatBox1.inviteTargetUserId}}).",
74+
},
75+
{
76+
label: "Invite Accept",
77+
value: "inviteAccept",
78+
description:
79+
"User accepted a pending invite. Read chatBox.pendingInviteId, then call chatController.acceptInvite({{chatBox1.pendingInviteId}}).",
80+
},
81+
{
82+
label: "Invite Decline",
83+
value: "inviteDecline",
84+
description:
85+
"User declined a pending invite. Read chatBox.pendingInviteId, then call chatController.declineInvite({{chatBox1.pendingInviteId}}).",
86+
},
4587
] as const;
4688

4789
// ─── Children map ────────────────────────────────────────────────────────────
4890

4991
const childrenMap = {
92+
// ── Chat content ─────────────────────────────────────────────────
5093
chatTitle: stringExposingStateControl("chatTitle", "Chat"),
5194
showHeader: withDefault(BoolControl, true),
52-
5395
messages: jsonArrayControl([]),
5496
currentUserId: withDefault(StringControl, "user_1"),
5597
currentUserName: withDefault(StringControl, "User"),
5698
typingUsers: jsonArrayControl([]),
57-
5899
lastSentMessageText: stringExposingStateControl("lastSentMessageText", ""),
59100
messageText: stringExposingStateControl("messageText", ""),
60101

102+
// ── Rooms panel ──────────────────────────────────────────────────
103+
rooms: jsonArrayControl([]),
104+
currentRoomId: withDefault(StringControl, ""),
105+
pendingInvites: jsonArrayControl([]),
106+
showRoomsPanel: withDefault(BoolControl, true),
107+
roomsPanelWidth: withDefault(StringControl, "240px"),
108+
allowRoomCreation: withDefault(BoolControl, true),
109+
allowRoomSearch: withDefault(BoolControl, true),
110+
111+
// ── Exposed state written on user interactions ────────────────────
112+
pendingRoomId: stringExposingStateControl("pendingRoomId", ""),
113+
newRoomName: stringExposingStateControl("newRoomName", ""),
114+
newRoomType: stringExposingStateControl("newRoomType", "public"),
115+
newRoomDescription: stringExposingStateControl("newRoomDescription", ""),
116+
newRoomLlmQuery: stringExposingStateControl("newRoomLlmQuery", ""),
117+
inviteTargetUserId: stringExposingStateControl("inviteTargetUserId", ""),
118+
pendingInviteId: stringExposingStateControl("pendingInviteId", ""),
119+
120+
// ── Style / layout ────────────────────────────────────────────────
61121
autoHeight: AutoHeightControl,
62122
onEvent: eventHandlerControl(ChatEvents),
63123
style: styleControl(TextStyle, "style"),
@@ -93,6 +153,31 @@ const ChatBoxPropertyView = React.memo((props: { children: any }) => {
93153
})}
94154
</Section>
95155

156+
<Section name="Rooms Panel">
157+
{children.showRoomsPanel.propertyView({ label: "Show Rooms Panel" })}
158+
{children.roomsPanelWidth.propertyView({
159+
label: "Panel Width",
160+
tooltip: "Width of the rooms sidebar, e.g. 240px or 30%",
161+
})}
162+
{children.rooms.propertyView({
163+
label: "Rooms",
164+
tooltip:
165+
"Bind to {{ chatController1.userRooms }} — the list of rooms visible to the current user.",
166+
})}
167+
{children.currentRoomId.propertyView({
168+
label: "Current Room ID",
169+
tooltip:
170+
"Bind to {{ chatController1.currentRoomId }} to highlight the active room.",
171+
})}
172+
{children.pendingInvites.propertyView({
173+
label: "Pending Invites",
174+
tooltip:
175+
"Bind to {{ chatController1.pendingInvites }} to show invite notifications.",
176+
})}
177+
{children.allowRoomCreation.propertyView({ label: "Allow Room Creation" })}
178+
{children.allowRoomSearch.propertyView({ label: "Allow Room Search" })}
179+
</Section>
180+
96181
<Section name="Real-time">
97182
{children.typingUsers.propertyView({
98183
label: "Typing Users",
@@ -148,6 +233,46 @@ let ChatBoxV2Tmp = (function () {
148233
style={props.style}
149234
animationStyle={props.animationStyle}
150235
onEvent={props.onEvent}
236+
// Rooms panel
237+
rooms={props.rooms}
238+
currentRoomId={props.currentRoomId}
239+
pendingInvites={props.pendingInvites}
240+
showRoomsPanel={props.showRoomsPanel}
241+
roomsPanelWidth={props.roomsPanelWidth}
242+
allowRoomCreation={props.allowRoomCreation}
243+
allowRoomSearch={props.allowRoomSearch}
244+
// Callbacks that set state then fire events
245+
onRoomSwitch={(roomId) => {
246+
props.pendingRoomId.onChange(roomId);
247+
props.onEvent("roomSwitch");
248+
}}
249+
onRoomJoin={(roomId) => {
250+
props.pendingRoomId.onChange(roomId);
251+
props.onEvent("roomJoin");
252+
}}
253+
onRoomLeave={(roomId) => {
254+
props.pendingRoomId.onChange(roomId);
255+
props.onEvent("roomLeave");
256+
}}
257+
onRoomCreate={(name, type, description, llmQueryName) => {
258+
props.newRoomName.onChange(name);
259+
props.newRoomType.onChange(type);
260+
props.newRoomDescription.onChange(description || "");
261+
props.newRoomLlmQuery.onChange(llmQueryName || "");
262+
props.onEvent("roomCreate");
263+
}}
264+
onInviteSend={(toUserId) => {
265+
props.inviteTargetUserId.onChange(toUserId);
266+
props.onEvent("inviteSend");
267+
}}
268+
onInviteAccept={(inviteId) => {
269+
props.pendingInviteId.onChange(inviteId);
270+
props.onEvent("inviteAccept");
271+
}}
272+
onInviteDecline={(inviteId) => {
273+
props.pendingInviteId.onChange(inviteId);
274+
props.onEvent("inviteDecline");
275+
}}
151276
/>
152277
);
153278
})
@@ -170,5 +295,27 @@ export const ChatBoxV2Comp = withExposingConfigs(ChatBoxV2Tmp, [
170295
"Text of the last message sent by the user — use in your save query",
171296
),
172297
new NameConfig("messageText", "Current text in the message input"),
298+
new NameConfig(
299+
"pendingRoomId",
300+
"Room ID the user wants to switch to, join, or leave — read in roomSwitch/roomJoin/roomLeave events",
301+
),
302+
new NameConfig("newRoomName", "Name entered in the create-room form"),
303+
new NameConfig(
304+
"newRoomType",
305+
"Type selected in the create-room form: public | private | llm",
306+
),
307+
new NameConfig("newRoomDescription", "Description entered in the create-room form"),
308+
new NameConfig(
309+
"newRoomLlmQuery",
310+
"Query name entered for LLM rooms in the create-room form",
311+
),
312+
new NameConfig(
313+
"inviteTargetUserId",
314+
"User ID entered in the invite form — read in inviteSend event",
315+
),
316+
new NameConfig(
317+
"pendingInviteId",
318+
"Invite ID the user accepted or declined — read in inviteAccept/inviteDecline events",
319+
),
173320
NameConfigHidden,
174321
]);

0 commit comments

Comments
 (0)