Skip to content

Commit bc0c1b1

Browse files
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.
1 parent 8e5b67d commit bc0c1b1

File tree

4 files changed

+158
-0
lines changed

4 files changed

+158
-0
lines changed

lib/stream-chat/channel.rb

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,42 @@ 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+
# @param [String] parent_id Optional parent message ID for thread drafts
368+
# @return [StreamChat::StreamResponse]
369+
sig { params(message: StringKeyHash, user_id: String).returns(StreamChat::StreamResponse) }
370+
def create_draft(message, user_id)
371+
payload = { message: add_user_id(message, user_id) }
372+
@client.post("#{url}/draft", data: payload)
373+
end
374+
375+
# Deletes a draft message for this channel.
376+
#
377+
# @param [String] user_id The ID of the user deleting the draft
378+
# @param [String] parent_id Optional parent message ID for thread drafts
379+
# @return [StreamChat::StreamResponse]
380+
sig { params(user_id: String, parent_id: T.nilable(String)).returns(StreamChat::StreamResponse) }
381+
def delete_draft(user_id, parent_id: nil)
382+
params = { user_id: user_id }
383+
params[:parent_id] = parent_id if parent_id
384+
@client.delete("#{url}/draft", params: params)
385+
end
386+
387+
# Gets a draft message for this channel.
388+
#
389+
# @param [String] user_id The ID of the user getting the draft
390+
# @param [String] parent_id Optional parent message ID for thread drafts
391+
# @return [StreamChat::StreamResponse]
392+
sig { params(user_id: String, parent_id: T.nilable(String)).returns(StreamChat::StreamResponse) }
393+
def get_draft(user_id, parent_id: nil)
394+
params = { user_id: user_id }
395+
params[:parent_id] = parent_id if parent_id
396+
@client.get("#{url}/draft", params: params)
397+
end
398+
363399
private
364400

365401
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
@@ -790,6 +790,22 @@ def create_command(command)
790790
post('commands', data: command)
791791
end
792792

793+
# Queries draft messages for the current user.
794+
#
795+
# @param [String] user_id The ID of the user to query drafts for
796+
# @param [StringKeyHash] filter Optional filter conditions for the query
797+
# @param [Array] sort Optional sort parameters
798+
# @param [Hash] options Additional query options
799+
# @return [StreamChat::StreamResponse]
800+
sig { params(user_id: String, filter: T.nilable(StringKeyHash), sort: T.nilable(T::Array[StringKeyHash]), options: T.untyped).returns(StreamChat::StreamResponse) }
801+
def query_drafts(user_id, filter: nil, sort: nil, **options)
802+
data = { user_id: user_id }
803+
data['filter'] = filter if filter
804+
data['sort'] = sort if sort
805+
data.merge!(options) if options
806+
post('drafts/query', data: data)
807+
end
808+
793809
# Gets a comamnd.
794810
sig { params(name: String).returns(StreamChat::StreamResponse) }
795811
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
@@ -788,6 +788,51 @@ def loop_times(times)
788788
list_resp = @client.list_imports({ limit: 1 })
789789
expect(list_resp['import_tasks'].length).to eq 1
790790
end
791+
792+
it 'can query drafts' do
793+
# Create multiple drafts in different channels
794+
draft1 = { 'text' => 'Draft in channel 1' }
795+
@channel.create_draft(draft1, @random_user[:id])
796+
797+
# Create another channel with a draft
798+
channel2 = @client.channel('messaging', data: {'members' => @random_users.map { |u| u[:id] } })
799+
channel2.create(@random_user[:id])
800+
801+
draft2 = { 'text' => 'Draft in channel 2' }
802+
channel2.create_draft(draft2, @random_user[:id])
803+
804+
# Sort by created_at
805+
sort = [{ 'field' => 'created_at', 'direction' => 1 }]
806+
response = @client.query_drafts(@random_user[:id], sort: sort)
807+
expect(response['drafts']).not_to be_empty
808+
expect(response['drafts'].length).to eq(2)
809+
expect(response['drafts'][0]['channel']['id']).to eq(@channel.id)
810+
expect(response['drafts'][1]['channel']['id']).to eq(channel2.id)
811+
812+
# Query for a specific channel
813+
response = @client.query_drafts(@random_user[:id], filter: { 'channel_cid' => @channel.cid })
814+
expect(response['drafts']).not_to be_empty
815+
expect(response['drafts'].length).to eq(1)
816+
expect(response['drafts'][0]['channel']['id']).to eq(@channel.id)
817+
818+
# Query all drafts for the user
819+
response = @client.query_drafts(@random_user[:id])
820+
expect(response['drafts']).not_to be_empty
821+
expect(response['drafts'].length).to eq(2)
822+
823+
# Paginate
824+
response = @client.query_drafts(@random_user[:id], sort: sort, limit: 1)
825+
expect(response['drafts']).not_to be_empty
826+
expect(response['drafts'].length).to eq(1)
827+
expect(response['drafts'][0]['channel']['id']).to eq(@channel.id)
828+
829+
# Cleanup
830+
begin
831+
channel2.delete
832+
rescue StandardError
833+
# Ignore errors if channel is already deleted
834+
end
835+
end
791836
end
792837

793838
describe 'permissions' do

0 commit comments

Comments
 (0)