Skip to content

Commit c7bccb3

Browse files
[CHA-610] Draft messages (#161)
* feat: add deactivate_users method to StreamChat client and corresponding tests * feat: implement draft message management in StreamChat - Added methods to create, get, and delete draft messages in the Channel class. - Introduced a method to query draft messages in the Client class. - Added corresponding tests for draft message functionality in channel_spec.rb and client_spec.rb. * removed unwanted changes * rubocop corrections * chore: removed unwanted changes * chore: removed unwanted file changes * chore: removed unwanted rdoc comment
1 parent 18981d0 commit c7bccb3

File tree

4 files changed

+157
-0
lines changed

4 files changed

+157
-0
lines changed

lib/stream-chat/channel.rb

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,41 @@ def delete_image(url)
360360
@client.delete("#{self.url}/image", params: { url: url })
361361
end
362362

363+
# Creates or updates a draft message for this channel.
364+
#
365+
# @param [StringKeyHash] message The draft message content
366+
# @param [String] user_id The ID of the user creating/updating the draft
367+
# @return [StreamChat::StreamResponse]
368+
sig { params(message: StringKeyHash, user_id: String).returns(StreamChat::StreamResponse) }
369+
def create_draft(message, user_id)
370+
payload = { message: add_user_id(message, user_id) }
371+
@client.post("#{url}/draft", data: payload)
372+
end
373+
374+
# Deletes a draft message for this channel.
375+
#
376+
# @param [String] user_id The ID of the user deleting the draft
377+
# @param [String] parent_id Optional parent message ID for thread drafts
378+
# @return [StreamChat::StreamResponse]
379+
sig { params(user_id: String, parent_id: T.nilable(String)).returns(StreamChat::StreamResponse) }
380+
def delete_draft(user_id, parent_id: nil)
381+
params = { user_id: user_id }
382+
params[:parent_id] = parent_id if parent_id
383+
@client.delete("#{url}/draft", params: params)
384+
end
385+
386+
# Gets a draft message for this channel.
387+
#
388+
# @param [String] user_id The ID of the user getting the draft
389+
# @param [String] parent_id Optional parent message ID for thread drafts
390+
# @return [StreamChat::StreamResponse]
391+
sig { params(user_id: String, parent_id: T.nilable(String)).returns(StreamChat::StreamResponse) }
392+
def get_draft(user_id, parent_id: nil)
393+
params = { user_id: user_id }
394+
params[:parent_id] = parent_id if parent_id
395+
@client.get("#{url}/draft", params: params)
396+
end
397+
363398
private
364399

365400
sig { params(payload: StringKeyHash, user_id: String).returns(StringKeyHash) }

lib/stream-chat/client.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -783,6 +783,22 @@ def create_command(command)
783783
post('commands', data: command)
784784
end
785785

786+
# Queries draft messages for the current user.
787+
#
788+
# @param [String] user_id The ID of the user to query drafts for
789+
# @param [StringKeyHash] filter Optional filter conditions for the query
790+
# @param [Array] sort Optional sort parameters
791+
# @param [Hash] options Additional query options
792+
# @return [StreamChat::StreamResponse]
793+
sig { params(user_id: String, filter: T.nilable(StringKeyHash), sort: T.nilable(T::Array[StringKeyHash]), options: T.untyped).returns(StreamChat::StreamResponse) }
794+
def query_drafts(user_id, filter: nil, sort: nil, **options)
795+
data = { user_id: user_id }
796+
data['filter'] = filter if filter
797+
data['sort'] = sort if sort
798+
data.merge!(options) if options
799+
post('drafts/query', data: data)
800+
end
801+
786802
# Gets a comamnd.
787803
sig { params(name: String).returns(StreamChat::StreamResponse) }
788804
def get_command(name)

spec/channel_spec.rb

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,4 +430,65 @@ def loop_times(times)
430430
# Verify the custom field was unset
431431
expect(updated_msg['message']).not_to include 'custom_field'
432432
end
433+
434+
it 'can create draft message' do
435+
draft_message = { 'text' => 'This is a draft message' }
436+
response = @channel.create_draft(draft_message, @random_user[:id])
437+
438+
expect(response).to include 'draft'
439+
expect(response['draft']['message']['text']).to eq 'This is a draft message'
440+
expect(response['draft']['channel_cid']).to eq @channel.cid
441+
end
442+
443+
it 'can get draft message' do
444+
# First create a draft
445+
draft_message = { 'text' => 'This is a draft to retrieve' }
446+
@channel.create_draft(draft_message, @random_user[:id])
447+
448+
# Then get the draft
449+
response = @channel.get_draft(@random_user[:id])
450+
451+
expect(response).to include 'draft'
452+
expect(response['draft']['message']['text']).to eq 'This is a draft to retrieve'
453+
expect(response['draft']['channel_cid']).to eq @channel.cid
454+
end
455+
456+
it 'can delete draft message' do
457+
# First create a draft
458+
draft_message = { 'text' => 'This is a draft to delete' }
459+
@channel.create_draft(draft_message, @random_user[:id])
460+
461+
# Then delete the draft
462+
@channel.delete_draft(@random_user[:id])
463+
464+
# Verify it's deleted by trying to get it
465+
expect { @channel.get_draft(@random_user[:id]) }.to raise_error(StreamChat::StreamAPIException)
466+
end
467+
468+
it 'can create and manage thread draft' do
469+
# First create a parent message
470+
msg = @channel.send_message({ 'text' => 'Parent message' }, @random_user[:id])
471+
parent_id = msg['message']['id']
472+
473+
# Create a draft reply
474+
draft_reply = { 'text' => 'This is a draft reply', 'parent_id' => parent_id }
475+
response = @channel.create_draft(draft_reply, @random_user[:id])
476+
477+
expect(response).to include 'draft'
478+
expect(response['draft']['message']['text']).to eq 'This is a draft reply'
479+
expect(response['draft']['parent_id']).to eq parent_id
480+
481+
# Get the draft reply
482+
response = @channel.get_draft(@random_user[:id], parent_id: parent_id)
483+
484+
expect(response).to include 'draft'
485+
expect(response['draft']['message']['text']).to eq 'This is a draft reply'
486+
expect(response['draft']['parent_id']).to eq parent_id
487+
488+
# Delete the draft reply
489+
@channel.delete_draft(@random_user[:id], parent_id: parent_id)
490+
491+
# Verify it's deleted
492+
expect { @channel.get_draft(@random_user[:id], parent_id: parent_id) }.to raise_error(StreamChat::StreamAPIException)
493+
end
433494
end

spec/client_spec.rb

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -782,6 +782,51 @@ def loop_times(times)
782782
list_resp = @client.list_imports({ limit: 1 })
783783
expect(list_resp['import_tasks'].length).to eq 1
784784
end
785+
786+
it 'can query drafts' do
787+
# Create multiple drafts in different channels
788+
draft1 = { 'text' => 'Draft in channel 1' }
789+
@channel.create_draft(draft1, @random_user[:id])
790+
791+
# Create another channel with a draft
792+
channel2 = @client.channel('messaging', data: { 'members' => @random_users.map { |u| u[:id] } })
793+
channel2.create(@random_user[:id])
794+
795+
draft2 = { 'text' => 'Draft in channel 2' }
796+
channel2.create_draft(draft2, @random_user[:id])
797+
798+
# Sort by created_at
799+
sort = [{ 'field' => 'created_at', 'direction' => 1 }]
800+
response = @client.query_drafts(@random_user[:id], sort: sort)
801+
expect(response['drafts']).not_to be_empty
802+
expect(response['drafts'].length).to eq(2)
803+
expect(response['drafts'][0]['channel']['id']).to eq(@channel.id)
804+
expect(response['drafts'][1]['channel']['id']).to eq(channel2.id)
805+
806+
# Query for a specific channel
807+
response = @client.query_drafts(@random_user[:id], filter: { 'channel_cid' => @channel.cid })
808+
expect(response['drafts']).not_to be_empty
809+
expect(response['drafts'].length).to eq(1)
810+
expect(response['drafts'][0]['channel']['id']).to eq(@channel.id)
811+
812+
# Query all drafts for the user
813+
response = @client.query_drafts(@random_user[:id])
814+
expect(response['drafts']).not_to be_empty
815+
expect(response['drafts'].length).to eq(2)
816+
817+
# Paginate
818+
response = @client.query_drafts(@random_user[:id], sort: sort, limit: 1)
819+
expect(response['drafts']).not_to be_empty
820+
expect(response['drafts'].length).to eq(1)
821+
expect(response['drafts'][0]['channel']['id']).to eq(@channel.id)
822+
823+
# Cleanup
824+
begin
825+
channel2.delete
826+
rescue StandardError
827+
# Ignore errors if channel is already deleted
828+
end
829+
end
785830
end
786831

787832
describe 'permissions' do

0 commit comments

Comments
 (0)