Skip to content

Commit

Permalink
Implemented pinning channels in the demo app (#419)
Browse files Browse the repository at this point in the history
  • Loading branch information
martinmitrevski authored Jan 2, 2024
1 parent b4b1d4c commit 29c617e
Show file tree
Hide file tree
Showing 353 changed files with 632 additions and 803 deletions.
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

0 comments on commit 29c617e

Please sign in to comment.