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

Pinning channels for the current user #3518

Merged
merged 13 commits into from
Dec 5, 2024
Merged

Conversation

laevandus
Copy link
Contributor

@laevandus laevandus commented Dec 2, 2024

🔗 Issue Links

Part of IOS-553

🎯 Goal

Add a new feature enabling users to pin channels (pinned status is tied to the user, not a global action)

📝 Summary

  • Public API changes:
    • Add Chat.pin(scope:) and Chat.unpin(scope:)
    • Add ChatChannelController.pin(scope:completion:) and ChatChannelController.unpin(scope:completion:)
    • Add ChannelPinningScope with only one supported option of me (pinning the channel for everyone is not supported)
    • Add FilterKey.pinned for filtering channel lists
    • Add ChannelListSortingKey.pinnedAt
    • Add ChatChannel.membership.pinnedAt
    • Add ChatChannel.isPinned
  • Parse pinned_at in member payloads
  • Add supporting code for calling member's partial update with pinned: true using the new MemberUpdatePayload type or unsetting pinned
  • Updated the demo app and replaced the custom pinning support. Additionally added channel list filter for pinned channels.

🛠 Implementation

Pinning and unpinning works by calling partial update on the chat channel member (current user) and setting either pinned: true or unsetting this. Therefore, one could also use ChatChannelMemberController.partialUpdate(extraData:unsetProperties:completion:) where the user if is the current user id and extra data is ["pinned": .boolean(true)] or unsetProperties is set to ["pinned"]. New high-level pin and unpinning methods end up calling the same member updater's code, just make it more natural and discoverable.

Note: Pinning is per user. Meaning that if user A pins a channel with user B, then user B does not get the pinned state.

🧪 Manual Testing Notes

Pin and unpin channel

  1. Open channel list
  2. Pin a channel (debug menu > Pin channel)
    Result: Pinned channel gets a yellow background (demo app has a custom message cell)
  3. Unpin the channel (debug menu > Unpin channel)
    Result: yellow background is removed

Querying pinned channels

  1. Open channel list
  2. Pin multiple channels (debug menu > Pin channel)
  3. Open "Filter channels" menu in the toolbar > Pinned channels
    Result: Only pinned channels are displayed
  4. Unpin a channel
    Result: channel list removes the unpinned channel

Sorting

Change the demo app: DemoAppCoordinator+DemoApp.swift:L98 to

channelListQuery = .init(
                filter: .containMembers(userIds: [userCredentials.id]),
                sort: [.init(key: .pinnedAt), .init(key: .default)]
            )
  1. Launch the app
  2. Pinning a channel moves it to the top of the list
  3. Unpin a channel and the list is reordered again

☑️ 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
  • Comparison screenshots added for visual changes
  • Affected documentation updated (docusaurus, tutorial, CMS)

@laevandus laevandus added 🔧 WIP A PR that is Work in Progress 🌐 SDK: StreamChat (LLC) Tasks related to the StreamChat LLC SDK ✅ Feature An issue or PR related to a feature labels Dec 2, 2024
@laevandus laevandus requested a review from a team as a code owner December 2, 2024 13:31
Copy link

github-actions bot commented Dec 2, 2024

1 Warning
⚠️ Big PR

Generated by 🚫 Danger

@Stream-SDK-Bot
Copy link
Collaborator

SDK Size

title develop branch diff status
StreamChat 7.06 MB 7.07 MB +17 KB 🟢
StreamChatUI 4.96 MB 4.96 MB 0 KB 🟢

@Stream-SDK-Bot
Copy link
Collaborator

SDK Performance

target metric benchmark branch performance status
MessageList Hitches total duration 10 ms 10.01 ms -0.1% 🔽 🟡
Duration 2.6 s 2.54 s 2.31% 🔼 🟢
Hitch time ratio 4 ms per s 3.94 ms per s 1.5% 🔼 🟢
Frame rate 75 fps 78.04 fps 4.05% 🔼 🟢
Number of hitches 1 1.2 -20.0% 🔽 🔴

@laevandus laevandus changed the title [WIP] Pinning channels Pinning channels Dec 4, 2024
@laevandus laevandus removed the 🔧 WIP A PR that is Work in Progress label Dec 4, 2024
@Stream-SDK-Bot
Copy link
Collaborator

Stream-SDK-Bot commented Dec 4, 2024

SDK Size

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

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 good to me ✅ Can you also do this in the SwiftUI app? Most of the stuff is already in place.

Sources/StreamChat/Workers/ChannelMemberUpdater.swift Outdated Show resolved Hide resolved
nuno-vieira

This comment was marked as off-topic.

@laevandus laevandus added the 🤞 Ready For QA A PR that is Ready for QA label Dec 5, 2024
Copy link

sonarcloud bot commented Dec 5, 2024

@laevandus laevandus changed the title Pinning channels Pinning channels for the current user Dec 5, 2024
@@ -11,7 +11,7 @@ final class DemoChatChannelListItemView: ChatChannelListItemView {
if content?.searchResult?.message != nil {
return super.contentBackgroundColor
}
if AppConfig.shared.demoAppConfig.isChannelPinningEnabled && content?.channel.isPinned == true {
if content?.channel.isPinned == true {
Copy link
Member

Choose a reason for hiding this comment

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

Out of scope (but not intended 😄 ) but in the future if we have global pinning, we might need to have more than 1 property to distinguish isPinned from local only or global only 🤔

Comment on lines +8 to +11
public enum ChannelPinningScope: String {
/// Channel is pinned only for the currently connected user. Other channel members do not see channels as pinned.
case me
}
Copy link
Member

Choose a reason for hiding this comment

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

Since this not meant to be used by the customer to perform switching it should be fine. But in theory, adding a new case would be a breaking change. But I guess it is fine in this case 👍

Copy link
Member

@nuno-vieira nuno-vieira left a comment

Choose a reason for hiding this comment

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

LGTM! ✅

@testableapple testableapple added 🟢 QAed A PR that was QAed and removed 🤞 Ready For QA A PR that is Ready for QA labels Dec 5, 2024
@laevandus laevandus merged commit 8fd696a into develop Dec 5, 2024
14 checks passed
@laevandus laevandus deleted the feature/channel-pinning branch December 5, 2024 13:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
✅ Feature An issue or PR related to a feature 🟢 QAed A PR that was QAed 🌐 SDK: StreamChat (LLC) Tasks related to the StreamChat LLC SDK
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants