Skip to content

Convert structs to classes#1173

Open
martinmitrevski wants to merge 2 commits intodevelopfrom
structs-to-classes
Open

Convert structs to classes#1173
martinmitrevski wants to merge 2 commits intodevelopfrom
structs-to-classes

Conversation

@martinmitrevski
Copy link
Contributor

@martinmitrevski martinmitrevski commented Feb 6, 2026

πŸ”— Issue Links

Provide all Linear and/or Github issues related to this PR, if applicable.

🎯 Goal

Describe why we are making this change.

πŸ“ Summary

Provide bullet points with the most important changes in the codebase.

πŸ›  Implementation

Provide a detailed description of the implementation and explain your decisions if you find them relevant.

🎨 Showcase

Add relevant screenshots and/or videos/gifs to easily see what this PR changes, if applicable.

Before After
img img

πŸ§ͺ Manual Testing Notes

Explain how this change can be tested manually, if applicable.

β˜‘οΈ Contributor Checklist

  • I have signed the Stream CLA (required)
  • This change should be manually QAed
  • Changelog is updated with client-facing changes
  • Changelog is updated with new localization keys
  • New code is covered by unit tests
  • Documentation has been updated in the docs-content repo

Summary by CodeRabbit

Release Notes

  • Refactor
    • Internal architectural improvements to enhance code maintainability and performance. No changes to user-facing functionality.

@martinmitrevski martinmitrevski requested a review from a team as a code owner February 6, 2026 12:57
@coderabbitai
Copy link

coderabbitai bot commented Feb 6, 2026

πŸ“ Walkthrough

Walkthrough

This pull request systematically converts 40+ public and private struct types to final classes throughout the StreamChatSwiftUI codebase, changing their semantics from value types to reference types. The changes preserve existing properties and initializers while altering object identity, mutation, and allocation behavior.

Changes

Cohort / File(s) Summary
ChannelInfo Models
ChatChannel/ChannelInfo/AddUsersView.swift, ChatInfoParticipantsView.swift, FileAttachmentsViewModel.swift, MediaAttachmentsViewModel.swift, ParticipantInfoView.swift
Five public model types converted from struct to final class, preserving properties and public APIs while shifting to reference semantics.
Composer Configuration
ChatChannel/Composer/ComposerConfig.swift
ComposerConfig and PaddingsConfig converted from struct to final class, maintaining properties and initializers.
Composer Models
ChatChannel/Composer/ComposerModels.swift
AddedAsset, CustomAttachment, AddedVoiceRecording converted to final classes; AddedVoiceRecording adds explicit equality operator comparing url, duration, and waveform.
Composer View Models
ChatChannel/Composer/MessageComposerViewModel.swift
ComposerAssets and FileAddedAsset converted to final classes with explicit initializers (mediaAssets, fileAssets, voiceAssets, customAssets, url, payload).
Photo Assets Utilities
ChatChannel/Composer/PhotoAssetsUtils.swift
PHFetchResultCollection converted to final class with added fetchResult property and public equality operator.
Command Handlers
ChatChannel/Composer/Suggestions/CommandsHandler.swift
ComposerCommand, SuggestionInfo, CommandDisplayInfo converted to final classes; CommandDisplayInfo adds isInstant property.
Instant Command Handlers
ChatChannel/Composer/Suggestions/InstantCommands/GiphyCommandHandler.swift
GiphyCommandHandler converted from struct to final class.
Mentions Handler
ChatChannel/Composer/Suggestions/Mentions/MentionsCommandHandler.swift
MentionsCommandHandler converted to final class with weak self capture pattern added in searchAllUsers closure to prevent reference cycles.
Typing Suggester
ChatChannel/Composer/Suggestions/TypingSuggester.swift
TypingSuggestionOptions, TypingSuggestion, TypingSuggester converted to final classes with explicit initializers.
Message List Media
ChatChannel/MessageList/ImageAttachmentView.swift
MediaAttachment, MediaAttachmentType, MediaViewsOptions converted to final classes; MediaAttachment.init(from:) changed to convenience initializer.
Message Bubble
ChatChannel/MessageList/MessageBubble.swift
MessageModifierInfo converted from struct to final class.
Message Container
ChatChannel/MessageList/MessageContainerView.swift
MessageDisplayInfo and HighlightedMessageIdKey converted to final classes.
Message List Config
ChatChannel/MessageList/MessageListConfig.swift
MessageListConfig, MessagePaddings, MessageDisplayOptions converted to final classes.
Polls Configuration
ChatChannel/MessageList/Polls/PollsConfig.swift
PollsConfig and PollsEntryConfig converted to final classes; PollsEntryConfig adds public static default member.
Quoted Message
ChatChannel/MessageList/QuotedMessageView.swift
QuotedMessageContentViewOptions converted from struct to final class.
Polls UI
ChatChannel/Polls/CreatePollView.swift
TextFieldToggleAlignment (private) converted from struct to final class.
Message Actions
ChatChannel/Reactions/MessageActions/MessageActionsViewModel.swift
MessageAction and MessageActionInfo converted to final classes with Equatable conformance.
Channel List Config
ChatChannelList/ChannelListConfig.swift
ChannelListConfig converted from struct to final class.
Channel List Items
ChatChannelList/ChatChannelListItem.swift
ChannelAvatarViewOptions, InjectedChannelInfo (adds lastMessageAt, latestMessages properties), and ChannelItemMutedLayoutStyle (adds equality and hash operators) converted to final classes.
Channel List View Model
ChatChannelList/ChatChannelListViewModel.swift
ChannelListSearchType converted to final class with explicit Equatable operator; static members changed from var to let.
Channel Navigation
ChatChannelList/ChatChannelNavigatableListItem.swift
ChannelSelectionInfo converted to final class with added injectedChannelInfo and searchType properties.
More Channel Actions
ChatChannelList/MoreChannelActionsViewModel.swift
ChannelAction and ConfirmationPopup converted to final classes.
Thread List Items
ChatThreadList/ChatThreadListItem.swift
ChatThreadListItemViewModel converted from struct to final class.
Thread Navigation
ChatThreadList/ChatThreadListNavigatableItem.swift
ThreadSelectionInfo converted to final class with explicit initializer.
Core Utilities
ColorPalette.swift, DependencyInjection.swift, Fonts.swift
ColorPalette, InjectedValues, Injected, and Fonts converted to final classes.
Dependency & Error Handling
StreamChat.swift, Utils/Common/ChatMessageReactionAppeareance.swift, Utils/Common/NukeImageProcessor.swift, Utils/Errors.swift, Utils/MessageCachingUtils.swift
StreamChatProviderKey, ChatMessageReactionAppearance, LateResize, StreamChatError (adds explicit initializer), and UserDisplayInfo converted to final classes.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

The changes are largely homogeneous (struct-to-class conversions), but span 40+ files across multiple domains with occasional logic additions (weak self patterns, equality operators, new properties). While individual file changes are straightforward, the breadth requires systematic verification of reference semantics implications, particularly for memory management and identity-based equality.

Poem

🐰 From structs to classes, we hop with glee,
Reference types now, wild and free!
Values once copied, now shared with care,
Identity and mutability everywhere.
A grand refactor, consistent and neat,
Making the codebase springy and sweet! 🌱

πŸš₯ Pre-merge checks | βœ… 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
βœ… Passed checks (2 passed)
Check name Status Explanation
Description Check βœ… Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check βœ… Passed The title 'Convert structs to classes' accurately and directly summarizes the main change in the pull request: a comprehensive conversion of value types to reference types across the codebase.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • πŸ“ Generate docstrings
πŸ§ͺ Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch structs-to-classes

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.

❀️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link

github-actions bot commented Feb 6, 2026

1 Message
πŸ“– There seems to be app changes but CHANGELOG wasn't modified.
Please include an entry if the PR includes user-facing changes.
You can find it at CHANGELOG.md.

Generated by 🚫 Danger

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (15)
Sources/StreamChatSwiftUI/ChatChannel/MessageList/Polls/PollsConfig.swift (1)

56-58: ⚠️ Potential issue | πŸ”΄ Critical

Shared mutable singleton β€” mutating any default entry silently corrupts all others.

PollsEntryConfig.default is a single shared class instance. Because all properties are var, any mutation (e.g. config.multipleAnswers.configurable = false) mutates the shared .default in-place, silently affecting every PollsConfig that was (or will be) created with defaults. Additionally, PollsConfig() assigns the same object to all five properties, so mutating one entry also mutates the other four.

With structs this was safe because each assignment was a copy. With classes, you need either:

  1. A computed property / factory method that vends a fresh instance each time, or
  2. Immutable (let) properties on PollsEntryConfig so the shared instance can't be corrupted.

Option 1 (factory method β€” minimal diff):

Proposed fix
 extension PollsEntryConfig {
     /// The default configuration for a poll entry.
-    public static let `default` = PollsEntryConfig(configurable: true, defaultValue: false)
+    public static func makeDefault() -> PollsEntryConfig {
+        PollsEntryConfig(configurable: true, defaultValue: false)
+    }
 }

Then update the PollsConfig init defaults accordingly:

public init(
    multipleAnswers: PollsEntryConfig = .makeDefault(),
    anonymousPoll: PollsEntryConfig = .makeDefault(),
    suggestAnOption: PollsEntryConfig = .makeDefault(),
    addComments: PollsEntryConfig = .makeDefault(),
    maxVotesPerPerson: PollsEntryConfig = .makeDefault()
)
Sources/StreamChatSwiftUI/ChatChannel/Reactions/MessageActions/MessageActionsViewModel.swift (1)

24-53: ⚠️ Potential issue | 🟠 Major

@Published array of reference types won't notify on in-place property mutations.

Changing MessageAction from struct to class is a subtle but breaking change for @Published public var messageActions: [MessageAction]. With structs, in-place mutations of properties (like setting navigationDestination) changed the array value itself, triggering change notifications. With classes, mutations to properties on existing array elements don't trigger the publisherβ€”the array reference remains unchanged.

The codebase has at least two places that rely on this pattern:

  • DefaultChannelActions.swift:220 sets navigationDestination on an existing action
  • ChatChannelInfoViewModel.swift:299 sets navigationDestination on an existing action

If these mutations happen after the action is already in messageActions, the UI won't update because the published array won't fire objectWillChange.

Additionally, making id a mutable var on an Identifiable type risks breaking SwiftUI's identity diffing if the ID changes after the initial render. Consider making it let.

Sources/StreamChatSwiftUI/ChatChannel/Composer/Suggestions/TypingSuggester.swift (1)

9-15: ⚠️ Potential issue | 🟑 Minor

Fix doc comment mismatch and consider making TypingSuggestionOptions properties immutable.

Line 35 states "A structure" but the type on line 36 is a public final class. While the codebase shows no actual mutations of symbol, shouldTriggerOnlyAtStart, or minimumRequiredCharacters after construction, converting these properties from var to let would clarify the intent that options are configured at initialization and then treated as immutable. This also better documents the contract for consumers of this API.

Suggested safer alternative: make properties immutable
-    /// A structure that contains the information of the typing suggestion.
+    /// A class that contains the information of the typing suggestion.

And convert properties to let:

-    public var symbol: String
-    public var shouldTriggerOnlyAtStart: Bool
-    public var minimumRequiredCharacters: Int
+    public let symbol: String
+    public let shouldTriggerOnlyAtStart: Bool
+    public let minimumRequiredCharacters: Int
Sources/StreamChatSwiftUI/ChatChannel/MessageList/AsyncVoiceMessages/WaveformView.swift (1)

17-58: ⚠️ Potential issue | 🟑 Minor

API design concern: Content properties should be read-only to prevent in-place mutations.

While Content was converted from a struct to a final class, the properties remain public var, which invites callers to mutate them directly. A struct would allow view.content.currentTime = 5.0 to implicitly trigger didSet on content (value semantics), but a class will notβ€”the reference itself remains unchanged.

A search of the codebase found no current in-place mutations; all assignments use full object replacement (view.content = Content(...)), so this is not an active regression. However, the public mutable properties create a latent risk for future maintainers.

Consider marking Content properties as read-only:

  • Change public var to public let in the initializer, or
  • Use public private(set) var if mutation is needed internally.

This forces callers to replace the entire Content object, ensuring didSet always fires.

Sources/StreamChatSwiftUI/ChatChannelList/MoreChannelActionsViewModel.swift (1)

94-119: ⚠️ Potential issue | 🟑 Minor

Mutable navigationDestination on a reference type introduces a design risk.

ChannelAction is now a class with a mutable navigationDestination property that's stored in @Published arrays. Current usage is safeβ€”navigationDestination is always set during construction (before the action is added to any array)β€”but the design permits a footgun: if navigationDestination were mutated on an action already in the @Published array, SwiftUI wouldn't detect the change because class mutations don't trigger the publisher.

To prevent future accidental mutations post-insertion, either:

  1. Add navigationDestination to the initializer and make it let, or
  2. Document that navigationDestination must only be set before the action is added to a collection.
Sources/StreamChatSwiftUI/ChatChannel/MessageList/QuotedMessageView.swift (1)

155-171: ⚠️ Potential issue | 🟑 Minor

Add Equatable conformance to avoid unnecessary SwiftUI re-renders.

Converting QuotedMessageContentViewOptions from a struct to a class removes the compiler's automatic Equatable synthesis. Since this class is stored as a property in QuotedMessageContentView (a SwiftUI View struct at line 186), SwiftUI relies on property comparison to detect changes. Without Equatable, the comparison falls back to identity (===), meaning every new instance is treated as "different" even when all values are identical, causing unnecessary re-renders.

Since all properties are let (immutable), implementing structural equality is straightforward:

Suggested fix
-public final class QuotedMessageContentViewOptions {
+public final class QuotedMessageContentViewOptions: Equatable {
     /// The quoted message to display.
     public let quotedMessage: ChatMessage
     /// Whether the quoted container should take all the available space.
     public let fillAvailableSpace: Bool
     /// The size of the attachment preview.
     public let attachmentSize: CGSize
 
+    public static func == (lhs: QuotedMessageContentViewOptions, rhs: QuotedMessageContentViewOptions) -> Bool {
+        lhs.quotedMessage == rhs.quotedMessage
+            && lhs.fillAvailableSpace == rhs.fillAvailableSpace
+            && lhs.attachmentSize == rhs.attachmentSize
+    }
+
     public init(

(Optional: Sendable conformance is also valid for this final class with all let properties, beneficial for Swift 6 strict concurrency.)

Sources/StreamChatSwiftUI/ChatChannel/ChannelInfo/ChatInfoParticipantsView.swift (1)

72-92: ⚠️ Potential issue | 🟠 Major

ParticipantInfo needs Equatable conformance for correct SwiftUI @Binding behavior.

This type is used with @Binding var selectedParticipant: ParticipantInfo? (line 14). Structs could rely on synthesized Equatable, but classes do not get that for free. Without Equatable, SwiftUI cannot properly diff old vs. new values for the binding, which can cause missed or redundant view updates.

Since all stored properties are let, the fix is straightforward:

Proposed fix
-public final class ParticipantInfo: Identifiable {
+public final class ParticipantInfo: Identifiable, Equatable {
+    public static func == (lhs: ParticipantInfo, rhs: ParticipantInfo) -> Bool {
+        lhs.chatUser.id == rhs.chatUser.id
+            && lhs.displayName == rhs.displayName
+            && lhs.onlineInfoText == rhs.onlineInfoText
+            && lhs.isDeactivated == rhs.isDeactivated
+    }
+
     public var id: String {
         chatUser.id
     }
Sources/StreamChatSwiftUI/ColorPalette.swift (1)

9-19: ⚠️ Potential issue | 🟠 Major

Shared-mutation risk: mutable var properties on a reference type.

ColorPalette has many public var properties. As a struct, consumers could safely do:

var myColors = appearance.colors
myColors.tintColor = .red // only affects the local copy

Now that it's a class, this mutates the shared instance. This is a silent behavioral change for existing consumers who relied on value-copy semantics.

Since lazy var properties (lines 83–105) genuinely benefit from class semantics (no mutating access needed), the conversion has merit, but consider documenting the change in the SDK migration guide and/or providing a copy() method so consumers can opt into independent instances.

Sources/StreamChatSwiftUI/ChatChannel/Composer/ComposerConfig.swift (1)

9-61: ⚠️ Potential issue | 🟠 Major

Mutable var properties on a reference type risk unintended shared-state mutations.

ComposerConfig has 11 public var properties. As a struct, mutations were local (copy semantics). Now that it's a class, any holder mutating a property (e.g., config.isVoiceRecordingEnabled = true) silently affects every other holder of the same instance. This is especially risky for closures like adjustMessageOnSend that could be swapped at runtime.

Consider either:

  • Making stored properties let (as done in the other converted types), or
  • Keeping this particular type as a struct if runtime mutation is intended to be local.
Sources/StreamChatSwiftUI/ChatChannel/Composer/Suggestions/Mentions/MentionsCommandHandler.swift (1)

152-166: ⚠️ Potential issue | 🟑 Minor

Handle case when self is deallocated before the Future resolves.

If self is deallocated before the closure runs, the early return on line 154 means the Future never resolves (no .success or .failure). Any downstream sink/receive subscriber will hang indefinitely.

Fail the promise explicitly instead:

Proposed fix
     private func searchAllUsers(for typingMention: String) -> Future<SuggestionInfo, Error> {
         Future { [weak self] promise in
-            guard let self else { return }
+            guard let self else {
+                promise(.failure(ClientError("MentionsCommandHandler was deallocated")))
+                return
+            }
             let query = queryForMentionSuggestionsSearch(typingMention: typingMention)
Sources/StreamChatSwiftUI/ChatChannel/Utils/ChatChannelHelpers.swift (1)

21-43: ⚠️ Potential issue | 🟑 Minor

Use struct instead of class for PreferenceKey conformanceβ€”it's the standard and expected pattern.

While PreferenceKey technically works as a class (the protocol only requires static members), all three types here should be struct. SwiftUI convention and all examples use struct for preference keys because only the type itself is used by SwiftUI (never instantiated). Using class adds no benefit and creates unnecessary confusion about instance semantics.

Sources/StreamChatSwiftUI/ChatChannelList/ChatChannelNavigatableListItem.swift (2)

92-95: ⚠️ Potential issue | 🟑 Minor

Default searchType of .messages looks incorrect for non-search channel selections.

The initializer defaults searchType to .messages, and the convenience ChatChannel.channelSelectionInfo (line 120) uses message: nil. This means every channel opened from the list (not via search) gets tagged with .messages search type. Should the default be .channels instead?


85-106: ⚠️ Potential issue | πŸ”΄ Critical

Mutating class properties on a @Published reference won't trigger view updates.

Converting ChannelSelectionInfo from a struct to a class breaks SwiftUI's observation mechanism for property mutations. When selectedChannel?.injectedChannelInfo is mutated at lines 549 and 572, the reference itself remains unchanged, so the @Published observer never fires and dependent views don't re-render.

With a struct, these mutations would trigger copy-on-write reassignment and fire @Published watchers. With a class, mutations happen in-place on the reference without notifying SwiftUI.

selectedChannel?.injectedChannelInfo = InjectedChannelInfo(unreadCount: 0) // line 549
selectedChannel?.injectedChannelInfo = InjectedChannelInfo(...) // line 572

This causes channel list items displaying subtitle, timestamp, and unreadCount (which come from injectedChannelInfo) to show stale data when returning from a conversation.

Sources/StreamChatSwiftUI/ChatChannelList/ChatChannelListItem.swift (1)

394-418: ⚠️ Potential issue | 🟠 Major

Static class instances should be let, not var β€” same pattern as ChannelListSearchType.

default, topRightCorner, and afterChannelName are static var on a class. External code could reassign them (e.g., ChannelItemMutedLayoutStyle.default = .topRightCorner), corrupting all consumers.

Proposed fix
-    public static var `default`: ChannelItemMutedLayoutStyle = .init("default")
-    public static var topRightCorner: ChannelItemMutedLayoutStyle = .init("topRightCorner")
-    public static var afterChannelName: ChannelItemMutedLayoutStyle = .init("afterChannelName")
+    public static let `default`: ChannelItemMutedLayoutStyle = .init("default")
+    public static let topRightCorner: ChannelItemMutedLayoutStyle = .init("topRightCorner")
+    public static let afterChannelName: ChannelItemMutedLayoutStyle = .init("afterChannelName")
Sources/StreamChatSwiftUI/ChatChannel/MessageList/MessageContainerView.swift (1)

441-466: ⚠️ Potential issue | 🟑 Minor

Consider if mutable properties on a reference type create unnecessary mutation surface.

showsMessageActions, showsBottomContainer, and keyboardWasShown are declared as var on a class. While the current codebase patterns (creating fresh instances in handleLongPress at line 426, read-only access in ReactionsOverlayView) avoid mutations, this API design unnecessarily exposes mutable state on a reference type. If these properties should not change after initialization, marking them as let with proper initialization would eliminate the risk entirely and clarify intent.

πŸ€– Fix all issues with AI agents
In
`@Sources/StreamChatSwiftUI/ChatChannel/Composer/MessageComposerViewModel`+Recording.swift:
- Around line 19-22: AudioRecordingInfo is now a class so in-place mutations in
MessageComposerViewModel (e.g., AudioRecordingInfo.update(with:duration:) and
direct waveform mutations) don't trigger the `@Published` publisher; after any
in-place mutation of audioRecordingInfo (calls to update(with:duration:) or
modifying audioRecordingInfo.waveform/duration), explicitly notify SwiftUI by
either calling objectWillChange.send() on MessageComposerViewModel or force a
setter by reassigning the property (audioRecordingInfo = audioRecordingInfo) so
observers update; update usages where waveform.append(...) and waveform
assignments occur to perform one of these notifications immediately after the
mutation.

In
`@Sources/StreamChatSwiftUI/ChatChannel/Composer/Suggestions/TypingSuggester.swift`:
- Around line 35-36: The doc comment for TypingSuggestion is stale: it says "A
structure that contains..." but TypingSuggestion is declared as a final class;
update the documentation comment above the TypingSuggestion declaration to refer
to it as a "class" (e.g., "A class that contains the information of the typing
suggestion.") so the comment matches the TypingSuggestion type.

In `@Sources/StreamChatSwiftUI/ChatChannel/MessageList/ImageAttachmentView.swift`:
- Around line 488-496: Add explicit Equatable conformance to MediaAttachmentType
by declaring it conforms to Equatable and implementing the equality operator to
compare rawValue; specifically update the class declaration for
MediaAttachmentType to include Equatable and add a static func ==(lhs:
MediaAttachmentType, rhs: MediaAttachmentType) -> Bool { return lhs.rawValue ==
rhs.rawValue } so generic constraints requiring Equatable will be satisfied
(refer to MediaAttachmentType and its rawValue property).

In `@Sources/StreamChatSwiftUI/ChatChannelList/ChatChannelListViewModel.swift`:
- Around line 655-656: Change the two shared static properties on
ChannelListSearchType from mutable to immutable to prevent external
reassignment: replace the declarations of ChannelListSearchType.channels and
ChannelListSearchType.messages (currently declared as `static var`) with `static
let` so the shared instances cannot be overwritten by consumers.

In `@Sources/StreamChatSwiftUI/Fonts.swift`:
- Around line 8-11: Fonts currently exposes all mutable var properties which
allows shared-mutation when consumers copy appearance.fonts; fix this by making
Fonts value-type or its properties immutable: either convert the public final
class Fonts into a struct Fonts (so appearance.fonts becomes a value copy) or
change each public mutable property on Fonts to let and add explicit
builder/with... methods that return a new Fonts when callers need changes;
reference the Fonts type and appearance.fonts usage and ensure any consumers are
updated to use the new immutable/struct API or builder methods to mutate safely.
🧹 Nitpick comments (6)
Sources/StreamChatSwiftUI/ChatChannel/ChannelInfo/MediaAttachmentsViewModel.swift (1)

109-139: Making videoAttachment and imageAttachment properties let strengthens immutability.

The struct-to-class conversion with final is soundβ€”Identifiable is sufficient for SwiftUI's ForEach (which uses index-based iteration), and no code compares MediaItem instances for equality. Since videoAttachment and imageAttachment are initialized only once and never mutated afterward, making them let properties clarifies intent and eliminates the theoretical risk of accidental mutation through a stored reference:

-    public var videoAttachment: ChatMessageVideoAttachment?
-    public var imageAttachment: ChatMessageImageAttachment?
+    public let videoAttachment: ChatMessageVideoAttachment?
+    public let imageAttachment: ChatMessageImageAttachment?

This change simplifies the contract and prevents any future mutations from introducing state coherency issues.

Sources/StreamChatSwiftUI/Utils/Common/NukeImageProcessor.swift (1)

65-65: Add explicit Sendable conformance to align with codebase patterns.

Converting from struct to final class loses the implicit Sendable conformance that value types with all-Sendable members enjoy. Since sizeProvider is already @Sendable and the class is final with no mutable state, adding Sendable conforms to the established pattern used throughout this codebase for similar types.

Suggested change
-    public final class LateResize: ImageProcessing {
+    public final class LateResize: ImageProcessing, `@unchecked` Sendable {

(@unchecked is appropriate here because DispatchQueue.main.sync access isn't provable to the compiler, though the type is effectively safe.)

Sources/StreamChatSwiftUI/ChatChannelList/ChannelListConfig.swift (1)

31-31: Redundant inline default on channelItemMutedStyle.

The init parameter already defaults to .default (line 12) and always assigns to this property (line 16), so the inline = .default here is dead code. The other two properties in this class don't carry inline defaults, making this inconsistent.

Proposed fix
-    public var channelItemMutedStyle: ChannelItemMutedLayoutStyle = .default
+    public var channelItemMutedStyle: ChannelItemMutedLayoutStyle
Sources/StreamChatSwiftUI/ChatChannel/ChannelInfo/ParticipantInfoView.swift (1)

116-141: Class with closure properties can form retain cycles β€” low risk but worth noting.

As a struct, ParticipantAction was immune to reference cycles. Now that it's a class holding action: () -> Void and navigationDestination: AnyView?, a retain cycle is possible if a closure or AnyView captures the ParticipantAction instance itself. In practice this is unlikely given typical usage patterns, but keep it in mind if you expose builder APIs that chain back to the action.

Sources/StreamChatSwiftUI/DependencyInjection.swift (1)

34-45: Injected<T> should declare Sendable conformance to maintain compatibility with Swift 6 strict concurrency.

Injected<T> is a final class with only a single let keyPath stored property. When this was a struct, it implicitly conformed to Sendable. As a class, it loses that automatic conformance. Since @Injected is used 510+ times across the codebaseβ€”predominantly in View structsβ€”those Views will fail to satisfy Sendable requirements under Swift 6's strict concurrency checking. Since the sole stored property is immutable and WritableKeyPath is Sendable, declaring conformance is safe and trivial.

Proposed fix
 `@propertyWrapper`
-public final class Injected<T> {
+public final class Injected<T>: Sendable {
     private let keyPath: WritableKeyPath<InjectedValues, T>
Sources/StreamChatSwiftUI/ChatChannel/Composer/MessageComposerViewModel+Recording.swift (1)

29-33: static var initial heap-allocates a new instance on every access.

As a computed property returning a new class instance, each call to .initial triggers a heap allocation. This is used on line 50 purely for an equality check (audioRecordingInfo == .initial), creating a throwaway object. Consider a lighter guard:

Possible alternatives
-        if audioRecordingInfo == .initial { return }
+        if audioRecordingInfo.waveform.isEmpty && audioRecordingInfo.duration == 0 { return }

Or cache a shared sentinel instance if .initial is accessed frequently (though be careful with shared mutable state on a class).

Also applies to: 50-50

Comment on lines 19 to 22
func update(with entry: Float, duration: TimeInterval) {
waveform.append(entry)
self.duration = duration
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | πŸ”΄ Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find AudioRecordingInfo definition and check if it's a class or struct
rg -n 'class AudioRecordingInfo|struct AudioRecordingInfo' --type=swift -A 5

Repository: GetStream/stream-chat-swiftui

Length of output: 817


🏁 Script executed:

#!/bin/bash
# Search for `@Published` audioRecordingInfo on MessageComposerViewModel
rg -n '@Published.*audioRecordingInfo|var audioRecordingInfo' --type=swift -B 2 -A 2

Repository: GetStream/stream-chat-swiftui

Length of output: 1164


🏁 Script executed:

#!/bin/bash
# View the entire file to understand context and verify line numbers
cat -n "Sources/StreamChatSwiftUI/ChatChannel/Composer/MessageComposerViewModel+Recording.swift"

Repository: GetStream/stream-chat-swiftui

Length of output: 5305


🏁 Script executed:

#!/bin/bash
# Verify impact: check if RecordingView or other UI components actively observe audioRecordingInfo for live updates
rg -n 'audioRecordingInfo' --type=swift -B 2 -A 2 | grep -A 5 "RecordingView\|\.onChange\|\.onReceive"

Repository: GetStream/stream-chat-swiftui

Length of output: 2375


🏁 Script executed:

#!/bin/bash
# Check if objectWillChange is already being sent anywhere in MessageComposerViewModel
rg -n 'objectWillChange' "Sources/StreamChatSwiftUI/ChatChannel/Composer/MessageComposerViewModel+Recording.swift"

Repository: GetStream/stream-chat-swiftui

Length of output: 55


🏁 Script executed:

#!/bin/bash
# Check RecordingView to see if it's a struct or view and how audioRecordingInfo is used
cat -n "Sources/StreamChatSwiftUI/ChatChannel/Composer/VoiceRecording/RecordingView.swift" | head -50

Repository: GetStream/stream-chat-swiftui

Length of output: 1808


🏁 Script executed:

#!/bin/bash
# Check RecordingDurationView to see if it updates with duration changes
rg -n 'RecordingDurationView' --type=swift -B 2 -A 10

Repository: GetStream/stream-chat-swiftui

Length of output: 8450


🏁 Script executed:

#!/bin/bash
# Check how RecordingView is embedded in the parent view and if it's responding to viewModel changes
rg -n 'RecordingView\(' --type=swift -B 3 -A 3 | head -40

Repository: GetStream/stream-chat-swiftui

Length of output: 3563


🏁 Script executed:

#!/bin/bash
# Check if the parent view observes the viewModel
cat -n "Sources/StreamChatSwiftUI/DefaultViewFactory.swift" | sed -n '720,735p'

Repository: GetStream/stream-chat-swiftui

Length of output: 695


🏁 Script executed:

#!/bin/bash
# Check RecordingWaveform to see if it also uses audioRecordingInfo properties
rg -n 'RecordingWaveform' --type=swift -B 2 -A 10 | head -60

Repository: GetStream/stream-chat-swiftui

Length of output: 3202


🏁 Script executed:

#!/bin/bash
# Check LockedView to see if it observes viewModel
cat -n "Sources/StreamChatSwiftUI/ChatChannel/Composer/VoiceRecording/LockedView.swift" | head -30

Repository: GetStream/stream-chat-swiftui

Length of output: 1105


🏁 Script executed:

#!/bin/bash
# Check the parent view structure - where makeComposerRecordingView is called from
rg -n 'makeComposerRecordingView' --type=swift -B 5 -A 5

Repository: GetStream/stream-chat-swiftui

Length of output: 5387


🏁 Script executed:

#!/bin/bash
# Check MessageComposerView to see how viewModel observes changes
cat -n "Sources/StreamChatSwiftUI/ChatChannel/Composer/MessageComposerView.swift" | head -50

Repository: GetStream/stream-chat-swiftui

Length of output: 2151


🏁 Script executed:

#!/bin/bash
# Check if RecordingView might be wrapped with `@ObservedObject` or similar
rg -n 'RecordingView' "Sources/StreamChatSwiftUI/DefaultViewFactory.swift" -B 10 -A 10

Repository: GetStream/stream-chat-swiftui

Length of output: 1640


🏁 Script executed:

#!/bin/bash
# Final verification: confirm the parent view structure
cat -n "Sources/StreamChatSwiftUI/ChatChannel/Composer/MessageComposerView.swift" | sed -n '118,135p'

Repository: GetStream/stream-chat-swiftui

Length of output: 1177


Critical: In-place mutations on a class won't trigger @Published / SwiftUI updates.

When AudioRecordingInfo was a struct, mutating it through audioRecordingInfo.update(…) (line 40) or audioRecordingInfo.waveform = … (line 66) would trigger the property setter on the @Published var audioRecordingInfo, firing objectWillChange and refreshing any observing SwiftUI views. Now that it's a reference type, these in-place mutations modify the object's internals without replacing the reference, so @Published never fires.

This silently breaks live waveform and duration UI updates during recording. Only full reassignments like audioRecordingInfo = .initial (lines 70, 87, 118, 127) will trigger SwiftUI.

You need to manually fire objectWillChange after in-place mutations, or reassign the property to itself:

Possible fix β€” explicitly notify after in-place mutation
     public func audioRecorder(
         _ audioRecorder: AudioRecording,
         didUpdateContext: AudioRecordingContext
     ) {
         audioRecordingInfo.update(
             with: didUpdateContext.averagePower,
             duration: didUpdateContext.duration
         )
+        objectWillChange.send()
     }

And similarly on line 66:

                         if self.recordingState == .stopped {
                             self.pendingAudioRecording = recording
                             self.audioRecordingInfo.waveform = waveform
+                            self.objectWillChange.send()
                         } else {

Alternatively, consider keeping AudioRecordingInfo as a struct if the value semantics were intentionally leveraged for SwiftUI reactivity.

πŸ€– Prompt for AI Agents
In
`@Sources/StreamChatSwiftUI/ChatChannel/Composer/MessageComposerViewModel`+Recording.swift
around lines 19 - 22, AudioRecordingInfo is now a class so in-place mutations in
MessageComposerViewModel (e.g., AudioRecordingInfo.update(with:duration:) and
direct waveform mutations) don't trigger the `@Published` publisher; after any
in-place mutation of audioRecordingInfo (calls to update(with:duration:) or
modifying audioRecordingInfo.waveform/duration), explicitly notify SwiftUI by
either calling objectWillChange.send() on MessageComposerViewModel or force a
setter by reassigning the property (audioRecordingInfo = audioRecordingInfo) so
observers update; update usages where waveform.append(...) and waveform
assignments occur to perform one of these notifications immediately after the
mutation.

Comment on lines 35 to 36
/// A structure that contains the information of the typing suggestion.
public struct TypingSuggestion {
public final class TypingSuggestion {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟑 Minor

Stale doc comment: "structure" should be "class".

Line 35 still reads "A structure that contains..." but the type is now a final class.

Suggested fix
-/// A structure that contains the information of the typing suggestion.
+/// A class that contains the information of the typing suggestion.
πŸ“ Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/// A structure that contains the information of the typing suggestion.
public struct TypingSuggestion {
public final class TypingSuggestion {
/// A class that contains the information of the typing suggestion.
public final class TypingSuggestion {
πŸ€– Prompt for AI Agents
In
`@Sources/StreamChatSwiftUI/ChatChannel/Composer/Suggestions/TypingSuggester.swift`
around lines 35 - 36, The doc comment for TypingSuggestion is stale: it says "A
structure that contains..." but TypingSuggestion is declared as a final class;
update the documentation comment above the TypingSuggestion declaration to refer
to it as a "class" (e.g., "A class that contains the information of the typing
suggestion.") so the comment matches the TypingSuggestion type.

Comment on lines +488 to 496
public final class MediaAttachmentType: RawRepresentable {
public let rawValue: String
public init(rawValue: String) {
self.rawValue = rawValue
}

public static let image = Self(rawValue: "image")
public static let video = Self(rawValue: "video")
public static let image = MediaAttachmentType(rawValue: "image")
public static let video = MediaAttachmentType(rawValue: "video")
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟑 Minor

🧩 Analysis chain

🏁 Script executed:

# First, let's verify the file exists and examine the MediaAttachmentType implementation
cat -n Sources/StreamChatSwiftUI/ChatChannel/MessageList/ImageAttachmentView.swift | sed -n '480,510p'

Repository: GetStream/stream-chat-swiftui

Length of output: 952


🏁 Script executed:

# Search for all usages of MediaAttachmentType across the codebase
rg -n --type swift 'MediaAttachmentType' | head -60

Repository: GetStream/stream-chat-swiftui

Length of output: 814


🏁 Script executed:

# Search for broader context: look for comparisons, usage in SwiftUI views, arrays, etc.
rg -n --type swift 'MediaAttachmentType' -B 2 -A 2

Repository: GetStream/stream-chat-swiftui

Length of output: 2152


🏁 Script executed:

# Check if there are any Equatable constraints or comparisons involving MediaAttachmentType
rg -n --type swift '(\.image|\.video|== .*MediaAttachmentType|MediaAttachmentType.*==)'

Repository: GetStream/stream-chat-swiftui

Length of output: 50386


🏁 Script executed:

# Search for the struct that contains MediaAttachmentType property to see if it needs Equatable
rg -n --type swift -B 10 'public let type: MediaAttachmentType' Sources/StreamChatSwiftUI/ChatChannel/MessageList/ImageAttachmentView.swift | head -30

Repository: GetStream/stream-chat-swiftui

Length of output: 376


🏁 Script executed:

# Get the full MediaAttachment class definition
rg -n --type swift 'public final class MediaAttachment' -A 50 Sources/StreamChatSwiftUI/ChatChannel/MessageList/ImageAttachmentView.swift | head -60

Repository: GetStream/stream-chat-swiftui

Length of output: 2140


🏁 Script executed:

# Search for any custom == implementation or Equatable conformance issues
rg -n --type swift '(func ==|extension.*Equatable)' Sources/StreamChatSwiftUI/ChatChannel/MessageList/ImageAttachmentView.swift

Repository: GetStream/stream-chat-swiftui

Length of output: 157


🏁 Script executed:

# Check if MediaAttachmentType is used directly in any comparisons or SwiftUI state
rg -n --type swift 'MediaAttachmentType.*=='

Repository: GetStream/stream-chat-swiftui

Length of output: 55


🏁 Script executed:

# Look for ForEach with MediaAttachmentType or similar SwiftUI patterns
rg -n --type swift 'ForEach.*MediaAttachmentType|\.image|\.video' -B 2 -A 2 | head -50

Repository: GetStream/stream-chat-swiftui

Length of output: 4013


🏁 Script executed:

# Check if MediaAttachmentType is used in any Array or Collection contexts that might need Equatable
rg -n --type swift '\[.*MediaAttachmentType.*\]|\@State.*MediaAttachmentType|\.filter.*type.*==' Sources/StreamChatSwiftUI/ChatChannel/MessageList/ImageAttachmentView.swift

Repository: GetStream/stream-chat-swiftui

Length of output: 242


🏁 Script executed:

# Check the GalleryView file which seems to reference source.type == .image (line 77 from earlier search)
cat -n Sources/StreamChatSwiftUI/ChatChannel/Gallery/GalleryView.swift | sed -n '70,90p'

Repository: GetStream/stream-chat-swiftui

Length of output: 1320


🏁 Script executed:

# Check if MediaAttachmentType is used in any SwiftUI state/binding contexts
rg -n --type swift '@State.*source|@Binding.*source|id: \.self.*mediaAttachments' Sources/StreamChatSwiftUI/ChatChannel/Gallery/GalleryView.swift

Repository: GetStream/stream-chat-swiftui

Length of output: 55


🏁 Script executed:

# Check if there are any Hashable constraints on MediaAttachmentType (which would require Equatable)
rg -n --type swift 'Hashable.*MediaAttachmentType|MediaAttachmentType.*Hashable'

Repository: GetStream/stream-chat-swiftui

Length of output: 55


🏁 Script executed:

# Verify the exact line where == is used on MediaAttachmentType in MediaAttachment's == implementation
cat -n Sources/StreamChatSwiftUI/ChatChannel/MessageList/ImageAttachmentView.swift | sed -n '465,470p'

Repository: GetStream/stream-chat-swiftui

Length of output: 322


Add explicit Equatable conformance to MediaAttachmentType.

MediaAttachmentType currently relies on the free-function == overload from RawRepresentable, which allows direct == calls to work but does not satisfy Equatable protocol constraints. While comparisons function in the current codebase, explicit conformance ensures the type can be used safely in generic contexts requiring where T: Equatable.

Proposed fix
-public final class MediaAttachmentType: RawRepresentable {
+public final class MediaAttachmentType: RawRepresentable, Equatable {
     public let rawValue: String
     public init(rawValue: String) {
         self.rawValue = rawValue
     }
 
     public static let image = MediaAttachmentType(rawValue: "image")
     public static let video = MediaAttachmentType(rawValue: "video")
+
+    public static func == (lhs: MediaAttachmentType, rhs: MediaAttachmentType) -> Bool {
+        lhs.rawValue == rhs.rawValue
+    }
 }
πŸ€– Prompt for AI Agents
In `@Sources/StreamChatSwiftUI/ChatChannel/MessageList/ImageAttachmentView.swift`
around lines 488 - 496, Add explicit Equatable conformance to
MediaAttachmentType by declaring it conforms to Equatable and implementing the
equality operator to compare rawValue; specifically update the class declaration
for MediaAttachmentType to include Equatable and add a static func ==(lhs:
MediaAttachmentType, rhs: MediaAttachmentType) -> Bool { return lhs.rawValue ==
rhs.rawValue } so generic constraints requiring Equatable will be satisfied
(refer to MediaAttachmentType and its rawValue property).

Comment on lines +8 to 11
public final class Fonts {
public init() {
// Public init.
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Same shared-mutation risk as ColorPalette β€” all properties are mutable var.

Fonts has all var properties, so the value-to-reference semantics shift carries the same risk described for ColorPalette: consumers copying appearance.fonts into a local variable and mutating it will now unintentionally modify the shared instance. Unlike ColorPalette, there are no lazy var properties here that benefit from class semantics.

πŸ€– Prompt for AI Agents
In `@Sources/StreamChatSwiftUI/Fonts.swift` around lines 8 - 11, Fonts currently
exposes all mutable var properties which allows shared-mutation when consumers
copy appearance.fonts; fix this by making Fonts value-type or its properties
immutable: either convert the public final class Fonts into a struct Fonts (so
appearance.fonts becomes a value copy) or change each public mutable property on
Fonts to let and add explicit builder/with... methods that return a new Fonts
when callers need changes; reference the Fonts type and appearance.fonts usage
and ensure any consumers are updated to use the new immutable/struct API or
builder methods to mutate safely.

@Stream-SDK-Bot
Copy link
Collaborator

SDK Size

title develop branch diff status
StreamChatSwiftUI 9.78 MB 7.92 MB -1902 KB πŸš€

@github-actions
Copy link

github-actions bot commented Feb 6, 2026

Public Interface

+ public final class PaddingsConfig  
+ 
+   public let top: CGFloat
+   public let bottom: CGFloat
+   public let leading: CGFloat
+   public let trailing: CGFloat
+   public var horizontal: CGFloat
+   public var vertical: CGFloat
+   
+ 
+   public init(top: CGFloat,bottom: CGFloat,leading: CGFloat,trailing: CGFloat)

+ public final class LateResize: ImageProcessing  
+ 
+   public var identifier: String
+   
+ 
+   public init(sizeProvider: @escaping @Sendable () -> CGSize)
+   
+ 
+   public func process(_ image: PlatformImage)-> PlatformImage?

+ public final class MessageActionInfo  
+ 
+   public let message: ChatMessage
+   public let identifier: String
+   
+ 
+   public init(message: ChatMessage,identifier: String)

+ public final class MessagePaddings  
+ 
+   public let horizontal: CGFloat
+   public let quotedViewPadding: CGFloat
+   public let singleBottom: CGFloat
+   public let groupBottom: CGFloat
+   
+ 
+   public init(horizontal: CGFloat = 8,quotedViewPadding: CGFloat = 8,singleBottom: CGFloat = 8,groupBottom: CGFloat = 2)

+ public final class Fonts  
+ 
+   public var caption1
+   public var footnoteBold
+   public var footnote
+   public var subheadline
+   public var subheadlineBold
+   public var body
+   public var bodyBold
+   public var bodyItalic
+   public var headline
+   public var headlineBold
+   public var title
+   public var title2
+   public var title3
+   public var emoji
+   
+ 
+   public init()

+ public final class CustomAttachment: Identifiable, Equatable  
+ 
+   public let id: String
+   public let content: AnyAttachmentPayload
+   
+ 
+   public init(id: String,content: AnyAttachmentPayload)
+   
+ 
+   public static func ==(lhs: CustomAttachment,rhs: CustomAttachment)-> Bool

+ public final class ChannelListSearchType: Equatable  
+ 
+   public static let channels
+   public static let messages
+   
+ 
+   public static func ==(lhs: ChannelListSearchType,rhs: ChannelListSearchType)-> Bool

+ public final class ParticipantInfo: Identifiable  
+ 
+   public var id: String
+   public let chatUser: ChatUser
+   public let displayName: String
+   public let onlineInfoText: String
+   public let isDeactivated: Bool
+   
+ 
+   public init(chatUser: ChatUser,displayName: String,onlineInfoText: String,isDeactivated: Bool = false)

+ public final class PollsConfig  
+ 
+   public var multipleAnswers: PollsEntryConfig
+   public var anonymousPoll: PollsEntryConfig
+   public var suggestAnOption: PollsEntryConfig
+   public var addComments: PollsEntryConfig
+   public var maxVotesPerPerson: PollsEntryConfig
+   
+ 
+   public init(multipleAnswers: PollsEntryConfig = .default,anonymousPoll: PollsEntryConfig = .default,suggestAnOption: PollsEntryConfig = .default,addComments: PollsEntryConfig = .default,maxVotesPerPerson: PollsEntryConfig = .default)

+ public final class PHFetchResultCollection: RandomAccessCollection, Equatable  
+ 
+   public let fetchResult: PHFetchResult<PHAsset>
+   public var endIndex: Int
+   public var startIndex: Int
+   
+ 
+   public subscript(position: Int)-> PHAsset
+   
+ 
+   public init(fetchResult: PHFetchResult<PHAsset>)
+   
+ 
+   public static func ==(lhs: PHFetchResultCollection,rhs: PHFetchResultCollection)-> Bool

+ public final class ChatThreadListItemViewModel  
+ 
+   public var parentMessageText: String
+   public var latestReplyMessageText: String
+   public var latestReplyTimestampText: String
+   public var draftReplyText: String?
+   public var unreadRepliesCount: Int
+   public var latestReplyAuthorNameText: String
+   public var isLatestReplyAuthorOnline: Bool
+   public var latestReplyAuthorImageURL: URL?
+   public var latestReplyAuthorId: String
+   public var channelNameText: String
+   
+ 
+   public init(thread: ChatThread)

+ public final class ChannelSelectionInfo: Identifiable  
+ 
+   public let id: String
+   public let channel: ChatChannel
+   public let message: ChatMessage?
+   public var injectedChannelInfo: InjectedChannelInfo?
+   public var searchType: ChannelListSearchType
+   
+ 
+   public init(channel: ChatChannel,message: ChatMessage?,searchType: ChannelListSearchType = .messages)

+ public final class InjectedValues  
+ 
+   public static subscript<K>(key: K.Type)-> K.Value where K: InjectionKey
+   public static subscript<T>(_ keyPath: WritableKeyPath<InjectedValues, T>)-> T

+ public final class ColorPalette  
+ 
+   public var tintColor: Color
+   public var text: UIColor
+   public var textInverted: UIColor
+   public var textLowEmphasis: UIColor
+   public var staticColorText: UIColor
+   public var subtitleText: UIColor
+   public var highlightedColorForColor: (UIColor) -> UIColor
+   public var disabledColorForColor: (UIColor) -> UIColor
+   public var unselectedColorForColor: (UIColor) -> UIColor
+   public var background: UIColor
+   public var background1: UIColor
+   public var background2: UIColor
+   public var background3: UIColor
+   public var background4: UIColor
+   public var background5: UIColor
+   public var background6: UIColor
+   public var background7: UIColor
+   public var background8: UIColor
+   public var overlayBackground: UIColor
+   public var popoverBackground: UIColor
+   public var highlightedBackground: UIColor
+   public var highlightedAccentBackground: UIColor
+   public var highlightedAccentBackground1: UIColor
+   public var pinnedBackground: UIColor
+   public var messageCellHighlightBackground: UIColor
+   public var shadow: UIColor
+   public var lightBorder: UIColor
+   public var innerBorder: UIColor
+   public var border: UIColor
+   public var border2: UIColor
+   public var border3: UIColor
+   public var alert: UIColor
+   public var alternativeActiveTint: UIColor
+   public var inactiveTint: UIColor
+   public var alternativeInactiveTint: UIColor
+   public lazy var messageCurrentUserBackground: [UIColor]
+   public lazy var messageCurrentUserEmphemeralBackground: [UIColor]
+   public lazy var messageOtherUserBackground: [UIColor]
+   public lazy var messageCurrentUserTextColor: UIColor
+   public lazy var messageOtherUserTextColor: UIColor
+   public lazy var quotedMessageBackgroundCurrentUser: UIColor
+   public lazy var quotedMessageBackgroundOtherUser: UIColor
+   public lazy var reactionCurrentUserColor: UIColor?
+   public lazy var reactionOtherUserColor: UIColor?
+   public lazy var selectedReactionBackgroundColor: UIColor?
+   public var voiceMessageControlBackground: UIColor
+   public var messageLinkAttachmentAuthorColor: Color
+   public var messageLinkAttachmentTitleColor: Color
+   public var messageLinkAttachmentTextColor: Color
+   public lazy var composerPlaceholderColor: UIColor
+   public lazy var composerInputBackground: UIColor
+   public lazy var composerInputHighlightedBorder: UIColor
+   public var navigationBarGlyph: UIColor
+   public var navigationBarTitle: UIColor
+   public var navigationBarSubtitle: UIColor
+   public var navigationBarTintColor: Color
+   public var navigationBarBackground: UIColor?
+   public var bannerBackgroundColor: UIColor
+   
+ 
+   public init()

+ public final class ConfirmationPopup  
+ 
+   public let title: String
+   public let message: String?
+   public let buttonTitle: String
+   
+ 
+   public init(title: String,message: String?,buttonTitle: String)

+ public final class TypingSuggestion  
+ 
+   public let text: String
+   public let locationRange: NSRange
+   
+ 
+   public init(text: String,locationRange: NSRange)

+ public final class UserDisplayInfo  
+ 
+   public let id: String
+   public let name: String
+   public let imageURL: URL?
+   public let role: UserRole?
+   public let size: CGSize?
+   public let extraData: [String: RawJSON]
+   
+ 
+   public init(id: String,name: String,imageURL: URL?,role: UserRole? = nil,size: CGSize? = nil,extraData: [String: RawJSON] = [:])

+ public final class ParticipantAction: Identifiable  
+ 
+   public var id: String
+   public let title: String
+   public let iconName: String
+   public let action: () -> Void
+   public let confirmationPopup: ConfirmationPopup?
+   public let isDestructive: Bool
+   public var navigationDestination: AnyView?
+   
+ 
+   public init(title: String,iconName: String,action: @escaping () -> Void,confirmationPopup: ConfirmationPopup?,isDestructive: Bool)

+ public final class MediaAttachmentType: RawRepresentable  
+ 
+   public let rawValue: String
+   public static let image
+   public static let video
+   
+ 
+   public init(rawValue: String)

+ public final class QuotedMessageContentViewOptions  
+ 
+   public let quotedMessage: ChatMessage
+   public let fillAvailableSpace: Bool
+   public let attachmentSize: CGSize
+   
+ 
+   public init(quotedMessage: ChatMessage,fillAvailableSpace: Bool,attachmentSize: CGSize = CGSize(width: 36, height: 36))

+ public final class AddedAsset: Identifiable, Equatable  
+ 
+   public let image: UIImage
+   public let id: String
+   public let url: URL
+   public let type: AssetType
+   public var extraData: [String: RawJSON]
+   public var payload: AttachmentPayload?
+   
+ 
+   public init(image: UIImage,id: String,url: URL,type: AssetType,extraData: [String: RawJSON] = [:],payload: AttachmentPayload? = nil)
+   
+ 
+   public static func ==(lhs: AddedAsset,rhs: AddedAsset)-> Bool

+ public final class ComposerCommand  
+ 
+   public let id: String
+   public var typingSuggestion: TypingSuggestion
+   public let displayInfo: CommandDisplayInfo?
+   public var replacesMessageSent: Bool
+   
+ 
+   public init(id: String,typingSuggestion: TypingSuggestion,displayInfo: CommandDisplayInfo?,replacesMessageSent: Bool = false)

+ public final class TypingSuggestionOptions  
+ 
+   public var symbol: String
+   public var shouldTriggerOnlyAtStart: Bool
+   public var minimumRequiredCharacters: Int
+   
+ 
+   public init(symbol: String,shouldTriggerOnlyAtStart: Bool = false,minimumRequiredCharacters: Int = 0)

+ public final class MediaAttachment: Identifiable, Equatable  
+ 
+   public let url: URL
+   public let type: MediaAttachmentType
+   public var uploadingState: AttachmentUploadingState?
+   public var id: String
+   
+ 
+   public init(url: URL,type: MediaAttachmentType,uploadingState: AttachmentUploadingState? = nil)
+   
+ 
+   public static func ==(lhs: MediaAttachment,rhs: MediaAttachment)-> Bool

+ public final class InjectedChannelInfo  
+ 
+   public var subtitle: String?
+   public var unreadCount: Int
+   public var timestamp: String?
+   public var lastMessageAt: Date?
+   public var latestMessages: [ChatMessage]?
+   
+ 
+   public init(subtitle: String? = nil,unreadCount: Int,timestamp: String? = nil,lastMessageAt: Date? = nil,latestMessages: [ChatMessage]? = nil)

+ public final class ChannelAction: Identifiable  
+ 
+   public var id: String
+   public let title: String
+   public let iconName: String
+   public let action: () -> Void
+   public let confirmationPopup: ConfirmationPopup?
+   public let isDestructive: Bool
+   public var navigationDestination: AnyView?
+   
+ 
+   public init(title: String,iconName: String,action: @escaping () -> Void,confirmationPopup: ConfirmationPopup?,isDestructive: Bool)

+ public final class MediaViewsOptions  
+ 
+   public let selectedIndex: Int
+   
+ 
+   public init(selectedIndex: Int)

+ public final class StreamChatError: Error  
+ 
+   public let errorCode: StreamChatErrorCode
+   public let description: String?
+   public let additionalInfo: [String: Any]?
+   public static let unknown
+   public static let missingData
+   public static let wrongConfig
+   public static let noSuggestionsAvailable
+   
+ 
+   public init(errorCode: StreamChatErrorCode,description: String?,additionalInfo: [String: Any]?)

+ public final class GiphyCommandHandler: CommandHandler  
+ 
+   public let id: String
+   public var displayInfo: CommandDisplayInfo?
+   
+ 
+   public init(commandSymbol: String,id: String = "/giphy")
+   
+ 
+   public func canHandleCommand(in text: String,caretLocation: Int)-> ComposerCommand?
+   public func handleCommand(for text: Binding<String>,selectedRangeLocation: Binding<Int>,command: Binding<ComposerCommand?>,extraData: [String: Any])
+   public func commandHandler(for command: ComposerCommand)-> CommandHandler?
+   public func showSuggestions(for command: ComposerCommand)-> Future<SuggestionInfo, Error>

+ public final class AddUsersOptions  
+ 
+   public let loadedUsers: [ChatUser]
+   
+ 
+   public init(loadedUsers: [ChatUser])

+ public final class MessageAction: Identifiable, Equatable  
+ 
+   public var id: String
+   public let title: String
+   public let iconName: String
+   public let action: () -> Void
+   public let confirmationPopup: ConfirmationPopup?
+   public let isDestructive: Bool
+   public var navigationDestination: AnyView?
+   
+ 
+   public init(id: String = UUID().uuidString,title: String,iconName: String,action: @escaping () -> Void,confirmationPopup: ConfirmationPopup?,isDestructive: Bool)
+   
+ 
+   public static func ==(lhs: MessageAction,rhs: MessageAction)-> Bool

+ public final class ChannelListConfig  
+ 
+   public var messageRelativeDateFormatEnabled: Bool
+   public var showChannelListDividerOnLastItem: Bool
+   public var channelItemMutedStyle: ChannelItemMutedLayoutStyle
+   
+ 
+   public init(messageRelativeDateFormatEnabled: Bool = false,showChannelListDividerOnLastItem: Bool = true,channelItemMutedStyle: ChannelItemMutedLayoutStyle = .default)

+ public final class ChannelAvatarViewOptions  
+ 
+   public var showOnlineIndicator: Bool
+   public var size: CGSize
+   public var avatar: UIImage?
+   
+ 
+   public init(showOnlineIndicator: Bool,size: CGSize = .defaultAvatarSize,avatar: UIImage? = nil)

+ public final class MessageDisplayInfo  
+ 
+   public let message: ChatMessage
+   public let frame: CGRect
+   public let contentWidth: CGFloat
+   public let isFirst: Bool
+   public var showsMessageActions: Bool
+   public var showsBottomContainer: Bool
+   public var keyboardWasShown: Bool
+   
+ 
+   public init(message: ChatMessage,frame: CGRect,contentWidth: CGFloat,isFirst: Bool,showsMessageActions: Bool = true,showsBottomContainer: Bool = true,keyboardWasShown: Bool = false)

+ public final class SuggestionInfo  
+ 
+   public let key: String
+   public let value: Any
+   
+ 
+   public init(key: String,value: Any)

+ public final class MessageModifierInfo  
+ 
+   public var message: ChatMessage
+   public var isFirst: Bool
+   public var injectedBackgroundColor: UIColor?
+   public var cornerRadius: CGFloat
+   public var forceLeftToRight
+   
+ 
+   public init(message: ChatMessage,isFirst: Bool,injectedBackgroundColor: UIColor? = nil,cornerRadius: CGFloat = 18,forceLeftToRight: Bool = false)

+ public final class ChannelItemMutedLayoutStyle: Hashable  
+ 
+   public static var `default`: ChannelItemMutedLayoutStyle
+   public static var topRightCorner: ChannelItemMutedLayoutStyle
+   public static var afterChannelName: ChannelItemMutedLayoutStyle
+   
+ 
+   public static func ==(lhs: ChannelItemMutedLayoutStyle,rhs: ChannelItemMutedLayoutStyle)-> Bool
+   public func hash(into hasher: inout Hasher)

+ public final class PollsEntryConfig  
+ 
+   public var configurable: Bool
+   public var defaultValue: Bool
+   
+ 
+   public init(configurable: Bool,defaultValue: Bool)

+ public final class MentionsCommandHandler: CommandHandler  
+ 
+   public let id: String
+   public var displayInfo: CommandDisplayInfo?
+   
+ 
+   public init(channelController: ChatChannelController,userSearchController: ChatUserSearchController? = nil,commandSymbol: String,mentionAllAppUsers: Bool,id: String = "mentions")
+   
+ 
+   public func canHandleCommand(in text: String,caretLocation: Int)-> ComposerCommand?
+   public func handleCommand(for text: Binding<String>,selectedRangeLocation: Binding<Int>,command: Binding<ComposerCommand?>,extraData: [String: Any])
+   public func commandHandler(for command: ComposerCommand)-> CommandHandler?
+   public func showSuggestions(for command: ComposerCommand)-> Future<SuggestionInfo, Error>

+ public final class MessageDisplayOptions  
+ 
+   public let showAvatars: Bool
+   public let showAvatarsInGroups: Bool
+   public let showMessageDate: Bool
+   public let showAuthorName: Bool
+   public let animateChanges: Bool
+   public let dateLabelSize: CGFloat
+   public let lastInGroupHeaderSize: CGFloat
+   public let newMessagesSeparatorSize: CGFloat
+   public let minimumSwipeGestureDistance: CGFloat
+   public let currentUserMessageTransition: AnyTransition
+   public let otherUserMessageTransition: AnyTransition
+   public let shouldAnimateReactions: Bool
+   public let reactionsPlacement: ReactionsPlacement
+   public let showOriginalTranslatedButton: Bool
+   public let messageLinkDisplayResolver: (ChatMessage) -> [NSAttributedString.Key: Any]
+   public let spacerWidth: (CGFloat) -> CGFloat
+   public let reactionsTopPadding: (ChatMessage) -> CGFloat
+   public let dateSeparator: (ChatMessage, ChatMessage) -> Date?
+   public static var defaultLinkDisplay: (ChatMessage) -> [NSAttributedString.Key: Any]
+   public static var defaultSpacerWidth: (CGFloat) -> (CGFloat)
+   public static var defaultReactionsTopPadding: (ChatMessage) -> CGFloat
+   
+ 
+   public init(showAvatars: Bool = true,showAvatarsInGroups: Bool? = nil,showMessageDate: Bool = true,showAuthorName: Bool = true,animateChanges: Bool = true,overlayDateLabelSize: CGFloat = 40,lastInGroupHeaderSize: CGFloat = 0,newMessagesSeparatorSize: CGFloat = 50,minimumSwipeGestureDistance: CGFloat = 20,currentUserMessageTransition: AnyTransition = .identity,otherUserMessageTransition: AnyTransition = .identity,shouldAnimateReactions: Bool = true,reactionsPlacement: ReactionsPlacement = .top,showOriginalTranslatedButton: Bool = false,messageLinkDisplayResolver: @escaping (ChatMessage) -> [NSAttributedString.Key: Any] = MessageDisplayOptions
+             .defaultLinkDisplay,spacerWidth: @escaping (CGFloat) -> CGFloat = MessageDisplayOptions.defaultSpacerWidth,reactionsTopPadding: @escaping (ChatMessage) -> CGFloat = MessageDisplayOptions.defaultReactionsTopPadding,dateSeparator: @escaping (ChatMessage, ChatMessage) -> Date? = MessageDisplayOptions.defaultDateSeparator)
+   
+ 
+   public func showAvatars(for channel: ChatChannel)-> Bool
+   public static func defaultDateSeparator(message: ChatMessage,previous: ChatMessage)-> Date?

+ public final class MediaItem: Identifiable  
+ 
+   public let id: String
+   public let isVideo: Bool
+   public let message: ChatMessage
+   public var videoAttachment: ChatMessageVideoAttachment?
+   public var imageAttachment: ChatMessageImageAttachment?
+   public var mediaAttachment: MediaAttachment?
+   
+ 
+   public init(id: String,isVideo: Bool,message: ChatMessage,videoAttachment: ChatMessageVideoAttachment?,imageAttachment: ChatMessageImageAttachment?)

+ public final class TypingSuggester  
+ 
+   public let options: TypingSuggestionOptions
+   
+ 
+   public init(options: TypingSuggestionOptions)
+   
+ 
+   public func typingSuggestion(in text: String,caretLocation: Int)-> TypingSuggestion?

+ public final class ChatMessageReactionAppearance: ChatMessageReactionAppearanceType  
+ 
+   public let smallIcon: UIImage
+   public let largeIcon: UIImage
+   
+ 
+   public init(smallIcon: UIImage,largeIcon: UIImage)

+ public final class CommandDisplayInfo  
+ 
+   public let displayName: String
+   public let icon: UIImage
+   public let format: String
+   public let isInstant: Bool
+   
+ 
+   public init(displayName: String,icon: UIImage,format: String,isInstant: Bool)

+ public final class ThreadSelectionInfo: Identifiable  
+ 
+   public let id: String
+   public let thread: ChatThread
+   
+ 
+   public init(thread: ChatThread)

+ public final class ComposerConfig  
+ 
+   public var isVoiceRecordingEnabled: Bool
+   public var inputViewMinHeight: CGFloat
+   public var inputViewMaxHeight: CGFloat
+   public var inputViewCornerRadius: CGFloat
+   public var inputFont: UIFont
+   public var gallerySupportedTypes: GallerySupportedTypes
+   public var maxGalleryAssetsCount: Int?
+   public var inputPaddingsConfig: PaddingsConfig
+   public var adjustMessageOnSend: (String) -> (String)
+   public var adjustMessageOnRead: (String) -> (String)
+   @available(
+         *,
+         deprecated,
+         message: """
+         Override the MessageComposerViewModel.inputAttachmentsAsPayloads() in order to convert the message attachments to payloads.
+         """
+     ) public var attachmentPayloadConverter: (ChatMessage) -> [AnyAttachmentPayload]
+   public static var defaultAttachmentPayloadConverter: (ChatMessage) -> [AnyAttachmentPayload]
+   
+ 
+   public init(isVoiceRecordingEnabled: Bool = false,inputViewMinHeight: CGFloat = 38,inputViewMaxHeight: CGFloat = 76,inputViewCornerRadius: CGFloat = 20,inputFont: UIFont = UIFont.preferredFont(forTextStyle: .body),gallerySupportedTypes: GallerySupportedTypes = .imagesAndVideo,maxGalleryAssetsCount: Int? = nil,inputPaddingsConfig: PaddingsConfig = .composerInput,adjustMessageOnSend: @escaping (String) -> (String) = { $0 },adjustMessageOnRead: @escaping (String) -> (String) = { $0 },attachmentPayloadConverter: @escaping (ChatMessage) -> [AnyAttachmentPayload]
+             = ComposerConfig.defaultAttachmentPayloadConverter)

+ public final class AddedVoiceRecording: Identifiable, Equatable  
+ 
+   public var id: String
+   public let url: URL
+   public let duration: TimeInterval
+   public let waveform: [Float]
+   
+ 
+   public init(url: URL,duration: TimeInterval,waveform: [Float])
+   
+ 
+   public static func ==(lhs: AddedVoiceRecording,rhs: AddedVoiceRecording)-> Bool

+ public final class MessageListConfig  
+ 
+   public let messageListType: MessageListType
+   public let typingIndicatorPlacement: TypingIndicatorPlacement
+   public let groupMessages: Bool
+   public let messageDisplayOptions: MessageDisplayOptions
+   public let messagePaddings: MessagePaddings
+   public let dateIndicatorPlacement: DateIndicatorPlacement
+   public let pageSize: Int
+   public let messagePopoverEnabled: Bool
+   public let doubleTapOverlayEnabled: Bool
+   public let becomesFirstResponderOnOpen: Bool
+   public let resignsFirstResponderOnScrollDown: Bool
+   public let updateChannelsFromMessageList: Bool
+   public let maxTimeIntervalBetweenMessagesInGroup: TimeInterval
+   public let cacheSizeOnChatDismiss: Int
+   public let iPadSplitViewEnabled: Bool
+   public let scrollingAnchor: UnitPoint
+   public let showNewMessagesSeparator: Bool
+   public let handleTabBarVisibility: Bool
+   public let messageListAlignment: MessageListAlignment
+   public let uniqueReactionsEnabled: Bool
+   public let localLinkDetectionEnabled: Bool
+   public let isMessageEditedLabelEnabled: Bool
+   public let markdownSupportEnabled: Bool
+   public let userBlockingEnabled: Bool
+   public let hidesCommandsOverlayOnMessageListTap: Bool
+   public let hidesAttachmentsPickersOnMessageListTap: Bool
+   public let bouncedMessagesAlertActionsEnabled: Bool
+   public let skipEditedMessageLabel: (ChatMessage) -> Bool
+   public let draftMessagesEnabled: Bool
+   public let downloadFileAttachmentsEnabled: Bool
+   public let highlightMessageWhenJumping: Bool
+   
+ 
+   public init(messageListType: MessageListType = .messaging,typingIndicatorPlacement: TypingIndicatorPlacement = .bottomOverlay,groupMessages: Bool = true,messageDisplayOptions: MessageDisplayOptions = MessageDisplayOptions(),messagePaddings: MessagePaddings = MessagePaddings(),dateIndicatorPlacement: DateIndicatorPlacement = .overlay,pageSize: Int = 25,messagePopoverEnabled: Bool = true,doubleTapOverlayEnabled: Bool = false,becomesFirstResponderOnOpen: Bool = false,resignsFirstResponderOnScrollDown: Bool = true,updateChannelsFromMessageList: Bool = false,maxTimeIntervalBetweenMessagesInGroup: TimeInterval = 60,cacheSizeOnChatDismiss: Int = 1024 * 1024 * 100,iPadSplitViewEnabled: Bool = true,scrollingAnchor: UnitPoint = .center,showNewMessagesSeparator: Bool = true,highlightMessageWhenJumping: Bool = true,handleTabBarVisibility: Bool = true,messageListAlignment: MessageListAlignment = .standard,uniqueReactionsEnabled: Bool = false,localLinkDetectionEnabled: Bool = true,isMessageEditedLabelEnabled: Bool = true,markdownSupportEnabled: Bool = true,userBlockingEnabled: Bool = false,bouncedMessagesAlertActionsEnabled: Bool = true,skipEditedMessageLabel: @escaping (ChatMessage) -> Bool = { _ in false },draftMessagesEnabled: Bool = false,downloadFileAttachmentsEnabled: Bool = false,hidesCommandsOverlayOnMessageListTap: Bool = true,hidesAttachmentsPickersOnMessageListTap: Bool = true)

+ @propertyWrapper public final class Injected  
+ 
+   public var wrappedValue: T
+   
+ 
+   public init(_ keyPath: WritableKeyPath<InjectedValues, T>)

- public struct ChannelSelectionInfo: Identifiable  
- 
-   public let id: String
-   public let channel: ChatChannel
-   public let message: ChatMessage?
-   public var injectedChannelInfo: InjectedChannelInfo?
-   public var searchType: ChannelListSearchType
-   
- 
-   public init(channel: ChatChannel,message: ChatMessage?,searchType: ChannelListSearchType = .messages)

- public struct ChannelListSearchType: Equatable  
- 
-   public static var channels
-   public static var messages

- public struct InjectedChannelInfo  
- 
-   public var subtitle: String?
-   public var unreadCount: Int
-   public var timestamp: String?
-   public var lastMessageAt: Date?
-   public var latestMessages: [ChatMessage]?
-   
- 
-   public init(subtitle: String? = nil,unreadCount: Int,timestamp: String? = nil,lastMessageAt: Date? = nil,latestMessages: [ChatMessage]? = nil)

- public struct MessageActionInfo  
- 
-   public let message: ChatMessage
-   public let identifier: String
-   
- 
-   public init(message: ChatMessage,identifier: String)

- public struct MessageModifierInfo  
- 
-   public var message: ChatMessage
-   public var isFirst: Bool
-   public var injectedBackgroundColor: UIColor?
-   public var cornerRadius: CGFloat
-   public var forceLeftToRight
-   
- 
-   public init(message: ChatMessage,isFirst: Bool,injectedBackgroundColor: UIColor? = nil,cornerRadius: CGFloat = 18,forceLeftToRight: Bool = false)

- public struct GiphyCommandHandler: CommandHandler  
- 
-   public let id: String
-   public var displayInfo: CommandDisplayInfo?
-   
- 
-   public init(commandSymbol: String,id: String = "/giphy")
-   
- 
-   public func canHandleCommand(in text: String,caretLocation: Int)-> ComposerCommand?
-   public func handleCommand(for text: Binding<String>,selectedRangeLocation: Binding<Int>,command: Binding<ComposerCommand?>,extraData: [String: Any])
-   public func commandHandler(for command: ComposerCommand)-> CommandHandler?
-   public func showSuggestions(for command: ComposerCommand)-> Future<SuggestionInfo, Error>

- public struct ChannelListConfig  
- 
-   public var messageRelativeDateFormatEnabled: Bool
-   public var showChannelListDividerOnLastItem: Bool
-   public var channelItemMutedStyle: ChannelItemMutedLayoutStyle
-   
- 
-   public init(messageRelativeDateFormatEnabled: Bool = false,showChannelListDividerOnLastItem: Bool = true,channelItemMutedStyle: ChannelItemMutedLayoutStyle = .default)

- public struct ChannelAvatarViewOptions  
- 
-   public var showOnlineIndicator: Bool
-   public var size: CGSize
-   public var avatar: UIImage?
-   
- 
-   public init(showOnlineIndicator: Bool,size: CGSize = .defaultAvatarSize,avatar: UIImage? = nil)

- public struct LateResize: ImageProcessing  
- 
-   public var identifier: String
-   
- 
-   public init(sizeProvider: @escaping @Sendable () -> CGSize)
-   
- 
-   public func process(_ image: PlatformImage)-> PlatformImage?

- public struct ColorPalette  
- 
-   public var tintColor: Color
-   public var text: UIColor
-   public var textInverted: UIColor
-   public var textLowEmphasis: UIColor
-   public var staticColorText: UIColor
-   public var subtitleText: UIColor
-   public var highlightedColorForColor: (UIColor) -> UIColor
-   public var disabledColorForColor: (UIColor) -> UIColor
-   public var unselectedColorForColor: (UIColor) -> UIColor
-   public var background: UIColor
-   public var background1: UIColor
-   public var background2: UIColor
-   public var background3: UIColor
-   public var background4: UIColor
-   public var background5: UIColor
-   public var background6: UIColor
-   public var background7: UIColor
-   public var background8: UIColor
-   public var overlayBackground: UIColor
-   public var popoverBackground: UIColor
-   public var highlightedBackground: UIColor
-   public var highlightedAccentBackground: UIColor
-   public var highlightedAccentBackground1: UIColor
-   public var pinnedBackground: UIColor
-   public var messageCellHighlightBackground: UIColor
-   public var shadow: UIColor
-   public var lightBorder: UIColor
-   public var innerBorder: UIColor
-   public var border: UIColor
-   public var border2: UIColor
-   public var border3: UIColor
-   public var alert: UIColor
-   public var alternativeActiveTint: UIColor
-   public var inactiveTint: UIColor
-   public var alternativeInactiveTint: UIColor
-   public lazy var messageCurrentUserBackground: [UIColor]
-   public lazy var messageCurrentUserEmphemeralBackground: [UIColor]
-   public lazy var messageOtherUserBackground: [UIColor]
-   public lazy var messageCurrentUserTextColor: UIColor
-   public lazy var messageOtherUserTextColor: UIColor
-   public lazy var quotedMessageBackgroundCurrentUser: UIColor
-   public lazy var quotedMessageBackgroundOtherUser: UIColor
-   public lazy var reactionCurrentUserColor: UIColor?
-   public lazy var reactionOtherUserColor: UIColor?
-   public lazy var selectedReactionBackgroundColor: UIColor?
-   public var voiceMessageControlBackground: UIColor
-   public var messageLinkAttachmentAuthorColor: Color
-   public var messageLinkAttachmentTitleColor: Color
-   public var messageLinkAttachmentTextColor: Color
-   public lazy var composerPlaceholderColor: UIColor
-   public lazy var composerInputBackground: UIColor
-   public lazy var composerInputHighlightedBorder: UIColor
-   public var navigationBarGlyph: UIColor
-   public var navigationBarTitle: UIColor
-   public var navigationBarSubtitle: UIColor
-   public var navigationBarTintColor: Color
-   public var navigationBarBackground: UIColor?
-   public var bannerBackgroundColor: UIColor
-   
- 
-   public init()

- public struct ChatThreadListItemViewModel  
- 
-   public var parentMessageText: String
-   public var latestReplyMessageText: String
-   public var latestReplyTimestampText: String
-   public var draftReplyText: String?
-   public var unreadRepliesCount: Int
-   public var latestReplyAuthorNameText: String
-   public var isLatestReplyAuthorOnline: Bool
-   public var latestReplyAuthorImageURL: URL?
-   public var latestReplyAuthorId: String
-   public var channelNameText: String
-   
- 
-   public init(thread: ChatThread)

- public struct ConfirmationPopup  
- 
-   public let title: String
-   public let message: String?
-   public let buttonTitle: String
-   
- 
-   public init(title: String,message: String?,buttonTitle: String)

- public struct ChatMessageReactionAppearance: ChatMessageReactionAppearanceType  
- 
-   public let smallIcon: UIImage
-   public let largeIcon: UIImage
-   
- 
-   public init(smallIcon: UIImage,largeIcon: UIImage)

- public struct MediaViewsOptions  
- 
-   public let selectedIndex: Int
-   
- 
-   public init(selectedIndex: Int)

- public struct PollsEntryConfig  
- 
-   public var configurable: Bool
-   public var defaultValue: Bool
-   
- 
-   public init(configurable: Bool,defaultValue: Bool)

- public struct TypingSuggester  
- 
-   public let options: TypingSuggestionOptions
-   
- 
-   public init(options: TypingSuggestionOptions)
-   
- 
-   public func typingSuggestion(in text: String,caretLocation: Int)-> TypingSuggestion?

- public struct PaddingsConfig  
- 
-   public let top: CGFloat
-   public let bottom: CGFloat
-   public let leading: CGFloat
-   public let trailing: CGFloat
-   public var horizontal: CGFloat
-   public var vertical: CGFloat
-   
- 
-   public init(top: CGFloat,bottom: CGFloat,leading: CGFloat,trailing: CGFloat)

- public struct MessageListConfig  
- 
-   public let messageListType: MessageListType
-   public let typingIndicatorPlacement: TypingIndicatorPlacement
-   public let groupMessages: Bool
-   public let messageDisplayOptions: MessageDisplayOptions
-   public let messagePaddings: MessagePaddings
-   public let dateIndicatorPlacement: DateIndicatorPlacement
-   public let pageSize: Int
-   public let messagePopoverEnabled: Bool
-   public let doubleTapOverlayEnabled: Bool
-   public let becomesFirstResponderOnOpen: Bool
-   public let resignsFirstResponderOnScrollDown: Bool
-   public let updateChannelsFromMessageList: Bool
-   public let maxTimeIntervalBetweenMessagesInGroup: TimeInterval
-   public let cacheSizeOnChatDismiss: Int
-   public let iPadSplitViewEnabled: Bool
-   public let scrollingAnchor: UnitPoint
-   public let showNewMessagesSeparator: Bool
-   public let handleTabBarVisibility: Bool
-   public let messageListAlignment: MessageListAlignment
-   public let uniqueReactionsEnabled: Bool
-   public let localLinkDetectionEnabled: Bool
-   public let isMessageEditedLabelEnabled: Bool
-   public let markdownSupportEnabled: Bool
-   public let userBlockingEnabled: Bool
-   public let hidesCommandsOverlayOnMessageListTap: Bool
-   public let hidesAttachmentsPickersOnMessageListTap: Bool
-   public let bouncedMessagesAlertActionsEnabled: Bool
-   public let skipEditedMessageLabel: (ChatMessage) -> Bool
-   public let draftMessagesEnabled: Bool
-   public let downloadFileAttachmentsEnabled: Bool
-   public let highlightMessageWhenJumping: Bool
-   
- 
-   public init(messageListType: MessageListType = .messaging,typingIndicatorPlacement: TypingIndicatorPlacement = .bottomOverlay,groupMessages: Bool = true,messageDisplayOptions: MessageDisplayOptions = MessageDisplayOptions(),messagePaddings: MessagePaddings = MessagePaddings(),dateIndicatorPlacement: DateIndicatorPlacement = .overlay,pageSize: Int = 25,messagePopoverEnabled: Bool = true,doubleTapOverlayEnabled: Bool = false,becomesFirstResponderOnOpen: Bool = false,resignsFirstResponderOnScrollDown: Bool = true,updateChannelsFromMessageList: Bool = false,maxTimeIntervalBetweenMessagesInGroup: TimeInterval = 60,cacheSizeOnChatDismiss: Int = 1024 * 1024 * 100,iPadSplitViewEnabled: Bool = true,scrollingAnchor: UnitPoint = .center,showNewMessagesSeparator: Bool = true,highlightMessageWhenJumping: Bool = true,handleTabBarVisibility: Bool = true,messageListAlignment: MessageListAlignment = .standard,uniqueReactionsEnabled: Bool = false,localLinkDetectionEnabled: Bool = true,isMessageEditedLabelEnabled: Bool = true,markdownSupportEnabled: Bool = true,userBlockingEnabled: Bool = false,bouncedMessagesAlertActionsEnabled: Bool = true,skipEditedMessageLabel: @escaping (ChatMessage) -> Bool = { _ in false },draftMessagesEnabled: Bool = false,downloadFileAttachmentsEnabled: Bool = false,hidesCommandsOverlayOnMessageListTap: Bool = true,hidesAttachmentsPickersOnMessageListTap: Bool = true)

- public struct CommandDisplayInfo  
- 
-   public let displayName: String
-   public let icon: UIImage
-   public let format: String
-   public let isInstant: Bool
-   
- 
-   public init(displayName: String,icon: UIImage,format: String,isInstant: Bool)

- public struct ComposerConfig  
- 
-   public var isVoiceRecordingEnabled: Bool
-   public var inputViewMinHeight: CGFloat
-   public var inputViewMaxHeight: CGFloat
-   public var inputViewCornerRadius: CGFloat
-   public var inputFont: UIFont
-   public var gallerySupportedTypes: GallerySupportedTypes
-   public var maxGalleryAssetsCount: Int?
-   public var inputPaddingsConfig: PaddingsConfig
-   public var adjustMessageOnSend: (String) -> (String)
-   public var adjustMessageOnRead: (String) -> (String)
-   @available(
-         *,
-         deprecated,
-         message: """
-         Override the MessageComposerViewModel.inputAttachmentsAsPayloads() in order to convert the message attachments to payloads.
-         """
-     ) public var attachmentPayloadConverter: (ChatMessage) -> [AnyAttachmentPayload]
-   public static var defaultAttachmentPayloadConverter: (ChatMessage) -> [AnyAttachmentPayload]
-   
- 
-   public init(isVoiceRecordingEnabled: Bool = false,inputViewMinHeight: CGFloat = 38,inputViewMaxHeight: CGFloat = 76,inputViewCornerRadius: CGFloat = 20,inputFont: UIFont = UIFont.preferredFont(forTextStyle: .body),gallerySupportedTypes: GallerySupportedTypes = .imagesAndVideo,maxGalleryAssetsCount: Int? = nil,inputPaddingsConfig: PaddingsConfig = .composerInput,adjustMessageOnSend: @escaping (String) -> (String) = { $0 },adjustMessageOnRead: @escaping (String) -> (String) = { $0 },attachmentPayloadConverter: @escaping (ChatMessage) -> [AnyAttachmentPayload]
-             = ComposerConfig.defaultAttachmentPayloadConverter)

- public struct ChannelItemMutedLayoutStyle: Hashable  
- 
-   public static var `default`: ChannelItemMutedLayoutStyle
-   public static var topRightCorner: ChannelItemMutedLayoutStyle
-   public static var afterChannelName: ChannelItemMutedLayoutStyle

- public struct MediaAttachment: Identifiable, Equatable  
- 
-   public let url: URL
-   public let type: MediaAttachmentType
-   public var uploadingState: AttachmentUploadingState?
-   public var id: String
-   
- 
-   public init(url: URL,type: MediaAttachmentType,uploadingState: AttachmentUploadingState? = nil)
-   
- 
-   public static func ==(lhs: MediaAttachment,rhs: MediaAttachment)-> Bool

- public struct ParticipantAction: Identifiable  
- 
-   public var id: String
-   public let title: String
-   public let iconName: String
-   public let action: () -> Void
-   public let confirmationPopup: ConfirmationPopup?
-   public let isDestructive: Bool
-   public var navigationDestination: AnyView?
-   
- 
-   public init(title: String,iconName: String,action: @escaping () -> Void,confirmationPopup: ConfirmationPopup?,isDestructive: Bool)

- public struct TypingSuggestionOptions  
- 
-   public var symbol: String
-   public var shouldTriggerOnlyAtStart: Bool
-   public var minimumRequiredCharacters: Int
-   
- 
-   public init(symbol: String,shouldTriggerOnlyAtStart: Bool = false,minimumRequiredCharacters: Int = 0)

- public struct PHFetchResultCollection: RandomAccessCollection, Equatable  
- 
-   public let fetchResult: PHFetchResult<PHAsset>
-   public var endIndex: Int
-   public var startIndex: Int
-   
- 
-   public subscript(position: Int)-> PHAsset
-   
- 
-   public init(fetchResult: PHFetchResult<PHAsset>)

- public struct MessageDisplayOptions  
- 
-   public let showAvatars: Bool
-   public let showAvatarsInGroups: Bool
-   public let showMessageDate: Bool
-   public let showAuthorName: Bool
-   public let animateChanges: Bool
-   public let dateLabelSize: CGFloat
-   public let lastInGroupHeaderSize: CGFloat
-   public let newMessagesSeparatorSize: CGFloat
-   public let minimumSwipeGestureDistance: CGFloat
-   public let currentUserMessageTransition: AnyTransition
-   public let otherUserMessageTransition: AnyTransition
-   public let shouldAnimateReactions: Bool
-   public let reactionsPlacement: ReactionsPlacement
-   public let showOriginalTranslatedButton: Bool
-   public let messageLinkDisplayResolver: (ChatMessage) -> [NSAttributedString.Key: Any]
-   public let spacerWidth: (CGFloat) -> CGFloat
-   public let reactionsTopPadding: (ChatMessage) -> CGFloat
-   public let dateSeparator: (ChatMessage, ChatMessage) -> Date?
-   public static var defaultLinkDisplay: (ChatMessage) -> [NSAttributedString.Key: Any]
-   public static var defaultSpacerWidth: (CGFloat) -> (CGFloat)
-   public static var defaultReactionsTopPadding: (ChatMessage) -> CGFloat
-   
- 
-   public init(showAvatars: Bool = true,showAvatarsInGroups: Bool? = nil,showMessageDate: Bool = true,showAuthorName: Bool = true,animateChanges: Bool = true,overlayDateLabelSize: CGFloat = 40,lastInGroupHeaderSize: CGFloat = 0,newMessagesSeparatorSize: CGFloat = 50,minimumSwipeGestureDistance: CGFloat = 20,currentUserMessageTransition: AnyTransition = .identity,otherUserMessageTransition: AnyTransition = .identity,shouldAnimateReactions: Bool = true,reactionsPlacement: ReactionsPlacement = .top,showOriginalTranslatedButton: Bool = false,messageLinkDisplayResolver: @escaping (ChatMessage) -> [NSAttributedString.Key: Any] = MessageDisplayOptions
-             .defaultLinkDisplay,spacerWidth: @escaping (CGFloat) -> CGFloat = MessageDisplayOptions.defaultSpacerWidth,reactionsTopPadding: @escaping (ChatMessage) -> CGFloat = MessageDisplayOptions.defaultReactionsTopPadding,dateSeparator: @escaping (ChatMessage, ChatMessage) -> Date? = MessageDisplayOptions.defaultDateSeparator)
-   
- 
-   public func showAvatars(for channel: ChatChannel)-> Bool
-   public static func defaultDateSeparator(message: ChatMessage,previous: ChatMessage)-> Date?

- public struct MediaItem: Identifiable  
- 
-   public let id: String
-   public let isVideo: Bool
-   public let message: ChatMessage
-   public var videoAttachment: ChatMessageVideoAttachment?
-   public var imageAttachment: ChatMessageImageAttachment?
-   public var mediaAttachment: MediaAttachment?
-   
- 
-   public init(id: String,isVideo: Bool,message: ChatMessage,videoAttachment: ChatMessageVideoAttachment?,imageAttachment: ChatMessageImageAttachment?)

- public struct TypingSuggestion  
- 
-   public let text: String
-   public let locationRange: NSRange
-   
- 
-   public init(text: String,locationRange: NSRange)

- @propertyWrapper public struct Injected  
- 
-   public var wrappedValue: T
-   
- 
-   public init(_ keyPath: WritableKeyPath<InjectedValues, T>)

- public struct PollsConfig  
- 
-   public var multipleAnswers: PollsEntryConfig
-   public var anonymousPoll: PollsEntryConfig
-   public var suggestAnOption: PollsEntryConfig
-   public var addComments: PollsEntryConfig
-   public var maxVotesPerPerson: PollsEntryConfig
-   
- 
-   public init(multipleAnswers: PollsEntryConfig = .default,anonymousPoll: PollsEntryConfig = .default,suggestAnOption: PollsEntryConfig = .default,addComments: PollsEntryConfig = .default,maxVotesPerPerson: PollsEntryConfig = .default)

- public struct ThreadSelectionInfo: Identifiable  
- 
-   public let id: String
-   public let thread: ChatThread
-   
- 
-   public init(thread: ChatThread)

- public struct Fonts  
- 
-   public var caption1
-   public var footnoteBold
-   public var footnote
-   public var subheadline
-   public var subheadlineBold
-   public var body
-   public var bodyBold
-   public var bodyItalic
-   public var headline
-   public var headlineBold
-   public var title
-   public var title2
-   public var title3
-   public var emoji
-   
- 
-   public init()

- public struct UserDisplayInfo  
- 
-   public let id: String
-   public let name: String
-   public let imageURL: URL?
-   public let role: UserRole?
-   public let size: CGSize?
-   public let extraData: [String: RawJSON]
-   
- 
-   public init(id: String,name: String,imageURL: URL?,role: UserRole? = nil,size: CGSize? = nil,extraData: [String: RawJSON] = [:])

- public struct MessageDisplayInfo  
- 
-   public let message: ChatMessage
-   public let frame: CGRect
-   public let contentWidth: CGFloat
-   public let isFirst: Bool
-   public var showsMessageActions: Bool
-   public var showsBottomContainer: Bool
-   public var keyboardWasShown: Bool
-   
- 
-   public init(message: ChatMessage,frame: CGRect,contentWidth: CGFloat,isFirst: Bool,showsMessageActions: Bool = true,showsBottomContainer: Bool = true,keyboardWasShown: Bool = false)

- public struct MediaAttachmentType: RawRepresentable  
- 
-   public let rawValue: String
-   public static let image
-   public static let video
-   
- 
-   public init(rawValue: String)

- public struct InjectedValues  
- 
-   public static subscript<K>(key: K.Type)-> K.Value where K: InjectionKey
-   public static subscript<T>(_ keyPath: WritableKeyPath<InjectedValues, T>)-> T

- public struct ComposerCommand  
- 
-   public let id: String
-   public var typingSuggestion: TypingSuggestion
-   public let displayInfo: CommandDisplayInfo?
-   public var replacesMessageSent: Bool
-   
- 
-   public init(id: String,typingSuggestion: TypingSuggestion,displayInfo: CommandDisplayInfo?,replacesMessageSent: Bool = false)

- public struct ParticipantInfo: Identifiable  
- 
-   public var id: String
-   public let chatUser: ChatUser
-   public let displayName: String
-   public let onlineInfoText: String
-   public let isDeactivated: Bool
-   
- 
-   public init(chatUser: ChatUser,displayName: String,onlineInfoText: String,isDeactivated: Bool = false)

- public struct AddUsersOptions  
- 
-   public let loadedUsers: [ChatUser]
-   
- 
-   public init(loadedUsers: [ChatUser])

- public struct AddedAsset: Identifiable, Equatable  
- 
-   public let image: UIImage
-   public let id: String
-   public let url: URL
-   public let type: AssetType
-   public var extraData: [String: RawJSON]
-   public var payload: AttachmentPayload?
-   
- 
-   public init(image: UIImage,id: String,url: URL,type: AssetType,extraData: [String: RawJSON] = [:],payload: AttachmentPayload? = nil)
-   
- 
-   public static func ==(lhs: AddedAsset,rhs: AddedAsset)-> Bool

- public struct AddedVoiceRecording: Identifiable, Equatable  
- 
-   public var id: String
-   public let url: URL
-   public let duration: TimeInterval
-   public let waveform: [Float]
-   
- 
-   public init(url: URL,duration: TimeInterval,waveform: [Float])

- public struct MessageAction: Identifiable, Equatable  
- 
-   public var id: String
-   public let title: String
-   public let iconName: String
-   public let action: () -> Void
-   public let confirmationPopup: ConfirmationPopup?
-   public let isDestructive: Bool
-   public var navigationDestination: AnyView?
-   
- 
-   public init(id: String = UUID().uuidString,title: String,iconName: String,action: @escaping () -> Void,confirmationPopup: ConfirmationPopup?,isDestructive: Bool)
-   
- 
-   public static func ==(lhs: MessageAction,rhs: MessageAction)-> Bool

- public struct QuotedMessageContentViewOptions  
- 
-   public let quotedMessage: ChatMessage
-   public let fillAvailableSpace: Bool
-   public let attachmentSize: CGSize
-   
- 
-   public init(quotedMessage: ChatMessage,fillAvailableSpace: Bool,attachmentSize: CGSize = CGSize(width: 36, height: 36))

- public struct StreamChatError: Error  
- 
-   public let errorCode: StreamChatErrorCode
-   public let description: String?
-   public let additionalInfo: [String: Any]?
-   public static let unknown
-   public static let missingData
-   public static let wrongConfig
-   public static let noSuggestionsAvailable

- public struct SuggestionInfo  
- 
-   public let key: String
-   public let value: Any
-   
- 
-   public init(key: String,value: Any)

- public struct CustomAttachment: Identifiable, Equatable  
- 
-   public let id: String
-   public let content: AnyAttachmentPayload
-   
- 
-   public init(id: String,content: AnyAttachmentPayload)
-   
- 
-   public static func ==(lhs: CustomAttachment,rhs: CustomAttachment)-> Bool

- public struct MessagePaddings  
- 
-   public let horizontal: CGFloat
-   public let quotedViewPadding: CGFloat
-   public let singleBottom: CGFloat
-   public let groupBottom: CGFloat
-   
- 
-   public init(horizontal: CGFloat = 8,quotedViewPadding: CGFloat = 8,singleBottom: CGFloat = 8,groupBottom: CGFloat = 2)

- public struct ChannelAction: Identifiable  
- 
-   public var id: String
-   public let title: String
-   public let iconName: String
-   public let action: () -> Void
-   public let confirmationPopup: ConfirmationPopup?
-   public let isDestructive: Bool
-   public var navigationDestination: AnyView?
-   
- 
-   public init(title: String,iconName: String,action: @escaping () -> Void,confirmationPopup: ConfirmationPopup?,isDestructive: Bool)

- public struct MentionsCommandHandler: CommandHandler  
- 
-   public let id: String
-   public var displayInfo: CommandDisplayInfo?
-   
- 
-   public init(channelController: ChatChannelController,userSearchController: ChatUserSearchController? = nil,commandSymbol: String,mentionAllAppUsers: Bool,id: String = "mentions")
-   
- 
-   public func canHandleCommand(in text: String,caretLocation: Int)-> ComposerCommand?
-   public func handleCommand(for text: Binding<String>,selectedRangeLocation: Binding<Int>,command: Binding<ComposerCommand?>,extraData: [String: Any])
-   public func commandHandler(for command: ComposerCommand)-> CommandHandler?
-   public func showSuggestions(for command: ComposerCommand)-> Future<SuggestionInfo, Error>

@Stream-SDK-Bot
Copy link
Collaborator

StreamChatSwiftUI XCSize

Object Diff (bytes)
SearchResultsView.o -487844
ChatThreadListNavigatableItem.o -344719
ChatChannelList.o -270508
ChatThreadList.o -253084
ChatChannelNavigatableListItem.o -231943
Show 174 more objects
Object Diff (bytes)
ChatThreadListItem.o -189928
MediaAttachmentsView.o -46177
QuotedMessageView.o -40165
MediaAttachmentsViewModel.o -38354
ChatChannelView.o -31220
ReactionsOverlayView.o -27584
MessageActionsViewModel.o -21860
MessageBubble.o -20253
MessageContainerView.o -19847
DefaultViewFactory.o +7668
ImageAttachmentView.o -7229
Images.o -6108
ChatChannelViewModel.o +5392
MessageComposerViewModel.o -4243
MessageListView.o +3708
ChatChannelInfoViewModel.o +2818
MessageListConfig.o +2710
ParticipantInfoView.o -2579
ColorPalette.o +2423
ChatChannelListItem.o +2261
ChatChannelHeaderViewModifier.o +2250
ComposerConfig.o +2223
CreatePollView.o +2202
MessageListHelperViews.o +2180
ChatChannelExtensions.o +2017
FileAttachmentView.o +2004
ComposerHelperViews.o +1988
ChatChannelListViewModel.o -1939
ComposerModels.o -1852
ImagePipeline.o -1792
PinnedMessagesView.o +1672
MessageView.o +1652
CreatePollViewModel.o +1648
DefaultMessageActions.o +1636
Utils.o -1552
GalleryView.o +1492
Appearance.o -1464
LinkAttachmentView.o +1332
ChannelAvatarsMerger.o +1324
AddUsersView.o +1281
DeletedMessageView.o +1280
MoreChannelActionsViewModel.o +1209
TypingSuggester.o +1171
AttachmentPickerView.o +1164
MessageCachingUtils.o -1162
MarkdownFormatter.o +1128
GiphyCommandHandler.o -1113
FileAttachmentsView.o +1052
GiphyAttachmentView.o +1048
ReactionUserView.o +1012
GalleryHeaderView.o +984
MessageActionsView.o -920
PollsConfig.o +909
CommandsHandler.o -906
MessageTranslationFooterView.o +880
DependencyInjection.o +874
ReactionsOverlayContainer.o +868
ChatChannelInfoHelperViews.o +866
ChatChannelListView.o -814
InstantCommandsHandler.o -810
PollAttachmentView.o +792
ActionItemView.o +780
InjectedValuesExtensions.o -772
StreamChat.o +765
ChatChannelListHeader.o +756
SearchBar.o +752
MessageViewModel.o +740
AttachmentPickerTypeView.o +688
InstantCommandsView.o +660
PhotoAttachmentPickerView.o +656
ChannelListConfig.o +655
TrailingComposerView.o +636
FileAttachmentsViewModel.o +629
FileAttachmentPreview.o +608
MessageThreadHeaderViewModifier.o +604
MentionUsersView.o +584
ImagePickerView.o +580
MentionsCommandHandler.o -566
PhotoAssetsUtils.o +565
Modifiers.o +560
ChannelHeaderLoader.o +544
VideoAttachmentView.o +540
MessageAvatarView.o +536
NoContentView.o +504
TwoStepMentionCommand.o -504
ChatChannelHelperViews.o +500
PollResultsView.o +488
AttachmentUploadingStateView.o +488
PollCommentsView.o +480
CommandsConfig.o -472
ActionBannerView.o +468
BottomReactionsView.o +468
SlowModeView.o +460
AudioVisualizationView.o +452
ReactionsUsersView.o +448
SendInChannelView.o +436
ChatChannelSwipeableListItem.o +432
PollsHelpers.o +432
ReactionsIconProvider.o -432
NavigationBarThemeViewModifier.o +416
ReactionsBubbleView.o +416
AttachmentDownloadingStateView.o +408
RecordingView.o +388
ChatThreadListViewModel.o -376
UnmuteCommandHandler.o +376
MuteCommandHandler.o +376
SendMessageButton.o +356
ImageRequestKeys.o +356
VoiceRecordingContainerView.o -346
NukeImageProcessor.o +343
GridMediaView.o -332
LockedView.o +320
Errors.o +320
WaveformView.o -308
VideoPlayerFooterView.o +308
MessageComposerView.o +300
AddedFileAttachmentsView.o +296
MessagePreviewFormatter.o +288
BouncedMessageActionsModifier.o +288
CommandsContainerView.o -286
SystemMessageView.o +284
LinkTextView.o +264
ReactionsOverlayViewModel.o +264
GiphyBadgeView.o +256
PollCommentsViewModel.o +248
Fonts.o +247
ChatMessageReactionAppeareance.o +247
ChatThreadListHeaderViewModifier.o +244
TypingIndicatorView.o +224
NoThreadsView.o +220
ChatThreadListHeaderView.o +220
VideoPlayerView.o +216
MessageRepliesView.o +216
PercentageProgressView.o +212
AssetType.o +208
ChatThreadListErrorBannerView.o +204
ZoomableScrollView.o +204
ChatMessage+Extensions.o +204
TitleWithCloseButton.o +200
PollAttachmentViewModel.o +200
RecordingTipView.o +188
Shimmer.o +176
DiscardAttachmentButton.o +176
NoChannelsView.o +172
LoadingView.o -172
RecordingDurationView.o +172
ChannelControllerFactory.o +168
AddedVoiceRecordingsView.o +166
SnapshotCreator.o +164
NavigationContainerView.o +164
ChatInfoParticipantsView.o +163
AsyncTask.o -132
AddUsersViewModel.o +132
ComposerTextInputView.o +124
AddedImageAttachmentsView.o -124
VideoPreviewLoader.o +116
FilePickerView.o +116
ChatThreadListView.o -104
MessageComposerViewModel+Recording.o -104
DiscardButtonView.o +104
LazyImageExtensions.o +92
ChatChannelListScreen.o +92
ShareButtonView.o +84
ReactionsUsersViewModel.o +84
PollOptionAllVotesView.o +80
NukeImageLoader.o +80
MoreChannelActionsView.o +80
MessageActionsResolver.o +68
VideoDurationFormatter.o -64
MoreChannelActionsFullScreenWrappingView.o +60
ChatChannelInfoView.o +60
PollAllOptionsView.o -48
ReactionsHelperViews.o +48
MessageListDateUtils.o -44

@sonarqubecloud
Copy link

sonarqubecloud bot commented Feb 6, 2026

Quality Gate Failed Quality Gate failed

Failed conditions
73.5% Coverage on New Code (required β‰₯ 80%)

See analysis details on SonarQube Cloud

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants