Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(livechat): registering guest multiple times cause message loss #32069

Merged
merged 2 commits into from
Apr 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/nine-houses-reply.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@rocket.chat/meteor": patch
"@rocket.chat/livechat": patch
---

Livechat: A registered user loses their messages if 'registerGuest' is called using the same token.
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,6 @@ test.describe('OC - Livechat API', () => {
await poLiveChat.btnSendMessageToOnlineAgent.click();

await expect(poLiveChat.txtChatMessage('this_a_test_message_from_visitor_1')).toBeVisible();

});

await test.step('Expect registerGuest to create guest 2', async () => {
Expand All @@ -448,7 +447,6 @@ test.describe('OC - Livechat API', () => {

await poLiveChat.txtChatMessage('this_a_test_message_from_visitor_2').waitFor({ state: 'visible' });
await expect(poLiveChat.txtChatMessage('this_a_test_message_from_visitor_2')).toBeVisible();

});
});

Expand All @@ -460,8 +458,6 @@ test.describe('OC - Livechat API', () => {
};

await test.step('Expect registerGuest work with the same token, multiple times', async () => {
test.fail();

await poLiveChat.page.evaluate(() => window.RocketChat.livechat.maximizeWidget());
await expect(page.frameLocator('#rocketchat-iframe').getByText('Start Chat')).toBeVisible();

Expand Down
74 changes: 57 additions & 17 deletions packages/livechat/src/lib/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,49 @@ import { createToken } from './random';
import { loadMessages } from './room';
import Triggers from './triggers';

const evaluateChangesAndLoadConfigByFields = async (fn: () => Promise<void>) => {
const oldStore = JSON.parse(
JSON.stringify({
user: store.state.user || {},
department: store.state.department,
token: store.state.token,
}),
);
await fn();

/**
* it solves the issues where the registerGuest is called every time the widget is opened
* and the guest is already registered. If there is nothing different in the data,
* it will not call the loadConfig again.
*
* if user changes, it will call loadConfig
* if department changes, it will call loadConfig
* if token changes, it will call loadConfig
*/

if (oldStore.user._id !== store.state.user?._id) {
await loadConfig();
await loadMessages();
return;
}

if (oldStore.department !== store.state.department) {
await loadConfig();
await loadMessages();
return;
}

if (oldStore.token !== store.state.token) {
await loadConfig();
await loadMessages();
}
};

const createOrUpdateGuest = async (guest: StoreState['guest']) => {
if (!guest) {
return;
}

const { token } = guest;
token && (await store.setState({ token }));
const { visitor: user } = await Livechat.grantVisitor({ visitor: { ...guest } });
Expand All @@ -23,7 +62,6 @@ const createOrUpdateGuest = async (guest: StoreState['guest']) => {
return;
}
store.setState({ user } as Omit<StoreState['user'], 'ts'>);
await loadConfig();
Triggers.callbacks?.emit('chat-visitor-registered');
};

Expand Down Expand Up @@ -97,6 +135,10 @@ const api = {
},

setDepartment: async (value: string) => {
await evaluateChangesAndLoadConfigByFields(async () => api._setDepartment(value));
},

_setDepartment: async (value: string) => {
const {
user,
config: { departments = [] },
Expand All @@ -108,8 +150,6 @@ const api = {
return;
}

const { department: existingDepartment } = user || {};

const department = departments.find((dep) => dep._id === value || dep.name === value)?._id || '';

if (!department) {
Expand All @@ -124,11 +164,6 @@ const api = {
if (defaultAgent && defaultAgent.department !== department) {
store.setState({ defaultAgent: undefined });
}

if (department !== existingDepartment) {
await loadConfig();
await loadMessages();
}
},

setBusinessUnit: async (newBusinessUnit: string) => {
Expand Down Expand Up @@ -185,7 +220,10 @@ const api = {
if (token === localToken) {
return;
}
await createOrUpdateGuest({ token });

await evaluateChangesAndLoadConfigByFields(async () => {
await createOrUpdateGuest({ token });
});
},

setGuestName: (name: string) => {
Expand All @@ -201,17 +239,19 @@ const api = {
return;
}

if (!data.token) {
data.token = createToken();
}
await evaluateChangesAndLoadConfigByFields(async () => {
if (!data.token) {
data.token = createToken();
}

if (data.department) {
api.setDepartment(data.department);
}
if (data.department) {
await api._setDepartment(data.department);
}

Livechat.unsubscribeAll();
Livechat.unsubscribeAll();

await createOrUpdateGuest(data);
await createOrUpdateGuest(data);
});
},

setLanguage: async (language: StoreState['iframe']['language']) => {
Expand Down
Loading