diff --git a/CHANGELOG.md b/CHANGELOG.md index ea114c339..33ede5150 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,33 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [8.35.0](https://github.com/GetStream/stream-chat-js/compare/v8.34.0...v8.35.0) (2024-06-06) + + +### Features + +* list of blocked users should be returned while connecting user ([#1318](https://github.com/GetStream/stream-chat-js/issues/1318)) ([415f9c7](https://github.com/GetStream/stream-chat-js/commit/415f9c7317ac7f87a874ce3b8bc8bc6c13ce8916)) + + +### Bug Fixes + +* fix blockuser() vars naming ([#1316](https://github.com/GetStream/stream-chat-js/issues/1316)) ([d06acaa](https://github.com/GetStream/stream-chat-js/commit/d06acaa2369d120ca08407f58400970a85d749ae)) + +## [8.34.0](https://github.com/GetStream/stream-chat-js/compare/v8.33.1...v8.34.0) (2024-06-04) + + +### Features + +* block user endpoints ([#1314](https://github.com/GetStream/stream-chat-js/issues/1314)) ([1be14f7](https://github.com/GetStream/stream-chat-js/commit/1be14f7ee928201511737240d59dec0eb8d37b48)) + +### [8.33.1](https://github.com/GetStream/stream-chat-js/compare/v8.33.0...v8.33.1) (2024-06-03) + + +### Bug Fixes + +* update quoted message references on message.updated and message.deleted events ([#1310](https://github.com/GetStream/stream-chat-js/issues/1310)) ([6c4e29a](https://github.com/GetStream/stream-chat-js/commit/6c4e29a01716c9b46c53de4e6fda370e5f731716)) +* wrong sort field names ([#1308](https://github.com/GetStream/stream-chat-js/issues/1308)) ([a361ee7](https://github.com/GetStream/stream-chat-js/commit/a361ee7286e32948487b46a9c16e0ee6b82c367d)) + ## [8.33.0](https://github.com/GetStream/stream-chat-js/compare/v8.32.0...v8.33.0) (2024-05-17) diff --git a/package.json b/package.json index 88d83397a..97deb738a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "stream-chat", - "version": "8.33.0", + "version": "8.35.0", "description": "JS SDK for the Stream Chat API", "author": "GetStream", "homepage": "https://getstream.io/chat/", diff --git a/src/channel.ts b/src/channel.ts index 5ffb0bcb9..75905bf08 100644 --- a/src/channel.ts +++ b/src/channel.ts @@ -1352,6 +1352,7 @@ export class Channel) { + _updateQuotedMessageReferences({ + message, + remove, + }: { + message: MessageResponse; + remove?: boolean; + }) { const parseMessage = (m: ReturnType['formatMessage']>) => (({ ...m, @@ -358,14 +363,26 @@ export class ChannelState); - this.messageSets.forEach((set) => { - const updatedMessages = set.messages - .filter((msg) => msg.quoted_message_id === message.id) - .map(parseMessage) - .map((msg) => ({ ...msg, quoted_message: { ...message, attachments: [] } })); - + const update = (messages: FormatMessageResponse[]) => { + const updatedMessages = messages.reduce[]>((acc, msg) => { + if (msg.quoted_message_id === message.id) { + acc.push({ ...parseMessage(msg), quoted_message: remove ? { ...message, attachments: [] } : message }); + } + return acc; + }, []); this.addMessagesSorted(updatedMessages, true); - }); + }; + + if (!message.parent_id) { + this.messageSets.forEach((set) => update(set.messages)); + } else if (message.parent_id && this.threads[message.parent_id]) { + // prevent going through all the threads even though it is possible to quote a message from another thread + update(this.threads[message.parent_id]); + } + } + + removeQuotedMessageReferences(message: MessageResponse) { + this._updateQuotedMessageReferences({ message, remove: true }); } /** diff --git a/src/client.ts b/src/client.ts index 53768fbe0..34f4741a6 100644 --- a/src/client.ts +++ b/src/client.ts @@ -40,6 +40,7 @@ import { BaseDeviceFields, BlockList, BlockListResponse, + BlockUserAPIResponse, CampaignResponse, CampaignData, CampaignFilters, @@ -179,6 +180,7 @@ import { QuerySegmentTargetsFilter, SortParam, GetMessageOptions, + GetBlockedUsersAPIResponse, QueryVotesFilters, VoteSort, CreatePollAPIResponse, @@ -2237,7 +2239,24 @@ export class StreamChat(this.baseURL + '/users/block', { + blocked_user_id: blockedUserID, + ...(user_id ? { user_id } : {}), + }); + } + async getBlockedUsers(user_id?: string) { + return await this.get(this.baseURL + '/users/block', { + ...(user_id ? { user_id } : {}), + }); + } + async unBlockUser(blockedUserID: string, userID?: string) { + return await this.post(this.baseURL + '/users/unblock', { + blocked_user_id: blockedUserID, + ...(userID ? { user_id: userID } : {}), + }); + } /** muteUser - mutes a user * * @param {string} targetID diff --git a/src/types.ts b/src/types.ts index 9470d4a59..1f1e7e3fd 100644 --- a/src/types.ts +++ b/src/types.ts @@ -697,6 +697,26 @@ export type MuteUserResponse; }; +export type BlockUserAPIResponse = APIResponse & { + blocks: BlockUserResponse[]; +}; +export type BlockUserResponse = APIResponse & { + blocked_at: string; + blocked_by_user_id: string; + blocked_user_id: string; +}; + +export type GetBlockedUsersAPIResponse = APIResponse & { + blocks: BlockedUserDetails[]; +}; +export type BlockedUserDetails = APIResponse & { + blocked_user: UserResponse; + blocked_user_id: string; + created_at: string; + user: UserResponse; + user_id: string; +}; + export type OwnUserBase = { channel_mutes: ChannelMute[]; devices: Device[]; @@ -818,6 +838,7 @@ export type UpdateUsersAPIResponse = User & { banned?: boolean; + blocked_user_ids?: string[]; created_at?: string; deactivated_at?: string; deleted_at?: string; @@ -2040,6 +2061,7 @@ export type ChannelConfigWithInfo< export type ChannelData< StreamChatGenerics extends ExtendableGenerics = DefaultGenerics > = StreamChatGenerics['channelType'] & { + blocked?: boolean; members?: string[]; name?: string; }; diff --git a/test/unit/channel.js b/test/unit/channel.js index 11609a758..ab724086d 100644 --- a/test/unit/channel.js +++ b/test/unit/channel.js @@ -542,6 +542,45 @@ describe('Channel _handleChannelEvent', function () { }); }); + it('should update quoted_message references on "message.updated" and "message.deleted" event', () => { + const originalText = 'XX'; + const updatedText = 'YY'; + const parent_id = '0'; + const parentMesssage = generateMsg({ date: new Date(0).toISOString(), id: parent_id }); + const quoted_message = generateMsg({ + date: new Date(2).toISOString(), + id: 'quoted-message', + text: originalText, + }); + const quotingMessage = generateMsg({ + date: new Date(3).toISOString(), + id: 'quoting-message', + quoted_message, + quoted_message_id: quoted_message.id, + }); + const updatedQuotedMessage = { ...quoted_message, text: updatedText }; + const updatedQuotedThreadReply = { ...quoted_message, parent_id, text: updatedText }; + [ + [quoted_message, quotingMessage], // channel message + [parentMesssage, { ...quoted_message, parent_id }, { ...quotingMessage, parent_id }], // thread message + ].forEach((messages) => { + ['message.updated', 'message.deleted'].forEach((eventType) => { + channel.state.addMessagesSorted(messages); + const isThread = messages.length === 3; + const quotingMessage = messages[messages.length - 1]; + const event = { + type: eventType, + message: isThread ? updatedQuotedThreadReply : updatedQuotedMessage, + }; + channel._handleChannelEvent(event); + expect( + channel.state.findMessage(quotingMessage.id, quotingMessage.parent_id).quoted_message.text, + ).to.equal(updatedQuotedMessage.text); + channel.state.clearMessages(); + }); + }); + }); + it('should mark channel visible on channel.visible event', () => { const channelVisibleEvent = { type: 'channel.visible',