Skip to content

Commit 981af32

Browse files
ggazzotassoevan
andauthored
refactor: incrementally remove Meteor deps from the frontend (#40268)
Co-authored-by: Tasso Evangelista <tasso.evangelista@rocket.chat>
1 parent fac6472 commit 981af32

44 files changed

Lines changed: 502 additions & 445 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
import { Meteor } from 'meteor/meteor';
2-
31
import { AutoTranslate } from './autotranslate';
42

5-
Meteor.startup(() => {
6-
AutoTranslate.init();
7-
});
3+
AutoTranslate.init();

apps/meteor/app/autotranslate/client/lib/autotranslate.ts

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
import type { IRoom, ISubscription, ISupportedLanguage, ITranslatedMessage, MessageAttachmentDefault } from '@rocket.chat/core-typings';
22
import { isTranslatedMessageAttachment } from '@rocket.chat/core-typings';
33
import mem from 'mem';
4-
import { Meteor } from 'meteor/meteor';
5-
import { Tracker } from 'meteor/tracker';
64

5+
import { PermissionsCachedStore } from '../../../../client/cachedStores';
76
import { settings } from '../../../../client/lib/settings';
8-
import { getUserId } from '../../../../client/lib/user';
9-
import { watchUser, watchUserId } from '../../../../client/meteor/user';
10-
import { Messages, Subscriptions } from '../../../../client/stores';
7+
import { getUserId, userIdStore } from '../../../../client/lib/user';
8+
import { Messages, Subscriptions, Users } from '../../../../client/stores';
119
import {
1210
hasTranslationLanguageInAttachments,
1311
hasTranslationLanguageInMessage,
@@ -18,15 +16,16 @@ import { sdk } from '../../../utils/client/lib/SDKClient';
1816
let userLanguage = 'en';
1917
let username = '';
2018

21-
Meteor.startup(() => {
22-
Tracker.autorun(() => {
23-
const user = watchUser();
24-
if (!user) return;
25-
26-
userLanguage = user.language || 'en';
27-
username = user.username || '';
28-
});
29-
});
19+
const refreshUserCache = () => {
20+
const uid = userIdStore.getState();
21+
const user = uid ? Users.use.getState().get(uid) : undefined;
22+
if (!user) return;
23+
userLanguage = user.language || 'en';
24+
username = user.username || '';
25+
};
26+
refreshUserCache();
27+
userIdStore.subscribe(refreshUserCache);
28+
Users.use.subscribe(refreshUserCache);
3029

3130
export const AutoTranslate = {
3231
initialized: false,
@@ -84,14 +83,7 @@ export const AutoTranslate = {
8483
return;
8584
}
8685

87-
Tracker.autorun(async (c) => {
88-
const uid = watchUserId();
89-
if (!settings.watch('AutoTranslate_Enabled') || !uid || !hasPermission('auto-translate')) {
90-
return;
91-
}
92-
93-
c.stop();
94-
86+
const loadProviders = async () => {
9587
try {
9688
[this.providersMetadata, this.supportedLanguages] = await Promise.all([
9789
sdk.call('autoTranslate.getProviderUiMetadata'),
@@ -101,7 +93,25 @@ export const AutoTranslate = {
10193
// Avoid unwanted error message on UI when autotranslate is disabled while fetching data
10294
console.error((e as Error).message);
10395
}
104-
});
96+
};
97+
98+
let loaded = false;
99+
const unsubs: Array<() => void> = [];
100+
const tryLoad = async () => {
101+
if (loaded) return;
102+
if (!settings.peek('AutoTranslate_Enabled') || !userIdStore.getState() || !hasPermission('auto-translate')) {
103+
return;
104+
}
105+
loaded = true;
106+
unsubs.splice(0).forEach((unsubscribe) => unsubscribe());
107+
await loadProviders();
108+
};
109+
110+
unsubs.push(userIdStore.subscribe(() => void tryLoad()));
111+
unsubs.push(settings.observe('AutoTranslate_Enabled', () => void tryLoad()));
112+
unsubs.push(PermissionsCachedStore.useReady.subscribe(() => void tryLoad()));
113+
114+
void tryLoad();
105115

106116
Subscriptions.use.subscribe(() => {
107117
mem.clear(this.findSubscriptionByRid);
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
import '../lib/MessageTypes';
22
import './OAuthProxy';
3-
import './methods/sendMessage';
Lines changed: 34 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import type { IMessage } from '@rocket.chat/core-typings';
2-
import type { ServerMethods } from '@rocket.chat/ddp-client';
32
import { clientCallbacks } from '@rocket.chat/ui-client';
4-
import { Meteor } from 'meteor/meteor';
53

64
import { onClientMessageReceived } from '../../../../client/lib/onClientMessageReceived';
75
import { settings } from '../../../../client/lib/settings';
@@ -11,40 +9,41 @@ import { Messages, Rooms } from '../../../../client/stores';
119
import { trim } from '../../../../lib/utils/stringUtils';
1210
import { t } from '../../../utils/lib/i18n';
1311

14-
Meteor.methods<ServerMethods>({
15-
async sendMessage(message) {
16-
const uid = getUserId();
17-
if (!uid || trim(message.msg) === '') {
18-
return false;
19-
}
20-
const messageAlreadyExists = message._id && Messages.state.get(message._id);
21-
if (messageAlreadyExists) {
22-
return dispatchToastMessage({ type: 'error', message: t('Message_Already_Sent') });
23-
}
24-
const user = getUser();
25-
if (!user?.username) {
26-
throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'sendMessage' });
27-
}
28-
message.ts = new Date();
29-
message.u = {
12+
export const runOptimisticSendMessage = async (
13+
message: Partial<IMessage> & { rid: IMessage['rid']; msg: IMessage['msg'] },
14+
): Promise<void> => {
15+
const uid = getUserId();
16+
if (!uid || trim(message.msg) === '') {
17+
return;
18+
}
19+
const messageAlreadyExists = message._id && Messages.state.get(message._id);
20+
if (messageAlreadyExists) {
21+
dispatchToastMessage({ type: 'error', message: t('Message_Already_Sent') });
22+
return;
23+
}
24+
const user = getUser();
25+
if (!user?.username) {
26+
return;
27+
}
28+
29+
const room = Rooms.state.get(message.rid);
30+
if (room?.federated) {
31+
return;
32+
}
33+
34+
const optimistic: IMessage = {
35+
...(message as IMessage),
36+
ts: new Date(),
37+
u: {
3038
_id: uid,
3139
username: user.username,
3240
name: user.name || '',
33-
};
34-
message.temp = true;
35-
if (settings.peek('Message_Read_Receipt_Enabled')) {
36-
message.unread = true;
37-
}
38-
39-
// If the room is federated, send the message to matrix only
40-
const room = Rooms.state.get(message.rid);
41-
if (room?.federated) {
42-
return;
43-
}
41+
},
42+
temp: true,
43+
...(settings.peek('Message_Read_Receipt_Enabled') ? { unread: true } : {}),
44+
};
4445

45-
await onClientMessageReceived(message as IMessage).then((message) => {
46-
Messages.state.store(message);
47-
return clientCallbacks.run('afterSaveMessage', message, { room, user });
48-
});
49-
},
50-
});
46+
const processed = await onClientMessageReceived(optimistic);
47+
Messages.state.store(processed);
48+
await clientCallbacks.run('afterSaveMessage', processed, { room, user });
49+
};

apps/meteor/app/livechat/client/lib/stream/queueManager.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import {
55
type IOmnichannelAgent,
66
type Serialized,
77
} from '@rocket.chat/core-typings';
8-
import { Tracker } from 'meteor/tracker';
98

109
import { useLivechatInquiryStore } from '../../../../../client/hooks/useLivechatInquiryStore';
1110
import { queryClient } from '../../../../../client/lib/queryClient';
@@ -64,8 +63,10 @@ const removeInquiry = async (inquiry: ILivechatInquiryRecord) => {
6463
return queryClient.invalidateQueries({ queryKey: ['rooms', { reference: inquiry.rid, type: 'l' }] });
6564
};
6665

66+
const INQUIRY_COUNT_SETTING = 'Livechat_guest_pool_max_number_incoming_livechats_displayed';
67+
6768
const getInquiriesFromAPI = async () => {
68-
const count = settings.peek('Livechat_guest_pool_max_number_incoming_livechats_displayed') ?? 0;
69+
const count = settings.peek<number>(INQUIRY_COUNT_SETTING) ?? 0;
6970
const { inquiries } = await sdk.rest.get('/v1/livechat/inquiries.queuedForUser', { count });
7071
return inquiries;
7172
};
@@ -140,10 +141,12 @@ const subscribe = async (userId: IOmnichannelAgent['_id']) => {
140141
const cleanDepartmentListeners = addListenerForeachDepartment(agentDepartments);
141142
const globalCleanup = addGlobalListener();
142143

143-
const computation = Tracker.autorun(async () => {
144-
const inquiriesFromAPI = await getInquiriesFromAPI();
144+
const refetchInquiries = async () => updateInquiries(await getInquiriesFromAPI());
145+
146+
await refetchInquiries();
145147

146-
await updateInquiries(inquiriesFromAPI);
148+
const unobserveInquiryCount = settings.observe(INQUIRY_COUNT_SETTING, () => {
149+
void refetchInquiries();
147150
});
148151

149152
return () => {
@@ -152,8 +155,8 @@ const subscribe = async (userId: IOmnichannelAgent['_id']) => {
152155
cleanAgentListener?.();
153156
cleanDepartmentListeners?.();
154157
globalCleanup?.();
158+
unobserveInquiryCount();
155159
departments.clear();
156-
computation.stop();
157160
};
158161
} catch (error) {
159162
dispatchToastMessage({ type: 'error', message: error });

apps/meteor/app/reactions/client/index.ts

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 60 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,81 @@
11
import type { IMessage } from '@rocket.chat/core-typings';
2-
import type { ServerMethods } from '@rocket.chat/ddp-client';
3-
import { Meteor } from 'meteor/meteor';
42

53
import { roomCoordinator } from '../../../../client/lib/rooms/roomCoordinator';
64
import { getUser, getUserId } from '../../../../client/lib/user';
75
import { Rooms, Subscriptions, Messages } from '../../../../client/stores';
86
import { emoji } from '../../../emoji/client';
97

10-
Meteor.methods<ServerMethods>({
11-
async setReaction(reaction, messageId) {
12-
if (!getUserId()) {
13-
throw new Meteor.Error(203, 'User_logged_out');
14-
}
15-
16-
const user = getUser();
8+
export const runOptimisticSetReaction = (reaction: string, messageId: IMessage['_id']): void => {
9+
if (!getUserId()) {
10+
return;
11+
}
1712

18-
if (!user?.username) {
19-
return false;
20-
}
13+
const user = getUser();
14+
if (!user?.username) {
15+
return;
16+
}
2117

22-
const message: IMessage | undefined = Messages.state.get(messageId);
23-
if (!message) {
24-
return false;
25-
}
18+
const message: IMessage | undefined = Messages.state.get(messageId);
19+
if (!message) {
20+
return;
21+
}
2622

27-
const room = Rooms.state.get(message.rid);
28-
if (!room) {
29-
return false;
30-
}
31-
32-
if (message.private) {
33-
return false;
34-
}
23+
const room = Rooms.state.get(message.rid);
24+
if (!room) {
25+
return;
26+
}
3527

36-
if (!emoji.list[reaction]) {
37-
return false;
38-
}
28+
if (message.private) {
29+
return;
30+
}
3931

40-
if (roomCoordinator.readOnly(room, user)) {
41-
return false;
42-
}
32+
if (!emoji.list[reaction]) {
33+
return;
34+
}
4335

44-
if (!Subscriptions.state.find(({ rid }) => rid === message.rid)) {
45-
return false;
46-
}
36+
if (roomCoordinator.readOnly(room, user)) {
37+
return;
38+
}
4739

48-
if (message.reactions?.[reaction] && message.reactions[reaction].usernames.indexOf(user.username) !== -1) {
49-
message.reactions[reaction].usernames.splice(message.reactions[reaction].usernames.indexOf(user.username), 1);
40+
if (!Subscriptions.state.find(({ rid }) => rid === message.rid)) {
41+
return;
42+
}
5043

51-
if (message.reactions[reaction].usernames.length === 0) {
52-
delete message.reactions[reaction];
53-
}
44+
if (message.reactions?.[reaction] && message.reactions[reaction].usernames.indexOf(user.username) !== -1) {
45+
message.reactions[reaction].usernames.splice(message.reactions[reaction].usernames.indexOf(user.username), 1);
5446

55-
if (!message.reactions || typeof message.reactions !== 'object' || Object.keys(message.reactions).length === 0) {
56-
delete message.reactions;
57-
Messages.state.update(
58-
(record) => record._id === messageId,
59-
({ reactions: _, ...record }) => record,
60-
);
61-
} else {
62-
Messages.state.update(
63-
(record) => record._id === messageId,
64-
(record) => ({ ...record, reactions: message.reactions }),
65-
);
66-
}
67-
} else {
68-
if (!message.reactions) {
69-
message.reactions = {};
70-
}
71-
if (!message.reactions[reaction]) {
72-
message.reactions[reaction] = {
73-
usernames: [],
74-
};
75-
}
76-
message.reactions[reaction].usernames.push(user.username);
47+
if (message.reactions[reaction].usernames.length === 0) {
48+
delete message.reactions[reaction];
49+
}
7750

51+
if (!message.reactions || typeof message.reactions !== 'object' || Object.keys(message.reactions).length === 0) {
52+
delete message.reactions;
7853
Messages.state.update(
7954
(record) => record._id === messageId,
80-
(record) => ({ ...record, reactions: message.reactions }),
55+
({ reactions: _, ...record }) => record,
8156
);
57+
return;
8258
}
83-
},
84-
});
59+
60+
Messages.state.update(
61+
(record) => record._id === messageId,
62+
(record) => ({ ...record, reactions: message.reactions }),
63+
);
64+
return;
65+
}
66+
67+
if (!message.reactions) {
68+
message.reactions = {};
69+
}
70+
if (!message.reactions[reaction]) {
71+
message.reactions[reaction] = {
72+
usernames: [],
73+
};
74+
}
75+
message.reactions[reaction].usernames.push(user.username);
76+
77+
Messages.state.update(
78+
(record) => record._id === messageId,
79+
(record) => ({ ...record, reactions: message.reactions }),
80+
);
81+
};

apps/meteor/app/slashcommands-join/client/client.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import type { Meteor } from 'meteor/meteor';
2-
31
import { slashCommands } from '../../utils/client/slashCommand';
42

53
slashCommands.add({
@@ -10,7 +8,7 @@ slashCommands.add({
108
permission: 'view-c-room',
119
},
1210
result(err, _result: unknown, params: Record<string, any>) {
13-
if ((err as Meteor.Error).error === 'error-user-already-in-room') {
11+
if ((err as { error?: string } | undefined)?.error === 'error-user-already-in-room') {
1412
params.cmd = 'open';
1513
params.msg.msg = params.msg.msg.replace('join', 'open');
1614
return void slashCommands.run({ command: 'open', params: params.params, message: params.msg, triggerId: '', userId: params.userId });

0 commit comments

Comments
 (0)