Closed moubry closed 2 years ago
Hi @moubry!
Thank you for your time in creating the issue!
We are currently investigating it, and we will get back to you as soon as possible.
Best, Nuno
Hi @moubry!
Can you show us the query of your ChatChannelListController
? It does seem that on iOS SDK we don't parse this event. And we should fix this, but usually, the channel list query is observing the current user as a member, and that triggers a different event, which is “notification.added_to_channel”. Any reason you are observing channels where the current user is not a member? If that is a mistake, you can fix it on your side, if not, you will need to wait for a fix. Please let me know your use case.
Thanks, Nuno
Thanks for investigating this @nuno-vieira — I really appreciate it!
I believe that I’m definitely observing channels where the user is a member. However, there could be something else I’m doing that could be exacerbating the issue. Here’s an approximation of what I’m currently doing (some non-relevant code removed):
struct StreamView: View {
@ObservedObject var connection: ChatConnectionController.ObservableObject
init(connectionController: ChatConnectionController) {
self.connection = connectionController.observableObject
}
var body: some View {
switch connection.connectionStatus {
case .connected:
if let userID = ChatClient.shared.currentUserId {
let channelListController = ChatClient.shared.channelListController(
query: ChannelListQuery(filter: .containMembers(userIds: [userID]))
)
ChannelListView(channelListController: channelListController)
} else {
Text("Error: Connected but couldn’t find Stream user to log in as.")
}
case .disconnected, .disconnecting:
Text("Disconnected.")
case .connecting, .initialized:
Text("Connecting…")
}
}
}
struct ChannelListView: View {
var channelListController: ChatChannelListController
@State var channels = [ChatChannel]()
init(channelListController: ChatChannelListController) {
self.channelListController = channelListController
}
var body: some View {
NavigationView {
VStack(alignment: .trailing) {
List(channels, id: \.id) { channel in
NavigationLink(tag: channel, selection: $streamWindow.selectedChannel,
destination: {
HStack(alignment: .top, spacing: 0) {
ChatChannelView(
viewFactory: streamWindow.customViewFactory,
channelController: ChatClient.shared.channelController(for: channel.cid)
)
.navigationBarHidden(false)
.onAppear {
print("Channel `\(channel.cid)` is appearing. Clearing last thread viewed.")
streamWindow.lastThreadViewed = nil
}
}
}, label: {
Text(channel.name ?? "Untitled")
})
}
.navigationTitle("Channels")
}
// Channel List Toolbar
.toolbar {
// A hidden button that is activated when the
// NewChannelView sets the showingNewChannel flag.
ToolbarItem(placement: .navigationBarTrailing) {
NavigationLink(
isActive: $showingNewChannel,
destination: {
if let controller = newChatChannelController {
ChatChannelView(
viewFactory: streamWindow.customViewFactory,
channelController: controller
)
}
}, label: {
EmptyView()
}
)
}
ToolbarItem(placement: .navigationBarTrailing) {
Button {
showingNewChannelForm = true
} label: {
Image(systemName: "plus")
.resizable()
}
}
}
.sheet(isPresented: $showingNewChannelForm) {
NewChannelView(controller: $newChatChannelController, showingNewChannel: $showingNewChannel)
}
}
.workaroundNavigationStyle()
.onAppear {
print("StreamView has appeared. Synchronizing channel list controller.")
// Update the locally cached list of channels with Stream servers.
channelListController.observableObject.controller.synchronize()
}
// We are subscribing to changes on channels here, then updating our own
// local channels state, instead of setting the channel list controller as
// `@ObservedObject var channelList: ChatChannelListController.ObservableObject`
// because that was causing the entire navigation view hierarchy to be blown away (and
// navigation reset) on minor channel state changes.
.onReceive(channelListController.observableObject.$channels) { channels in
// When a new channel is created on the server, this never gets called.
// However, it does otherwise get called quite often throughout normal usage of the app.
print("Channel list's channels changing (\(channels.count)).")
self.channels = channels.sorted(by: { channelA, channelB in
channelA.lastMessageAt ?? Date() > channelB.lastMessageAt ?? Date()
})
}
}
}
Thanks for the snippet @moubry!
What I think is missing is that you need to watch the channel on the backend side, when creating the channel you need to watch it so that events are propagated to the members of the channel. More details here: https://getstream.io/chat/docs/go-golang/watch_channel/?language=go
Let me know if that helped!
Hi @moubry!
Never mind what I said above, you can only watch a channel from the Client SDKs. Just to double check that the issue is actually from not observing that missing event, when you create a channel from the ServerSide SDK if you turn on the web socket logging in the iOS SDK, you should observe in the logs that "channel.created" event.
LogConfig.level = .debug
LogConfig.subsystems = .webSocket
Meanwhile, we will try to reproduce this ourselves and provide a fix as soon as possible 👍
Best, Nuno
Thanks for looking into it, @nuno-vieira!
I turned on verbose logging. Immediately after creating the channel on the server, I do successfully see one notification.added_to_channel
event in the client, but I do not see a channel.created
event, and channelListController.observableObject.$channels
does not notify me of the new channel. Then when I quit and restart the app, I see the error about failing to decode channel.created
right after /sync
is called for missing events.
Just to be sure, I set LogConfig.subsystems = .all
and I don’t see anything about channel.created
when the channel is created, however I’m not sure if I should or not. If it’s useful, here’s the verbose logs (all subsystems) when my client receives the new channel: new_channel.log.
Hi @moubry!
That is all very useful information, thank you!
We will let you know once we have more details about the issue.
Best, Nuno
Hi @moubry!
After some more investigation, it seems everything is working fine from our testing, but having a better look at your example, what might actually be happening is a misuse of our Combine helpers. I recommend you to take a look at this example on how to work with the ChannelList Observable Object here: https://github.com/GetStream/stream-chat-swift/blob/develop/StreamChatSample/Samples/SwiftUISimpleChat/ChannelListView.swift#L14
It seems the way you are handling the channel list updates is not the correct way, and that is why the updates are not performed. You should use the ChannelList Controller as a @StateObject and just use the channelList.channels
directly.
Please, let me know if our SwiftUI Sample was helpful. If you still encounter issues, let me know and we can schedule a call 👍
Best, Nuno
Thank you, @nuno-vieira. Yes, I can confirm making this change works for me — when I subscribe to changes in the channels list through @StateObject
instead of using onReceive
, the issue where channels
does not change goes away.
I still see the error in my logs where channel.created
cannot be decoded, but I no longer experience the UX symptoms that motivated me to create this issue. It sounds like these were totally separate things that I was conflating together.
Thank you so much for the help!
Hi @moubry !
Great that we could finally pinpoint the issue! Yes, that event does not seem to be important to handle since it is a bit redundant, at least for now. The other platforms are also not handling it, so for now I'll close this issue :)
Thank you for your patience!
What did you do?
ChatClient.shared.connectUser
, then begins subscribing to changes fromChatChannelListController
’s list of channels.What did you expect to happen?
I expect to not see an error from Stream in logs, and to instead see new channels appear in channel list controller’s
channels
as they're created.Note: Relaunching the app DOES show the newly created channel, despite the error in the logs. I’m hoping that perhaps this error message sheds some light on to why I might not be receiving channels as they’re created.
What happened instead?
I do not receive the newly created channel and instead (upon restarting the app), see this console/log error:
I see many of these errors after quitting/reopening the app — all for channel creation events, which seems to be the only event that the SDK is failing to decode.
GetStream Environment
GetStream Chat version: 4.18.0 GetStream Chat frameworks: Both StreamChat and StreamChatUI. iOS version: iOS 15 Swift version: latest Xcode version: latest Device: iPhone 13 Pro
Additional detail
I’m assuming this does not matter, but just in case it’s useful information: I’m not creating these channels in the Swift client, but am instead creating them on the server using the Go package: