diff --git a/app/assets/stylesheets/chat.scss b/app/assets/stylesheets/chat.scss index da4cae04f..4dc9f7740 100644 --- a/app/assets/stylesheets/chat.scss +++ b/app/assets/stylesheets/chat.scss @@ -1287,3 +1287,22 @@ .active__message__list { background: var(--theme-container-accent-background, #f5f6f7); } +.chatmessage__action { + &:hover { + background: none; + } + + .chatmessage__bodytext { + margin: 0; + font-size: 12px; + font-style: italic; + color: var(--card-color-tertiary); + a { + text-decoration: none; + color: var(--card-color-tertiary); + &:hover { + text-decoration: underline; + } + } + } +} diff --git a/app/controllers/chat_channel_memberships_controller.rb b/app/controllers/chat_channel_memberships_controller.rb index fcb664783..6f80921c8 100644 --- a/app/controllers/chat_channel_memberships_controller.rb +++ b/app/controllers/chat_channel_memberships_controller.rb @@ -1,5 +1,6 @@ class ChatChannelMembershipsController < ApplicationController after_action :verify_authorized + include MessagesHelper def index skip_authorization @@ -46,6 +47,7 @@ class ChatChannelMembershipsController < ApplicationController @chat_channel_membership.destroy flash[:settings_notice] = "Invitation removed." else + send_chat_action_message("@#{current_user.username} removed @#{@chat_channel_membership.user.username} from #{@chat_channel_membership.channel_name}", current_user, @chat_channel_membership.chat_channel_id, "removed_from_channel") @chat_channel_membership.update(status: "removed_from_channel") flash[:settings_notice] = "Removed #{@chat_channel_membership.user.name}" end @@ -69,6 +71,7 @@ class ChatChannelMembershipsController < ApplicationController @chat_channel_membership = ChatChannelMembership.find(params[:id]) authorize @chat_channel_membership channel_name = @chat_channel_membership.chat_channel.channel_name + send_chat_action_message("@#{current_user.username} left #{@chat_channel_membership.channel_name}", current_user, @chat_channel_membership.chat_channel_id, "left_channel") @chat_channel_membership.update(status: "left_channel") @chat_channels_memberships = [] flash[:settings_notice] = "You have left the channel #{channel_name}. It may take a moment to be removed from your list." @@ -85,6 +88,7 @@ class ChatChannelMembershipsController < ApplicationController if permitted_params[:user_action] == "accept" @chat_channel_membership.update(status: "active") channel_name = @chat_channel_membership.chat_channel.channel_name + send_chat_action_message("@#{current_user.username} joined #{@chat_channel_membership.channel_name}", current_user, @chat_channel_membership.chat_channel_id, "joined") flash[:settings_notice] = "Invitation to #{channel_name} accepted. It may take a moment to show up in your list." else @chat_channel_membership.update(status: "rejected") @@ -92,4 +96,10 @@ class ChatChannelMembershipsController < ApplicationController end redirect_to chat_channel_memberships_path end + + def send_chat_action_message(message, user, channel_id, action) + temp_message_id = (0...20).map { ("a".."z").to_a[rand(8)] }.join + message = Message.create("message_markdown" => message, "user_id" => user.id, "chat_channel_id" => channel_id, "chat_action" => action) + pusher_message_created(false, message, temp_message_id) + end end diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb index f8ffb2612..02645ad9f 100644 --- a/app/controllers/messages_controller.rb +++ b/app/controllers/messages_controller.rb @@ -1,6 +1,7 @@ class MessagesController < ApplicationController before_action :set_message, only: %i[destroy update] before_action :authenticate_user!, only: %i[create] + include MessagesHelper def create @message = Message.new(message_params) @@ -9,9 +10,9 @@ class MessagesController < ApplicationController authorize @message # sending temp message only to sender - pusher_message_created(true) + pusher_message_created(true, @message, @temp_message_id) if @message.save - pusher_message_created(false) + pusher_message_created(false, @message, @temp_message_id) notify_users(@message.chat_channel.channel_users_ids, "all") notify_users(@mentioned_users_id, "mention") render json: { status: "success", message: { temp_id: @temp_message_id, id: @message.id } }, status: :created @@ -79,30 +80,6 @@ class MessagesController < ApplicationController private - def create_pusher_payload(new_message, temp_id) - payload = { - temp_id: temp_id, - id: new_message.id, - user_id: new_message.user.id, - chat_channel_id: new_message.chat_channel.id, - chat_channel_adjusted_slug: new_message.chat_channel.adjusted_slug(current_user, "sender"), - channel_type: new_message.chat_channel.channel_type, - username: new_message.user.username, - profile_image_url: ProfileImage.new(new_message.user).get(width: 90), - message: new_message.message_html, - markdown: new_message.message_markdown, - edited_at: new_message.edited_at, - timestamp: Time.current, - color: new_message.preferred_user_color, - reception_method: "pushed" - } - - if new_message.chat_channel.group? - payload[:chat_channel_adjusted_slug] = new_message.chat_channel.adjusted_slug - end - payload.to_json - end - def message_params @mentioned_users_id = params[:message][:mentioned_users_id] params.require(:message).permit(:message_markdown, :user_id, :chat_channel_id) @@ -127,21 +104,6 @@ class MessagesController < ApplicationController end end - def pusher_message_created(is_single) - return unless @message.valid? - - begin - message_json = create_pusher_payload(@message, @temp_message_id) - if is_single - Pusher.trigger("private-message-notifications-#{@message.user_id}", "message-created", message_json) - else - Pusher.trigger(@message.chat_channel.pusher_channels, "message-created", message_json) - end - rescue Pusher::Error => e - logger.info "PUSHER ERROR: #{e.message}" - end - end - def notify_users(user_ids, type) return unless user_ids diff --git a/app/helpers/messages_helper.rb b/app/helpers/messages_helper.rb new file mode 100644 index 000000000..2e74b942c --- /dev/null +++ b/app/helpers/messages_helper.rb @@ -0,0 +1,41 @@ +module MessagesHelper + def create_pusher_payload(new_message, temp_id) + payload = { + temp_id: temp_id, + id: new_message.id, + user_id: new_message.user.id, + chat_channel_id: new_message.chat_channel.id, + chat_channel_adjusted_slug: new_message.chat_channel.adjusted_slug(current_user, "sender"), + channel_type: new_message.chat_channel.channel_type, + username: new_message.user.username, + profile_image_url: ProfileImage.new(new_message.user).get(width: 90), + message: new_message.message_html, + markdown: new_message.message_markdown, + edited_at: new_message.edited_at, + timestamp: Time.current, + color: new_message.preferred_user_color, + reception_method: "pushed", + action: new_message.chat_action + } + + if new_message.chat_channel.group? + payload[:chat_channel_adjusted_slug] = new_message.chat_channel.adjusted_slug + end + payload.to_json + end + + def pusher_message_created(is_single, message, temp_message_id) + return unless message.valid? + + begin + message_json = create_pusher_payload(message, temp_message_id) + if is_single + Pusher.trigger("private-message-notifications-#{message.user_id}", "message-created", message_json) + else + Pusher.trigger(message.chat_channel.pusher_channels, "message-created", message_json) + end + rescue Pusher::Error => e + logger.info "PUSHER ERROR: #{e.message}" + end + end +end diff --git a/app/javascript/chat/actionMessage.jsx b/app/javascript/chat/actionMessage.jsx new file mode 100644 index 000000000..a54f92a89 --- /dev/null +++ b/app/javascript/chat/actionMessage.jsx @@ -0,0 +1,90 @@ +import { h } from 'preact'; +import PropTypes from 'prop-types'; +import { adjustTimestamp } from './util'; + +const ActionMessage = ({ + user, + message, + color, + timestamp, + profileImageUrl, + onContentTrigger, +}) => { + const spanStyle = { color }; + + const messageArea = ( + + ); + + return ( +