Skip to content

Commit ccbe05e

Browse files
authored
Do not reset blocked state when channel specific WS event without blocked state is handled (#3794)
1 parent fdf3693 commit ccbe05e

File tree

7 files changed

+103
-13
lines changed

7 files changed

+103
-13
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
66
## StreamChat
77
### ✅ Added
88
- Add support for `user.messages.deleted` event [#3792](https://github.com/GetStream/stream-chat-swift/pull/3792)
9+
### 🐞 Fixed
10+
- Fix channel getting removed from channel list which includes blocked channels [#3794](https://github.com/GetStream/stream-chat-swift/pull/3794)
11+
912
## StreamChatUI
1013
### 🐞 Fixed
1114
- Fix input text view's placeholder alignment in RTL [#3790](https://github.com/GetStream/stream-chat-swift/pull/3790)

DemoApp/StreamChat/Components/DemoChatChannelListVC.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,16 @@ final class DemoChatChannelListVC: ChatChannelListVC {
4848
.equal(.blocked, to: true)
4949
])
5050
]))
51+
52+
lazy var blockedUnblockedWithHiddenChannelsQuery: ChannelListQuery = .init(
53+
filter: .and([
54+
.containMembers(userIds: [currentUserId]),
55+
.or([
56+
.and([.equal(.blocked, to: false), .equal(.hidden, to: false)]),
57+
.and([.equal(.blocked, to: true), .equal(.hidden, to: true)])
58+
])
59+
])
60+
)
5161

5262
lazy var unreadCountChannelsQuery: ChannelListQuery = .init(
5363
filter: .and([
@@ -161,6 +171,15 @@ final class DemoChatChannelListVC: ChatChannelListVC {
161171
self?.setAllBlockedChannelsQuery()
162172
}
163173
)
174+
175+
let blockedUnBlockedExcludingDeletedChannelsAction = UIAlertAction(
176+
title: "Blocked Unblocked with Matching Hidden Channels",
177+
style: .default,
178+
handler: { [weak self] _ in
179+
self?.title = "Blocked Unblocked with Matching Hidden Channels"
180+
self?.setBlockedUnblockedWithHiddenChannelsQuery()
181+
}
182+
)
164183

165184
let unreadCountChannelsAction = UIAlertAction(
166185
title: "Unread Count Channels",
@@ -230,6 +249,7 @@ final class DemoChatChannelListVC: ChatChannelListVC {
230249
hasUnreadChannelsAction,
231250
hiddenChannelsAction,
232251
allBlockedChannelsAction,
252+
blockedUnBlockedExcludingDeletedChannelsAction,
233253
mutedChannelsAction,
234254
coolChannelsAction,
235255
pinnedChannelsAction,
@@ -248,6 +268,10 @@ final class DemoChatChannelListVC: ChatChannelListVC {
248268
func setAllBlockedChannelsQuery() {
249269
replaceQuery(allBlockedChannelsQuery)
250270
}
271+
272+
func setBlockedUnblockedWithHiddenChannelsQuery() {
273+
replaceQuery(blockedUnblockedWithHiddenChannelsQuery)
274+
}
251275

252276
func setUnreadCountChannelsQuery() {
253277
replaceQuery(unreadCountChannelsQuery)

Sources/StreamChat/Database/DTOs/ChannelDTO.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -285,8 +285,6 @@ extension NSManagedObjectContext {
285285
// for blocked 1:1 channels on channel list query
286286
if let isBlocked = payload.isBlocked {
287287
dto.isBlocked = isBlocked
288-
} else {
289-
dto.isBlocked = false
290288
}
291289

292290
// Backend only returns a boolean for hidden state

Sources/StreamChat/Database/StreamChatModel.xcdatamodeld/StreamChatModel.xcdatamodel/contents

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2-
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="23605" systemVersion="24F74" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
2+
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="23788.4" systemVersion="24F74" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
33
<entity name="AttachmentDTO" representedClassName="AttachmentDTO" syncable="YES">
44
<attribute name="data" attributeType="Binary"/>
55
<attribute name="id" attributeType="String"/>
@@ -49,7 +49,7 @@
4949
<attribute name="hasUnreadSorting" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/>
5050
<attribute name="id" optional="YES" attributeType="String"/>
5151
<attribute name="imageURL" optional="YES" attributeType="URI"/>
52-
<attribute name="isBlocked" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
52+
<attribute name="isBlocked" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
5353
<attribute name="isDisabled" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
5454
<attribute name="isFrozen" attributeType="Boolean" usesScalarValueType="YES"/>
5555
<attribute name="isHidden" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>

TestTools/StreamChatTestTools/TestData/DummyData/ChannelDetailPayload.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ extension ChannelDetailPayload {
2222
config: ChannelConfig = .mock(),
2323
ownCapabilities: [String] = [],
2424
isFrozen: Bool = false,
25-
isBlocked: Bool = false,
25+
isBlocked: Bool? = false,
2626
isDisabled: Bool = false,
2727
isHidden: Bool? = nil,
2828
members: [MemberPayload] = [],

TestTools/StreamChatTestTools/TestData/DummyData/XCTestCase+Dummy.swift

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,8 @@ extension XCTestCase {
156156
ownCapabilities: [String] = [],
157157
channelExtraData: [String: RawJSON] = [:],
158158
createdAt: Date = XCTestCase.channelCreatedDate,
159+
blocked: Bool? = false,
160+
hidden: Bool? = nil,
159161
truncatedAt: Date? = nil,
160162
cooldownDuration: Int? = nil,
161163
channelReads: [ChannelReadPayload]? = nil
@@ -189,8 +191,8 @@ extension XCTestCase {
189191
ownCapabilities: ownCapabilities,
190192
isDisabled: false,
191193
isFrozen: true,
192-
isBlocked: false,
193-
isHidden: nil,
194+
isBlocked: blocked,
195+
isHidden: hidden,
194196
members: members,
195197
memberCount: 100,
196198
team: .unique,
@@ -409,9 +411,9 @@ extension XCTestCase {
409411
latestAnswers: [PollVotePayload?]? = nil,
410412
options: [PollOptionPayload?] = [],
411413
ownVotes: [PollVotePayload?] = [],
412-
custom: [String : RawJSON] = [:],
413-
latestVotesByOption: [String : [PollVotePayload]] = [:],
414-
voteCountsByOption: [String : Int] = [:],
414+
custom: [String: RawJSON] = [:],
415+
latestVotesByOption: [String: [PollVotePayload]] = [:],
416+
voteCountsByOption: [String: Int] = [:],
415417
isClosed: Bool? = nil,
416418
maxVotesAllowed: Int? = nil,
417419
votingVisibility: String? = nil,
@@ -501,7 +503,7 @@ private extension MemberPayload {
501503
isInvisible: true,
502504
isBanned: true,
503505
teams: [],
504-
language: nil,
506+
language: nil,
505507
extraData: [:]
506508
),
507509
userId: userId,

Tests/StreamChatTests/StateLayer/ChannelList_Tests.swift

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,65 @@ final class ChannelList_Tests: XCTestCase {
343343
cancellable.cancel()
344344
}
345345

346+
func test_updatingChannels_whenBlockedAndUnblockedWithHiddenQuery() async throws {
347+
await setUpChannelList(
348+
usesMockedChannelUpdater: false,
349+
filter: .and([
350+
.containMembers(userIds: [memberId]),
351+
.or([
352+
.and([.equal(.blocked, to: false), .equal(.hidden, to: false)]),
353+
.and([.equal(.blocked, to: true), .equal(.hidden, to: true)])
354+
])
355+
])
356+
)
357+
358+
// Get initial batch of channels where 2 are blocked, 3 are not
359+
let blockedOffsets = Set([1, 3])
360+
let hiddenOffsets = Set([1, 3])
361+
let firstChannelListPayload = makeMatchingChannelListPayload(
362+
channelCount: 5,
363+
createdAtOffset: 0,
364+
blocked: { _, offset in blockedOffsets.contains(offset) },
365+
hidden: { _, offset in hiddenOffsets.contains(offset) }
366+
)
367+
env.client.mockAPIClient.test_mockResponseResult(.success(firstChannelListPayload))
368+
try await channelList.get()
369+
await XCTAssertEqual(5, channelList.state.channels.count)
370+
await XCTAssertEqual(2, channelList.state.channels.filter(\.isBlocked).count)
371+
await XCTAssertEqual(2, channelList.state.channels.filter(\.isHidden).count)
372+
373+
// Send an event which does not include blocked and hidden states, but contains channel info
374+
// Channel gets saved to DB and should not change blocked and hidden states.
375+
let secondChannel = firstChannelListPayload.channels[1].channel
376+
let channelPayloadWithoutBlockedAndHidden = ChannelDetailPayload.dummy(
377+
cid: secondChannel.cid,
378+
isBlocked: nil,
379+
isHidden: nil,
380+
members: secondChannel.members ?? []
381+
)
382+
let eventPayload = EventPayload(
383+
eventType: .notificationMarkRead,
384+
cid: channelPayloadWithoutBlockedAndHidden.cid,
385+
user: .dummy(userId: memberId),
386+
channel: channelPayloadWithoutBlockedAndHidden,
387+
unreadCount: .init(channels: 0, messages: 0, threads: 0),
388+
createdAt: Date()
389+
)
390+
let notificationMarkReadEvent = try NotificationMarkReadEventDTO(from: eventPayload)
391+
let expectation = XCTestExpectation()
392+
env.client.eventNotificationCenter.process(notificationMarkReadEvent, postNotification: true) {
393+
expectation.fulfill()
394+
}
395+
await fulfillment(of: [expectation])
396+
397+
let secondChannelDataAfterEvent = try env.client.databaseContainer.readSynchronously { session in
398+
try XCTUnwrap(session.channel(cid: secondChannel.cid)).asModel()
399+
}
400+
XCTAssertEqual(true, secondChannelDataAfterEvent.isBlocked, "State did not change")
401+
XCTAssertEqual(true, secondChannelDataAfterEvent.isHidden, "State did not change")
402+
await XCTAssertEqual(5, channelList.state.channels.count)
403+
}
404+
346405
// MARK: - Linking and Unlinking Channels
347406

348407
func test_observingEvents_whenAddedToChannelEventReceived_thenChannelIsLinkedAndStateUpdates() async throws {
@@ -487,7 +546,9 @@ final class ChannelList_Tests: XCTestCase {
487546
createdAtOffset: Int,
488547
namePrefix: String = "Name",
489548
membersCreator: ((ChannelId, Int) -> [MemberPayload])? = nil,
490-
messagesCreator: ((ChannelId, Int) -> [MessagePayload])? = nil
549+
messagesCreator: ((ChannelId, Int) -> [MessagePayload])? = nil,
550+
blocked: ((ChannelId, Int) -> Bool) = { _, _ in false },
551+
hidden: ((ChannelId, Int) -> Bool) = { _, _ in false }
491552
) -> ChannelListPayload {
492553
let channelPayloads = (0..<channelCount)
493554
.map {
@@ -498,7 +559,9 @@ final class ChannelList_Tests: XCTestCase {
498559
name: "\(namePrefix) \($0 + createdAtOffset)",
499560
members: members,
500561
messages: messagesCreator?(channelId, $0 + createdAtOffset),
501-
createdAt: Date(timeIntervalSinceReferenceDate: TimeInterval($0 + createdAtOffset))
562+
createdAt: Date(timeIntervalSinceReferenceDate: TimeInterval($0 + createdAtOffset)),
563+
blocked: blocked(channelId, $0 + createdAtOffset),
564+
hidden: hidden(channelId, $0 + createdAtOffset)
502565
)
503566
}
504567
return ChannelListPayload(channels: channelPayloads)

0 commit comments

Comments
 (0)