diff --git a/.changeset/afraid-guests-jog.md b/.changeset/afraid-guests-jog.md
deleted file mode 100644
index 420b9bb5d329..000000000000
--- a/.changeset/afraid-guests-jog.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-"@rocket.chat/meteor": minor
-"@rocket.chat/livechat": minor
----
-
-Created a `transferChat` Livechat API endpoint for transferring chats programmatically, the endpoint has all the limitations & permissions required that transferring via UI has
diff --git a/.changeset/brown-crabs-chew.md b/.changeset/brown-crabs-chew.md
new file mode 100644
index 000000000000..3291f18bf225
--- /dev/null
+++ b/.changeset/brown-crabs-chew.md
@@ -0,0 +1,13 @@
+---
+'@rocket.chat/uikit-playground': patch
+'@rocket.chat/fuselage-ui-kit': patch
+'@rocket.chat/ui-theming': patch
+'@rocket.chat/ui-video-conf': patch
+'@rocket.chat/ui-composer': patch
+'@rocket.chat/gazzodown': patch
+'@rocket.chat/ui-avatar': patch
+'@rocket.chat/ui-client': patch
+'@rocket.chat/meteor': patch
+---
+
+Bumped @rocket.chat/fuselage that fixes the Menu onPointerUp event behavior
diff --git a/.changeset/calm-tigers-peel.md b/.changeset/calm-tigers-peel.md
new file mode 100644
index 000000000000..32feed6f7107
--- /dev/null
+++ b/.changeset/calm-tigers-peel.md
@@ -0,0 +1,5 @@
+---
+"@rocket.chat/ui-kit": patch
+---
+
+fix UiKit error message: Failed to resolve module: @rocket.chat/icons
diff --git a/.changeset/chatty-hounds-hammer.md b/.changeset/chatty-hounds-hammer.md
deleted file mode 100644
index 1a2d3a7de559..000000000000
--- a/.changeset/chatty-hounds-hammer.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-"@rocket.chat/meteor": patch
-"@rocket.chat/fuselage-ui-kit": patch
----
-
-Fix validations from "UiKit" modal component
diff --git a/.changeset/chilled-yaks-beg.md b/.changeset/chilled-yaks-beg.md
deleted file mode 100644
index 670fa24887b7..000000000000
--- a/.changeset/chilled-yaks-beg.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@rocket.chat/meteor": patch
----
-
-Fixed issue in Marketplace that caused a subscription app to show incorrect modals when subscribing
diff --git a/.changeset/chilly-papayas-march.md b/.changeset/chilly-papayas-march.md
deleted file mode 100644
index a7724b126695..000000000000
--- a/.changeset/chilly-papayas-march.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@rocket.chat/meteor": patch
----
-
-Fixed SAML users' full names being updated on login regardless of the "Overwrite user fullname (use idp attribute)" setting
diff --git a/.changeset/cuddly-brooms-approve.md b/.changeset/cuddly-brooms-approve.md
deleted file mode 100644
index 24905bb91c62..000000000000
--- a/.changeset/cuddly-brooms-approve.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-"@rocket.chat/meteor": minor
-"@rocket.chat/i18n": minor
----
-
-Allows admins to customize the `Subject` field of Omnichannel email transcripts via setting. By passing a value to the setting `Custom email subject for transcript`, system will use it as the `Subject` field, unless a custom subject is passed when requesting a transcript. If there's no custom subject and setting value is empty, the current default value will be used
diff --git a/.changeset/dry-pumas-draw.md b/.changeset/dry-pumas-draw.md
deleted file mode 100644
index b66ca5157cd5..000000000000
--- a/.changeset/dry-pumas-draw.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-"@rocket.chat/meteor": patch
-"@rocket.chat/livechat": patch
----
-
-Fixed an issue that caused the widget to set the wrong department when using the setDepartment Livechat api endpoint in conjunction with a Livechat Trigger
diff --git a/.changeset/empty-readers-teach.md b/.changeset/empty-readers-teach.md
deleted file mode 100644
index b4bd075ef654..000000000000
--- a/.changeset/empty-readers-teach.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-"@rocket.chat/meteor": patch
-"@rocket.chat/tools": patch
-"@rocket.chat/account-service": patch
----
-
-Fixed an inconsistent evaluation of the `Accounts_LoginExpiration` setting over the codebase. In some places, it was being used as milliseconds while in others as days. Invalid values produced different results. A helper function was created to centralize the setting validation and the proper value being returned to avoid edge cases.
-Negative values may be saved on the settings UI panel but the code will interpret any negative, NaN or 0 value to the default expiration which is 90 days.
diff --git a/.changeset/empty-toys-smell.md b/.changeset/empty-toys-smell.md
new file mode 100644
index 000000000000..043d9c19567d
--- /dev/null
+++ b/.changeset/empty-toys-smell.md
@@ -0,0 +1,5 @@
+---
+'@rocket.chat/meteor': patch
+---
+
+Federated users can no longer be deleted.
diff --git a/.changeset/fast-buttons-shake.md b/.changeset/fast-buttons-shake.md
deleted file mode 100644
index 6281fc9941ec..000000000000
--- a/.changeset/fast-buttons-shake.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@rocket.chat/meteor': minor
----
-
-Fixed an issue where FCM actions did not respect environment's proxy settings
diff --git a/.changeset/fast-lobsters-turn.md b/.changeset/fast-lobsters-turn.md
new file mode 100644
index 000000000000..ff1d97ea7289
--- /dev/null
+++ b/.changeset/fast-lobsters-turn.md
@@ -0,0 +1,5 @@
+---
+"@rocket.chat/meteor": patch
+---
+
+Fixed an issue due to an endpoint pagination that was causing that when an agent have assigned more than 50 departments, the departments have a blank space instead of the name.
diff --git a/.changeset/fifty-mails-admire.md b/.changeset/fifty-mails-admire.md
deleted file mode 100644
index b87fd11d47ee..000000000000
--- a/.changeset/fifty-mails-admire.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-'@rocket.chat/web-ui-registration': patch
-"@rocket.chat/meteor": minor
----
-
-Login services button was not respecting the button color and text color settings. Implemented a fix to respect these settings and change the button colors accordingly.
-
-Added a warning on all settings which allow admins to change OAuth button colors, so that they can be alerted about WCAG (Web Content Accessibility Guidelines) compliance.
diff --git a/.changeset/funny-boats-guess.md b/.changeset/funny-boats-guess.md
new file mode 100644
index 000000000000..076acff98329
--- /dev/null
+++ b/.changeset/funny-boats-guess.md
@@ -0,0 +1,6 @@
+---
+"@rocket.chat/meteor": minor
+"@rocket.chat/i18n": minor
+---
+
+Added a new Audit endpoint `audit/rooms.members` that allows users with `view-members-list-all-rooms` to fetch a list of the members of any room even if the user is not part of it.
diff --git a/.changeset/funny-snails-promise.md b/.changeset/funny-snails-promise.md
deleted file mode 100644
index bdd74a60b1e9..000000000000
--- a/.changeset/funny-snails-promise.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-"@rocket.chat/meteor": patch
-"@rocket.chat/livechat": patch
----
-
-livechat `setDepartment` livechat api fixes:
-- Changing department didn't reflect on the registration form in real time
-- Changing the department mid conversation didn't transfer the chat
-- Depending on the state of the department, it couldn't be set as default
-
diff --git a/.changeset/funny-wolves-tie.md b/.changeset/funny-wolves-tie.md
deleted file mode 100644
index e2364ccb05e5..000000000000
--- a/.changeset/funny-wolves-tie.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@rocket.chat/meteor': patch
----
-
-Fixed issue where bad word filtering was not working in the UI for messages
diff --git a/.changeset/gentle-bugs-think.md b/.changeset/gentle-bugs-think.md
new file mode 100644
index 000000000000..fc4738f3043a
--- /dev/null
+++ b/.changeset/gentle-bugs-think.md
@@ -0,0 +1,5 @@
+---
+"@rocket.chat/meteor": patch
+---
+
+Prevent `processRoomAbandonment` callback from erroring out when a room was inactive during a day Business Hours was not configured for.
diff --git a/.changeset/gentle-news-wonder.md b/.changeset/gentle-news-wonder.md
new file mode 100644
index 000000000000..dd3218003d7a
--- /dev/null
+++ b/.changeset/gentle-news-wonder.md
@@ -0,0 +1,5 @@
+---
+"@rocket.chat/meteor": minor
+---
+
+Added a new 'Deactivated' tab to the users page, this tab lists users who have logged in for the first time but have been deactivated for any reason. Also added the UI code for the Active tab;
diff --git a/.changeset/gorgeous-hotels-attend.md b/.changeset/gorgeous-hotels-attend.md
new file mode 100644
index 000000000000..fd858d7ace86
--- /dev/null
+++ b/.changeset/gorgeous-hotels-attend.md
@@ -0,0 +1,5 @@
+---
+"@rocket.chat/meteor": patch
+---
+
+Stopped non channel members from dragging and dropping files in a channel they do not belong
diff --git a/.changeset/grumpy-worms-appear.md b/.changeset/grumpy-worms-appear.md
deleted file mode 100644
index fb9fab77b24c..000000000000
--- a/.changeset/grumpy-worms-appear.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@rocket.chat/i18n": patch
----
-
-Fixed wrong wording on a federation setting
diff --git a/.changeset/happy-peaches-nail.md b/.changeset/happy-peaches-nail.md
deleted file mode 100644
index 2dfb2151ced0..000000000000
--- a/.changeset/happy-peaches-nail.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@rocket.chat/meteor": patch
----
-
-Fixed issue with livechat agents not being able to leave omnichannel rooms if joining after a room has been closed by the visitor (due to race conditions)
diff --git a/.changeset/hip-queens-taste.md b/.changeset/hip-queens-taste.md
deleted file mode 100644
index f1d7bb6f3f0e..000000000000
--- a/.changeset/hip-queens-taste.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@rocket.chat/meteor": minor
----
-
-Added the possibility for apps to remove users from a room
diff --git a/.changeset/hungry-wombats-act.md b/.changeset/hungry-wombats-act.md
deleted file mode 100644
index 4e50b172e17e..000000000000
--- a/.changeset/hungry-wombats-act.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@rocket.chat/meteor": patch
----
-
-Fixed an issue where non-encrypted attachments were not being downloaded
diff --git a/.changeset/kind-drinks-joke.md b/.changeset/kind-drinks-joke.md
new file mode 100644
index 000000000000..b235f5556805
--- /dev/null
+++ b/.changeset/kind-drinks-joke.md
@@ -0,0 +1,5 @@
+---
+'@rocket.chat/meteor': patch
+---
+
+Fixed issue with asterisk-wrapped text not becoming bold when user enters profile custom status.
diff --git a/.changeset/large-geese-ring.md b/.changeset/large-geese-ring.md
new file mode 100644
index 000000000000..9b36edf1c02d
--- /dev/null
+++ b/.changeset/large-geese-ring.md
@@ -0,0 +1,5 @@
+---
+'@rocket.chat/meteor': minor
+---
+
+Replaces an outdated banner with the Bubble component in order to display retention policy warning
diff --git a/.changeset/large-vans-attack.md b/.changeset/large-vans-attack.md
deleted file mode 100644
index c1008b2ca06f..000000000000
--- a/.changeset/large-vans-attack.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@rocket.chat/meteor": patch
----
-
-fixed the contextual bar closing when editing thread messages instead of cancelling the message edit
diff --git a/.changeset/lemon-steaks-provide.md b/.changeset/lemon-steaks-provide.md
new file mode 100644
index 000000000000..29f0289419a0
--- /dev/null
+++ b/.changeset/lemon-steaks-provide.md
@@ -0,0 +1,6 @@
+---
+'@rocket.chat/i18n': minor
+'@rocket.chat/meteor': minor
+---
+
+Added an accordion for advanced settings on Create teams and channels
diff --git a/.changeset/lucky-beds-glow.md b/.changeset/lucky-beds-glow.md
deleted file mode 100644
index 3e23797025e1..000000000000
--- a/.changeset/lucky-beds-glow.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-'@rocket.chat/ui-client': minor
-'@rocket.chat/i18n': minor
-'@rocket.chat/meteor': minor
----
-
-Feature Preview: New Navigation - `Header` and `Contextualbar` size improvements consistent with the new global `NavBar`
diff --git a/.changeset/lucky-countries-look.md b/.changeset/lucky-countries-look.md
deleted file mode 100644
index 79deda53edfc..000000000000
--- a/.changeset/lucky-countries-look.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@rocket.chat/meteor': patch
----
-
-Fixed the disappearance of some settings after navigation under network latency.
diff --git a/.changeset/many-tables-love.md b/.changeset/many-tables-love.md
deleted file mode 100644
index 8f37283c6a96..000000000000
--- a/.changeset/many-tables-love.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-"@rocket.chat/meteor": minor
-"@rocket.chat/model-typings": minor
----
-
-Fixed Livechat rooms being displayed in the Engagement Dashboard's "Channels" tab
diff --git a/.changeset/mean-hairs-move.md b/.changeset/mean-hairs-move.md
deleted file mode 100644
index c92293d6ae95..000000000000
--- a/.changeset/mean-hairs-move.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@rocket.chat/meteor': minor
----
-
-Fixed an issue where adding `OVERWRITE_SETTING_` for any setting wasn't immediately taking effect sometimes, and needed a server restart to reflect.
diff --git a/.changeset/nervous-rockets-impress.md b/.changeset/nervous-rockets-impress.md
deleted file mode 100644
index 26e9276193de..000000000000
--- a/.changeset/nervous-rockets-impress.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@rocket.chat/meteor": patch
----
-
-Fixes Missing line breaks on Omnichannel Room Info Panel
diff --git a/.changeset/new-balloons-speak.md b/.changeset/new-balloons-speak.md
deleted file mode 100644
index 7d4e7cd3a57e..000000000000
--- a/.changeset/new-balloons-speak.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@rocket.chat/meteor': patch
----
-
-Fixed web client crashing on Firefox private window. Firefox disables access to service workers inside private windows. Rocket.Chat needs service workers to process E2EE encrypted files on rooms. These types of files won't be available inside private windows, but the rest of E2EE encrypted features should work normally
diff --git a/.changeset/new-mayflies-wait.md b/.changeset/new-mayflies-wait.md
new file mode 100644
index 000000000000..832db68cecd4
--- /dev/null
+++ b/.changeset/new-mayflies-wait.md
@@ -0,0 +1,5 @@
+---
+'@rocket.chat/meteor': patch
+---
+
+Deactivating users who federated will now be permanent.
diff --git a/.changeset/new-scissors-love.md b/.changeset/new-scissors-love.md
deleted file mode 100644
index fb962407b353..000000000000
--- a/.changeset/new-scissors-love.md
+++ /dev/null
@@ -1,12 +0,0 @@
----
-'@rocket.chat/omnichannel-services': minor
-'@rocket.chat/pdf-worker': minor
-'@rocket.chat/core-services': minor
-'@rocket.chat/model-typings': minor
-'@rocket.chat/i18n': minor
-'@rocket.chat/meteor': minor
----
-
-Added system messages support for Omnichannel PDF transcripts and email transcripts. Currently these transcripts don't render system messages and is shown as an empty message in PDF/email. This PR adds this support for all valid livechat system messages.
-
-Also added a new setting under transcripts, to toggle the inclusion of system messages in email and PDF transcripts.
diff --git a/.changeset/nice-laws-eat.md b/.changeset/nice-laws-eat.md
deleted file mode 100644
index e99e4f219ef9..000000000000
--- a/.changeset/nice-laws-eat.md
+++ /dev/null
@@ -1,15 +0,0 @@
----
-'rocketchat-services': minor
-'@rocket.chat/core-services': minor
-'@rocket.chat/model-typings': minor
-'@rocket.chat/ui-video-conf': minor
-'@rocket.chat/core-typings': minor
-'@rocket.chat/ui-contexts': minor
-'@rocket.chat/models': minor
-'@rocket.chat/ui-kit': minor
-'@rocket.chat/i18n': minor
-'@rocket.chat/meteor': minor
----
-
-New Feature: Video Conference Persistent Chat.
-This feature provides a discussion id for conference provider apps to store the chat messages exchanged during the conferences, so that those users may then access those messages again at any time through Rocket.Chat.
\ No newline at end of file
diff --git a/.changeset/perfect-coins-camp.md b/.changeset/perfect-coins-camp.md
deleted file mode 100644
index 4dbddf965742..000000000000
--- a/.changeset/perfect-coins-camp.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@rocket.chat/meteor": patch
----
-
-fixed an issue in the "Create discussion" form, that would have the "Create" action button disabled even though the form is prefilled when opening it from the message action
diff --git a/.changeset/polite-foxes-repair.md b/.changeset/polite-foxes-repair.md
deleted file mode 100644
index 2f524c7e5f10..000000000000
--- a/.changeset/polite-foxes-repair.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@rocket.chat/meteor': minor
----
-
-Added a method to the Apps-Engine that allows apps to read multiple messages from a room
diff --git a/.changeset/popular-bottles-visit.md b/.changeset/popular-bottles-visit.md
new file mode 100644
index 000000000000..9e44e9dd7144
--- /dev/null
+++ b/.changeset/popular-bottles-visit.md
@@ -0,0 +1,5 @@
+---
+"@rocket.chat/meteor": patch
+---
+
+Fixed an issue that caused UI to show an error when the call to get the Business Hour type from settings returned `undefined`.
diff --git a/.changeset/popular-trees-lay.md b/.changeset/popular-trees-lay.md
deleted file mode 100644
index f38ef1f92367..000000000000
--- a/.changeset/popular-trees-lay.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@rocket.chat/meteor": patch
----
-
-Removed 'Hide' option in the room menu for Omnichannel conversations.
diff --git a/.changeset/proud-waves-bathe.md b/.changeset/proud-waves-bathe.md
deleted file mode 100644
index 556fa3af80e1..000000000000
--- a/.changeset/proud-waves-bathe.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-"@rocket.chat/meteor": minor
-"@rocket.chat/model-typings": minor
----
-
-Improved Engagement Dashboard's "Channels" tab performance by not returning rooms that had no activity in the analyzed period
diff --git a/.changeset/proud-years-buy.md b/.changeset/proud-years-buy.md
new file mode 100644
index 000000000000..94f4ab0df736
--- /dev/null
+++ b/.changeset/proud-years-buy.md
@@ -0,0 +1,5 @@
+---
+'@rocket.chat/i18n': patch
+---
+
+Fixes a typo in german translation and fixes the broken hyperlink for Resend and Change Email
diff --git a/.changeset/quick-ducks-live.md b/.changeset/quick-ducks-live.md
deleted file mode 100644
index ad628c13d087..000000000000
--- a/.changeset/quick-ducks-live.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@rocket.chat/meteor": patch
----
-
-Fixed LDAP rooms, teams and roles syncs not being triggered on login even when the "Update User Data on Login" setting is enabled
diff --git a/.changeset/rare-penguins-hope.md b/.changeset/rare-penguins-hope.md
deleted file mode 100644
index 187bd9d09ddc..000000000000
--- a/.changeset/rare-penguins-hope.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-"@rocket.chat/meteor": patch
-"@rocket.chat/core-typings": patch
----
-
-Allow customFields on livechat creation bridge
diff --git a/.changeset/red-numbers-happen.md b/.changeset/red-numbers-happen.md
deleted file mode 100644
index 61cb0d2b7586..000000000000
--- a/.changeset/red-numbers-happen.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@rocket.chat/meteor": patch
----
-
-Fixed "Copy link" message action enabled in Starred and Pinned list for End to End Encrypted channels, this action is disabled now
diff --git a/.changeset/red-vans-shave.md b/.changeset/red-vans-shave.md
deleted file mode 100644
index ddf76535087e..000000000000
--- a/.changeset/red-vans-shave.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@rocket.chat/meteor": patch
----
-
-Fixed issue that caused unintentional clicks when scrolling the channels sidebar on safari/chrome in iOS
diff --git a/.changeset/rich-carpets-brush.md b/.changeset/rich-carpets-brush.md
deleted file mode 100644
index 16741e31e54a..000000000000
--- a/.changeset/rich-carpets-brush.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@rocket.chat/meteor': patch
----
-
-Fixed some anomalies related to disabled E2EE rooms. Earlier there are some weird issues with disabled E2EE rooms, this PR fixes these anomalies.
diff --git a/.changeset/rooms-table-ts.md b/.changeset/rooms-table-ts.md
new file mode 100644
index 000000000000..b5055ad26f69
--- /dev/null
+++ b/.changeset/rooms-table-ts.md
@@ -0,0 +1,5 @@
+---
+'@rocket.chat/meteor': minor
+---
+
+Add "Created at" column to admin rooms table
diff --git a/.changeset/rotten-eggs-end.md b/.changeset/rotten-eggs-end.md
deleted file mode 100644
index 7d0ad6ee5047..000000000000
--- a/.changeset/rotten-eggs-end.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-"@rocket.chat/meteor": minor
-"@rocket.chat/i18n": patch
-"@rocket.chat/ui-client": patch
----
-
-Implemented a new tab to the users page called 'Active', this tab lists all users who have logged in for the first time and are active.
diff --git a/.changeset/rude-dogs-burn.md b/.changeset/rude-dogs-burn.md
new file mode 100644
index 000000000000..e81f00782083
--- /dev/null
+++ b/.changeset/rude-dogs-burn.md
@@ -0,0 +1,5 @@
+---
+"@rocket.chat/meteor": patch
+---
+
+Fixed a behavior when updating messages that prevented the `customFields` prop from being updated if there were no changes to the `msg` property. Now, `customFields` will be always updated on message update even if `msg` doesn't change
diff --git a/.changeset/selfish-emus-sing.md b/.changeset/selfish-emus-sing.md
deleted file mode 100644
index 315d674a1857..000000000000
--- a/.changeset/selfish-emus-sing.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-"@rocket.chat/meteor": minor
-"@rocket.chat/i18n": minor
----
-
-Added account setting `Accounts_Default_User_Preferences_sidebarSectionsOrder` to allow users to reorganize sidebar sections
diff --git a/.changeset/shaggy-hats-raise.md b/.changeset/shaggy-hats-raise.md
deleted file mode 100644
index 40ee9f8fbb55..000000000000
--- a/.changeset/shaggy-hats-raise.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@rocket.chat/meteor": minor
----
-
-Added a new setting `Livechat_transcript_send_always` that allows admins to decide if email transcript should be sent all the times when a conversation is closed. This setting bypasses agent's preferences. For this setting to work, `Livechat_enable_transcript` should be off, meaning that visitors will no longer receive the option to decide if they want a transcript or not.
diff --git a/.changeset/sixty-nails-clean.md b/.changeset/sixty-nails-clean.md
deleted file mode 100644
index 7d13e02f0bd3..000000000000
--- a/.changeset/sixty-nails-clean.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@rocket.chat/meteor': patch
----
-
-Fixed an issue that prevented the option to start a discussion from being shown on the message actions
diff --git a/.changeset/smooth-lobsters-flash.md b/.changeset/smooth-lobsters-flash.md
deleted file mode 100644
index 541d5069ee9c..000000000000
--- a/.changeset/smooth-lobsters-flash.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@rocket.chat/meteor': patch
----
-
-Fix show correct user roles after updating user roles on admin edit user panel.
diff --git a/.changeset/soft-donkeys-thank.md b/.changeset/soft-donkeys-thank.md
deleted file mode 100644
index 7273ddcffca4..000000000000
--- a/.changeset/soft-donkeys-thank.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-"@rocket.chat/meteor": patch
-"@rocket.chat/mock-providers": patch
-"@rocket.chat/ui-contexts": patch
-"@rocket.chat/web-ui-registration": patch
----
-
-Fixed an issue with blocked login when dismissed 2FA modal by clicking outside of it or pressing the escape key
diff --git a/.changeset/sour-forks-breathe.md b/.changeset/sour-forks-breathe.md
deleted file mode 100644
index 2d1076845fa9..000000000000
--- a/.changeset/sour-forks-breathe.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@rocket.chat/meteor": minor
----
-
-Extended apps-engine events for users leaving a room to also fire when being removed by another user. Also added the triggering user's information to the event's context payload.
diff --git a/.changeset/spicy-kings-think.md b/.changeset/spicy-kings-think.md
new file mode 100644
index 000000000000..9e8f3648b28c
--- /dev/null
+++ b/.changeset/spicy-kings-think.md
@@ -0,0 +1,6 @@
+---
+"@rocket.chat/meteor": patch
+---
+
+Fixes multiple problems with the `processRoomAbandonment` hook. This hook is in charge of calculating the time a room has been abandoned (this means, the time that elapsed since a room was last answered by an agent until it was closed). However, when business hours were enabled and the user didn't open on one day, if an abandoned room happened to be abandoned _over_ the day there was no business hour configuration, then the process will error out.
+Additionally, the values the code was calculating were not right. When business hours are enabled, this code should only count the abandonment time _while a business hour was open_. When rooms were left abandoned for days or weeks, this will also throw an error or output an invalid count.
diff --git a/.changeset/strong-swans-double.md b/.changeset/strong-swans-double.md
new file mode 100644
index 000000000000..db521aeeef0f
--- /dev/null
+++ b/.changeset/strong-swans-double.md
@@ -0,0 +1,6 @@
+---
+'@rocket.chat/uikit-playground': minor
+'@rocket.chat/meteor': minor
+---
+
+Upgrades fuselage-toastbar version in order to add pause on hover functionality
diff --git a/.changeset/swift-maps-tickle.md b/.changeset/swift-maps-tickle.md
new file mode 100644
index 000000000000..076ead1cea4c
--- /dev/null
+++ b/.changeset/swift-maps-tickle.md
@@ -0,0 +1,9 @@
+---
+'@rocket.chat/core-services': minor
+'@rocket.chat/model-typings': minor
+'@rocket.chat/core-typings': minor
+'@rocket.chat/rest-typings': minor
+'@rocket.chat/meteor': minor
+---
+
+Added `sidepanel` field to `teams.create` and `rooms.saveRoomSettings` endpoints
diff --git a/.changeset/ten-bulldogs-clap.md b/.changeset/ten-bulldogs-clap.md
new file mode 100644
index 000000000000..15f88bb6bd97
--- /dev/null
+++ b/.changeset/ten-bulldogs-clap.md
@@ -0,0 +1,5 @@
+---
+"@rocket.chat/meteor": patch
+---
+
+fixed an issue with the "follow message" button not changing state after click
diff --git a/.changeset/thin-windows-reply.md b/.changeset/thin-windows-reply.md
deleted file mode 100644
index 1a32e1ddebfb..000000000000
--- a/.changeset/thin-windows-reply.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@rocket.chat/meteor': patch
----
-
-Fixes an issue not displaying all groups in settings list
diff --git a/.changeset/thirty-dryers-help.md b/.changeset/thirty-dryers-help.md
new file mode 100644
index 000000000000..6d9a7dc205ae
--- /dev/null
+++ b/.changeset/thirty-dryers-help.md
@@ -0,0 +1,6 @@
+---
+"@rocket.chat/meteor": patch
+"@rocket.chat/livechat": patch
+---
+
+Fixed issue where `after-registration-triggers` would show up in a page when the user was not yet registered
diff --git a/.changeset/twelve-windows-train.md b/.changeset/twelve-windows-train.md
new file mode 100644
index 000000000000..4c6ef548e650
--- /dev/null
+++ b/.changeset/twelve-windows-train.md
@@ -0,0 +1,5 @@
+---
+'@rocket.chat/meteor': patch
+---
+
+Fixed: Custom fields in extraData now correctly added to extraRoomInfo by livechat.beforeRoom callback during livechat room creation.
diff --git a/.changeset/violet-brooms-press.md b/.changeset/violet-brooms-press.md
deleted file mode 100644
index 632026d6fe2e..000000000000
--- a/.changeset/violet-brooms-press.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@rocket.chat/meteor': patch
----
-
-Security Hotfix (https://docs.rocket.chat/guides/security/security-updates)
diff --git a/.changeset/weak-insects-sort.md b/.changeset/weak-insects-sort.md
deleted file mode 100644
index cbbe7c4aa08c..000000000000
--- a/.changeset/weak-insects-sort.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@rocket.chat/meteor": patch
----
-
-Improving UX by change the position of room info actions buttons and menu order to avoid missclick in destructive actions.
diff --git a/.changeset/weak-pets-talk.md b/.changeset/weak-pets-talk.md
deleted file mode 100644
index abaa9c683d65..000000000000
--- a/.changeset/weak-pets-talk.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-'@rocket.chat/omnichannel-services': patch
-'@rocket.chat/core-services': patch
-'@rocket.chat/meteor': patch
----
-
-Reduced time on generation of PDF transcripts. Earlier Rocket.Chat was fetching the required translations everytime a PDF transcript was requested, this process was async and was being unnecessarily being performed on every pdf transcript request. This PR improves this and now the translations are loaded at the start and kept in memory to process further pdf transcripts requests. This reduces the time of asynchronously fetching translations again and again.
diff --git a/.changeset/weak-taxis-design.md b/.changeset/weak-taxis-design.md
deleted file mode 100644
index a2d435495cd7..000000000000
--- a/.changeset/weak-taxis-design.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'@rocket.chat/meteor': minor
----
-
-Added handling of attachments in Omnichannel email transcripts. Earlier attachments were being skipped and were being shown as empty space, now it should render the image attachments and should show relevant error message for unsupported attachments.
diff --git a/.changeset/weak-tigers-suffer.md b/.changeset/weak-tigers-suffer.md
deleted file mode 100644
index 91748a43c677..000000000000
--- a/.changeset/weak-tigers-suffer.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-"@rocket.chat/meteor": minor
-"@rocket.chat/model-typings": minor
-"@rocket.chat/rest-typings": minor
----
-
-Added the ability to filter chats by `queued` on the Current Chats Omnichannel page
diff --git a/.changeset/witty-bats-develop.md b/.changeset/witty-bats-develop.md
deleted file mode 100644
index 42c9409d9ef3..000000000000
--- a/.changeset/witty-bats-develop.md
+++ /dev/null
@@ -1,13 +0,0 @@
----
-"@rocket.chat/meteor": patch
-"@rocket.chat/apps": patch
-"@rocket.chat/core-services": patch
-"@rocket.chat/core-typings": patch
-"@rocket.chat/fuselage-ui-kit": patch
-"@rocket.chat/rest-typings": patch
-"@rocket.chat/ddp-streamer": patch
-"@rocket.chat/presence": patch
-"rocketchat-services": patch
----
-
-Added the `user` param to apps-engine update method call, allowing apps' new `onUpdate` hook to know who triggered the update.
diff --git a/.github/actions/build-docker/action.yml b/.github/actions/build-docker/action.yml
index 364957ecdf01..5af39b924057 100644
--- a/.github/actions/build-docker/action.yml
+++ b/.github/actions/build-docker/action.yml
@@ -17,13 +17,28 @@ inputs:
required: false
description: 'Containers to build along with Rocket.Chat'
type: string
+ turbo-cache:
+ required: false
+ description: 'Enable turbo cache'
+ default: 'true'
+ publish-image:
+ required: false
+ description: 'Publish image'
+ default: 'true'
+ setup:
+ required: false
+ description: 'Setup node.js'
+ default: 'true'
+ NPM_TOKEN:
+ required: false
+ description: 'NPM token'
runs:
using: composite
steps:
- name: Login to GitHub Container Registry
- if: (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop')
+ if: inputs.publish-image == 'true' &&(github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop')
uses: docker/login-action@v2
with:
registry: ghcr.io
@@ -31,7 +46,7 @@ runs:
password: ${{ inputs.CR_PAT }}
- name: Restore build
- uses: actions/download-artifact@v3
+ uses: actions/download-artifact@v4
with:
name: build
path: /tmp/build
@@ -42,17 +57,21 @@ runs:
cd /tmp/build
tar xzf Rocket.Chat.tar.gz
rm Rocket.Chat.tar.gz
-
- - uses: dtinth/setup-github-actions-caching-for-turbo@v1
+ - uses: rharkor/caching-for-turbo@v1.5
+ # if we are testing a PR from a fork, we already called the turbo cache at this point, so it should be false
+ if: inputs.turbo-cache == 'true'
- name: Setup NodeJS
uses: ./.github/actions/setup-node
+ if: inputs.setup == 'true'
with:
node-version: ${{ inputs.node-version }}
cache-modules: true
install: true
+ NPM_TOKEN: ${{ inputs.NPM_TOKEN }}
- run: yarn build
+ if: inputs.setup == 'true'
shell: bash
- name: Build Docker images
@@ -63,9 +82,14 @@ runs:
docker compose -f docker-compose-ci.yml build "${args[@]}"
- name: Publish Docker images to GitHub Container Registry
- if: (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop')
+ if: inputs.publish-image == 'true' && (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop')
shell: bash
run: |
args=(rocketchat ${{ inputs.build-containers }})
docker compose -f docker-compose-ci.yml push "${args[@]}"
+
+ - name: Clean up temporary files
+ shell: bash
+ run: |
+ sudo rm -rf /tmp/bundle
diff --git a/.github/actions/meteor-build/action.yml b/.github/actions/meteor-build/action.yml
index d261000ceb87..525595146700 100644
--- a/.github/actions/meteor-build/action.yml
+++ b/.github/actions/meteor-build/action.yml
@@ -13,6 +13,9 @@ inputs:
required: true
description: 'Node version'
type: string
+ NPM_TOKEN:
+ required: false
+ description: 'NPM token'
runs:
using: composite
@@ -29,6 +32,7 @@ runs:
node-version: ${{ inputs.node-version }}
cache-modules: true
install: true
+ NPM_TOKEN: ${{ inputs.NPM_TOKEN }}
# - name: Free disk space
# run: |
@@ -91,7 +95,7 @@ runs:
meteor node -v
git version
- - uses: dtinth/setup-github-actions-caching-for-turbo@v1
+ - uses: rharkor/caching-for-turbo@v1.5
- name: Translation check
shell: bash
@@ -124,7 +128,8 @@ runs:
tar czf /tmp/Rocket.Chat.tar.gz bundle
- name: Store build
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
with:
name: build
path: /tmp/Rocket.Chat.tar.gz
+ overwrite: true
diff --git a/.github/actions/setup-node/action.yml b/.github/actions/setup-node/action.yml
index caa3c63e00f0..1035e2835792 100644
--- a/.github/actions/setup-node/action.yml
+++ b/.github/actions/setup-node/action.yml
@@ -1,22 +1,27 @@
name: 'Setup Node'
+description: 'Setup NodeJS'
inputs:
node-version:
required: true
- type: string
+ description: 'Node version'
cache-modules:
required: false
- type: boolean
+ description: 'Cache node_modules'
install:
required: false
- type: boolean
+ description: 'Install dependencies'
deno-dir:
required: false
- type: string
+ description: 'Deno directory'
default: ~/.deno-cache
+ NPM_TOKEN:
+ required: false
+ description: 'NPM token'
outputs:
node-version:
+ description: 'Node version'
value: ${{ steps.node-version.outputs.node-version }}
runs:
@@ -32,6 +37,7 @@ runs:
uses: actions/cache@v3
with:
path: |
+ .turbo/cache
node_modules
${{ env.DENO_DIR }}
apps/meteor/node_modules
@@ -48,6 +54,13 @@ runs:
node-version: ${{ inputs.node-version }}
cache: 'yarn'
+ - name: yarn login
+ shell: bash
+ if: inputs.NPM_TOKEN
+ run: |
+ echo "//registry.npmjs.org/:_authToken=${{ inputs.NPM_TOKEN }}" > ~/.npmrc
+
- name: yarn install
+ if: inputs.install
shell: bash
run: yarn
diff --git a/.github/workflows/ci-code-check.yml b/.github/workflows/ci-code-check.yml
index 75deb399d2f2..af50b3230ba7 100644
--- a/.github/workflows/ci-code-check.yml
+++ b/.github/workflows/ci-code-check.yml
@@ -35,6 +35,7 @@ jobs:
node-version: ${{ inputs.node-version }}
cache-modules: true
install: true
+ NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
# - name: Free disk space
# run: |
@@ -42,7 +43,7 @@ jobs:
# docker rmi $(docker image ls -aq)
# df -h
- - uses: dtinth/setup-github-actions-caching-for-turbo@v1
+ - uses: rharkor/caching-for-turbo@v1.5
- name: Cache TypeCheck
uses: actions/cache@v3
diff --git a/.github/workflows/ci-test-e2e.yml b/.github/workflows/ci-test-e2e.yml
index 6ac9d751fc7a..e6c02b7b6417 100644
--- a/.github/workflows/ci-test-e2e.yml
+++ b/.github/workflows/ci-test-e2e.yml
@@ -130,16 +130,24 @@ jobs:
node-version: ${{ inputs.node-version }}
cache-modules: true
install: true
+ NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
+ - uses: rharkor/caching-for-turbo@v1.5
+
+ - run: yarn build
# if we are testing a PR from a fork, we need to build the docker image at this point
- uses: ./.github/actions/build-docker
- if: github.event.pull_request.head.repo.full_name != github.repository
+ if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository
with:
CR_USER: ${{ secrets.CR_USER }}
CR_PAT: ${{ secrets.CR_PAT }}
node-version: ${{ inputs.node-version }}
-
- - uses: dtinth/setup-github-actions-caching-for-turbo@v1
+ # we already called the turbo cache at this point, so it should be false
+ turbo-cache: false
+ # the same reason we need to rebuild the docker image at this point is the reason we dont want to publish it
+ publish-image: false
+ setup: false
+ NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Start httpbin container and wait for it to be ready
if: inputs.type == 'api'
@@ -159,8 +167,6 @@ jobs:
exit 1
fi
- - run: yarn build
-
- name: Prepare code coverage directory
if: inputs.release == 'ee'
run: |
@@ -221,6 +227,8 @@ jobs:
sleep 10
done;
+ - name: Remove unused Docker images
+ run: docker system prune -af
- name: E2E Test API
if: inputs.type == 'api'
working-directory: ./apps/meteor
@@ -281,9 +289,9 @@ jobs:
- name: Store playwright test trace
if: inputs.type == 'ui' && always()
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
with:
- name: playwright-test-trace${{ inputs.release }}
+ name: playwright-test-trace-${{ matrix.mongodb-version }}-${{ matrix.shard }}
path: ./apps/meteor/tests/e2e/.playwright*
- name: Show server logs if E2E test failed
@@ -314,14 +322,14 @@ jobs:
- name: Store e2e-api-ee-coverage
if: inputs.type == 'api' && inputs.release == 'ee'
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
with:
- name: e2e-api-ee-coverage
+ name: e2e-api-ee-coverage-${{ matrix.mongodb-version }}-${{ matrix.shard }}
path: /tmp/coverage
- name: Store e2e-ee-coverage
if: inputs.type == 'ui' && inputs.release == 'ee'
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
with:
- name: e2e-ee-coverage
+ name: e2e-ee-coverage-${{ matrix.mongodb-version }}-${{ matrix.shard }}
path: ./apps/meteor/coverage*
diff --git a/.github/workflows/ci-test-unit.yml b/.github/workflows/ci-test-unit.yml
index bfb22ffa4e73..840808ff5e31 100644
--- a/.github/workflows/ci-test-unit.yml
+++ b/.github/workflows/ci-test-unit.yml
@@ -39,8 +39,9 @@ jobs:
node-version: ${{ inputs.node-version }}
cache-modules: true
install: true
+ NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
- - uses: dtinth/setup-github-actions-caching-for-turbo@v1
+ - uses: rharkor/caching-for-turbo@v1.5
- name: Unit Test
run: yarn testunit
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 411aa2cc5b1a..514dd6d1c518 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -152,6 +152,7 @@ jobs:
node-version: ${{ needs.release-versions.outputs.node-version }}
cache-modules: true
install: true
+ NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Cache vite
uses: actions/cache@v3
@@ -161,7 +162,7 @@ jobs:
restore-keys: |
vite-local-cache-${{ runner.os }}-
- - uses: dtinth/setup-github-actions-caching-for-turbo@v1
+ - uses: rharkor/caching-for-turbo@v1.5
- name: Build Rocket.Chat Packages
run: yarn build
@@ -253,6 +254,7 @@ jobs:
node-version: ${{ needs.release-versions.outputs.node-version }}
platform: ${{ matrix.platform }}
build-containers: ${{ matrix.platform == 'alpine' && 'authorization-service account-service ddp-streamer-service presence-service stream-hub-service queue-worker-service omnichannel-transcript-service' || '' }}
+ NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
build-gh-docker:
name: đĸ Build Docker Images for Production
@@ -280,6 +282,7 @@ jobs:
node-version: ${{ needs.release-versions.outputs.node-version }}
platform: ${{ matrix.platform }}
build-containers: ${{ matrix.platform == 'alpine' && 'authorization-service account-service ddp-streamer-service presence-service stream-hub-service queue-worker-service omnichannel-transcript-service' || '' }}
+ NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Rename official Docker tag to GitHub Container Registry
if: matrix.platform == 'official'
@@ -492,7 +495,7 @@ jobs:
ref: ${{ github.ref }}
- name: Restore build
- uses: actions/download-artifact@v3
+ uses: actions/download-artifact@v4
with:
name: build
path: /tmp/build
@@ -540,7 +543,7 @@ jobs:
- uses: actions/checkout@v4
- name: Restore build
- uses: actions/download-artifact@v3
+ uses: actions/download-artifact@v4
with:
name: build
path: /tmp/build
@@ -560,6 +563,7 @@ jobs:
release: preview
username: ${{ secrets.CR_USER }}
password: ${{ secrets.CR_PAT }}
+ NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
docker-image-publish:
name: đ Publish Docker Image (main)
@@ -576,13 +580,13 @@ jobs:
steps:
- name: Login to DockerHub
- uses: docker/login-action@v2
+ uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USER }}
password: ${{ secrets.DOCKER_PASS }}
- name: Login to GitHub Container Registry
- uses: docker/login-action@v2
+ uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ secrets.CR_USER }}
@@ -683,13 +687,13 @@ jobs:
steps:
- name: Login to DockerHub
- uses: docker/login-action@v2
+ uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USER }}
password: ${{ secrets.DOCKER_PASS }}
- name: Login to GitHub Container Registry
- uses: docker/login-action@v2
+ uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ secrets.CR_USER }}
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 483b404a6dc8..202a02dd7785 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -26,7 +26,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
- uses: github/codeql-action/init@v2
+ uses: github/codeql-action/init@v3
# Override language selection by uncommenting this and choosing your languages
with:
languages: javascript
@@ -34,7 +34,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
- uses: github/codeql-action/autobuild@v2
+ uses: github/codeql-action/autobuild@v3
# âšī¸ Command-line programs to run using the OS shell.
# đ https://git.io/JvXDl
@@ -48,4 +48,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v2
+ uses: github/codeql-action/analyze@v3
diff --git a/.github/workflows/new-release.yml b/.github/workflows/new-release.yml
index f10578d5879f..b2eae5d90b92 100644
--- a/.github/workflows/new-release.yml
+++ b/.github/workflows/new-release.yml
@@ -37,8 +37,9 @@ jobs:
node-version: 14.21.3
cache-modules: true
install: true
+ NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
- - uses: dtinth/setup-github-actions-caching-for-turbo@v1
+ - uses: rharkor/caching-for-turbo@v1.5
- name: Build packages
run: yarn build
diff --git a/.github/workflows/pr-title-checker.yml b/.github/workflows/pr-title-checker.yml
index bc9d1f042d58..d8f6db97c455 100644
--- a/.github/workflows/pr-title-checker.yml
+++ b/.github/workflows/pr-title-checker.yml
@@ -12,6 +12,6 @@ jobs:
check:
runs-on: ubuntu-latest
steps:
- - uses: thehanimo/pr-title-checker@v1.4.1
+ - uses: thehanimo/pr-title-checker@v1.4.2
with:
GITHUB_TOKEN: ${{ secrets.RC_TITLE_CHECKER }}
diff --git a/.github/workflows/pr-update-description.yml b/.github/workflows/pr-update-description.yml
index 71b4ffeda801..084f2a383480 100644
--- a/.github/workflows/pr-update-description.yml
+++ b/.github/workflows/pr-update-description.yml
@@ -24,8 +24,9 @@ jobs:
node-version: 14.21.3
cache-modules: true
install: true
+ NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
- - uses: dtinth/setup-github-actions-caching-for-turbo@v1
+ - uses: rharkor/caching-for-turbo@v1.5
- name: Build packages
run: yarn build
@@ -36,4 +37,3 @@ jobs:
action: update-pr-description
env:
GITHUB_TOKEN: ${{ secrets.CI_PAT }}
-
diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml
index e133a3153722..3f2067ac7ec3 100644
--- a/.github/workflows/publish-release.yml
+++ b/.github/workflows/publish-release.yml
@@ -27,8 +27,9 @@ jobs:
node-version: 14.21.3
cache-modules: true
install: true
+ NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
- - uses: dtinth/setup-github-actions-caching-for-turbo@v1
+ - uses: rharkor/caching-for-turbo@v1.5
- name: Build packages
run: yarn build
diff --git a/.github/workflows/update-version-durability.yml b/.github/workflows/update-version-durability.yml
index e52b4870b369..90c835577dc1 100644
--- a/.github/workflows/update-version-durability.yml
+++ b/.github/workflows/update-version-durability.yml
@@ -17,7 +17,7 @@ jobs:
- uses: actions/checkout@v4
- name: Use Node.js
- uses: actions/setup-node@v3.7.0
+ uses: actions/setup-node@v4.0.3
with:
node-version: '20.15.1'
diff --git a/_templates/package/new/jest.config.ts.t b/_templates/package/new/jest.config.ts.t
new file mode 100644
index 000000000000..c18c8ae02465
--- /dev/null
+++ b/_templates/package/new/jest.config.ts.t
@@ -0,0 +1,6 @@
+import server from '@rocket.chat/jest-presets/server';
+import type { Config } from 'jest';
+
+export default {
+ preset: server.preset,
+} satisfies Config;
diff --git a/_templates/package/new/package.json.ejs.t b/_templates/package/new/package.json.ejs.t
index 950e5cb2bf62..6bee52f55927 100644
--- a/_templates/package/new/package.json.ejs.t
+++ b/_templates/package/new/package.json.ejs.t
@@ -7,11 +7,11 @@ to: packages/<%= name %>/package.json
"version": "0.0.1",
"private": true,
"devDependencies": {
- "@types/jest": "~29.5.3",
+ "@rocket.chat/jest-presets": "workspace:~",
+ "@types/jest": "~29.5.12",
"eslint": "~8.45.0",
- "jest": "~29.6.1",
- "ts-jest": "~29.0.5",
- "typescript": "~5.1.6"
+ "jest": "~29.7.0",
+ "typescript": "~5.3.3"
},
"scripts": {
"lint": "eslint --ext .js,.jsx,.ts,.tsx .",
diff --git a/_templates/package/new/tsconfig.json.ejs.t b/_templates/package/new/tsconfig.json.ejs.t
index 3e192c674d1b..399544502ed0 100644
--- a/_templates/package/new/tsconfig.json.ejs.t
+++ b/_templates/package/new/tsconfig.json.ejs.t
@@ -2,10 +2,10 @@
to: packages/<%= name %>/tsconfig.json
---
{
- "extends": "../../tsconfig.base.client.json",
+ "extends": "../../tsconfig.base.server.json",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./dist"
},
- "include": ["./src/**/*"]
+ "include": ["./src/**/*"],
}
diff --git a/apps/meteor/.meteorMocks/index.ts b/apps/meteor/.meteorMocks/index.ts
deleted file mode 100644
index e70ffa7f7c46..000000000000
--- a/apps/meteor/.meteorMocks/index.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-import sinon from 'sinon';
-
-export const Meteor = {
- loginWithSamlToken: sinon.stub(),
-};
diff --git a/apps/meteor/.mocharc.client.js b/apps/meteor/.mocharc.client.js
deleted file mode 100644
index cf339a420378..000000000000
--- a/apps/meteor/.mocharc.client.js
+++ /dev/null
@@ -1,42 +0,0 @@
-'use strict';
-
-/**
- * Mocha configuration for client-side unit and integration tests.
- */
-
-const base = require('./.mocharc.base.json');
-
-/**
- * Mocha will run `ts-node` without doing type checking to speed-up the tests. It should be fine as `npm run typecheck`
- * covers test files too.
- */
-
-Object.assign(
- process.env,
- {
- TS_NODE_FILES: true,
- TS_NODE_TRANSPILE_ONLY: true,
- },
- process.env,
-);
-
-module.exports = {
- ...base, // see https://github.com/mochajs/mocha/issues/3916
- require: [
- ...base.require,
- './tests/setup/registerWebApiMocks.ts',
- './tests/setup/hoistedReact.ts',
- './tests/setup/cleanupTestingLibrary.ts',
- ],
- reporter: 'dot',
- timeout: 5000,
- exit: false,
- slow: 200,
- spec: [
- 'tests/unit/client/sidebar/**/*.spec.{ts,tsx}',
- 'tests/unit/client/components/**/*.spec.{ts,tsx}',
- 'tests/unit/client/lib/**/*.spec.{ts,tsx}',
- 'tests/unit/lib/**/*.tests.ts',
- 'tests/unit/client/**/*.test.ts',
- ],
-};
diff --git a/apps/meteor/CHANGELOG.md b/apps/meteor/CHANGELOG.md
index 75ffb7f02d7a..f466c34da838 100644
--- a/apps/meteor/CHANGELOG.md
+++ b/apps/meteor/CHANGELOG.md
@@ -1,5 +1,516 @@
# @rocket.chat/meteor
+## 6.11.0
+
+### Minor Changes
+
+- ([#32498](https://github.com/RocketChat/Rocket.Chat/pull/32498)) Created a `transferChat` Livechat API endpoint for transferring chats programmatically, the endpoint has all the limitations & permissions required that transferring via UI has
+
+- ([#32792](https://github.com/RocketChat/Rocket.Chat/pull/32792)) Allows admins to customize the `Subject` field of Omnichannel email transcripts via setting. By passing a value to the setting `Custom email subject for transcript`, system will use it as the `Subject` field, unless a custom subject is passed when requesting a transcript. If there's no custom subject and setting value is empty, the current default value will be used
+
+- ([#32739](https://github.com/RocketChat/Rocket.Chat/pull/32739)) Fixed an issue where FCM actions did not respect environment's proxy settings
+
+- ([#32706](https://github.com/RocketChat/Rocket.Chat/pull/32706)) Added the possibility for apps to remove users from a room
+
+- ([#32517](https://github.com/RocketChat/Rocket.Chat/pull/32517)) Feature Preview: New Navigation - `Header` and `Contextualbar` size improvements consistent with the new global `NavBar`
+
+- ([#32493](https://github.com/RocketChat/Rocket.Chat/pull/32493)) Fixed Livechat rooms being displayed in the Engagement Dashboard's "Channels" tab
+
+- ([#32742](https://github.com/RocketChat/Rocket.Chat/pull/32742)) Fixed an issue where adding `OVERWRITE_SETTING_` for any setting wasn't immediately taking effect sometimes, and needed a server restart to reflect.
+
+- ([#32752](https://github.com/RocketChat/Rocket.Chat/pull/32752)) Added system messages support for Omnichannel PDF transcripts and email transcripts. Currently these transcripts don't render system messages and is shown as an empty message in PDF/email. This PR adds this support for all valid livechat system messages.
+
+ Also added a new setting under transcripts, to toggle the inclusion of system messages in email and PDF transcripts.
+
+- ([#32793](https://github.com/RocketChat/Rocket.Chat/pull/32793)) New Feature: Video Conference Persistent Chat.
+ This feature provides a discussion id for conference provider apps to store the chat messages exchanged during the conferences, so that those users may then access those messages again at any time through Rocket.Chat.
+- ([#32176](https://github.com/RocketChat/Rocket.Chat/pull/32176)) Added a method to the Apps-Engine that allows apps to read multiple messages from a room
+
+- ([#32493](https://github.com/RocketChat/Rocket.Chat/pull/32493)) Improved Engagement Dashboard's "Channels" tab performance by not returning rooms that had no activity in the analyzed period
+
+- ([#32024](https://github.com/RocketChat/Rocket.Chat/pull/32024)) Implemented a new tab to the users page called 'Active', this tab lists all users who have logged in for the first time and are active.
+
+- ([#32744](https://github.com/RocketChat/Rocket.Chat/pull/32744)) Added account setting `Accounts_Default_User_Preferences_sidebarSectionsOrder` to allow users to reorganize sidebar sections
+
+- ([#32820](https://github.com/RocketChat/Rocket.Chat/pull/32820)) Added a new setting `Livechat_transcript_send_always` that allows admins to decide if email transcript should be sent all the times when a conversation is closed. This setting bypasses agent's preferences. For this setting to work, `Livechat_enable_transcript` should be off, meaning that visitors will no longer receive the option to decide if they want a transcript or not.
+
+- ([#32724](https://github.com/RocketChat/Rocket.Chat/pull/32724)) Extended apps-engine events for users leaving a room to also fire when being removed by another user. Also added the triggering user's information to the event's context payload.
+
+- ([#32777](https://github.com/RocketChat/Rocket.Chat/pull/32777)) Added handling of attachments in Omnichannel email transcripts. Earlier attachments were being skipped and were being shown as empty space, now it should render the image attachments and should show relevant error message for unsupported attachments.
+
+- ([#32800](https://github.com/RocketChat/Rocket.Chat/pull/32800)) Added the ability to filter chats by `queued` on the Current Chats Omnichannel page
+
+### Patch Changes
+
+- Bump @rocket.chat/meteor version.
+
+- Bump @rocket.chat/meteor version.
+
+- Bump @rocket.chat/meteor version.
+
+- Bump @rocket.chat/meteor version.
+
+- Bump @rocket.chat/meteor version.
+
+- Bump @rocket.chat/meteor version.
+
+- Bump @rocket.chat/meteor version.
+
+- ([#32679](https://github.com/RocketChat/Rocket.Chat/pull/32679)) Fix validations from "UiKit" modal component
+
+- ([#32730](https://github.com/RocketChat/Rocket.Chat/pull/32730)) Fixed issue in Marketplace that caused a subscription app to show incorrect modals when subscribing
+
+- ([#32628](https://github.com/RocketChat/Rocket.Chat/pull/32628)) Fixed SAML users' full names being updated on login regardless of the "Overwrite user fullname (use idp attribute)" setting
+
+- ([#32692](https://github.com/RocketChat/Rocket.Chat/pull/32692)) Fixed an issue that caused the widget to set the wrong department when using the setDepartment Livechat api endpoint in conjunction with a Livechat Trigger
+
+- ([#32527](https://github.com/RocketChat/Rocket.Chat/pull/32527)) Fixed an inconsistent evaluation of the `Accounts_LoginExpiration` setting over the codebase. In some places, it was being used as milliseconds while in others as days. Invalid values produced different results. A helper function was created to centralize the setting validation and the proper value being returned to avoid edge cases.
+ Negative values may be saved on the settings UI panel but the code will interpret any negative, NaN or 0 value to the default expiration which is 90 days.
+- ([#32626](https://github.com/RocketChat/Rocket.Chat/pull/32626)) livechat `setDepartment` livechat api fixes:
+ - Changing department didn't reflect on the registration form in real time
+ - Changing the department mid conversation didn't transfer the chat
+ - Depending on the state of the department, it couldn't be set as default
+- ([#32810](https://github.com/RocketChat/Rocket.Chat/pull/32810)) Fixed issue where bad word filtering was not working in the UI for messages
+
+- ([#32707](https://github.com/RocketChat/Rocket.Chat/pull/32707)) Fixed issue with livechat agents not being able to leave omnichannel rooms if joining after a room has been closed by the visitor (due to race conditions)
+
+- ([#32837](https://github.com/RocketChat/Rocket.Chat/pull/32837)) Fixed an issue where non-encrypted attachments were not being downloaded
+
+- ([#32861](https://github.com/RocketChat/Rocket.Chat/pull/32861)) fixed the contextual bar closing when editing thread messages instead of cancelling the message edit
+
+- ([#32713](https://github.com/RocketChat/Rocket.Chat/pull/32713)) Fixed the disappearance of some settings after navigation under network latency.
+
+- ([#32592](https://github.com/RocketChat/Rocket.Chat/pull/32592)) Fixes Missing line breaks on Omnichannel Room Info Panel
+
+- ([#32807](https://github.com/RocketChat/Rocket.Chat/pull/32807)) Fixed web client crashing on Firefox private window. Firefox disables access to service workers inside private windows. Rocket.Chat needs service workers to process E2EE encrypted files on rooms. These types of files won't be available inside private windows, but the rest of E2EE encrypted features should work normally
+
+- ([#32864](https://github.com/RocketChat/Rocket.Chat/pull/32864)) fixed an issue in the "Create discussion" form, that would have the "Create" action button disabled even though the form is prefilled when opening it from the message action
+
+- ([#32691](https://github.com/RocketChat/Rocket.Chat/pull/32691)) Removed 'Hide' option in the room menu for Omnichannel conversations.
+
+- ([#32445](https://github.com/RocketChat/Rocket.Chat/pull/32445)) Fixed LDAP rooms, teams and roles syncs not being triggered on login even when the "Update User Data on Login" setting is enabled
+
+- ([#32328](https://github.com/RocketChat/Rocket.Chat/pull/32328)) Allow customFields on livechat creation bridge
+
+- ([#32803](https://github.com/RocketChat/Rocket.Chat/pull/32803)) Fixed "Copy link" message action enabled in Starred and Pinned list for End to End Encrypted channels, this action is disabled now
+
+- ([#32769](https://github.com/RocketChat/Rocket.Chat/pull/32769)) Fixed issue that caused unintentional clicks when scrolling the channels sidebar on safari/chrome in iOS
+
+- ([#32857](https://github.com/RocketChat/Rocket.Chat/pull/32857)) Fixed some anomalies related to disabled E2EE rooms. Earlier there are some weird issues with disabled E2EE rooms, this PR fixes these anomalies.
+
+- ([#32765](https://github.com/RocketChat/Rocket.Chat/pull/32765)) Fixed an issue that prevented the option to start a discussion from being shown on the message actions
+
+- ([#32671](https://github.com/RocketChat/Rocket.Chat/pull/32671)) Fix show correct user roles after updating user roles on admin edit user panel.
+
+- ([#32482](https://github.com/RocketChat/Rocket.Chat/pull/32482)) Fixed an issue with blocked login when dismissed 2FA modal by clicking outside of it or pressing the escape key
+
+- ([#32804](https://github.com/RocketChat/Rocket.Chat/pull/32804)) Fixes an issue not displaying all groups in settings list
+
+- ([#32815](https://github.com/RocketChat/Rocket.Chat/pull/32815)) Security Hotfix (https://docs.rocket.chat/guides/security/security-updates)
+
+- ([#32632](https://github.com/RocketChat/Rocket.Chat/pull/32632)) Improving UX by change the position of room info actions buttons and menu order to avoid missclick in destructive actions.
+
+- ([#32752](https://github.com/RocketChat/Rocket.Chat/pull/32752)) Reduced time on generation of PDF transcripts. Earlier Rocket.Chat was fetching the required translations everytime a PDF transcript was requested, this process was async and was being unnecessarily being performed on every pdf transcript request. This PR improves this and now the translations are loaded at the start and kept in memory to process further pdf transcripts requests. This reduces the time of asynchronously fetching translations again and again.
+
+- ([#32719](https://github.com/RocketChat/Rocket.Chat/pull/32719)) Added the `user` param to apps-engine update method call, allowing apps' new `onUpdate` hook to know who triggered the update.
+
+- Updated dependencies [88e5219bd2, b4bbcbfc9a, 8fc6ca8b4e, 25da5280a5, 1b7b1161cf, 439faa87d3, 03c8b066f9, 2d89a0c448, 439faa87d3, 24f7df4894, 3ffe4a2944, 3b4b19cfc5, 4e8aa575a6, 03c8b066f9, 264d7d5496, b8e5887fb9]:
+
+ - @rocket.chat/fuselage-ui-kit@9.0.0
+ - @rocket.chat/i18n@0.6.0
+ - @rocket.chat/tools@0.2.2
+ - @rocket.chat/ui-client@9.0.0
+ - @rocket.chat/model-typings@0.6.0
+ - @rocket.chat/omnichannel-services@0.3.0
+ - @rocket.chat/pdf-worker@0.2.0
+ - @rocket.chat/core-services@0.5.0
+ - @rocket.chat/ui-video-conf@9.0.0
+ - @rocket.chat/core-typings@6.11.0
+ - @rocket.chat/ui-contexts@9.0.0
+ - @rocket.chat/models@0.2.0
+ - @rocket.chat/ui-kit@0.36.0
+ - @rocket.chat/web-ui-registration@9.0.0
+ - @rocket.chat/rest-typings@6.11.0
+ - @rocket.chat/apps@0.1.3
+ - @rocket.chat/presence@0.2.3
+ - @rocket.chat/gazzodown@9.0.0
+ - @rocket.chat/api-client@0.2.3
+ - @rocket.chat/license@0.2.3
+ - @rocket.chat/cron@0.1.3
+ - @rocket.chat/ui-theming@0.2.0
+ - @rocket.chat/ui-avatar@5.0.0
+ - @rocket.chat/instance-status@0.1.3
+ - @rocket.chat/server-cloud-communication@0.0.2
+
+
+## 6.11.0-rc.6
+
+### Patch Changes
+
+- Bump @rocket.chat/meteor version.
+
+- Updated dependencies []:
+
+ - @rocket.chat/core-typings@6.11.0-rc.6
+ - @rocket.chat/rest-typings@6.11.0-rc.6
+ - @rocket.chat/api-client@0.2.3-rc.6
+ - @rocket.chat/license@0.2.3-rc.6
+ - @rocket.chat/omnichannel-services@0.3.0-rc.6
+ - @rocket.chat/pdf-worker@0.2.0-rc.6
+ - @rocket.chat/presence@0.2.3-rc.6
+ - @rocket.chat/apps@0.1.3-rc.6
+ - @rocket.chat/core-services@0.5.0-rc.6
+ - @rocket.chat/cron@0.1.3-rc.6
+ - @rocket.chat/fuselage-ui-kit@9.0.0-rc.6
+ - @rocket.chat/gazzodown@9.0.0-rc.6
+ - @rocket.chat/model-typings@0.6.0-rc.6
+ - @rocket.chat/ui-contexts@9.0.0-rc.6
+ - @rocket.chat/server-cloud-communication@0.0.2
+ - @rocket.chat/models@0.2.0-rc.6
+ - @rocket.chat/ui-theming@0.2.0
+ - @rocket.chat/ui-avatar@5.0.0-rc.6
+ - @rocket.chat/ui-client@9.0.0-rc.6
+ - @rocket.chat/ui-video-conf@9.0.0-rc.6
+ - @rocket.chat/web-ui-registration@9.0.0-rc.6
+ - @rocket.chat/instance-status@0.1.3-rc.6
+
+
+## 6.11.0-rc.5
+
+### Patch Changes
+
+- Bump @rocket.chat/meteor version.
+
+- Updated dependencies []:
+
+ - @rocket.chat/core-typings@6.11.0-rc.5
+ - @rocket.chat/rest-typings@6.11.0-rc.5
+ - @rocket.chat/api-client@0.2.3-rc.5
+ - @rocket.chat/license@0.2.3-rc.5
+ - @rocket.chat/omnichannel-services@0.3.0-rc.5
+ - @rocket.chat/pdf-worker@0.2.0-rc.5
+ - @rocket.chat/presence@0.2.3-rc.5
+ - @rocket.chat/apps@0.1.3-rc.5
+ - @rocket.chat/core-services@0.5.0-rc.5
+ - @rocket.chat/cron@0.1.3-rc.5
+ - @rocket.chat/fuselage-ui-kit@9.0.0-rc.5
+ - @rocket.chat/gazzodown@9.0.0-rc.5
+ - @rocket.chat/model-typings@0.6.0-rc.5
+ - @rocket.chat/ui-contexts@9.0.0-rc.5
+ - @rocket.chat/server-cloud-communication@0.0.2
+ - @rocket.chat/models@0.2.0-rc.5
+ - @rocket.chat/ui-theming@0.2.0
+ - @rocket.chat/ui-avatar@5.0.0-rc.5
+ - @rocket.chat/ui-client@9.0.0-rc.5
+ - @rocket.chat/ui-video-conf@9.0.0-rc.5
+ - @rocket.chat/web-ui-registration@9.0.0-rc.5
+ - @rocket.chat/instance-status@0.1.3-rc.5
+
+
+## 6.11.0-rc.4
+
+### Patch Changes
+
+- Bump @rocket.chat/meteor version.
+
+- Updated dependencies []:
+
+ - @rocket.chat/core-typings@6.11.0-rc.4
+ - @rocket.chat/rest-typings@6.11.0-rc.4
+ - @rocket.chat/api-client@0.2.3-rc.4
+ - @rocket.chat/license@0.2.3-rc.4
+ - @rocket.chat/omnichannel-services@0.3.0-rc.4
+ - @rocket.chat/pdf-worker@0.2.0-rc.4
+ - @rocket.chat/presence@0.2.3-rc.4
+ - @rocket.chat/apps@0.1.3-rc.4
+ - @rocket.chat/core-services@0.5.0-rc.4
+ - @rocket.chat/cron@0.1.3-rc.4
+ - @rocket.chat/fuselage-ui-kit@9.0.0-rc.4
+ - @rocket.chat/gazzodown@9.0.0-rc.4
+ - @rocket.chat/model-typings@0.6.0-rc.4
+ - @rocket.chat/ui-contexts@9.0.0-rc.4
+ - @rocket.chat/server-cloud-communication@0.0.2
+ - @rocket.chat/models@0.2.0-rc.4
+ - @rocket.chat/ui-theming@0.2.0
+ - @rocket.chat/ui-avatar@5.0.0-rc.4
+ - @rocket.chat/ui-client@9.0.0-rc.4
+ - @rocket.chat/ui-video-conf@9.0.0-rc.4
+ - @rocket.chat/web-ui-registration@9.0.0-rc.4
+ - @rocket.chat/instance-status@0.1.3-rc.4
+
+
+## 6.11.0-rc.3
+
+### Patch Changes
+
+- Bump @rocket.chat/meteor version.
+
+- Updated dependencies []:
+
+ - @rocket.chat/core-typings@6.11.0-rc.3
+ - @rocket.chat/rest-typings@6.11.0-rc.3
+ - @rocket.chat/api-client@0.2.3-rc.3
+ - @rocket.chat/license@0.2.3-rc.3
+ - @rocket.chat/omnichannel-services@0.3.0-rc.3
+ - @rocket.chat/pdf-worker@0.2.0-rc.3
+ - @rocket.chat/presence@0.2.3-rc.3
+ - @rocket.chat/apps@0.1.3-rc.3
+ - @rocket.chat/core-services@0.5.0-rc.3
+ - @rocket.chat/cron@0.1.3-rc.3
+ - @rocket.chat/fuselage-ui-kit@9.0.0-rc.3
+ - @rocket.chat/gazzodown@9.0.0-rc.3
+ - @rocket.chat/model-typings@0.6.0-rc.3
+ - @rocket.chat/ui-contexts@9.0.0-rc.3
+ - @rocket.chat/server-cloud-communication@0.0.2
+ - @rocket.chat/models@0.2.0-rc.3
+ - @rocket.chat/ui-theming@0.2.0
+ - @rocket.chat/ui-avatar@5.0.0-rc.3
+ - @rocket.chat/ui-client@9.0.0-rc.3
+ - @rocket.chat/ui-video-conf@9.0.0-rc.3
+ - @rocket.chat/web-ui-registration@9.0.0-rc.3
+ - @rocket.chat/instance-status@0.1.3-rc.3
+
+
+## 6.11.0-rc.2
+
+### Patch Changes
+
+- Bump @rocket.chat/meteor version.
+
+- Updated dependencies []:
+
+ - @rocket.chat/core-typings@6.11.0-rc.2
+ - @rocket.chat/rest-typings@6.11.0-rc.2
+ - @rocket.chat/api-client@0.2.3-rc.2
+ - @rocket.chat/license@0.2.3-rc.2
+ - @rocket.chat/omnichannel-services@0.3.0-rc.2
+ - @rocket.chat/pdf-worker@0.2.0-rc.2
+ - @rocket.chat/presence@0.2.3-rc.2
+ - @rocket.chat/apps@0.1.3-rc.2
+ - @rocket.chat/core-services@0.5.0-rc.2
+ - @rocket.chat/cron@0.1.3-rc.2
+ - @rocket.chat/fuselage-ui-kit@9.0.0-rc.2
+ - @rocket.chat/gazzodown@9.0.0-rc.2
+ - @rocket.chat/model-typings@0.6.0-rc.2
+ - @rocket.chat/ui-contexts@9.0.0-rc.2
+ - @rocket.chat/server-cloud-communication@0.0.2
+ - @rocket.chat/models@0.2.0-rc.2
+ - @rocket.chat/ui-theming@0.2.0
+ - @rocket.chat/ui-avatar@5.0.0-rc.2
+ - @rocket.chat/ui-client@9.0.0-rc.2
+ - @rocket.chat/ui-video-conf@9.0.0-rc.2
+ - @rocket.chat/web-ui-registration@9.0.0-rc.2
+ - @rocket.chat/instance-status@0.1.3-rc.2
+
+
+## 6.11.0-rc.1
+
+### Patch Changes
+
+- Bump @rocket.chat/meteor version.
+
+- Updated dependencies []:
+
+ - @rocket.chat/core-typings@6.11.0-rc.1
+ - @rocket.chat/rest-typings@6.11.0-rc.1
+ - @rocket.chat/api-client@0.2.2-rc.1
+ - @rocket.chat/license@0.2.2-rc.1
+ - @rocket.chat/omnichannel-services@0.3.0-rc.1
+ - @rocket.chat/pdf-worker@0.2.0-rc.1
+ - @rocket.chat/presence@0.2.2-rc.1
+ - @rocket.chat/apps@0.1.2-rc.1
+ - @rocket.chat/core-services@0.5.0-rc.1
+ - @rocket.chat/cron@0.1.2-rc.1
+ - @rocket.chat/fuselage-ui-kit@9.0.0-rc.1
+ - @rocket.chat/gazzodown@9.0.0-rc.1
+ - @rocket.chat/model-typings@0.6.0-rc.1
+ - @rocket.chat/ui-contexts@9.0.0-rc.1
+ - @rocket.chat/server-cloud-communication@0.0.2
+ - @rocket.chat/models@0.2.0-rc.1
+ - @rocket.chat/ui-theming@0.2.0
+ - @rocket.chat/ui-avatar@5.0.0-rc.1
+ - @rocket.chat/ui-client@9.0.0-rc.1
+ - @rocket.chat/ui-video-conf@9.0.0-rc.1
+ - @rocket.chat/web-ui-registration@9.0.0-rc.1
+ - @rocket.chat/instance-status@0.1.2-rc.1
+
+
+## 6.11.0-rc.0
+
+### Minor Changes
+
+- ([#32498](https://github.com/RocketChat/Rocket.Chat/pull/32498)) Created a `transferChat` Livechat API endpoint for transferring chats programmatically, the endpoint has all the limitations & permissions required that transferring via UI has
+
+- ([#32792](https://github.com/RocketChat/Rocket.Chat/pull/32792)) Allows admins to customize the `Subject` field of Omnichannel email transcripts via setting. By passing a value to the setting `Custom email subject for transcript`, system will use it as the `Subject` field, unless a custom subject is passed when requesting a transcript. If there's no custom subject and setting value is empty, the current default value will be used
+
+- ([#32739](https://github.com/RocketChat/Rocket.Chat/pull/32739)) Fixed an issue where FCM actions did not respect environment's proxy settings
+
+- ([#32570](https://github.com/RocketChat/Rocket.Chat/pull/32570)) Login services button was not respecting the button color and text color settings. Implemented a fix to respect these settings and change the button colors accordingly.
+
+ Added a warning on all settings which allow admins to change OAuth button colors, so that they can be alerted about WCAG (Web Content Accessibility Guidelines) compliance.
+
+- ([#32706](https://github.com/RocketChat/Rocket.Chat/pull/32706)) Added the possibility for apps to remove users from a room
+
+- ([#32517](https://github.com/RocketChat/Rocket.Chat/pull/32517)) Feature Preview: New Navigation - `Header` and `Contextualbar` size improvements consistent with the new global `NavBar`
+
+- ([#32493](https://github.com/RocketChat/Rocket.Chat/pull/32493)) Fixed Livechat rooms being displayed in the Engagement Dashboard's "Channels" tab
+
+- ([#32742](https://github.com/RocketChat/Rocket.Chat/pull/32742)) Fixed an issue where adding `OVERWRITE_SETTING_` for any setting wasn't immediately taking effect sometimes, and needed a server restart to reflect.
+
+- ([#32752](https://github.com/RocketChat/Rocket.Chat/pull/32752)) Added system messages support for Omnichannel PDF transcripts and email transcripts. Currently these transcripts don't render system messages and is shown as an empty message in PDF/email. This PR adds this support for all valid livechat system messages.
+
+ Also added a new setting under transcripts, to toggle the inclusion of system messages in email and PDF transcripts.
+
+- ([#32793](https://github.com/RocketChat/Rocket.Chat/pull/32793)) New Feature: Video Conference Persistent Chat.
+ This feature provides a discussion id for conference provider apps to store the chat messages exchanged during the conferences, so that those users may then access those messages again at any time through Rocket.Chat.
+- ([#32176](https://github.com/RocketChat/Rocket.Chat/pull/32176)) Added a method to the Apps-Engine that allows apps to read multiple messages from a room
+
+- ([#32493](https://github.com/RocketChat/Rocket.Chat/pull/32493)) Improved Engagement Dashboard's "Channels" tab performance by not returning rooms that had no activity in the analyzed period
+
+- ([#32024](https://github.com/RocketChat/Rocket.Chat/pull/32024)) Implemented a new tab to the users page called 'Active', this tab lists all users who have logged in for the first time and are active.
+
+- ([#32744](https://github.com/RocketChat/Rocket.Chat/pull/32744)) Added account setting `Accounts_Default_User_Preferences_sidebarSectionsOrder` to allow users to reorganize sidebar sections
+
+- ([#32820](https://github.com/RocketChat/Rocket.Chat/pull/32820)) Added a new setting `Livechat_transcript_send_always` that allows admins to decide if email transcript should be sent all the times when a conversation is closed. This setting bypasses agent's preferences. For this setting to work, `Livechat_enable_transcript` should be off, meaning that visitors will no longer receive the option to decide if they want a transcript or not.
+
+- ([#32724](https://github.com/RocketChat/Rocket.Chat/pull/32724)) Extended apps-engine events for users leaving a room to also fire when being removed by another user. Also added the triggering user's information to the event's context payload.
+
+- ([#32777](https://github.com/RocketChat/Rocket.Chat/pull/32777)) Added handling of attachments in Omnichannel email transcripts. Earlier attachments were being skipped and were being shown as empty space, now it should render the image attachments and should show relevant error message for unsupported attachments.
+
+- ([#32800](https://github.com/RocketChat/Rocket.Chat/pull/32800)) Added the ability to filter chats by `queued` on the Current Chats Omnichannel page
+
+### Patch Changes
+
+- ([#32679](https://github.com/RocketChat/Rocket.Chat/pull/32679)) Fix validations from "UiKit" modal component
+
+- ([#32730](https://github.com/RocketChat/Rocket.Chat/pull/32730)) Fixed issue in Marketplace that caused a subscription app to show incorrect modals when subscribing
+
+- ([#32628](https://github.com/RocketChat/Rocket.Chat/pull/32628)) Fixed SAML users' full names being updated on login regardless of the "Overwrite user fullname (use idp attribute)" setting
+
+- ([#32692](https://github.com/RocketChat/Rocket.Chat/pull/32692)) Fixed an issue that caused the widget to set the wrong department when using the setDepartment Livechat api endpoint in conjunction with a Livechat Trigger
+
+- ([#32527](https://github.com/RocketChat/Rocket.Chat/pull/32527)) Fixed an inconsistent evaluation of the `Accounts_LoginExpiration` setting over the codebase. In some places, it was being used as milliseconds while in others as days. Invalid values produced different results. A helper function was created to centralize the setting validation and the proper value being returned to avoid edge cases.
+ Negative values may be saved on the settings UI panel but the code will interpret any negative, NaN or 0 value to the default expiration which is 90 days.
+- ([#32626](https://github.com/RocketChat/Rocket.Chat/pull/32626)) livechat `setDepartment` livechat api fixes:
+ - Changing department didn't reflect on the registration form in real time
+ - Changing the department mid conversation didn't transfer the chat
+ - Depending on the state of the department, it couldn't be set as default
+- ([#32810](https://github.com/RocketChat/Rocket.Chat/pull/32810)) Fixed issue where bad word filtering was not working in the UI for messages
+
+- ([#32707](https://github.com/RocketChat/Rocket.Chat/pull/32707)) Fixed issue with livechat agents not being able to leave omnichannel rooms if joining after a room has been closed by the visitor (due to race conditions)
+
+- ([#32837](https://github.com/RocketChat/Rocket.Chat/pull/32837)) Fixed an issue where non-encrypted attachments were not being downloaded
+
+- ([#32861](https://github.com/RocketChat/Rocket.Chat/pull/32861)) fixed the contextual bar closing when editing thread messages instead of cancelling the message edit
+
+- ([#32713](https://github.com/RocketChat/Rocket.Chat/pull/32713)) Fixed the disappearance of some settings after navigation under network latency.
+
+- ([#32592](https://github.com/RocketChat/Rocket.Chat/pull/32592)) Fixes Missing line breaks on Omnichannel Room Info Panel
+
+- ([#32807](https://github.com/RocketChat/Rocket.Chat/pull/32807)) Fixed web client crashing on Firefox private window. Firefox disables access to service workers inside private windows. Rocket.Chat needs service workers to process E2EE encrypted files on rooms. These types of files won't be available inside private windows, but the rest of E2EE encrypted features should work normally
+
+- ([#32864](https://github.com/RocketChat/Rocket.Chat/pull/32864)) fixed an issue in the "Create discussion" form, that would have the "Create" action button disabled even though the form is prefilled when opening it from the message action
+
+- ([#32691](https://github.com/RocketChat/Rocket.Chat/pull/32691)) Removed 'Hide' option in the room menu for Omnichannel conversations.
+
+- ([#32445](https://github.com/RocketChat/Rocket.Chat/pull/32445)) Fixed LDAP rooms, teams and roles syncs not being triggered on login even when the "Update User Data on Login" setting is enabled
+
+- ([#32328](https://github.com/RocketChat/Rocket.Chat/pull/32328)) Allow customFields on livechat creation bridge
+
+- ([#32803](https://github.com/RocketChat/Rocket.Chat/pull/32803)) Fixed "Copy link" message action enabled in Starred and Pinned list for End to End Encrypted channels, this action is disabled now
+
+- ([#32769](https://github.com/RocketChat/Rocket.Chat/pull/32769)) Fixed issue that caused unintentional clicks when scrolling the channels sidebar on safari/chrome in iOS
+
+- ([#32857](https://github.com/RocketChat/Rocket.Chat/pull/32857)) Fixed some anomalies related to disabled E2EE rooms. Earlier there are some weird issues with disabled E2EE rooms, this PR fixes these anomalies.
+
+- ([#32765](https://github.com/RocketChat/Rocket.Chat/pull/32765)) Fixed an issue that prevented the option to start a discussion from being shown on the message actions
+
+- ([#32671](https://github.com/RocketChat/Rocket.Chat/pull/32671)) Fix show correct user roles after updating user roles on admin edit user panel.
+
+- ([#32482](https://github.com/RocketChat/Rocket.Chat/pull/32482)) Fixed an issue with blocked login when dismissed 2FA modal by clicking outside of it or pressing the escape key
+
+- ([#32804](https://github.com/RocketChat/Rocket.Chat/pull/32804)) Fixes an issue not displaying all groups in settings list
+
+- ([#32815](https://github.com/RocketChat/Rocket.Chat/pull/32815)) Security Hotfix (https://docs.rocket.chat/guides/security/security-updates)
+
+- ([#32632](https://github.com/RocketChat/Rocket.Chat/pull/32632)) Improving UX by change the position of room info actions buttons and menu order to avoid missclick in destructive actions.
+
+- ([#32752](https://github.com/RocketChat/Rocket.Chat/pull/32752)) Reduced time on generation of PDF transcripts. Earlier Rocket.Chat was fetching the required translations everytime a PDF transcript was requested, this process was async and was being unnecessarily being performed on every pdf transcript request. This PR improves this and now the translations are loaded at the start and kept in memory to process further pdf transcripts requests. This reduces the time of asynchronously fetching translations again and again.
+
+- ([#32719](https://github.com/RocketChat/Rocket.Chat/pull/32719)) Added the `user` param to apps-engine update method call, allowing apps' new `onUpdate` hook to know who triggered the update.
+
+- Updated dependencies [88e5219bd2, b4bbcbfc9a, 8fc6ca8b4e, 15664127be, 25da5280a5, 1b7b1161cf, 439faa87d3, 03c8b066f9, 2d89a0c448, 439faa87d3, 24f7df4894, 3ffe4a2944, 3b4b19cfc5, 4e8aa575a6, 03c8b066f9, 264d7d5496, b8e5887fb9]:
+
+ - @rocket.chat/fuselage-ui-kit@9.0.0-rc.0
+ - @rocket.chat/i18n@0.6.0-rc.0
+ - @rocket.chat/tools@0.2.2-rc.0
+ - @rocket.chat/web-ui-registration@9.0.0-rc.0
+ - @rocket.chat/ui-client@9.0.0-rc.0
+ - @rocket.chat/model-typings@0.6.0-rc.0
+ - @rocket.chat/omnichannel-services@0.3.0-rc.0
+ - @rocket.chat/pdf-worker@0.2.0-rc.0
+ - @rocket.chat/core-services@0.5.0-rc.0
+ - @rocket.chat/ui-video-conf@9.0.0-rc.0
+ - @rocket.chat/core-typings@6.11.0-rc.0
+ - @rocket.chat/ui-contexts@9.0.0-rc.0
+ - @rocket.chat/models@0.2.0-rc.0
+ - @rocket.chat/ui-kit@0.36.0-rc.0
+ - @rocket.chat/rest-typings@6.11.0-rc.0
+ - @rocket.chat/apps@0.1.2-rc.0
+ - @rocket.chat/presence@0.2.2-rc.0
+ - @rocket.chat/gazzodown@9.0.0-rc.0
+ - @rocket.chat/api-client@0.2.2-rc.0
+ - @rocket.chat/license@0.2.2-rc.0
+ - @rocket.chat/cron@0.1.2-rc.0
+ - @rocket.chat/ui-theming@0.2.0
+ - @rocket.chat/ui-avatar@5.0.0-rc.0
+ - @rocket.chat/instance-status@0.1.2-rc.0
+ - @rocket.chat/server-cloud-communication@0.0.2
+
+## 6.10.2
+
+### Patch Changes
+
+- Bump @rocket.chat/meteor version.
+
+- ([#32935](https://github.com/RocketChat/Rocket.Chat/pull/32935)) Fixed an issue that prevented apps from being updated or uninstalled in some cases
+
+- ([#32935](https://github.com/RocketChat/Rocket.Chat/pull/32935)) Fixed an issue that prevented apps from handling errors during execution in some cases
+
+- ([#32935](https://github.com/RocketChat/Rocket.Chat/pull/32935)) Improved Apps-Engine installation to prevent start up errors on manual installation setups
+
+- ([#32950](https://github.com/RocketChat/Rocket.Chat/pull/32950) by [@dionisio-bot](https://github.com/dionisio-bot)) Fixed a crash on web client due to service workers not being available, this can happen in multiple scenarios like on Firefox's private window or if the connection is not secure (non-HTTPS), [see more details](https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts).
+
+ Rocket.Chat needs service workers to process E2EE encrypted files on rooms. These types of files won't be available inside private windows, but the rest of E2EE encrypted features should work normally
+
+- ([#32935](https://github.com/RocketChat/Rocket.Chat/pull/32935)) Fixed an issue that caused the video conference button on rooms to not recognize a video conference provider app in some cases
+
+- Updated dependencies [ca6a9d8de8, ca6a9d8de8, ca6a9d8de8, ca6a9d8de8]:
+
+ - @rocket.chat/fuselage-ui-kit@8.0.2
+ - @rocket.chat/core-services@0.4.2
+ - @rocket.chat/core-typings@6.10.2
+ - @rocket.chat/rest-typings@6.10.2
+ - @rocket.chat/presence@0.2.2
+ - @rocket.chat/apps@0.1.2
+ - @rocket.chat/omnichannel-services@0.2.2
+ - @rocket.chat/api-client@0.2.2
+ - @rocket.chat/license@0.2.2
+ - @rocket.chat/pdf-worker@0.1.2
+ - @rocket.chat/cron@0.1.2
+ - @rocket.chat/gazzodown@8.0.2
+ - @rocket.chat/model-typings@0.5.2
+ - @rocket.chat/ui-contexts@8.0.2
+ - @rocket.chat/server-cloud-communication@0.0.2
+ - @rocket.chat/models@0.1.2
+ - @rocket.chat/ui-theming@0.2.0
+ - @rocket.chat/ui-avatar@4.0.2
+ - @rocket.chat/ui-client@8.0.2
+ - @rocket.chat/ui-video-conf@8.0.2
+ - @rocket.chat/web-ui-registration@8.0.2
+ - @rocket.chat/instance-status@0.1.2
+
+
## 6.10.1
### Patch Changes
diff --git a/apps/meteor/app/2fa/server/methods/checkCodesRemaining.ts b/apps/meteor/app/2fa/server/methods/checkCodesRemaining.ts
index 219a78483cea..f5f5b0e1f275 100644
--- a/apps/meteor/app/2fa/server/methods/checkCodesRemaining.ts
+++ b/apps/meteor/app/2fa/server/methods/checkCodesRemaining.ts
@@ -1,7 +1,7 @@
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'2fa:checkCodesRemaining': () => { remaining: number };
diff --git a/apps/meteor/app/2fa/server/methods/disable.ts b/apps/meteor/app/2fa/server/methods/disable.ts
index 0927b3f854ac..d2c71febdc35 100644
--- a/apps/meteor/app/2fa/server/methods/disable.ts
+++ b/apps/meteor/app/2fa/server/methods/disable.ts
@@ -1,10 +1,10 @@
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Users } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { TOTP } from '../lib/totp';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'2fa:disable': (code: string) => Promise;
diff --git a/apps/meteor/app/2fa/server/methods/enable.ts b/apps/meteor/app/2fa/server/methods/enable.ts
index 6b786c0743e9..dea859d27b62 100644
--- a/apps/meteor/app/2fa/server/methods/enable.ts
+++ b/apps/meteor/app/2fa/server/methods/enable.ts
@@ -1,10 +1,10 @@
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Users } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { TOTP } from '../lib/totp';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'2fa:enable': () => Promise<{ secret: string; url: string }>;
diff --git a/apps/meteor/app/2fa/server/methods/regenerateCodes.ts b/apps/meteor/app/2fa/server/methods/regenerateCodes.ts
index e0f4cfaa4797..6968abfb93c2 100644
--- a/apps/meteor/app/2fa/server/methods/regenerateCodes.ts
+++ b/apps/meteor/app/2fa/server/methods/regenerateCodes.ts
@@ -1,10 +1,10 @@
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Users } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { TOTP } from '../lib/totp';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'2fa:regenerateCodes': (userToken: string) => { codes: string[] } | undefined;
diff --git a/apps/meteor/app/2fa/server/methods/validateTempToken.ts b/apps/meteor/app/2fa/server/methods/validateTempToken.ts
index cc2b44372a04..840fadc8cbf7 100644
--- a/apps/meteor/app/2fa/server/methods/validateTempToken.ts
+++ b/apps/meteor/app/2fa/server/methods/validateTempToken.ts
@@ -1,11 +1,11 @@
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Users } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { notifyOnUserChangeAsync } from '../../../lib/server/lib/notifyListener';
import { TOTP } from '../lib/totp';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'2fa:validateTempToken': (userToken: string) => { codes: string[] } | undefined;
diff --git a/apps/meteor/app/api/server/v1/emoji-custom.ts b/apps/meteor/app/api/server/v1/emoji-custom.ts
index a61149c5e66e..9cbf202896e1 100644
--- a/apps/meteor/app/api/server/v1/emoji-custom.ts
+++ b/apps/meteor/app/api/server/v1/emoji-custom.ts
@@ -3,6 +3,8 @@ import { EmojiCustom } from '@rocket.chat/models';
import { Meteor } from 'meteor/meteor';
import { SystemLogger } from '../../../../server/lib/logger/system';
+import { insertOrUpdateEmoji } from '../../../emoji-custom/server/lib/insertOrUpdateEmoji';
+import { uploadEmojiCustomWithBuffer } from '../../../emoji-custom/server/lib/uploadEmojiCustom';
import { settings } from '../../../settings/server';
import { API } from '../api';
import { getPaginationItems } from '../helpers/getPaginationItems';
@@ -148,9 +150,19 @@ API.v1.addRoute(
fields.extension = emojiToUpdate.extension;
}
- await Meteor.callAsync('insertOrUpdateEmoji', { ...fields, newFile });
+ const emojiData = {
+ name: fields.name,
+ _id: fields._id,
+ aliases: fields.aliases,
+ extension: fields.extension,
+ previousName: fields.previousName,
+ previousExtension: fields.previousExtension,
+ newFile,
+ };
+
+ await insertOrUpdateEmoji(this.userId, emojiData);
if (fields.newFile) {
- await Meteor.callAsync('uploadEmojiCustom', fileBuffer, mimetype, { ...fields, newFile });
+ await uploadEmojiCustomWithBuffer(this.userId, fileBuffer, mimetype, emojiData);
}
return API.v1.success();
},
diff --git a/apps/meteor/app/api/server/v1/teams.ts b/apps/meteor/app/api/server/v1/teams.ts
index 4ea8f2a48f38..f64f8c820575 100644
--- a/apps/meteor/app/api/server/v1/teams.ts
+++ b/apps/meteor/app/api/server/v1/teams.ts
@@ -1,6 +1,6 @@
import { Team } from '@rocket.chat/core-services';
import type { ITeam, UserStatus } from '@rocket.chat/core-typings';
-import { TEAM_TYPE } from '@rocket.chat/core-typings';
+import { TEAM_TYPE, isValidSidepanel } from '@rocket.chat/core-typings';
import { Users, Rooms } from '@rocket.chat/models';
import {
isTeamsConvertToChannelProps,
@@ -85,7 +85,11 @@ API.v1.addRoute(
}),
);
- const { name, type, members, room, owner } = this.bodyParams;
+ const { name, type, members, room, owner, sidepanel } = this.bodyParams;
+
+ if (sidepanel?.items && !isValidSidepanel(sidepanel)) {
+ throw new Error('error-invalid-sidepanel');
+ }
const team = await Team.create(this.userId, {
team: {
@@ -95,6 +99,7 @@ API.v1.addRoute(
room,
members,
owner,
+ sidepanel,
});
return API.v1.success({ team });
diff --git a/apps/meteor/app/api/server/v1/users.ts b/apps/meteor/app/api/server/v1/users.ts
index 26ef2fa30ff2..7ae585b89dfa 100644
--- a/apps/meteor/app/api/server/v1/users.ts
+++ b/apps/meteor/app/api/server/v1/users.ts
@@ -1216,7 +1216,7 @@ API.v1.addRoute(
throw new Meteor.Error('error-invalid-user-id', 'Invalid user id');
}
- void notifyOnUserChange({ clientAction: 'updated', id: this.userId, diff: { 'services.resume.loginTokens': [] } });
+ void notifyOnUserChange({ clientAction: 'updated', id: userId, diff: { 'services.resume.loginTokens': [] } });
return API.v1.success({
message: `User ${userId} has been logged out!`,
diff --git a/apps/meteor/app/apps/server/bridges/livechat.ts b/apps/meteor/app/apps/server/bridges/livechat.ts
index ec5cff29a99b..4f4794591e02 100644
--- a/apps/meteor/app/apps/server/bridges/livechat.ts
+++ b/apps/meteor/app/apps/server/bridges/livechat.ts
@@ -1,7 +1,7 @@
-import type { IAppServerOrchestrator, IAppsLivechatMessage } from '@rocket.chat/apps';
+import type { IAppServerOrchestrator, IAppsLivechatMessage, IAppsMessage } from '@rocket.chat/apps';
import type { IExtraRoomParams } from '@rocket.chat/apps-engine/definition/accessors/ILivechatCreator';
import type { IVisitor, ILivechatRoom, ILivechatTransferData, IDepartment } from '@rocket.chat/apps-engine/definition/livechat';
-import type { IMessage as IAppsEngineMesage } from '@rocket.chat/apps-engine/definition/messages';
+import type { IMessage as IAppsEngineMessage } from '@rocket.chat/apps-engine/definition/messages';
import type { IUser } from '@rocket.chat/apps-engine/definition/users';
import { LivechatBridge } from '@rocket.chat/apps-engine/server/bridges/LivechatBridge';
import type { ILivechatDepartment, IOmnichannelRoom, SelectedAgent, IMessage, ILivechatVisitor } from '@rocket.chat/core-typings';
@@ -13,6 +13,12 @@ import { deasyncPromise } from '../../../../server/deasync/deasync';
import { type ILivechatMessage, Livechat as LivechatTyped } from '../../../livechat/server/lib/LivechatTyped';
import { settings } from '../../../settings/server';
+declare module '@rocket.chat/apps/dist/converters/IAppMessagesConverter' {
+ export interface IAppMessagesConverter {
+ convertMessage(message: IMessage, cacheObj?: object): Promise;
+ }
+}
+
declare module '@rocket.chat/apps-engine/definition/accessors/ILivechatCreator' {
interface IExtraRoomParams {
customFields?: Record;
@@ -337,7 +343,7 @@ export class AppLivechatBridge extends LivechatBridge {
return Promise.all((await LivechatDepartment.findEnabledWithAgents().toArray()).map(boundConverter));
}
- protected async _fetchLivechatRoomMessages(appId: string, roomId: string): Promise> {
+ protected async _fetchLivechatRoomMessages(appId: string, roomId: string): Promise> {
this.orch.debugLog(`The App ${appId} is getting the transcript for livechat room ${roomId}.`);
const messageConverter = this.orch.getConverters()?.get('messages');
@@ -346,8 +352,7 @@ export class AppLivechatBridge extends LivechatBridge {
}
const livechatMessages = await LivechatTyped.getRoomMessages({ rid: roomId });
-
- return Promise.all(livechatMessages.map((message) => messageConverter.convertMessage(message) as Promise));
+ return Promise.all(await livechatMessages.map((message) => messageConverter.convertMessage(message, livechatMessages)).toArray());
}
protected async setCustomFields(
diff --git a/apps/meteor/app/apps/server/converters/messages.js b/apps/meteor/app/apps/server/converters/messages.js
index d7dae512e9a8..89ef2454d895 100644
--- a/apps/meteor/app/apps/server/converters/messages.js
+++ b/apps/meteor/app/apps/server/converters/messages.js
@@ -52,19 +52,26 @@ export class AppMessagesConverter {
return transformMappedData(message, map);
}
- async convertMessage(msgObj) {
+ async convertMessage(msgObj, cacheObj = msgObj) {
if (!msgObj) {
return undefined;
}
const cache =
- this.mem.get(msgObj) ??
+ this.mem.get(cacheObj) ??
new Map([
['room', cachedFunction(this.orch.getConverters().get('rooms').convertById.bind(this.orch.getConverters().get('rooms')))],
- ['user', cachedFunction(this.orch.getConverters().get('users').convertById.bind(this.orch.getConverters().get('users')))],
+ [
+ 'user.convertById',
+ cachedFunction(this.orch.getConverters().get('users').convertById.bind(this.orch.getConverters().get('users'))),
+ ],
+ [
+ 'user.convertToApp',
+ cachedFunction(this.orch.getConverters().get('users').convertToApp.bind(this.orch.getConverters().get('users'))),
+ ],
]);
- this.mem.set(msgObj, cache);
+ this.mem.set(cacheObj, cache);
const map = {
id: '_id',
@@ -96,7 +103,7 @@ export class AppMessagesConverter {
return undefined;
}
- return cache.get('user')(editedBy._id);
+ return cache.get('user.convertById')(editedBy._id);
},
attachments: async (message) => {
const result = await this._convertAttachmentsToApp(message.attachments);
@@ -110,8 +117,8 @@ export class AppMessagesConverter {
// When the message contains token, means the message is from the visitor(omnichannel)
const user = await (isMessageFromVisitor(msgObj)
- ? this.orch.getConverters().get('users').convertToApp(message.u)
- : cache.get('user')(message.u._id));
+ ? cache.get('user.convertToApp')(message.u)
+ : cache.get('user.convertById')(message.u._id));
delete message.u;
@@ -120,7 +127,7 @@ export class AppMessagesConverter {
* `sender` as undefined, so we need to add this fallback here.
*/
- return user || this.orch.getConverters().get('users').convertToApp(message.u);
+ return user || cache.get('user.convertToApp')(message.u);
},
};
diff --git a/apps/meteor/app/assets/server/assets.ts b/apps/meteor/app/assets/server/assets.ts
index b9653a2f1b9a..5d627a4b1d29 100644
--- a/apps/meteor/app/assets/server/assets.ts
+++ b/apps/meteor/app/assets/server/assets.ts
@@ -2,8 +2,8 @@ import crypto from 'crypto';
import type { ServerResponse, IncomingMessage } from 'http';
import type { IRocketChatAssets, IRocketChatAsset, ISetting } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Settings } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import type { NextHandleFunction } from 'connect';
import sizeOf from 'image-size';
import { Meteor } from 'meteor/meteor';
@@ -406,7 +406,7 @@ Meteor.startup(() => {
}, 200);
});
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
refreshClients(): boolean;
diff --git a/apps/meteor/app/authorization/server/methods/addPermissionToRole.ts b/apps/meteor/app/authorization/server/methods/addPermissionToRole.ts
index 13a114732bd2..9a336478ca3e 100644
--- a/apps/meteor/app/authorization/server/methods/addPermissionToRole.ts
+++ b/apps/meteor/app/authorization/server/methods/addPermissionToRole.ts
@@ -1,12 +1,12 @@
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Permissions } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { notifyOnPermissionChangedById } from '../../../lib/server/lib/notifyListener';
import { CONSTANTS, AuthorizationUtils } from '../../lib';
import { hasPermissionAsync } from '../functions/hasPermission';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'authorization:addPermissionToRole'(permissionId: string, role: string): void;
diff --git a/apps/meteor/app/authorization/server/methods/addUserToRole.ts b/apps/meteor/app/authorization/server/methods/addUserToRole.ts
index 02ccc76373f1..81582dd7e9fb 100644
--- a/apps/meteor/app/authorization/server/methods/addUserToRole.ts
+++ b/apps/meteor/app/authorization/server/methods/addUserToRole.ts
@@ -1,14 +1,14 @@
import { api } from '@rocket.chat/core-services';
import type { IRole, IUser } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Roles, Users } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger';
import { settings } from '../../../settings/server';
import { hasPermissionAsync } from '../functions/hasPermission';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'authorization:addUserToRole'(roleId: IRole['_id'], username: IUser['username'], scope: string | undefined): Promise;
diff --git a/apps/meteor/app/authorization/server/methods/deleteRole.ts b/apps/meteor/app/authorization/server/methods/deleteRole.ts
index 2ff09deadf68..140852e0f1ec 100644
--- a/apps/meteor/app/authorization/server/methods/deleteRole.ts
+++ b/apps/meteor/app/authorization/server/methods/deleteRole.ts
@@ -1,13 +1,13 @@
import type { IRole } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Roles } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import type { DeleteResult } from 'mongodb';
import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger';
import { hasPermissionAsync } from '../functions/hasPermission';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'authorization:deleteRole'(roleId: IRole['_id'] | IRole['name']): Promise;
diff --git a/apps/meteor/app/authorization/server/methods/removeRoleFromPermission.ts b/apps/meteor/app/authorization/server/methods/removeRoleFromPermission.ts
index 91a4df1eddf7..68ca11ef9fb5 100644
--- a/apps/meteor/app/authorization/server/methods/removeRoleFromPermission.ts
+++ b/apps/meteor/app/authorization/server/methods/removeRoleFromPermission.ts
@@ -1,12 +1,12 @@
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Permissions } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { notifyOnPermissionChangedById } from '../../../lib/server/lib/notifyListener';
import { CONSTANTS } from '../../lib';
import { hasPermissionAsync } from '../functions/hasPermission';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'authorization:removeRoleFromPermission'(permissionId: string, role: string): void;
diff --git a/apps/meteor/app/authorization/server/methods/removeUserFromRole.ts b/apps/meteor/app/authorization/server/methods/removeUserFromRole.ts
index d5dba40a1e53..56f0c2e307ab 100644
--- a/apps/meteor/app/authorization/server/methods/removeUserFromRole.ts
+++ b/apps/meteor/app/authorization/server/methods/removeUserFromRole.ts
@@ -1,14 +1,14 @@
import { api } from '@rocket.chat/core-services';
import type { IRole, IUser } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Roles, Users } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger';
import { settings } from '../../../settings/server';
import { hasPermissionAsync } from '../functions/hasPermission';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'authorization:removeUserFromRole'(roleId: IRole['_id'], username: IUser['username'], scope?: string): Promise;
diff --git a/apps/meteor/app/authorization/server/streamer/permissions/index.ts b/apps/meteor/app/authorization/server/streamer/permissions/index.ts
index ff8fd3c93262..e74cf37869fd 100644
--- a/apps/meteor/app/authorization/server/streamer/permissions/index.ts
+++ b/apps/meteor/app/authorization/server/streamer/permissions/index.ts
@@ -1,11 +1,11 @@
import type { IPermission, RocketChatRecordDeleted } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Permissions } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { check, Match } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import type { WithId } from 'mongodb';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'permissions/get'(
diff --git a/apps/meteor/app/autotranslate/server/autotranslate.ts b/apps/meteor/app/autotranslate/server/autotranslate.ts
index 7a9eb8780a2d..f3c6d9e55fdb 100644
--- a/apps/meteor/app/autotranslate/server/autotranslate.ts
+++ b/apps/meteor/app/autotranslate/server/autotranslate.ts
@@ -15,7 +15,7 @@ import _ from 'underscore';
import { callbacks } from '../../../lib/callbacks';
import { isTruthy } from '../../../lib/isTruthy';
-import { broadcastMessageFromData } from '../../../server/modules/watchers/lib/messages';
+import { notifyOnMessageChange } from '../../lib/server/lib/notifyListener';
import { Markdown } from '../../markdown/server';
import { settings } from '../../settings/server';
@@ -79,7 +79,7 @@ export class TranslationProviderRegistry {
return null;
}
- return provider.translateMessage(message, room, targetLanguage);
+ return provider.translateMessage(message, { room, targetLanguage });
}
static getProviders(): AutoTranslate[] {
@@ -290,7 +290,7 @@ export abstract class AutoTranslate {
* @param {object} targetLanguage
* @returns {object} unmodified message object.
*/
- async translateMessage(message: IMessage, room: IRoom, targetLanguage?: string): Promise {
+ async translateMessage(message: IMessage, { room, targetLanguage }: { room: IRoom; targetLanguage?: string }): Promise {
let targetLanguages: string[];
if (targetLanguage) {
targetLanguages = [targetLanguage];
@@ -332,7 +332,7 @@ export abstract class AutoTranslate {
}
private notifyTranslatedMessage(messageId: string): void {
- void broadcastMessageFromData({
+ void notifyOnMessageChange({
id: messageId,
});
}
diff --git a/apps/meteor/app/autotranslate/server/methods/getProviderUiMetadata.ts b/apps/meteor/app/autotranslate/server/methods/getProviderUiMetadata.ts
index 30760e854ed1..1d443c21d210 100644
--- a/apps/meteor/app/autotranslate/server/methods/getProviderUiMetadata.ts
+++ b/apps/meteor/app/autotranslate/server/methods/getProviderUiMetadata.ts
@@ -1,9 +1,9 @@
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
import { TranslationProviderRegistry } from '../autotranslate';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'autoTranslate.getProviderUiMetadata'(): Record;
diff --git a/apps/meteor/app/autotranslate/server/methods/getSupportedLanguages.ts b/apps/meteor/app/autotranslate/server/methods/getSupportedLanguages.ts
index e0118e8d95a4..7b9614da7739 100644
--- a/apps/meteor/app/autotranslate/server/methods/getSupportedLanguages.ts
+++ b/apps/meteor/app/autotranslate/server/methods/getSupportedLanguages.ts
@@ -1,5 +1,5 @@
import type { ISupportedLanguage } from '@rocket.chat/core-typings';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { DDPRateLimiter } from 'meteor/ddp-rate-limiter';
import { Meteor } from 'meteor/meteor';
@@ -7,7 +7,7 @@ import { TranslationProviderRegistry } from '..';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
import { settings } from '../../../settings/server';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'autoTranslate.getSupportedLanguages'(targetLanguage: string): ISupportedLanguage[] | undefined;
diff --git a/apps/meteor/app/autotranslate/server/methods/saveSettings.ts b/apps/meteor/app/autotranslate/server/methods/saveSettings.ts
index e396d78887a9..2f119c948263 100644
--- a/apps/meteor/app/autotranslate/server/methods/saveSettings.ts
+++ b/apps/meteor/app/autotranslate/server/methods/saveSettings.ts
@@ -1,11 +1,11 @@
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Subscriptions, Rooms } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'autoTranslate.saveSettings'(rid: string, field: string, value: string, options: { defaultLanguage: string }): boolean;
diff --git a/apps/meteor/app/autotranslate/server/methods/translateMessage.ts b/apps/meteor/app/autotranslate/server/methods/translateMessage.ts
index d90cad90ce77..551eba57c005 100644
--- a/apps/meteor/app/autotranslate/server/methods/translateMessage.ts
+++ b/apps/meteor/app/autotranslate/server/methods/translateMessage.ts
@@ -1,11 +1,11 @@
import type { IMessage } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Rooms } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { TranslationProviderRegistry } from '..';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'autoTranslate.translateMessage'(message: IMessage | undefined, targetLanguage: string): Promise;
diff --git a/apps/meteor/app/bot-helpers/server/index.ts b/apps/meteor/app/bot-helpers/server/index.ts
index 5e19e1652454..6c0984ae483d 100644
--- a/apps/meteor/app/bot-helpers/server/index.ts
+++ b/apps/meteor/app/bot-helpers/server/index.ts
@@ -1,7 +1,7 @@
import type { IUser } from '@rocket.chat/core-typings';
import { UserStatus } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Rooms, Users } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import type { Filter, FindCursor } from 'mongodb';
@@ -194,7 +194,7 @@ settings.watch('BotHelpers_userFields', (value) => {
botHelpers.setupCursors(value);
});
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
botRequest: (prop: keyof BotHelpers, ...params: unknown[]) => Promise;
diff --git a/apps/meteor/app/channel-settings/server/methods/saveRoomSettings.ts b/apps/meteor/app/channel-settings/server/methods/saveRoomSettings.ts
index e17faebea384..44ad253d83ef 100644
--- a/apps/meteor/app/channel-settings/server/methods/saveRoomSettings.ts
+++ b/apps/meteor/app/channel-settings/server/methods/saveRoomSettings.ts
@@ -1,8 +1,8 @@
import { Team } from '@rocket.chat/core-services';
import type { IRoom, IRoomWithRetentionPolicy, IUser, MessageTypesValues } from '@rocket.chat/core-typings';
-import { TEAM_TYPE } from '@rocket.chat/core-typings';
+import { TEAM_TYPE, isValidSidepanel } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Rooms, Users } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Match } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
@@ -49,6 +49,7 @@ type RoomSettings = {
favorite: boolean;
defaultValue: boolean;
};
+ sidepanel?: IRoom['sidepanel'];
};
type RoomSettingsValidators = {
@@ -80,6 +81,24 @@ const validators: RoomSettingsValidators = {
});
}
},
+ async sidepanel({ room, userId, value }) {
+ if (!room.teamMain) {
+ throw new Meteor.Error('error-action-not-allowed', 'Invalid room', {
+ method: 'saveRoomSettings',
+ });
+ }
+
+ if (!(await hasPermissionAsync(userId, 'edit-team', room._id))) {
+ throw new Meteor.Error('error-action-not-allowed', 'You do not have permission to change sidepanel items', {
+ method: 'saveRoomSettings',
+ });
+ }
+
+ if (!isValidSidepanel(value)) {
+ throw new Meteor.Error('error-invalid-sidepanel');
+ }
+ },
+
async roomType({ userId, room, value }) {
if (value === room.t) {
return;
@@ -213,6 +232,11 @@ const settingSavers: RoomSettingsSavers = {
await saveRoomTopic(rid, value, user);
}
},
+ async sidepanel({ value, rid, room }) {
+ if (JSON.stringify(value) !== JSON.stringify(room.sidepanel)) {
+ await Rooms.setSidepanelById(rid, value);
+ }
+ },
async roomAnnouncement({ value, room, rid, user }) {
if (!value && !room.announcement) {
return;
@@ -304,7 +328,7 @@ const settingSavers: RoomSettingsSavers = {
},
};
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
saveRoomSettings(rid: IRoom['_id'], settings: Partial): Promise<{ result: true; rid: IRoom['_id'] }>;
@@ -339,6 +363,7 @@ const fields: (keyof RoomSettings)[] = [
'retentionOverrideGlobal',
'encrypted',
'favorite',
+ 'sidepanel',
];
const validate = (
diff --git a/apps/meteor/app/cloud/server/methods.ts b/apps/meteor/app/cloud/server/methods.ts
index 0e47a8ba8754..29daefe0d58c 100644
--- a/apps/meteor/app/cloud/server/methods.ts
+++ b/apps/meteor/app/cloud/server/methods.ts
@@ -1,4 +1,4 @@
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
@@ -13,7 +13,7 @@ import { startRegisterWorkspace } from './functions/startRegisterWorkspace';
import { syncWorkspace } from './functions/syncWorkspace';
import { userLogout } from './functions/userLogout';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'cloud:checkRegisterStatus': () => {
diff --git a/apps/meteor/app/crowd/server/methods.ts b/apps/meteor/app/crowd/server/methods.ts
index a621e3c8d027..48faa2fcbcab 100644
--- a/apps/meteor/app/crowd/server/methods.ts
+++ b/apps/meteor/app/crowd/server/methods.ts
@@ -1,4 +1,5 @@
-import type { ServerMethods, TranslationKey } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
+import type { TranslationKey } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../authorization/server/functions/hasPermission';
@@ -6,7 +7,7 @@ import { settings } from '../../settings/server';
import { CROWD } from './crowd';
import { logger } from './logger';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
crowd_test_connection(): { message: TranslationKey; params: string[] };
diff --git a/apps/meteor/app/custom-sounds/server/methods/deleteCustomSound.ts b/apps/meteor/app/custom-sounds/server/methods/deleteCustomSound.ts
index 5ddf0cc66e52..1c63c7a67d9f 100644
--- a/apps/meteor/app/custom-sounds/server/methods/deleteCustomSound.ts
+++ b/apps/meteor/app/custom-sounds/server/methods/deleteCustomSound.ts
@@ -1,13 +1,13 @@
import { api } from '@rocket.chat/core-services';
import type { ICustomSound } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { CustomSounds } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
import { RocketChatFileCustomSoundsInstance } from '../startup/custom-sounds';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
deleteCustomSound(_id: ICustomSound['_id']): Promise;
diff --git a/apps/meteor/app/custom-sounds/server/methods/insertOrUpdateSound.ts b/apps/meteor/app/custom-sounds/server/methods/insertOrUpdateSound.ts
index 4b48a64dc14c..1b922c6b162e 100644
--- a/apps/meteor/app/custom-sounds/server/methods/insertOrUpdateSound.ts
+++ b/apps/meteor/app/custom-sounds/server/methods/insertOrUpdateSound.ts
@@ -1,6 +1,6 @@
import { api } from '@rocket.chat/core-services';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { CustomSounds } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
@@ -20,7 +20,7 @@ export type ICustomSoundData = {
random?: number;
};
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
insertOrUpdateSound(soundData: ICustomSoundData): Promise;
diff --git a/apps/meteor/app/custom-sounds/server/methods/listCustomSounds.ts b/apps/meteor/app/custom-sounds/server/methods/listCustomSounds.ts
index 2c2130fc0d30..eda1325d7733 100644
--- a/apps/meteor/app/custom-sounds/server/methods/listCustomSounds.ts
+++ b/apps/meteor/app/custom-sounds/server/methods/listCustomSounds.ts
@@ -1,9 +1,9 @@
import type { ICustomSound } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { CustomSounds } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
listCustomSounds(): ICustomSound[];
diff --git a/apps/meteor/app/custom-sounds/server/methods/uploadCustomSound.ts b/apps/meteor/app/custom-sounds/server/methods/uploadCustomSound.ts
index eee693634d7d..f955f373ed4d 100644
--- a/apps/meteor/app/custom-sounds/server/methods/uploadCustomSound.ts
+++ b/apps/meteor/app/custom-sounds/server/methods/uploadCustomSound.ts
@@ -1,6 +1,6 @@
import { api } from '@rocket.chat/core-services';
import type { RequiredField } from '@rocket.chat/core-typings';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
@@ -8,7 +8,7 @@ import { RocketChatFile } from '../../../file/server';
import { RocketChatFileCustomSoundsInstance } from '../startup/custom-sounds';
import type { ICustomSoundData } from './insertOrUpdateSound';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
uploadCustomSound(binaryContent: string, contentType: string, soundData: RequiredField): void;
diff --git a/apps/meteor/app/discussion/server/hooks/propagateDiscussionMetadata.ts b/apps/meteor/app/discussion/server/hooks/propagateDiscussionMetadata.ts
index d8e3637575ab..1ff9ed1dc1ba 100644
--- a/apps/meteor/app/discussion/server/hooks/propagateDiscussionMetadata.ts
+++ b/apps/meteor/app/discussion/server/hooks/propagateDiscussionMetadata.ts
@@ -2,15 +2,15 @@ import type { IRoom } from '@rocket.chat/core-typings';
import { Messages, Rooms, VideoConference } from '@rocket.chat/models';
import { callbacks } from '../../../../lib/callbacks';
-import { broadcastMessageFromData } from '../../../../server/modules/watchers/lib/messages';
import { deleteRoom } from '../../../lib/server/functions/deleteRoom';
+import { notifyOnMessageChange } from '../../../lib/server/lib/notifyListener';
const updateAndNotifyParentRoomWithParentMessage = async (room: IRoom): Promise => {
const { value: parentMessage } = await Messages.refreshDiscussionMetadata(room);
if (!parentMessage) {
return;
}
- void broadcastMessageFromData({
+ void notifyOnMessageChange({
id: parentMessage._id,
data: parentMessage,
});
@@ -22,7 +22,7 @@ const updateAndNotifyParentRoomWithParentMessage = async (room: IRoom): Promise<
*/
callbacks.add(
'afterSaveMessage',
- async (message, { _id, prid }) => {
+ async (message, { room: { _id, prid } }) => {
if (!prid) {
return message;
}
diff --git a/apps/meteor/app/discussion/server/methods/createDiscussion.ts b/apps/meteor/app/discussion/server/methods/createDiscussion.ts
index 18b42ba1a31f..96e0bd846390 100644
--- a/apps/meteor/app/discussion/server/methods/createDiscussion.ts
+++ b/apps/meteor/app/discussion/server/methods/createDiscussion.ts
@@ -1,11 +1,10 @@
import { Message } from '@rocket.chat/core-services';
import type { IMessage, IRoom, IUser, MessageAttachmentDefault } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Messages, Rooms, Users } from '@rocket.chat/models';
import { Random } from '@rocket.chat/random';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
-import { callbacks } from '../../../../lib/callbacks';
import { i18n } from '../../../../server/lib/i18n';
import { roomCoordinator } from '../../../../server/lib/rooms/roomCoordinator';
import { canSendMessageAsync } from '../../../authorization/server/functions/canSendMessage';
@@ -14,6 +13,7 @@ import { addUserToRoom } from '../../../lib/server/functions/addUserToRoom';
import { attachMessage } from '../../../lib/server/functions/attachMessage';
import { createRoom } from '../../../lib/server/functions/createRoom';
import { sendMessage } from '../../../lib/server/functions/sendMessage';
+import { afterSaveMessageAsync } from '../../../lib/server/lib/afterSaveMessage';
import { settings } from '../../../settings/server';
const getParentRoom = async (rid: IRoom['_id']) => {
@@ -27,13 +27,11 @@ async function createDiscussionMessage(
drid: IRoom['_id'],
msg: IMessage['msg'],
messageEmbedded?: MessageAttachmentDefault,
-): Promise {
- const msgId = await Message.saveSystemMessage('discussion-created', rid, msg, user, {
+): Promise {
+ return Message.saveSystemMessage('discussion-created', rid, msg, user, {
drid,
...(messageEmbedded && { attachments: [messageEmbedded] }),
});
-
- return Messages.findOneById(msgId);
}
async function mentionMessage(
@@ -191,12 +189,13 @@ const create = async ({
}
if (discussionMsg) {
- callbacks.runAsync('afterSaveMessage', discussionMsg, parentRoom);
+ afterSaveMessageAsync(discussionMsg, parentRoom);
}
+
return discussion;
};
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
createDiscussion: typeof create;
diff --git a/apps/meteor/app/e2e/server/methods/fetchMyKeys.ts b/apps/meteor/app/e2e/server/methods/fetchMyKeys.ts
index 519317cb40fe..df1150cee846 100644
--- a/apps/meteor/app/e2e/server/methods/fetchMyKeys.ts
+++ b/apps/meteor/app/e2e/server/methods/fetchMyKeys.ts
@@ -1,8 +1,8 @@
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Users } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'e2e.fetchMyKeys'(): { public_key?: string; private_key?: string };
diff --git a/apps/meteor/app/e2e/server/methods/getUsersOfRoomWithoutKey.ts b/apps/meteor/app/e2e/server/methods/getUsersOfRoomWithoutKey.ts
index cc586676482f..1f1a21262de8 100644
--- a/apps/meteor/app/e2e/server/methods/getUsersOfRoomWithoutKey.ts
+++ b/apps/meteor/app/e2e/server/methods/getUsersOfRoomWithoutKey.ts
@@ -1,12 +1,12 @@
import type { IRoom, IUser } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Subscriptions, Users } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import { canAccessRoomIdAsync } from '../../../authorization/server/functions/canAccessRoom';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'e2e.getUsersOfRoomWithoutKey'(rid: IRoom['_id']): { users: Pick[] };
diff --git a/apps/meteor/app/e2e/server/methods/requestSubscriptionKeys.ts b/apps/meteor/app/e2e/server/methods/requestSubscriptionKeys.ts
index 8c5add77a0bf..cf899a5d64ad 100644
--- a/apps/meteor/app/e2e/server/methods/requestSubscriptionKeys.ts
+++ b/apps/meteor/app/e2e/server/methods/requestSubscriptionKeys.ts
@@ -1,9 +1,9 @@
import { api } from '@rocket.chat/core-services';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Subscriptions, Rooms } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'e2e.requestSubscriptionKeys'(): boolean;
diff --git a/apps/meteor/app/e2e/server/methods/resetOwnE2EKey.ts b/apps/meteor/app/e2e/server/methods/resetOwnE2EKey.ts
index 365feb1ac95d..b1d40e48bb5e 100644
--- a/apps/meteor/app/e2e/server/methods/resetOwnE2EKey.ts
+++ b/apps/meteor/app/e2e/server/methods/resetOwnE2EKey.ts
@@ -1,10 +1,10 @@
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
import { resetUserE2EEncriptionKey } from '../../../../server/lib/resetUserE2EKey';
import { twoFactorRequired } from '../../../2fa/server/twoFactorRequired';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'e2e.resetOwnE2EKey'(): Promise;
diff --git a/apps/meteor/app/e2e/server/methods/setRoomKeyID.ts b/apps/meteor/app/e2e/server/methods/setRoomKeyID.ts
index 6b0e685616b5..b52913e4f984 100644
--- a/apps/meteor/app/e2e/server/methods/setRoomKeyID.ts
+++ b/apps/meteor/app/e2e/server/methods/setRoomKeyID.ts
@@ -1,13 +1,13 @@
import type { IRoom } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Rooms } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import { canAccessRoomIdAsync } from '../../../authorization/server/functions/canAccessRoom';
import { notifyOnRoomChangedById } from '../../../lib/server/lib/notifyListener';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'e2e.setRoomKeyID'(rid: IRoom['_id'], keyID: string): void;
diff --git a/apps/meteor/app/e2e/server/methods/setUserPublicAndPrivateKeys.ts b/apps/meteor/app/e2e/server/methods/setUserPublicAndPrivateKeys.ts
index 94d252601bc4..6ef35a063a28 100644
--- a/apps/meteor/app/e2e/server/methods/setUserPublicAndPrivateKeys.ts
+++ b/apps/meteor/app/e2e/server/methods/setUserPublicAndPrivateKeys.ts
@@ -1,8 +1,8 @@
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Rooms, Users } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'e2e.setUserPublicAndPrivateKeys'({ public_key, private_key }: { public_key: string; private_key: string; force?: boolean }): void;
diff --git a/apps/meteor/app/e2e/server/methods/updateGroupKey.ts b/apps/meteor/app/e2e/server/methods/updateGroupKey.ts
index c856f8cf708a..5764a021f54c 100644
--- a/apps/meteor/app/e2e/server/methods/updateGroupKey.ts
+++ b/apps/meteor/app/e2e/server/methods/updateGroupKey.ts
@@ -1,10 +1,10 @@
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Subscriptions } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'e2e.updateGroupKey'(rid: string, uid: string, key: string): Promise;
diff --git a/apps/meteor/app/emoji-custom/server/lib/insertOrUpdateEmoji.ts b/apps/meteor/app/emoji-custom/server/lib/insertOrUpdateEmoji.ts
new file mode 100644
index 000000000000..7e838baee9b0
--- /dev/null
+++ b/apps/meteor/app/emoji-custom/server/lib/insertOrUpdateEmoji.ts
@@ -0,0 +1,148 @@
+import { api } from '@rocket.chat/core-services';
+import { EmojiCustom } from '@rocket.chat/models';
+import limax from 'limax';
+import { Meteor } from 'meteor/meteor';
+import _ from 'underscore';
+
+import { trim } from '../../../../lib/utils/stringUtils';
+import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
+import { RocketChatFileEmojiCustomInstance } from '../startup/emoji-custom';
+
+type EmojiData = {
+ _id?: string;
+ name: string;
+ aliases: string;
+ extension: string;
+ previousName?: string;
+ previousExtension?: string;
+ newFile?: boolean;
+};
+
+type EmojiDataWithParsedAliases = Omit & { _id: string; aliases: string[] };
+
+export async function insertOrUpdateEmoji(userId: string | null, emojiData: EmojiData): Promise {
+ if (!userId || !(await hasPermissionAsync(userId, 'manage-emoji'))) {
+ throw new Meteor.Error('not_authorized');
+ }
+
+ if (!trim(emojiData.name)) {
+ throw new Meteor.Error('error-the-field-is-required', 'The field Name is required', {
+ method: 'insertOrUpdateEmoji',
+ field: 'Name',
+ });
+ }
+
+ emojiData.name = limax(emojiData.name, { replacement: '_' });
+ emojiData.aliases = limax(emojiData.aliases, { replacement: '_' });
+
+ // allow all characters except colon, whitespace, comma, >, <, &, ", ', /, \, (, )
+ // more practical than allowing specific sets of characters; also allows foreign languages
+ const nameValidation = /[\s,:><&"'\/\\\(\)]/;
+ const aliasValidation = /[:><&\|"'\/\\\(\)]/;
+
+ // silently strip colon; this allows for uploading :emojiname: as emojiname
+ emojiData.name = emojiData.name.replace(/:/g, '');
+ emojiData.aliases = emojiData.aliases.replace(/:/g, '');
+
+ if (nameValidation.test(emojiData.name)) {
+ throw new Meteor.Error('error-input-is-not-a-valid-field', `${emojiData.name} is not a valid name`, {
+ method: 'insertOrUpdateEmoji',
+ input: emojiData.name,
+ field: 'Name',
+ });
+ }
+
+ let aliases: string[] = [];
+ if (emojiData.aliases) {
+ if (aliasValidation.test(emojiData.aliases)) {
+ throw new Meteor.Error('error-input-is-not-a-valid-field', `${emojiData.aliases} is not a valid alias set`, {
+ method: 'insertOrUpdateEmoji',
+ input: emojiData.aliases,
+ field: 'Alias_Set',
+ });
+ }
+ aliases = _.without(emojiData.aliases.split(/[\s,]/).filter(Boolean), emojiData.name);
+ }
+
+ emojiData.extension = emojiData.extension === 'svg+xml' ? 'png' : emojiData.extension;
+
+ let matchingResults = [];
+
+ if (emojiData._id) {
+ matchingResults = await EmojiCustom.findByNameOrAliasExceptID(emojiData.name, emojiData._id).toArray();
+ for await (const alias of aliases) {
+ matchingResults = matchingResults.concat(await EmojiCustom.findByNameOrAliasExceptID(alias, emojiData._id).toArray());
+ }
+ } else {
+ matchingResults = await EmojiCustom.findByNameOrAlias(emojiData.name).toArray();
+ for await (const alias of aliases) {
+ matchingResults = matchingResults.concat(await EmojiCustom.findByNameOrAlias(alias).toArray());
+ }
+ }
+
+ if (matchingResults.length > 0) {
+ throw new Meteor.Error('Custom_Emoji_Error_Name_Or_Alias_Already_In_Use', 'The custom emoji or one of its aliases is already in use', {
+ method: 'insertOrUpdateEmoji',
+ });
+ }
+
+ if (typeof emojiData.extension === 'undefined') {
+ throw new Meteor.Error('error-the-field-is-required', 'The custom emoji file is required', {
+ method: 'insertOrUpdateEmoji',
+ });
+ }
+
+ if (!emojiData._id) {
+ // insert emoji
+ const createEmoji = {
+ name: emojiData.name,
+ aliases,
+ extension: emojiData.extension,
+ };
+
+ const _id = (await EmojiCustom.create(createEmoji)).insertedId;
+
+ void api.broadcast('emoji.updateCustom', createEmoji);
+
+ return { ...emojiData, ...createEmoji, _id };
+ }
+
+ // update emoji
+ if (emojiData.newFile) {
+ await RocketChatFileEmojiCustomInstance.deleteFile(encodeURIComponent(`${emojiData.name}.${emojiData.extension}`));
+ await RocketChatFileEmojiCustomInstance.deleteFile(encodeURIComponent(`${emojiData.name}.${emojiData.previousExtension}`));
+ await RocketChatFileEmojiCustomInstance.deleteFile(encodeURIComponent(`${emojiData.previousName}.${emojiData.extension}`));
+ await RocketChatFileEmojiCustomInstance.deleteFile(encodeURIComponent(`${emojiData.previousName}.${emojiData.previousExtension}`));
+
+ await EmojiCustom.setExtension(emojiData._id, emojiData.extension);
+ } else if (emojiData.name !== emojiData.previousName) {
+ const rs = await RocketChatFileEmojiCustomInstance.getFileWithReadStream(
+ encodeURIComponent(`${emojiData.previousName}.${emojiData.previousExtension}`),
+ );
+ if (rs !== null) {
+ await RocketChatFileEmojiCustomInstance.deleteFile(encodeURIComponent(`${emojiData.name}.${emojiData.extension}`));
+ const ws = RocketChatFileEmojiCustomInstance.createWriteStream(
+ encodeURIComponent(`${emojiData.name}.${emojiData.previousExtension}`),
+ rs.contentType,
+ );
+ ws.on('end', () =>
+ RocketChatFileEmojiCustomInstance.deleteFile(encodeURIComponent(`${emojiData.previousName}.${emojiData.previousExtension}`)),
+ );
+ rs.readStream.pipe(ws);
+ }
+ }
+
+ if (emojiData.name !== emojiData.previousName) {
+ await EmojiCustom.setName(emojiData._id, emojiData.name);
+ }
+
+ if (emojiData.aliases) {
+ await EmojiCustom.setAliases(emojiData._id, aliases);
+ } else {
+ await EmojiCustom.setAliases(emojiData._id, []);
+ }
+
+ void api.broadcast('emoji.updateCustom', { ...emojiData, aliases });
+
+ return { ...emojiData, aliases } as EmojiDataWithParsedAliases;
+}
diff --git a/apps/meteor/app/emoji-custom/server/lib/uploadEmojiCustom.ts b/apps/meteor/app/emoji-custom/server/lib/uploadEmojiCustom.ts
new file mode 100644
index 000000000000..07633eaa1a7d
--- /dev/null
+++ b/apps/meteor/app/emoji-custom/server/lib/uploadEmojiCustom.ts
@@ -0,0 +1,77 @@
+import { api, Media } from '@rocket.chat/core-services';
+import limax from 'limax';
+import { Meteor } from 'meteor/meteor';
+import sharp from 'sharp';
+
+import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
+import { RocketChatFile } from '../../../file/server';
+import { RocketChatFileEmojiCustomInstance } from '../startup/emoji-custom';
+
+const getFile = async (file: Buffer, extension: string) => {
+ if (extension !== 'svg+xml') {
+ return file;
+ }
+
+ return sharp(file).png().toBuffer();
+};
+
+type EmojiData = {
+ _id?: string;
+ name: string;
+ aliases?: string | string[];
+ extension: string;
+ previousName?: string;
+ previousExtension?: string;
+ newFile?: boolean;
+};
+
+export async function uploadEmojiCustom(userId: string | null, binaryContent: string, contentType: string, emojiData: EmojiData) {
+ return uploadEmojiCustomWithBuffer(userId, Buffer.from(binaryContent, 'binary'), contentType, emojiData);
+}
+
+export async function uploadEmojiCustomWithBuffer(
+ userId: string | null,
+ buffer: Buffer,
+ contentType: string,
+ emojiData: EmojiData,
+): Promise {
+ // technically, since this method doesnt have any datatype validations, users can
+ // upload videos as emojis. The FE won't play them, but they will waste space for sure.
+ if (!userId || !(await hasPermissionAsync(userId, 'manage-emoji'))) {
+ throw new Meteor.Error('not_authorized');
+ }
+
+ emojiData.name = limax(emojiData.name, { replacement: '_' });
+ // delete aliases for notification purposes. here, it is a string rather than an array
+ delete emojiData.aliases;
+
+ const file = await getFile(buffer, emojiData.extension);
+ emojiData.extension = emojiData.extension === 'svg+xml' ? 'png' : emojiData.extension;
+
+ let fileBuffer;
+ // sharp doesn't support these formats without imagemagick or libvips installed
+ // so they will be stored as they are :(
+ if (['gif', 'x-icon', 'bmp', 'webm'].includes(emojiData.extension)) {
+ fileBuffer = file;
+ } else {
+ // This is to support the idea of having "sticker-like" emojis
+ const { data: resizedEmojiBuffer } = await Media.resizeFromBuffer(file, 512, 512, true, false, false, 'inside');
+ fileBuffer = resizedEmojiBuffer;
+ }
+
+ const rs = RocketChatFile.bufferToStream(fileBuffer);
+ await RocketChatFileEmojiCustomInstance.deleteFile(encodeURIComponent(`${emojiData.name}.${emojiData.extension}`));
+
+ return new Promise((resolve) => {
+ const ws = RocketChatFileEmojiCustomInstance.createWriteStream(
+ encodeURIComponent(`${emojiData.name}.${emojiData.extension}`),
+ contentType,
+ );
+ ws.on('end', () => {
+ setTimeout(() => api.broadcast('emoji.updateCustom', emojiData), 500);
+ resolve();
+ });
+
+ rs.pipe(ws);
+ });
+}
diff --git a/apps/meteor/app/emoji-custom/server/methods/deleteEmojiCustom.ts b/apps/meteor/app/emoji-custom/server/methods/deleteEmojiCustom.ts
index 555d5544ab33..c16d3b82449b 100644
--- a/apps/meteor/app/emoji-custom/server/methods/deleteEmojiCustom.ts
+++ b/apps/meteor/app/emoji-custom/server/methods/deleteEmojiCustom.ts
@@ -1,13 +1,13 @@
import { api } from '@rocket.chat/core-services';
import type { ICustomEmojiDescriptor } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { EmojiCustom } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
import { RocketChatFileEmojiCustomInstance } from '../startup/emoji-custom';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
deleteEmojiCustom(emojiID: ICustomEmojiDescriptor['_id']): boolean;
diff --git a/apps/meteor/app/emoji-custom/server/methods/insertOrUpdateEmoji.ts b/apps/meteor/app/emoji-custom/server/methods/insertOrUpdateEmoji.ts
index 874180097cb9..1891d1b3ed95 100644
--- a/apps/meteor/app/emoji-custom/server/methods/insertOrUpdateEmoji.ts
+++ b/apps/meteor/app/emoji-custom/server/methods/insertOrUpdateEmoji.ts
@@ -1,15 +1,9 @@
-import { api } from '@rocket.chat/core-services';
-import { EmojiCustom } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
-import limax from 'limax';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
-import _ from 'underscore';
-import { trim } from '../../../../lib/utils/stringUtils';
-import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
-import { RocketChatFileEmojiCustomInstance } from '../startup/emoji-custom';
+import { insertOrUpdateEmoji } from '../lib/insertOrUpdateEmoji';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
insertOrUpdateEmoji(emojiData: {
@@ -26,130 +20,12 @@ declare module '@rocket.chat/ui-contexts' {
Meteor.methods({
async insertOrUpdateEmoji(emojiData) {
- if (!this.userId || !(await hasPermissionAsync(this.userId, 'manage-emoji'))) {
- throw new Meteor.Error('not_authorized');
- }
-
- if (!trim(emojiData.name)) {
- throw new Meteor.Error('error-the-field-is-required', 'The field Name is required', {
- method: 'insertOrUpdateEmoji',
- field: 'Name',
- });
- }
-
- emojiData.name = limax(emojiData.name, { replacement: '_' });
- emojiData.aliases = limax(emojiData.aliases, { replacement: '_' });
-
- // allow all characters except colon, whitespace, comma, >, <, &, ", ', /, \, (, )
- // more practical than allowing specific sets of characters; also allows foreign languages
- const nameValidation = /[\s,:><&"'\/\\\(\)]/;
- const aliasValidation = /[:><&\|"'\/\\\(\)]/;
-
- // silently strip colon; this allows for uploading :emojiname: as emojiname
- emojiData.name = emojiData.name.replace(/:/g, '');
- emojiData.aliases = emojiData.aliases.replace(/:/g, '');
-
- if (nameValidation.test(emojiData.name)) {
- throw new Meteor.Error('error-input-is-not-a-valid-field', `${emojiData.name} is not a valid name`, {
- method: 'insertOrUpdateEmoji',
- input: emojiData.name,
- field: 'Name',
- });
- }
-
- let aliases: string[] = [];
- if (emojiData.aliases) {
- if (aliasValidation.test(emojiData.aliases)) {
- throw new Meteor.Error('error-input-is-not-a-valid-field', `${emojiData.aliases} is not a valid alias set`, {
- method: 'insertOrUpdateEmoji',
- input: emojiData.aliases,
- field: 'Alias_Set',
- });
- }
- aliases = _.without(emojiData.aliases.split(/[\s,]/).filter(Boolean), emojiData.name);
- }
-
- emojiData.extension = emojiData.extension === 'svg+xml' ? 'png' : emojiData.extension;
-
- let matchingResults = [];
-
- if (emojiData._id) {
- matchingResults = await EmojiCustom.findByNameOrAliasExceptID(emojiData.name, emojiData._id).toArray();
- for await (const alias of aliases) {
- matchingResults = matchingResults.concat(await EmojiCustom.findByNameOrAliasExceptID(alias, emojiData._id).toArray());
- }
- } else {
- matchingResults = await EmojiCustom.findByNameOrAlias(emojiData.name).toArray();
- for await (const alias of aliases) {
- matchingResults = matchingResults.concat(await EmojiCustom.findByNameOrAlias(alias).toArray());
- }
- }
-
- if (matchingResults.length > 0) {
- throw new Meteor.Error(
- 'Custom_Emoji_Error_Name_Or_Alias_Already_In_Use',
- 'The custom emoji or one of its aliases is already in use',
- { method: 'insertOrUpdateEmoji' },
- );
- }
-
- if (typeof emojiData.extension === 'undefined') {
- throw new Meteor.Error('error-the-field-is-required', 'The custom emoji file is required', {
- method: 'insertOrUpdateEmoji',
- });
- }
+ const emoji = await insertOrUpdateEmoji(this.userId, emojiData);
if (!emojiData._id) {
- // insert emoji
- const createEmoji = {
- name: emojiData.name,
- aliases,
- extension: emojiData.extension,
- };
-
- const _id = (await EmojiCustom.create(createEmoji)).insertedId;
-
- void api.broadcast('emoji.updateCustom', createEmoji);
-
- return _id;
+ return emoji._id;
}
- // update emoji
- if (emojiData.newFile) {
- await RocketChatFileEmojiCustomInstance.deleteFile(encodeURIComponent(`${emojiData.name}.${emojiData.extension}`));
- await RocketChatFileEmojiCustomInstance.deleteFile(encodeURIComponent(`${emojiData.name}.${emojiData.previousExtension}`));
- await RocketChatFileEmojiCustomInstance.deleteFile(encodeURIComponent(`${emojiData.previousName}.${emojiData.extension}`));
- await RocketChatFileEmojiCustomInstance.deleteFile(encodeURIComponent(`${emojiData.previousName}.${emojiData.previousExtension}`));
-
- await EmojiCustom.setExtension(emojiData._id, emojiData.extension);
- } else if (emojiData.name !== emojiData.previousName) {
- const rs = await RocketChatFileEmojiCustomInstance.getFileWithReadStream(
- encodeURIComponent(`${emojiData.previousName}.${emojiData.previousExtension}`),
- );
- if (rs !== null) {
- await RocketChatFileEmojiCustomInstance.deleteFile(encodeURIComponent(`${emojiData.name}.${emojiData.extension}`));
- const ws = RocketChatFileEmojiCustomInstance.createWriteStream(
- encodeURIComponent(`${emojiData.name}.${emojiData.previousExtension}`),
- rs.contentType,
- );
- ws.on('end', () =>
- RocketChatFileEmojiCustomInstance.deleteFile(encodeURIComponent(`${emojiData.previousName}.${emojiData.previousExtension}`)),
- );
- rs.readStream.pipe(ws);
- }
- }
-
- if (emojiData.name !== emojiData.previousName) {
- await EmojiCustom.setName(emojiData._id, emojiData.name);
- }
-
- if (emojiData.aliases) {
- await EmojiCustom.setAliases(emojiData._id, aliases);
- } else {
- await EmojiCustom.setAliases(emojiData._id, []);
- }
-
- void api.broadcast('emoji.updateCustom', emojiData);
- return true;
+ return !!emoji;
},
});
diff --git a/apps/meteor/app/emoji-custom/server/methods/listEmojiCustom.ts b/apps/meteor/app/emoji-custom/server/methods/listEmojiCustom.ts
index 485737b95f9b..a16d536d92d4 100644
--- a/apps/meteor/app/emoji-custom/server/methods/listEmojiCustom.ts
+++ b/apps/meteor/app/emoji-custom/server/methods/listEmojiCustom.ts
@@ -1,12 +1,12 @@
import type { IEmojiCustom } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { EmojiCustom } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { check, Match } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
listEmojiCustom(options?: { name?: string; aliases?: string[] }): IEmojiCustom[];
diff --git a/apps/meteor/app/emoji-custom/server/methods/uploadEmojiCustom.ts b/apps/meteor/app/emoji-custom/server/methods/uploadEmojiCustom.ts
index ded98b7f5469..e387888b1311 100644
--- a/apps/meteor/app/emoji-custom/server/methods/uploadEmojiCustom.ts
+++ b/apps/meteor/app/emoji-custom/server/methods/uploadEmojiCustom.ts
@@ -1,22 +1,9 @@
-import { api, Media } from '@rocket.chat/core-services';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
-import limax from 'limax';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
-import sharp from 'sharp';
-import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
-import { RocketChatFile } from '../../../file/server';
-import { RocketChatFileEmojiCustomInstance } from '../startup/emoji-custom';
+import { uploadEmojiCustom } from '../lib/uploadEmojiCustom';
-const getFile = async (file: Buffer, extension: string) => {
- if (extension !== 'svg+xml') {
- return file;
- }
-
- return sharp(file).png().toBuffer();
-};
-
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
uploadEmojiCustom(
@@ -33,44 +20,6 @@ declare module '@rocket.chat/ui-contexts' {
Meteor.methods({
async uploadEmojiCustom(binaryContent, contentType, emojiData) {
- // technically, since this method doesnt have any datatype validations, users can
- // upload videos as emojis. The FE won't play them, but they will waste space for sure.
- if (!this.userId || !(await hasPermissionAsync(this.userId, 'manage-emoji'))) {
- throw new Meteor.Error('not_authorized');
- }
-
- emojiData.name = limax(emojiData.name, { replacement: '_' });
- // delete aliases for notification purposes. here, it is a string rather than an array
- delete emojiData.aliases;
-
- const file = await getFile(Buffer.from(binaryContent, 'binary'), emojiData.extension);
- emojiData.extension = emojiData.extension === 'svg+xml' ? 'png' : emojiData.extension;
-
- let fileBuffer;
- // sharp doesn't support these formats without imagemagick or libvips installed
- // so they will be stored as they are :(
- if (['gif', 'x-icon', 'bmp', 'webm'].includes(emojiData.extension)) {
- fileBuffer = file;
- } else {
- // This is to support the idea of having "sticker-like" emojis
- const { data: resizedEmojiBuffer } = await Media.resizeFromBuffer(file, 512, 512, true, false, false, 'inside');
- fileBuffer = resizedEmojiBuffer;
- }
-
- const rs = RocketChatFile.bufferToStream(fileBuffer);
- await RocketChatFileEmojiCustomInstance.deleteFile(encodeURIComponent(`${emojiData.name}.${emojiData.extension}`));
-
- return new Promise((resolve) => {
- const ws = RocketChatFileEmojiCustomInstance.createWriteStream(
- encodeURIComponent(`${emojiData.name}.${emojiData.extension}`),
- contentType,
- );
- ws.on('end', () => {
- setTimeout(() => api.broadcast('emoji.updateCustom', emojiData), 500);
- resolve();
- });
-
- rs.pipe(ws);
- });
+ await uploadEmojiCustom(this.userId, binaryContent, contentType, emojiData);
},
});
diff --git a/apps/meteor/app/federation/server/endpoints/dispatch.js b/apps/meteor/app/federation/server/endpoints/dispatch.js
index 4cab0b0c41e8..7090f053a22b 100644
--- a/apps/meteor/app/federation/server/endpoints/dispatch.js
+++ b/apps/meteor/app/federation/server/endpoints/dispatch.js
@@ -3,11 +3,10 @@ import { eventTypes } from '@rocket.chat/core-typings';
import { FederationServers, FederationRoomEvents, Rooms, Messages, Subscriptions, Users, ReadReceipts } from '@rocket.chat/models';
import EJSON from 'ejson';
-import { broadcastMessageFromData } from '../../../../server/modules/watchers/lib/messages';
import { API } from '../../../api/server';
import { FileUpload } from '../../../file-upload/server';
import { deleteRoom } from '../../../lib/server/functions/deleteRoom';
-import { notifyOnRoomChanged, notifyOnRoomChangedById } from '../../../lib/server/lib/notifyListener';
+import { notifyOnMessageChange, notifyOnRoomChanged, notifyOnRoomChangedById } from '../../../lib/server/lib/notifyListener';
import { notifyUsersOnMessage } from '../../../lib/server/lib/notifyUsersOnMessage';
import { sendAllNotifications } from '../../../lib/server/lib/sendNotificationsOnMessage';
import { processThreads } from '../../../threads/server/hooks/aftersavemessage';
@@ -294,8 +293,12 @@ const eventHandlers = {
await processThreads(denormalizedMessage, room);
- // Notify users
- await notifyUsersOnMessage(denormalizedMessage, room);
+ const roomUpdater = Rooms.getUpdater();
+ await notifyUsersOnMessage(denormalizedMessage, room, roomUpdater);
+ if (roomUpdater.hasChanges()) {
+ await Rooms.updateFromUpdater({ _id: room._id }, roomUpdater);
+ }
+
sendAllNotifications(denormalizedMessage, room);
messageForNotification = denormalizedMessage;
} catch (err) {
@@ -303,7 +306,7 @@ const eventHandlers = {
}
}
if (messageForNotification) {
- void broadcastMessageFromData({
+ void notifyOnMessageChange({
id: messageForNotification._id,
data: messageForNotification,
});
@@ -334,7 +337,7 @@ const eventHandlers = {
} else {
// Update the message
await Messages.updateOne({ _id: persistedMessage._id }, { $set: { msg: message.msg, federation: message.federation } });
- void broadcastMessageFromData({
+ void notifyOnMessageChange({
id: persistedMessage._id,
data: {
...persistedMessage,
@@ -404,7 +407,7 @@ const eventHandlers = {
// Update the property
await Messages.updateOne({ _id: messageId }, { $set: { [`reactions.${reaction}`]: reactionObj } });
- void broadcastMessageFromData({
+ void notifyOnMessageChange({
id: persistedMessage._id,
data: {
...persistedMessage,
@@ -462,7 +465,7 @@ const eventHandlers = {
// Otherwise, update the property
await Messages.updateOne({ _id: messageId }, { $set: { [`reactions.${reaction}`]: reactionObj } });
}
- void broadcastMessageFromData({
+ void notifyOnMessageChange({
id: persistedMessage._id,
data: {
...persistedMessage,
diff --git a/apps/meteor/app/federation/server/hooks/afterSaveMessage.js b/apps/meteor/app/federation/server/hooks/afterSaveMessage.js
index 7f67f4770686..20c64f87dda8 100644
--- a/apps/meteor/app/federation/server/hooks/afterSaveMessage.js
+++ b/apps/meteor/app/federation/server/hooks/afterSaveMessage.js
@@ -6,7 +6,7 @@ import { getFederationDomain } from '../lib/getFederationDomain';
import { clientLogger } from '../lib/logger';
import { normalizers } from '../normalizers';
-async function afterSaveMessage(message, room) {
+async function afterSaveMessage(message, { room }) {
// If there are not federated users on this room, ignore it
if (!hasExternalDomain(room)) {
return message;
diff --git a/apps/meteor/app/federation/server/methods/dashboard.ts b/apps/meteor/app/federation/server/methods/dashboard.ts
index 90a050556893..eacb42b24cbb 100644
--- a/apps/meteor/app/federation/server/methods/dashboard.ts
+++ b/apps/meteor/app/federation/server/methods/dashboard.ts
@@ -1,10 +1,10 @@
import type { IFederationServer } from '@rocket.chat/core-typings';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
import { federationGetServers, federationGetOverviewData } from '../functions/dashboard';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'federation:getServers': () => { data: IFederationServer[] };
diff --git a/apps/meteor/app/federation/server/methods/loadContextEvents.ts b/apps/meteor/app/federation/server/methods/loadContextEvents.ts
index 9e286bbf913a..e20acb7e37c9 100644
--- a/apps/meteor/app/federation/server/methods/loadContextEvents.ts
+++ b/apps/meteor/app/federation/server/methods/loadContextEvents.ts
@@ -1,11 +1,11 @@
import type { IFederationEvent } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { FederationRoomEvents } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'federation:loadContextEvents'(latestEventTimestamp: number): IFederationEvent[];
diff --git a/apps/meteor/app/federation/server/methods/testSetup.ts b/apps/meteor/app/federation/server/methods/testSetup.ts
index 93e501535474..bc50ef158194 100644
--- a/apps/meteor/app/federation/server/methods/testSetup.ts
+++ b/apps/meteor/app/federation/server/methods/testSetup.ts
@@ -1,11 +1,11 @@
import { eventTypes } from '@rocket.chat/core-typings';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
import { dispatchEvent } from '../handler';
import { getFederationDomain } from '../lib/getFederationDomain';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
FEDERATION_Test_Setup(): { message: string };
diff --git a/apps/meteor/app/file-upload/server/methods/getS3FileUrl.ts b/apps/meteor/app/file-upload/server/methods/getS3FileUrl.ts
index fdb8d131916d..3e9bcd192674 100644
--- a/apps/meteor/app/file-upload/server/methods/getS3FileUrl.ts
+++ b/apps/meteor/app/file-upload/server/methods/getS3FileUrl.ts
@@ -1,5 +1,5 @@
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Rooms, Uploads } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
@@ -7,7 +7,7 @@ import { UploadFS } from '../../../../server/ufs';
import { canAccessRoomAsync } from '../../../authorization/server';
import { settings } from '../../../settings/server';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
getS3FileUrl(fileId: string): string;
diff --git a/apps/meteor/app/file-upload/server/methods/sendFileMessage.ts b/apps/meteor/app/file-upload/server/methods/sendFileMessage.ts
index 485528a5e62f..73dfd0216a73 100644
--- a/apps/meteor/app/file-upload/server/methods/sendFileMessage.ts
+++ b/apps/meteor/app/file-upload/server/methods/sendFileMessage.ts
@@ -7,8 +7,8 @@ import type {
FilesAndAttachments,
IMessage,
} from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Rooms, Uploads, Users } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Match, check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
@@ -141,7 +141,7 @@ export const parseFileIntoMessageAttachments = async (
return { files, attachments };
};
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
sendFileMessage: (roomId: string, _store: string, file: Partial, msgData?: Record) => boolean;
diff --git a/apps/meteor/app/iframe-login/server/iframe_server.ts b/apps/meteor/app/iframe-login/server/iframe_server.ts
index c7e67edf9deb..b3e661cf6ff3 100644
--- a/apps/meteor/app/iframe-login/server/iframe_server.ts
+++ b/apps/meteor/app/iframe-login/server/iframe_server.ts
@@ -1,5 +1,5 @@
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Users } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Accounts } from 'meteor/accounts-base';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
@@ -23,7 +23,7 @@ Accounts.registerLoginHandler('iframe', async (result) => {
}
});
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'OAuth.retrieveCredential'(credentialToken: string, credentialSecret: string): unknown;
diff --git a/apps/meteor/app/importer/server/methods/downloadPublicImportFile.ts b/apps/meteor/app/importer/server/methods/downloadPublicImportFile.ts
index 81e06ec8eb0f..d2da85c7cfd4 100644
--- a/apps/meteor/app/importer/server/methods/downloadPublicImportFile.ts
+++ b/apps/meteor/app/importer/server/methods/downloadPublicImportFile.ts
@@ -4,7 +4,7 @@ import https from 'https';
import { Import } from '@rocket.chat/core-services';
import type { IUser } from '@rocket.chat/core-typings';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
import { Importers } from '..';
@@ -75,7 +75,7 @@ export const executeDownloadPublicImportFile = async (userId: IUser['_id'], file
}
};
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
downloadPublicImportFile(fileUrl: string, importerKey: string): void;
diff --git a/apps/meteor/app/importer/server/methods/getImportFileData.ts b/apps/meteor/app/importer/server/methods/getImportFileData.ts
index 03f9a53abe6c..1d36f7fc5a5e 100644
--- a/apps/meteor/app/importer/server/methods/getImportFileData.ts
+++ b/apps/meteor/app/importer/server/methods/getImportFileData.ts
@@ -2,8 +2,8 @@ import fs from 'fs';
import path from 'path';
import type { IImportProgress, IImporterSelection } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Imports } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { Importers } from '..';
@@ -61,7 +61,7 @@ export const executeGetImportFileData = async (): Promise => {
return instance.getProgress();
};
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
getImportProgress(): IImportProgress;
diff --git a/apps/meteor/app/importer/server/methods/getLatestImportOperations.ts b/apps/meteor/app/importer/server/methods/getLatestImportOperations.ts
index edf021a19eac..0471cb57955d 100644
--- a/apps/meteor/app/importer/server/methods/getLatestImportOperations.ts
+++ b/apps/meteor/app/importer/server/methods/getLatestImportOperations.ts
@@ -1,6 +1,6 @@
import type { IImport } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Imports } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
@@ -17,7 +17,7 @@ export const executeGetLatestImportOperations = async () => {
return data.toArray();
};
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
getLatestImportOperations(): IImport[];
diff --git a/apps/meteor/app/importer/server/methods/startImport.ts b/apps/meteor/app/importer/server/methods/startImport.ts
index af91295ede29..bbb5ce76ad1c 100644
--- a/apps/meteor/app/importer/server/methods/startImport.ts
+++ b/apps/meteor/app/importer/server/methods/startImport.ts
@@ -1,7 +1,7 @@
import type { IUser } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Imports } from '@rocket.chat/models';
import type { StartImportParamsPOST } from '@rocket.chat/rest-typings';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { Importers, Selection, SelectionChannel, SelectionUser } from '..';
@@ -32,7 +32,7 @@ export const executeStartImport = async ({ input }: StartImportParamsPOST, start
await instance.startImport(selection, startedByUserId);
};
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
startImport(params: StartImportParamsPOST): void;
diff --git a/apps/meteor/app/importer/server/methods/uploadImportFile.ts b/apps/meteor/app/importer/server/methods/uploadImportFile.ts
index d6ded455793b..df5d2af883fa 100644
--- a/apps/meteor/app/importer/server/methods/uploadImportFile.ts
+++ b/apps/meteor/app/importer/server/methods/uploadImportFile.ts
@@ -1,6 +1,6 @@
import { Import } from '@rocket.chat/core-services';
import type { IUser } from '@rocket.chat/core-typings';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
import { Importers } from '..';
@@ -55,7 +55,7 @@ export const executeUploadImportFile = async (
await instance.updateProgress(ProgressStep.FILE_LOADED);
};
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
uploadImportFile(binaryContent: string, contentType: string, fileName: string, importerKey: string): void;
diff --git a/apps/meteor/app/integrations/server/methods/clearIntegrationHistory.ts b/apps/meteor/app/integrations/server/methods/clearIntegrationHistory.ts
index 5b8f13ef1a3a..a30bb9b5ee9a 100644
--- a/apps/meteor/app/integrations/server/methods/clearIntegrationHistory.ts
+++ b/apps/meteor/app/integrations/server/methods/clearIntegrationHistory.ts
@@ -1,11 +1,11 @@
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Integrations, IntegrationHistory } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
import notifications from '../../../notifications/server/lib/Notifications';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
clearIntegrationHistory(integrationId: string): Promise;
diff --git a/apps/meteor/app/integrations/server/methods/incoming/addIncomingIntegration.ts b/apps/meteor/app/integrations/server/methods/incoming/addIncomingIntegration.ts
index db058bec960b..8f1f1b5dd576 100644
--- a/apps/meteor/app/integrations/server/methods/incoming/addIncomingIntegration.ts
+++ b/apps/meteor/app/integrations/server/methods/incoming/addIncomingIntegration.ts
@@ -1,7 +1,7 @@
import type { INewIncomingIntegration, IIncomingIntegration } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Integrations, Roles, Subscriptions, Users, Rooms } from '@rocket.chat/models';
import { Random } from '@rocket.chat/random';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Babel } from 'meteor/babel-compiler';
import { Match, check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
@@ -13,7 +13,7 @@ import { validateScriptEngine, isScriptEngineFrozen } from '../../lib/validateSc
const validChannelChars = ['@', '#'];
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
addIncomingIntegration(integration: INewIncomingIntegration): Promise;
diff --git a/apps/meteor/app/integrations/server/methods/incoming/deleteIncomingIntegration.ts b/apps/meteor/app/integrations/server/methods/incoming/deleteIncomingIntegration.ts
index e73a46bb27db..9a116f51bbaf 100644
--- a/apps/meteor/app/integrations/server/methods/incoming/deleteIncomingIntegration.ts
+++ b/apps/meteor/app/integrations/server/methods/incoming/deleteIncomingIntegration.ts
@@ -1,11 +1,11 @@
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Integrations } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../../authorization/server/functions/hasPermission';
import { notifyOnIntegrationChangedById } from '../../../../lib/server/lib/notifyListener';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
deleteIncomingIntegration(integrationId: string): Promise;
diff --git a/apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts b/apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts
index 0ea5028130da..c94b7b9fd7a8 100644
--- a/apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts
+++ b/apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts
@@ -1,7 +1,7 @@
import type { IIntegration, INewIncomingIntegration, IUpdateIncomingIntegration } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Integrations, Roles, Subscriptions, Users, Rooms } from '@rocket.chat/models';
import { wrapExceptions } from '@rocket.chat/tools';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Babel } from 'meteor/babel-compiler';
import { Meteor } from 'meteor/meteor';
import _ from 'underscore';
@@ -12,7 +12,7 @@ import { isScriptEngineFrozen, validateScriptEngine } from '../../lib/validateSc
const validChannelChars = ['@', '#'];
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
updateIncomingIntegration(
diff --git a/apps/meteor/app/integrations/server/methods/outgoing/addOutgoingIntegration.ts b/apps/meteor/app/integrations/server/methods/outgoing/addOutgoingIntegration.ts
index c8dc31e08446..dc54c76b1897 100644
--- a/apps/meteor/app/integrations/server/methods/outgoing/addOutgoingIntegration.ts
+++ b/apps/meteor/app/integrations/server/methods/outgoing/addOutgoingIntegration.ts
@@ -1,6 +1,6 @@
import type { INewOutgoingIntegration, IOutgoingIntegration } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Integrations } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Match, check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
@@ -9,7 +9,7 @@ import { notifyOnIntegrationChanged } from '../../../../lib/server/lib/notifyLis
import { validateOutgoingIntegration } from '../../lib/validateOutgoingIntegration';
import { validateScriptEngine } from '../../lib/validateScriptEngine';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
addOutgoingIntegration(integration: INewOutgoingIntegration): Promise;
diff --git a/apps/meteor/app/integrations/server/methods/outgoing/deleteOutgoingIntegration.ts b/apps/meteor/app/integrations/server/methods/outgoing/deleteOutgoingIntegration.ts
index c9f2211d835b..46d4c65159c0 100644
--- a/apps/meteor/app/integrations/server/methods/outgoing/deleteOutgoingIntegration.ts
+++ b/apps/meteor/app/integrations/server/methods/outgoing/deleteOutgoingIntegration.ts
@@ -1,11 +1,11 @@
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Integrations, IntegrationHistory } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../../authorization/server/functions/hasPermission';
import { notifyOnIntegrationChangedById } from '../../../../lib/server/lib/notifyListener';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
deleteOutgoingIntegration(integrationId: string): Promise;
diff --git a/apps/meteor/app/integrations/server/methods/outgoing/replayOutgoingIntegration.ts b/apps/meteor/app/integrations/server/methods/outgoing/replayOutgoingIntegration.ts
index 417c308ca6cb..83c13f2d981b 100644
--- a/apps/meteor/app/integrations/server/methods/outgoing/replayOutgoingIntegration.ts
+++ b/apps/meteor/app/integrations/server/methods/outgoing/replayOutgoingIntegration.ts
@@ -1,11 +1,11 @@
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Integrations, IntegrationHistory } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../../authorization/server/functions/hasPermission';
import { triggerHandler } from '../../lib/triggerHandler';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
replayOutgoingIntegration(params: { integrationId: string; historyId: string }): Promise;
diff --git a/apps/meteor/app/integrations/server/methods/outgoing/updateOutgoingIntegration.ts b/apps/meteor/app/integrations/server/methods/outgoing/updateOutgoingIntegration.ts
index 116dbd043039..c9b1f4ed7d64 100644
--- a/apps/meteor/app/integrations/server/methods/outgoing/updateOutgoingIntegration.ts
+++ b/apps/meteor/app/integrations/server/methods/outgoing/updateOutgoingIntegration.ts
@@ -1,7 +1,7 @@
import type { IIntegration, INewOutgoingIntegration, IUpdateOutgoingIntegration } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Integrations, Users } from '@rocket.chat/models';
import { wrapExceptions } from '@rocket.chat/tools';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../../authorization/server/functions/hasPermission';
@@ -9,7 +9,7 @@ import { notifyOnIntegrationChanged } from '../../../../lib/server/lib/notifyLis
import { validateOutgoingIntegration } from '../../lib/validateOutgoingIntegration';
import { isScriptEngineFrozen, validateScriptEngine } from '../../lib/validateScriptEngine';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
updateOutgoingIntegration(
diff --git a/apps/meteor/app/irc/server/methods/resetIrcConnection.ts b/apps/meteor/app/irc/server/methods/resetIrcConnection.ts
index 24eef975d5d5..aaaeef1c06b8 100644
--- a/apps/meteor/app/irc/server/methods/resetIrcConnection.ts
+++ b/apps/meteor/app/irc/server/methods/resetIrcConnection.ts
@@ -1,12 +1,12 @@
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Settings } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { notifyOnSettingChangedById } from '../../../lib/server/lib/notifyListener';
import { settings } from '../../../settings/server';
import Bridge from '../irc-bridge';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
resetIrcConnection(): { message: string; params: unknown[] };
diff --git a/apps/meteor/app/lib/client/methods/sendMessage.ts b/apps/meteor/app/lib/client/methods/sendMessage.ts
index e824c9e491af..bdaca587493a 100644
--- a/apps/meteor/app/lib/client/methods/sendMessage.ts
+++ b/apps/meteor/app/lib/client/methods/sendMessage.ts
@@ -1,5 +1,5 @@
import type { IMessage, IUser } from '@rocket.chat/core-typings';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
import { onClientMessageReceived } from '../../../../client/lib/onClientMessageReceived';
diff --git a/apps/meteor/app/lib/server/functions/createRoom.ts b/apps/meteor/app/lib/server/functions/createRoom.ts
index 19e5fb2f9489..183cb789051f 100644
--- a/apps/meteor/app/lib/server/functions/createRoom.ts
+++ b/apps/meteor/app/lib/server/functions/createRoom.ts
@@ -112,6 +112,7 @@ export const createRoom = async (
readOnly?: boolean,
roomExtraData?: Partial,
options?: ICreateRoomParams['options'],
+ sidepanel?: ICreateRoomParams['sidepanel'],
): Promise<
ICreatedRoom & {
rid: string;
@@ -187,6 +188,7 @@ export const createRoom = async (
},
ts: now,
ro: readOnly === true,
+ sidepanel,
};
if (teamId) {
diff --git a/apps/meteor/app/lib/server/functions/deleteMessage.ts b/apps/meteor/app/lib/server/functions/deleteMessage.ts
index e977874b3454..04542d5f1d27 100644
--- a/apps/meteor/app/lib/server/functions/deleteMessage.ts
+++ b/apps/meteor/app/lib/server/functions/deleteMessage.ts
@@ -5,11 +5,10 @@ import { Messages, Rooms, Uploads, Users, ReadReceipts } from '@rocket.chat/mode
import { Meteor } from 'meteor/meteor';
import { callbacks } from '../../../../lib/callbacks';
-import { broadcastMessageFromData } from '../../../../server/modules/watchers/lib/messages';
import { canDeleteMessageAsync } from '../../../authorization/server/functions/canDeleteMessage';
import { FileUpload } from '../../../file-upload/server';
import { settings } from '../../../settings/server';
-import { notifyOnRoomChangedById } from '../lib/notifyListener';
+import { notifyOnRoomChangedById, notifyOnMessageChange } from '../lib/notifyListener';
export const deleteMessageValidatingPermission = async (message: AtLeast, userId: IUser['_id']): Promise => {
if (!message?._id) {
@@ -93,7 +92,7 @@ export async function deleteMessage(message: IMessage, user: IUser): Promise,
+ message: AtLeast,
user: IUser,
originalMsg?: IMessage,
previewUrls?: string[],
@@ -100,11 +99,11 @@ export const updateMessage = async function (
// although this is an "afterSave" kind callback, we know they can extend message's properties
// so we wait for it to run before broadcasting
- const data = await callbacks.run('afterSaveMessage', msg, room, user._id);
+ const data = await afterSaveMessage(msg, room, user._id);
- void broadcastMessageFromData({
+ void notifyOnMessageChange({
id: msg._id,
- data: data as any, // TODO move "afterSaveMessage" type definition to specify a return value
+ data,
});
if (room?.lastMessage?._id === msg._id) {
diff --git a/apps/meteor/app/lib/server/lib/afterSaveMessage.ts b/apps/meteor/app/lib/server/lib/afterSaveMessage.ts
new file mode 100644
index 000000000000..5b6e12b1e185
--- /dev/null
+++ b/apps/meteor/app/lib/server/lib/afterSaveMessage.ts
@@ -0,0 +1,35 @@
+import type { IMessage, IUser, IRoom } from '@rocket.chat/core-typings';
+import type { Updater } from '@rocket.chat/models';
+import { Rooms } from '@rocket.chat/models';
+
+import { callbacks } from '../../../../lib/callbacks';
+
+export async function afterSaveMessage(
+ message: IMessage,
+ room: IRoom,
+ uid?: IUser['_id'],
+ roomUpdater?: Updater,
+): Promise {
+ const updater = roomUpdater ?? Rooms.getUpdater();
+ const data = await callbacks.run('afterSaveMessage', message, { room, uid, roomUpdater: updater });
+
+ if (!roomUpdater && updater.hasChanges()) {
+ await Rooms.updateFromUpdater({ _id: room._id }, updater);
+ }
+
+ // TODO: Fix type - callback configuration needs to be updated
+ return data as unknown as IMessage;
+}
+
+export function afterSaveMessageAsync(
+ message: IMessage,
+ room: IRoom,
+ uid?: IUser['_id'],
+ roomUpdater: Updater = Rooms.getUpdater(),
+): void {
+ callbacks.runAsync('afterSaveMessage', message, { room, uid, roomUpdater });
+
+ if (roomUpdater.hasChanges()) {
+ void Rooms.updateFromUpdater({ _id: room._id }, roomUpdater);
+ }
+}
diff --git a/apps/meteor/app/lib/server/lib/notifyListener.ts b/apps/meteor/app/lib/server/lib/notifyListener.ts
index 635c236fda27..934742945f2d 100644
--- a/apps/meteor/app/lib/server/lib/notifyListener.ts
+++ b/apps/meteor/app/lib/server/lib/notifyListener.ts
@@ -17,6 +17,9 @@ import type {
AtLeast,
ISettingColor,
IUser,
+ IMessage,
+ SettingValue,
+ MessageTypesValues,
} from '@rocket.chat/core-typings';
import {
Rooms,
@@ -30,7 +33,11 @@ import {
LivechatInquiry,
LivechatDepartmentAgents,
Users,
+ Messages,
} from '@rocket.chat/models';
+import mem from 'mem';
+
+import { shouldHideSystemMessage } from '../../../../server/lib/systemMessage/hideSystemMessage';
type ClientAction = 'inserted' | 'updated' | 'removed';
@@ -401,3 +408,62 @@ export const notifyOnUserChangeById = withDbWatcherCheck(
void notifyOnUserChange({ id, clientAction, data: user });
},
);
+
+const getUserNameCached = mem(
+ async (userId: string): Promise => {
+ const user = await Users.findOne>(userId, { projection: { name: 1 } });
+ return user?.name;
+ },
+ { maxAge: 10000 },
+);
+
+const getSettingCached = mem(async (setting: string): Promise => Settings.getValueById(setting), { maxAge: 10000 });
+
+export async function getMessageToBroadcast({ id, data }: { id: IMessage['_id']; data?: IMessage }): Promise {
+ const message = data ?? (await Messages.findOneById(id));
+ if (!message) {
+ return;
+ }
+
+ if (message.t) {
+ const hiddenSystemMessages = (await getSettingCached('Hide_System_Messages')) as MessageTypesValues[];
+ const shouldHide = shouldHideSystemMessage(message.t, hiddenSystemMessages);
+
+ if (shouldHide) {
+ return;
+ }
+ }
+
+ if (message._hidden || message.imported != null) {
+ return;
+ }
+
+ const useRealName = (await getSettingCached('UI_Use_Real_Name')) === true;
+ if (useRealName) {
+ if (message.u?._id) {
+ const name = await getUserNameCached(message.u._id);
+ if (name) {
+ message.u.name = name;
+ }
+ }
+
+ if (message.mentions?.length) {
+ for await (const mention of message.mentions) {
+ const name = await getUserNameCached(mention._id);
+ if (name) {
+ mention.name = name;
+ }
+ }
+ }
+ }
+
+ return message;
+}
+
+export const notifyOnMessageChange = withDbWatcherCheck(async ({ id, data }: { id: IMessage['_id']; data?: IMessage }): Promise => {
+ const message = await getMessageToBroadcast({ id, data });
+ if (!message) {
+ return;
+ }
+ void api.broadcast('watch.messages', { message });
+});
diff --git a/apps/meteor/app/lib/server/lib/notifyUsersOnMessage.ts b/apps/meteor/app/lib/server/lib/notifyUsersOnMessage.ts
index 76a18eba3362..85f2ac52b702 100644
--- a/apps/meteor/app/lib/server/lib/notifyUsersOnMessage.ts
+++ b/apps/meteor/app/lib/server/lib/notifyUsersOnMessage.ts
@@ -1,5 +1,6 @@
import type { IMessage, IRoom, IUser, RoomType } from '@rocket.chat/core-typings';
import { isEditedMessage } from '@rocket.chat/core-typings';
+import type { Updater } from '@rocket.chat/models';
import { Subscriptions, Rooms } from '@rocket.chat/models';
import { escapeRegExp } from '@rocket.chat/string-helpers';
import moment from 'moment';
@@ -141,12 +142,14 @@ export async function updateThreadUsersSubscriptions(message: IMessage, replies:
await Subscriptions.setLastReplyForRoomIdAndUserIds(message.rid, repliesPlusSender, new Date());
}
-export async function notifyUsersOnMessage(message: IMessage, room: IRoom): Promise {
+export async function notifyUsersOnMessage(message: IMessage, room: IRoom, roomUpdater: Updater): Promise {
+ console.log('notifyUsersOnMessage function');
+
// Skips this callback if the message was edited and increments it if the edit was way in the past (aka imported)
if (isEditedMessage(message)) {
if (Math.abs(moment(message.editedAt).diff(Date.now())) > 60000) {
// TODO: Review as I am not sure how else to get around this as the incrementing of the msgs count shouldn't be in this callback
- await Rooms.incMsgCountById(message.rid, 1);
+ Rooms.getIncMsgCountUpdateQuery(1, roomUpdater);
return message;
}
@@ -156,25 +159,39 @@ export async function notifyUsersOnMessage(message: IMessage, room: IRoom): Prom
(!message.tmid || message.tshow) &&
(!room.lastMessage || room.lastMessage._id === message._id)
) {
- await Rooms.setLastMessageById(message.rid, message);
+ Rooms.getLastMessageUpdateQuery(message, roomUpdater);
}
return message;
}
if (message.ts && Math.abs(moment(message.ts).diff(Date.now())) > 60000) {
- await Rooms.incMsgCountById(message.rid, 1);
+ Rooms.getIncMsgCountUpdateQuery(1, roomUpdater);
return message;
}
// If message sent ONLY on a thread, skips the rest as it is done on a callback specific to threads
if (message.tmid && !message.tshow) {
- await Rooms.incMsgCountById(message.rid, 1);
+ Rooms.getIncMsgCountUpdateQuery(1, roomUpdater);
return message;
}
// Update all the room activity tracker fields
- await Rooms.incMsgCountAndSetLastMessageById(message.rid, 1, message.ts, settings.get('Store_Last_Message') ? message : undefined);
+ Rooms.setIncMsgCountAndSetLastMessageUpdateQuery(1, message, !!settings.get('Store_Last_Message'), roomUpdater);
+ await updateUsersSubscriptions(message, room);
+
+ return message;
+}
+
+export async function notifyUsersOnSystemMessage(message: IMessage, room: IRoom): Promise {
+ const roomUpdater = Rooms.getUpdater();
+ Rooms.setIncMsgCountAndSetLastMessageUpdateQuery(1, message, !!settings.get('Store_Last_Message'), roomUpdater);
+
+ if (roomUpdater.hasChanges()) {
+ await Rooms.updateFromUpdater({ _id: room._id }, roomUpdater);
+ }
+
+ // TODO: Rewrite to use just needed calls from the function
await updateUsersSubscriptions(message, room);
return message;
@@ -182,7 +199,15 @@ export async function notifyUsersOnMessage(message: IMessage, room: IRoom): Prom
callbacks.add(
'afterSaveMessage',
- (message, room) => notifyUsersOnMessage(message, room),
+ async (message, { room, roomUpdater }) => {
+ if (!roomUpdater) {
+ return message;
+ }
+
+ await notifyUsersOnMessage(message, room, roomUpdater);
+
+ return message;
+ },
callbacks.priority.MEDIUM,
'notifyUsersOnMessage',
);
diff --git a/apps/meteor/app/lib/server/lib/sendNotificationsOnMessage.ts b/apps/meteor/app/lib/server/lib/sendNotificationsOnMessage.ts
index 49fcc0ea4725..94c25f476222 100644
--- a/apps/meteor/app/lib/server/lib/sendNotificationsOnMessage.ts
+++ b/apps/meteor/app/lib/server/lib/sendNotificationsOnMessage.ts
@@ -406,7 +406,7 @@ settings.watch('Troubleshoot_Disable_Notifications', (value) => {
callbacks.add(
'afterSaveMessage',
- (message, room) => sendAllNotifications(message, room),
+ (message, { room }) => sendAllNotifications(message, room),
callbacks.priority.LOW,
'sendNotificationsOnMessage',
);
diff --git a/apps/meteor/app/lib/server/methods/addOAuthService.ts b/apps/meteor/app/lib/server/methods/addOAuthService.ts
index 05b0e5a7e4e6..09287bb9bb74 100644
--- a/apps/meteor/app/lib/server/methods/addOAuthService.ts
+++ b/apps/meteor/app/lib/server/methods/addOAuthService.ts
@@ -1,11 +1,11 @@
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import { addOAuthService } from '../../../../server/lib/oauth/addOAuthService';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
addOAuthService(name: string): void;
diff --git a/apps/meteor/app/lib/server/methods/addUserToRoom.ts b/apps/meteor/app/lib/server/methods/addUserToRoom.ts
index 880b413d0618..8100cafc33b0 100644
--- a/apps/meteor/app/lib/server/methods/addUserToRoom.ts
+++ b/apps/meteor/app/lib/server/methods/addUserToRoom.ts
@@ -1,9 +1,9 @@
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
import { addUsersToRoomMethod } from './addUsersToRoom';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
addUserToRoom(data: { rid: string; username: string }): void;
diff --git a/apps/meteor/app/lib/server/methods/addUsersToRoom.ts b/apps/meteor/app/lib/server/methods/addUsersToRoom.ts
index 48b7f9db58f5..73fbf6e51a04 100644
--- a/apps/meteor/app/lib/server/methods/addUsersToRoom.ts
+++ b/apps/meteor/app/lib/server/methods/addUsersToRoom.ts
@@ -1,8 +1,8 @@
import { api } from '@rocket.chat/core-services';
import type { IUser } from '@rocket.chat/core-typings';
import { isRoomFederated } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Subscriptions, Users, Rooms } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Match } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
@@ -12,7 +12,7 @@ import { Federation } from '../../../../server/services/federation/Federation';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
import { addUserToRoom } from '../functions/addUserToRoom';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
addUsersToRoom(data: { rid: string; users: string[] }): boolean;
diff --git a/apps/meteor/app/lib/server/methods/archiveRoom.ts b/apps/meteor/app/lib/server/methods/archiveRoom.ts
index c30014f59c11..dfa5a2c55412 100644
--- a/apps/meteor/app/lib/server/methods/archiveRoom.ts
+++ b/apps/meteor/app/lib/server/methods/archiveRoom.ts
@@ -1,6 +1,6 @@
import { isRegisterUser } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Users, Rooms } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
@@ -9,7 +9,7 @@ import { roomCoordinator } from '../../../../server/lib/rooms/roomCoordinator';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
import { archiveRoom } from '../functions/archiveRoom';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
archiveRoom(rid: string): Promise;
diff --git a/apps/meteor/app/lib/server/methods/blockUser.ts b/apps/meteor/app/lib/server/methods/blockUser.ts
index b65423edf25b..b967e35d7bc1 100644
--- a/apps/meteor/app/lib/server/methods/blockUser.ts
+++ b/apps/meteor/app/lib/server/methods/blockUser.ts
@@ -1,12 +1,12 @@
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Subscriptions, Rooms } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import { RoomMemberActions } from '../../../../definition/IRoomTypeConfig';
import { roomCoordinator } from '../../../../server/lib/rooms/roomCoordinator';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
blockUser({ rid, blocked }: { rid: string; blocked: string }): boolean;
diff --git a/apps/meteor/app/lib/server/methods/checkRegistrationSecretURL.ts b/apps/meteor/app/lib/server/methods/checkRegistrationSecretURL.ts
index 3f349a8b43e6..ecba6844da26 100644
--- a/apps/meteor/app/lib/server/methods/checkRegistrationSecretURL.ts
+++ b/apps/meteor/app/lib/server/methods/checkRegistrationSecretURL.ts
@@ -1,4 +1,4 @@
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
diff --git a/apps/meteor/app/lib/server/methods/checkUsernameAvailability.ts b/apps/meteor/app/lib/server/methods/checkUsernameAvailability.ts
index 34ad02ddb2cf..4df2706bb479 100644
--- a/apps/meteor/app/lib/server/methods/checkUsernameAvailability.ts
+++ b/apps/meteor/app/lib/server/methods/checkUsernameAvailability.ts
@@ -1,4 +1,4 @@
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
@@ -6,7 +6,7 @@ import { checkUsernameAvailabilityWithValidation } from '../functions/checkUsern
import { RateLimiter } from '../lib';
import { methodDeprecationLogger } from '../lib/deprecationWarningLogger';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
checkUsernameAvailability(username: string): boolean;
diff --git a/apps/meteor/app/lib/server/methods/cleanRoomHistory.ts b/apps/meteor/app/lib/server/methods/cleanRoomHistory.ts
index a724d1b38b2c..d6136eee9131 100644
--- a/apps/meteor/app/lib/server/methods/cleanRoomHistory.ts
+++ b/apps/meteor/app/lib/server/methods/cleanRoomHistory.ts
@@ -1,11 +1,11 @@
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Match, check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
import { cleanRoomHistory } from '../functions/cleanRoomHistory';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
cleanRoomHistory(data: {
diff --git a/apps/meteor/app/lib/server/methods/createChannel.ts b/apps/meteor/app/lib/server/methods/createChannel.ts
index 98cea517bed4..a490fa1e3c42 100644
--- a/apps/meteor/app/lib/server/methods/createChannel.ts
+++ b/apps/meteor/app/lib/server/methods/createChannel.ts
@@ -1,13 +1,13 @@
import type { ICreatedRoom } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Users } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Match, check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
import { createRoom } from '../functions/createRoom';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
createChannel(
diff --git a/apps/meteor/app/lib/server/methods/createPrivateGroup.ts b/apps/meteor/app/lib/server/methods/createPrivateGroup.ts
index 75097b5c89b8..3b92b2607829 100644
--- a/apps/meteor/app/lib/server/methods/createPrivateGroup.ts
+++ b/apps/meteor/app/lib/server/methods/createPrivateGroup.ts
@@ -1,13 +1,13 @@
import type { ICreatedRoom, IUser } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Users } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Match, check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
import { createRoom } from '../functions/createRoom';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
createPrivateGroup(
diff --git a/apps/meteor/app/lib/server/methods/createToken.ts b/apps/meteor/app/lib/server/methods/createToken.ts
index ed665944415a..de60a7e37fe8 100644
--- a/apps/meteor/app/lib/server/methods/createToken.ts
+++ b/apps/meteor/app/lib/server/methods/createToken.ts
@@ -1,12 +1,12 @@
import { User } from '@rocket.chat/core-services';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Accounts } from 'meteor/accounts-base';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
import { methodDeprecationLogger } from '../lib/deprecationWarningLogger';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
createToken(userId: string): { userId: string; authToken: string };
diff --git a/apps/meteor/app/lib/server/methods/deleteMessage.ts b/apps/meteor/app/lib/server/methods/deleteMessage.ts
index a1b1000c06b8..b0be64c245ef 100644
--- a/apps/meteor/app/lib/server/methods/deleteMessage.ts
+++ b/apps/meteor/app/lib/server/methods/deleteMessage.ts
@@ -1,11 +1,11 @@
import type { IMessage } from '@rocket.chat/core-typings';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
import { deleteMessageValidatingPermission } from '../functions/deleteMessage';
import { methodDeprecationLogger } from '../lib/deprecationWarningLogger';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
deleteMessage({ _id }: Pick): void;
diff --git a/apps/meteor/app/lib/server/methods/deleteUserOwnAccount.ts b/apps/meteor/app/lib/server/methods/deleteUserOwnAccount.ts
index 2d651950da19..7b5663185bc5 100644
--- a/apps/meteor/app/lib/server/methods/deleteUserOwnAccount.ts
+++ b/apps/meteor/app/lib/server/methods/deleteUserOwnAccount.ts
@@ -1,7 +1,7 @@
import { Apps, AppEvents } from '@rocket.chat/apps';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Users } from '@rocket.chat/models';
import { SHA256 } from '@rocket.chat/sha256';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Accounts } from 'meteor/accounts-base';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
@@ -10,7 +10,7 @@ import { trim } from '../../../../lib/utils/stringUtils';
import { settings } from '../../../settings/server';
import { deleteUser } from '../functions/deleteUser';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
deleteUserOwnAccount(password: string, confirmRelinquish?: boolean): Promise;
diff --git a/apps/meteor/app/lib/server/methods/executeSlashCommandPreview.ts b/apps/meteor/app/lib/server/methods/executeSlashCommandPreview.ts
index 80b5428efbef..1c116863610d 100644
--- a/apps/meteor/app/lib/server/methods/executeSlashCommandPreview.ts
+++ b/apps/meteor/app/lib/server/methods/executeSlashCommandPreview.ts
@@ -1,10 +1,10 @@
import type { IMessage, RequiredField, SlashCommandPreviewItem } from '@rocket.chat/core-typings';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
import { slashCommands } from '../../../utils/server/slashCommand';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
executeSlashCommandPreview(
diff --git a/apps/meteor/app/lib/server/methods/getChannelHistory.ts b/apps/meteor/app/lib/server/methods/getChannelHistory.ts
index 00ff01639593..8f1f4c586141 100644
--- a/apps/meteor/app/lib/server/methods/getChannelHistory.ts
+++ b/apps/meteor/app/lib/server/methods/getChannelHistory.ts
@@ -1,6 +1,6 @@
import type { IMessage, MessageTypesValues } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Messages, Subscriptions, Rooms } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import _ from 'underscore';
@@ -11,7 +11,7 @@ import { settings } from '../../../settings/server/cached';
import { normalizeMessagesForUser } from '../../../utils/server/lib/normalizeMessagesForUser';
import { getHiddenSystemMessages } from '../lib/getHiddenSystemMessages';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
getChannelHistory(params: {
diff --git a/apps/meteor/app/lib/server/methods/getMessages.ts b/apps/meteor/app/lib/server/methods/getMessages.ts
index 909e3d0c656b..d8684f82453c 100644
--- a/apps/meteor/app/lib/server/methods/getMessages.ts
+++ b/apps/meteor/app/lib/server/methods/getMessages.ts
@@ -1,12 +1,12 @@
import type { IMessage } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Messages } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import { canAccessRoomIdAsync } from '../../../authorization/server/functions/canAccessRoom';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
getMessages(messages: IMessage['_id'][]): Promise;
diff --git a/apps/meteor/app/lib/server/methods/getRoomJoinCode.ts b/apps/meteor/app/lib/server/methods/getRoomJoinCode.ts
index 75e4a4372f57..5ba4b3490722 100644
--- a/apps/meteor/app/lib/server/methods/getRoomJoinCode.ts
+++ b/apps/meteor/app/lib/server/methods/getRoomJoinCode.ts
@@ -1,12 +1,12 @@
import { isRoomWithJoinCode } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Rooms } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
getRoomJoinCode(rid: string): string | false;
diff --git a/apps/meteor/app/lib/server/methods/getRoomRoles.ts b/apps/meteor/app/lib/server/methods/getRoomRoles.ts
index ac5fcc734d0f..b411ba8fedf5 100644
--- a/apps/meteor/app/lib/server/methods/getRoomRoles.ts
+++ b/apps/meteor/app/lib/server/methods/getRoomRoles.ts
@@ -1,6 +1,6 @@
import type { IRoom, ISubscription } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Rooms } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
@@ -8,7 +8,7 @@ import { getRoomRoles } from '../../../../server/lib/roles/getRoomRoles';
import { canAccessRoomAsync } from '../../../authorization/server';
import { settings } from '../../../settings/server';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
getRoomRoles(rid: IRoom['_id']): ISubscription[];
diff --git a/apps/meteor/app/lib/server/methods/getSingleMessage.ts b/apps/meteor/app/lib/server/methods/getSingleMessage.ts
index 1aaf2a652257..c4b6f065296b 100644
--- a/apps/meteor/app/lib/server/methods/getSingleMessage.ts
+++ b/apps/meteor/app/lib/server/methods/getSingleMessage.ts
@@ -1,12 +1,12 @@
import type { IMessage } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Messages } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import { canAccessRoomIdAsync } from '../../../authorization/server/functions/canAccessRoom';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
getSingleMessage(mid: IMessage['_id']): Promise;
diff --git a/apps/meteor/app/lib/server/methods/getSlashCommandPreviews.ts b/apps/meteor/app/lib/server/methods/getSlashCommandPreviews.ts
index dcb39c466063..965c91cc502f 100644
--- a/apps/meteor/app/lib/server/methods/getSlashCommandPreviews.ts
+++ b/apps/meteor/app/lib/server/methods/getSlashCommandPreviews.ts
@@ -1,10 +1,10 @@
import type { IMessage, RequiredField, SlashCommandPreviews } from '@rocket.chat/core-typings';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
import { slashCommands } from '../../../utils/server/slashCommand';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
getSlashCommandPreviews(command: {
diff --git a/apps/meteor/app/lib/server/methods/getUserRoles.ts b/apps/meteor/app/lib/server/methods/getUserRoles.ts
index cc7588276c33..cbd4712930a2 100644
--- a/apps/meteor/app/lib/server/methods/getUserRoles.ts
+++ b/apps/meteor/app/lib/server/methods/getUserRoles.ts
@@ -1,9 +1,9 @@
import { Authorization } from '@rocket.chat/core-services';
import type { IUser, IRocketChatRecord } from '@rocket.chat/core-typings';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
getUserRoles(): (IRocketChatRecord & Pick)[];
diff --git a/apps/meteor/app/lib/server/methods/getUsernameSuggestion.ts b/apps/meteor/app/lib/server/methods/getUsernameSuggestion.ts
index 5724449a5790..b42799f24081 100644
--- a/apps/meteor/app/lib/server/methods/getUsernameSuggestion.ts
+++ b/apps/meteor/app/lib/server/methods/getUsernameSuggestion.ts
@@ -1,9 +1,9 @@
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
import { generateUsernameSuggestion } from '../functions/getUsernameSuggestion';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
getUsernameSuggestion(): Promise;
diff --git a/apps/meteor/app/lib/server/methods/insertOrUpdateUser.ts b/apps/meteor/app/lib/server/methods/insertOrUpdateUser.ts
index 5a8b1c8d1a58..122b11172d57 100644
--- a/apps/meteor/app/lib/server/methods/insertOrUpdateUser.ts
+++ b/apps/meteor/app/lib/server/methods/insertOrUpdateUser.ts
@@ -1,4 +1,4 @@
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
@@ -6,7 +6,7 @@ import { twoFactorRequired } from '../../../2fa/server/twoFactorRequired';
import { saveUser } from '../functions/saveUser';
import { methodDeprecationLogger } from '../lib/deprecationWarningLogger';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
insertOrUpdateUser(userData: Record): Promise;
diff --git a/apps/meteor/app/lib/server/methods/joinDefaultChannels.ts b/apps/meteor/app/lib/server/methods/joinDefaultChannels.ts
index 309ac4e449be..df654bc4aef0 100644
--- a/apps/meteor/app/lib/server/methods/joinDefaultChannels.ts
+++ b/apps/meteor/app/lib/server/methods/joinDefaultChannels.ts
@@ -1,11 +1,11 @@
import type { IUser } from '@rocket.chat/core-typings';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Match, check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import { addUserToDefaultChannels } from '../functions/addUserToDefaultChannels';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
joinDefaultChannels(silenced?: boolean): void;
diff --git a/apps/meteor/app/lib/server/methods/joinRoom.ts b/apps/meteor/app/lib/server/methods/joinRoom.ts
index 0fa3ac0b3c3b..ef3f069ee614 100644
--- a/apps/meteor/app/lib/server/methods/joinRoom.ts
+++ b/apps/meteor/app/lib/server/methods/joinRoom.ts
@@ -1,11 +1,11 @@
import { Room } from '@rocket.chat/core-services';
import type { IRoom } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Rooms } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
joinRoom(rid: IRoom['_id'], code?: string): boolean | undefined;
diff --git a/apps/meteor/app/lib/server/methods/leaveRoom.ts b/apps/meteor/app/lib/server/methods/leaveRoom.ts
index ec1bb1638a21..4fc85b35fd05 100644
--- a/apps/meteor/app/lib/server/methods/leaveRoom.ts
+++ b/apps/meteor/app/lib/server/methods/leaveRoom.ts
@@ -1,6 +1,6 @@
import type { IUser } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Roles, Subscriptions, Rooms } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
@@ -10,7 +10,7 @@ import { hasPermissionAsync } from '../../../authorization/server/functions/hasP
import { hasRoleAsync } from '../../../authorization/server/functions/hasRole';
import { removeUserFromRoom } from '../functions/removeUserFromRoom';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
leaveRoom(rid: string): Promise;
diff --git a/apps/meteor/app/lib/server/methods/refreshOAuthService.ts b/apps/meteor/app/lib/server/methods/refreshOAuthService.ts
index e5b1c377a33e..1d547b770361 100644
--- a/apps/meteor/app/lib/server/methods/refreshOAuthService.ts
+++ b/apps/meteor/app/lib/server/methods/refreshOAuthService.ts
@@ -1,10 +1,10 @@
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
import { refreshLoginServices } from '../../../../server/lib/refreshLoginServices';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
refreshOAuthService(): Promise;
diff --git a/apps/meteor/app/lib/server/methods/removeOAuthService.ts b/apps/meteor/app/lib/server/methods/removeOAuthService.ts
index 6e16dc8d2d5b..fee2caa911d2 100644
--- a/apps/meteor/app/lib/server/methods/removeOAuthService.ts
+++ b/apps/meteor/app/lib/server/methods/removeOAuthService.ts
@@ -1,13 +1,13 @@
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Settings } from '@rocket.chat/models';
import { capitalize } from '@rocket.chat/string-helpers';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
import { notifyOnSettingChangedById } from '../lib/notifyListener';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
removeOAuthService(name: string): Promise;
diff --git a/apps/meteor/app/lib/server/methods/restartServer.ts b/apps/meteor/app/lib/server/methods/restartServer.ts
index 206824aebe7e..264ab4d1bee6 100644
--- a/apps/meteor/app/lib/server/methods/restartServer.ts
+++ b/apps/meteor/app/lib/server/methods/restartServer.ts
@@ -1,9 +1,9 @@
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
restart_server(): {
diff --git a/apps/meteor/app/lib/server/methods/saveCustomFields.ts b/apps/meteor/app/lib/server/methods/saveCustomFields.ts
index a509c97bdb85..d683e59a905c 100644
--- a/apps/meteor/app/lib/server/methods/saveCustomFields.ts
+++ b/apps/meteor/app/lib/server/methods/saveCustomFields.ts
@@ -1,11 +1,11 @@
import type { IUser } from '@rocket.chat/core-typings';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
import { saveCustomFields } from '../functions/saveCustomFields';
import { RateLimiter } from '../lib';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
saveCustomFields: (fields: IUser['customFields']) => Promise;
diff --git a/apps/meteor/app/lib/server/methods/saveSetting.ts b/apps/meteor/app/lib/server/methods/saveSetting.ts
index 7f900d1751d8..4f4d29b9fa24 100644
--- a/apps/meteor/app/lib/server/methods/saveSetting.ts
+++ b/apps/meteor/app/lib/server/methods/saveSetting.ts
@@ -1,6 +1,6 @@
import type { SettingValue } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Settings } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Match, check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
@@ -9,7 +9,7 @@ import { getSettingPermissionId } from '../../../authorization/lib';
import { hasPermissionAsync, hasAllPermissionAsync } from '../../../authorization/server/functions/hasPermission';
import { notifyOnSettingChanged } from '../lib/notifyListener';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
saveSetting(_id: string, value: SettingValue, editor?: string): Promise;
diff --git a/apps/meteor/app/lib/server/methods/saveSettings.ts b/apps/meteor/app/lib/server/methods/saveSettings.ts
index 8c4f92cfb88f..dffa986b7217 100644
--- a/apps/meteor/app/lib/server/methods/saveSettings.ts
+++ b/apps/meteor/app/lib/server/methods/saveSettings.ts
@@ -1,7 +1,7 @@
import type { ISetting } from '@rocket.chat/core-typings';
import { isSettingCode } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Settings } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Match, check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
@@ -11,7 +11,7 @@ import { hasPermissionAsync } from '../../../authorization/server/functions/hasP
import { settings } from '../../../settings/server';
import { notifyOnSettingChangedById } from '../lib/notifyListener';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
saveSettings(
diff --git a/apps/meteor/app/lib/server/methods/sendMessage.ts b/apps/meteor/app/lib/server/methods/sendMessage.ts
index a61ab499ce87..56009f15fede 100644
--- a/apps/meteor/app/lib/server/methods/sendMessage.ts
+++ b/apps/meteor/app/lib/server/methods/sendMessage.ts
@@ -1,7 +1,7 @@
import { api } from '@rocket.chat/core-services';
import type { AtLeast, IMessage, IUser } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Messages, Users } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import moment from 'moment';
@@ -111,7 +111,7 @@ export async function executeSendMessage(uid: IUser['_id'], message: AtLeast, previewUrls?: string[]): any;
diff --git a/apps/meteor/app/lib/server/methods/sendSMTPTestEmail.ts b/apps/meteor/app/lib/server/methods/sendSMTPTestEmail.ts
index 2ede129dd380..5a04032ad82e 100644
--- a/apps/meteor/app/lib/server/methods/sendSMTPTestEmail.ts
+++ b/apps/meteor/app/lib/server/methods/sendSMTPTestEmail.ts
@@ -1,11 +1,11 @@
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { DDPRateLimiter } from 'meteor/ddp-rate-limiter';
import { Meteor } from 'meteor/meteor';
import * as Mailer from '../../../mailer/server/api';
import { settings } from '../../../settings/server';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
sendSMTPTestEmail(): {
diff --git a/apps/meteor/app/lib/server/methods/setAdminStatus.ts b/apps/meteor/app/lib/server/methods/setAdminStatus.ts
index 42ffdc91f85e..300aa735b014 100644
--- a/apps/meteor/app/lib/server/methods/setAdminStatus.ts
+++ b/apps/meteor/app/lib/server/methods/setAdminStatus.ts
@@ -1,12 +1,12 @@
import { isUserFederated } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Users } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Match, check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
setAdminStatus(userId: string, admin?: boolean): void;
diff --git a/apps/meteor/app/lib/server/methods/setEmail.ts b/apps/meteor/app/lib/server/methods/setEmail.ts
index a172eba72555..26540db26b4c 100644
--- a/apps/meteor/app/lib/server/methods/setEmail.ts
+++ b/apps/meteor/app/lib/server/methods/setEmail.ts
@@ -1,4 +1,4 @@
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
@@ -6,7 +6,7 @@ import { settings } from '../../../settings/server';
import { setEmail } from '../functions/setEmail';
import { RateLimiter } from '../lib';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
setEmail(email: string): string;
diff --git a/apps/meteor/app/lib/server/methods/setRealName.ts b/apps/meteor/app/lib/server/methods/setRealName.ts
index 2a55bd102172..f347eef1580e 100644
--- a/apps/meteor/app/lib/server/methods/setRealName.ts
+++ b/apps/meteor/app/lib/server/methods/setRealName.ts
@@ -1,4 +1,4 @@
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
@@ -6,7 +6,7 @@ import { settings } from '../../../settings/server';
import { setRealName } from '../functions/setRealName';
import { RateLimiter } from '../lib';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
setRealName(name: string): string;
diff --git a/apps/meteor/app/lib/server/methods/setUsername.ts b/apps/meteor/app/lib/server/methods/setUsername.ts
index 900848f37783..58fac75ed3bd 100644
--- a/apps/meteor/app/lib/server/methods/setUsername.ts
+++ b/apps/meteor/app/lib/server/methods/setUsername.ts
@@ -1,11 +1,11 @@
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import { setUsernameWithValidation } from '../functions/setUsername';
import { RateLimiter } from '../lib';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
setUsername(username: string, param?: { joinDefaultChannelsSilenced?: boolean }): string;
diff --git a/apps/meteor/app/lib/server/methods/unarchiveRoom.ts b/apps/meteor/app/lib/server/methods/unarchiveRoom.ts
index 0f9349365f4f..74b74c11e54a 100644
--- a/apps/meteor/app/lib/server/methods/unarchiveRoom.ts
+++ b/apps/meteor/app/lib/server/methods/unarchiveRoom.ts
@@ -1,13 +1,13 @@
import { isRegisterUser } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Users, Rooms } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
import { unarchiveRoom } from '../functions/unarchiveRoom';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
unarchiveRoom(rid: string): Promise;
diff --git a/apps/meteor/app/lib/server/methods/unblockUser.ts b/apps/meteor/app/lib/server/methods/unblockUser.ts
index 6c8a9d486bab..2eec5a082109 100644
--- a/apps/meteor/app/lib/server/methods/unblockUser.ts
+++ b/apps/meteor/app/lib/server/methods/unblockUser.ts
@@ -1,9 +1,9 @@
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Subscriptions } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
unblockUser({ rid, blocked }: { rid: string; blocked: string }): boolean;
diff --git a/apps/meteor/app/lib/server/methods/updateMessage.ts b/apps/meteor/app/lib/server/methods/updateMessage.ts
index 161a168a2cdc..8cebe563cd23 100644
--- a/apps/meteor/app/lib/server/methods/updateMessage.ts
+++ b/apps/meteor/app/lib/server/methods/updateMessage.ts
@@ -1,6 +1,6 @@
import type { IEditedMessage, IMessage, IUser, AtLeast } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Messages, Users } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Match, check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import moment from 'moment';
@@ -12,7 +12,11 @@ import { updateMessage } from '../functions/updateMessage';
const allowedEditedFields = ['tshow', 'alias', 'attachments', 'avatar', 'emoji', 'msg', 'customFields', 'content'];
-export async function executeUpdateMessage(uid: IUser['_id'], message: AtLeast, previewUrls?: string[]) {
+export async function executeUpdateMessage(
+ uid: IUser['_id'],
+ message: AtLeast,
+ previewUrls?: string[],
+) {
const originalMessage = await Messages.findOneById(message._id);
if (!originalMessage?._id) {
return;
@@ -26,8 +30,11 @@ export async function executeUpdateMessage(uid: IUser['_id'], message: AtLeast {
+ async (message, { room }) => {
// TODO: check if I need to test this 60 second rule.
// If the message was edited, or is older than 60 seconds (imported)
// the notifications will be skipped, so we can also skip this validation
diff --git a/apps/meteor/app/livechat-enterprise/client/startup.ts b/apps/meteor/app/livechat-enterprise/client/startup.ts
index 0535f8926a7d..bdf6c2549816 100644
--- a/apps/meteor/app/livechat-enterprise/client/startup.ts
+++ b/apps/meteor/app/livechat-enterprise/client/startup.ts
@@ -15,7 +15,7 @@ const businessHours: Record = {
Meteor.startup(() => {
Tracker.autorun(async () => {
const bhType = settings.get('Livechat_business_hour_type');
- if (await hasLicense('livechat-enterprise')) {
+ if (bhType && (await hasLicense('livechat-enterprise'))) {
businessHourManager.registerBusinessHourBehavior(businessHours[bhType.toLowerCase()]);
}
});
diff --git a/apps/meteor/app/livechat/client/externalFrame/generateNewKey.ts b/apps/meteor/app/livechat/client/externalFrame/generateNewKey.ts
index eb0742813c1f..54c6ba4d75f1 100644
--- a/apps/meteor/app/livechat/client/externalFrame/generateNewKey.ts
+++ b/apps/meteor/app/livechat/client/externalFrame/generateNewKey.ts
@@ -1,4 +1,4 @@
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
import { sdk } from '../../../utils/client/lib/SDKClient';
diff --git a/apps/meteor/app/livechat/server/api/lib/agents.ts b/apps/meteor/app/livechat/server/api/lib/agents.ts
index 3bc5180c2f59..2dbcce8c7e2e 100644
--- a/apps/meteor/app/livechat/server/api/lib/agents.ts
+++ b/apps/meteor/app/livechat/server/api/lib/agents.ts
@@ -7,14 +7,8 @@ export async function findAgentDepartments({
}: {
enabledDepartmentsOnly?: boolean;
agentId: string;
-}): Promise<{ departments: ILivechatDepartmentAgents[] }> {
- if (enabledDepartmentsOnly) {
- return {
- departments: await LivechatDepartmentAgents.findActiveDepartmentsByAgentId(agentId).toArray(),
- };
- }
-
+}): Promise<{ departments: (ILivechatDepartmentAgents & { departmentName: string })[] }> {
return {
- departments: await LivechatDepartmentAgents.find({ agentId }).toArray(),
+ departments: await LivechatDepartmentAgents.findDepartmentsOfAgent(agentId, enabledDepartmentsOnly).toArray(),
};
}
diff --git a/apps/meteor/app/livechat/server/api/v1/pageVisited.ts b/apps/meteor/app/livechat/server/api/v1/pageVisited.ts
index e89a3e17f0a1..2688ad673af0 100644
--- a/apps/meteor/app/livechat/server/api/v1/pageVisited.ts
+++ b/apps/meteor/app/livechat/server/api/v1/pageVisited.ts
@@ -1,5 +1,4 @@
import type { IOmnichannelSystemMessage } from '@rocket.chat/core-typings';
-import { Messages } from '@rocket.chat/models';
import { isPOSTLivechatPageVisitedParams } from '@rocket.chat/rest-typings';
import { API } from '../../../../api/server';
@@ -11,17 +10,13 @@ API.v1.addRoute(
{
async post() {
const { token, rid, pageInfo } = this.bodyParams;
- const msgId = await Livechat.savePageHistory(token, rid, pageInfo);
- if (!msgId) {
- return API.v1.success();
- }
- const message = await Messages.findOneById(msgId);
+ const message = await Livechat.savePageHistory(token, rid, pageInfo);
if (!message) {
return API.v1.success();
}
- const { msg, navigation } = message;
+ const { msg, navigation } = message as IOmnichannelSystemMessage;
return API.v1.success({ page: { msg, navigation } });
},
},
diff --git a/apps/meteor/app/livechat/server/externalFrame/generateNewKey.ts b/apps/meteor/app/livechat/server/externalFrame/generateNewKey.ts
index 11463bcf00d4..a8f145f47d39 100644
--- a/apps/meteor/app/livechat/server/externalFrame/generateNewKey.ts
+++ b/apps/meteor/app/livechat/server/externalFrame/generateNewKey.ts
@@ -1,7 +1,7 @@
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
omnichannelExternalFrameGenerateKey(): unknown;
diff --git a/apps/meteor/app/livechat/server/hooks/afterSaveOmnichannelMessage.ts b/apps/meteor/app/livechat/server/hooks/afterSaveOmnichannelMessage.ts
new file mode 100644
index 000000000000..311343c4ad01
--- /dev/null
+++ b/apps/meteor/app/livechat/server/hooks/afterSaveOmnichannelMessage.ts
@@ -0,0 +1,24 @@
+import { isOmnichannelRoom } from '@rocket.chat/core-typings';
+import { LivechatRooms } from '@rocket.chat/models';
+
+import { callbacks } from '../../../../lib/callbacks';
+
+callbacks.add(
+ 'afterSaveMessage',
+ async (message, { room }) => {
+ if (!isOmnichannelRoom(room)) {
+ return message;
+ }
+
+ const updater = LivechatRooms.getUpdater();
+ const result = await callbacks.run('afterOmnichannelSaveMessage', message, { room, roomUpdater: updater });
+
+ if (updater.hasChanges()) {
+ await LivechatRooms.updateFromUpdater({ _id: room._id }, updater);
+ }
+
+ return result;
+ },
+ callbacks.priority.MEDIUM,
+ 'after-omnichannel-save-message',
+);
diff --git a/apps/meteor/app/livechat/server/hooks/leadCapture.ts b/apps/meteor/app/livechat/server/hooks/leadCapture.ts
index 4b987c00c02e..6a3826b8ba11 100644
--- a/apps/meteor/app/livechat/server/hooks/leadCapture.ts
+++ b/apps/meteor/app/livechat/server/hooks/leadCapture.ts
@@ -1,5 +1,5 @@
import type { IMessage, IOmnichannelRoom } from '@rocket.chat/core-typings';
-import { isEditedMessage, isOmnichannelRoom } from '@rocket.chat/core-typings';
+import { isEditedMessage } from '@rocket.chat/core-typings';
import { LivechatVisitors } from '@rocket.chat/models';
import { callbacks } from '../../../../lib/callbacks';
@@ -31,12 +31,8 @@ function validateMessage(message: IMessage, room: IOmnichannelRoom) {
}
callbacks.add(
- 'afterSaveMessage',
- async (message, room) => {
- if (!isOmnichannelRoom(room)) {
- return message;
- }
-
+ 'afterOmnichannelSaveMessage',
+ async (message, { room }) => {
if (!validateMessage(message, room)) {
return message;
}
diff --git a/apps/meteor/app/livechat/server/hooks/markRoomNotResponded.ts b/apps/meteor/app/livechat/server/hooks/markRoomNotResponded.ts
index f0bfb8574e6a..01d3014f1c27 100644
--- a/apps/meteor/app/livechat/server/hooks/markRoomNotResponded.ts
+++ b/apps/meteor/app/livechat/server/hooks/markRoomNotResponded.ts
@@ -1,15 +1,11 @@
-import { isOmnichannelRoom, isEditedMessage } from '@rocket.chat/core-typings';
+import { isEditedMessage } from '@rocket.chat/core-typings';
import { LivechatRooms } from '@rocket.chat/models';
import { callbacks } from '../../../../lib/callbacks';
callbacks.add(
- 'afterSaveMessage',
- async (message, room) => {
- if (!isOmnichannelRoom(room)) {
- return message;
- }
-
+ 'afterOmnichannelSaveMessage',
+ (message, { room, roomUpdater }) => {
// skips this callback if the message was edited
if (!message || isEditedMessage(message)) {
return message;
@@ -21,11 +17,11 @@ callbacks.add(
}
// check if room is yet awaiting for response
- if (typeof room.t !== 'undefined' && room.t === 'l' && room.waitingResponse) {
+ if (room.waitingResponse) {
return message;
}
- await LivechatRooms.setNotResponseByRoomId(room._id);
+ LivechatRooms.getNotResponseByRoomIdUpdateQuery(roomUpdater);
return message;
},
diff --git a/apps/meteor/app/livechat/server/hooks/markRoomResponded.ts b/apps/meteor/app/livechat/server/hooks/markRoomResponded.ts
index 48ec985aa42c..69e9b11c57b9 100644
--- a/apps/meteor/app/livechat/server/hooks/markRoomResponded.ts
+++ b/apps/meteor/app/livechat/server/hooks/markRoomResponded.ts
@@ -1,78 +1,72 @@
-import type { IOmnichannelRoom } from '@rocket.chat/core-typings';
-import { isOmnichannelRoom, isEditedMessage } from '@rocket.chat/core-typings';
+import type { IOmnichannelRoom, IMessage } from '@rocket.chat/core-typings';
+import { isEditedMessage, isMessageFromVisitor } from '@rocket.chat/core-typings';
+import type { Updater } from '@rocket.chat/models';
import { LivechatRooms, LivechatVisitors, LivechatInquiry } from '@rocket.chat/models';
import moment from 'moment';
import { callbacks } from '../../../../lib/callbacks';
import { notifyOnLivechatInquiryChanged } from '../../../lib/server/lib/notifyListener';
-callbacks.add(
- 'afterSaveMessage',
- async (message, room) => {
- if (!isOmnichannelRoom(room)) {
- return message;
- }
-
- // skips this callback if the message was edited
- if (!message || isEditedMessage(message)) {
- return message;
- }
+export async function markRoomResponded(
+ message: IMessage,
+ room: IOmnichannelRoom,
+ roomUpdater: Updater,
+): Promise {
+ if (message.t || isEditedMessage(message) || isMessageFromVisitor(message)) {
+ return;
+ }
- // skips this callback if the message is a system message
- if (message.t) {
- return message;
- }
+ const monthYear = moment().format('YYYY-MM');
+ const isVisitorActive = await LivechatVisitors.isVisitorActiveOnPeriod(room.v._id, monthYear);
- // if the message has a token, it was sent by the visitor, so ignore it
- if (message.token) {
- return message;
- }
+ // Case: agent answers & visitor is not active, we mark visitor as active
+ if (!isVisitorActive) {
+ await LivechatVisitors.markVisitorActiveForPeriod(room.v._id, monthYear);
+ }
- // Return YYYY-MM from moment
- const monthYear = moment().format('YYYY-MM');
- const isVisitorActive = await LivechatVisitors.isVisitorActiveOnPeriod(room.v._id, monthYear);
+ if (!room.v?.activity?.includes(monthYear)) {
+ LivechatRooms.getVisitorActiveForPeriodUpdateQuery(monthYear, roomUpdater);
+ const livechatInquiry = await LivechatInquiry.markInquiryActiveForPeriod(room._id, monthYear);
- // Case: agent answers & visitor is not active, we mark visitor as active
- if (!isVisitorActive) {
- await LivechatVisitors.markVisitorActiveForPeriod(room.v._id, monthYear);
+ if (livechatInquiry) {
+ void notifyOnLivechatInquiryChanged(livechatInquiry, 'updated', { v: livechatInquiry.v });
}
+ }
- if (!room.v?.activity?.includes(monthYear)) {
- const [, livechatInquiry] = await Promise.all([
- LivechatRooms.markVisitorActiveForPeriod(room._id, monthYear),
- LivechatInquiry.markInquiryActiveForPeriod(room._id, monthYear),
- ]);
- if (livechatInquiry) {
- void notifyOnLivechatInquiryChanged(livechatInquiry, 'updated', { v: livechatInquiry.v });
- }
- }
+ if (room.responseBy) {
+ LivechatRooms.getAgentLastMessageTsUpdateQuery(roomUpdater);
+ }
+ if (!room.waitingResponse) {
+ // case where agent sends second message or any subsequent message in a room before visitor responds to the first message
+ // in this case, we just need to update the lastMessageTs of the responseBy object
if (room.responseBy) {
- await LivechatRooms.setAgentLastMessageTs(room._id);
+ LivechatRooms.getAgentLastMessageTsUpdateQuery(roomUpdater);
}
- // check if room is yet awaiting for response from visitor
- if (!room.waitingResponse) {
- // case where agent sends second message or any subsequent message in a room before visitor responds to the first message
- // in this case, we just need to update the lastMessageTs of the responseBy object
- if (room.responseBy) {
- await LivechatRooms.setAgentLastMessageTs(room._id);
- }
- return message;
- }
+ return room.responseBy;
+ }
+
+ const responseBy: IOmnichannelRoom['responseBy'] = room.responseBy || {
+ _id: message.u._id,
+ username: message.u.username,
+ firstResponseTs: new Date(message.ts),
+ lastMessageTs: new Date(message.ts),
+ };
- // This is the first message from agent after visitor had last responded
- const responseBy: IOmnichannelRoom['responseBy'] = room.responseBy || {
- _id: message.u._id,
- username: message.u.username,
- firstResponseTs: new Date(message.ts),
- lastMessageTs: new Date(message.ts),
- };
+ LivechatRooms.getResponseByRoomIdUpdateQuery(responseBy, roomUpdater);
- // this unsets waitingResponse and sets responseBy object
- await LivechatRooms.setResponseByRoomId(room._id, responseBy);
+ return responseBy;
+}
+
+callbacks.add(
+ 'afterOmnichannelSaveMessage',
+ async (message, { room, roomUpdater }) => {
+ if (!message || message.t || isEditedMessage(message) || isMessageFromVisitor(message)) {
+ return;
+ }
- return message;
+ await markRoomResponded(message, room, roomUpdater);
},
callbacks.priority.HIGH,
'markRoomResponded',
diff --git a/apps/meteor/app/livechat/server/hooks/processRoomAbandonment.ts b/apps/meteor/app/livechat/server/hooks/processRoomAbandonment.ts
index 8a5a4c280670..a6031bd42efa 100644
--- a/apps/meteor/app/livechat/server/hooks/processRoomAbandonment.ts
+++ b/apps/meteor/app/livechat/server/hooks/processRoomAbandonment.ts
@@ -6,11 +6,12 @@ import moment from 'moment';
import { callbacks } from '../../../../lib/callbacks';
import { settings } from '../../../settings/server';
import { businessHourManager } from '../business-hour';
+import type { CloseRoomParams } from '../lib/localTypes';
-const getSecondsWhenOfficeHoursIsDisabled = (room: IOmnichannelRoom, agentLastMessage: IMessage) =>
+export const getSecondsWhenOfficeHoursIsDisabled = (room: IOmnichannelRoom, agentLastMessage: IMessage) =>
moment(new Date(room.closedAt || new Date())).diff(moment(new Date(agentLastMessage.ts)), 'seconds');
-const parseDays = (
+export const parseDays = (
acc: Record,
day: IBusinessHourWorkHour,
) => {
@@ -22,7 +23,7 @@ const parseDays = (
return acc;
};
-const getSecondsSinceLastAgentResponse = async (room: IOmnichannelRoom, agentLastMessage: IMessage) => {
+export const getSecondsSinceLastAgentResponse = async (room: IOmnichannelRoom, agentLastMessage: IMessage) => {
if (!settings.get('Livechat_enable_business_hours')) {
return getSecondsWhenOfficeHoursIsDisabled(room, agentLastMessage);
}
@@ -43,65 +44,91 @@ const getSecondsSinceLastAgentResponse = async (room: IOmnichannelRoom, agentLas
officeDays = (await businessHourManager.getBusinessHour())?.workHours.reduce(parseDays, {});
}
- if (!officeDays) {
+ // Empty object we assume invalid config
+ if (!officeDays || !Object.keys(officeDays).length) {
return getSecondsWhenOfficeHoursIsDisabled(room, agentLastMessage);
}
let totalSeconds = 0;
- const endOfConversation = moment(new Date(room.closedAt || new Date()));
- const startOfInactivity = moment(new Date(agentLastMessage.ts));
+ const endOfConversation = moment.utc(new Date(room.closedAt || new Date()));
+ const startOfInactivity = moment.utc(new Date(agentLastMessage.ts));
const daysOfInactivity = endOfConversation.clone().startOf('day').diff(startOfInactivity.clone().startOf('day'), 'days');
- const inactivityDay = moment(new Date(agentLastMessage.ts));
+ const inactivityDay = moment.utc(new Date(agentLastMessage.ts));
+
for (let index = 0; index <= daysOfInactivity; index++) {
const today = inactivityDay.clone().format('dddd');
const officeDay = officeDays[today];
- const startTodaysOfficeHour = moment(`${officeDay.start.day}:${officeDay.start.time}`, 'dddd:HH:mm').add(index, 'days');
- const endTodaysOfficeHour = moment(`${officeDay.finish.day}:${officeDay.finish.time}`, 'dddd:HH:mm').add(index, 'days');
- if (officeDays[today].open) {
- const firstDayOfInactivity = startOfInactivity.clone().format('D') === inactivityDay.clone().format('D');
- const lastDayOfInactivity = endOfConversation.clone().format('D') === inactivityDay.clone().format('D');
-
- if (!firstDayOfInactivity && !lastDayOfInactivity) {
- totalSeconds += endTodaysOfficeHour.clone().diff(startTodaysOfficeHour, 'seconds');
- } else {
- const end = endOfConversation.isBefore(endTodaysOfficeHour) ? endOfConversation : endTodaysOfficeHour;
- const start = firstDayOfInactivity ? inactivityDay : startTodaysOfficeHour;
- totalSeconds += end.clone().diff(start, 'seconds');
- }
+ if (!officeDay) {
+ inactivityDay.add(1, 'days');
+ continue;
+ }
+ if (!officeDay.open) {
+ inactivityDay.add(1, 'days');
+ continue;
+ }
+ if (!officeDay?.start?.time || !officeDay?.finish?.time) {
+ inactivityDay.add(1, 'days');
+ continue;
}
- inactivityDay.add(1, 'days');
- }
- return totalSeconds;
-};
-callbacks.add(
- 'livechat.closeRoom',
- async (params) => {
- const { room } = params;
+ const [officeStartHour, officeStartMinute] = officeDay.start.time.split(':');
+ const [officeCloseHour, officeCloseMinute] = officeDay.finish.time.split(':');
+ // We should only take in consideration the time where the office is open and the conversation was inactive
+ const todayStartOfficeHours = inactivityDay
+ .clone()
+ .set({ hour: parseInt(officeStartHour, 10), minute: parseInt(officeStartMinute, 10) });
+ const todayEndOfficeHours = inactivityDay.clone().set({ hour: parseInt(officeCloseHour, 10), minute: parseInt(officeCloseMinute, 10) });
- if (!isOmnichannelRoom(room)) {
- return params;
+ // 1: Room was inactive the whole day, we add the whole time BH is inactive
+ if (startOfInactivity.isBefore(todayStartOfficeHours) && endOfConversation.isAfter(todayEndOfficeHours)) {
+ totalSeconds += todayEndOfficeHours.diff(todayStartOfficeHours, 'seconds');
}
- const closedByAgent = room.closer !== 'visitor';
- const wasTheLastMessageSentByAgent = room.lastMessage && !room.lastMessage.token;
- if (!closedByAgent || !wasTheLastMessageSentByAgent) {
- return params;
+ // 2: Room was inactive before start but was closed before end of BH, we add the inactive time
+ if (startOfInactivity.isBefore(todayStartOfficeHours) && endOfConversation.isBefore(todayEndOfficeHours)) {
+ totalSeconds += endOfConversation.diff(todayStartOfficeHours, 'seconds');
}
- if (!room.v?.lastMessageTs) {
- return params;
+ // 3: Room was inactive after start and ended after end of BH, we add the inactive time
+ if (startOfInactivity.isAfter(todayStartOfficeHours) && endOfConversation.isAfter(todayEndOfficeHours)) {
+ totalSeconds += todayEndOfficeHours.diff(startOfInactivity, 'seconds');
}
- const agentLastMessage = await Messages.findAgentLastMessageByVisitorLastMessageTs(room._id, room.v.lastMessageTs);
- if (!agentLastMessage) {
- return params;
+ // 4: Room was inactive after start and before end of BH, we add the inactive time
+ if (startOfInactivity.isAfter(todayStartOfficeHours) && endOfConversation.isBefore(todayEndOfficeHours)) {
+ totalSeconds += endOfConversation.diff(startOfInactivity, 'seconds');
}
- const secondsSinceLastAgentResponse = await getSecondsSinceLastAgentResponse(room, agentLastMessage);
- await LivechatRooms.setVisitorInactivityInSecondsById(room._id, secondsSinceLastAgentResponse);
+ inactivityDay.add(1, 'days');
+ }
+ return totalSeconds;
+};
+
+export const onCloseRoom = async (params: { room: IOmnichannelRoom; options: CloseRoomParams['options'] }) => {
+ const { room } = params;
+
+ if (!isOmnichannelRoom(room)) {
return params;
- },
- callbacks.priority.HIGH,
- 'process-room-abandonment',
-);
+ }
+
+ const closedByAgent = room.closer !== 'visitor';
+ const wasTheLastMessageSentByAgent = room.lastMessage && !room.lastMessage.token;
+ if (!closedByAgent || !wasTheLastMessageSentByAgent) {
+ return params;
+ }
+
+ if (!room.v?.lastMessageTs) {
+ return params;
+ }
+
+ const agentLastMessage = await Messages.findAgentLastMessageByVisitorLastMessageTs(room._id, room.v.lastMessageTs);
+ if (!agentLastMessage) {
+ return params;
+ }
+ const secondsSinceLastAgentResponse = await getSecondsSinceLastAgentResponse(room, agentLastMessage);
+ await LivechatRooms.setVisitorInactivityInSecondsById(room._id, secondsSinceLastAgentResponse);
+
+ return params;
+};
+
+callbacks.add('livechat.closeRoom', onCloseRoom, callbacks.priority.HIGH, 'process-room-abandonment');
diff --git a/apps/meteor/app/livechat/server/hooks/saveAnalyticsData.ts b/apps/meteor/app/livechat/server/hooks/saveAnalyticsData.ts
index e92e6b4d940b..109f49f440b5 100644
--- a/apps/meteor/app/livechat/server/hooks/saveAnalyticsData.ts
+++ b/apps/meteor/app/livechat/server/hooks/saveAnalyticsData.ts
@@ -1,84 +1,82 @@
-import { isEditedMessage, isOmnichannelRoom } from '@rocket.chat/core-typings';
+import { isEditedMessage, isMessageFromVisitor } from '@rocket.chat/core-typings';
+import type { IOmnichannelRoom } from '@rocket.chat/core-typings';
import { LivechatRooms } from '@rocket.chat/models';
import { callbacks } from '../../../../lib/callbacks';
import { normalizeMessageFileUpload } from '../../../utils/server/functions/normalizeMessageFileUpload';
-callbacks.add(
- 'afterSaveMessage',
- async (message, room) => {
- // check if room is livechat
- if (!isOmnichannelRoom(room)) {
- return message;
- }
+const getMetricValue = (metric: T | undefined, defaultValue: T): T => metric ?? defaultValue;
+const calculateTimeDifference = (startTime: T, now: Date): number =>
+ (now.getTime() - new Date(startTime).getTime()) / 1000;
+const calculateAvgResponseTime = (totalResponseTime: number, newResponseTime: number, responseCount: number) =>
+ (totalResponseTime + newResponseTime) / (responseCount + 1);
- // skips this callback if the message was edited
- if (!message || isEditedMessage(message)) {
- return message;
- }
+const getFirstResponseAnalytics = (
+ visitorLastQuery: Date,
+ agentJoinTime: Date,
+ totalResponseTime: number,
+ responseCount: number,
+ now: Date,
+) => {
+ const responseTime = calculateTimeDifference(visitorLastQuery, now);
+ const reactionTime = calculateTimeDifference(agentJoinTime, now);
+ const avgResponseTime = calculateAvgResponseTime(totalResponseTime, responseTime, responseCount);
- // if the message has a token, it was sent by the visitor
- if (message.token) {
- // When visitor sends a mesage, most metrics wont be calculated/served.
- // But, v.lq (last query) will be updated to the message time. This has to be done
- // As not doing it will cause the metrics to be crazy and not have real values.
- await LivechatRooms.saveAnalyticsDataByRoomId(room, message);
- return message;
- }
+ return {
+ firstResponseDate: now,
+ firstResponseTime: responseTime,
+ responseTime,
+ avgResponseTime,
+ firstReactionDate: now,
+ firstReactionTime: reactionTime,
+ reactionTime,
+ };
+};
- if (message.file) {
- message = { ...(await normalizeMessageFileUpload(message)), ...{ _updatedAt: message._updatedAt } };
- }
+const getSubsequentResponseAnalytics = (visitorLastQuery: Date, totalResponseTime: number, responseCount: number, now: Date) => {
+ const responseTime = calculateTimeDifference(visitorLastQuery, now);
+ const avgResponseTime = calculateAvgResponseTime(totalResponseTime, responseTime, responseCount);
- const now = new Date();
- let analyticsData;
+ return {
+ responseTime,
+ avgResponseTime,
+ reactionTime: responseTime,
+ };
+};
- const visitorLastQuery = room.metrics?.v ? room.metrics.v.lq : room.ts;
- const agentLastReply = room.metrics?.servedBy ? room.metrics.servedBy.lr : room.ts;
- const agentJoinTime = room.servedBy?.ts ? room.servedBy.ts : room.ts;
+const getAnalyticsData = (room: IOmnichannelRoom, now: Date): Record | undefined => {
+ const visitorLastQuery = getMetricValue(room.metrics?.v?.lq, room.ts);
+ const agentLastReply = getMetricValue(room.metrics?.servedBy?.lr, room.ts);
+ const agentJoinTime = getMetricValue(room.servedBy?.ts, room.ts);
+ const totalResponseTime = getMetricValue(room.metrics?.response?.tt, 0);
+ const responseCount = getMetricValue(room.metrics?.response?.total, 0);
- const isResponseTt = room.metrics?.response?.tt;
- const isResponseTotal = room.metrics?.response?.total;
+ if (agentLastReply === room.ts) {
+ return getFirstResponseAnalytics(visitorLastQuery, agentJoinTime, totalResponseTime, responseCount, now);
+ }
+ if (visitorLastQuery > agentLastReply) {
+ return getSubsequentResponseAnalytics(visitorLastQuery, totalResponseTime, responseCount, now);
+ }
+};
- if (agentLastReply === room.ts) {
- // first response
- const firstResponseDate = now;
- const firstResponseTime = (now.getTime() - new Date(visitorLastQuery).getTime()) / 1000;
- const responseTime = (now.getTime() - new Date(visitorLastQuery).getTime()) / 1000;
- const avgResponseTime =
- ((isResponseTt ? room.metrics?.response?.tt : 0) || 0 + responseTime) /
- ((isResponseTotal ? room.metrics?.response?.total : 0) || 0 + 1);
-
- const firstReactionDate = now;
- const firstReactionTime = (now.getTime() - new Date(agentJoinTime).getTime()) / 1000;
- const reactionTime = (now.getTime() - new Date(agentJoinTime).getTime()) / 1000;
-
- analyticsData = {
- firstResponseDate,
- firstResponseTime,
- responseTime,
- avgResponseTime,
- firstReactionDate,
- firstReactionTime,
- reactionTime,
- };
- } else if (visitorLastQuery > agentLastReply) {
- // response, not first
- const responseTime = (now.getTime() - new Date(visitorLastQuery).getTime()) / 1000;
- const avgResponseTime =
- ((isResponseTt ? room.metrics?.response?.tt : 0) || 0 + responseTime) /
- ((isResponseTotal ? room.metrics?.response?.total : 0) || 0 + 1);
+callbacks.add(
+ 'afterOmnichannelSaveMessage',
+ async (message, { room, roomUpdater }) => {
+ if (!message || isEditedMessage(message)) {
+ return message;
+ }
- const reactionTime = (now.getTime() - new Date(visitorLastQuery).getTime()) / 1000;
+ if (message.file) {
+ message = { ...(await normalizeMessageFileUpload(message)), ...{ _updatedAt: message._updatedAt } };
+ }
- analyticsData = {
- responseTime,
- avgResponseTime,
- reactionTime,
- };
- } // ignore, its continuing response
+ if (isMessageFromVisitor(message)) {
+ LivechatRooms.getAnalyticsUpdateQueryBySentByVisitor(room, message, roomUpdater);
+ } else {
+ const analyticsData = getAnalyticsData(room, new Date());
+ LivechatRooms.getAnalyticsUpdateQueryBySentByAgent(room, message, analyticsData, roomUpdater);
+ }
- await LivechatRooms.saveAnalyticsDataByRoomId(room, message, analyticsData);
return message;
},
callbacks.priority.LOW,
diff --git a/apps/meteor/app/livechat/server/hooks/saveLastMessageToInquiry.ts b/apps/meteor/app/livechat/server/hooks/saveLastMessageToInquiry.ts
index e65f1d99b884..1925e135a562 100644
--- a/apps/meteor/app/livechat/server/hooks/saveLastMessageToInquiry.ts
+++ b/apps/meteor/app/livechat/server/hooks/saveLastMessageToInquiry.ts
@@ -1,4 +1,4 @@
-import { isOmnichannelRoom, isEditedMessage } from '@rocket.chat/core-typings';
+import { isEditedMessage } from '@rocket.chat/core-typings';
import { LivechatInquiry } from '@rocket.chat/models';
import { callbacks } from '../../../../lib/callbacks';
@@ -7,9 +7,9 @@ import { settings } from '../../../settings/server';
import { RoutingManager } from '../lib/RoutingManager';
callbacks.add(
- 'afterSaveMessage',
- async (message, room) => {
- if (!isOmnichannelRoom(room) || isEditedMessage(message) || message.t) {
+ 'afterOmnichannelSaveMessage',
+ async (message, { room }) => {
+ if (isEditedMessage(message) || message.t) {
return message;
}
diff --git a/apps/meteor/app/livechat/server/hooks/saveLastVisitorMessageTs.ts b/apps/meteor/app/livechat/server/hooks/saveLastVisitorMessageTs.ts
index 4bc28c3990ba..03dcfdbf81bd 100644
--- a/apps/meteor/app/livechat/server/hooks/saveLastVisitorMessageTs.ts
+++ b/apps/meteor/app/livechat/server/hooks/saveLastVisitorMessageTs.ts
@@ -1,22 +1,18 @@
-import { isOmnichannelRoom } from '@rocket.chat/core-typings';
+import { isMessageFromVisitor } from '@rocket.chat/core-typings';
import { LivechatRooms } from '@rocket.chat/models';
import { callbacks } from '../../../../lib/callbacks';
callbacks.add(
- 'afterSaveMessage',
- async (message, room) => {
- if (!(isOmnichannelRoom(room) && room.v.token)) {
- return message;
- }
- if (message.t) {
- return message;
- }
- if (!message.token) {
+ 'afterOmnichannelSaveMessage',
+ async (message, { roomUpdater }) => {
+ if (message.t || !isMessageFromVisitor(message)) {
return message;
}
- await LivechatRooms.setVisitorLastMessageTimestampByRoomId(room._id, message.ts);
+ await LivechatRooms.getVisitorLastMessageTsUpdateQueryByRoomId(message.ts, roomUpdater);
+
+ return message;
},
callbacks.priority.HIGH,
'save-last-visitor-message-timestamp',
diff --git a/apps/meteor/app/livechat/server/hooks/sendToCRM.ts b/apps/meteor/app/livechat/server/hooks/sendToCRM.ts
index 24e1d685a0e6..b3624bd3ecf6 100644
--- a/apps/meteor/app/livechat/server/hooks/sendToCRM.ts
+++ b/apps/meteor/app/livechat/server/hooks/sendToCRM.ts
@@ -261,13 +261,8 @@ callbacks.add(
);
callbacks.add(
- 'afterSaveMessage',
- async (message, room) => {
- // only call webhook if it is a livechat room
- if (!isOmnichannelRoom(room) || !room?.v?.token) {
- return message;
- }
-
+ 'afterOmnichannelSaveMessage',
+ async (message, { room }) => {
// if the message has a token, it was sent from the visitor
// if not, it was sent from the agent
if (message.token && !settings.get('Livechat_webhook_on_visitor_message')) {
diff --git a/apps/meteor/app/livechat/server/index.ts b/apps/meteor/app/livechat/server/index.ts
index fc96f2a921a9..9a1f40238df5 100644
--- a/apps/meteor/app/livechat/server/index.ts
+++ b/apps/meteor/app/livechat/server/index.ts
@@ -16,6 +16,7 @@ import './hooks/saveContactLastChat';
import './hooks/saveLastMessageToInquiry';
import './hooks/afterUserActions';
import './hooks/afterAgentRemoved';
+import './hooks/afterSaveOmnichannelMessage';
import './methods/addAgent';
import './methods/addManager';
import './methods/changeLivechatStatus';
diff --git a/apps/meteor/app/livechat/server/lib/Helper.ts b/apps/meteor/app/livechat/server/lib/Helper.ts
index c0e85a8c7c2b..1ef572df3068 100644
--- a/apps/meteor/app/livechat/server/lib/Helper.ts
+++ b/apps/meteor/app/livechat/server/lib/Helper.ts
@@ -36,7 +36,6 @@ import { validateEmail as validatorFunc } from '../../../../lib/emailValidator';
import { i18n } from '../../../../server/lib/i18n';
import { hasRoleAsync } from '../../../authorization/server/functions/hasRole';
import { sendNotification } from '../../../lib/server';
-import { sendMessage } from '../../../lib/server/functions/sendMessage';
import {
notifyOnLivechatDepartmentAgentChanged,
notifyOnLivechatDepartmentAgentChangedByAgentsAndDepartmentId,
@@ -141,10 +140,7 @@ export const createLivechatRoom = async <
}
await callbacks.run('livechat.newRoom', room);
-
- // TODO: replace with `Message.saveSystemMessage`
-
- await sendMessage(guest, { t: 'livechat-started', msg: '', groupable: false, token: guest.token }, room);
+ await Message.saveSystemMessageAndNotifyUser('livechat-started', rid, '', { _id, username }, { groupable: false, token: guest.token });
return result.value as IOmnichannelRoom;
};
diff --git a/apps/meteor/app/livechat/server/lib/LivechatTyped.ts b/apps/meteor/app/livechat/server/lib/LivechatTyped.ts
index ccca7a8eb68e..bb8a3fd77ba2 100644
--- a/apps/meteor/app/livechat/server/lib/LivechatTyped.ts
+++ b/apps/meteor/app/livechat/server/lib/LivechatTyped.ts
@@ -252,7 +252,6 @@ class LivechatClass {
const isRoomClosedByVisitorParams = (params: CloseRoomParams): params is CloseRoomParamsByVisitor =>
(params as CloseRoomParamsByVisitor).visitor !== undefined;
- let chatCloser: any;
if (isRoomClosedByUserParams(params)) {
const { user } = params;
this.logger.debug(`Closing by user ${user?._id}`);
@@ -261,7 +260,6 @@ class LivechatClass {
_id: user?._id || '',
username: user?.username,
};
- chatCloser = user;
} else if (isRoomClosedByVisitorParams(params)) {
const { visitor } = params;
this.logger.debug(`Closing by visitor ${params.visitor._id}`);
@@ -270,7 +268,6 @@ class LivechatClass {
_id: visitor._id,
username: visitor.username,
};
- chatCloser = visitor;
} else {
throw new Error('Error: Please provide details of the user or visitor who closed the room');
}
@@ -296,10 +293,6 @@ class LivechatClass {
this.logger.debug(`DB updated for room ${room._id}`);
- const transcriptRequested =
- !!transcriptRequest || (!settings.get('Livechat_enable_transcript') && settings.get('Livechat_transcript_send_always'));
-
- // Retrieve the closed room
const newRoom = await LivechatRooms.findOneById(rid);
if (!newRoom) {
@@ -307,24 +300,20 @@ class LivechatClass {
}
this.logger.debug(`Sending closing message to room ${room._id}`);
- await sendMessage(
- chatCloser,
- {
- t: 'livechat-close',
- msg: comment,
- groupable: false,
- transcriptRequested,
- ...(isRoomClosedByVisitorParams(params) && { token: chatCloser.token }),
- },
- newRoom,
- );
+
+ const transcriptRequested =
+ !!transcriptRequest || (!settings.get('Livechat_enable_transcript') && settings.get('Livechat_transcript_send_always'));
+
+ await Message.saveSystemMessageAndNotifyUser('livechat-close', rid, comment ?? '', closeData.closedBy, {
+ groupable: false,
+ transcriptRequested,
+ ...(isRoomClosedByVisitorParams(params) && { token: params.visitor.token }),
+ });
if (settings.get('Livechat_enable_transcript') && !settings.get('Livechat_transcript_send_always')) {
await Message.saveSystemMessage('command', rid, 'promptTranscript', closeData.closedBy);
}
- this.logger.debug(`Running callbacks for room ${newRoom._id}`);
-
process.nextTick(() => {
/**
* @deprecated the `AppEvents.ILivechatRoomClosedHandler` event will be removed
@@ -878,7 +867,7 @@ class LivechatClass {
return Messages.findVisibleByRoomIdNotContainingTypes(rid, ignoredMessageTypes, {
sort: { ts: 1 },
- }).toArray();
+ });
}
async archiveDepartment(_id: string) {
@@ -1254,31 +1243,20 @@ class LivechatClass {
const scopeData = scope || (nextDepartment ? 'department' : 'agent');
this.logger.info(`Storing new chat transfer of ${room._id} [Transfered by: ${_id} to ${scopeData}]`);
- await sendMessage(
- transferredBy,
- {
- t: 'livechat_transfer_history',
- rid: room._id,
+ const transferMessage = {
+ ...(transferData.transferredBy.userType === 'visitor' && { token: room.v.token }),
+ transferData: {
+ transferredBy,
ts: new Date(),
- msg: '',
- u: {
- _id,
- username,
- },
- groupable: false,
- ...(transferData.transferredBy.userType === 'visitor' && { token: room.v.token }),
- transferData: {
- transferredBy,
- ts: new Date(),
- scope: scopeData,
- comment,
- ...(previousDepartment && { previousDepartment }),
- ...(nextDepartment && { nextDepartment }),
- ...(transferredTo && { transferredTo }),
- },
+ scope: scopeData,
+ comment,
+ ...(previousDepartment && { previousDepartment }),
+ ...(nextDepartment && { nextDepartment }),
+ ...(transferredTo && { transferredTo }),
},
- room,
- );
+ };
+
+ await Message.saveSystemMessageAndNotifyUser('livechat_transfer_history', room._id, '', { _id, username }, transferMessage);
}
async saveGuest(guestData: Pick & { email?: string; phone?: string }, userId: string) {
diff --git a/apps/meteor/app/livechat/server/lib/QueueManager.ts b/apps/meteor/app/livechat/server/lib/QueueManager.ts
index 5ae03e0ee03b..e1ea79d84163 100644
--- a/apps/meteor/app/livechat/server/lib/QueueManager.ts
+++ b/apps/meteor/app/livechat/server/lib/QueueManager.ts
@@ -15,6 +15,7 @@ import { Random } from '@rocket.chat/random';
import { Match, check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
+import { dispatchInquiryPosition } from '../../../../ee/app/livechat-enterprise/server/lib/Helper';
import { callbacks } from '../../../../lib/callbacks';
import { sendNotification } from '../../../lib/server';
import {
@@ -27,6 +28,7 @@ import { i18n } from '../../../utils/lib/i18n';
import { createLivechatRoom, createLivechatInquiry, allowAgentSkipQueue } from './Helper';
import { Livechat } from './LivechatTyped';
import { RoutingManager } from './RoutingManager';
+import { getInquirySortMechanismSetting } from './settings';
const logger = new Logger('QueueManager');
@@ -221,7 +223,7 @@ export class QueueManager {
const name = (roomInfo?.fname as string) || guest.name || guest.username;
- const room = await createLivechatRoom(rid, name, guest, roomInfo, {
+ const room = await createLivechatRoom(rid, name, { ...guest, ...(department && { department }) }, roomInfo, {
...extraData,
...(Boolean(customFields) && { customFields }),
});
@@ -259,6 +261,18 @@ export class QueueManager {
throw new Error('room-not-found');
}
+ if (!newRoom.servedBy && settings.get('Omnichannel_calculate_dispatch_service_queue_statistics')) {
+ const [inq] = await LivechatInquiry.getCurrentSortedQueueAsync({
+ inquiryId: inquiry._id,
+ department,
+ queueSortBy: getInquirySortMechanismSetting(),
+ });
+
+ if (inq) {
+ void dispatchInquiryPosition(inq);
+ }
+ }
+
return newRoom;
}
diff --git a/apps/meteor/app/livechat/server/methods/addAgent.ts b/apps/meteor/app/livechat/server/methods/addAgent.ts
index 6160db590ece..0551e985e18e 100644
--- a/apps/meteor/app/livechat/server/methods/addAgent.ts
+++ b/apps/meteor/app/livechat/server/methods/addAgent.ts
@@ -1,12 +1,12 @@
import type { IUser } from '@rocket.chat/core-typings';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger';
import { Livechat } from '../lib/LivechatTyped';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:addAgent'(username: string): Promise;
diff --git a/apps/meteor/app/livechat/server/methods/addManager.ts b/apps/meteor/app/livechat/server/methods/addManager.ts
index 347c4f07d63f..a954d8111773 100644
--- a/apps/meteor/app/livechat/server/methods/addManager.ts
+++ b/apps/meteor/app/livechat/server/methods/addManager.ts
@@ -1,12 +1,12 @@
import type { IUser } from '@rocket.chat/core-typings';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger';
import { Livechat } from '../lib/LivechatTyped';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:addManager'(username: string): Promise;
diff --git a/apps/meteor/app/livechat/server/methods/changeLivechatStatus.ts b/apps/meteor/app/livechat/server/methods/changeLivechatStatus.ts
index 8ccfcd5ec468..f45588cad6d3 100644
--- a/apps/meteor/app/livechat/server/methods/changeLivechatStatus.ts
+++ b/apps/meteor/app/livechat/server/methods/changeLivechatStatus.ts
@@ -1,13 +1,13 @@
import { ILivechatAgentStatus } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Users } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger';
import { Livechat as LivechatTS } from '../lib/LivechatTyped';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:changeLivechatStatus'(params?: { status?: ILivechatAgentStatus; agentId?: string }): unknown;
diff --git a/apps/meteor/app/livechat/server/methods/closeRoom.ts b/apps/meteor/app/livechat/server/methods/closeRoom.ts
index 5fdf9e7d504f..19c8b2709389 100644
--- a/apps/meteor/app/livechat/server/methods/closeRoom.ts
+++ b/apps/meteor/app/livechat/server/methods/closeRoom.ts
@@ -1,6 +1,6 @@
import type { IOmnichannelRoom } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Users, LivechatRooms, Subscriptions as SubscriptionRaw } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
@@ -35,7 +35,7 @@ type LivechatCloseRoomOptions = Omit
};
};
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:closeRoom'(roomId: string, comment?: string, options?: CloseRoomOptions): void;
diff --git a/apps/meteor/app/livechat/server/methods/discardTranscript.ts b/apps/meteor/app/livechat/server/methods/discardTranscript.ts
index d46c8ffea35f..3265aa9c54d2 100644
--- a/apps/meteor/app/livechat/server/methods/discardTranscript.ts
+++ b/apps/meteor/app/livechat/server/methods/discardTranscript.ts
@@ -1,12 +1,12 @@
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { LivechatRooms } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:discardTranscript'(rid: string): boolean;
diff --git a/apps/meteor/app/livechat/server/methods/getAgentData.ts b/apps/meteor/app/livechat/server/methods/getAgentData.ts
index d32d24d7f7c1..5fe58560806e 100644
--- a/apps/meteor/app/livechat/server/methods/getAgentData.ts
+++ b/apps/meteor/app/livechat/server/methods/getAgentData.ts
@@ -1,13 +1,13 @@
import type { ILivechatAgent } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { LivechatVisitors, LivechatRooms, Users } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger';
import { settings } from '../../../settings/server';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:getAgentData'(params: {
diff --git a/apps/meteor/app/livechat/server/methods/getAgentOverviewData.ts b/apps/meteor/app/livechat/server/methods/getAgentOverviewData.ts
index b5ea8dafe92c..819bac03c5b4 100644
--- a/apps/meteor/app/livechat/server/methods/getAgentOverviewData.ts
+++ b/apps/meteor/app/livechat/server/methods/getAgentOverviewData.ts
@@ -1,13 +1,13 @@
import type { ConversationData } from '@rocket.chat/core-services';
import { OmnichannelAnalytics } from '@rocket.chat/core-services';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Users } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:getAgentOverviewData'(options: { chartOptions: { name: string } }): ConversationData | void;
diff --git a/apps/meteor/app/livechat/server/methods/getAnalyticsChartData.ts b/apps/meteor/app/livechat/server/methods/getAnalyticsChartData.ts
index 85c8e033b8f5..2ff682c1c39c 100644
--- a/apps/meteor/app/livechat/server/methods/getAnalyticsChartData.ts
+++ b/apps/meteor/app/livechat/server/methods/getAnalyticsChartData.ts
@@ -1,12 +1,12 @@
import type { ChartDataResult } from '@rocket.chat/core-services';
import { OmnichannelAnalytics } from '@rocket.chat/core-services';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Users } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:getAnalyticsChartData'(options: { chartOptions: { name: string } }): ChartDataResult | void;
diff --git a/apps/meteor/app/livechat/server/methods/getAnalyticsOverviewData.ts b/apps/meteor/app/livechat/server/methods/getAnalyticsOverviewData.ts
index c9bb3d163457..9f56cfa57069 100644
--- a/apps/meteor/app/livechat/server/methods/getAnalyticsOverviewData.ts
+++ b/apps/meteor/app/livechat/server/methods/getAnalyticsOverviewData.ts
@@ -1,14 +1,14 @@
import type { AnalyticsOverviewDataResult } from '@rocket.chat/core-services';
import { OmnichannelAnalytics } from '@rocket.chat/core-services';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Users } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger';
import { settings } from '../../../settings/server';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:getAnalyticsOverviewData'(options: { analyticsOptions: { name: string } }): AnalyticsOverviewDataResult[] | void;
diff --git a/apps/meteor/app/livechat/server/methods/getCustomFields.ts b/apps/meteor/app/livechat/server/methods/getCustomFields.ts
index ec0ac35d6c21..36dca08f0859 100644
--- a/apps/meteor/app/livechat/server/methods/getCustomFields.ts
+++ b/apps/meteor/app/livechat/server/methods/getCustomFields.ts
@@ -1,11 +1,11 @@
import type { ILivechatCustomField } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { LivechatCustomField } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:getCustomFields'(): ILivechatCustomField[];
diff --git a/apps/meteor/app/livechat/server/methods/getDepartmentForwardRestrictions.ts b/apps/meteor/app/livechat/server/methods/getDepartmentForwardRestrictions.ts
index b26d9706a8cd..2b891514d03e 100644
--- a/apps/meteor/app/livechat/server/methods/getDepartmentForwardRestrictions.ts
+++ b/apps/meteor/app/livechat/server/methods/getDepartmentForwardRestrictions.ts
@@ -1,10 +1,10 @@
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
import { callbacks } from '../../../../lib/callbacks';
import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:getDepartmentForwardRestrictions'(departmentId: string): unknown;
diff --git a/apps/meteor/app/livechat/server/methods/getFirstRoomMessage.ts b/apps/meteor/app/livechat/server/methods/getFirstRoomMessage.ts
index 197898e8d2b2..d8accf7f84f5 100644
--- a/apps/meteor/app/livechat/server/methods/getFirstRoomMessage.ts
+++ b/apps/meteor/app/livechat/server/methods/getFirstRoomMessage.ts
@@ -1,12 +1,12 @@
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { LivechatRooms, Messages } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:getFirstRoomMessage'(params: { rid: string }): unknown;
diff --git a/apps/meteor/app/livechat/server/methods/getNextAgent.ts b/apps/meteor/app/livechat/server/methods/getNextAgent.ts
index 53b8441cad2e..179f1f95dedf 100644
--- a/apps/meteor/app/livechat/server/methods/getNextAgent.ts
+++ b/apps/meteor/app/livechat/server/methods/getNextAgent.ts
@@ -1,6 +1,6 @@
import type { ILivechatAgent } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { LivechatRooms, Users } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
@@ -9,7 +9,7 @@ import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarn
import { settings } from '../../../settings/server';
import { Livechat } from '../lib/LivechatTyped';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:getNextAgent'(params: {
diff --git a/apps/meteor/app/livechat/server/methods/getRoutingConfig.ts b/apps/meteor/app/livechat/server/methods/getRoutingConfig.ts
index 364853a74511..02b2840f41cc 100644
--- a/apps/meteor/app/livechat/server/methods/getRoutingConfig.ts
+++ b/apps/meteor/app/livechat/server/methods/getRoutingConfig.ts
@@ -1,10 +1,10 @@
import type { OmichannelRoutingConfig } from '@rocket.chat/core-typings';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
import { RoutingManager } from '../lib/RoutingManager';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:getRoutingConfig'(): OmichannelRoutingConfig | undefined;
diff --git a/apps/meteor/app/livechat/server/methods/getTagsList.ts b/apps/meteor/app/livechat/server/methods/getTagsList.ts
index e9e467d243c8..b3efe5d026a3 100644
--- a/apps/meteor/app/livechat/server/methods/getTagsList.ts
+++ b/apps/meteor/app/livechat/server/methods/getTagsList.ts
@@ -1,11 +1,11 @@
import type { ILivechatTag } from '@rocket.chat/core-typings';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
import { callbacks } from '../../../../lib/callbacks';
import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:getTagsList'(): ILivechatTag[];
diff --git a/apps/meteor/app/livechat/server/methods/loadHistory.ts b/apps/meteor/app/livechat/server/methods/loadHistory.ts
index 373ede1a3610..1004f9dd604d 100644
--- a/apps/meteor/app/livechat/server/methods/loadHistory.ts
+++ b/apps/meteor/app/livechat/server/methods/loadHistory.ts
@@ -1,13 +1,13 @@
import type { IMessage } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { LivechatVisitors, LivechatRooms } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { check, Match } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import { loadMessageHistory } from '../../../lib/server/functions/loadMessageHistory';
import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:loadHistory'(params: { token: string; rid: string; end?: Date; limit?: number; ls: Date }):
diff --git a/apps/meteor/app/livechat/server/methods/loginByToken.ts b/apps/meteor/app/livechat/server/methods/loginByToken.ts
index cae23e6d16f7..3b82413e038a 100644
--- a/apps/meteor/app/livechat/server/methods/loginByToken.ts
+++ b/apps/meteor/app/livechat/server/methods/loginByToken.ts
@@ -1,10 +1,10 @@
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { LivechatVisitors } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:loginByToken'(token: string): { _id: string } | undefined;
diff --git a/apps/meteor/app/livechat/server/methods/pageVisited.ts b/apps/meteor/app/livechat/server/methods/pageVisited.ts
index c226a91de430..7c0864f27b74 100644
--- a/apps/meteor/app/livechat/server/methods/pageVisited.ts
+++ b/apps/meteor/app/livechat/server/methods/pageVisited.ts
@@ -1,10 +1,10 @@
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger';
import { Livechat } from '../lib/LivechatTyped';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:pageVisited'(token: string, room: string, pageInfo: { title: string; location: { href: string }; change: string }): void;
diff --git a/apps/meteor/app/livechat/server/methods/registerGuest.ts b/apps/meteor/app/livechat/server/methods/registerGuest.ts
index 4a531d0c89e5..c6a119d91591 100644
--- a/apps/meteor/app/livechat/server/methods/registerGuest.ts
+++ b/apps/meteor/app/livechat/server/methods/registerGuest.ts
@@ -1,13 +1,13 @@
import type { ILivechatVisitor, IRoom } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { LivechatVisitors, Messages, LivechatRooms } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { callbacks } from '../../../../lib/callbacks';
import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger';
import { Livechat as LivechatTyped } from '../lib/LivechatTyped';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:registerGuest'({
diff --git a/apps/meteor/app/livechat/server/methods/removeAgent.ts b/apps/meteor/app/livechat/server/methods/removeAgent.ts
index 643ae696ada0..ebb57383784f 100644
--- a/apps/meteor/app/livechat/server/methods/removeAgent.ts
+++ b/apps/meteor/app/livechat/server/methods/removeAgent.ts
@@ -1,11 +1,11 @@
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger';
import { Livechat } from '../lib/LivechatTyped';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:removeAgent'(username: string): boolean;
diff --git a/apps/meteor/app/livechat/server/methods/removeAllClosedRooms.ts b/apps/meteor/app/livechat/server/methods/removeAllClosedRooms.ts
index 9be699ae05ed..ba3939bb8573 100644
--- a/apps/meteor/app/livechat/server/methods/removeAllClosedRooms.ts
+++ b/apps/meteor/app/livechat/server/methods/removeAllClosedRooms.ts
@@ -1,14 +1,14 @@
import type { IOmnichannelRoom } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Logger } from '@rocket.chat/logger';
import { LivechatRooms } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { callbacks } from '../../../../lib/callbacks';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
import { Livechat } from '../lib/LivechatTyped';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:removeAllClosedRooms'(departmentIds?: string[]): Promise;
diff --git a/apps/meteor/app/livechat/server/methods/removeCustomField.ts b/apps/meteor/app/livechat/server/methods/removeCustomField.ts
index 1d3e7c817738..ad02df582337 100644
--- a/apps/meteor/app/livechat/server/methods/removeCustomField.ts
+++ b/apps/meteor/app/livechat/server/methods/removeCustomField.ts
@@ -1,12 +1,12 @@
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { LivechatCustomField } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import type { DeleteResult } from 'mongodb';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:removeCustomField'(_id: string): DeleteResult;
diff --git a/apps/meteor/app/livechat/server/methods/removeDepartment.ts b/apps/meteor/app/livechat/server/methods/removeDepartment.ts
index 3c46f3a424d6..6e4b11c836f6 100644
--- a/apps/meteor/app/livechat/server/methods/removeDepartment.ts
+++ b/apps/meteor/app/livechat/server/methods/removeDepartment.ts
@@ -1,4 +1,4 @@
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import type { DeleteResult } from 'mongodb';
@@ -7,7 +7,7 @@ import { hasPermissionAsync } from '../../../authorization/server/functions/hasP
import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger';
import { DepartmentHelper } from '../lib/Departments';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:removeDepartment'(_id: string): DeleteResult;
diff --git a/apps/meteor/app/livechat/server/methods/removeManager.ts b/apps/meteor/app/livechat/server/methods/removeManager.ts
index 4c003ff922bc..85a5f3076c8c 100644
--- a/apps/meteor/app/livechat/server/methods/removeManager.ts
+++ b/apps/meteor/app/livechat/server/methods/removeManager.ts
@@ -1,11 +1,11 @@
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger';
import { Livechat } from '../lib/LivechatTyped';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:removeManager'(username: string): boolean;
diff --git a/apps/meteor/app/livechat/server/methods/removeRoom.ts b/apps/meteor/app/livechat/server/methods/removeRoom.ts
index db3fcf2c849f..751d51d4f019 100644
--- a/apps/meteor/app/livechat/server/methods/removeRoom.ts
+++ b/apps/meteor/app/livechat/server/methods/removeRoom.ts
@@ -1,12 +1,12 @@
import type { IRoom } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { LivechatRooms } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
import { Livechat } from '../lib/LivechatTyped';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:removeRoom'(rid: IRoom['_id']): void;
diff --git a/apps/meteor/app/livechat/server/methods/removeTrigger.ts b/apps/meteor/app/livechat/server/methods/removeTrigger.ts
index 69f3a4a2d80c..41d79d725176 100644
--- a/apps/meteor/app/livechat/server/methods/removeTrigger.ts
+++ b/apps/meteor/app/livechat/server/methods/removeTrigger.ts
@@ -1,12 +1,12 @@
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { LivechatTrigger } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:removeTrigger'(triggerId: string): boolean;
diff --git a/apps/meteor/app/livechat/server/methods/requestTranscript.ts b/apps/meteor/app/livechat/server/methods/requestTranscript.ts
index 5abf6a3b72e3..80cb3a9625fe 100644
--- a/apps/meteor/app/livechat/server/methods/requestTranscript.ts
+++ b/apps/meteor/app/livechat/server/methods/requestTranscript.ts
@@ -1,5 +1,5 @@
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Users } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
@@ -7,7 +7,7 @@ import { hasPermissionAsync } from '../../../authorization/server/functions/hasP
import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger';
import { Livechat } from '../lib/LivechatTyped';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:requestTranscript'(rid: string, email: string, subject: string): Promise;
diff --git a/apps/meteor/app/livechat/server/methods/returnAsInquiry.ts b/apps/meteor/app/livechat/server/methods/returnAsInquiry.ts
index 38b58b9d2d42..bf76519a5afb 100644
--- a/apps/meteor/app/livechat/server/methods/returnAsInquiry.ts
+++ b/apps/meteor/app/livechat/server/methods/returnAsInquiry.ts
@@ -1,13 +1,13 @@
import { Omnichannel } from '@rocket.chat/core-services';
import type { ILivechatDepartment, IRoom } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { LivechatRooms } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
import { Livechat } from '../lib/LivechatTyped';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:returnAsInquiry'(rid: IRoom['_id'], departmentID?: ILivechatDepartment['_id']): boolean;
diff --git a/apps/meteor/app/livechat/server/methods/saveAgentInfo.ts b/apps/meteor/app/livechat/server/methods/saveAgentInfo.ts
index 90d9815d4cf1..fe542b67156e 100644
--- a/apps/meteor/app/livechat/server/methods/saveAgentInfo.ts
+++ b/apps/meteor/app/livechat/server/methods/saveAgentInfo.ts
@@ -1,12 +1,12 @@
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Users } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
import { hasRoleAsync } from '../../../authorization/server/functions/hasRole';
import { Livechat } from '../lib/LivechatTyped';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:saveAgentInfo'(_id: string, agentData: Record, agentDepartments: string[]): unknown;
diff --git a/apps/meteor/app/livechat/server/methods/saveAppearance.ts b/apps/meteor/app/livechat/server/methods/saveAppearance.ts
index cac5d34264d2..619dae147708 100644
--- a/apps/meteor/app/livechat/server/methods/saveAppearance.ts
+++ b/apps/meteor/app/livechat/server/methods/saveAppearance.ts
@@ -1,12 +1,12 @@
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Settings } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger';
import { notifyOnSettingChangedById } from '../../../lib/server/lib/notifyListener';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:saveAppearance'(settings: { _id: string; value: any }[]): Promise;
diff --git a/apps/meteor/app/livechat/server/methods/saveBusinessHour.ts b/apps/meteor/app/livechat/server/methods/saveBusinessHour.ts
index 2e3e64365649..9bf32697fae9 100644
--- a/apps/meteor/app/livechat/server/methods/saveBusinessHour.ts
+++ b/apps/meteor/app/livechat/server/methods/saveBusinessHour.ts
@@ -1,10 +1,10 @@
import type { ILivechatBusinessHour } from '@rocket.chat/core-typings';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
import { businessHourManager } from '../business-hour';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:saveBusinessHour'(businessHourData: ILivechatBusinessHour): void;
diff --git a/apps/meteor/app/livechat/server/methods/saveCustomField.ts b/apps/meteor/app/livechat/server/methods/saveCustomField.ts
index 8a0435560dd5..c83148ba8d29 100644
--- a/apps/meteor/app/livechat/server/methods/saveCustomField.ts
+++ b/apps/meteor/app/livechat/server/methods/saveCustomField.ts
@@ -1,12 +1,12 @@
import type { ILivechatCustomField } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { LivechatCustomField } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Match, check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:saveCustomField'(
diff --git a/apps/meteor/app/livechat/server/methods/saveDepartment.ts b/apps/meteor/app/livechat/server/methods/saveDepartment.ts
index 971c2189f9a7..b4833523ab3f 100644
--- a/apps/meteor/app/livechat/server/methods/saveDepartment.ts
+++ b/apps/meteor/app/livechat/server/methods/saveDepartment.ts
@@ -1,11 +1,11 @@
import type { ILivechatDepartment } from '@rocket.chat/core-typings';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
import { Livechat } from '../lib/LivechatTyped';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:saveDepartment': (
diff --git a/apps/meteor/app/livechat/server/methods/saveDepartmentAgents.ts b/apps/meteor/app/livechat/server/methods/saveDepartmentAgents.ts
index 73a471869926..42ee521713c0 100644
--- a/apps/meteor/app/livechat/server/methods/saveDepartmentAgents.ts
+++ b/apps/meteor/app/livechat/server/methods/saveDepartmentAgents.ts
@@ -1,12 +1,12 @@
import type { ILivechatDepartmentAgents } from '@rocket.chat/core-typings';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger';
import { Livechat } from '../lib/LivechatTyped';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:saveDepartmentAgents'(
diff --git a/apps/meteor/app/livechat/server/methods/saveInfo.ts b/apps/meteor/app/livechat/server/methods/saveInfo.ts
index a057706fdc23..bb22c127effa 100644
--- a/apps/meteor/app/livechat/server/methods/saveInfo.ts
+++ b/apps/meteor/app/livechat/server/methods/saveInfo.ts
@@ -1,6 +1,6 @@
import { isOmnichannelRoom } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { LivechatRooms, Users } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Match, check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
@@ -9,7 +9,7 @@ import { hasPermissionAsync } from '../../../authorization/server/functions/hasP
import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger';
import { Livechat as LivechatTyped } from '../lib/LivechatTyped';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:saveInfo'(
diff --git a/apps/meteor/app/livechat/server/methods/saveIntegration.ts b/apps/meteor/app/livechat/server/methods/saveIntegration.ts
index de7461d08e10..0a4d82cfbcc1 100644
--- a/apps/meteor/app/livechat/server/methods/saveIntegration.ts
+++ b/apps/meteor/app/livechat/server/methods/saveIntegration.ts
@@ -1,5 +1,5 @@
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Settings } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { trim } from '../../../../lib/utils/stringUtils';
@@ -7,7 +7,7 @@ import { hasPermissionAsync } from '../../../authorization/server/functions/hasP
import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger';
import { notifyOnSettingChangedById } from '../../../lib/server/lib/notifyListener';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:saveIntegration'(values: Record): void;
diff --git a/apps/meteor/app/livechat/server/methods/saveSurveyFeedback.ts b/apps/meteor/app/livechat/server/methods/saveSurveyFeedback.ts
index 48dea8175ea8..36fc3f775b9f 100644
--- a/apps/meteor/app/livechat/server/methods/saveSurveyFeedback.ts
+++ b/apps/meteor/app/livechat/server/methods/saveSurveyFeedback.ts
@@ -1,5 +1,5 @@
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { LivechatRooms, LivechatVisitors } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Match, check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import type { UpdateResult } from 'mongodb';
@@ -7,7 +7,7 @@ import _ from 'underscore';
import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:saveSurveyFeedback'(
diff --git a/apps/meteor/app/livechat/server/methods/saveTrigger.ts b/apps/meteor/app/livechat/server/methods/saveTrigger.ts
index 37f78d081203..850dead9a589 100644
--- a/apps/meteor/app/livechat/server/methods/saveTrigger.ts
+++ b/apps/meteor/app/livechat/server/methods/saveTrigger.ts
@@ -1,13 +1,13 @@
import type { ILivechatTrigger } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { LivechatTrigger } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Match, check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:saveTrigger'(trigger: ILivechatTrigger): boolean;
diff --git a/apps/meteor/app/livechat/server/methods/searchAgent.ts b/apps/meteor/app/livechat/server/methods/searchAgent.ts
index 2a69679f2a07..932eb51e89d6 100644
--- a/apps/meteor/app/livechat/server/methods/searchAgent.ts
+++ b/apps/meteor/app/livechat/server/methods/searchAgent.ts
@@ -1,12 +1,12 @@
import type { IUser } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Users } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:searchAgent'(username: string): { _id: string; username?: string } | undefined;
diff --git a/apps/meteor/app/livechat/server/methods/sendFileLivechatMessage.ts b/apps/meteor/app/livechat/server/methods/sendFileLivechatMessage.ts
index 15577abd76e3..0268207b2f6c 100644
--- a/apps/meteor/app/livechat/server/methods/sendFileLivechatMessage.ts
+++ b/apps/meteor/app/livechat/server/methods/sendFileLivechatMessage.ts
@@ -5,9 +5,9 @@ import type {
VideoAttachmentProps,
IUpload,
} from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { LivechatVisitors, LivechatRooms } from '@rocket.chat/models';
import { Random } from '@rocket.chat/random';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Match, check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
@@ -21,7 +21,7 @@ interface ISendFileLivechatMessage {
msgData?: { avatar?: string; emoji?: string; alias?: string; groupable?: boolean; msg?: string };
}
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
sendFileLivechatMessage(
diff --git a/apps/meteor/app/livechat/server/methods/sendMessageLivechat.ts b/apps/meteor/app/livechat/server/methods/sendMessageLivechat.ts
index ad16dea23e4f..6fac80397906 100644
--- a/apps/meteor/app/livechat/server/methods/sendMessageLivechat.ts
+++ b/apps/meteor/app/livechat/server/methods/sendMessageLivechat.ts
@@ -1,6 +1,6 @@
import { OmnichannelSourceType } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { LivechatVisitors } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Match, check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
@@ -18,7 +18,7 @@ interface ISendMessageLivechat {
agent?: ILivechatMessageAgent;
}
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
sendMessageLivechat(message: ILivechatMessage, agent: ILivechatMessageAgent): boolean;
diff --git a/apps/meteor/app/livechat/server/methods/sendOfflineMessage.ts b/apps/meteor/app/livechat/server/methods/sendOfflineMessage.ts
index c3b5537f31be..b620aa434100 100644
--- a/apps/meteor/app/livechat/server/methods/sendOfflineMessage.ts
+++ b/apps/meteor/app/livechat/server/methods/sendOfflineMessage.ts
@@ -1,4 +1,4 @@
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { check } from 'meteor/check';
import { DDPRateLimiter } from 'meteor/ddp-rate-limiter';
import { Meteor } from 'meteor/meteor';
@@ -6,7 +6,7 @@ import { Meteor } from 'meteor/meteor';
import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger';
import { Livechat } from '../lib/LivechatTyped';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:sendOfflineMessage'(data: { name: string; email: string; message: string }): Promise;
diff --git a/apps/meteor/app/livechat/server/methods/sendTranscript.ts b/apps/meteor/app/livechat/server/methods/sendTranscript.ts
index 366a73c8bb0a..4891f579926a 100644
--- a/apps/meteor/app/livechat/server/methods/sendTranscript.ts
+++ b/apps/meteor/app/livechat/server/methods/sendTranscript.ts
@@ -1,6 +1,6 @@
import { Omnichannel } from '@rocket.chat/core-services';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { LivechatRooms, Users } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
@@ -8,7 +8,7 @@ import { hasPermissionAsync } from '../../../authorization/server/functions/hasP
import { RateLimiter } from '../../../lib/server';
import { Livechat } from '../lib/LivechatTyped';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:sendTranscript'(token: string, rid: string, email: string, subject: string): boolean;
diff --git a/apps/meteor/app/livechat/server/methods/setCustomField.ts b/apps/meteor/app/livechat/server/methods/setCustomField.ts
index fb07c2b29a4e..6d3a2384cdd7 100644
--- a/apps/meteor/app/livechat/server/methods/setCustomField.ts
+++ b/apps/meteor/app/livechat/server/methods/setCustomField.ts
@@ -1,11 +1,11 @@
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { LivechatVisitors, LivechatCustomField, LivechatRooms } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import type { UpdateResult, Document } from 'mongodb';
import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:setCustomField'(token: string, key: string, value: string, overwrite?: boolean): Promise;
diff --git a/apps/meteor/app/livechat/server/methods/setDepartmentForVisitor.ts b/apps/meteor/app/livechat/server/methods/setDepartmentForVisitor.ts
index a14933ed8d47..385f2d989015 100644
--- a/apps/meteor/app/livechat/server/methods/setDepartmentForVisitor.ts
+++ b/apps/meteor/app/livechat/server/methods/setDepartmentForVisitor.ts
@@ -1,5 +1,5 @@
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { LivechatVisitors, Messages, LivechatRooms } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
@@ -7,7 +7,7 @@ import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarn
import { normalizeTransferredByData } from '../lib/Helper';
import { Livechat } from '../lib/LivechatTyped';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:setDepartmentForVisitor'({
diff --git a/apps/meteor/app/livechat/server/methods/setUpConnection.ts b/apps/meteor/app/livechat/server/methods/setUpConnection.ts
index 788b2384c4d3..21ce09acaa22 100644
--- a/apps/meteor/app/livechat/server/methods/setUpConnection.ts
+++ b/apps/meteor/app/livechat/server/methods/setUpConnection.ts
@@ -1,11 +1,11 @@
import { UserStatus } from '@rocket.chat/core-typings';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import { Livechat } from '../lib/LivechatTyped';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:setUpConnection'(data: { token: string }): void;
diff --git a/apps/meteor/app/livechat/server/methods/takeInquiry.ts b/apps/meteor/app/livechat/server/methods/takeInquiry.ts
index 30a5dabb5717..733cbd995208 100644
--- a/apps/meteor/app/livechat/server/methods/takeInquiry.ts
+++ b/apps/meteor/app/livechat/server/methods/takeInquiry.ts
@@ -1,13 +1,13 @@
import { Omnichannel } from '@rocket.chat/core-services';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { LivechatInquiry, LivechatRooms, Users } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
import { settings } from '../../../settings/server';
import { RoutingManager } from '../lib/RoutingManager';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:takeInquiry'(
diff --git a/apps/meteor/app/livechat/server/methods/transfer.ts b/apps/meteor/app/livechat/server/methods/transfer.ts
index 64a32c24638c..e0516fa27981 100644
--- a/apps/meteor/app/livechat/server/methods/transfer.ts
+++ b/apps/meteor/app/livechat/server/methods/transfer.ts
@@ -1,7 +1,7 @@
import { Omnichannel } from '@rocket.chat/core-services';
import type { IUser } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { LivechatVisitors, LivechatRooms, Subscriptions, Users } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Match, check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
@@ -10,7 +10,7 @@ import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarn
import { normalizeTransferredByData } from '../lib/Helper';
import { Livechat } from '../lib/LivechatTyped';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'livechat:transfer'(transferData: {
diff --git a/apps/meteor/app/livechat/server/methods/webhookTest.ts b/apps/meteor/app/livechat/server/methods/webhookTest.ts
index 12a4711d75b4..68800e1a0616 100644
--- a/apps/meteor/app/livechat/server/methods/webhookTest.ts
+++ b/apps/meteor/app/livechat/server/methods/webhookTest.ts
@@ -1,5 +1,5 @@
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { serverFetch as fetch } from '@rocket.chat/server-fetch';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { SystemLogger } from '../../../../server/lib/logger/system';
@@ -14,7 +14,7 @@ const postCatchError = async function (url: string, options?: Record;
diff --git a/apps/meteor/app/livechat/server/sendMessageBySMS.ts b/apps/meteor/app/livechat/server/sendMessageBySMS.ts
index 2557fcdeb83d..c7f88646158b 100644
--- a/apps/meteor/app/livechat/server/sendMessageBySMS.ts
+++ b/apps/meteor/app/livechat/server/sendMessageBySMS.ts
@@ -1,5 +1,5 @@
import { OmnichannelIntegration } from '@rocket.chat/core-services';
-import { isEditedMessage, isOmnichannelRoom } from '@rocket.chat/core-typings';
+import { isEditedMessage } from '@rocket.chat/core-typings';
import { LivechatVisitors } from '@rocket.chat/models';
import { callbacks } from '../../../lib/callbacks';
@@ -8,8 +8,8 @@ import { normalizeMessageFileUpload } from '../../utils/server/functions/normali
import { callbackLogger } from './lib/logger';
callbacks.add(
- 'afterSaveMessage',
- async (message, room) => {
+ 'afterOmnichannelSaveMessage',
+ async (message, { room }) => {
// skips this callback if the message was edited
if (isEditedMessage(message)) {
return message;
@@ -20,7 +20,7 @@ callbacks.add(
}
// only send the sms by SMS if it is a livechat room with SMS set to true
- if (!(isOmnichannelRoom(room) && room.sms && room.v && room.v.token)) {
+ if (!(room.sms && room.v && room.v.token)) {
return message;
}
diff --git a/apps/meteor/app/mail-messages/server/methods/sendMail.ts b/apps/meteor/app/mail-messages/server/methods/sendMail.ts
index 158d271d5379..cc6469544df8 100644
--- a/apps/meteor/app/mail-messages/server/methods/sendMail.ts
+++ b/apps/meteor/app/mail-messages/server/methods/sendMail.ts
@@ -1,11 +1,11 @@
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger';
import { Mailer } from '../lib/Mailer';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'Mailer.sendMail'(from: string, subject: string, body: string, dryrun?: boolean, query?: string): any;
diff --git a/apps/meteor/app/mail-messages/server/methods/unsubscribe.ts b/apps/meteor/app/mail-messages/server/methods/unsubscribe.ts
index 24243cc98c2d..e52677b5ee1a 100644
--- a/apps/meteor/app/mail-messages/server/methods/unsubscribe.ts
+++ b/apps/meteor/app/mail-messages/server/methods/unsubscribe.ts
@@ -1,11 +1,11 @@
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { DDPRateLimiter } from 'meteor/ddp-rate-limiter';
import { Meteor } from 'meteor/meteor';
import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger';
import { Mailer } from '../lib/Mailer';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'Mailer:unsubscribe'(_id: string, createdAt: string): Promise;
diff --git a/apps/meteor/app/mentions/server/methods/getUserMentionsByChannel.ts b/apps/meteor/app/mentions/server/methods/getUserMentionsByChannel.ts
index 948187d089ae..6d9a16539704 100644
--- a/apps/meteor/app/mentions/server/methods/getUserMentionsByChannel.ts
+++ b/apps/meteor/app/mentions/server/methods/getUserMentionsByChannel.ts
@@ -1,12 +1,12 @@
import type { IMessage } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Messages, Users, Rooms } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import { canAccessRoomAsync } from '../../../authorization/server';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
getUserMentionsByChannel(params: { roomId: string; options: { limit: number; sort: { ts: -1 | 1 } } }): IMessage[];
diff --git a/apps/meteor/app/message-mark-as-unread/server/unreadMessages.ts b/apps/meteor/app/message-mark-as-unread/server/unreadMessages.ts
index 2ba0224a0c70..6ef1f5567a20 100644
--- a/apps/meteor/app/message-mark-as-unread/server/unreadMessages.ts
+++ b/apps/meteor/app/message-mark-as-unread/server/unreadMessages.ts
@@ -1,11 +1,11 @@
import type { IMessage, IRoom } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Messages, Subscriptions } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import logger from './logger';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
unreadMessages(firstUnreadMessage?: IMessage, room?: IRoom['_id']): void;
diff --git a/apps/meteor/app/message-pin/server/pinMessage.ts b/apps/meteor/app/message-pin/server/pinMessage.ts
index b0eab3f929d6..9f3dd44cc16d 100644
--- a/apps/meteor/app/message-pin/server/pinMessage.ts
+++ b/apps/meteor/app/message-pin/server/pinMessage.ts
@@ -2,17 +2,16 @@ import { Apps, AppEvents } from '@rocket.chat/apps';
import { Message } from '@rocket.chat/core-services';
import { isQuoteAttachment, isRegisterUser } from '@rocket.chat/core-typings';
import type { IMessage, MessageAttachment, MessageQuoteAttachment } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Messages, Rooms, Subscriptions, Users, ReadReceipts } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import { isTruthy } from '../../../lib/isTruthy';
-import { broadcastMessageFromData } from '../../../server/modules/watchers/lib/messages';
import { canAccessRoomAsync, roomAccessAttributes } from '../../authorization/server';
import { hasPermissionAsync } from '../../authorization/server/functions/hasPermission';
import { isTheLastMessage } from '../../lib/server/functions/isTheLastMessage';
-import { notifyOnRoomChangedById } from '../../lib/server/lib/notifyListener';
+import { notifyOnRoomChangedById, notifyOnMessageChange } from '../../lib/server/lib/notifyListener';
import { settings } from '../../settings/server';
import { getUserAvatarURL } from '../../utils/server/getUserAvatarURL';
@@ -36,7 +35,7 @@ const recursiveRemove = (msg: MessageAttachment, deep = 1) => {
const shouldAdd = (attachments: MessageAttachment[], attachment: MessageQuoteAttachment) =>
!attachments.some((_attachment) => isQuoteAttachment(_attachment) && _attachment.message_link === attachment.message_link);
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
pinMessage(message: IMessage, pinnedAt?: Date): IMessage | null;
@@ -135,7 +134,7 @@ Meteor.methods({
const pinMessageType = originalMessage.t === 'e2e' ? 'message_pinned_e2e' : 'message_pinned';
- const msgId = await Message.saveSystemMessage(pinMessageType, originalMessage.rid, '', me, {
+ return Message.saveSystemMessage(pinMessageType, originalMessage.rid, '', me, {
attachments: [
{
text: originalMessage.msg,
@@ -146,8 +145,6 @@ Meteor.methods({
},
],
});
-
- return Messages.findOneById(msgId);
},
async unpinMessage(message) {
check(message._id, String);
@@ -227,7 +224,7 @@ Meteor.methods({
if (settings.get('Message_Read_Receipt_Store_Users')) {
await ReadReceipts.setPinnedByMessageId(originalMessage._id, originalMessage.pinned);
}
- void broadcastMessageFromData({
+ void notifyOnMessageChange({
id: message._id,
});
diff --git a/apps/meteor/app/message-star/server/starMessage.ts b/apps/meteor/app/message-star/server/starMessage.ts
index 4529efb63f6f..36c67c1f4020 100644
--- a/apps/meteor/app/message-star/server/starMessage.ts
+++ b/apps/meteor/app/message-star/server/starMessage.ts
@@ -1,16 +1,15 @@
import { Apps, AppEvents } from '@rocket.chat/apps';
import type { IMessage } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Messages, Subscriptions, Rooms } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
-import { broadcastMessageFromData } from '../../../server/modules/watchers/lib/messages';
import { canAccessRoomAsync, roomAccessAttributes } from '../../authorization/server';
import { isTheLastMessage } from '../../lib/server/functions/isTheLastMessage';
-import { notifyOnRoomChangedById } from '../../lib/server/lib/notifyListener';
+import { notifyOnRoomChangedById, notifyOnMessageChange } from '../../lib/server/lib/notifyListener';
import { settings } from '../../settings/server';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
starMessage(message: Omit & { starred: boolean }): boolean;
@@ -63,7 +62,7 @@ Meteor.methods({
await Messages.updateUserStarById(message._id, uid, message.starred);
- void broadcastMessageFromData({
+ void notifyOnMessageChange({
id: message._id,
});
diff --git a/apps/meteor/app/meteor-accounts-saml/server/lib/settings.ts b/apps/meteor/app/meteor-accounts-saml/server/lib/settings.ts
index 5c16716720b0..bb9567260337 100644
--- a/apps/meteor/app/meteor-accounts-saml/server/lib/settings.ts
+++ b/apps/meteor/app/meteor-accounts-saml/server/lib/settings.ts
@@ -230,12 +230,10 @@ export const addSettings = async function (name: string): Promise {
await this.add(`SAML_Custom_${name}_button_label_color`, '#FFFFFF', {
type: 'string',
i18nLabel: 'Accounts_OAuth_Custom_Button_Label_Color',
- alert: 'OAuth_button_colors_alert',
});
await this.add(`SAML_Custom_${name}_button_color`, '#1d74f5', {
type: 'string',
i18nLabel: 'Accounts_OAuth_Custom_Button_Color',
- alert: 'OAuth_button_colors_alert',
});
});
diff --git a/apps/meteor/app/meteor-accounts-saml/server/methods/addSamlService.ts b/apps/meteor/app/meteor-accounts-saml/server/methods/addSamlService.ts
index f952ce3b3fe3..0b6b5a6c8f6e 100644
--- a/apps/meteor/app/meteor-accounts-saml/server/methods/addSamlService.ts
+++ b/apps/meteor/app/meteor-accounts-saml/server/methods/addSamlService.ts
@@ -1,9 +1,9 @@
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
import { addSamlService } from '../lib/settings';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
addSamlService(name: string): void;
diff --git a/apps/meteor/app/meteor-accounts-saml/server/methods/samlLogout.ts b/apps/meteor/app/meteor-accounts-saml/server/methods/samlLogout.ts
index 956426082d40..a7f9e87a93de 100644
--- a/apps/meteor/app/meteor-accounts-saml/server/methods/samlLogout.ts
+++ b/apps/meteor/app/meteor-accounts-saml/server/methods/samlLogout.ts
@@ -1,5 +1,5 @@
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Users } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import type { IServiceProviderOptions } from '../definition/IServiceProviderOptions';
@@ -25,7 +25,7 @@ function getSamlServiceProviderOptions(provider: string): IServiceProviderOption
return providers.filter(samlProvider)[0];
}
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
samlLogout(provider: string): string | undefined;
diff --git a/apps/meteor/app/models/client/models/Users.ts b/apps/meteor/app/models/client/models/Users.ts
index 089486f3a20c..26d333cc8bb1 100644
--- a/apps/meteor/app/models/client/models/Users.ts
+++ b/apps/meteor/app/models/client/models/Users.ts
@@ -30,5 +30,13 @@ class UsersCollection extends Mongo.Collection {
}
}
+Object.assign(Meteor.users, {
+ _connection: undefined,
+ findOneById: UsersCollection.prototype.findOneById,
+ isUserInRole: UsersCollection.prototype.isUserInRole,
+ findUsersInRoles: UsersCollection.prototype.findUsersInRoles,
+ remove: UsersCollection.prototype.remove,
+});
+
/** @deprecated */
-export const Users = new UsersCollection();
+export const Users = Meteor.users as UsersCollection;
diff --git a/apps/meteor/app/notifications/server/lib/Notifications.ts b/apps/meteor/app/notifications/server/lib/Notifications.ts
index ed4985777414..3ddb611d76bd 100644
--- a/apps/meteor/app/notifications/server/lib/Notifications.ts
+++ b/apps/meteor/app/notifications/server/lib/Notifications.ts
@@ -1,5 +1,5 @@
import { api } from '@rocket.chat/core-services';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { DDPCommon } from 'meteor/ddp-common';
import { Meteor } from 'meteor/meteor';
diff --git a/apps/meteor/app/notifications/server/lib/Presence.ts b/apps/meteor/app/notifications/server/lib/Presence.ts
index 9955b687701f..17f35a9d39ff 100644
--- a/apps/meteor/app/notifications/server/lib/Presence.ts
+++ b/apps/meteor/app/notifications/server/lib/Presence.ts
@@ -1,6 +1,6 @@
import type { IUser } from '@rocket.chat/core-typings';
+import type { StreamerEvents } from '@rocket.chat/ddp-client';
import { Emitter } from '@rocket.chat/emitter';
-import type { StreamerEvents } from '@rocket.chat/ui-contexts';
import type { IPublication, IStreamerConstructor, Connection, IStreamer } from 'meteor/rocketchat:streamer';
type UserPresenceStreamProps = {
diff --git a/apps/meteor/app/oauth2-server-config/server/admin/methods/addOAuthApp.ts b/apps/meteor/app/oauth2-server-config/server/admin/methods/addOAuthApp.ts
index 4556a5be7d9f..3f41b1b01bea 100644
--- a/apps/meteor/app/oauth2-server-config/server/admin/methods/addOAuthApp.ts
+++ b/apps/meteor/app/oauth2-server-config/server/admin/methods/addOAuthApp.ts
@@ -1,12 +1,12 @@
import type { IOAuthApps } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import type { OauthAppsAddParams } from '@rocket.chat/rest-typings';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { methodDeprecationLogger } from '../../../../lib/server/lib/deprecationWarningLogger';
import { addOAuthApp } from '../functions/addOAuthApp';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
addOAuthApp(application: OauthAppsAddParams): IOAuthApps;
diff --git a/apps/meteor/app/oauth2-server-config/server/admin/methods/deleteOAuthApp.ts b/apps/meteor/app/oauth2-server-config/server/admin/methods/deleteOAuthApp.ts
index 0209f9d453b5..9c5cbf6fd9ae 100644
--- a/apps/meteor/app/oauth2-server-config/server/admin/methods/deleteOAuthApp.ts
+++ b/apps/meteor/app/oauth2-server-config/server/admin/methods/deleteOAuthApp.ts
@@ -1,11 +1,11 @@
import type { IOAuthApps } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { OAuthAccessTokens, OAuthApps, OAuthAuthCodes } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../../authorization/server/functions/hasPermission';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
deleteOAuthApp(applicationId: IOAuthApps['_id']): boolean;
diff --git a/apps/meteor/app/oauth2-server-config/server/admin/methods/updateOAuthApp.ts b/apps/meteor/app/oauth2-server-config/server/admin/methods/updateOAuthApp.ts
index 525d0fa2d124..f2daca1885c9 100644
--- a/apps/meteor/app/oauth2-server-config/server/admin/methods/updateOAuthApp.ts
+++ b/apps/meteor/app/oauth2-server-config/server/admin/methods/updateOAuthApp.ts
@@ -1,12 +1,12 @@
import type { IOAuthApps } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { OAuthApps, Users } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../../authorization/server/functions/hasPermission';
import { parseUriList } from '../functions/parseUriList';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
updateOAuthApp(
diff --git a/apps/meteor/app/otr/server/methods/deleteOldOTRMessages.ts b/apps/meteor/app/otr/server/methods/deleteOldOTRMessages.ts
index a994b19dd1a4..1b57c65b4bb7 100644
--- a/apps/meteor/app/otr/server/methods/deleteOldOTRMessages.ts
+++ b/apps/meteor/app/otr/server/methods/deleteOldOTRMessages.ts
@@ -1,9 +1,9 @@
import type { IRoom } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Messages, Subscriptions, ReadReceipts } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
deleteOldOTRMessages(roomId: IRoom['_id']): Promise;
diff --git a/apps/meteor/app/otr/server/methods/sendSystemMessages.ts b/apps/meteor/app/otr/server/methods/sendSystemMessages.ts
index a2abf0938b9e..13abbd7511af 100644
--- a/apps/meteor/app/otr/server/methods/sendSystemMessages.ts
+++ b/apps/meteor/app/otr/server/methods/sendSystemMessages.ts
@@ -1,7 +1,7 @@
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
sendSystemMessages(rid: string, user: string | undefined, id: string): void;
diff --git a/apps/meteor/app/otr/server/methods/updateOTRAck.ts b/apps/meteor/app/otr/server/methods/updateOTRAck.ts
index a5a502ddf1a2..4fbd182e9d27 100644
--- a/apps/meteor/app/otr/server/methods/updateOTRAck.ts
+++ b/apps/meteor/app/otr/server/methods/updateOTRAck.ts
@@ -1,9 +1,9 @@
import { api } from '@rocket.chat/core-services';
import type { IOTRMessage } from '@rocket.chat/core-typings';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
updateOTRAck({ message, ack }: { message: IOTRMessage; ack: string }): void;
diff --git a/apps/meteor/app/push-notifications/server/methods/saveNotificationSettings.ts b/apps/meteor/app/push-notifications/server/methods/saveNotificationSettings.ts
index a4376c709275..a86ded6f24e5 100644
--- a/apps/meteor/app/push-notifications/server/methods/saveNotificationSettings.ts
+++ b/apps/meteor/app/push-notifications/server/methods/saveNotificationSettings.ts
@@ -1,6 +1,6 @@
import type { ISubscription } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Subscriptions } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
@@ -9,7 +9,7 @@ import { getUserNotificationPreference } from '../../../utils/server/getUserNoti
const saveAudioNotificationValue = (subId: ISubscription['_id'], value: string) =>
value === 'default' ? Subscriptions.clearAudioNotificationValueById(subId) : Subscriptions.updateAudioNotificationValueById(subId, value);
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
saveNotificationSettings(
diff --git a/apps/meteor/app/push/server/methods.ts b/apps/meteor/app/push/server/methods.ts
index 364a16cbdb5e..1f1e261eccae 100644
--- a/apps/meteor/app/push/server/methods.ts
+++ b/apps/meteor/app/push/server/methods.ts
@@ -1,7 +1,7 @@
import type { IAppsTokens } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { AppsTokens } from '@rocket.chat/models';
import { Random } from '@rocket.chat/random';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Accounts } from 'meteor/accounts-base';
import { Match, check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
@@ -9,7 +9,7 @@ import { Meteor } from 'meteor/meteor';
import { logger } from './logger';
import { _matchToken } from './push';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'raix:push-update'(options: {
diff --git a/apps/meteor/app/reactions/client/methods/setReaction.ts b/apps/meteor/app/reactions/client/methods/setReaction.ts
index a38e6c156790..ed15cda9ab8e 100644
--- a/apps/meteor/app/reactions/client/methods/setReaction.ts
+++ b/apps/meteor/app/reactions/client/methods/setReaction.ts
@@ -1,5 +1,5 @@
import type { IMessage, IRoom } from '@rocket.chat/core-typings';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
import { roomCoordinator } from '../../../../client/lib/rooms/roomCoordinator';
diff --git a/apps/meteor/app/reactions/server/setReaction.ts b/apps/meteor/app/reactions/server/setReaction.ts
index 896e5041bd61..e35103e9d333 100644
--- a/apps/meteor/app/reactions/server/setReaction.ts
+++ b/apps/meteor/app/reactions/server/setReaction.ts
@@ -1,19 +1,18 @@
import { Apps, AppEvents } from '@rocket.chat/apps';
import { api } from '@rocket.chat/core-services';
import type { IMessage, IRoom, IUser } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Messages, EmojiCustom, Rooms, Users } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import _ from 'underscore';
import { callbacks } from '../../../lib/callbacks';
import { i18n } from '../../../server/lib/i18n';
-import { broadcastMessageFromData } from '../../../server/modules/watchers/lib/messages';
import { canAccessRoomAsync } from '../../authorization/server';
import { hasPermissionAsync } from '../../authorization/server/functions/hasPermission';
import { emoji } from '../../emoji/server';
import { isTheLastMessage } from '../../lib/server/functions/isTheLastMessage';
-import { notifyOnRoomChangedById } from '../../lib/server/lib/notifyListener';
+import { notifyOnRoomChangedById, notifyOnMessageChange } from '../../lib/server/lib/notifyListener';
const removeUserReaction = (message: IMessage, reaction: string, username: string) => {
if (!message.reactions) {
@@ -111,7 +110,7 @@ async function setReaction(room: IRoom, user: IUser, message: IMessage, reaction
await Apps.self?.triggerEvent(AppEvents.IPostMessageReacted, message, user, reaction, isReacted);
- void broadcastMessageFromData({
+ void notifyOnMessageChange({
id: message._id,
});
}
@@ -140,7 +139,7 @@ export async function executeSetReaction(userId: string, reaction: string, messa
return setReaction(room, user, message, reaction, shouldReact);
}
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
setReaction(reaction: string, messageId: IMessage['_id'], shouldReact?: boolean): boolean | undefined;
diff --git a/apps/meteor/app/retention-policy/server/cronPruneMessages.ts b/apps/meteor/app/retention-policy/server/cronPruneMessages.ts
index 337691bfbe57..640aa517a679 100644
--- a/apps/meteor/app/retention-policy/server/cronPruneMessages.ts
+++ b/apps/meteor/app/retention-policy/server/cronPruneMessages.ts
@@ -6,13 +6,20 @@ import { getCronAdvancedTimerFromPrecisionSetting } from '../../../lib/getCronAd
import { cleanRoomHistory } from '../../lib/server/functions/cleanRoomHistory';
import { settings } from '../../settings/server';
-const maxTimes = {
- c: 0,
- p: 0,
- d: 0,
+type RetentionRoomTypes = 'c' | 'p' | 'd';
+
+const getMaxAgeSettingIdByRoomType = (type: RetentionRoomTypes) => {
+ switch (type) {
+ case 'c':
+ return settings.get('RetentionPolicy_TTL_Channels');
+ case 'p':
+ return settings.get('RetentionPolicy_TTL_Groups');
+ case 'd':
+ return settings.get('RetentionPolicy_TTL_DMs');
+ }
};
-let types: (keyof typeof maxTimes)[] = [];
+let types: RetentionRoomTypes[] = [];
const oldest = new Date('0001-01-01T00:00:00Z');
@@ -29,7 +36,7 @@ async function job(): Promise {
// get all rooms with default values
for await (const type of types) {
- const maxAge = maxTimes[type] || 0;
+ const maxAge = getMaxAgeSettingIdByRoomType(type) || 0;
const latest = new Date(now.getTime() - maxAge);
const rooms = await Rooms.find(
@@ -95,9 +102,6 @@ settings.watchMultiple(
'RetentionPolicy_AppliesToChannels',
'RetentionPolicy_AppliesToGroups',
'RetentionPolicy_AppliesToDMs',
- 'RetentionPolicy_TTL_Channels',
- 'RetentionPolicy_TTL_Groups',
- 'RetentionPolicy_TTL_DMs',
'RetentionPolicy_Advanced_Precision',
'RetentionPolicy_Advanced_Precision_Cron',
'RetentionPolicy_Precision',
@@ -120,10 +124,6 @@ settings.watchMultiple(
types.push('d');
}
- maxTimes.c = settings.get('RetentionPolicy_TTL_Channels');
- maxTimes.p = settings.get('RetentionPolicy_TTL_Groups');
- maxTimes.d = settings.get('RetentionPolicy_TTL_DMs');
-
const precision =
(settings.get('RetentionPolicy_Advanced_Precision') && settings.get('RetentionPolicy_Advanced_Precision_Cron')) ||
getCronAdvancedTimerFromPrecisionSetting(settings.get('RetentionPolicy_Precision'));
diff --git a/apps/meteor/app/search/server/methods.ts b/apps/meteor/app/search/server/methods.ts
index 686b5b429e96..cdb3b4180f7a 100644
--- a/apps/meteor/app/search/server/methods.ts
+++ b/apps/meteor/app/search/server/methods.ts
@@ -1,12 +1,12 @@
import type { IMessageSearchProvider, IMessageSearchSuggestion, IRoom, IUser } from '@rocket.chat/core-typings';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
import { SearchLogger } from './logger/logger';
import type { IRawSearchResult, ISearchResult } from './model/ISearchResult';
import { searchProviderService, validationService } from './service';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'rocketchatSearch.getProvider'(): IMessageSearchProvider | undefined;
diff --git a/apps/meteor/app/settings/server/SettingsRegistry.ts b/apps/meteor/app/settings/server/SettingsRegistry.ts
index e86a391ad8fa..d7d2fa0a79f8 100644
--- a/apps/meteor/app/settings/server/SettingsRegistry.ts
+++ b/apps/meteor/app/settings/server/SettingsRegistry.ts
@@ -139,6 +139,7 @@ export class SettingsRegistry {
const settingFromCodeOverwritten = overwriteSetting(settingFromCode);
const settingStored = this.store.getSetting(_id);
+
const settingStoredOverwritten = settingStored && overwriteSetting(settingStored);
try {
@@ -166,7 +167,10 @@ export class SettingsRegistry {
})();
await this.saveUpdatedSetting(_id, updatedProps, removedKeys);
- this.store.set(settingFromCodeOverwritten);
+ if ('value' in updatedProps) {
+ this.store.set(updatedProps as ISetting);
+ }
+
return;
}
diff --git a/apps/meteor/app/slackbridge/client/slackbridge_import.client.js b/apps/meteor/app/slackbridge/client/slackbridge_import.client.js
index 6aeffb7bef45..eebc07ddb72d 100644
--- a/apps/meteor/app/slackbridge/client/slackbridge_import.client.js
+++ b/apps/meteor/app/slackbridge/client/slackbridge_import.client.js
@@ -1,5 +1,5 @@
import { settings } from '../../settings/client';
-import { slashCommands } from '../../utils/lib/slashCommand';
+import { slashCommands } from '../../utils/client/slashCommand';
settings.onload('SlackBridge_Enabled', (key, value) => {
if (value) {
diff --git a/apps/meteor/app/slackbridge/server/removeChannelLinks.ts b/apps/meteor/app/slackbridge/server/removeChannelLinks.ts
index 1a4e6f6a0096..2c89e71f9635 100644
--- a/apps/meteor/app/slackbridge/server/removeChannelLinks.ts
+++ b/apps/meteor/app/slackbridge/server/removeChannelLinks.ts
@@ -1,11 +1,11 @@
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Rooms } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../authorization/server/functions/hasPermission';
import { settings } from '../../settings/server';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
removeSlackBridgeChannelLinks(): { message: string; params: unknown[] };
diff --git a/apps/meteor/app/slashcommand-asciiarts/client/gimme.ts b/apps/meteor/app/slashcommand-asciiarts/client/gimme.ts
index 4c9d6a4e40c8..7cd5edb6bb87 100644
--- a/apps/meteor/app/slashcommand-asciiarts/client/gimme.ts
+++ b/apps/meteor/app/slashcommand-asciiarts/client/gimme.ts
@@ -1,7 +1,7 @@
import type { SlashCommandCallbackParams } from '@rocket.chat/core-typings';
import { sdk } from '../../utils/client/lib/SDKClient';
-import { slashCommands } from '../../utils/lib/slashCommand';
+import { slashCommands } from '../../utils/client/slashCommand';
/*
* Gimme is a named function that will replace /gimme commands
* @param {Object} message - The message object
diff --git a/apps/meteor/app/slashcommand-asciiarts/client/lenny.ts b/apps/meteor/app/slashcommand-asciiarts/client/lenny.ts
index 99eaa03b9e59..0e3cc55f6b86 100644
--- a/apps/meteor/app/slashcommand-asciiarts/client/lenny.ts
+++ b/apps/meteor/app/slashcommand-asciiarts/client/lenny.ts
@@ -1,7 +1,7 @@
import type { SlashCommandCallbackParams } from '@rocket.chat/core-typings';
import { sdk } from '../../utils/client/lib/SDKClient';
-import { slashCommands } from '../../utils/lib/slashCommand';
+import { slashCommands } from '../../utils/client/slashCommand';
/*
* Lenny is a named function that will replace /lenny commands
* @param {Object} message - The message object
diff --git a/apps/meteor/app/slashcommand-asciiarts/client/shrug.ts b/apps/meteor/app/slashcommand-asciiarts/client/shrug.ts
index bc0fb300789e..c4bdec8f1a8c 100644
--- a/apps/meteor/app/slashcommand-asciiarts/client/shrug.ts
+++ b/apps/meteor/app/slashcommand-asciiarts/client/shrug.ts
@@ -1,7 +1,7 @@
import type { SlashCommandCallbackParams } from '@rocket.chat/core-typings';
import { sdk } from '../../utils/client/lib/SDKClient';
-import { slashCommands } from '../../utils/lib/slashCommand';
+import { slashCommands } from '../../utils/client/slashCommand';
/*
* Shrug is a named function that will replace /shrug commands
* @param {Object} message - The message object
diff --git a/apps/meteor/app/slashcommand-asciiarts/client/tableflip.ts b/apps/meteor/app/slashcommand-asciiarts/client/tableflip.ts
index 0d709760fe84..8820b81f7c4a 100644
--- a/apps/meteor/app/slashcommand-asciiarts/client/tableflip.ts
+++ b/apps/meteor/app/slashcommand-asciiarts/client/tableflip.ts
@@ -1,7 +1,7 @@
import type { SlashCommandCallbackParams } from '@rocket.chat/core-typings';
import { sdk } from '../../utils/client/lib/SDKClient';
-import { slashCommands } from '../../utils/lib/slashCommand';
+import { slashCommands } from '../../utils/client/slashCommand';
/*
* Tableflip is a named function that will replace /Tableflip commands
* @param {Object} message - The message object
diff --git a/apps/meteor/app/slashcommand-asciiarts/client/unflip.ts b/apps/meteor/app/slashcommand-asciiarts/client/unflip.ts
index a7dc0d257e78..6c02fa196052 100644
--- a/apps/meteor/app/slashcommand-asciiarts/client/unflip.ts
+++ b/apps/meteor/app/slashcommand-asciiarts/client/unflip.ts
@@ -1,7 +1,7 @@
import type { SlashCommandCallbackParams } from '@rocket.chat/core-typings';
import { sdk } from '../../utils/client/lib/SDKClient';
-import { slashCommands } from '../../utils/lib/slashCommand';
+import { slashCommands } from '../../utils/client/slashCommand';
/*
* Unflip is a named function that will replace /unflip commands
* @param {Object} message - The message object
diff --git a/apps/meteor/app/slashcommand-asciiarts/server/gimme.ts b/apps/meteor/app/slashcommand-asciiarts/server/gimme.ts
index f426d6cf85c0..f902d75f33d1 100644
--- a/apps/meteor/app/slashcommand-asciiarts/server/gimme.ts
+++ b/apps/meteor/app/slashcommand-asciiarts/server/gimme.ts
@@ -1,7 +1,7 @@
import type { SlashCommandCallbackParams } from '@rocket.chat/core-typings';
import { executeSendMessage } from '../../lib/server/methods/sendMessage';
-import { slashCommands } from '../../utils/lib/slashCommand';
+import { slashCommands } from '../../utils/server/slashCommand';
/*
* Gimme is a named function that will replace /gimme commands
* @param {Object} message - The message object
diff --git a/apps/meteor/app/slashcommand-asciiarts/server/lenny.ts b/apps/meteor/app/slashcommand-asciiarts/server/lenny.ts
index 878a10e356d4..e760b5a1169e 100644
--- a/apps/meteor/app/slashcommand-asciiarts/server/lenny.ts
+++ b/apps/meteor/app/slashcommand-asciiarts/server/lenny.ts
@@ -1,7 +1,7 @@
import type { SlashCommandCallbackParams } from '@rocket.chat/core-typings';
import { executeSendMessage } from '../../lib/server/methods/sendMessage';
-import { slashCommands } from '../../utils/lib/slashCommand';
+import { slashCommands } from '../../utils/server/slashCommand';
/*
* Lenny is a named function that will replace /lenny commands
* @param {Object} message - The message object
diff --git a/apps/meteor/app/slashcommand-asciiarts/server/shrug.ts b/apps/meteor/app/slashcommand-asciiarts/server/shrug.ts
index 1240027bb38f..c2e5d166bfd8 100644
--- a/apps/meteor/app/slashcommand-asciiarts/server/shrug.ts
+++ b/apps/meteor/app/slashcommand-asciiarts/server/shrug.ts
@@ -1,7 +1,7 @@
import type { SlashCommandCallbackParams } from '@rocket.chat/core-typings';
import { executeSendMessage } from '../../lib/server/methods/sendMessage';
-import { slashCommands } from '../../utils/lib/slashCommand';
+import { slashCommands } from '../../utils/server/slashCommand';
/*
* Shrug is a named function that will replace /shrug commands
* @param {Object} message - The message object
diff --git a/apps/meteor/app/slashcommand-asciiarts/server/tableflip.ts b/apps/meteor/app/slashcommand-asciiarts/server/tableflip.ts
index 34acef9805e2..ac3f599dff1d 100644
--- a/apps/meteor/app/slashcommand-asciiarts/server/tableflip.ts
+++ b/apps/meteor/app/slashcommand-asciiarts/server/tableflip.ts
@@ -1,7 +1,7 @@
import type { SlashCommandCallbackParams } from '@rocket.chat/core-typings';
import { executeSendMessage } from '../../lib/server/methods/sendMessage';
-import { slashCommands } from '../../utils/lib/slashCommand';
+import { slashCommands } from '../../utils/server/slashCommand';
/*
* Tableflip is a named function that will replace /Tableflip commands
* @param {Object} message - The message object
diff --git a/apps/meteor/app/slashcommand-asciiarts/server/unflip.ts b/apps/meteor/app/slashcommand-asciiarts/server/unflip.ts
index 689e7262eac0..b905ed567447 100644
--- a/apps/meteor/app/slashcommand-asciiarts/server/unflip.ts
+++ b/apps/meteor/app/slashcommand-asciiarts/server/unflip.ts
@@ -1,7 +1,7 @@
import type { SlashCommandCallbackParams } from '@rocket.chat/core-typings';
import { executeSendMessage } from '../../lib/server/methods/sendMessage';
-import { slashCommands } from '../../utils/lib/slashCommand';
+import { slashCommands } from '../../utils/server/slashCommand';
/*
* Unflip is a named function that will replace /unflip commands
* @param {Object} message - The message object
diff --git a/apps/meteor/app/slashcommands-archiveroom/client/client.ts b/apps/meteor/app/slashcommands-archiveroom/client/client.ts
index c24763106684..f5154fb32a5b 100644
--- a/apps/meteor/app/slashcommands-archiveroom/client/client.ts
+++ b/apps/meteor/app/slashcommands-archiveroom/client/client.ts
@@ -1,4 +1,4 @@
-import { slashCommands } from '../../utils/lib/slashCommand';
+import { slashCommands } from '../../utils/client/slashCommand';
slashCommands.add({
command: 'archive',
diff --git a/apps/meteor/app/slashcommands-archiveroom/server/server.ts b/apps/meteor/app/slashcommands-archiveroom/server/server.ts
index 99bcec2cd7b3..f1b33c1022bb 100644
--- a/apps/meteor/app/slashcommands-archiveroom/server/server.ts
+++ b/apps/meteor/app/slashcommands-archiveroom/server/server.ts
@@ -10,7 +10,7 @@ import { roomCoordinator } from '../../../server/lib/rooms/roomCoordinator';
import { hasPermissionAsync } from '../../authorization/server/functions/hasPermission';
import { archiveRoom } from '../../lib/server/functions/archiveRoom';
import { settings } from '../../settings/server';
-import { slashCommands } from '../../utils/lib/slashCommand';
+import { slashCommands } from '../../utils/server/slashCommand';
slashCommands.add({
command: 'archive',
diff --git a/apps/meteor/app/slashcommands-create/client/client.ts b/apps/meteor/app/slashcommands-create/client/client.ts
index 299db606db9c..7e8ba831dbd8 100644
--- a/apps/meteor/app/slashcommands-create/client/client.ts
+++ b/apps/meteor/app/slashcommands-create/client/client.ts
@@ -1,4 +1,4 @@
-import { slashCommands } from '../../utils/lib/slashCommand';
+import { slashCommands } from '../../utils/client/slashCommand';
slashCommands.add({
command: 'create',
diff --git a/apps/meteor/app/slashcommands-create/server/server.ts b/apps/meteor/app/slashcommands-create/server/server.ts
index 104d50c56926..6abee71c56fd 100644
--- a/apps/meteor/app/slashcommands-create/server/server.ts
+++ b/apps/meteor/app/slashcommands-create/server/server.ts
@@ -6,7 +6,7 @@ import { i18n } from '../../../server/lib/i18n';
import { createChannelMethod } from '../../lib/server/methods/createChannel';
import { createPrivateGroupMethod } from '../../lib/server/methods/createPrivateGroup';
import { settings } from '../../settings/server';
-import { slashCommands } from '../../utils/lib/slashCommand';
+import { slashCommands } from '../../utils/server/slashCommand';
slashCommands.add({
command: 'create',
diff --git a/apps/meteor/app/slashcommands-help/server/server.ts b/apps/meteor/app/slashcommands-help/server/server.ts
index c24bfb22c6fe..80efaffeb852 100644
--- a/apps/meteor/app/slashcommands-help/server/server.ts
+++ b/apps/meteor/app/slashcommands-help/server/server.ts
@@ -4,7 +4,7 @@ import { Users } from '@rocket.chat/models';
import { i18n } from '../../../server/lib/i18n';
import { settings } from '../../settings/server';
-import { slashCommands } from '../../utils/lib/slashCommand';
+import { slashCommands } from '../../utils/server/slashCommand';
/*
* Help is a named function that will replace /help commands
diff --git a/apps/meteor/app/slashcommands-hide/client/hide.ts b/apps/meteor/app/slashcommands-hide/client/hide.ts
index 99c1eaea7049..c6486053ecc2 100644
--- a/apps/meteor/app/slashcommands-hide/client/hide.ts
+++ b/apps/meteor/app/slashcommands-hide/client/hide.ts
@@ -1,4 +1,4 @@
-import { slashCommands } from '../../utils/lib/slashCommand';
+import { slashCommands } from '../../utils/client/slashCommand';
slashCommands.add({
command: 'hide',
diff --git a/apps/meteor/app/slashcommands-invite/client/client.ts b/apps/meteor/app/slashcommands-invite/client/client.ts
index 729073b785d8..7c8af755d64d 100644
--- a/apps/meteor/app/slashcommands-invite/client/client.ts
+++ b/apps/meteor/app/slashcommands-invite/client/client.ts
@@ -1,4 +1,4 @@
-import { slashCommands } from '../../utils/lib/slashCommand';
+import { slashCommands } from '../../utils/client/slashCommand';
slashCommands.add({
command: 'invite',
diff --git a/apps/meteor/app/slashcommands-invite/server/server.ts b/apps/meteor/app/slashcommands-invite/server/server.ts
index de525d8c6fc6..06a85301540c 100644
--- a/apps/meteor/app/slashcommands-invite/server/server.ts
+++ b/apps/meteor/app/slashcommands-invite/server/server.ts
@@ -6,7 +6,7 @@ import { Meteor } from 'meteor/meteor';
import { i18n } from '../../../server/lib/i18n';
import { addUsersToRoomMethod } from '../../lib/server/methods/addUsersToRoom';
import { settings } from '../../settings/server';
-import { slashCommands } from '../../utils/lib/slashCommand';
+import { slashCommands } from '../../utils/server/slashCommand';
/*
* Invite is a named function that will replace /invite commands
diff --git a/apps/meteor/app/slashcommands-inviteall/client/client.ts b/apps/meteor/app/slashcommands-inviteall/client/client.ts
index f8ab40953d27..5083cd4a83ab 100644
--- a/apps/meteor/app/slashcommands-inviteall/client/client.ts
+++ b/apps/meteor/app/slashcommands-inviteall/client/client.ts
@@ -1,4 +1,4 @@
-import { slashCommands } from '../../utils/lib/slashCommand';
+import { slashCommands } from '../../utils/client/slashCommand';
slashCommands.add({
command: 'invite-all-to',
diff --git a/apps/meteor/app/slashcommands-inviteall/server/server.ts b/apps/meteor/app/slashcommands-inviteall/server/server.ts
index bac4349ec72c..e74bb89899c2 100644
--- a/apps/meteor/app/slashcommands-inviteall/server/server.ts
+++ b/apps/meteor/app/slashcommands-inviteall/server/server.ts
@@ -15,7 +15,7 @@ import { addUsersToRoomMethod } from '../../lib/server/methods/addUsersToRoom';
import { createChannelMethod } from '../../lib/server/methods/createChannel';
import { createPrivateGroupMethod } from '../../lib/server/methods/createPrivateGroup';
import { settings } from '../../settings/server';
-import { slashCommands } from '../../utils/lib/slashCommand';
+import { slashCommands } from '../../utils/server/slashCommand';
function inviteAll(type: T): SlashCommand['callback'] {
return async function inviteAll({ command, params, message, userId }: SlashCommandCallbackParams): Promise {
diff --git a/apps/meteor/app/slashcommands-join/client/client.ts b/apps/meteor/app/slashcommands-join/client/client.ts
index 417fe1e5cd47..bc8d589f51ac 100644
--- a/apps/meteor/app/slashcommands-join/client/client.ts
+++ b/apps/meteor/app/slashcommands-join/client/client.ts
@@ -1,6 +1,6 @@
import type { Meteor } from 'meteor/meteor';
-import { slashCommands } from '../../utils/lib/slashCommand';
+import { slashCommands } from '../../utils/client/slashCommand';
slashCommands.add({
command: 'join',
diff --git a/apps/meteor/app/slashcommands-join/server/server.ts b/apps/meteor/app/slashcommands-join/server/server.ts
index 33d0278f81a3..6497324ae9e0 100644
--- a/apps/meteor/app/slashcommands-join/server/server.ts
+++ b/apps/meteor/app/slashcommands-join/server/server.ts
@@ -5,7 +5,7 @@ import { Meteor } from 'meteor/meteor';
import { i18n } from '../../../server/lib/i18n';
import { settings } from '../../settings/server';
-import { slashCommands } from '../../utils/lib/slashCommand';
+import { slashCommands } from '../../utils/server/slashCommand';
slashCommands.add({
command: 'join',
diff --git a/apps/meteor/app/slashcommands-kick/client/client.ts b/apps/meteor/app/slashcommands-kick/client/client.ts
index 475346216f1e..7fc167e17c88 100644
--- a/apps/meteor/app/slashcommands-kick/client/client.ts
+++ b/apps/meteor/app/slashcommands-kick/client/client.ts
@@ -1,6 +1,6 @@
import type { SlashCommandCallbackParams } from '@rocket.chat/core-typings';
-import { slashCommands } from '../../utils/lib/slashCommand';
+import { slashCommands } from '../../utils/client/slashCommand';
slashCommands.add({
command: 'kick',
diff --git a/apps/meteor/app/slashcommands-kick/server/server.ts b/apps/meteor/app/slashcommands-kick/server/server.ts
index 5ca6b45ec835..fdde07b897bf 100644
--- a/apps/meteor/app/slashcommands-kick/server/server.ts
+++ b/apps/meteor/app/slashcommands-kick/server/server.ts
@@ -6,7 +6,7 @@ import { Users } from '@rocket.chat/models';
import { i18n } from '../../../server/lib/i18n';
import { removeUserFromRoomMethod } from '../../../server/methods/removeUserFromRoom';
import { settings } from '../../settings/server';
-import { slashCommands } from '../../utils/lib/slashCommand';
+import { slashCommands } from '../../utils/server/slashCommand';
slashCommands.add({
command: 'kick',
diff --git a/apps/meteor/app/slashcommands-leave/server/leave.ts b/apps/meteor/app/slashcommands-leave/server/leave.ts
index 42dad0807246..fa108fe18c72 100644
--- a/apps/meteor/app/slashcommands-leave/server/leave.ts
+++ b/apps/meteor/app/slashcommands-leave/server/leave.ts
@@ -5,7 +5,7 @@ import { Users } from '@rocket.chat/models';
import { i18n } from '../../../server/lib/i18n';
import { leaveRoomMethod } from '../../lib/server/methods/leaveRoom';
import { settings } from '../../settings/server';
-import { slashCommands } from '../../utils/lib/slashCommand';
+import { slashCommands } from '../../utils/server/slashCommand';
/*
* Leave is a named function that will replace /leave commands
diff --git a/apps/meteor/app/slashcommands-me/server/me.ts b/apps/meteor/app/slashcommands-me/server/me.ts
index ba6a9f8c82cc..b8b4a593cb73 100644
--- a/apps/meteor/app/slashcommands-me/server/me.ts
+++ b/apps/meteor/app/slashcommands-me/server/me.ts
@@ -1,7 +1,7 @@
import type { SlashCommandCallbackParams } from '@rocket.chat/core-typings';
import { executeSendMessage } from '../../lib/server/methods/sendMessage';
-import { slashCommands } from '../../utils/lib/slashCommand';
+import { slashCommands } from '../../utils/server/slashCommand';
/*
* Me is a named function that will replace /me commands
diff --git a/apps/meteor/app/slashcommands-msg/server/server.ts b/apps/meteor/app/slashcommands-msg/server/server.ts
index c6a244b80207..e757938106eb 100644
--- a/apps/meteor/app/slashcommands-msg/server/server.ts
+++ b/apps/meteor/app/slashcommands-msg/server/server.ts
@@ -7,7 +7,7 @@ import { i18n } from '../../../server/lib/i18n';
import { createDirectMessage } from '../../../server/methods/createDirectMessage';
import { executeSendMessage } from '../../lib/server/methods/sendMessage';
import { settings } from '../../settings/server';
-import { slashCommands } from '../../utils/lib/slashCommand';
+import { slashCommands } from '../../utils/server/slashCommand';
/*
* Msg is a named function that will replace /msg commands
diff --git a/apps/meteor/app/slashcommands-mute/server/mute.ts b/apps/meteor/app/slashcommands-mute/server/mute.ts
index 03ce960496da..da20ff4fed47 100644
--- a/apps/meteor/app/slashcommands-mute/server/mute.ts
+++ b/apps/meteor/app/slashcommands-mute/server/mute.ts
@@ -5,7 +5,7 @@ import { Users } from '@rocket.chat/models';
import { i18n } from '../../../server/lib/i18n';
import { muteUserInRoom } from '../../../server/methods/muteUserInRoom';
import { settings } from '../../settings/server';
-import { slashCommands } from '../../utils/lib/slashCommand';
+import { slashCommands } from '../../utils/server/slashCommand';
/*
* Mute is a named function that will replace /mute commands
diff --git a/apps/meteor/app/slashcommands-mute/server/unmute.ts b/apps/meteor/app/slashcommands-mute/server/unmute.ts
index 25c0956d49e3..4dc683f4ca93 100644
--- a/apps/meteor/app/slashcommands-mute/server/unmute.ts
+++ b/apps/meteor/app/slashcommands-mute/server/unmute.ts
@@ -5,7 +5,7 @@ import { Users } from '@rocket.chat/models';
import { i18n } from '../../../server/lib/i18n';
import { unmuteUserInRoom } from '../../../server/methods/unmuteUserInRoom';
import { settings } from '../../settings/server';
-import { slashCommands } from '../../utils/lib/slashCommand';
+import { slashCommands } from '../../utils/server/slashCommand';
/*
* Unmute is a named function that will replace /unmute commands
diff --git a/apps/meteor/app/slashcommands-open/client/client.ts b/apps/meteor/app/slashcommands-open/client/client.ts
index 987df9599761..99438a24eeb0 100644
--- a/apps/meteor/app/slashcommands-open/client/client.ts
+++ b/apps/meteor/app/slashcommands-open/client/client.ts
@@ -5,7 +5,7 @@ import { roomCoordinator } from '../../../client/lib/rooms/roomCoordinator';
import { router } from '../../../client/providers/RouterProvider';
import { Subscriptions, ChatSubscription } from '../../models/client';
import { sdk } from '../../utils/client/lib/SDKClient';
-import { slashCommands } from '../../utils/lib/slashCommand';
+import { slashCommands } from '../../utils/client/slashCommand';
slashCommands.add({
command: 'open',
diff --git a/apps/meteor/app/slashcommands-status/client/status.ts b/apps/meteor/app/slashcommands-status/client/status.ts
index 9136ef8f586f..3698b5fda4cb 100644
--- a/apps/meteor/app/slashcommands-status/client/status.ts
+++ b/apps/meteor/app/slashcommands-status/client/status.ts
@@ -2,7 +2,7 @@ import type { SlashCommandCallbackParams } from '@rocket.chat/core-typings';
import { dispatchToastMessage } from '../../../client/lib/toast';
import { sdk } from '../../utils/client/lib/SDKClient';
-import { slashCommands } from '../../utils/lib/slashCommand';
+import { slashCommands } from '../../utils/client/slashCommand';
slashCommands.add({
command: 'status',
diff --git a/apps/meteor/app/slashcommands-status/server/status.ts b/apps/meteor/app/slashcommands-status/server/status.ts
index 72d92afaf3f2..a2ff6483d398 100644
--- a/apps/meteor/app/slashcommands-status/server/status.ts
+++ b/apps/meteor/app/slashcommands-status/server/status.ts
@@ -5,7 +5,7 @@ import { Users } from '@rocket.chat/models';
import { i18n } from '../../../server/lib/i18n';
import { settings } from '../../settings/server';
import { setUserStatusMethod } from '../../user-status/server/methods/setUserStatus';
-import { slashCommands } from '../../utils/lib/slashCommand';
+import { slashCommands } from '../../utils/server/slashCommand';
slashCommands.add({
command: 'status',
diff --git a/apps/meteor/app/slashcommands-topic/client/topic.ts b/apps/meteor/app/slashcommands-topic/client/topic.ts
index f5f5ed58bb0f..f7e47c334b5a 100644
--- a/apps/meteor/app/slashcommands-topic/client/topic.ts
+++ b/apps/meteor/app/slashcommands-topic/client/topic.ts
@@ -5,7 +5,7 @@ import { callbacks } from '../../../lib/callbacks';
import { hasPermission } from '../../authorization/client';
import { ChatRoom } from '../../models/client/models/ChatRoom';
import { sdk } from '../../utils/client/lib/SDKClient';
-import { slashCommands } from '../../utils/lib/slashCommand';
+import { slashCommands } from '../../utils/client/slashCommand';
slashCommands.add({
command: 'topic',
diff --git a/apps/meteor/app/slashcommands-topic/server/topic.ts b/apps/meteor/app/slashcommands-topic/server/topic.ts
index 24fd51d5f509..c1fa6ea283b7 100644
--- a/apps/meteor/app/slashcommands-topic/server/topic.ts
+++ b/apps/meteor/app/slashcommands-topic/server/topic.ts
@@ -2,7 +2,7 @@ import type { SlashCommandCallbackParams } from '@rocket.chat/core-typings';
import { hasPermissionAsync } from '../../authorization/server/functions/hasPermission';
import { saveRoomSettings } from '../../channel-settings/server/methods/saveRoomSettings';
-import { slashCommands } from '../../utils/lib/slashCommand';
+import { slashCommands } from '../../utils/server/slashCommand';
slashCommands.add({
command: 'topic',
diff --git a/apps/meteor/app/slashcommands-unarchiveroom/client/client.ts b/apps/meteor/app/slashcommands-unarchiveroom/client/client.ts
index 2fed1e1c7802..7b65fc067031 100644
--- a/apps/meteor/app/slashcommands-unarchiveroom/client/client.ts
+++ b/apps/meteor/app/slashcommands-unarchiveroom/client/client.ts
@@ -1,4 +1,4 @@
-import { slashCommands } from '../../utils/lib/slashCommand';
+import { slashCommands } from '../../utils/client/slashCommand';
slashCommands.add({
command: 'unarchive',
diff --git a/apps/meteor/app/slashcommands-unarchiveroom/server/server.ts b/apps/meteor/app/slashcommands-unarchiveroom/server/server.ts
index d87981bd65a2..4c0c44269d2f 100644
--- a/apps/meteor/app/slashcommands-unarchiveroom/server/server.ts
+++ b/apps/meteor/app/slashcommands-unarchiveroom/server/server.ts
@@ -10,7 +10,7 @@ import { roomCoordinator } from '../../../server/lib/rooms/roomCoordinator';
import { hasPermissionAsync } from '../../authorization/server/functions/hasPermission';
import { unarchiveRoom } from '../../lib/server/functions/unarchiveRoom';
import { settings } from '../../settings/server';
-import { slashCommands } from '../../utils/lib/slashCommand';
+import { slashCommands } from '../../utils/server/slashCommand';
slashCommands.add({
command: 'unarchive',
diff --git a/apps/meteor/app/statistics/server/methods/getStatistics.ts b/apps/meteor/app/statistics/server/methods/getStatistics.ts
index c7eb79b5b985..a804ef83584e 100644
--- a/apps/meteor/app/statistics/server/methods/getStatistics.ts
+++ b/apps/meteor/app/statistics/server/methods/getStatistics.ts
@@ -1,10 +1,10 @@
import type { IStats } from '@rocket.chat/core-typings';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
import { getLastStatistics } from '../functions/getLastStatistics';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
getStatistics(refresh?: boolean): IStats;
diff --git a/apps/meteor/app/theme/client/imports/general/base_old.css b/apps/meteor/app/theme/client/imports/general/base_old.css
index 20b023cc61aa..3120d9c05ff0 100644
--- a/apps/meteor/app/theme/client/imports/general/base_old.css
+++ b/apps/meteor/app/theme/client/imports/general/base_old.css
@@ -776,21 +776,6 @@
padding: 21px 0 10px;
}
- & .start {
- margin-top: 44px;
-
- text-align: center;
-
- & .start__purge-warning {
- margin-top: -33px;
- margin-bottom: 0.5rem;
- padding: 1rem;
-
- border-width: 1px 0 0;
- background: linear-gradient(to bottom, var(--rc-color-alert-message-warning-background) 0%, rgba(255, 255, 255, 0) 100%);
- }
- }
-
& .editing .body {
border-radius: var(--border-radius);
}
diff --git a/apps/meteor/app/threads/server/hooks/aftersavemessage.ts b/apps/meteor/app/threads/server/hooks/aftersavemessage.ts
index ab1fa182599b..a938dadddb27 100644
--- a/apps/meteor/app/threads/server/hooks/aftersavemessage.ts
+++ b/apps/meteor/app/threads/server/hooks/aftersavemessage.ts
@@ -4,7 +4,7 @@ import { Messages } from '@rocket.chat/models';
import { Meteor } from 'meteor/meteor';
import { callbacks } from '../../../../lib/callbacks';
-import { broadcastMessageFromData } from '../../../../server/modules/watchers/lib/messages';
+import { notifyOnMessageChange } from '../../../lib/server/lib/notifyListener';
import { updateThreadUsersSubscriptions, getMentions } from '../../../lib/server/lib/notifyUsersOnMessage';
import { sendMessageNotifications } from '../../../lib/server/lib/sendNotificationsOnMessage';
import { settings } from '../../../settings/server';
@@ -62,7 +62,7 @@ export async function processThreads(message: IMessage, room: IRoom) {
await notifyUsersOnReply(message, replies);
await metaData(message, parentMessage, replies);
await notification(message, room, replies);
- void broadcastMessageFromData({
+ void notifyOnMessageChange({
id: message.tmid,
});
@@ -77,7 +77,7 @@ Meteor.startup(() => {
}
callbacks.add(
'afterSaveMessage',
- async (message, room) => {
+ async (message, { room }) => {
return processThreads(message, room);
},
callbacks.priority.LOW,
diff --git a/apps/meteor/app/threads/server/methods/followMessage.ts b/apps/meteor/app/threads/server/methods/followMessage.ts
index 05650d0ad2ef..8ed7093e00d4 100644
--- a/apps/meteor/app/threads/server/methods/followMessage.ts
+++ b/apps/meteor/app/threads/server/methods/followMessage.ts
@@ -1,16 +1,17 @@
import { Apps, AppEvents } from '@rocket.chat/apps';
import type { IMessage } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Messages } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import { canAccessRoomIdAsync } from '../../../authorization/server/functions/canAccessRoom';
import { RateLimiter } from '../../../lib/server';
+import { notifyOnMessageChange } from '../../../lib/server/lib/notifyListener';
import { settings } from '../../../settings/server';
import { follow } from '../functions';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
followMessage(message: { mid: IMessage['_id'] }): false | undefined;
@@ -41,7 +42,13 @@ Meteor.methods({
throw new Meteor.Error('error-not-allowed', 'not-allowed', { method: 'followMessage' });
}
- const followResult = await follow({ tmid: message.tmid || message._id, uid });
+ const id = message.tmid || message._id;
+
+ const followResult = await follow({ tmid: id, uid });
+
+ void notifyOnMessageChange({
+ id,
+ });
const isFollowed = true;
await Apps.self?.triggerEvent(AppEvents.IPostMessageFollowed, message, await Meteor.userAsync(), isFollowed);
diff --git a/apps/meteor/app/threads/server/methods/getThreadMessages.ts b/apps/meteor/app/threads/server/methods/getThreadMessages.ts
index d6c2d65ff4d4..8ae31130df1b 100644
--- a/apps/meteor/app/threads/server/methods/getThreadMessages.ts
+++ b/apps/meteor/app/threads/server/methods/getThreadMessages.ts
@@ -1,6 +1,6 @@
import type { IMessage } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Messages, Rooms } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { callbacks } from '../../../../lib/callbacks';
@@ -8,7 +8,7 @@ import { canAccessRoomAsync } from '../../../authorization/server';
import { settings } from '../../../settings/server';
import { readThread } from '../functions';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
getThreadMessages(params: { tmid: IMessage['_id']; limit?: number; skip?: number }): Promise;
diff --git a/apps/meteor/app/threads/server/methods/getThreadsList.ts b/apps/meteor/app/threads/server/methods/getThreadsList.ts
index 5a33dc16280b..c51449ff2d4d 100644
--- a/apps/meteor/app/threads/server/methods/getThreadsList.ts
+++ b/apps/meteor/app/threads/server/methods/getThreadsList.ts
@@ -1,6 +1,6 @@
import type { IMessage, IRoom } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Messages, Rooms } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { canAccessRoomAsync } from '../../../authorization/server';
@@ -8,7 +8,7 @@ import { settings } from '../../../settings/server';
const MAX_LIMIT = 100;
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
getThreadsList(params: { rid: IRoom['_id']; limit?: number; skip?: number }): IMessage[];
diff --git a/apps/meteor/app/threads/server/methods/unfollowMessage.ts b/apps/meteor/app/threads/server/methods/unfollowMessage.ts
index afc9206b038f..de4f2683be41 100644
--- a/apps/meteor/app/threads/server/methods/unfollowMessage.ts
+++ b/apps/meteor/app/threads/server/methods/unfollowMessage.ts
@@ -1,16 +1,17 @@
import { Apps, AppEvents } from '@rocket.chat/apps';
import type { IMessage } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Messages } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import { canAccessRoomIdAsync } from '../../../authorization/server/functions/canAccessRoom';
import { RateLimiter } from '../../../lib/server';
+import { notifyOnMessageChange } from '../../../lib/server/lib/notifyListener';
import { settings } from '../../../settings/server';
import { unfollow } from '../functions';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
unfollowMessage(message: { mid: IMessage['_id'] }): false | undefined;
@@ -41,7 +42,13 @@ Meteor.methods({
throw new Meteor.Error('error-not-allowed', 'not-allowed', { method: 'unfollowMessage' });
}
- const unfollowResult = await unfollow({ rid: message.rid, tmid: message.tmid || message._id, uid });
+ const id = message.tmid || message._id;
+
+ const unfollowResult = await unfollow({ rid: message.rid, tmid: id, uid });
+
+ void notifyOnMessageChange({
+ id,
+ });
const isFollowed = false;
await Apps.self?.triggerEvent(AppEvents.IPostMessageFollowed, message, await Meteor.userAsync(), isFollowed);
diff --git a/apps/meteor/app/ui-cached-collection/client/models/CachedCollection.ts b/apps/meteor/app/ui-cached-collection/client/models/CachedCollection.ts
index 545e1e73342d..602a0eddb8ce 100644
--- a/apps/meteor/app/ui-cached-collection/client/models/CachedCollection.ts
+++ b/apps/meteor/app/ui-cached-collection/client/models/CachedCollection.ts
@@ -1,5 +1,5 @@
+import type { StreamNames } from '@rocket.chat/ddp-client';
import { Emitter } from '@rocket.chat/emitter';
-import type { StreamNames } from '@rocket.chat/ui-contexts';
import localforage from 'localforage';
import { Accounts } from 'meteor/accounts-base';
import { Meteor } from 'meteor/meteor';
diff --git a/apps/meteor/app/ui-cached-collection/client/models/CachedCollectionManager.ts b/apps/meteor/app/ui-cached-collection/client/models/CachedCollectionManager.ts
index 845731e2450a..b03115105841 100644
--- a/apps/meteor/app/ui-cached-collection/client/models/CachedCollectionManager.ts
+++ b/apps/meteor/app/ui-cached-collection/client/models/CachedCollectionManager.ts
@@ -41,12 +41,12 @@ class CachedCollectionManager extends Emitter<{ reconnect: void; login: string |
}
});
+ Accounts.onLogin(() => {
+ this.emit('login', Meteor.userId());
+ });
Tracker.autorun(() => {
const uid = Meteor.userId();
this.logged = uid !== null;
- if (this.logged) {
- this.emit('login', uid);
- }
});
}
diff --git a/apps/meteor/app/user-status/server/methods/deleteCustomUserStatus.ts b/apps/meteor/app/user-status/server/methods/deleteCustomUserStatus.ts
index f58fa9551f4c..416bc6f678ed 100644
--- a/apps/meteor/app/user-status/server/methods/deleteCustomUserStatus.ts
+++ b/apps/meteor/app/user-status/server/methods/deleteCustomUserStatus.ts
@@ -1,11 +1,11 @@
import { api } from '@rocket.chat/core-services';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { CustomUserStatus } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
deleteCustomUserStatus(userStatusID: string): Promise;
diff --git a/apps/meteor/app/user-status/server/methods/getUserStatusText.ts b/apps/meteor/app/user-status/server/methods/getUserStatusText.ts
index 5aa80627d562..911a69854b95 100644
--- a/apps/meteor/app/user-status/server/methods/getUserStatusText.ts
+++ b/apps/meteor/app/user-status/server/methods/getUserStatusText.ts
@@ -1,9 +1,9 @@
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
import { getStatusText } from '../../../lib/server/functions/getStatusText';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
getUserStatusText(userId: string): Promise;
diff --git a/apps/meteor/app/user-status/server/methods/insertOrUpdateUserStatus.ts b/apps/meteor/app/user-status/server/methods/insertOrUpdateUserStatus.ts
index b6a98895bc2c..6e034f030679 100644
--- a/apps/meteor/app/user-status/server/methods/insertOrUpdateUserStatus.ts
+++ b/apps/meteor/app/user-status/server/methods/insertOrUpdateUserStatus.ts
@@ -1,14 +1,14 @@
import { api } from '@rocket.chat/core-services';
import type { ICustomUserStatus } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import type { InsertionModel } from '@rocket.chat/model-typings';
import { CustomUserStatus } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { trim } from '../../../../lib/utils/stringUtils';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
insertOrUpdateUserStatus(userStatusData: {
diff --git a/apps/meteor/app/user-status/server/methods/listCustomUserStatus.ts b/apps/meteor/app/user-status/server/methods/listCustomUserStatus.ts
index 3a962121d65c..d9a58f8b8c72 100644
--- a/apps/meteor/app/user-status/server/methods/listCustomUserStatus.ts
+++ b/apps/meteor/app/user-status/server/methods/listCustomUserStatus.ts
@@ -1,9 +1,9 @@
import type { ICustomUserStatus } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { CustomUserStatus } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
listCustomUserStatus(): ICustomUserStatus[];
diff --git a/apps/meteor/app/user-status/server/methods/setUserStatus.ts b/apps/meteor/app/user-status/server/methods/setUserStatus.ts
index 32db93e722fb..0b40e7e37246 100644
--- a/apps/meteor/app/user-status/server/methods/setUserStatus.ts
+++ b/apps/meteor/app/user-status/server/methods/setUserStatus.ts
@@ -1,6 +1,6 @@
import { Presence } from '@rocket.chat/core-services';
import type { IUser } from '@rocket.chat/core-typings';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
@@ -8,7 +8,7 @@ import { RateLimiter } from '../../../lib/server';
import { setStatusText } from '../../../lib/server/functions/setStatusText';
import { settings } from '../../../settings/server';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
setUserStatus(statusType: IUser['status'], statusText: IUser['statusText']): void;
diff --git a/apps/meteor/app/utils/client/index.ts b/apps/meteor/app/utils/client/index.ts
index fd03ffc3d720..561a1116141b 100644
--- a/apps/meteor/app/utils/client/index.ts
+++ b/apps/meteor/app/utils/client/index.ts
@@ -2,6 +2,6 @@ export { Info } from '../rocketchat.info';
export { getUserPreference } from './lib/getUserPreference';
export { fileUploadIsValidContentType } from './restrictions';
export { getUserAvatarURL } from './getUserAvatarURL';
-export { slashCommands } from '../lib/slashCommand';
+export { slashCommands } from './slashCommand';
export { getURL } from './getURL';
export { APIClient } from './lib/RestApiClient';
diff --git a/apps/meteor/app/utils/client/lib/SDKClient.ts b/apps/meteor/app/utils/client/lib/SDKClient.ts
index c174f9125f49..3c7e43c85f7c 100644
--- a/apps/meteor/app/utils/client/lib/SDKClient.ts
+++ b/apps/meteor/app/utils/client/lib/SDKClient.ts
@@ -1,15 +1,12 @@
import type { RestClientInterface } from '@rocket.chat/api-client';
-import type { SDK } from '@rocket.chat/ddp-client/src/DDPSDK';
-import type { ClientStream } from '@rocket.chat/ddp-client/src/types/ClientStream';
-import type { StreamKeys, StreamNames, StreamerCallbackArgs } from '@rocket.chat/ddp-client/src/types/streams';
+import type { SDK, ClientStream, StreamKeys, StreamNames, StreamerCallbackArgs, ServerMethods } from '@rocket.chat/ddp-client';
import { Emitter } from '@rocket.chat/emitter';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { DDPCommon } from 'meteor/ddp-common';
import { Meteor } from 'meteor/meteor';
import { APIClient } from './RestApiClient';
-declare module '@rocket.chat/ddp-client/src/DDPSDK' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface SDK {
stream>(
@@ -138,6 +135,12 @@ const createStreamManager = () => {
const streams = new Map();
+ Accounts.onLogout(() => {
+ streams.forEach((stream) => {
+ stream.unsubList.forEach((stop) => stop());
+ });
+ });
+
Meteor.connection._stream.on('message', (rawMsg: string) => {
const msg = DDPCommon.parseDDP(rawMsg);
if (!isChangedCollectionPayload(msg)) {
@@ -169,7 +172,6 @@ const createStreamManager = () => {
const stop = (): void => {
streamProxy.off(eventLiteral, proxyCallback);
-
// If someone is still listening, don't unsubscribe
if (streamProxy.has(eventLiteral)) {
return;
@@ -182,11 +184,15 @@ const createStreamManager = () => {
};
const stream = streams.get(eventLiteral) || createNewMeteorStream(name, key, args);
+
stream.unsubList.add(stop);
if (!streams.has(eventLiteral)) {
streams.set(eventLiteral, stream);
}
- stream.error(() => stop());
+
+ stream.error(() => {
+ stream.unsubList.forEach((stop) => stop());
+ });
return {
id: '',
diff --git a/apps/meteor/app/utils/lib/slashCommand.ts b/apps/meteor/app/utils/client/slashCommand.ts
similarity index 84%
rename from apps/meteor/app/utils/lib/slashCommand.ts
rename to apps/meteor/app/utils/client/slashCommand.ts
index f4e2cc1b359a..66e793012fac 100644
--- a/apps/meteor/app/utils/lib/slashCommand.ts
+++ b/apps/meteor/app/utils/client/slashCommand.ts
@@ -6,7 +6,8 @@ import type {
SlashCommandPreviewItem,
SlashCommandPreviews,
} from '@rocket.chat/core-typings';
-import { Meteor } from 'meteor/meteor';
+
+import { InvalidCommandUsage, InvalidPreview } from '../../../client/lib/errors';
interface ISlashCommandAddParams {
command: string;
@@ -69,7 +70,7 @@ export const slashCommands = {
}
if (!message?.rid) {
- throw new Meteor.Error('invalid-command-usage', 'Executing a command requires at least a message with a room id.');
+ throw new InvalidCommandUsage();
}
return cmd.callback({ command, params, message, triggerId, userId });
@@ -85,7 +86,7 @@ export const slashCommands = {
}
if (!message?.rid) {
- throw new Meteor.Error('invalid-command-usage', 'Executing a command requires at least a message with a room id.');
+ throw new InvalidCommandUsage();
}
const previewInfo = await cmd.previewer(command, params, message);
@@ -114,19 +115,19 @@ export const slashCommands = {
}
if (!message?.rid) {
- throw new Meteor.Error('invalid-command-usage', 'Executing a command requires at least a message with a room id.');
+ throw new InvalidCommandUsage();
}
// { id, type, value }
if (!preview.id || !preview.type || !preview.value) {
- throw new Meteor.Error('error-invalid-preview', 'Preview Item must have an id, type, and value.');
+ throw new InvalidPreview();
}
return cmd.previewCallback(command, params, message, preview, triggerId);
},
};
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
slashCommand(params: { cmd: string; params: string; msg: IMessage; triggerId: string }): unknown;
diff --git a/apps/meteor/app/utils/lib/i18n.ts b/apps/meteor/app/utils/lib/i18n.ts
index 9d3fbc59d245..b69fe6b30513 100644
--- a/apps/meteor/app/utils/lib/i18n.ts
+++ b/apps/meteor/app/utils/lib/i18n.ts
@@ -9,11 +9,11 @@ export const i18n = i18next.use(sprintf);
export const addSprinfToI18n = function (t: (typeof i18n)['t']) {
return function (key: string, ...replaces: any): string {
if (replaces[0] === undefined) {
- return t(key, ...replaces);
+ return t(key);
}
if (isObject(replaces[0]) && !Array.isArray(replaces[0])) {
- return t(key, ...replaces);
+ return t(key, replaces[0]);
}
return t(key, {
diff --git a/apps/meteor/app/utils/rocketchat.info b/apps/meteor/app/utils/rocketchat.info
index ef7c8e5717c9..faf0e8f47de6 100644
--- a/apps/meteor/app/utils/rocketchat.info
+++ b/apps/meteor/app/utils/rocketchat.info
@@ -1,3 +1,3 @@
{
- "version": "6.11.0-develop"
+ "version": "6.12.0-develop"
}
diff --git a/apps/meteor/app/utils/server/slashCommand.ts b/apps/meteor/app/utils/server/slashCommand.ts
index 74f2c5716cc4..27b3c81735f9 100644
--- a/apps/meteor/app/utils/server/slashCommand.ts
+++ b/apps/meteor/app/utils/server/slashCommand.ts
@@ -1,7 +1,139 @@
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
+import { MeteorError } from '@rocket.chat/core-services';
+import type {
+ IMessage,
+ SlashCommand,
+ SlashCommandOptions,
+ RequiredField,
+ SlashCommandPreviewItem,
+ SlashCommandPreviews,
+} from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Meteor } from 'meteor/meteor';
-import { slashCommands } from '../lib/slashCommand';
+interface ISlashCommandAddParams {
+ command: string;
+ callback?: SlashCommand['callback'];
+ options?: SlashCommandOptions;
+ result?: SlashCommand['result'];
+ providesPreview?: boolean;
+ previewer?: SlashCommand['previewer'];
+ previewCallback?: SlashCommand['previewCallback'];
+ appId?: string;
+ description?: string;
+}
+
+export const slashCommands = {
+ commands: {} as Record,
+ add({
+ command,
+ callback,
+ options = {},
+ result,
+ providesPreview = false,
+ previewer,
+ previewCallback,
+ appId,
+ description = '',
+ }: ISlashCommandAddParams): void {
+ if (this.commands[command]) {
+ return;
+ }
+ this.commands[command] = {
+ command,
+ callback,
+ params: options.params,
+ description: options.description || description,
+ permission: options.permission,
+ clientOnly: options.clientOnly || false,
+ result,
+ providesPreview: Boolean(providesPreview),
+ previewer,
+ previewCallback,
+ appId,
+ } as SlashCommand;
+ },
+ async run({
+ command,
+ message,
+ params,
+ triggerId,
+ userId,
+ }: {
+ command: string;
+ params: string;
+ message: RequiredField, 'rid' | '_id'>;
+ userId: string;
+ triggerId?: string | undefined;
+ }): Promise {
+ const cmd = this.commands[command];
+ if (typeof cmd?.callback !== 'function') {
+ return;
+ }
+
+ if (!message?.rid) {
+ throw new MeteorError('invalid-command-usage', 'Executing a command requires at least a message with a room id.');
+ }
+
+ return cmd.callback({ command, params, message, triggerId, userId });
+ },
+ async getPreviews(
+ command: string,
+ params: string,
+ message: RequiredField, 'rid'>,
+ ): Promise {
+ const cmd = this.commands[command];
+ if (typeof cmd?.previewer !== 'function') {
+ return;
+ }
+
+ if (!message?.rid) {
+ throw new MeteorError('invalid-command-usage', 'Executing a command requires at least a message with a room id.');
+ }
+
+ const previewInfo = await cmd.previewer(command, params, message);
+
+ if (!previewInfo?.items?.length) {
+ return;
+ }
+
+ // A limit of ten results, to save time and bandwidth
+ if (previewInfo.items.length >= 10) {
+ previewInfo.items = previewInfo.items.slice(0, 10);
+ }
+
+ return previewInfo;
+ },
+ async executePreview(
+ command: string,
+ params: string,
+ message: Pick & Partial>,
+ preview: SlashCommandPreviewItem,
+ triggerId?: string,
+ ) {
+ const cmd = this.commands[command];
+ if (typeof cmd?.previewCallback !== 'function') {
+ return;
+ }
+
+ if (!message?.rid) {
+ throw new MeteorError('invalid-command-usage', 'Executing a command requires at least a message with a room id.');
+ }
+
+ // { id, type, value }
+ if (!preview.id || !preview.type || !preview.value) {
+ throw new MeteorError('error-invalid-preview', 'Preview Item must have an id, type, and value.');
+ }
+
+ return cmd.previewCallback(command, params, message, preview, triggerId);
+ },
+};
+
+declare module '@rocket.chat/ddp-client' {
+ // eslint-disable-next-line @typescript-eslint/naming-convention
+ interface ServerMethods {
+ slashCommand(params: { cmd: string; params: string; msg: IMessage; triggerId: string }): unknown;
+ }
+}
Meteor.methods({
async slashCommand(command) {
@@ -27,5 +159,3 @@ Meteor.methods({
});
},
});
-
-export { slashCommands };
diff --git a/apps/meteor/app/version-check/server/methods/banner_dismiss.ts b/apps/meteor/app/version-check/server/methods/banner_dismiss.ts
index 5ffebcfbbd5a..a3bf337626f9 100644
--- a/apps/meteor/app/version-check/server/methods/banner_dismiss.ts
+++ b/apps/meteor/app/version-check/server/methods/banner_dismiss.ts
@@ -1,10 +1,10 @@
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Users } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { notifyOnUserChange } from '../../../lib/server/lib/notifyListener';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
'banner/dismiss'({ id }: { id: string }): void;
diff --git a/apps/meteor/app/webdav/server/methods/addWebdavAccount.ts b/apps/meteor/app/webdav/server/methods/addWebdavAccount.ts
index e2c9a9ddc324..2c3973649091 100644
--- a/apps/meteor/app/webdav/server/methods/addWebdavAccount.ts
+++ b/apps/meteor/app/webdav/server/methods/addWebdavAccount.ts
@@ -1,14 +1,14 @@
import { api } from '@rocket.chat/core-services';
import type { IWebdavAccountPayload } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { WebdavAccounts } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Match, check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import { settings } from '../../../settings/server';
import { WebdavClientAdapter } from '../lib/webdavClientAdapter';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
addWebdavAccount(formData: IWebdavAccountPayload): boolean;
diff --git a/apps/meteor/app/webdav/server/methods/getFileFromWebdav.ts b/apps/meteor/app/webdav/server/methods/getFileFromWebdav.ts
index 346362935d87..38aeb0442c5c 100644
--- a/apps/meteor/app/webdav/server/methods/getFileFromWebdav.ts
+++ b/apps/meteor/app/webdav/server/methods/getFileFromWebdav.ts
@@ -1,15 +1,15 @@
import type { IWebdavAccount, IWebdavNode } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { WebdavAccounts } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { settings } from '../../../settings/server';
import { getWebdavCredentials } from '../lib/getWebdavCredentials';
import { WebdavClientAdapter } from '../lib/webdavClientAdapter';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
- export interface ServerMethods {
+ interface ServerMethods {
getFileFromWebdav(accountId: IWebdavAccount['_id'], file: IWebdavNode): Promise<{ success: boolean; data: Uint8Array }>;
}
}
diff --git a/apps/meteor/app/webdav/server/methods/getWebdavFileList.ts b/apps/meteor/app/webdav/server/methods/getWebdavFileList.ts
index f4d944181928..66e924b719a2 100644
--- a/apps/meteor/app/webdav/server/methods/getWebdavFileList.ts
+++ b/apps/meteor/app/webdav/server/methods/getWebdavFileList.ts
@@ -1,13 +1,13 @@
import type { IWebdavAccount, IWebdavNode } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { WebdavAccounts } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { settings } from '../../../settings/server';
import { getWebdavCredentials } from '../lib/getWebdavCredentials';
import { WebdavClientAdapter } from '../lib/webdavClientAdapter';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
getWebdavFileList(accountId: IWebdavAccount['_id'], path: string): { success: boolean; data: IWebdavNode[] };
diff --git a/apps/meteor/app/webdav/server/methods/getWebdavFilePreview.ts b/apps/meteor/app/webdav/server/methods/getWebdavFilePreview.ts
index 1e01937a0e52..34077babf276 100644
--- a/apps/meteor/app/webdav/server/methods/getWebdavFilePreview.ts
+++ b/apps/meteor/app/webdav/server/methods/getWebdavFilePreview.ts
@@ -1,13 +1,13 @@
import type { IWebdavAccount } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { WebdavAccounts } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { createClient } from 'webdav';
import { settings } from '../../../settings/server';
import { getWebdavCredentials } from '../lib/getWebdavCredentials';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
getWebdavFilePreview(accountId: IWebdavAccount['_id'], path: string): { success: true; data: ArrayBuffer } | undefined;
diff --git a/apps/meteor/app/webdav/server/methods/removeWebdavAccount.ts b/apps/meteor/app/webdav/server/methods/removeWebdavAccount.ts
index df6102297cc2..a68a14e29e40 100644
--- a/apps/meteor/app/webdav/server/methods/removeWebdavAccount.ts
+++ b/apps/meteor/app/webdav/server/methods/removeWebdavAccount.ts
@@ -1,14 +1,14 @@
import { api } from '@rocket.chat/core-services';
import type { IWebdavAccount } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { WebdavAccounts } from '@rocket.chat/models';
-import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import type { DeleteResult } from 'mongodb';
import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger';
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
removeWebdavAccount(accountId: IWebdavAccount['_id']): DeleteResult;
diff --git a/apps/meteor/app/webdav/server/methods/uploadFileToWebdav.ts b/apps/meteor/app/webdav/server/methods/uploadFileToWebdav.ts
index 8a2e1badd27d..97bcf4632216 100644
--- a/apps/meteor/app/webdav/server/methods/uploadFileToWebdav.ts
+++ b/apps/meteor/app/webdav/server/methods/uploadFileToWebdav.ts
@@ -1,7 +1,8 @@
import { MeteorError } from '@rocket.chat/core-services';
import type { IWebdavAccount } from '@rocket.chat/core-typings';
+import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Logger } from '@rocket.chat/logger';
-import type { ServerMethods, TranslationKey } from '@rocket.chat/ui-contexts';
+import type { TranslationKey } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { settings } from '../../../settings/server';
@@ -9,7 +10,7 @@ import { uploadFileToWebdav } from '../lib/uploadFileToWebdav';
const logger = new Logger('WebDAV_Upload');
-declare module '@rocket.chat/ui-contexts' {
+declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
uploadFileToWebdav(
diff --git a/apps/meteor/client/NavBarV2/NavBarPagesToolbar/hooks/useAuditMenu.spec.tsx b/apps/meteor/client/NavBarV2/NavBarPagesToolbar/hooks/useAuditMenu.spec.tsx
index 11eddf934055..94fdfe25a92d 100644
--- a/apps/meteor/client/NavBarV2/NavBarPagesToolbar/hooks/useAuditMenu.spec.tsx
+++ b/apps/meteor/client/NavBarV2/NavBarPagesToolbar/hooks/useAuditMenu.spec.tsx
@@ -1,10 +1,11 @@
import { mockAppRoot } from '@rocket.chat/mock-providers';
-import { renderHook } from '@testing-library/react-hooks';
+import { renderHook, waitFor } from '@testing-library/react';
import { useAuditMenu } from './useAuditMenu';
it('should return an empty array of items if doesn`t have license', async () => {
- const { result, waitFor } = renderHook(() => useAuditMenu(), {
+ const { result } = renderHook(() => useAuditMenu(), {
+ legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/v1/licenses.info', () => ({
// @ts-expect-error: just for testing
@@ -18,13 +19,12 @@ it('should return an empty array of items if doesn`t have license', async () =>
.build(),
});
- await waitFor(() => result.all.length > 1);
-
- expect(result.current).toEqual([]);
+ await waitFor(() => expect(result.current).toEqual([]));
});
it('should return an empty array of items if have license and not have permissions', async () => {
- const { result, waitFor } = renderHook(() => useAuditMenu(), {
+ const { result } = renderHook(() => useAuditMenu(), {
+ legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/v1/licenses.info', () => ({
license: {
@@ -41,13 +41,12 @@ it('should return an empty array of items if have license and not have permissio
.build(),
});
- await waitFor(() => result.all.length > 1);
-
- expect(result.current).toEqual([]);
+ await waitFor(() => expect(result.current).toEqual([]));
});
it('should return auditItems if have license and permissions', async () => {
- const { result, waitFor } = renderHook(() => useAuditMenu(), {
+ const { result } = renderHook(() => useAuditMenu(), {
+ legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/v1/licenses.info', () => ({
license: {
@@ -65,12 +64,12 @@ it('should return auditItems if have license and permissions', async () => {
.build(),
});
- await waitFor(() => result.current.length > 0);
-
- expect(result.current[0].items[0]).toEqual(
- expect.objectContaining({
- id: 'messages',
- }),
+ await waitFor(() =>
+ expect(result.current[0]?.items[0]).toEqual(
+ expect.objectContaining({
+ id: 'messages',
+ }),
+ ),
);
expect(result.current[0].items[1]).toEqual(
@@ -81,7 +80,8 @@ it('should return auditItems if have license and permissions', async () => {
});
it('should return auditMessages item if have license and can-audit permission', async () => {
- const { result, waitFor } = renderHook(() => useAuditMenu(), {
+ const { result } = renderHook(() => useAuditMenu(), {
+ legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/v1/licenses.info', () => ({
license: {
@@ -98,17 +98,18 @@ it('should return auditMessages item if have license and can-audit permission',
.build(),
});
- await waitFor(() => result.current.length > 0);
-
- expect(result.current[0].items[0]).toEqual(
- expect.objectContaining({
- id: 'messages',
- }),
+ await waitFor(() =>
+ expect(result.current[0]?.items[0]).toEqual(
+ expect.objectContaining({
+ id: 'messages',
+ }),
+ ),
);
});
it('should return audiLogs item if have license and can-audit-log permission', async () => {
- const { result, waitFor } = renderHook(() => useAuditMenu(), {
+ const { result } = renderHook(() => useAuditMenu(), {
+ legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/v1/licenses.info', () => ({
license: {
@@ -125,11 +126,11 @@ it('should return audiLogs item if have license and can-audit-log permission', a
.build(),
});
- await waitFor(() => result.current.length > 0);
-
- expect(result.current[0].items[0]).toEqual(
- expect.objectContaining({
- id: 'auditLog',
- }),
+ await waitFor(() =>
+ expect(result.current[0]?.items[0]).toEqual(
+ expect.objectContaining({
+ id: 'auditLog',
+ }),
+ ),
);
});
diff --git a/apps/meteor/client/NavBarV2/NavBarPagesToolbar/hooks/useMarketPlaceMenu.spec.tsx b/apps/meteor/client/NavBarV2/NavBarPagesToolbar/hooks/useMarketPlaceMenu.spec.tsx
index 2a3d277e69fe..d2d1e36ca05e 100644
--- a/apps/meteor/client/NavBarV2/NavBarPagesToolbar/hooks/useMarketPlaceMenu.spec.tsx
+++ b/apps/meteor/client/NavBarV2/NavBarPagesToolbar/hooks/useMarketPlaceMenu.spec.tsx
@@ -1,11 +1,12 @@
import { UIActionButtonContext } from '@rocket.chat/apps-engine/definition/ui';
import { mockAppRoot } from '@rocket.chat/mock-providers';
-import { renderHook } from '@testing-library/react-hooks';
+import { renderHook, waitFor } from '@testing-library/react';
import { useMarketPlaceMenu } from './useMarketPlaceMenu';
it('should return and empty array if the user does not have `manage-apps` and `access-marketplace` permission', () => {
const { result } = renderHook(() => useMarketPlaceMenu(), {
+ legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/apps/actionButtons', () => [])
.build(),
@@ -16,6 +17,7 @@ it('should return and empty array if the user does not have `manage-apps` and `a
it('should return `explore` and `installed` items if the user has `access-marketplace` permission', () => {
const { result } = renderHook(() => useMarketPlaceMenu(), {
+ legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/apps/actionButtons', () => [])
.withPermission('access-marketplace')
@@ -37,6 +39,7 @@ it('should return `explore` and `installed` items if the user has `access-market
it('should return `explore`, `installed` and `requested` items if the user has `manage-apps` permission', () => {
const { result } = renderHook(() => useMarketPlaceMenu(), {
+ legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/apps/actionButtons', () => [])
.withEndpoint('GET', '/apps/app-request/stats', () => ({
@@ -69,7 +72,8 @@ it('should return `explore`, `installed` and `requested` items if the user has `
});
it('should return one action from the server with no conditions', async () => {
- const { result, waitForValueToChange } = renderHook(() => useMarketPlaceMenu(), {
+ const { result } = renderHook(() => useMarketPlaceMenu(), {
+ legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/apps/actionButtons', () => [
{
@@ -101,18 +105,19 @@ it('should return one action from the server with no conditions', async () => {
}),
);
- await waitForValueToChange(() => result.current[0].items[3]);
-
- expect(result.current[0].items[3]).toEqual(
- expect.objectContaining({
- id: 'APP_ID_ACTION_ID',
- }),
+ await waitFor(() =>
+ expect(result.current[0]?.items[3]).toEqual(
+ expect.objectContaining({
+ id: 'APP_ID_ACTION_ID',
+ }),
+ ),
);
});
describe('Marketplace menu with role conditions', () => {
it('should return the action if the user has admin role', async () => {
- const { result, waitForValueToChange } = renderHook(() => useMarketPlaceMenu(), {
+ const { result } = renderHook(() => useMarketPlaceMenu(), {
+ legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/apps/actionButtons', () => [
{
@@ -149,17 +154,18 @@ describe('Marketplace menu with role conditions', () => {
}),
);
- await waitForValueToChange(() => result.current[0].items[3]);
-
- expect(result.current[0].items[3]).toEqual(
- expect.objectContaining({
- id: 'APP_ID_ACTION_ID',
- }),
+ await waitFor(() =>
+ expect(result.current[0]?.items[3]).toEqual(
+ expect.objectContaining({
+ id: 'APP_ID_ACTION_ID',
+ }),
+ ),
);
});
it('should return filter the action if the user doesn`t have admin role', async () => {
const { result } = renderHook(() => useMarketPlaceMenu(), {
+ legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/apps/actionButtons', () => [
{
@@ -206,7 +212,8 @@ describe('Marketplace menu with role conditions', () => {
describe('Marketplace menu with permission conditions', () => {
it('should return the action if the user has manage-apps permission', async () => {
- const { result, waitForValueToChange } = renderHook(() => useMarketPlaceMenu(), {
+ const { result } = renderHook(() => useMarketPlaceMenu(), {
+ legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/apps/actionButtons', () => [
{
@@ -241,17 +248,18 @@ describe('Marketplace menu with permission conditions', () => {
}),
);
- await waitForValueToChange(() => result.current[0].items[3]);
-
- expect(result.current[0].items[3]).toEqual(
- expect.objectContaining({
- id: 'APP_ID_ACTION_ID',
- }),
+ await waitFor(() =>
+ expect(result.current[0].items[3]).toEqual(
+ expect.objectContaining({
+ id: 'APP_ID_ACTION_ID',
+ }),
+ ),
);
});
it('should return filter the action if the user doesn`t have `any` permission', async () => {
const { result } = renderHook(() => useMarketPlaceMenu(), {
+ legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/apps/actionButtons', () => [
{
diff --git a/apps/meteor/client/NavBarV2/NavBarSettingsToolbar/hooks/useAdministrationMenu.spec.tsx b/apps/meteor/client/NavBarV2/NavBarSettingsToolbar/hooks/useAdministrationMenu.spec.tsx
index 1315d1053392..ba100fe79783 100644
--- a/apps/meteor/client/NavBarV2/NavBarSettingsToolbar/hooks/useAdministrationMenu.spec.tsx
+++ b/apps/meteor/client/NavBarV2/NavBarSettingsToolbar/hooks/useAdministrationMenu.spec.tsx
@@ -1,10 +1,11 @@
import { mockAppRoot } from '@rocket.chat/mock-providers';
-import { renderHook } from '@testing-library/react-hooks';
+import { renderHook, waitFor } from '@testing-library/react';
import { useAdministrationMenu } from './useAdministrationMenu';
it('should return omnichannel item if has `view-livechat-manager` permission ', async () => {
- const { result, waitFor } = renderHook(() => useAdministrationMenu(), {
+ const { result } = renderHook(() => useAdministrationMenu(), {
+ legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/v1/licenses.info', () => ({
// @ts-expect-error this is a mock
@@ -19,17 +20,18 @@ it('should return omnichannel item if has `view-livechat-manager` permission ',
.build(),
});
- await waitFor(() => !!result.current.length);
-
- expect(result.current[0].items[0]).toEqual(
- expect.objectContaining({
- id: 'omnichannel',
- }),
+ await waitFor(() =>
+ expect(result.current[0]?.items[0]).toEqual(
+ expect.objectContaining({
+ id: 'omnichannel',
+ }),
+ ),
);
});
it('should show administration item if has at least one admin permission', async () => {
- const { result, waitFor } = renderHook(() => useAdministrationMenu(), {
+ const { result } = renderHook(() => useAdministrationMenu(), {
+ legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/v1/licenses.info', () => ({
// @ts-expect-error this is a mock
@@ -44,11 +46,11 @@ it('should show administration item if has at least one admin permission', async
.build(),
});
- await waitFor(() => !!result.current.length);
-
- expect(result.current[0].items[0]).toEqual(
- expect.objectContaining({
- id: 'workspace',
- }),
+ await waitFor(() =>
+ expect(result.current[0]?.items[0]).toEqual(
+ expect.objectContaining({
+ id: 'workspace',
+ }),
+ ),
);
});
diff --git a/apps/meteor/client/components/FilterByText.tsx b/apps/meteor/client/components/FilterByText.tsx
index 1aeeb29a0a57..5c5a3d599e2f 100644
--- a/apps/meteor/client/components/FilterByText.tsx
+++ b/apps/meteor/client/components/FilterByText.tsx
@@ -1,26 +1,13 @@
-import { Box, Icon, TextInput, Button, Margins } from '@rocket.chat/fuselage';
+import { Box, Icon, TextInput, Margins } from '@rocket.chat/fuselage';
import { useAutoFocus, useMergedRefs } from '@rocket.chat/fuselage-hooks';
import { useTranslation } from '@rocket.chat/ui-contexts';
-import type { ReactNode, ChangeEvent, FormEvent } from 'react';
-import React, { forwardRef, memo, useCallback, useEffect, useState } from 'react';
+import type { ChangeEvent, FormEvent, HTMLAttributes } from 'react';
+import React, { forwardRef, memo, useCallback, useState } from 'react';
-type FilterByTextCommonProps = {
- children?: ReactNode | undefined;
- placeholder?: string;
- onChange: (filter: { text: string }) => void;
+type FilterByTextProps = {
+ onChange: (filter: string) => void;
shouldAutoFocus?: boolean;
-};
-
-type FilterByTextPropsWithButton = FilterByTextCommonProps & {
- displayButton: true;
- textButton: string;
- onButtonClick: () => void;
-};
-
-type FilterByTextProps = FilterByTextCommonProps | FilterByTextPropsWithButton;
-
-const isFilterByTextPropsWithButton = (props: any): props is FilterByTextPropsWithButton =>
- 'displayButton' in props && props.displayButton === true;
+} & Omit, 'is' | 'onChange'>;
const FilterByText = forwardRef(function FilterByText(
{ placeholder, onChange: setFilter, shouldAutoFocus = false, children, ...props },
@@ -31,13 +18,10 @@ const FilterByText = forwardRef(function Fi
const autoFocusRef = useAutoFocus(shouldAutoFocus);
const mergedRefs = useMergedRefs(ref, autoFocusRef);
- const handleInputChange = useCallback((event: ChangeEvent) => {
+ const handleInputChange = (event: ChangeEvent) => {
setText(event.currentTarget.value);
- }, []);
-
- useEffect(() => {
- setFilter({ text });
- }, [setFilter, text]);
+ setFilter(event.currentTarget.value);
+ };
const handleFormSubmit = useCallback((event: FormEvent) => {
event.preventDefault();
@@ -47,6 +31,7 @@ const FilterByText = forwardRef(function Fi
}
@@ -57,13 +42,7 @@ const FilterByText = forwardRef(function Fi
aria-label={placeholder ?? t('Search')}
/>
- {isFilterByTextPropsWithButton(props) ? (
-
- ) : (
- children && {children}
- )}
+ {children && {children}}
);
});
diff --git a/apps/meteor/client/components/GenericMenu/GenericMenu.spec.tsx b/apps/meteor/client/components/GenericMenu/GenericMenu.spec.tsx
index 99e62bac1a60..530bd1404dc7 100644
--- a/apps/meteor/client/components/GenericMenu/GenericMenu.spec.tsx
+++ b/apps/meteor/client/components/GenericMenu/GenericMenu.spec.tsx
@@ -1,4 +1,3 @@
-import '@testing-library/jest-dom';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import React from 'react';
@@ -32,28 +31,28 @@ const sections = [regular, danger];
describe('Room Actions Menu', () => {
it('should render kebab menu with the list content', async () => {
- render();
+ render(, { legacyRoot: true });
- userEvent.click(screen.getByRole('button'));
+ await userEvent.click(screen.getByRole('button'));
expect(await screen.findByText('Edit')).toBeInTheDocument();
expect(await screen.findByText('Delete')).toBeInTheDocument();
});
it('should have two different sections, regular and danger', async () => {
- render();
+ render(, { legacyRoot: true });
- userEvent.click(screen.getByRole('button'));
+ await userEvent.click(screen.getByRole('button'));
expect(screen.getAllByRole('presentation')).toHaveLength(2);
expect(screen.getByRole('separator')).toBeInTheDocument();
});
it('should call the action when item clicked', async () => {
- render();
+ render(, { legacyRoot: true });
- userEvent.click(screen.getByRole('button'));
- userEvent.click(screen.getAllByRole('menuitem')[0]);
+ await userEvent.click(screen.getByRole('button'));
+ await userEvent.click(screen.getAllByRole('menuitem')[0]);
expect(mockedFunction).toHaveBeenCalled();
});
diff --git a/apps/meteor/client/components/GenericModal/GenericModal.spec.tsx b/apps/meteor/client/components/GenericModal/GenericModal.spec.tsx
index 0ef7235729c4..b47b6abf7b00 100644
--- a/apps/meteor/client/components/GenericModal/GenericModal.spec.tsx
+++ b/apps/meteor/client/components/GenericModal/GenericModal.spec.tsx
@@ -1,6 +1,5 @@
import { useSetModal } from '@rocket.chat/ui-contexts';
-import { act, screen } from '@testing-library/react';
-import { renderHook } from '@testing-library/react-hooks';
+import { act, screen, renderHook } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import type { ReactElement } from 'react';
import React, { Suspense } from 'react';
@@ -8,12 +7,11 @@ import React, { Suspense } from 'react';
import ModalProviderWithRegion from '../../providers/ModalProvider/ModalProviderWithRegion';
import GenericModal from './GenericModal';
-import '@testing-library/jest-dom';
-
const renderModal = (modalElement: ReactElement) => {
const {
result: { current: setModal },
} = renderHook(() => useSetModal(), {
+ legacyRoot: true,
wrapper: ({ children }) => (
{children}
@@ -34,11 +32,11 @@ describe('callbacks', () => {
renderModal();
- expect(await screen.findByRole('heading', { name: 'Modal', exact: true })).toBeInTheDocument();
+ expect(await screen.findByRole('heading', { name: 'Modal' })).toBeInTheDocument();
- userEvent.keyboard('{Escape}');
+ await userEvent.keyboard('{Escape}');
- expect(screen.queryByRole('heading', { name: 'Modal', exact: true })).not.toBeInTheDocument();
+ expect(screen.queryByRole('heading', { name: 'Modal' })).not.toBeInTheDocument();
expect(handleClose).toHaveBeenCalled();
});
@@ -49,9 +47,9 @@ describe('callbacks', () => {
const { setModal } = renderModal();
- expect(await screen.findByRole('heading', { name: 'Modal', exact: true })).toBeInTheDocument();
+ expect(await screen.findByRole('heading', { name: 'Modal' })).toBeInTheDocument();
- userEvent.click(screen.getByRole('button', { name: 'Ok', exact: true }));
+ await userEvent.click(screen.getByRole('button', { name: 'Ok' }));
expect(handleConfirm).toHaveBeenCalled();
@@ -59,7 +57,7 @@ describe('callbacks', () => {
setModal(null);
});
- expect(screen.queryByRole('heading', { name: 'Modal', exact: true })).not.toBeInTheDocument();
+ expect(screen.queryByRole('heading', { name: 'Modal' })).not.toBeInTheDocument();
expect(handleClose).not.toHaveBeenCalled();
});
@@ -70,9 +68,9 @@ describe('callbacks', () => {
const { setModal } = renderModal();
- expect(await screen.findByRole('heading', { name: 'Modal', exact: true })).toBeInTheDocument();
+ expect(await screen.findByRole('heading', { name: 'Modal' })).toBeInTheDocument();
- userEvent.click(screen.getByRole('button', { name: 'Cancel', exact: true }));
+ await userEvent.click(screen.getByRole('button', { name: 'Cancel' }));
expect(handleCancel).toHaveBeenCalled();
@@ -80,7 +78,7 @@ describe('callbacks', () => {
setModal(null);
});
- expect(screen.queryByRole('heading', { name: 'Modal', exact: true })).not.toBeInTheDocument();
+ expect(screen.queryByRole('heading', { name: 'Modal' })).not.toBeInTheDocument();
expect(handleClose).not.toHaveBeenCalled();
});
diff --git a/apps/meteor/client/components/InfoPanel/RetentionPolicyCallout.spec.tsx b/apps/meteor/client/components/InfoPanel/RetentionPolicyCallout.spec.tsx
index 9a2e7eac4c45..8db42e8c649d 100644
--- a/apps/meteor/client/components/InfoPanel/RetentionPolicyCallout.spec.tsx
+++ b/apps/meteor/client/components/InfoPanel/RetentionPolicyCallout.spec.tsx
@@ -1,26 +1,30 @@
import { render, screen } from '@testing-library/react';
import React from 'react';
-import '@testing-library/jest-dom/extend-expect';
import { createRenteionPolicySettingsMock as createMock } from '../../../tests/mocks/client/mockRetentionPolicySettings';
import { createFakeRoom } from '../../../tests/mocks/data';
-import { setDate } from '../../../tests/mocks/mockDate';
import RetentionPolicyCallout from './RetentionPolicyCallout';
jest.useFakeTimers();
+beforeEach(() => {
+ jest.setSystemTime(new Date(2024, 5, 1, 0, 0, 0));
+});
+
describe('RetentionPolicyCallout', () => {
it('Should render callout if settings are valid', () => {
- setDate();
const fakeRoom = createFakeRoom({ t: 'c' });
- render(, { wrapper: createMock({ appliesToChannels: true, TTLChannels: 60000 }) });
+ render(, {
+ legacyRoot: true,
+ wrapper: createMock({ appliesToChannels: true, TTLChannels: 60000 }),
+ });
expect(screen.getByRole('alert')).toHaveTextContent('a minute June 1, 2024, 12:30 AM');
});
it('Should not render callout if settings are invalid', () => {
- setDate();
const fakeRoom = createFakeRoom({ t: 'c' });
render(, {
+ legacyRoot: true,
wrapper: createMock({ appliesToChannels: true, TTLChannels: 60000, advancedPrecisionCron: '* * * 12 *', advancedPrecision: true }),
});
expect(screen.queryByRole('alert')).not.toBeInTheDocument();
diff --git a/apps/meteor/client/components/MarkdownText.tsx b/apps/meteor/client/components/MarkdownText.tsx
index c9af942f6e1c..3670bcc7cec0 100644
--- a/apps/meteor/client/components/MarkdownText.tsx
+++ b/apps/meteor/client/components/MarkdownText.tsx
@@ -16,16 +16,21 @@ type MarkdownTextParams = {
withTruncatedText: boolean;
} & ComponentProps;
+const walkTokens = (token: marked.Token) => {
+ const boldPattern = /^\*.*\*$|^\*.*|.*\*$/;
+ const italicPattern = /^__(?=\S)([\s\S]*?\S)__(?!_)|^_(?=\S)([\s\S]*?\S)_(?!_)/;
+ if (boldPattern.test(token.raw)) {
+ token.type = 'strong';
+ } else if (italicPattern.test(token.raw)) {
+ token.type = 'em';
+ }
+};
+
+marked.use({ walkTokens });
const documentRenderer = new marked.Renderer();
const inlineRenderer = new marked.Renderer();
const inlineWithoutBreaks = new marked.Renderer();
-marked.Lexer.rules.gfm = {
- ...marked.Lexer.rules.gfm,
- strong: /^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/,
- em: /^__(?=\S)([\s\S]*?\S)__(?!_)|^_(?=\S)([\s\S]*?\S)_(?!_)/,
-};
-
const linkMarked = (href: string | null, _title: string | null, text: string): string =>
`${text} `;
const paragraphMarked = (text: string): string => text;
@@ -112,7 +117,6 @@ const MarkdownText = ({
const markedHtml = /inline/.test(variant)
? marked.parseInline(new Option(content).innerHTML, markedOptions)
: marked.parse(new Option(content).innerHTML, markedOptions);
-
if (parseEmoji) {
// We are using the old emoji parser here. This could come
// with additional processing use, but is the workaround available right now.
diff --git a/apps/meteor/client/components/Omnichannel/modals/TranscriptModal.spec.tsx b/apps/meteor/client/components/Omnichannel/modals/TranscriptModal.spec.tsx
new file mode 100644
index 000000000000..87f7f70fbfbb
--- /dev/null
+++ b/apps/meteor/client/components/Omnichannel/modals/TranscriptModal.spec.tsx
@@ -0,0 +1,48 @@
+import type { IOmnichannelRoom } from '@rocket.chat/core-typings';
+import { render, screen } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
+import React from 'react';
+
+import TranscriptModal from './TranscriptModal';
+
+const room = {
+ open: true,
+ v: { token: '1234567890' },
+ transcriptRequest: {
+ email: 'example@example.com',
+ subject: 'Transcript of livechat conversation',
+ },
+} as IOmnichannelRoom;
+
+const defaultProps = {
+ room,
+ email: 'test@example.com',
+ onRequest: () => null,
+ onSend: () => null,
+ onCancel: () => null,
+ onDiscard: () => null,
+};
+
+it('should show Undo request button when roomOpen is true and transcriptRequest exist', async () => {
+ const onDiscardMock = jest.fn();
+ render(, { legacyRoot: true });
+
+ const undoRequestButton = await screen.findByText('Undo_request');
+ await userEvent.click(undoRequestButton);
+
+ expect(onDiscardMock).toHaveBeenCalled();
+});
+
+it('should show Request button when roomOpen is true and transcriptRequest not exist', async () => {
+ render(, { legacyRoot: true });
+
+ const requestBtn = await screen.findByRole('button', { name: 'request-button' });
+ expect(requestBtn).toBeInTheDocument();
+});
+
+it('should show Send button when roomOpen is false', async () => {
+ render(, { legacyRoot: true });
+
+ const sendBtn = await screen.findByRole('button', { name: 'send-button' });
+ expect(sendBtn).toBeInTheDocument();
+});
diff --git a/apps/meteor/client/components/Omnichannel/modals/TranscriptModal.tsx b/apps/meteor/client/components/Omnichannel/modals/TranscriptModal.tsx
index 95bda1e89107..c06b6a190465 100644
--- a/apps/meteor/client/components/Omnichannel/modals/TranscriptModal.tsx
+++ b/apps/meteor/client/components/Omnichannel/modals/TranscriptModal.tsx
@@ -21,8 +21,7 @@ const TranscriptModal = ({ email: emailDefault = '', room, onRequest, onSend, on
handleSubmit,
setValue,
setFocus,
- watch,
- formState: { errors, isValid, isSubmitting },
+ formState: { errors, isSubmitting },
} = useForm({
defaultValues: { email: emailDefault || '', subject: t('Transcript_of_your_livechat_conversation') },
});
@@ -56,7 +55,7 @@ const TranscriptModal = ({ email: emailDefault = '', room, onRequest, onSend, on
}
}, [setValue, transcriptRequest]);
- const canSubmit = isValid && Boolean(watch('subject'));
+ // const canSubmit = isValid && Boolean(watch('subject'));
return (
} {...props}>
@@ -103,12 +102,12 @@ const TranscriptModal = ({ email: emailDefault = '', room, onRequest, onSend, on
)}
{roomOpen && !transcriptRequest && (
-