GetStream / stream-chat-swiftui

SwiftUI Chat SDK ➜ Stream Chat 💬
https://getstream.io/chat/sdk/swiftui/
Other
342 stars 84 forks source link

makeChannelListItem not being invoked? #576

Closed jonahhugit closed 1 month ago

jonahhugit commented 1 month ago

What did you do?

I am trying to override the channel list view to expose a custom avatar (for group chats, shows up to 4 avatars in a resized image -- is there any other way to do this? I know in UIKit there is already code natively in the SDK)

What did you expect to happen?

I overrode makeChannelListItem as documented, expecting it to override the Default View Factory

What happened instead?

I overrode makeChannelListItem as documented, but it is not being overriding Default View Factory for some reason. makeChannelListHeaderViewModifier, which I am also overriding in the View Factory is overriding fine.

GetStream Environment

GetStream Chat version: 4.61.0 GetStream Chat frameworks: StreamChat, StreamChatSwiftUI iOS version: 17.5 Swift version: 5.10 Xcode version: 15.4 Device: iPhone 15 Pro emulator, iPhone 14 Pro physical

Additional context

Our view factory:

class CorgiStreamFactory: ViewFactory {
    @Injected(\.chatClient) public var chatClient

    private init() {}

    public static let shared = CorgiStreamFactory()

    func makeChannelListHeaderViewModifier(title: String) -> some ChannelListHeaderViewModifier {
        CorgiChannelHeaderModifier(title: title)
    }

    public func makeChannelListItem(
        channel: ChatChannel,
        channelName: String,
        avatar: UIImage,  // This parameter will be replaced by custom view
        onlineIndicatorShown: Bool,
        disabled: Bool,
        selectedChannel: Binding<ChannelSelectionInfo?>,
        swipedChannelId: Binding<String?>,
        channelDestination: @escaping (ChannelSelectionInfo) -> ChannelDestination,
        onItemTap: @escaping (ChatChannel) -> Void,
        trailingSwipeRightButtonTapped: @escaping (ChatChannel) -> Void,
        trailingSwipeLeftButtonTapped: @escaping (ChatChannel) -> Void,
        leadingSwipeButtonTapped: @escaping (ChatChannel) -> Void
    ) -> some View {  // The return type must be 'some View' or 'ChannelListItemType'
        print("Custom makeChannelListItem is being invoked")

        // Use CorgiChannelAvatarView for the avatar
        let customAvatarView = CorgiChannelAvatarView(channel: channel, avatarSize: CGSize(width: 40, height: 40))

        // Define the channel list item with the custom avatar view
        let channelListItem = HStack {
            customAvatarView  // Custom avatar view
            Text(channelName)
                .font(.headline)
            Spacer()
        }
        .padding()
        .background(Color.white)
        .contentShape(Rectangle())
        .onTapGesture {
            onItemTap(channel)
        }

        // Return the swipeable list item using the custom view
        return ChatChannelSwipeableListItem(
            factory: self,
            channelListItem: channelListItem,
            swipedChannelId: swipedChannelId,
            channel: channel,
            numberOfTrailingItems: channel.ownCapabilities.contains(.deleteChannel) ? 2 : 1,
            trailingRightButtonTapped: trailingSwipeRightButtonTapped,
            trailingLeftButtonTapped: trailingSwipeLeftButtonTapped,
            leadingSwipeButtonTapped: leadingSwipeButtonTapped
        )
    }
}
martinmitrevski commented 1 month ago

Hi @jonahhugit,

The problem with the code you shared is that the channelDestination parameter resolves to the associated type of the default view factory.

You need to explicitly provide your own custom view factory in this case:

channelDestination: @escaping (ChannelSelectionInfo) -> ChatChannelView< CorgiStreamFactory>

Hope this helps. Best, Martin

jonahhugit commented 1 month ago

Thank you @martinmitrevski - appreciate the help!