Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the βοΈ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
β¨ Finishing Touchesπ§ͺ Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
| import StreamChat | ||
| import SwiftUI | ||
|
|
||
| struct LazyLoadingImage: View { |
There was a problem hiding this comment.
This was just moved to a separate file, implementation is unchanged.
| import StreamChat | ||
| import SwiftUI | ||
|
|
||
| public final class MediaAttachment: Identifiable, Equatable, Sendable { |
There was a problem hiding this comment.
This was just moved to a separate file, but with addition of originalWidth and height needed for layout. It used to be in ImageAttachmentView.swift but that has been deleted.
| // Giphy | ||
| if messageTypeResolver.hasGiphyAttachment(message: message) { | ||
| factory.makeGiphyAttachmentView( | ||
| options: GiphyAttachmentViewOptions( | ||
| message: message, | ||
| isFirst: isFirst, | ||
| availableWidth: width, | ||
| scrolledId: $scrolledId | ||
| ) | ||
| ) | ||
| } |
There was a problem hiding this comment.
Should not be here, delete
Sources/StreamChatSwiftUI/ChatMessageList/MessageMediaAttachmentsContainerView.swift
Outdated
Show resolved
Hide resolved
Generated by π« Danger |
There was a problem hiding this comment.
This is actually OK. I guess I should change the test since it looks odd.
# Conflicts: # Sources/StreamChatSwiftUI/ChatMessageList/ImageAttachmentView.swift
martinmitrevski
left a comment
There was a problem hiding this comment.
Looks good to me, left few smaller comments. Also, good to re-check the spacing between first row/column in the image attachment picker when there are 4 of them, I think it's too small?
| AttachmentTextView(factory: factory, message: message) | ||
| .frame(maxWidth: .infinity) | ||
| VStack(spacing: 2) { | ||
| ForEach(message.voiceRecordingAttachments, id: \.self) { attachment in |
There was a problem hiding this comment.
we need to teach AI to not do this :)
There was a problem hiding this comment.
if these are not identifiable, we can do it in a follow up PR
There was a problem hiding this comment.
This is actually existing code and not AI generated.
| scrolledId: $scrolledId | ||
| ) | ||
| VStack(spacing: 4) { | ||
| ForEach(message.fileAttachments, id: \.self) { attachment in |
There was a problem hiding this comment.
This is also existing code, just moved.
| } | ||
|
|
||
| private var backgroundColor: Color { | ||
| let attachmentCounts = message.attachmentCounts |
There was a problem hiding this comment.
seems like we're repeating this stuff, maybe we can centralize this logic?
There was a problem hiding this comment.
Yeah, something similar to MessagePreviewResolver π€
| injectedBackgroundColor: colors.highlightedAccentBackground1 | ||
| ) | ||
| public var body: some View { | ||
| if !message.linkAttachments.isEmpty { |
There was a problem hiding this comment.
feels weird to have this without the container - shouldn't this be handled somewhere up? But on the other hand, good to have protection against crashes.
There was a problem hiding this comment.
Yeah agree, it feels like the view should already accept the link attachments directly to avoid having empty link attachments π€
There was a problem hiding this comment.
This is existing code and I think it is because attachment views have inits where it just takes message. Should be refactored separately. Same issue with giphy attachment view.
There was a problem hiding this comment.
Added a separate ticket for this: https://linear.app/stream/issue/IOS-1470/v5swiftui-pass-link-and-giphy-attachment-to-the-container-directly
| guard showsBubble else { return 0 } | ||
| // Single voice and file don't have extra padding | ||
| let attachmentCounts = message.attachmentCounts | ||
| if message.text.isEmpty, attachmentCounts.count == 1, attachmentCounts[.file] == 1 || attachmentCounts[.voiceRecording] == 1 { |
There was a problem hiding this comment.
this one is slightly different, but still applicable to the other case, I think we can easily make mistakes having this spread in multiple places.
| return videoSources + imageSources | ||
| } | ||
|
|
||
| private func containerSize(for itemCount: Int) -> CGSize { |
There was a problem hiding this comment.
we need to test this on ipads
nuno-vieira
left a comment
There was a problem hiding this comment.
Looks great overall, added some comments π
Sources/StreamChatSwiftUI/ChatMessageList/AsyncVoiceMessages/VoiceRecordingContainerView.swift
Outdated
Show resolved
Hide resolved
| /// - Parameters: | ||
| /// - factory: The view factory to create the quoted message view. | ||
| /// - quotedMessage: The quoted message to display. | ||
| /// - availableWidth: The available width for the quoted message view. |
Sources/StreamChatSwiftUI/ChatMessageList/FileAttachmentView.swift
Outdated
Show resolved
Hide resolved
| } | ||
|
|
||
| private var backgroundColor: Color { | ||
| let attachmentCounts = message.attachmentCounts |
There was a problem hiding this comment.
Yeah, something similar to MessagePreviewResolver π€
| injectedBackgroundColor: colors.highlightedAccentBackground1 | ||
| ) | ||
| public var body: some View { | ||
| if !message.linkAttachments.isEmpty { |
There was a problem hiding this comment.
Yeah agree, it feels like the view should already accept the link attachments directly to avoid having empty link attachments π€
...__Snapshots__/ChatQuotedMessageView_Tests/test_chatQuotedMessageView_outgoing.small-dark.png
Show resolved
Hide resolved
# Conflicts: # Sources/StreamChatSwiftUI/ChatMessageList/AsyncVoiceMessages/VoiceRecordingContainerView.swift # StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageComposerView_Tests/test_composerView_draftWithVoiceRecordingAttachment.default-light.png # StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageComposerView_Tests/test_composerView_editingMessageWithVoiceRecording.default-light.png # StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageComposerView_Tests/test_messageComposerView_addedVoiceRecording.1.png # StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageView_Tests/test_messageViewVoiceRecordingFromMeTheming_snapshot.default-light.png # StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageView_Tests/test_messageViewVoiceRecordingFromMe_snapshot.default-light.png # StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageView_Tests/test_messageViewVoiceRecordingFromMe_snapshot.extraExtraExtraLarge-light.png # StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageView_Tests/test_messageViewVoiceRecordingFromMe_snapshot.rightToLeftLayout-default.png # StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageView_Tests/test_messageViewVoiceRecordingFromMe_snapshot.small-dark.png # StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageView_Tests/test_messageViewVoiceRecordingFromParticipant_snapshot.default-light.png # StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageView_Tests/test_messageViewVoiceRecordingFromParticipant_snapshot.extraExtraExtraLarge-light.png # StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageView_Tests/test_messageViewVoiceRecordingFromParticipant_snapshot.rightToLeftLayout-default.png # StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageView_Tests/test_messageViewVoiceRecordingFromParticipant_snapshot.small-dark.png # StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageView_Tests/test_messageViewVoiceRecordingWithTextFromMeMultiple_snapshot.default-light.png # StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageView_Tests/test_messageViewVoiceRecordingWithTextFromMeMultiple_snapshot.extraExtraExtraLarge-light.png # StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageView_Tests/test_messageViewVoiceRecordingWithTextFromMeMultiple_snapshot.rightToLeftLayout-default.png # StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageView_Tests/test_messageViewVoiceRecordingWithTextFromMeMultiple_snapshot.small-dark.png # StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageView_Tests/test_messageViewVoiceRecordingWithTextFromMe_snapshot.default-light.png # StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageView_Tests/test_messageViewVoiceRecordingWithTextFromMe_snapshot.extraExtraExtraLarge-light.png # StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageView_Tests/test_messageViewVoiceRecordingWithTextFromMe_snapshot.rightToLeftLayout-default.png # StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageView_Tests/test_messageViewVoiceRecordingWithTextFromMe_snapshot.small-dark.png # StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageView_Tests/test_messageViewVoiceRecordingWithTextFromParticipantMultiple_snapshot.default-light.png # StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageView_Tests/test_messageViewVoiceRecordingWithTextFromParticipantMultiple_snapshot.extraExtraExtraLarge-light.png # StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageView_Tests/test_messageViewVoiceRecordingWithTextFromParticipantMultiple_snapshot.rightToLeftLayout-default.png # StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageView_Tests/test_messageViewVoiceRecordingWithTextFromParticipantMultiple_snapshot.small-dark.png # StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageView_Tests/test_messageViewVoiceRecordingWithTextFromParticipant_snapshot.default-light.png # StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageView_Tests/test_messageViewVoiceRecordingWithTextFromParticipant_snapshot.extraExtraExtraLarge-light.png # StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageView_Tests/test_messageViewVoiceRecordingWithTextFromParticipant_snapshot.rightToLeftLayout-default.png # StreamChatSwiftUITests/Tests/ChatChannel/__Snapshots__/MessageView_Tests/test_messageViewVoiceRecordingWithTextFromParticipant_snapshot.small-dark.png
| } | ||
|
|
||
| /// Bubble styling configuration for stacked attachments. | ||
| enum MessageAttachmentsBubbleConfiguration { |
There was a problem hiding this comment.
Moved this special bubble and attachment background logic to here.
| ) | ||
| ) | ||
| } else if !message.attachmentCounts.isEmpty || message.quotedMessage != nil { | ||
| factory.makeMessageAttachmentsView( |
There was a problem hiding this comment.
I don't really understand this - so we have everything except giphy attachments under this message attachments view? And why don't we have a way to customize image/video attachments separately as before?
There was a problem hiding this comment.
In the new design quoted and other attachments share a single bubble where as before it was not a case always. This view handles the centralised bubble logic for attachments + text. Before it used to be that each attachment had its own quoted message handling and bubble handling.
I'll add back the video attachment factory for flexibility. New design does not make any difference between image and video (except the play indicator).
There was a problem hiding this comment.
I reverted some of the view factory methods to look the same we had before.
Public Interface+ public struct MessageMediaAttachmentsContainerView: View
+
+ public var body: some View
+
+
+ public init(factory: Factory,message: ChatMessage,width: CGFloat)
+ public struct MessageMediaAttachmentContentView: View
+
+ public var body: some View
+
+
+ public init(factory: Factory,source: MediaAttachment,width: CGFloat,height: CGFloat,cornerRadius: CGFloat? = nil,isOutgoing: Bool = false)
+ public enum LoadingSpinnerSize: Sendable
+
+ @MainActor public static var large: CGFloat
+ @MainActor public static var small: CGFloat
+ @MainActor public static var extraSmall: CGFloat
+ public class StreamTextViewOptions
+
+ public let message: ChatMessage
+
+
+ public init(message: ChatMessage)
+ public enum VideoPlayIndicatorSize
+
+ @MainActor public static var extraLarge: CGFloat
+ @MainActor public static var large: CGFloat
+ @MainActor public static var medium: CGFloat
+ @MainActor public static var small: CGFloat
+ public final class MessageAttachmentsViewOptions: Sendable
+
+ public let message: ChatMessage
+ public let isFirst: Bool
+ public let availableWidth: CGFloat
+ public let scrolledId: Binding<String?>
+
+
+ public init(message: ChatMessage,isFirst: Bool,availableWidth: CGFloat,scrolledId: Binding<String?>)
+ public enum MediaGalleryOrientation: Sendable
+
+ case landscape
+ case portrait
+ case square
+
+
+ public init(width: Double?,height: Double?)
+ public struct MessageAttachmentsView: View
+
+ public var body: some View
+
+
+ public init(factory: Factory,message: ChatMessage,width: CGFloat,isFirst: Bool,scrolledId: Binding<String?>)
+ public struct VideoPlayIndicatorView: View
+
+ public var body: some View
+
+
+ public init(size: CGFloat,playing: Bool = false)
+ public struct LoadingSpinnerView: View
+
+ public var body: some View
+
+
+ public init(size: CGFloat,bordered: Bool)
- public struct VideoAttachmentsList: View
-
- public var body: some View
-
-
- public init(factory: Factory = DefaultViewFactory.shared,message: ChatMessage,width: CGFloat)
- public struct ImageAttachmentContainer: View
-
- public var body: some View
-
-
- public init(factory: Factory,message: ChatMessage,width: CGFloat,isFirst: Bool,scrolledId: Binding<String?>)
- public struct VideoAttachmentsContainer: View
-
- public var body: some View
- public struct VideoAttachmentView: View
-
- public var body: some View
-
-
- public init(factory: Factory = DefaultViewFactory.shared,attachment: ChatMessageVideoAttachment,message: ChatMessage,width: CGFloat,ratio: CGFloat = 0.75,cornerRadius: CGFloat = 24)
public struct ChatQuotedMessageView: View
- public init(factory: Factory,quotedMessage: ChatMessage,parentMessage: ChatMessage,scrolledId: Binding<String?>)
+ public init(factory: Factory,quotedMessage: ChatMessage,parentMessage: ChatMessage,availableWidth: CGFloat? = nil,scrolledId: Binding<String?>)
public final class ChatQuotedMessageViewOptions: Sendable
- public let scrolledId: Binding<String?>
+ public let availableWidth: CGFloat?
-
+ public let scrolledId: Binding<String?>
-
+
- public init(quotedMessage: ChatMessage,parentMessage: ChatMessage,scrolledId: Binding<String?>)
+
+ public init(quotedMessage: ChatMessage,parentMessage: ChatMessage,availableWidth: CGFloat? = nil,scrolledId: Binding<String?>)
public final class MediaAttachment: Identifiable, Equatable, Sendable
- public var id: String
+ public let originalWidth: Double?
-
+ public let originalHeight: Double?
-
+ public var id: String
- public init(url: URL,type: MediaAttachmentType,uploadingState: AttachmentUploadingState? = nil)
+
-
+
-
+ public init(url: URL,type: MediaAttachmentType,uploadingState: AttachmentUploadingState? = nil,originalWidth: Double? = nil,originalHeight: Double? = nil)
- public static func ==(lhs: MediaAttachment,rhs: MediaAttachment)-> Bool
+
+
+ public static func ==(lhs: MediaAttachment,rhs: MediaAttachment)-> Bool
public class AttachmentTextViewOptions
- public init(mesage: ChatMessage)
+ public init(message: ChatMessage)
extension ViewFactory
- public func makeImageAttachmentView(options: ImageAttachmentViewOptions)-> some View
+ public func makeMessageAttachmentsView(options: MessageAttachmentsViewOptions)-> some View
- public func makeGiphyAttachmentView(options: GiphyAttachmentViewOptions)-> some View
+ public func makeImageAttachmentView(options: ImageAttachmentViewOptions)-> some View
- public func makeLinkAttachmentView(options: LinkAttachmentViewOptions)-> some View
+ public func makeGiphyAttachmentView(options: GiphyAttachmentViewOptions)-> some View
- public func makeFileAttachmentView(options: FileAttachmentViewOptions)-> some View
+ public func makeLinkAttachmentView(options: LinkAttachmentViewOptions)-> some View
- public func makeVideoAttachmentView(options: VideoAttachmentViewOptions)-> some View
+ public func makeFileAttachmentView(options: FileAttachmentViewOptions)-> some View
- public func makeGalleryView(options: GalleryViewOptions)-> some View
+ public func makeVideoAttachmentView(options: VideoAttachmentViewOptions)-> some View
- public func makeGalleryHeaderView(options: GalleryHeaderViewOptions)-> some View
+ public func makeGalleryView(options: GalleryViewOptions)-> some View
- public func makeVideoPlayerView(options: VideoPlayerViewOptions)-> some View
+ public func makeGalleryHeaderView(options: GalleryHeaderViewOptions)-> some View
- public func makeVideoPlayerHeaderView(options: VideoPlayerHeaderViewOptions)-> some View
+ public func makeVideoPlayerView(options: VideoPlayerViewOptions)-> some View
- public func makeVideoPlayerFooterView(options: VideoPlayerFooterViewOptions)-> some View
+ public func makeVideoPlayerHeaderView(options: VideoPlayerHeaderViewOptions)-> some View
- public func makeDeletedMessageView(options: DeletedMessageViewOptions)-> some View
+ public func makeVideoPlayerFooterView(options: VideoPlayerFooterViewOptions)-> some View
- public func makeSystemMessageView(options: SystemMessageViewOptions)-> some View
+ public func makeDeletedMessageView(options: DeletedMessageViewOptions)-> some View
- public func makeEmojiTextView(options: EmojiTextViewOptions)-> some View
+ public func makeSystemMessageView(options: SystemMessageViewOptions)-> some View
- public func makeCustomAttachmentViewType(options: CustomAttachmentViewTypeOptions)-> some View
+ public func makeEmojiTextView(options: EmojiTextViewOptions)-> some View
- public func makeScrollToBottomButton(options: ScrollToBottomButtonOptions)-> some View
+ public func makeCustomAttachmentViewType(options: CustomAttachmentViewTypeOptions)-> some View
- public func makeDateIndicatorView(options: DateIndicatorViewOptions)-> some View
+ public func makeScrollToBottomButton(options: ScrollToBottomButtonOptions)-> some View
- public func makeMessageListDateIndicator(options: MessageListDateIndicatorViewOptions)-> some View
+ public func makeDateIndicatorView(options: DateIndicatorViewOptions)-> some View
- public func makeInlineTypingIndicatorView(options: TypingIndicatorViewOptions)-> some View
+ public func makeMessageListDateIndicator(options: MessageListDateIndicatorViewOptions)-> some View
- public func makeSubtitleTypingIndicatorView(options: SubtitleTypingIndicatorViewOptions)-> some View
+ public func makeInlineTypingIndicatorView(options: TypingIndicatorViewOptions)-> some View
- public func makeGiphyBadgeViewType(options: GiphyBadgeViewTypeOptions)-> some View
+ public func makeSubtitleTypingIndicatorView(options: SubtitleTypingIndicatorViewOptions)-> some View
- public func makeMessageRepliesView(options: MessageRepliesViewOptions)-> some View
+ public func makeGiphyBadgeViewType(options: GiphyBadgeViewTypeOptions)-> some View
- public func makeMessageComposerViewType(options: MessageComposerViewTypeOptions)-> MessageComposerView<Self>
+ public func makeMessageRepliesView(options: MessageRepliesViewOptions)-> some View
- public func makeLeadingComposerView(options: LeadingComposerViewOptions)-> some View
+ public func makeMessageComposerViewType(options: MessageComposerViewTypeOptions)-> MessageComposerView<Self>
- @ViewBuilder public func makeComposerInputView(options: ComposerInputViewOptions)-> some View
+ public func makeLeadingComposerView(options: LeadingComposerViewOptions)-> some View
- public func makeComposerTextInputView(options: ComposerTextInputViewOptions)-> some View
+ @ViewBuilder public func makeComposerInputView(options: ComposerInputViewOptions)-> some View
- public func makeComposerInputTrailingView(options: ComposerInputTrailingViewOptions)-> some View
+ public func makeComposerTextInputView(options: ComposerTextInputViewOptions)-> some View
- public func makeTrailingComposerView(options: TrailingComposerViewOptions)-> some View
+ public func makeComposerInputTrailingView(options: ComposerInputTrailingViewOptions)-> some View
- public func makeSendMessageButton(options: SendMessageButtonOptions)-> some View
+ public func makeTrailingComposerView(options: TrailingComposerViewOptions)-> some View
- public func makeConfirmEditButton(options: ConfirmEditButtonOptions)-> some View
+ public func makeSendMessageButton(options: SendMessageButtonOptions)-> some View
- public func makeComposerVoiceRecordingInputView(options: ComposerVoiceRecordingInputViewOptions)-> some View
+ public func makeConfirmEditButton(options: ConfirmEditButtonOptions)-> some View
- public func makeAttachmentPickerView(options: AttachmentPickerViewOptions)-> some View
+ public func makeComposerVoiceRecordingInputView(options: ComposerVoiceRecordingInputViewOptions)-> some View
- public func makeAttachmentCommandsPickerView(options: AttachmentCommandsPickerViewOptions)-> some View
+ public func makeAttachmentPickerView(options: AttachmentPickerViewOptions)-> some View
- public func makeVoiceRecordingView(options: VoiceRecordingViewOptions)-> some View
+ public func makeAttachmentCommandsPickerView(options: AttachmentCommandsPickerViewOptions)-> some View
- public func makeCustomAttachmentPickerView(options: CustomAttachmentPickerViewOptions)-> some View
+ public func makeVoiceRecordingView(options: VoiceRecordingViewOptions)-> some View
- public func makeCustomAttachmentPreviewView(options: CustomAttachmentPreviewViewOptions)-> some View
+ public func makeCustomAttachmentPickerView(options: CustomAttachmentPickerViewOptions)-> some View
- public func makeAttachmentTypePickerView(options: AttachmentTypePickerViewOptions)-> some View
+ public func makeCustomAttachmentPreviewView(options: CustomAttachmentPreviewViewOptions)-> some View
- public func makeAttachmentMediaPickerView(options: AttachmentMediaPickerViewOptions)-> some View
+ public func makeAttachmentTypePickerView(options: AttachmentTypePickerViewOptions)-> some View
- public func makeAttachmentFilePickerView(options: AttachmentFilePickerViewOptions)-> some View
+ public func makeAttachmentMediaPickerView(options: AttachmentMediaPickerViewOptions)-> some View
- public func makeAttachmentCameraPickerView(options: AttachmentCameraPickerViewOptions)-> some View
+ public func makeAttachmentFilePickerView(options: AttachmentFilePickerViewOptions)-> some View
- public func makeAttachmentPollPickerView(options: AttachmentPollPickerViewOptions)-> some View
+ public func makeAttachmentCameraPickerView(options: AttachmentCameraPickerViewOptions)-> some View
- public func makeSendInChannelView(options: SendInChannelViewOptions)-> some View
+ public func makeAttachmentPollPickerView(options: AttachmentPollPickerViewOptions)-> some View
- public func makeMessageActionsView(options: MessageActionsViewOptions)-> some View
+ public func makeSendInChannelView(options: SendInChannelViewOptions)-> some View
- public func makeBottomReactionsView(options: ReactionsBottomViewOptions)-> some View
+ public func makeMessageActionsView(options: MessageActionsViewOptions)-> some View
- public func makeMessageReactionView(options: MessageReactionViewOptions)-> some View
+ public func makeBottomReactionsView(options: ReactionsBottomViewOptions)-> some View
- public func makeReactionsOverlayView(options: ReactionsOverlayViewOptions)-> some View
+ public func makeMessageReactionView(options: MessageReactionViewOptions)-> some View
- public func makeReactionsContentView(options: ReactionsContentViewOptions)-> some View
+ public func makeReactionsOverlayView(options: ReactionsOverlayViewOptions)-> some View
- public func makeReactionsBackgroundView(options: ReactionsBackgroundOptions)-> some View
+ public func makeReactionsContentView(options: ReactionsContentViewOptions)-> some View
- public func makeMoreReactionsView(options: MoreReactionsViewOptions)-> some View
+ public func makeReactionsBackgroundView(options: ReactionsBackgroundOptions)-> some View
- public func makeReactionsDetailView(options: ReactionsDetailViewOptions)-> some View
+ public func makeMoreReactionsView(options: MoreReactionsViewOptions)-> some View
- public func makeComposerQuotedMessageView(options: ComposerQuotedMessageViewOptions)-> some View
+ public func makeReactionsDetailView(options: ReactionsDetailViewOptions)-> some View
- public func makeChatQuotedMessageView(options: ChatQuotedMessageViewOptions)-> some View
+ public func makeComposerQuotedMessageView(options: ComposerQuotedMessageViewOptions)-> some View
- public func makeQuotedMessageView(options: QuotedMessageViewOptions)-> some View
+ public func makeChatQuotedMessageView(options: ChatQuotedMessageViewOptions)-> some View
- public func makeComposerEditedMessageView(options: ComposerEditedMessageViewOptions)-> some View
+ public func makeQuotedMessageView(options: QuotedMessageViewOptions)-> some View
- public func makeMessageAttachmentPreviewThumbnailView(options: MessageAttachmentPreviewViewOptions)-> some View
+ public func makeComposerEditedMessageView(options: ComposerEditedMessageViewOptions)-> some View
- public func makeMessageAttachmentPreviewIconView(options: MessageAttachmentPreviewIconViewOptions)-> some View
+ public func makeMessageAttachmentPreviewThumbnailView(options: MessageAttachmentPreviewViewOptions)-> some View
- public func makeSuggestionsContainerView(options: SuggestionsContainerViewOptions)-> some View
+ public func makeMessageAttachmentPreviewIconView(options: MessageAttachmentPreviewIconViewOptions)-> some View
- public func makeMessageReadIndicatorView(options: MessageReadIndicatorViewOptions)-> some View
+ public func makeSuggestionsContainerView(options: SuggestionsContainerViewOptions)-> some View
- public func makeNewMessagesIndicatorView(options: NewMessagesIndicatorViewOptions)-> some View
+ public func makeMessageReadIndicatorView(options: MessageReadIndicatorViewOptions)-> some View
- public func makeJumpToUnreadButton(options: JumpToUnreadButtonOptions)-> some View
+ public func makeNewMessagesIndicatorView(options: NewMessagesIndicatorViewOptions)-> some View
- public func makeComposerPollView(options: ComposerPollViewOptions)-> some View
+ public func makeJumpToUnreadButton(options: JumpToUnreadButtonOptions)-> some View
- public func makePollView(options: PollViewOptions)-> some View
+ public func makeComposerPollView(options: ComposerPollViewOptions)-> some View
- public func makeThreadDestination(options: ThreadDestinationOptions)-> @MainActor (ChatThread) -> ChatChannelView<Self>
+ public func makePollView(options: PollViewOptions)-> some View
- public func makeThreadListItem(options: ThreadListItemOptions<ThreadDestination>)-> some View
+ public func makeThreadDestination(options: ThreadDestinationOptions)-> @MainActor (ChatThread) -> ChatChannelView<Self>
- public func makeNoThreadsView(options: NoThreadsViewOptions)-> some View
+ public func makeThreadListItem(options: ThreadListItemOptions<ThreadDestination>)-> some View
- public func makeThreadListLoadingView(options: ThreadListLoadingViewOptions)-> some View
+ public func makeNoThreadsView(options: NoThreadsViewOptions)-> some View
- public func makeThreadListContainerViewModifier(options: ThreadListContainerModifierOptions)-> some ViewModifier
+ public func makeThreadListLoadingView(options: ThreadListLoadingViewOptions)-> some View
- public func makeThreadListHeaderViewModifier(options: ThreadListHeaderViewModifierOptions)-> some ViewModifier
+ public func makeThreadListContainerViewModifier(options: ThreadListContainerModifierOptions)-> some ViewModifier
- public func makeThreadListHeaderView(options: ThreadListHeaderViewOptions)-> some View
+ public func makeThreadListHeaderViewModifier(options: ThreadListHeaderViewModifierOptions)-> some ViewModifier
- public func makeThreadListFooterView(options: ThreadListFooterViewOptions)-> some View
+ public func makeThreadListHeaderView(options: ThreadListHeaderViewOptions)-> some View
- public func makeThreadListBackground(options: ThreadListBackgroundOptions)-> some View
+ public func makeThreadListFooterView(options: ThreadListFooterViewOptions)-> some View
- public func makeThreadListItemBackground(options: ThreadListItemBackgroundOptions)-> some View
+ public func makeThreadListBackground(options: ThreadListBackgroundOptions)-> some View
- public func makeThreadListDividerItem(options: ThreadListDividerItemOptions)-> some View
+ public func makeThreadListItemBackground(options: ThreadListItemBackgroundOptions)-> some View
- public func makeAddUsersView(options: AddUsersViewOptions)-> some View
+ public func makeThreadListDividerItem(options: ThreadListDividerItemOptions)-> some View
- public func makeAttachmentTextView(options: AttachmentTextViewOptions)-> some View
+ public func makeAddUsersView(options: AddUsersViewOptions)-> some View
+ public func makeAttachmentTextView(options: AttachmentTextViewOptions)-> some View
+ public func makeStreamTextView(options: StreamTextViewOptions)-> some View |
SDK Size
|
StreamChatSwiftUI XCSize
Show 26 more objects
|
|




π Issue Links
Related: IOS-1441
π― Goal
Attachments redesign with new stacked logic for attachments
π Summary
MessageMediaAttachmentsContainerView that renders images and videos in an adaptive gallery grid (1β4+
items with orientation-aware layouts)
(media, files, voice recordings, links) with quoted messages and text captions
and per-cell loading spinners
makeStreamTextView/StreamTextViewOptions to clarify it's a shared text view reused across message
layouts
duplicated quoted message, text, and bubble logic (now handled by MessageAttachmentsView)
π Implementation
The old approach had each attachment type (ImageAttachmentView, VideoAttachmentView,
FileAttachmentsContainer, etc.) independently handling quoted messages, text display, and bubble
backgrounds. This led to duplicated logic and inconsistent behavior.
The new architecture introduces MessageAttachmentsView as an orchestrator that composes attachment
views via the view factory and handles the shared concerns (quoted messages, text captions, bubble
modifiers) in one place. Individual attachment views are now simpler, focused only on rendering their
specific content.
MessageMediaAttachmentsContainerView provides a gallery grid that adapts layout based on item count
(1β4+) and the first image's orientation (landscape/portrait/square). Each cell uses
MessageMediaAttachmentContentView which loads thumbnails asynchronously with shimmer placeholders.
π§ͺ Manual Testing Notes
βοΈ Contributor Checklist
docs-contentrepo