Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for transforming Messages, Channels and Members #3564

Open
wants to merge 20 commits into
base: develop
Choose a base branch
from

Conversation

nuno-vieira
Copy link
Member

@nuno-vieira nuno-vieira commented Jan 16, 2025

🔗 Issue Links

Resolves https://linear.app/stream/issue/IOS-638

🎯 Goal

Add support for transforming Messages, Channels and Members. This will allow changing some of the data of these models at run time.

The most common use case for this feature is to easily allow E2EE encryption.

Note

Our Members and User models are different, and since Member is a subclass of User (Tech Debt), transforming Users would not reflect on Members, so at the moment we only provide transforming members. If in the future Users is needed, it needs to be a new function to transform Users.

📝 Summary

A new StreamModelsTransformer protocol is added and can be implemented by customers. Currently, only Channels, Messages and Channel Members are transformable, with limited data that can be changed.

Example usage:

class CustomStreamModelsTransformer: StreamModelsTransformer {
    func transform(channel: ChatChannel) -> ChatChannel {
        channel.replacing(
            name: "Hey!",
            imageURL: channel.imageURL,
            extraData: channel.extraData
        )
    }

    func transform(message: ChatMessage) -> ChatMessage {
        message.replacing(
            text: "Yo",
            extraData: message.extraData,
            attachments: message.allAttachments
        )
    }

    func transform(newMessageInfo: NewMessageTransformableInfo) -> NewMessageTransformableInfo {
        newMessageInfo.replacing(
            text: "Changed",
            attachments: newMessageInfo.attachments,
            extraData: newMessageInfo.extraData
        )
    }
    
    func transform(member: ChatChannelMember) -> ChatChannelMember {
        member.replacing(
            name: "\(member.name ?? member.id)",
            imageURL: member.imageURL,
            userExtraData: member.extraData,
            memberExtraData: member.memberExtraData
        )
    }
}

With the replacing function, if customers want to only change the data of a specific controller, they can do it like so:

let transformedChannels = controller.channels.map {
    $0.replacing(name: "YO", imageURL: $0.imageURL, extraData: $0.extraData)
}

// with combine:
controller.observableObject
      .channels
      .publisher
      .map {
         $0.replacing(name: "YO", imageURL: $0.imageURL, extraData: $0.extraData)
      }
      .sink(receiveValue: { transformedChannel in
         print(transformedChannel)
      })

🛠 Implementation

The way it works is that when asModel() transformation happens, we provide a way to change it before returning the final model.

🧪 Manual Testing Notes

N/A

☑️ Contributor Checklist

  • I have signed the Stream CLA (required)
  • This change should be manually QAed
  • Changelog is updated with client-facing changes
  • Changelog is updated with new localization keys
  • New code is covered by unit tests
  • Documentation has been updated in the docs-content repo

@Stream-SDK-Bot
Copy link
Collaborator

Stream-SDK-Bot commented Jan 16, 2025

SDK Size

title develop branch diff status
StreamChat 7.0 MB 7.0 MB +1 KB 🟢
StreamChatUI 4.77 MB 4.77 MB 0 KB 🟢

@nuno-vieira nuno-vieira force-pushed the add/stream-models-transformer-support branch from 6066703 to 206c580 Compare January 16, 2025 17:57
Copy link

github-actions bot commented Jan 16, 2025

1 Warning
⚠️ Big PR

Generated by 🚫 Danger

@laevandus
Copy link
Contributor

StateLayer needs also this.

@nuno-vieira
Copy link
Member Author

@laevandus I've add it to the state layer already 🤔

@nuno-vieira nuno-vieira force-pushed the add/stream-models-transformer-support branch from c7b09f2 to c2307b6 Compare January 17, 2025 11:27
Copy link
Contributor

@martinmitrevski martinmitrevski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, I like this approach more! Few more finishing touches (docs, tests) and we're good to 🚢

DemoApp/Shared/StreamChatWrapper.swift Outdated Show resolved Hide resolved
Sources/StreamChat/Models/Channel.swift Show resolved Hide resolved
@nuno-vieira nuno-vieira marked this pull request as ready for review January 21, 2025 15:40
@nuno-vieira nuno-vieira requested a review from a team as a code owner January 21, 2025 15:40
@Stream-SDK-Bot
Copy link
Collaborator

SDK Performance

target metric benchmark branch performance status
MessageList Hitches total duration 10 ms 5.01 ms 49.9% 🔼 🟢
Duration 2.6 s 2.55 s 1.92% 🔼 🟢
Hitch time ratio 4 ms per s 1.96 ms per s 51.0% 🔼 🟢
Frame rate 75 fps 78.32 fps 4.43% 🔼 🟢
Number of hitches 1 0.4 60.0% 🔼 🟢

@nuno-vieira nuno-vieira changed the title Add support for transforming Messages and Channels Add support for transforming Messages, Channels and Members Jan 21, 2025
@Stream-SDK-Bot
Copy link
Collaborator

Stream-SDK-Bot commented Jan 22, 2025

SDK Size

title develop branch diff status
StreamChat 7.0 MB 7.0 MB +1 KB 🟢
StreamChatUI 4.77 MB 4.77 MB 0 KB 🟢

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants