Appearance
Module Overview — Conversation Runtime And Provider Boundary
1. conversation thực tế đang chia thành 4 lớp
| Lớp | Thành phần | Vai trò |
|---|---|---|
| Workspace shell | ConversationDetail, Conversation, ConversationList, ConversationMessages | UI list/detail/message cơ bản |
| Provider runtime | Stringee wrapper, Twilio overlay, conference components | Token, connect/join room, media tracks |
| Store/read-model layer | useConversationStore, conversation_current, search functions | Cache list/messages, unread/search surfaces |
| Action layer | twilioToken, stringeeToken, createConference, stringeeCallEvent | Sinh token, tạo conference, bridge vendor |
Điểm quan trọng là 4 lớp này chưa được một composition trung tâm điều phối; useConversation.ts hiện rỗng (diva-admin/src/modules/conversation/compositions/useConversation.ts:1).
2. Surface map
FE routes
| Route/config | Vai trò |
|---|---|
/conversation | Root module, redirect nội bộ |
/conversation/:id | Detail workspace |
/conversation/:id/conference | Có constant/config name nhưng không có route record thật |
/conversation/stringee | Chỉ là config constant, không có route record riêng |
Runtime backend
| Runtime | Vai trò |
|---|---|
Hasura CRUD conversation* | Membership, messages, mentions, unread/read state |
Function search_conversation_current | Feed runtime denormalized của conversation list |
Function search_unread_conversation_messages | Feed unread riêng |
conversation-api actions | Token cho Twilio/Stringee, create conference, Stringee call event |
3. Route shell có drift thật
module.ts chỉ mount đúng một child route:
ROUTE_CONVERSATION_DETAIL->ConversationDetail(module.ts:17)
Nhưng ConversationDetail lại push sang:
ROUTE_CONVERSATION_CONFERENCE(ConversationDetail.tsx:13)
Trong repo hiện tại, constant này không được mount thành route record nào cả; search toàn bộ src/router và module conversation chỉ thấy nó xuất hiện ở types, module configs và router.push call. Đây là drift có thể làm conference route vỡ ngay khi người dùng bấm video.
4. Workspace realtime vẫn là shell một phần
Những gì đã có
| Surface | Trạng thái |
|---|---|
| Conversation list | Có infinite scroll, unread badge, update read state intent |
| Message view | Có render stream + reverse scroll + composer UI |
| Store | Có merge conversations/messages, giữ cursor và currentConversation |
Những gì còn thiếu hoặc đang scaffold
| Surface | Dấu hiệu |
|---|---|
| Video action trong header | QBtn chưa gắn onClick emit video (Conversation/index.tsx:23) |
Update read_at khi click list | mutation helper cuối file throw new Error("Function not implemented.") (ConversationList.tsx:188) |
| Composer send message | handleChatEnter() return sớm, không gọi mutation nào (ConversationMessages.tsx:92) |
| Composition orchestration | useConversation.ts rỗng (useConversation.ts:1) |
5. Provider runtime
Stringee
| Thành phần | Vai trò |
|---|---|
StringeeProviderWrapper | Query token rồi mount StringeeProvider |
StringeeProvider | Connect client, reconnect khi requestnewtoken, emit chat events |
StringeeConferenceDialog | Request room token và mount StringeeConference |
StringeeConference | Preview -> join -> room runtime + sidebar chat/participants |
Twilio
| Thành phần | Vai trò |
|---|---|
TwilioVideo/index.tsx | Full-screen overlay khi currentConversation.video_room_id có giá trị |
TwilioVideoPreview | Preview trước khi join |
TwilioVideo | Connect room, attach/detach local-remote tracks |
6. Provider/backend contract đang lệch
createConference
Backend action này:
- parse
type = meet | stringee, - tạo Google Meet hoặc Stringee room,
- nếu có
conversation_id, cố updateconversation.external_call_id = conference_url(conversation.go:60).
Drift
| Drift | Vì sao quan trọng |
|---|---|
FE Twilio overlay đọc conversation.video_room_id (TwilioVideo/index.tsx:14) | nhưng createConference không update video_room_id |
Metadata permission chỉ expose video_room_id/video_room_provider, không thấy external_call_id trong conversation user/admin permissions (public_conversation.yaml:62, public_conversation_admin.yaml:43) | nên mutate external_call_id có thể fail theo role contract |
createConference log lỗi update conversation nhưng vẫn return success (conference.go:79) | FE có thể nghĩ conference đã gắn vào conversation dù DB không đổi |
7. Findings nổi bật
| ID | Finding |
|---|---|
| MO-F01 | ROUTE_CONVERSATION_CONFERENCE không có route record thật, dù detail page đang push sang route này. |
| MO-F02 | Nút video ở Conversation chưa emit event, nên kể cả route có tồn tại thì header shell hiện vẫn không khởi động conference từ component này. |
| MO-F03 | ConversationList click item sẽ chạm mutation stub và có nguy cơ throw runtime error ngay tại UI. |
| MO-F04 | Twilio preview emit audioEnabled, nhưng parent đọc microphoneEnabled; preview choices có thể không được chuyển đúng sang room runtime. |
| MO-F05 | createConference update sai field contract (external_call_id) và swallow lỗi mutation conversation, nên conference create có thể “thành công giả”. |
| MO-F06 | Nhánh createConference -> stringee không guard ctx.Stringee == nil, khác hẳn stringeeToken, tạo ra một điểm có thể panic hoặc nil dereference khi provider config thiếu. |