Skip to content

Commit 2e59f44

Browse files
[SWU-72] Implemented message search
1 parent 376571b commit 2e59f44

File tree

40 files changed

+742
-96
lines changed

40 files changed

+742
-96
lines changed

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,18 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
33

44
# Upcoming
55

6+
### ✅ Added
7+
- Pinning of a message
8+
- Display users who reacted to a message
9+
- Message Search
10+
- Customization of channel list separators
11+
12+
### 🐞 Fixed
13+
- Bug with image attachments selection and display
14+
- Reactions issues on iPad
15+
616
### 🔄 Changed
17+
- Creation method of channel destination
718

819
# [4.8.0](https://github.com/GetStream/stream-chat-swiftui/releases/tag/4.8.0)
920
_January 18, 2022_

DemoAppSwiftUI/iMessagePocView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ struct iMessagePocView: View {
5050
onlineIndicatorShown: viewModel.onlineIndicatorShown(for:),
5151
imageLoader: channelHeaderLoader.image(for:),
5252
onItemTap: { channel in
53-
viewModel.selectedChannel = channel
53+
viewModel.selectedChannel = ChannelSelectionInfo(channel: channel, message: nil)
5454
},
5555
onItemAppear: viewModel.checkForChannels(index:),
5656
channelNaming: viewModel.name(forChannel:),

Sources/StreamChatSwiftUI/ChatChannel/ChatChannelView.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@ public struct ChatChannelView<Factory: ViewFactory>: View {
1818
public init(
1919
viewFactory: Factory,
2020
channelController: ChatChannelController,
21-
messageController: ChatMessageController? = nil
21+
messageController: ChatMessageController? = nil,
22+
scrollToMessage: ChatMessage? = nil
2223
) {
2324
_viewModel = StateObject(
2425
wrappedValue: ViewModelsFactory.makeChannelViewModel(
2526
with: channelController,
26-
messageController: messageController
27+
messageController: messageController,
28+
scrollToMessage: scrollToMessage
2729
)
2830
)
2931
factory = viewFactory

Sources/StreamChatSwiftUI/ChatChannel/ChatChannelViewModel.swift

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@ open class ChatChannelViewModel: ObservableObject, MessagesDataSource {
108108

109109
public init(
110110
channelController: ChatChannelController,
111-
messageController: ChatMessageController? = nil
111+
messageController: ChatMessageController? = nil,
112+
scrollToMessage: ChatMessage? = nil
112113
) {
113114
self.channelController = channelController
114115
channelController.synchronize()
@@ -125,6 +126,10 @@ open class ChatChannelViewModel: ObservableObject, MessagesDataSource {
125126
channelDataSource.delegate = self
126127
messages = channelDataSource.messages
127128

129+
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { [weak self] in
130+
self?.scrolledId = scrollToMessage?.messageId
131+
}
132+
128133
NotificationCenter.default.addObserver(
129134
self,
130135
selector: #selector(didReceiveMemoryWarning),
@@ -177,7 +182,7 @@ open class ChatChannelViewModel: ObservableObject, MessagesDataSource {
177182
listId = UUID().uuidString
178183
}
179184

180-
if !showScrollToLatestButton {
185+
if !showScrollToLatestButton && scrolledId == nil {
181186
scrollToLastMessage()
182187
}
183188
}
@@ -238,20 +243,6 @@ open class ChatChannelViewModel: ObservableObject, MessagesDataSource {
238243
}
239244
}
240245

241-
private func topVC() -> UIViewController? {
242-
let keyWindow = UIApplication.shared.windows.filter { $0.isKeyWindow }.first
243-
244-
if var topController = keyWindow?.rootViewController {
245-
while let presentedViewController = topController.presentedViewController {
246-
topController = presentedViewController
247-
}
248-
249-
return topController
250-
}
251-
252-
return nil
253-
}
254-
255246
private func save(lastDate: Date) {
256247
currentDate = lastDate
257248
timer?.invalidate()

Sources/StreamChatSwiftUI/ChatChannel/MessageList/MessageContainerView.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,10 +166,14 @@ struct MessageContainerView<Factory: ViewFactory>: View {
166166
.padding(.horizontal, paddingValue)
167167
.padding(.bottom, showsAllInfo || isMessagePinned ? paddingValue : 2)
168168
.padding(.top, isLast ? paddingValue : 0)
169-
.background(isMessagePinned ? Color(colors.pinnedBackground) : nil)
169+
.background(isMessagePinned || shouldAnimateBackground ? Color(colors.pinnedBackground) : nil)
170170
.padding(.bottom, isMessagePinned ? paddingValue / 2 : 0)
171171
}
172172

173+
private var shouldAnimateBackground: Bool {
174+
scrolledId == message.messageId
175+
}
176+
173177
private var isMessagePinned: Bool {
174178
message.pinDetails != nil
175179
}

Sources/StreamChatSwiftUI/ChatChannel/MessageList/MessageListView.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,13 @@ struct MessageListView<Factory: ViewFactory>: View, KeyboardReadable {
110110
.frame(minWidth: self.width, minHeight: height)
111111
.onChange(of: scrolledId) { scrolledId in
112112
if let scrolledId = scrolledId {
113-
self.scrolledId = nil
113+
if scrolledId == messages.first?.messageId {
114+
self.scrolledId = nil
115+
} else {
116+
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
117+
self.scrolledId = nil
118+
}
119+
}
114120
withAnimation {
115121
scrollView.scrollTo(scrolledId, anchor: .bottom)
116122
}

Sources/StreamChatSwiftUI/ChatChannel/Reactions/ReactionsOverlayView.swift

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ public struct ReactionsOverlayView<Factory: ViewFactory>: View {
8181
scrolledId: .constant(nil)
8282
)
8383
.offset(
84-
x: messageDisplayInfo.frame.origin.x
84+
x: messageDisplayInfo.frame.origin.x - diffWidth
8585
)
8686
.overlay(
8787
channel.config.reactionsEnabled ?
@@ -94,7 +94,7 @@ public struct ReactionsOverlayView<Factory: ViewFactory>: View {
9494
}
9595
)
9696
.offset(
97-
x: messageDisplayInfo.frame.origin.x,
97+
x: messageDisplayInfo.frame.origin.x - diffWidth,
9898
y: -24
9999
)
100100
: nil
@@ -148,6 +148,16 @@ public struct ReactionsOverlayView<Factory: ViewFactory>: View {
148148
}
149149
}
150150

151+
private var diffWidth: CGFloat {
152+
if UIDevice.current.userInterfaceIdiom == .pad {
153+
let screenWidth = UIScreen.main.bounds.size.width
154+
let viewWidth = topVC()?.view.frame.width ?? 0
155+
return screenWidth - viewWidth
156+
} else {
157+
return 0
158+
}
159+
}
160+
151161
private var originY: CGFloat {
152162
let bottomPopupOffset =
153163
messageDisplayInfo.showsMessageActions ? messageActionsSize : userReactionsPopupHeight
@@ -160,7 +170,7 @@ public struct ReactionsOverlayView<Factory: ViewFactory>: View {
160170
} else if originY > maxOrigin {
161171
originY = maxOrigin
162172
}
163-
173+
164174
return originY
165175
}
166176

Sources/StreamChatSwiftUI/ChatChannel/Utils/ChatChannelHelpers.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,3 +75,30 @@ public struct BottomLeftView<Content: View>: View {
7575
}
7676
}
7777
}
78+
79+
/// Returns the top most view controller.
80+
func topVC() -> UIViewController? {
81+
let keyWindow = UIApplication.shared.windows.filter { $0.isKeyWindow }.first
82+
83+
if var topController = keyWindow?.rootViewController {
84+
while let presentedViewController = topController.presentedViewController {
85+
topController = presentedViewController
86+
}
87+
88+
if UIDevice.current.userInterfaceIdiom == .pad {
89+
let children = topController.children
90+
if !children.isEmpty {
91+
let splitVC = children[0]
92+
let sideVCs = splitVC.children
93+
if sideVCs.count > 1 {
94+
topController = sideVCs[1]
95+
return topController
96+
}
97+
}
98+
}
99+
100+
return topController
101+
}
102+
103+
return nil
104+
}

Sources/StreamChatSwiftUI/ChatChannelList/ChatChannelDeepLink.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ import SwiftUI
77

88
/// View providing support for deeplinking.
99
public struct ChannelDeepLink<ChannelDestination: View>: View {
10-
private var channelDestination: (ChatChannel) -> ChannelDestination
11-
@Binding var deeplinkChannel: ChatChannel?
10+
private var channelDestination: (ChannelSelectionInfo) -> ChannelDestination
11+
@Binding var deeplinkChannel: ChannelSelectionInfo?
1212

1313
public init(
14-
deeplinkChannel: Binding<ChatChannel?>,
15-
channelDestination: @escaping (ChatChannel) -> ChannelDestination
14+
deeplinkChannel: Binding<ChannelSelectionInfo?>,
15+
channelDestination: @escaping (ChannelSelectionInfo) -> ChannelDestination
1616
) {
1717
self.channelDestination = channelDestination
1818
_deeplinkChannel = deeplinkChannel

Sources/StreamChatSwiftUI/ChatChannelList/ChatChannelHelperViews.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,21 @@ public struct AvatarView: View {
5555
}
5656
}
5757

58+
struct ChatTitleView: View {
59+
60+
@Injected(\.fonts) private var fonts
61+
@Injected(\.colors) private var colors
62+
63+
var name: String
64+
65+
var body: some View {
66+
Text(name)
67+
.lineLimit(1)
68+
.font(fonts.bodyBold)
69+
.foregroundColor(Color(colors.text))
70+
}
71+
}
72+
5873
extension CGSize {
5974
/// Default size of the avatar used in the channel list.
6075
public static var defaultAvatarSize: CGSize = CGSize(width: 48, height: 48)

0 commit comments

Comments
 (0)