From 137a36b810a50bfa092d68891d19b3e3851b557c Mon Sep 17 00:00:00 2001 From: mgabdev <> Date: Thu, 3 Dec 2020 17:13:11 -0500 Subject: [PATCH] Progress with DMs Progress with DMs --- .../admin/custom_emojis_controller.rb | 7 +- .../api/v1/chat_conversation_controller.rb | 2 +- .../approved_conversations_controller.rb | 16 ++- .../chat_conversations/messages_controller.rb | 16 +++ .../api/v1/chat_messages_controller.rb | 28 +++-- .../gabsocial/actions/chat_conversations.js | 16 +++ .../gabsocial/actions/chat_messages.js | 34 +++--- app/javascript/gabsocial/actions/streaming.js | 17 ++- .../gabsocial/components/list_item.js | 1 + .../navigation_bar/default_navigation_bar.js | 10 +- .../components/navigation_bar_button.js | 28 +++-- .../chat_conversation_options_popover.js | 113 ++++++++++++++++++ .../popover/chat_message_delete_popover.js | 54 +++++++++ .../components/popover/popover_root.js | 45 ++++--- .../components/sidebar/default_sidebar.js | 5 +- .../components/sidebar_section_item.js | 12 +- app/javascript/gabsocial/constants.js | 2 + .../gabsocial/containers/gabsocial.js | 2 + .../components/chat_conversations_list.js | 3 - .../chat_conversations_list_item.js | 4 +- .../components/chat_message_compose_form.js | 11 +- .../components/chat_message_header.js | 32 +++-- .../messages/components/chat_message_item.js | 36 ++++-- app/javascript/gabsocial/features/ui/ui.js | 2 +- .../features/ui/util/async_components.js | 2 + .../gabsocial/layouts/messages_layout.js | 2 - app/javascript/gabsocial/pages/home_page.js | 8 ++ .../gabsocial/pages/messages_page.js | 15 ++- .../reducers/chat_conversation_messages.js | 6 +- .../gabsocial/reducers/chat_conversations.js | 13 ++ app/javascript/gabsocial/reducers/chats.js | 6 +- app/javascript/gabsocial/stream.js | 1 - app/javascript/styles/global.css | 5 +- app/lib/inline_renderer.rb | 2 + app/models/account_conversation.rb | 7 -- app/models/chat_block.rb | 4 +- app/models/chat_conversation_account.rb | 22 ++-- app/models/chat_message.rb | 15 +-- app/models/chat_mute.rb | 10 +- .../chat_conversation_account_serializer.rb | 6 +- .../rest/chat_message_serializer.rb | 9 ++ app/views/admin/accounts/index.html.haml | 5 - app/views/admin/custom_emojis/index.html.haml | 18 +-- config/routes.rb | 12 +- config/sidekiq.yml | 3 - ...ead_count_to_chat_conversation_accounts.rb | 10 ++ ..._unread_from_chat_conversation_accounts.rb | 5 + ...3211614_add_expires_at_to_chat_messages.rb | 5 + ...ead_count_to_chat_conversation_accounts.rb | 10 ++ ..._to_chat_conversation_accounts_not_null.rb | 5 + ...on_policy_to_chat_conversation_accounts.rb | 5 + db/schema.rb | 6 +- streaming/index.js | 8 +- 53 files changed, 539 insertions(+), 182 deletions(-) create mode 100644 app/javascript/gabsocial/components/popover/chat_conversation_options_popover.js create mode 100644 app/javascript/gabsocial/components/popover/chat_message_delete_popover.js create mode 100644 db/migrate/20201203211403_add_unread_count_to_chat_conversation_accounts.rb create mode 100644 db/migrate/20201203211419_remove_is_unread_from_chat_conversation_accounts.rb create mode 100644 db/migrate/20201203211614_add_expires_at_to_chat_messages.rb create mode 100644 db/migrate/20201203213059_backfill_add_unread_count_to_chat_conversation_accounts.rb create mode 100644 db/migrate/20201203213108_add_unread_count_to_chat_conversation_accounts_not_null.rb create mode 100644 db/migrate/20201203214600_add_chat_message_expiration_policy_to_chat_conversation_accounts.rb diff --git a/app/controllers/admin/custom_emojis_controller.rb b/app/controllers/admin/custom_emojis_controller.rb index 19339bcf..27ce8591 100644 --- a/app/controllers/admin/custom_emojis_controller.rb +++ b/app/controllers/admin/custom_emojis_controller.rb @@ -70,12 +70,7 @@ module Admin end def filter_params - params.permit( - :local, - :remote, - :by_domain, - :shortcode - ) + params.permit(:shortcode) end end end diff --git a/app/controllers/api/v1/chat_conversation_controller.rb b/app/controllers/api/v1/chat_conversation_controller.rb index 31f7feec..9ada4081 100644 --- a/app/controllers/api/v1/chat_conversation_controller.rb +++ b/app/controllers/api/v1/chat_conversation_controller.rb @@ -26,7 +26,7 @@ class Api::V1::ChatConversationController < Api::BaseController end def mark_chat_conversation_unread - @chat_conversation_account.update!(is_unread: true) + @chat_conversation_account.update!(unread_count: 1) render json: @chat_conversation_account, serializer: REST::ChatConversationAccountSerializer end diff --git a/app/controllers/api/v1/chat_conversations/approved_conversations_controller.rb b/app/controllers/api/v1/chat_conversations/approved_conversations_controller.rb index c606c23b..273ac293 100644 --- a/app/controllers/api/v1/chat_conversations/approved_conversations_controller.rb +++ b/app/controllers/api/v1/chat_conversations/approved_conversations_controller.rb @@ -4,22 +4,30 @@ class Api::V1::ChatConversations::ApprovedConversationsController < Api::BaseCon before_action -> { authorize_if_got_token! :read, :'read:chats' } before_action :require_user! + before_action :set_chat_conversation, only: :create after_action :insert_pagination_headers def index - puts "tilly ApprovedConversationsController-0" @chat_conversations = load_chat_conversations render json: @chat_conversations, each_serializer: REST::ChatConversationAccountSerializer end def show - puts "tilly ApprovedConversationsController-1" - @chat_conversations = load_chat_conversations - render json: @chat_conversations, each_serializer: REST::ChatConversationAccountSerializer + render json: @chat_conversation, serializer: REST::ChatConversationAccountSerializer + end + + def unread_count + # : todo : make is_unread into unread_count then count + # count = ChatConversationAccount.where(account: current_account, is_hidden: false, is_approved: true, unread_count: true).count + render json: 1 end private + def set_chat_conversation + @chat_conversation = ChatConversationAccount.where(account: current_account).find(params[:id]).first + end + def load_chat_conversations paginated_chat_conversations end diff --git a/app/controllers/api/v1/chat_conversations/messages_controller.rb b/app/controllers/api/v1/chat_conversations/messages_controller.rb index 579e6af8..7f3fa684 100644 --- a/app/controllers/api/v1/chat_conversations/messages_controller.rb +++ b/app/controllers/api/v1/chat_conversations/messages_controller.rb @@ -15,6 +15,22 @@ class Api::V1::ChatConversations::MessagesController < Api::BaseController render json: @chats, each_serializer: REST::ChatMessageSerializer end + def destroy_all + puts "tilly destry all chat" + # : todo : + # check if is pro + # @chat = ChatMessage.where(from_account: current_user.account).find(params[:id]) + + puts "tilly @chat: " + @chat.inspect + + # : todo : + # make sure last_chat_message_id in chat_account_conversation gets set to last + + # @chat.destroy! + + # render json: @chat, serializer: REST::ChatMessageSerializer + end + private def set_chat_conversation diff --git a/app/controllers/api/v1/chat_messages_controller.rb b/app/controllers/api/v1/chat_messages_controller.rb index 8b37b642..22c7dec3 100644 --- a/app/controllers/api/v1/chat_messages_controller.rb +++ b/app/controllers/api/v1/chat_messages_controller.rb @@ -5,25 +5,33 @@ class Api::V1::ChatMessagesController < Api::BaseController before_action -> { doorkeeper_authorize! :write, :'write:chats' } before_action :require_user! - before_action :set_chat_conversation + before_action :set_chat_conversation, only: :create + before_action :set_chat_conversation_recipients, only: :create def create @chat = ChatMessage.create!( from_account: current_account, chat_conversation: @chat_conversation, - text: params[:text] + text: ActionController::Base.helpers.strip_tags(params[:text]) ) - + # : todo : - # Redis.current.publish("chat_messages:10", 'hi') - Redis.current.publish("chat_messages:10", Oj.dump(event: :chat_message, payload: InlineRenderer.render(@chat, current_user.account, :chat_message))) + # check if blocked + + @chat_conversation_recipients.each do |account| + payload = InlineRenderer.render(@chat, account, :chat_message) + Redis.current.publish("chat_messages:#{account.id}", Oj.dump(event: :notification, payload: payload)) + end render json: @chat, serializer: REST::ChatMessageSerializer end def destroy - @chat = ChatMessage.where(account: current_user.account).find(params[:id]) - authorize @chat, :destroy? + puts "tilly destry chat" + + @chat = ChatMessage.where(from_account: current_user.account).find(params[:id]) + + puts "tilly @chat: " + @chat.inspect # : todo : # make sure last_chat_message_id in chat_account_conversation gets set to last @@ -39,6 +47,12 @@ class Api::V1::ChatMessagesController < Api::BaseController @chat_conversation = ChatConversation.find(params[:chat_conversation_id]) end + def set_chat_conversation_recipients + account_conversation = ChatConversationAccount.where(account: current_user.account, chat_conversation: @chat_conversation).first + puts "tilly account_conversation - " + account_conversation.inspect + @chat_conversation_recipients = Account.where(id: account_conversation.participant_account_ids) + end + def chat_params params.permit(:text, :chat_conversation_id) end diff --git a/app/javascript/gabsocial/actions/chat_conversations.js b/app/javascript/gabsocial/actions/chat_conversations.js index 4a594ac3..fc8051e5 100644 --- a/app/javascript/gabsocial/actions/chat_conversations.js +++ b/app/javascript/gabsocial/actions/chat_conversations.js @@ -13,6 +13,8 @@ export const CHAT_CONVERSATIONS_APPROVED_EXPAND_REQUEST = 'CHAT_CONVERSATIONS_AP export const CHAT_CONVERSATIONS_APPROVED_EXPAND_SUCCESS = 'CHAT_CONVERSATIONS_APPROVED_EXPAND_SUCCESS' export const CHAT_CONVERSATIONS_APPROVED_EXPAND_FAIL = 'CHAT_CONVERSATIONS_APPROVED_EXPAND_FAIL' +export const CHAT_CONVERSATION_APPROVED_UNREAD_COUNT_FETCH_SUCCESS = 'CHAT_CONVERSATIONS_APPROVED_EXPAND_FAIL' + // export const CHAT_CONVERSATIONS_CREATE_REQUEST = 'CHAT_CONVERSATIONS_CREATE_REQUEST' @@ -437,6 +439,20 @@ export const fetchChatConversationRequestedCount = () => (dispatch, getState) => }) } +/** + * + */ +export const fetchChatConversationUnreadCount = () => (dispatch, getState) => { + if (!me) return + + api(getState).get('/api/v1/chat_conversations/approved_conversations/unread_count').then(response => { + dispatch({ + type: CHAT_CONVERSATION_APPROVED_UNREAD_COUNT_FETCH_SUCCESS, + count: response.data, + }) + }) +} + /** * */ diff --git a/app/javascript/gabsocial/actions/chat_messages.js b/app/javascript/gabsocial/actions/chat_messages.js index 3c89cac0..038e2710 100644 --- a/app/javascript/gabsocial/actions/chat_messages.js +++ b/app/javascript/gabsocial/actions/chat_messages.js @@ -19,7 +19,7 @@ export const sendChatMessage = (text = '', chatConversationId) => (dispatch, get if (!me || !chatConversationId) return if (text.length === 0) return - dispatch(sendMessageRequest()) + dispatch(sendChatMessageRequest(chatConversationId)) api(getState).post('/api/v1/chat_messages', { text, @@ -30,23 +30,23 @@ export const sendChatMessage = (text = '', chatConversationId) => (dispatch, get // }, }).then((response) => { dispatch(importFetchedChatMessages([response.data])) - dispatch(sendMessageSuccess(response.data, chatConversationId)) + dispatch(sendChatMessageSuccess(response.data)) }).catch((error) => { - dispatch(sendMessageFail(error)) + dispatch(sendChatMessageFail(error)) }) } -const sendMessageRequest = () => ({ +const sendChatMessageRequest = (chatConversationId) => ({ type: CHAT_MESSAGES_SEND_REQUEST, -}) - -const sendMessageSuccess = (chatMessage, chatConversationId) => ({ - type: CHAT_MESSAGES_SEND_SUCCESS, - chatMessage, chatConversationId, }) -const sendMessageFail = (error) => ({ +export const sendChatMessageSuccess = (chatMessage) => ({ + type: CHAT_MESSAGES_SEND_SUCCESS, + chatMessage, +}) + +const sendChatMessageFail = (error) => ({ type: CHAT_MESSAGES_SEND_FAIL, error, }) @@ -54,32 +54,32 @@ const sendMessageFail = (error) => ({ /** * */ -const deleteMessage = (chatMessageId) => (dispatch, getState) => { +export const deleteChatMessage = (chatMessageId) => (dispatch, getState) => { if (!me || !chatMessageId) return - dispatch(deleteMessageRequest(chatMessageId)) + dispatch(deleteChatMessageRequest(chatMessageId)) api(getState).delete(`/api/v1/chat_messages/${chatMessageId}`, {}, { // headers: { // 'Idempotency-Key': getState().getIn(['chat_compose', 'idempotencyKey']), // }, }).then((response) => { - deleteMessageSuccess(response) + dispatch(deleteChatMessageSuccess(response.data)) }).catch((error) => { - dispatch(deleteMessageFail(error)) + dispatch(deleteChatMessageFail(error)) }) } -const deleteMessageRequest = (chatMessageId) => ({ +const deleteChatMessageRequest = (chatMessageId) => ({ type: CHAT_MESSAGES_DELETE_REQUEST, chatMessageId, }) -const deleteMessageSuccess = () => ({ +const deleteChatMessageSuccess = () => ({ type: CHAT_MESSAGES_DELETE_SUCCESS, }) -const deleteMessageFail = (error) => ({ +const deleteChatMessageFail = (error) => ({ type: CHAT_MESSAGES_DELETE_FAIL, error, }) \ No newline at end of file diff --git a/app/javascript/gabsocial/actions/streaming.js b/app/javascript/gabsocial/actions/streaming.js index 592b9e51..6ef58d25 100644 --- a/app/javascript/gabsocial/actions/streaming.js +++ b/app/javascript/gabsocial/actions/streaming.js @@ -6,6 +6,7 @@ import { updateTimelineQueue, } from './timelines' import { updateNotificationsQueue } from './notifications' +import { sendChatMessageSuccess } from './chat_messages' import { fetchFilters } from './filters' import { getLocale } from '../locales' import { handleComposeSubmit } from './compose' @@ -76,17 +77,15 @@ export const connectUserStream = () => connectTimelineStream('home', 'user') * */ export const connectChatMessagesStream = (accountId) => { - return connectStream(`chat_messages:${accountId}`, null, (dispatch, getState) => { + return connectStream(`chat_messages`, null, (dispatch, getState) => { return { - onConnect() { - // console.log("chat messages connected") - }, - onDisconnect() { - // console.log("chat messages disconnected") - }, + onConnect() {}, + onDisconnect() {}, onReceive (data) { - // : todo : - console.log("chat messages onReceive:", data) + if (!data['event'] || !data['payload']) return + if (data.event === 'notification') { + dispatch(sendChatMessageSuccess(JSON.parse(data.payload))) + } }, } }) diff --git a/app/javascript/gabsocial/components/list_item.js b/app/javascript/gabsocial/components/list_item.js index 357db825..c95f0cf3 100644 --- a/app/javascript/gabsocial/components/list_item.js +++ b/app/javascript/gabsocial/components/list_item.js @@ -81,6 +81,7 @@ class ListItem extends React.PureComponent { const textContainerClasses = CX({ d: 1, pr5: 1, + w100PC: hideArrow, maxW100PC42PX: !hideArrow || showActive, }) diff --git a/app/javascript/gabsocial/components/navigation_bar/default_navigation_bar.js b/app/javascript/gabsocial/components/navigation_bar/default_navigation_bar.js index 81e49b49..21269845 100644 --- a/app/javascript/gabsocial/components/navigation_bar/default_navigation_bar.js +++ b/app/javascript/gabsocial/components/navigation_bar/default_navigation_bar.js @@ -67,6 +67,8 @@ class DefaultNavigationBar extends ImmutablePureComponent { account, noActions, logoDisabled, + unreadChatsCount, + notificationCount, } = this.props const navigationContainerClasses = CX({ @@ -171,7 +173,8 @@ class DefaultNavigationBar extends ImmutablePureComponent {
-