From 4cdbef2ce27bb85a714d22ddac4edd8864262687 Mon Sep 17 00:00:00 2001 From: Gabriel Jablonski Date: Mon, 24 Nov 2025 14:23:05 -0300 Subject: [PATCH] fix: toggle typing status edge cases (#151) * fix: do not toggle typing status when typing private message * feat: toggle typing status off when sending message * Revert "fix: do not toggle typing status when typing private message" This reverts commit 3c74b7c5df0960be37c3e8726c2538ae8ebc4d60. * fix: ensure typing off event is triggered for all message types * fix: add success status expectation for typing off events in message controller specs * fix: ensure typing off event is dispatched correctly for both private and non-private messages --- .../conversations/messages_controller.rb | 11 ++++++++ .../conversations/messages_controller_spec.rb | 28 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/app/controllers/api/v1/accounts/conversations/messages_controller.rb b/app/controllers/api/v1/accounts/conversations/messages_controller.rb index 67381a715..40a5d8664 100644 --- a/app/controllers/api/v1/accounts/conversations/messages_controller.rb +++ b/app/controllers/api/v1/accounts/conversations/messages_controller.rb @@ -1,4 +1,6 @@ class Api::V1::Accounts::Conversations::MessagesController < Api::V1::Accounts::Conversations::BaseController + include Events::Types + before_action :ensure_api_inbox, only: :update def index @@ -9,6 +11,8 @@ class Api::V1::Accounts::Conversations::MessagesController < Api::V1::Accounts:: user = Current.user || @resource mb = Messages::MessageBuilder.new(user, @conversation, params) @message = mb.perform + + trigger_typing_event(CONVERSATION_TYPING_OFF) rescue StandardError => e render_could_not_create_error(e.message) end @@ -77,4 +81,11 @@ class Api::V1::Accounts::Conversations::MessagesController < Api::V1::Accounts:: # Only API inboxes can update messages render json: { error: 'Message status update is only allowed for API inboxes' }, status: :forbidden unless @conversation.inbox.api? end + + def trigger_typing_event(event) + user = Current.user || @resource + return unless user.is_a?(User) + + Rails.configuration.dispatcher.dispatch(event, Time.zone.now, conversation: @conversation, user: user, is_private: params[:private]) + end end diff --git a/spec/controllers/api/v1/accounts/conversations/messages_controller_spec.rb b/spec/controllers/api/v1/accounts/conversations/messages_controller_spec.rb index f7ff042e5..ce19e24bc 100644 --- a/spec/controllers/api/v1/accounts/conversations/messages_controller_spec.rb +++ b/spec/controllers/api/v1/accounts/conversations/messages_controller_spec.rb @@ -81,6 +81,34 @@ RSpec.describe 'Conversation Messages API', type: :request do expect(conversation.messages.last.attachments.first.file_type).to eq('image') end + it 'triggers typing off event for non-private messages' do + params = { content: 'test-message', private: false } + allow(Rails.configuration.dispatcher).to receive(:dispatch) + .with('conversation.typing_off', kind_of(Time), hash_including(conversation: conversation, user: agent, is_private: false)) + + post api_v1_account_conversation_messages_url(account_id: account.id, conversation_id: conversation.display_id), + params: params, + headers: agent.create_new_auth_token, + as: :json + + expect(response).to have_http_status(:success) + expect(Rails.configuration.dispatcher).to have_received(:dispatch) + end + + it 'triggers typing off event for private messages' do + params = { content: 'test-message', private: true } + allow(Rails.configuration.dispatcher).to receive(:dispatch).with('conversation.typing_off', kind_of(Time), + hash_including(conversation: conversation, user: agent, is_private: true)) + + post api_v1_account_conversation_messages_url(account_id: account.id, conversation_id: conversation.display_id), + params: params, + headers: agent.create_new_auth_token, + as: :json + + expect(response).to have_http_status(:success) + expect(Rails.configuration.dispatcher).to have_received(:dispatch) + end + context 'when api inbox' do let(:api_channel) { create(:channel_api, account: account) } let(:api_inbox) { create(:inbox, channel: api_channel, account: account) }