From f8bf002b39b7dfd0abc460d6980e1031c0b6e767 Mon Sep 17 00:00:00 2001 From: Arda Samadi Date: Sat, 25 Jul 2026 12:05:56 +0330 Subject: [PATCH] fix(chat): gate store-team grouping behind viewer_is_store MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The team-side logic (teamUserIds → right-aligned + coworker username label) was applied for every viewer, so a CUSTOMER saw the store's staff messages on their own side and with the staff's username/phone shown. Gate all team grouping on viewerIsStore (from the thread): customers now see store/staff messages on the left with no staff identity; the store inbox keeps the team-grouped view. Co-Authored-By: Claude Opus 4.8 --- app/components/thread/MessageList.tsx | 15 +++++++++++---- app/components/thread/ThreadChatPage.tsx | 1 + src/api/types/models/index.ts | 6 ++++++ 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/app/components/thread/MessageList.tsx b/app/components/thread/MessageList.tsx index 757ccd1..fe3690e 100644 --- a/app/components/thread/MessageList.tsx +++ b/app/components/thread/MessageList.tsx @@ -23,6 +23,7 @@ const MessageList = forwardRef( isFetching, userId, teamUserIds, + viewerIsStore = false, onReply, onDelete, onScroll, @@ -32,10 +33,13 @@ const MessageList = forwardRef( isLoading: boolean; isFetching: boolean; userId: string | undefined; - // When present, any message sender in this set is treated as "our side" - // (right-aligned, blue). Lets staff see coworkers' messages on the team - // side of the store inbox instead of confusing them with customer messages. + // Senders on the store team. Only treated as "our side" when the VIEWER + // is store-side (viewerIsStore) — otherwise a customer would wrongly see + // the store's staff messages on their own (right) side. teamUserIds?: readonly string[]; + // True when the current viewer is on this thread's store team. Gates all + // team-grouping so the customer view stays "my messages right, store left". + viewerIsStore?: boolean; onReply: (message: MessageListType) => void; onDelete?: (messageId: string) => void; onScroll?: (event: React.UIEvent) => void; @@ -170,9 +174,12 @@ const MessageList = forwardRef( message={message} isCurrentUser={ message.sender === userId || - (!!message.sender && !!teamUserIds?.includes(message.sender)) + (viewerIsStore && + !!message.sender && + !!teamUserIds?.includes(message.sender)) } isCoworker={ + viewerIsStore && message.sender !== userId && !!message.sender && !!teamUserIds?.includes(message.sender) diff --git a/app/components/thread/ThreadChatPage.tsx b/app/components/thread/ThreadChatPage.tsx index d7162d2..95171d0 100644 --- a/app/components/thread/ThreadChatPage.tsx +++ b/app/components/thread/ThreadChatPage.tsx @@ -286,6 +286,7 @@ export default function ThreadChatPage({ threadId }: ThreadChatPageProps) { isFetching={isFetchingNextPage} userId={user?.id} teamUserIds={threadDetails?.teamUserIds} + viewerIsStore={threadDetails?.viewerIsStore} onReply={handleReplyClick} onDelete={handleDeleteMessage} onScroll={handleScroll} diff --git a/src/api/types/models/index.ts b/src/api/types/models/index.ts index aa772d0..db92628 100644 --- a/src/api/types/models/index.ts +++ b/src/api/types/models/index.ts @@ -6587,6 +6587,12 @@ export interface ThreadDetail { * @memberof ThreadDetail */ readonly teamUserIds?: Array; + /** + * True when the viewer is on this thread's store team (owner/staff). + * @type {boolean} + * @memberof ThreadDetail + */ + readonly viewerIsStore?: boolean; } /** *