Skip to content

Commit c254567

Browse files
implemented inline replies
1 parent 4ee5db5 commit c254567

21 files changed

+253
-61
lines changed

Sources/StreamChatSwiftUI/ChatChannel/ChatChannelView.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ public struct ChatChannelView<Factory: ViewFactory>: View {
6868
factory.makeMessageComposerViewType(
6969
with: viewModel.channelController,
7070
messageController: viewModel.messageController,
71+
quotedMessage: $viewModel.quotedMessage,
7172
onMessageSent: viewModel.scrollToLastMessage
7273
)
7374
}
@@ -80,6 +81,8 @@ public struct ChatChannelView<Factory: ViewFactory>: View {
8081
messageDisplayInfo: messageDisplayInfo!,
8182
onBackgroundTap: {
8283
viewModel.reactionsShown = false
84+
}, onActionExecuted: { actionInfo in
85+
viewModel.messageActionExecuted(actionInfo)
8386
}
8487
)
8588
.transition(.identity)

Sources/StreamChatSwiftUI/ChatChannel/ChatChannelViewModel.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ public class ChatChannelViewModel: ObservableObject, MessagesDataSource {
8686
}
8787

8888
@Published var reactionsShown = false
89+
@Published var quotedMessage: ChatMessage?
8990

9091
var channel: ChatChannel {
9192
channelController.channel!
@@ -188,6 +189,13 @@ public class ChatChannelViewModel: ObservableObject, MessagesDataSource {
188189
UIGraphicsEndImageContext()
189190
}
190191

192+
func messageActionExecuted(_ messageActionInfo: MessageActionInfo) {
193+
utils.messageActionsResolver.resolveMessageAction(
194+
info: messageActionInfo,
195+
viewModel: self
196+
)
197+
}
198+
191199
func onViewAppear() {
192200
reactionsShown = false
193201
isActive = true

Sources/StreamChatSwiftUI/ChatChannel/Composer/DiscardAttachmentButton.swift

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,24 @@ public struct DiscardAttachmentButton: View {
2222
onDiscard(attachmentIdentifier)
2323
}
2424
}, label: {
25-
ZStack {
26-
Circle()
27-
.fill(Color.white)
28-
.frame(width: 16, height: 16)
29-
30-
Image(systemName: "xmark.circle.fill")
31-
.foregroundColor(Color.black.opacity(0.8))
32-
}
33-
.padding(.all, 4)
25+
DiscardButtonView()
3426
})
3527
}
3628
}
3729
}
30+
31+
/// View for the discard button.
32+
struct DiscardButtonView: View {
33+
34+
var body: some View {
35+
ZStack {
36+
Circle()
37+
.fill(Color.white)
38+
.frame(width: 16, height: 16)
39+
40+
Image(systemName: "xmark.circle.fill")
41+
.foregroundColor(Color.black.opacity(0.8))
42+
}
43+
.padding(.all, 4)
44+
}
45+
}

Sources/StreamChatSwiftUI/ChatChannel/Composer/MessageComposerView.swift

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,19 @@ import SwiftUI
88
/// Main view for the message composer.
99
public struct MessageComposerView<Factory: ViewFactory>: View, KeyboardReadable {
1010
@Injected(\.colors) private var colors
11+
@Injected(\.fonts) private var fonts
1112

1213
// Initial popup size, before the keyboard is shown.
1314
@State private var popupSize: CGFloat = 350
1415

1516
private var factory: Factory
17+
@Binding var quotedMessage: ChatMessage?
1618

1719
public init(
1820
viewFactory: Factory,
1921
channelController: ChatChannelController,
2022
messageController: ChatMessageController?,
23+
quotedMessage: Binding<ChatMessage?>,
2124
onMessageSent: @escaping () -> Void
2225
) {
2326
factory = viewFactory
@@ -27,6 +30,7 @@ public struct MessageComposerView<Factory: ViewFactory>: View, KeyboardReadable
2730
messageController: messageController
2831
)
2932
)
33+
_quotedMessage = quotedMessage
3034
self.onMessageSent = onMessageSent
3135
}
3236

@@ -36,6 +40,25 @@ public struct MessageComposerView<Factory: ViewFactory>: View, KeyboardReadable
3640

3741
public var body: some View {
3842
VStack(spacing: 0) {
43+
if quotedMessage != nil {
44+
ZStack {
45+
Text("Reply to Message")
46+
.font(fonts.bodyBold)
47+
48+
HStack {
49+
Spacer()
50+
Button(action: {
51+
withAnimation {
52+
quotedMessage = nil
53+
}
54+
}, label: {
55+
DiscardButtonView()
56+
})
57+
}
58+
}
59+
.frame(height: 32)
60+
}
61+
3962
HStack(alignment: .bottom) {
4063
factory.makeLeadingComposerView(state: $viewModel.pickerTypeState)
4164

@@ -44,13 +67,15 @@ public struct MessageComposerView<Factory: ViewFactory>: View, KeyboardReadable
4467
addedAssets: viewModel.addedAssets,
4568
addedFileURLs: viewModel.addedFileURLs,
4669
addedCustomAttachments: viewModel.addedCustomAttachments,
70+
quotedMessage: $quotedMessage,
4771
onCustomAttachmentTap: viewModel.customAttachmentTapped(_:),
4872
shouldScroll: viewModel.inputComposerShouldScroll,
4973
removeAttachmentWithId: viewModel.removeAttachment(with:)
5074
)
5175

5276
factory.makeTrailingComposerView(enabled: viewModel.sendButtonEnabled) {
53-
viewModel.sendMessage {
77+
viewModel.sendMessage(quotedMessage: quotedMessage) {
78+
quotedMessage = nil
5479
onMessageSent()
5580
}
5681
}
@@ -109,8 +134,8 @@ public struct ComposerInputView<Factory: ViewFactory>: View {
109134
var addedAssets: [AddedAsset]
110135
var addedFileURLs: [URL]
111136
var addedCustomAttachments: [CustomAttachment]
137+
var quotedMessage: Binding<ChatMessage?>
112138
var onCustomAttachmentTap: (CustomAttachment) -> Void
113-
114139
var removeAttachmentWithId: (String) -> Void
115140

116141
@State var textHeight: CGFloat = 34
@@ -132,6 +157,14 @@ public struct ComposerInputView<Factory: ViewFactory>: View {
132157

133158
public var body: some View {
134159
VStack {
160+
if let quotedMessage = quotedMessage.wrappedValue {
161+
QuotedMessageViewContainer(
162+
quotedMessage: quotedMessage,
163+
fillAvailableSpace: true,
164+
forceLeftToRight: true
165+
)
166+
}
167+
135168
if !addedAssets.isEmpty {
136169
AddedImageAttachmentsView(
137170
images: addedAssets,

Sources/StreamChatSwiftUI/ChatChannel/Composer/MessageComposerViewModel.swift

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import SwiftUI
88

99
/// View model for the `MessageComposerView`.
1010
public class MessageComposerViewModel: ObservableObject {
11+
@Injected(\.chatClient) private var chatClient
12+
1113
@Published var pickerState: AttachmentPickerState = .photos {
1214
didSet {
1315
if pickerState == .camera {
@@ -85,7 +87,10 @@ public class MessageComposerViewModel: ObservableObject {
8587
self.messageController = messageController
8688
}
8789

88-
public func sendMessage(completion: @escaping () -> Void) {
90+
public func sendMessage(
91+
quotedMessage: ChatMessage?,
92+
completion: @escaping () -> Void
93+
) {
8994
do {
9095
var attachments = try addedAssets.map { added in
9196
try AnyAttachmentPayload(
@@ -107,7 +112,8 @@ public class MessageComposerViewModel: ObservableObject {
107112
messageController.createNewReply(
108113
text: text,
109114
attachments: attachments,
110-
showReplyInChannel: showReplyInChannel
115+
showReplyInChannel: showReplyInChannel,
116+
quotedMessageId: quotedMessage?.id
111117
) { [weak self] in
112118
switch $0 {
113119
case .success:
@@ -119,7 +125,8 @@ public class MessageComposerViewModel: ObservableObject {
119125
} else {
120126
channelController.createNewMessage(
121127
text: text,
122-
attachments: attachments
128+
attachments: attachments,
129+
quotedMessageId: quotedMessage?.id
123130
) { [weak self] in
124131
switch $0 {
125132
case .success:

Sources/StreamChatSwiftUI/ChatChannel/MessageList/FileAttachmentView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public struct FileAttachmentsContainer: View {
1515
if let quotedMessage = message.quotedMessage {
1616
QuotedMessageViewContainer(
1717
quotedMessage: quotedMessage,
18-
message: message
18+
fillAvailableSpace: !message.attachmentCounts.isEmpty
1919
)
2020
}
2121

Sources/StreamChatSwiftUI/ChatChannel/MessageList/GiphyAttachmentView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public struct GiphyAttachmentView: View {
2121
if let quotedMessage = message.quotedMessage {
2222
QuotedMessageViewContainer(
2323
quotedMessage: quotedMessage,
24-
message: message
24+
fillAvailableSpace: !message.attachmentCounts.isEmpty
2525
)
2626
}
2727

Sources/StreamChatSwiftUI/ChatChannel/MessageList/ImageAttachmentView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public struct ImageAttachmentContainer: View {
2222
if let quotedMessage = message.quotedMessage {
2323
QuotedMessageViewContainer(
2424
quotedMessage: quotedMessage,
25-
message: message
25+
fillAvailableSpace: !message.attachmentCounts.isEmpty
2626
)
2727
}
2828

Sources/StreamChatSwiftUI/ChatChannel/MessageList/LinkAttachmentView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public struct LinkAttachmentContainer: View {
2626
if let quotedMessage = message.quotedMessage {
2727
QuotedMessageViewContainer(
2828
quotedMessage: quotedMessage,
29-
message: message
29+
fillAvailableSpace: !message.attachmentCounts.isEmpty
3030
)
3131
}
3232

Sources/StreamChatSwiftUI/ChatChannel/MessageList/MessageBubble.swift

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ public struct MessageBubbleModifier: ViewModifier {
1313
var isFirst: Bool
1414
var injectedBackgroundColor: UIColor?
1515
var cornerRadius: CGFloat = 18
16+
var forceLeftToRight = false
1617

1718
public func body(content: Content) -> some View {
1819
content
@@ -30,7 +31,7 @@ public struct MessageBubbleModifier: ViewModifier {
3031
return [.topLeft, .topRight, .bottomLeft, .bottomRight]
3132
}
3233

33-
if message.isSentByCurrentUser {
34+
if message.isSentByCurrentUser && !forceLeftToRight {
3435
return [.topLeft, .topRight, .bottomLeft]
3536
} else {
3637
return [.topLeft, .topRight, .bottomRight]
@@ -110,14 +111,16 @@ extension View {
110111
for message: ChatMessage,
111112
isFirst: Bool,
112113
backgroundColor: UIColor? = nil,
113-
cornerRadius: CGFloat = 18
114+
cornerRadius: CGFloat = 18,
115+
forceLeftToRight: Bool = false
114116
) -> some View {
115117
modifier(
116118
MessageBubbleModifier(
117119
message: message,
118120
isFirst: isFirst,
119121
injectedBackgroundColor: backgroundColor,
120-
cornerRadius: cornerRadius
122+
cornerRadius: cornerRadius,
123+
forceLeftToRight: forceLeftToRight
121124
)
122125
)
123126
}

0 commit comments

Comments
 (0)