Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
42c025c
Add new ChatMediaAttachmentContainerView to manage media layout handling
laevandus Mar 3, 2026
d872297
Merge branch 'v5' into v5-media-attachment-refresh
laevandus Mar 3, 2026
68b164c
Add shared loading spinner
laevandus Mar 3, 2026
88810ec
Implement stacked attachments for different types
laevandus Mar 4, 2026
580e573
Update snapshots
laevandus Mar 4, 2026
3db03d8
Cleanup unused types
laevandus Mar 4, 2026
b78ed39
Fix snapshots
laevandus Mar 4, 2026
bcfc15a
Update image loading in snapshots
laevandus Mar 4, 2026
e53cb1a
Use mocked video loader
laevandus Mar 4, 2026
b7c1d35
Update file and voice views
laevandus Mar 4, 2026
90f756f
Add VideoPlayIndicatorView
laevandus Mar 4, 2026
a1f4338
Merge branch 'v5' into v5-media-attachment-refresh
laevandus Mar 5, 2026
5c5cbc8
Move loading spinner to each of the thumbnail view
laevandus Mar 5, 2026
cd98c27
Fix attachment alignment
laevandus Mar 5, 2026
4712642
Fix e2e tests
laevandus Mar 5, 2026
39ebde7
Unify accessibility identifiers for message view
laevandus Mar 5, 2026
67f80eb
Clean text view factories
laevandus Mar 5, 2026
e7460b7
Merge branch 'v5' into v5-media-attachment-refresh
laevandus Mar 5, 2026
f4ab851
Tidy orientation
laevandus Mar 5, 2026
c58fa00
Tidy text view
laevandus Mar 5, 2026
ba86cb7
Merge branch 'v5' into v5-media-attachment-refresh
laevandus Mar 6, 2026
ad2c95e
Adjust voice recording for the stacked attachment list
laevandus Mar 6, 2026
0e21e24
Revert makeLoadingView changes
laevandus Mar 6, 2026
f3584b8
Tidy bubble styling logic
laevandus Mar 6, 2026
2e76d1f
Update snapshots
laevandus Mar 6, 2026
5a1c10e
Fix foreach
laevandus Mar 6, 2026
0237de7
Fix e2e tests
laevandus Mar 6, 2026
c7845e2
Fix image gallery layout for landscape
laevandus Mar 6, 2026
be8510e
Revert view factory naming
laevandus Mar 6, 2026
c1f07af
[CI] Snapshots (#1271)
Stream-SDK-Bot Mar 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
public struct VoiceRecordingContainerView<Factory: ViewFactory>: View {
@Injected(\.colors) var colors
@Injected(\.images) var images
@Injected(\.tokens) var tokens
@Injected(\.utils) var utils

let factory: Factory
Expand Down Expand Up @@ -39,38 +40,22 @@
}

public var body: some View {
VStack(spacing: 0) {
VStack {
if let quotedMessage = message.quotedMessage {
factory.makeChatQuotedMessageView(
options: ChatQuotedMessageViewOptions(
quotedMessage: quotedMessage,
parentMessage: message,
scrolledId: $scrolledId
)
)
}
VStack(spacing: 2) {
ForEach(message.voiceRecordingAttachments, id: \.self) { attachment in
VoiceRecordingView(
handler: handler,
addedVoiceRecording: AddedVoiceRecording(
url: attachment.payload.voiceRecordingURL,
duration: attachment.payload.duration ?? 0,
waveform: attachment.payload.waveformData ?? []
),
isSentByCurrentUser: message.isSentByCurrentUser
)
.padding(.all, 8)
}
}
}
if !message.text.isEmpty {
AttachmentTextView(factory: factory, message: message)
.frame(maxWidth: .infinity)
VStack(spacing: tokens.spacingXxxs) {
ForEach(message.voiceRecordingAttachments) { attachment in
VoiceRecordingView(
handler: handler,
addedVoiceRecording: AddedVoiceRecording(
url: attachment.payload.voiceRecordingURL,
duration: attachment.payload.duration ?? 0,
waveform: attachment.payload.waveformData ?? []
),
isSentByCurrentUser: message.isSentByCurrentUser
)
.padding(.all, tokens.spacingXs)
.background(MessageAttachmentsBubbleConfiguration.attachmentBackgroundColor(for: message))
.roundWithBorder(cornerRadius: tokens.messageBubbleRadiusAttachment)
}
}
.padding(.all, 2)
.onReceive(handler.$context, perform: { value in
guard message.voiceRecordingAttachments.count > 1 else { return }
if value.state == .playing {
Expand All @@ -92,15 +77,6 @@
.onAppear {
player.subscribe(handler)
}
.modifier(
factory.styles.makeMessageViewModifier(
for: MessageModifierInfo(
message: message,
isFirst: isFirst,
cornerRadius: 16
)
)
)
}

private func index(for attachment: ChatMessageVoiceRecordingAttachment) -> Int {
Expand All @@ -124,7 +100,7 @@
private var showContextDuration: Bool { isActive && handler.context.currentTime > 0 }

private var controlBorderColor: Color? {
isSentByCurrentUser ? Color(colors.chatBorderOnChatOutgoing) : nil
isSentByCurrentUser ? Color(colors.chatBorderOnChatOutgoing) : Color(colors.chatBorderOnChatIncoming)
}

var body: some View {
Expand Down Expand Up @@ -230,7 +206,7 @@
private var player: AudioPlaying { utils.audioPlayer }

func audioPlayer(
_ audioPlayer: AudioPlaying,

Check warning on line 209 in Sources/StreamChatSwiftUI/ChatMessageList/AsyncVoiceMessages/VoiceRecordingContainerView.swift

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove the unused function parameter "audioPlayer" or name it "_".

See more on https://sonarcloud.io/project/issues?id=GetStream_stream-chat-swiftui&issues=AZy5WsSdgE9ChFi-UZ48&open=AZy5WsSdgE9ChFi-UZ48&pullRequest=1264
didUpdateContext context: AudioPlaybackContext
) {
self.context = context
Expand All @@ -239,7 +215,7 @@
// MARK: - Shared Playback Helpers

var rateTitle: String {
switch rate {

Check warning on line 218 in Sources/StreamChatSwiftUI/ChatMessageList/AsyncVoiceMessages/VoiceRecordingContainerView.swift

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace this "switch" statement with "if" statement to increase readability.

See more on https://sonarcloud.io/project/issues?id=GetStream_stream-chat-swiftui&issues=AZy5WsSdgE9ChFi-UZ47&open=AZy5WsSdgE9ChFi-UZ47&pullRequest=1264
case .half: "x0.5"
default: "x\(Int(rate.rawValue))"
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//
// Copyright Β© 2026 Stream.io Inc. All rights reserved.
//

import StreamChat
import SwiftUI

public struct AttachmentTextView<Factory: ViewFactory>: View {
@Injected(\.colors) private var colors
@Injected(\.fonts) private var fonts
@Injected(\.tokens) private var tokens

var factory: Factory
var message: ChatMessage
let injectedBackgroundColor: UIColor?

public init(factory: Factory = DefaultViewFactory.shared, message: ChatMessage, injectedBackgroundColor: UIColor? = nil) {
self.factory = factory
self.message = message
self.injectedBackgroundColor = injectedBackgroundColor
}

public var body: some View {
HStack {
factory.makeStreamTextView(options: .init(message: message))
.padding(.horizontal, tokens.spacingXxs)
.fixedSize(horizontal: false, vertical: true)
Spacer()
}
.background(Color(backgroundColor))
.accessibilityIdentifier("MessageTextView")
}

private var backgroundColor: UIColor {
if let injectedBackgroundColor {
return injectedBackgroundColor
}
return message.isSentByCurrentUser ? colors.chatBackgroundOutgoing : colors.chatBackgroundIncoming
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import SwiftUI

public struct FileAttachmentsContainer<Factory: ViewFactory>: View {
@Injected(\.colors) var colors
@Injected(\.tokens) var tokens
var factory: Factory
var message: ChatMessage
var width: CGFloat
Expand All @@ -27,46 +29,17 @@
}

public var body: some View {
VStack(alignment: message.alignmentInBubble) {
if let quotedMessage = message.quotedMessage {
factory.makeChatQuotedMessageView(
options: ChatQuotedMessageViewOptions(
quotedMessage: quotedMessage,
parentMessage: message,
scrolledId: $scrolledId
)
VStack(spacing: tokens.spacingXxs) {
ForEach(message.fileAttachments) { attachment in
FileAttachmentView(
attachment: attachment,
width: width,
isFirst: isFirst
)
.background(MessageAttachmentsBubbleConfiguration.attachmentBackgroundColor(for: message))
.roundWithBorder(cornerRadius: tokens.messageBubbleRadiusAttachment)
}

VStack(spacing: 0) {
VStack(spacing: 4) {
ForEach(message.fileAttachments, id: \.self) { attachment in
FileAttachmentView(
attachment: attachment,
width: width,
isFirst: isFirst
)
}
}
if !message.text.isEmpty {
HStack {
Text(message.adjustedText)
.foregroundColor(textColor(for: message))
.standardPadding()
Spacer()
}
}
}
.padding(.all, 4)
}
.modifier(
factory.styles.makeMessageViewModifier(
for: MessageModifierInfo(
message: message,
isFirst: isFirst
)
)
)
.accessibilityIdentifier("FileAttachmentsContainer")
}
}
Expand All @@ -76,6 +49,7 @@
@Injected(\.images) private var images
@Injected(\.fonts) private var fonts
@Injected(\.colors) private var colors
@Injected(\.tokens) private var tokens
@Injected(\.chatClient) private var chatClient

@State private var fullScreenShown = false
Expand Down Expand Up @@ -110,10 +84,8 @@
DownloadShareAttachmentView(attachment: attachment)
}
}
.padding(.all, 8)
.background(Color(colors.background))
.padding(.all, tokens.spacingSm)
.frame(width: width)
.roundWithBorder()
.withUploadingStateIndicator(for: attachment.uploadingState, url: attachment.assetURL)
.withDownloadingStateIndicator(for: attachment.downloadingState, url: attachment.assetURL)
.sheet(isPresented: $fullScreenShown) {
Expand All @@ -135,6 +107,7 @@
@Injected(\.images) private var images
@Injected(\.fonts) private var fonts
@Injected(\.colors) private var colors
@Injected(\.tokens) private var tokens

var url: URL
var title: String
Expand All @@ -147,13 +120,13 @@
}

public var body: some View {
HStack {
HStack(spacing: tokens.spacingSm) {
Image(uiImage: previewImage)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 34, height: 40)
.accessibilityHidden(true)
VStack(alignment: .leading, spacing: 8) {
VStack(alignment: .leading, spacing: tokens.spacingXxs) {
Text(title)
.font(fonts.bodyBold)
.lineLimit(1)
Expand Down Expand Up @@ -241,5 +214,5 @@
UIActivityViewController(activityItems: activityItems, applicationActivities: nil)
}

func updateUIViewController(_ uiViewController: UIActivityViewController, context: Context) {}

Check failure on line 217 in Sources/StreamChatSwiftUI/ChatMessageList/FileAttachmentView.swift

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add a nested comment explaining why this function is empty, or complete the implementation.

See more on https://sonarcloud.io/project/issues?id=GetStream_stream-chat-swiftui&issues=AZy5WsVVgE9ChFi-UZ5N&open=AZy5WsVVgE9ChFi-UZ5N&pullRequest=1264

Check warning on line 217 in Sources/StreamChatSwiftUI/ChatMessageList/FileAttachmentView.swift

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove the unused function parameter "uiViewController" or name it "_".

See more on https://sonarcloud.io/project/issues?id=GetStream_stream-chat-swiftui&issues=AZy5WsVVgE9ChFi-UZ5O&open=AZy5WsVVgE9ChFi-UZ5O&pullRequest=1264
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public struct GiphyAttachmentView<Factory: ViewFactory>: View {
scrolledId: $scrolledId
)
)
.padding(tokens.spacingXs)
}

if visibleOnlyToCurrentUser {
Expand Down
Loading
Loading