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

Implemented pinning channels in the demo app #419

Merged
merged 4 commits into from
Jan 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion DemoAppSwiftUI/AppDelegate.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright © 2023 Stream.io Inc. All rights reserved.
// Copyright © 2024 Stream.io Inc. All rights reserved.
//

import Sentry
Expand Down
2 changes: 1 addition & 1 deletion DemoAppSwiftUI/AppleMessageComposerView.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright © 2023 Stream.io Inc. All rights reserved.
// Copyright © 2024 Stream.io Inc. All rights reserved.
//

import StreamChat
Expand Down
2 changes: 1 addition & 1 deletion DemoAppSwiftUI/CreateGroupView.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright © 2023 Stream.io Inc. All rights reserved.
// Copyright © 2024 Stream.io Inc. All rights reserved.
//

import StreamChat
Expand Down
2 changes: 1 addition & 1 deletion DemoAppSwiftUI/CreateGroupViewModel.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright © 2023 Stream.io Inc. All rights reserved.
// Copyright © 2024 Stream.io Inc. All rights reserved.
//

import StreamChat
Expand Down
2 changes: 1 addition & 1 deletion DemoAppSwiftUI/CustomAttachment.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright © 2023 Stream.io Inc. All rights reserved.
// Copyright © 2024 Stream.io Inc. All rights reserved.
//

import StreamChat
Expand Down
2 changes: 1 addition & 1 deletion DemoAppSwiftUI/CustomChannelHeader.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright © 2023 Stream.io Inc. All rights reserved.
// Copyright © 2024 Stream.io Inc. All rights reserved.
//

import StreamChat
Expand Down
2 changes: 1 addition & 1 deletion DemoAppSwiftUI/CustomComposerAttachmentView.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright © 2023 Stream.io Inc. All rights reserved.
// Copyright © 2024 Stream.io Inc. All rights reserved.
//

import Foundation
Expand Down
20 changes: 18 additions & 2 deletions DemoAppSwiftUI/DemoAppSwiftUIApp.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright © 2023 Stream.io Inc. All rights reserved.
// Copyright © 2024 Stream.io Inc. All rights reserved.
//

import StreamChat
Expand All @@ -14,6 +14,8 @@ struct DemoAppSwiftUIApp: App {

@ObservedObject var appState = AppState.shared
@ObservedObject var notificationsHandler = NotificationsHandler.shared

@State var channelListController: ChatChannelListController?

var body: some Scene {
WindowGroup {
Expand All @@ -26,17 +28,31 @@ struct DemoAppSwiftUIApp: App {
if notificationsHandler.notificationChannelId != nil {
ChatChannelListView(
viewFactory: DemoAppFactory.shared,
channelListController: channelListController,
selectedChannelId: notificationsHandler.notificationChannelId
)
} else {
ChatChannelListView(
viewFactory: DemoAppFactory.shared
viewFactory: DemoAppFactory.shared,
channelListController: channelListController
)
}
}
}
.onChange(of: appState.userState) { newValue in
if newValue == .loggedIn {
if let currentUserId = chatClient.currentUserId {
let pinnedByKey = ChatChannel.isPinnedBy(keyForUserId: currentUserId)
let channelListQuery = ChannelListQuery(
filter: .containMembers(userIds: [currentUserId]),
sort: [
.init(key: .custom(keyPath: \.isPinned, key: pinnedByKey), isAscending: true),
.init(key: .lastMessageAt),
.init(key: .updatedAt)
]
)
channelListController = chatClient.channelListController(query: channelListQuery)
}
notificationsHandler.setupRemoteNotifications()
}
}
Expand Down
2 changes: 1 addition & 1 deletion DemoAppSwiftUI/DemoUser.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright © 2023 Stream.io Inc. All rights reserved.
// Copyright © 2024 Stream.io Inc. All rights reserved.
//

import Foundation
Expand Down
2 changes: 1 addition & 1 deletion DemoAppSwiftUI/GroupNameView.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright © 2023 Stream.io Inc. All rights reserved.
// Copyright © 2024 Stream.io Inc. All rights reserved.
//

import StreamChatSwiftUI
Expand Down
2 changes: 1 addition & 1 deletion DemoAppSwiftUI/LaunchAnimationState.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright © 2023 Stream.io Inc. All rights reserved.
// Copyright © 2024 Stream.io Inc. All rights reserved.
//

import SwiftUI
Expand Down
2 changes: 1 addition & 1 deletion DemoAppSwiftUI/LaunchScreen.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright © 2023 Stream.io Inc. All rights reserved.
// Copyright © 2024 Stream.io Inc. All rights reserved.
//

import SwiftUI
Expand Down
2 changes: 1 addition & 1 deletion DemoAppSwiftUI/Localizable.strings
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright © 2023 Stream.io Inc. All rights reserved.
// Copyright © 2024 Stream.io Inc. All rights reserved.
//

"channel.name.and" = "and";
Expand Down
2 changes: 1 addition & 1 deletion DemoAppSwiftUI/LoginView.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright © 2023 Stream.io Inc. All rights reserved.
// Copyright © 2024 Stream.io Inc. All rights reserved.
//

import StreamChatSwiftUI
Expand Down
2 changes: 1 addition & 1 deletion DemoAppSwiftUI/LoginViewModel.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright © 2023 Stream.io Inc. All rights reserved.
// Copyright © 2024 Stream.io Inc. All rights reserved.
//

import StreamChat
Expand Down
2 changes: 1 addition & 1 deletion DemoAppSwiftUI/NewChatView.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright © 2023 Stream.io Inc. All rights reserved.
// Copyright © 2024 Stream.io Inc. All rights reserved.
//

import StreamChat
Expand Down
2 changes: 1 addition & 1 deletion DemoAppSwiftUI/NewChatViewModel.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright © 2023 Stream.io Inc. All rights reserved.
// Copyright © 2024 Stream.io Inc. All rights reserved.
//

import StreamChat
Expand Down
2 changes: 1 addition & 1 deletion DemoAppSwiftUI/NotificationsHandler.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright © 2023 Stream.io Inc. All rights reserved.
// Copyright © 2024 Stream.io Inc. All rights reserved.
//

import StreamChat
Expand Down
182 changes: 182 additions & 0 deletions DemoAppSwiftUI/PinChannelHelpers.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
//
// Copyright © 2024 Stream.io Inc. All rights reserved.
//

import StreamChat
import StreamChatSwiftUI
import SwiftUI

extension ChatChannel {
static func isPinnedBy(keyForUserId userId: UserId) -> String {
"is_pinned_by_\(userId)"
}

var isPinned: Bool {
guard let userId = membership?.id else { return false }
let key = Self.isPinnedBy(keyForUserId: userId)
return extraData[key]?.boolValue ?? false
}
}

struct DemoAppChatChannelListItem: View {

@Injected(\.fonts) private var fonts
@Injected(\.colors) private var colors
@Injected(\.utils) private var utils
@Injected(\.images) private var images
@Injected(\.chatClient) private var chatClient

var channel: ChatChannel
var channelName: String
var injectedChannelInfo: InjectedChannelInfo?
var avatar: UIImage
var onlineIndicatorShown: Bool
var disabled = false
var onItemTap: (ChatChannel) -> Void

public var body: some View {
Button {
onItemTap(channel)
} label: {
HStack {
ChannelAvatarView(
avatar: avatar,
showOnlineIndicator: onlineIndicatorShown
)

VStack(alignment: .leading, spacing: 4) {
HStack {
ChatTitleView(name: channelName)

Spacer()

if injectedChannelInfo == nil && channel.unreadCount != .noUnread {
UnreadIndicatorView(
unreadCount: channel.unreadCount.messages
)
}
}

HStack {
subtitleView

Spacer()

HStack(spacing: 4) {
if shouldShowReadEvents {
MessageReadIndicatorView(
readUsers: channel.readUsers(
currentUserId: chatClient.currentUserId,
message: channel.latestMessages.first
),
showReadCount: false
)
}
SubtitleText(text: injectedChannelInfo?.timestamp ?? channel.timestampText)
.accessibilityIdentifier("timestampView")
}
}
}
}
.padding(.all, 8)
}
.foregroundColor(.black)
.disabled(disabled)
.background(channel.isPinned ? Color(colors.pinnedBackground) : .clear)
.id("\(channel.id)-\(channel.isPinned ? "pinned" : "not-pinned")-base")
}

private var subtitleView: some View {
HStack(spacing: 4) {
if let image = image {
Image(uiImage: image)
.customizable()
.frame(maxHeight: 12)
.foregroundColor(Color(colors.subtitleText))
} else {
if channel.shouldShowTypingIndicator {
TypingIndicatorView()
}
}
SubtitleText(text: injectedChannelInfo?.subtitle ?? channel.subtitleText)
Spacer()
}
.accessibilityIdentifier("subtitleView")
}

private var shouldShowReadEvents: Bool {
if let message = channel.latestMessages.first,
message.isSentByCurrentUser,
!message.isDeleted {
return channel.config.readEventsEnabled
}

return false
}

private var image: UIImage? {
if channel.isMuted {
return images.muted
}
return nil
}
}

struct DemoAppChatChannelNavigatableListItem<ChannelDestination: View>: View {
private var channel: ChatChannel
private var channelName: String
private var avatar: UIImage
private var disabled: Bool
private var onlineIndicatorShown: Bool
@Binding private var selectedChannel: ChannelSelectionInfo?
private var channelDestination: (ChannelSelectionInfo) -> ChannelDestination
private var onItemTap: (ChatChannel) -> Void

init(
channel: ChatChannel,
channelName: String,
avatar: UIImage,
onlineIndicatorShown: Bool,
disabled: Bool = false,
selectedChannel: Binding<ChannelSelectionInfo?>,
channelDestination: @escaping (ChannelSelectionInfo) -> ChannelDestination,
onItemTap: @escaping (ChatChannel) -> Void
) {
self.channel = channel
self.channelName = channelName
self.channelDestination = channelDestination
self.onItemTap = onItemTap
self.avatar = avatar
self.onlineIndicatorShown = onlineIndicatorShown
self.disabled = disabled
_selectedChannel = selectedChannel
}

public var body: some View {
ZStack {
DemoAppChatChannelListItem(
channel: channel,
channelName: channelName,
injectedChannelInfo: injectedChannelInfo,
avatar: avatar,
onlineIndicatorShown: onlineIndicatorShown,
disabled: disabled,
onItemTap: onItemTap
)

NavigationLink(
tag: channel.channelSelectionInfo,
selection: $selectedChannel
) {
LazyView(channelDestination(channel.channelSelectionInfo))
} label: {
EmptyView()
}
}
.id("\(channel.id)-\(channel.isPinned ? "pinned" : "not-pinned")-base")
}

private var injectedChannelInfo: InjectedChannelInfo? {
selectedChannel?.channel.cid.rawValue == channel.cid.rawValue ? selectedChannel?.injectedChannelInfo : nil
}
}
2 changes: 1 addition & 1 deletion DemoAppSwiftUI/SceneDelegate.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright © 2023 Stream.io Inc. All rights reserved.
// Copyright © 2024 Stream.io Inc. All rights reserved.
//

import UIKit
Expand Down
2 changes: 1 addition & 1 deletion DemoAppSwiftUI/UserRepository.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright © 2023 Stream.io Inc. All rights reserved.
// Copyright © 2024 Stream.io Inc. All rights reserved.
//

import Foundation
Expand Down
Loading
Loading