Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 3f4b97d

Browse filesBrowse files
authored
Add support for editing attachments (#809)
* Fix scrolling to the last message when editing a message * Add support for editing message attachments * Remove edit action from giphy message * Fix being able to long press an unsent giphy message * Fix being able to swipe to reply an unsent giphy * Fix fill composer function causing main thread warning * Update CHANGELOG.md * Fix typo in deprecated message * Fix double tapping on ephemeral giphy opening message actions * Rename `inputAttachmentsAsPayloads()` -> `convertAddedAssetsToPayloads()` * Add test coverage to swipe to reply * Add test coverage to giphy edit action * Extract attachments convert to a component so that it can be tested and reused * Add test coverage to filling composer with edited message * Update CHANGELOG.md * Added back the fillComposer function again
1 parent 122dafb commit 3f4b97d
Copy full SHA for 3f4b97d
Expand file treeCollapse file tree

18 files changed

+642
-96
lines changed

‎CHANGELOG.md

Copy file name to clipboardExpand all lines: CHANGELOG.md
+8Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
33

44
# Upcoming
55

6+
### ✅ Added
7+
- Add support for editing message attachments [#806](https://github.com/GetStream/stream-chat-swiftui/pull/806)
8+
### 🐞 Fixed
9+
- Fix scrolling to the bottom when editing a message [#806](https://github.com/GetStream/stream-chat-swiftui/pull/806)
10+
- Fix having message edit action on Giphy messages [#806](https://github.com/GetStream/stream-chat-swiftui/pull/806)
11+
- Fix being able to long press an unsent Giphy message [#806](https://github.com/GetStream/stream-chat-swiftui/pull/806)
12+
- Fix being able to swipe to reply an unsent Giphy message [#806](https://github.com/GetStream/stream-chat-swiftui/pull/806)
613
### 🔄 Changed
14+
- Deprecated `ComposerConfig.attachmentPayloadConverter` in favour of `MessageComposerViewModel.convertAddedAssetsToPayloads()` [#806](https://github.com/GetStream/stream-chat-swiftui/pull/806)
715

816
# [4.77.0](https://github.com/GetStream/stream-chat-swiftui/releases/tag/4.77.0)
917
_April 10, 2025_

‎Sources/StreamChatSwiftUI/ChatChannel/ChatChannelView.swift

Copy file name to clipboardExpand all lines: Sources/StreamChatSwiftUI/ChatChannel/ChatChannelView.swift
+3-1Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,9 @@ public struct ChatChannelView<Factory: ViewFactory>: View, KeyboardReadable {
115115
messageController: viewModel.messageController,
116116
quotedMessage: $viewModel.quotedMessage,
117117
editedMessage: $viewModel.editedMessage,
118-
onMessageSent: viewModel.scrollToLastMessage
118+
onMessageSent: {
119+
viewModel.messageSentTapped()
120+
}
119121
)
120122
.opacity((
121123
utils.messageListConfig.messagePopoverEnabled && messageDisplayInfo != nil && !viewModel

‎Sources/StreamChatSwiftUI/ChatChannel/ChatChannelViewModel.swift

Copy file name to clipboardExpand all lines: Sources/StreamChatSwiftUI/ChatChannel/ChatChannelViewModel.swift
+9-1Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,15 @@ open class ChatChannelViewModel: ObservableObject, MessagesDataSource {
264264
}
265265
}
266266
}
267-
267+
268+
/// The user tapped on the message sent button.
269+
public func messageSentTapped() {
270+
// only scroll if the message is not being edited
271+
if editedMessage == nil {
272+
scrollToLastMessage()
273+
}
274+
}
275+
268276
public func jumpToMessage(messageId: String) -> Bool {
269277
if messageId == .unknownMessageId {
270278
if firstUnreadMessageId == nil, let lastReadMessageId {

‎Sources/StreamChatSwiftUI/ChatChannel/Composer/ComposerConfig.swift

Copy file name to clipboardExpand all lines: Sources/StreamChatSwiftUI/ChatChannel/Composer/ComposerConfig.swift
+11-2Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,14 @@ public struct ComposerConfig {
1717
public var inputPaddingsConfig: PaddingsConfig
1818
public var adjustMessageOnSend: (String) -> (String)
1919
public var adjustMessageOnRead: (String) -> (String)
20+
21+
@available(
22+
*,
23+
deprecated,
24+
message: """
25+
Override the MessageComposerViewModel.inputAttachmentsAsPayloads() in order to convert the message attachments to payloads.
26+
"""
27+
)
2028
public var attachmentPayloadConverter: (ChatMessage) -> [AnyAttachmentPayload]
2129

2230
public init(
@@ -44,8 +52,9 @@ public struct ComposerConfig {
4452
self.isVoiceRecordingEnabled = isVoiceRecordingEnabled
4553
}
4654

47-
public static var defaultAttachmentPayloadConverter: (ChatMessage) -> [AnyAttachmentPayload] = { message in
48-
message.allAttachments.toAnyAttachmentPayload()
55+
public static var defaultAttachmentPayloadConverter: (ChatMessage) -> [AnyAttachmentPayload] = { _ in
56+
/// This now returns empty array by default since attachmentPayloadConverter has been deprecated.
57+
[]
4958
}
5059
}
5160

‎Sources/StreamChatSwiftUI/ChatChannel/Composer/ComposerModels.swift

Copy file name to clipboardExpand all lines: Sources/StreamChatSwiftUI/ChatChannel/Composer/ComposerModels.swift
+16-5Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,25 +27,34 @@ public struct AddedAsset: Identifiable, Equatable {
2727
public let url: URL
2828
public let type: AssetType
2929
public var extraData: [String: RawJSON] = [:]
30-
30+
31+
/// The payload of the attachment, in case the attachment has been uploaded to server already.
32+
/// This is mostly used when editing an existing message that contains attachments.
33+
public var payload: AttachmentPayload?
34+
3135
public init(
3236
image: UIImage,
3337
id: String,
3438
url: URL,
3539
type: AssetType,
36-
extraData: [String: RawJSON] = [:]
40+
extraData: [String: RawJSON] = [:],
41+
payload: AttachmentPayload? = nil
3742
) {
3843
self.image = image
3944
self.id = id
4045
self.url = url
4146
self.type = type
4247
self.extraData = extraData
48+
self.payload = payload
4349
}
4450
}
4551

4652
extension AddedAsset {
4753
func toAttachmentPayload() throws -> AnyAttachmentPayload {
48-
try AnyAttachmentPayload(
54+
if let payload = self.payload {
55+
return AnyAttachmentPayload(payload: payload)
56+
}
57+
return try AnyAttachmentPayload(
4958
localFileURL: url,
5059
attachmentType: type == .video ? .video : .image,
5160
extraData: extraData
@@ -63,7 +72,8 @@ extension AnyChatMessageAttachment {
6372
id: imageAttachment.id.rawValue,
6473
url: imageAttachment.imageURL,
6574
type: .image,
66-
extraData: imageAttachment.extraData ?? [:]
75+
extraData: imageAttachment.extraData ?? [:],
76+
payload: imageAttachment.payload
6777
)
6878
} else if let videoAttachment = attachment(payloadType: VideoAttachmentPayload.self),
6979
let thumbnail = imageThumbnail(for: videoAttachment.payload) {
@@ -72,7 +82,8 @@ extension AnyChatMessageAttachment {
7282
id: videoAttachment.id.rawValue,
7383
url: videoAttachment.videoURL,
7484
type: .video,
75-
extraData: videoAttachment.extraData ?? [:]
85+
extraData: videoAttachment.extraData ?? [:],
86+
payload: videoAttachment.payload
7687
)
7788
}
7889
return nil

‎Sources/StreamChatSwiftUI/ChatChannel/Composer/MessageComposerView.swift

Copy file name to clipboardExpand all lines: Sources/StreamChatSwiftUI/ChatChannel/Composer/MessageComposerView.swift
+4-3Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,11 @@ public struct MessageComposerView<Factory: ViewFactory>: View, KeyboardReadable
102102
quotedMessage: quotedMessage,
103103
editedMessage: editedMessage
104104
) {
105+
// Calling onMessageSent() before erasing the edited and quoted message
106+
// so that onMessageSent can use them for state handling.
107+
onMessageSent()
105108
quotedMessage = nil
106109
editedMessage = nil
107-
onMessageSent()
108110
}
109111
}
110112
.environmentObject(viewModel)
@@ -208,11 +210,10 @@ public struct MessageComposerView<Factory: ViewFactory>: View, KeyboardReadable
208210
)
209211
.modifier(factory.makeComposerViewModifier())
210212
.onChange(of: editedMessage) { _ in
211-
viewModel.text = editedMessage?.text ?? ""
213+
viewModel.fillEditedMessage(editedMessage)
212214
if editedMessage != nil {
213215
becomeFirstResponder()
214216
editedMessageWillShow = true
215-
viewModel.selectedRangeLocation = editedMessage?.text.count ?? 0
216217
}
217218
}
218219
.onAppear(perform: {

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.