Observing channels just after user is signed in doesn't work

I’m trying to implement channels observation after user is signed in and I can’t make it to work, the observe closure is not called. It works fine when I kill the app and when the app is relaunched, but it doesn’t right after when user is logged in. I’m getting these warnings printed out in the console:

🟨 [AmitySDK]: Cannot fetch network configuration for chat module. User is not logged in. Use login() before calling any api.
🟨 [AmitySDK]: AmitySDK cannot subscribe to user deletion event (unable to find the current user).
🟨 [AmitySDK]: AmitySDK cannot subscribe to user deletion event (unable to find the current user).
🟨 [AmitySDK]: AmitySDK cannot subscribe to user deletion event (unable to find the current user).

these warning are triggered when I call the getChannels(channelIds:) function on object of AmityChannelRepository

I’m using AmityUIKit 3.20.3

Here’s what I’m doing:

  1. I’m initialising AmityClient and AmityUIKitManager using my apiKey and region
  2. I’m signing in user, fetching auth token from my server and then calling AmityUIKitManager.registerDevice(withUserId:displayName:authToken:sessionHandler:completion) function and waiting for completion block to be invoked and making sure that the parameter of Bool type is true
  3. I’m observing .amityClient.$sessionState and when it’s .established I’m creating object of AmityChannelRepository type and calling:
        let notificationToken = channelRepository
            .getChannels(channelIds: ids)
            .observe { liveCollection, _, error in

but the observe block is never called and I’m getting the warnings mentioned above printed in the console.

So I’m making sure that the getChannels is called only when user is logged in and session state is established but it doesn’t work. It works when I kill the app and launch it when the user is already logged in though.

I tried to investigate what are the differences in AmitySDK.AmityCollection<AmitySDK.AmityChannel> object returned from getChannels function when I sign in the user vs. when the app is launched with the user already logged in, and I found that in the first case result.transaction.currentUserId is nil while in the second case the currentUserId has the value set.

Any ideas what I’m doing wrong?

@nadol To ensure the Amity notification token works correctly in your implementation, it’s important to declare it at the class level. This helps prevent the token from being dismissed prematurely.

For detailed instructions on declaring and managing the Amity notification token, please see our documentation: Amity SDK Documentation.

@amitysupport I have it declared at the class level. I simplified my code so you can take a look:

final class ChatChannelsRepository {
    struct Dependencies {
        let amityClient: AmityClient
        let eventsStorage: EventsStorage
    }

    private let dependencies: Dependencies
    private var cancellables = [AnyCancellable]()
    private var channelRepository: AmityChannelRepository?
    private var token: AmityNotificationToken?

    init(dependencies: Dependencies) {
        self.dependencies = dependencies
        setupBindings()
    }

    private func setupBindings() {
        dependencies.amityClient.$sessionState
            .sink(receiveValue: { [weak self] in
                switch $0 {
                case .established:
                    if let self, channelRepository == nil {
                        self.channelRepository = .init(client: self.dependencies.amityClient)
                    }
                    self?.observeChannels(ids: [
                        "bei.lgdBoSXVJMYcedg73uvqOK7cBdW2.1714067336810",
                        "bei.lgdBoSXVJMYcedg73uvqOK7cBdW2.1714068108073"
                    ])
                default:
                    break
                }
            })
            .store(in: &cancellables)
    }

    private func observeChannels(ids: [String]) {
        guard let channelRepository else {
            return
        }

        token = channelRepository
            .getChannels(channelIds: ids)
            .observe { liveCollection, _, error in
                if let error = error {
                    return
                }

                let chatChannels = liveCollection.snapshots.map {
                    ChatChannel(
                        id: $0.channelId,
                        name: $0.displayName ?? "General",
                        unreadCount: $0.subChannelsUnreadCount
                    )
                }
                print("chatChannelsCount \(chatChannels.count)")
            }
    }
}

If you look at the warnings in my original post then it seems like I’m calling observe before user is logged in but the problem is that I call it after making sure that user got logged in and session state is established

@nadol Let me pass this on to my team, and I’ll get back to you.

@nadol After reviewing your code, could you please verify whether this code successfully completes the authentication process before proceeding to setupBindings()?

init(dependencies: Dependencies) {
    self.dependencies = dependencies
    setupBindings()
}

This code does not seem to confirm that the authentication process has been successful. Since the value of channelRepository does not necessarily indicate that the session has already been established, consider this modification:

if channelRepository == nil {
    self.channelRepository = .init(client: self.dependencies.amityClient)
}

This adjustment ensures that channelRepository is only initialized once the session has been established, providing a more reliable setup.

I don’t understand what has been changed?

                    if let self, channelRepository == nil {
                        self.channelRepository = .init(client: self.dependencies.amityClient)
                    }
                    self?.observeChannels(ids: [
                        "bei.lgdBoSXVJMYcedg73uvqOK7cBdW2.1714067336810",
                        "bei.lgdBoSXVJMYcedg73uvqOK7cBdW2.1714068108073"
                    ])

this code from my original snippet is called only when session is established

ChatChannelsRepository is initialised only when user successfully signs in, it is when completion block of AmityUIKitManager.registerDevice(withUserId:displayName:authToken:sessionHandler:completion) is called

Thank you @nadol for additional information. We passed this back to the team.

@amitysupport I think I found a workaround for this issue. It seems like amity client can’t properly update the status of session if it’s created before AmityUIKitManager.registerDevice(withUserId:displayName:authToken:sessionHandler:completion) is executed and completed and that was causing the warnings. If I initialise AmityClient only when session is established then it works fine

1 Like

@nadol After further investigation, it was found to be the expected behavior from the SDK, and your report to us was correct. We have informed the relevant team to correct our documentation accordingly. Thank you for sharing your findings.