diff --git a/packages/rocketchat-api/server/v1/chat.js b/packages/rocketchat-api/server/v1/chat.js index 6e3486ca34ab4..c53f25f8b251c 100644 --- a/packages/rocketchat-api/server/v1/chat.js +++ b/packages/rocketchat-api/server/v1/chat.js @@ -317,3 +317,24 @@ RocketChat.API.v1.addRoute('chat.reportMessage', { authRequired: true }, { return RocketChat.API.v1.success(); } }); + +RocketChat.API.v1.addRoute('chat.ignoreUser', { authRequired: true }, { + get() { + const { rid, userId } = this.queryParams; + let { ignore = true } = this.queryParams; + + ignore = typeof ignore === 'string' ? /true|1/.test(ignore) : ignore; + + if (!rid || !rid.trim()) { + throw new Meteor.Error('error-room-id-param-not-provided', 'The required "rid" param is missing.'); + } + + if (!userId || !userId.trim()) { + throw new Meteor.Error('error-user-id-param-not-provided', 'The required "userId" param is missing.'); + } + + Meteor.runAsUser(this.userId, () => Meteor.call('ignoreUser', { rid, userId, ignore })); + + return RocketChat.API.v1.success(); + } +}); diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 8aab13363db55..60161c16aef3c 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -889,6 +889,8 @@ "Iframe_Integration_send_enable_Description": "Send events to parent window", "Iframe_Integration_send_target_origin": "Send Target Origin", "Iframe_Integration_send_target_origin_Description": "Origin with protocol prefix, which commands are sent to e.g. 'https://localhost', or * to allow sending to anywhere.", + "Ignore": "Ignore", + "Ignored": "Ignored", "IMAP_intercepter_already_running": "IMAP intercepter already running", "IMAP_intercepter_Not_running": "IMAP intercepter Not running", "Impersonate_next_agent_from_queue": "Impersonate next agent from queue", @@ -1317,6 +1319,7 @@ "Message_HideType_ru": "Hide \"User Removed\" messages", "Message_HideType_uj": "Hide \"User Join\" messages", "Message_HideType_ul": "Hide \"User Leave\" messages", + "Message_Ignored": "This message was ignored", "Message_info": "Message info", "Message_KeepHistory": "Keep Per Message Editing History", "Message_MaxAll": "Maximum Channel Size for ALL Message", @@ -2035,6 +2038,7 @@ "unarchive-room_description": "Permission to unarchive channels", "Unblock_User": "Unblock User", "Uninstall": "Uninstall", + "Unignore": "Unignore", "Unmute_someone_in_room": "Unmute someone in the room", "Unmute_user": "Unmute user", "Unnamed": "Unnamed", @@ -2086,8 +2090,10 @@ "User_has_been_activated": "User has been activated", "User_has_been_deactivated": "User has been deactivated", "User_has_been_deleted": "User has been deleted", + "User_has_been_ignored": "User has been ignored", "User_has_been_muted_in_s": "User has been muted in %s", "User_has_been_removed_from_s": "User has been removed from %s", + "User_has_been_unignored": "User is no longer ignored", "User_Info": "User Info", "User_Interface": "User Interface", "User_is_blocked": "User is blocked", diff --git a/packages/rocketchat-lib/client/MessageAction.js b/packages/rocketchat-lib/client/MessageAction.js index dc6afdb31636a..225baa5f4eb17 100644 --- a/packages/rocketchat-lib/client/MessageAction.js +++ b/packages/rocketchat-lib/client/MessageAction.js @@ -4,6 +4,17 @@ import _ from 'underscore'; import moment from 'moment'; import toastr from 'toastr'; +const success = function success(fn) { + return function(error, result) { + if (error) { + return handleError(error); + } + if (result) { + fn.call(this, result); + } + }; +}; + RocketChat.MessageAction = new class { /* config expects the following keys (only id is mandatory): @@ -279,4 +290,45 @@ Meteor.startup(function() { order: 6, group: 'menu' }); + + + + RocketChat.MessageAction.addButton({ + id: 'ignore-user', + icon: 'ban', + label: t('Ignore'), + context: ['message', 'message-mobile'], + action() { + const [, {rid, u: {_id}}] = this._arguments; + Meteor.call('ignoreUser', { rid, userId:_id, ignore: true}, success(() => toastr.success(t('User_has_been_ignored')))); + }, + condition(message) { + const subscription = RocketChat.models.Subscriptions.findOne({rid: message.rid}); + + return Meteor.userId() !== message.u._id && !(subscription.ignored && subscription.ignored.indexOf(message.u._id) > -1); + }, + order: 20, + group: 'menu' + }); + + RocketChat.MessageAction.addButton({ + id: 'unignore-user', + icon: 'ban', + label: t('Unignore'), + context: ['message', 'message-mobile'], + action() { + const [, {rid, u: {_id}}] = this._arguments; + Meteor.call('ignoreUser', { rid, userId:_id, ignore: false}, success(() => toastr.success(t('User_has_been_unignored')))); + + }, + condition(message) { + const subscription = RocketChat.models.Subscriptions.findOne({rid: message.rid}); + return Meteor.userId() !== message.u._id && subscription.ignored && subscription.ignored.indexOf(message.u._id) > -1; + }, + order: 20, + group: 'menu' + }); + + + }); diff --git a/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js b/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js index 16c425a8a6dd6..33532cb036a9c 100644 --- a/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js +++ b/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js @@ -205,12 +205,11 @@ RocketChat.callbacks.add('afterSaveMessage', function(message, room, userId) { // Don't fetch all users if room exceeds max members const maxMembersForNotification = RocketChat.settings.get('Notifications_Max_Room_Members'); const disableAllMessageNotifications = room.usernames.length > maxMembersForNotification && maxMembersForNotification !== 0; - const subscriptions = RocketChat.models.Subscriptions.findNotificationPreferencesByRoom(room._id, disableAllMessageNotifications); + const subscriptions = RocketChat.models.Subscriptions.findNotificationPreferencesByRoom(room._id, disableAllMessageNotifications) || []; const userIds = []; - subscriptions.forEach((s) => { - userIds.push(s.u._id); - }); + subscriptions.forEach(s => userIds.push(s.u._id)); const users = {}; + RocketChat.models.Users.findUsersByIds(userIds, { fields: { 'settings.preferences': 1 } }).forEach((user) => { users[user._id] = user; }); @@ -223,6 +222,10 @@ RocketChat.callbacks.add('afterSaveMessage', function(message, room, userId) { return; } + if (Array.isArray(subscription.ignored) && subscription.ignored.find(message.u._id)) { + return; + } + const { audioNotifications = RocketChat.getUserPreference(users[subscription.u._id], 'audioNotifications'), desktopNotifications = RocketChat.getUserPreference(users[subscription.u._id], 'desktopNotifications'), diff --git a/packages/rocketchat-lib/server/models/Subscriptions.js b/packages/rocketchat-lib/server/models/Subscriptions.js index 9e585150bf012..116751db301d8 100644 --- a/packages/rocketchat-lib/server/models/Subscriptions.js +++ b/packages/rocketchat-lib/server/models/Subscriptions.js @@ -454,6 +454,21 @@ class ModelSubscriptions extends RocketChat.models._Base { return this.update(query, update, { multi: true }); } + ignoreUser({_id, ignoredUser : ignored, ignore = true}) { + const query = { + _id + }; + const update = { + }; + if (ignore) { + update.$addToSet = { ignored }; + } else { + update.$pull = { ignored }; + } + + return this.update(query, update); + } + setAlertForRoomIdExcludingUserId(roomId, userId) { const query = { rid: roomId, diff --git a/packages/rocketchat-theme/client/imports/components/messages.css b/packages/rocketchat-theme/client/imports/components/messages.css index 16e1b2986988a..1c76d40f33656 100644 --- a/packages/rocketchat-theme/client/imports/components/messages.css +++ b/packages/rocketchat-theme/client/imports/components/messages.css @@ -41,6 +41,23 @@ } .message { + + & .toggle-hidden { + display: none; + } + + &--ignored { + & .body { + display: none; + } + & .toggle-hidden { + display: block; + } + & + .message--ignored.sequential { + display: none; + } + } + &.active { & .message-actions__label { color: var(--rc-color-button-primary); diff --git a/packages/rocketchat-theme/client/imports/general/base_old.css b/packages/rocketchat-theme/client/imports/general/base_old.css index 638e7da8c6fb7..b0b9f26cb94e6 100644 --- a/packages/rocketchat-theme/client/imports/general/base_old.css +++ b/packages/rocketchat-theme/client/imports/general/base_old.css @@ -5384,6 +5384,11 @@ body:not(.is-cordova) { cursor: pointer; } +.toggle-hidden { + cursor: pointer; + font-style: italic; +} + /* kinda hacky, needed in oembedFrageWidget.html */ .rc-old br.only-after-a { diff --git a/packages/rocketchat-ui-flextab/client/tabs/membersList.html b/packages/rocketchat-ui-flextab/client/tabs/membersList.html index 651b3e73f1a5f..d9c415a730356 100644 --- a/packages/rocketchat-ui-flextab/client/tabs/membersList.html +++ b/packages/rocketchat-ui-flextab/client/tabs/membersList.html @@ -37,7 +37,7 @@ {{> avatar username=user.username}}