-
Notifications
You must be signed in to change notification settings - Fork 110
[V5] Use MainActor in StreamChat, Images, Fonts, Appearance, Utils #984
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Generated by 🚫 Danger |
SDK Size
|
a988c75
to
cb562f5
Compare
Public Interface+ public final class ChannelAvatarsMergerOptions: Sendable
+
+ public let imageProcessor: ImageProcessor
+ public let imageMerger: ImageMerging
+ public let placeholder1: UIImage
+ public let placeholder2: UIImage
+ public let placeholder3: UIImage
+ public let placeholder4: UIImage
+
+
+ @MainActor public convenience init()
+ public init(imageProcessor: ImageProcessor,imageMerger: ImageMerging,placeholder1: UIImage,placeholder2: UIImage,placeholder3: UIImage,placeholder4: UIImage)
- @propertyWrapper public struct Injected
+ @MainActor @propertyWrapper public struct Injected
public struct ThreadsLazyVStack: View
- public init(factory: Factory,threads: LazyCachedMapCollection<ChatThread>,threadDestination: @escaping (ChatThread) -> Factory.ThreadDestination,selectedThread: Binding<ThreadSelectionInfo?>,onItemTap: @escaping (ChatThread) -> Void,onItemAppear: @escaping (Int) -> Void)
+ public init(factory: Factory,threads: LazyCachedMapCollection<ChatThread>,threadDestination: @escaping @MainActor (ChatThread) -> Factory.ThreadDestination,selectedThread: Binding<ThreadSelectionInfo?>,onItemTap: @escaping (ChatThread) -> Void,onItemAppear: @escaping (Int) -> Void)
- public class Appearance
+ @MainActor public class Appearance
- public static var localizationProvider: (_ key: String, _ table: String) -> String
+ public static var localizationProvider: @Sendable (_ key: String, _ table: String) -> String
- public protocol AudioSessionFeedbackGenerator
+ @MainActor public protocol AudioSessionFeedbackGenerator
- public enum AssetType
+ public enum AssetType: Sendable
- open class ChatChannelListViewModel: ObservableObject, ChatChannelListControllerDelegate, ChatMessageSearchControllerDelegate
+ @MainActor open class ChatChannelListViewModel: ObservableObject, ChatChannelListControllerDelegate, ChatMessageSearchControllerDelegate
- open class MoreChannelActionsViewModel: ObservableObject
+ @MainActor open class MoreChannelActionsViewModel: ObservableObject
public struct MessageListView: View, KeyboardReadable
- public init(factory: Factory,channel: ChatChannel,messages: LazyCachedMapCollection<ChatMessage>,messagesGroupingInfo: [String: [String]],scrolledId: Binding<String?>,showScrollToLatestButton: Binding<Bool>,quotedMessage: Binding<ChatMessage?>,currentDateString: String? = nil,listId: String,isMessageThread: Bool = false,shouldShowTypingIndicator: Bool = false,scrollPosition: Binding<String?> = .constant(nil),loadingNextMessages: Bool = false,firstUnreadMessageId: Binding<MessageId?> = .constant(nil),onMessageAppear: @escaping (Int, ScrollDirection) -> Void,onScrollToBottom: @escaping () -> Void,onLongPress: @escaping (MessageDisplayInfo) -> Void,onJumpToMessage: ((String) -> Bool)? = nil)
+ public init(factory: Factory,channel: ChatChannel,messages: LazyCachedMapCollection<ChatMessage>,messagesGroupingInfo: [String: [String]],scrolledId: Binding<String?>,showScrollToLatestButton: Binding<Bool>,quotedMessage: Binding<ChatMessage?>,currentDateString: String? = nil,listId: String,isMessageThread: Bool = false,shouldShowTypingIndicator: Bool = false,scrollPosition: Binding<String?> = .constant(nil),loadingNextMessages: Bool = false,firstUnreadMessageId: Binding<MessageId?> = .constant(nil),onMessageAppear: @escaping @MainActor (Int, ScrollDirection) -> Void,onScrollToBottom: @escaping @MainActor () -> Void,onLongPress: @escaping @MainActor (MessageDisplayInfo) -> Void,onJumpToMessage: ((String) -> Bool)? = nil)
extension DateFormatter
- public static var messageListDateOverlay: DateFormatter
+ @MainActor public static var messageListDateOverlay: DateFormatter
extension ViewFactory
- public func supportedMoreChannelActions(for channel: ChatChannel,onDismiss: @escaping () -> Void,onError: @escaping (Error) -> Void)-> [ChannelAction]
+ public func supportedMoreChannelActions(for channel: ChatChannel,onDismiss: @escaping @MainActor () -> Void,onError: @escaping @MainActor (Error) -> Void)-> [ChannelAction]
- public func makeMoreChannelActionsView(for channel: ChatChannel,swipedChannelId: Binding<String?>,onDismiss: @escaping () -> Void,onError: @escaping (Error) -> Void)-> some View
+ public func makeMoreChannelActionsView(for channel: ChatChannel,swipedChannelId: Binding<String?>,onDismiss: @escaping @MainActor () -> Void,onError: @escaping @MainActor (Error) -> Void)-> some View
- public func makeChannelListItem(channel: ChatChannel,channelName: String,avatar: UIImage,onlineIndicatorShown: Bool,disabled: Bool,selectedChannel: Binding<ChannelSelectionInfo?>,swipedChannelId: Binding<String?>,channelDestination: @escaping (ChannelSelectionInfo) -> ChannelDestination,onItemTap: @escaping (ChatChannel) -> Void,trailingSwipeRightButtonTapped: @escaping (ChatChannel) -> Void,trailingSwipeLeftButtonTapped: @escaping (ChatChannel) -> Void,leadingSwipeButtonTapped: @escaping (ChatChannel) -> Void)-> some View
+ public func makeChannelListItem(channel: ChatChannel,channelName: String,avatar: UIImage,onlineIndicatorShown: Bool,disabled: Bool,selectedChannel: Binding<ChannelSelectionInfo?>,swipedChannelId: Binding<String?>,channelDestination: @escaping @MainActor (ChannelSelectionInfo) -> ChannelDestination,onItemTap: @escaping @MainActor (ChatChannel) -> Void,trailingSwipeRightButtonTapped: @escaping @MainActor (ChatChannel) -> Void,trailingSwipeLeftButtonTapped: @escaping @MainActor (ChatChannel) -> Void,leadingSwipeButtonTapped: @escaping @MainActor (ChatChannel) -> Void)-> some View
- public func makeTrailingSwipeActionsView(channel: ChatChannel,offsetX: CGFloat,buttonWidth: CGFloat,swipedChannelId: Binding<String?>,leftButtonTapped: @escaping (ChatChannel) -> Void,rightButtonTapped: @escaping (ChatChannel) -> Void)-> TrailingSwipeActionsView
+ public func makeTrailingSwipeActionsView(channel: ChatChannel,offsetX: CGFloat,buttonWidth: CGFloat,swipedChannelId: Binding<String?>,leftButtonTapped: @escaping @MainActor (ChatChannel) -> Void,rightButtonTapped: @escaping @MainActor (ChatChannel) -> Void)-> TrailingSwipeActionsView
- public func makeLeadingSwipeActionsView(channel: ChatChannel,offsetX: CGFloat,buttonWidth: CGFloat,swipedChannelId: Binding<String?>,buttonTapped: (ChatChannel) -> Void)-> EmptyView
+ public func makeLeadingSwipeActionsView(channel: ChatChannel,offsetX: CGFloat,buttonWidth: CGFloat,swipedChannelId: Binding<String?>,buttonTapped: @MainActor (ChatChannel) -> Void)-> EmptyView
- public func makeSearchResultsView(selectedChannel: Binding<ChannelSelectionInfo?>,searchResults: [ChannelSelectionInfo],loadingSearchResults: Bool,onlineIndicatorShown: @escaping (ChatChannel) -> Bool,channelNaming: @escaping (ChatChannel) -> String,imageLoader: @escaping (ChatChannel) -> UIImage,onSearchResultTap: @escaping (ChannelSelectionInfo) -> Void,onItemAppear: @escaping (Int) -> Void)-> some View
+ public func makeSearchResultsView(selectedChannel: Binding<ChannelSelectionInfo?>,searchResults: [ChannelSelectionInfo],loadingSearchResults: Bool,onlineIndicatorShown: @escaping @MainActor (ChatChannel) -> Bool,channelNaming: @escaping @MainActor (ChatChannel) -> String,imageLoader: @escaping @MainActor (ChatChannel) -> UIImage,onSearchResultTap: @escaping @MainActor (ChannelSelectionInfo) -> Void,onItemAppear: @escaping @MainActor (Int) -> Void)-> some View
- public func makeChannelListSearchResultItem(searchResult: ChannelSelectionInfo,onlineIndicatorShown: Bool,channelName: String,avatar: UIImage,onSearchResultTap: @escaping (ChannelSelectionInfo) -> Void,channelDestination: @escaping (ChannelSelectionInfo) -> ChannelDestination)-> some View
+ public func makeChannelListSearchResultItem(searchResult: ChannelSelectionInfo,onlineIndicatorShown: Bool,channelName: String,avatar: UIImage,onSearchResultTap: @escaping @MainActor (ChannelSelectionInfo) -> Void,channelDestination: @escaping @MainActor (ChannelSelectionInfo) -> ChannelDestination)-> some View
- public func makeChannelDestination()-> (ChannelSelectionInfo) -> ChatChannelView<Self>
+ public func makeChannelDestination()-> @MainActor (ChannelSelectionInfo) -> ChatChannelView<Self>
- public func makeMessageThreadDestination()-> (ChatChannel, ChatMessage) -> ChatChannelView<Self>
+ public func makeMessageThreadDestination()-> @MainActor (ChatChannel, ChatMessage) -> ChatChannelView<Self>
- public func makeMessageContainerView(channel: ChatChannel,message: ChatMessage,width: CGFloat?,showsAllInfo: Bool,isInThread: Bool,scrolledId: Binding<String?>,quotedMessage: Binding<ChatMessage?>,onLongPress: @escaping (MessageDisplayInfo) -> Void,isLast: Bool)-> some View
+ public func makeMessageContainerView(channel: ChatChannel,message: ChatMessage,width: CGFloat?,showsAllInfo: Bool,isInThread: Bool,scrolledId: Binding<String?>,quotedMessage: Binding<ChatMessage?>,onLongPress: @escaping @MainActor (MessageDisplayInfo) -> Void,isLast: Bool)-> some View
- public func makeScrollToBottomButton(unreadCount: Int,onScrollToBottom: @escaping () -> Void)-> some View
+ public func makeScrollToBottomButton(unreadCount: Int,onScrollToBottom: @escaping @MainActor () -> Void)-> some View
- public func makeMessageComposerViewType(with channelController: ChatChannelController,messageController: ChatMessageController?,quotedMessage: Binding<ChatMessage?>,editedMessage: Binding<ChatMessage?>,onMessageSent: @escaping () -> Void)-> MessageComposerView<Self>
+ public func makeMessageComposerViewType(with channelController: ChatChannelController,messageController: ChatMessageController?,quotedMessage: Binding<ChatMessage?>,editedMessage: Binding<ChatMessage?>,onMessageSent: @escaping @MainActor () -> Void)-> MessageComposerView<Self>
- @ViewBuilder public func makeComposerInputView(text: Binding<String>,selectedRangeLocation: Binding<Int>,command: Binding<ComposerCommand?>,addedAssets: [AddedAsset],addedFileURLs: [URL],addedCustomAttachments: [CustomAttachment],quotedMessage: Binding<ChatMessage?>,maxMessageLength: Int?,cooldownDuration: Int,onCustomAttachmentTap: @escaping (CustomAttachment) -> Void,shouldScroll: Bool,removeAttachmentWithId: @escaping (String) -> Void)-> some View
+ @ViewBuilder public func makeComposerInputView(text: Binding<String>,selectedRangeLocation: Binding<Int>,command: Binding<ComposerCommand?>,addedAssets: [AddedAsset],addedFileURLs: [URL],addedCustomAttachments: [CustomAttachment],quotedMessage: Binding<ChatMessage?>,maxMessageLength: Int?,cooldownDuration: Int,onCustomAttachmentTap: @escaping @MainActor (CustomAttachment) -> Void,shouldScroll: Bool,removeAttachmentWithId: @escaping @MainActor (String) -> Void)-> some View
- public func makeTrailingComposerView(enabled: Bool,cooldownDuration: Int,onTap: @escaping () -> Void)-> some View
+ public func makeTrailingComposerView(enabled: Bool,cooldownDuration: Int,onTap: @escaping @MainActor () -> Void)-> some View
- public func makeAttachmentPickerView(attachmentPickerState: Binding<AttachmentPickerState>,filePickerShown: Binding<Bool>,cameraPickerShown: Binding<Bool>,addedFileURLs: Binding<[URL]>,onPickerStateChange: @escaping (AttachmentPickerState) -> Void,photoLibraryAssets: PHFetchResult<PHAsset>?,onAssetTap: @escaping (AddedAsset) -> Void,onCustomAttachmentTap: @escaping (CustomAttachment) -> Void,isAssetSelected: @escaping (String) -> Bool,addedCustomAttachments: [CustomAttachment],cameraImageAdded: @escaping (AddedAsset) -> Void,askForAssetsAccessPermissions: @escaping () -> Void,isDisplayed: Bool,height: CGFloat,popupHeight: CGFloat)-> some View
+ public func makeAttachmentPickerView(attachmentPickerState: Binding<AttachmentPickerState>,filePickerShown: Binding<Bool>,cameraPickerShown: Binding<Bool>,addedFileURLs: Binding<[URL]>,onPickerStateChange: @escaping @MainActor (AttachmentPickerState) -> Void,photoLibraryAssets: PHFetchResult<PHAsset>?,onAssetTap: @escaping @MainActor (AddedAsset) -> Void,onCustomAttachmentTap: @escaping @MainActor (CustomAttachment) -> Void,isAssetSelected: @escaping @MainActor (String) -> Bool,addedCustomAttachments: [CustomAttachment],cameraImageAdded: @escaping @MainActor (AddedAsset) -> Void,askForAssetsAccessPermissions: @escaping @MainActor () -> Void,isDisplayed: Bool,height: CGFloat,popupHeight: CGFloat)-> some View
- public func makeCustomAttachmentView(addedCustomAttachments: [CustomAttachment],onCustomAttachmentTap: @escaping (CustomAttachment) -> Void)-> some View
+ public func makeCustomAttachmentView(addedCustomAttachments: [CustomAttachment],onCustomAttachmentTap: @escaping @MainActor (CustomAttachment) -> Void)-> some View
- public func makeCustomAttachmentPreviewView(addedCustomAttachments: [CustomAttachment],onCustomAttachmentTap: @escaping (CustomAttachment) -> Void)-> some View
+ public func makeCustomAttachmentPreviewView(addedCustomAttachments: [CustomAttachment],onCustomAttachmentTap: @escaping @MainActor (CustomAttachment) -> Void)-> some View
- public func makeAttachmentSourcePickerView(selected: AttachmentPickerState,onPickerStateChange: @escaping (AttachmentPickerState) -> Void)-> some View
+ public func makeAttachmentSourcePickerView(selected: AttachmentPickerState,onPickerStateChange: @escaping @MainActor (AttachmentPickerState) -> Void)-> some View
- public func makePhotoAttachmentPickerView(assets: PHFetchResultCollection,onAssetTap: @escaping (AddedAsset) -> Void,isAssetSelected: @escaping (String) -> Bool)-> some View
+ public func makePhotoAttachmentPickerView(assets: PHFetchResultCollection,onAssetTap: @escaping @MainActor (AddedAsset) -> Void,isAssetSelected: @escaping @MainActor (String) -> Bool)-> some View
- public func makeCameraPickerView(selected: Binding<AttachmentPickerState>,cameraPickerShown: Binding<Bool>,cameraImageAdded: @escaping (AddedAsset) -> Void)-> some View
+ public func makeCameraPickerView(selected: Binding<AttachmentPickerState>,cameraPickerShown: Binding<Bool>,cameraImageAdded: @escaping @MainActor (AddedAsset) -> Void)-> some View
- public func supportedMessageActions(for message: ChatMessage,channel: ChatChannel,onFinish: @escaping (MessageActionInfo) -> Void,onError: @escaping (Error) -> Void)-> [MessageAction]
+ public func supportedMessageActions(for message: ChatMessage,channel: ChatChannel,onFinish: @escaping @MainActor (MessageActionInfo) -> Void,onError: @escaping @MainActor (Error) -> Void)-> [MessageAction]
- public func makeMessageActionsView(for message: ChatMessage,channel: ChatChannel,onFinish: @escaping (MessageActionInfo) -> Void,onError: @escaping (Error) -> Void)-> some View
+ public func makeMessageActionsView(for message: ChatMessage,channel: ChatChannel,onFinish: @escaping @MainActor (MessageActionInfo) -> Void,onError: @escaping @MainActor (Error) -> Void)-> some View
- public func makeBottomReactionsView(message: ChatMessage,showsAllInfo: Bool,onTap: @escaping () -> Void,onLongPress: @escaping () -> Void)-> some View
+ public func makeBottomReactionsView(message: ChatMessage,showsAllInfo: Bool,onTap: @escaping @MainActor () -> Void,onLongPress: @escaping @MainActor () -> Void)-> some View
- public func makeMessageReactionView(message: ChatMessage,onTapGesture: @escaping () -> Void,onLongPressGesture: @escaping () -> Void)-> some View
+ public func makeMessageReactionView(message: ChatMessage,onTapGesture: @escaping @MainActor () -> Void,onLongPressGesture: @escaping @MainActor () -> Void)-> some View
- public func makeReactionsOverlayView(channel: ChatChannel,currentSnapshot: UIImage,messageDisplayInfo: MessageDisplayInfo,onBackgroundTap: @escaping () -> Void,onActionExecuted: @escaping (MessageActionInfo) -> Void)-> some View
+ public func makeReactionsOverlayView(channel: ChatChannel,currentSnapshot: UIImage,messageDisplayInfo: MessageDisplayInfo,onBackgroundTap: @escaping @MainActor () -> Void,onActionExecuted: @escaping @MainActor (MessageActionInfo) -> Void)-> some View
- public func makeReactionsContentView(message: ChatMessage,contentRect: CGRect,onReactionTap: @escaping (MessageReactionType) -> Void)-> some View
+ public func makeReactionsContentView(message: ChatMessage,contentRect: CGRect,onReactionTap: @escaping @MainActor (MessageReactionType) -> Void)-> some View
- public func makeCommandsContainerView(suggestions: [String: Any],handleCommand: @escaping ([String: Any]) -> Void)-> some View
+ public func makeCommandsContainerView(suggestions: [String: Any],handleCommand: @escaping @MainActor ([String: Any]) -> Void)-> some View
- public func makeJumpToUnreadButton(channel: ChatChannel,onJumpToMessage: @escaping () -> Void,onClose: @escaping () -> Void)-> some View
+ public func makeJumpToUnreadButton(channel: ChatChannel,onJumpToMessage: @escaping @MainActor () -> Void,onClose: @escaping @MainActor () -> Void)-> some View
- public func makeThreadDestination()-> (ChatThread) -> ChatChannelView<Self>
+ public func makeThreadDestination()-> @MainActor (ChatThread) -> ChatChannelView<Self>
- public func makeThreadListItem(thread: ChatThread,threadDestination: @escaping (ChatThread) -> ThreadDestination,selectedThread: Binding<ThreadSelectionInfo?>)-> some View
+ public func makeThreadListItem(thread: ChatThread,threadDestination: @escaping @MainActor (ChatThread) -> ThreadDestination,selectedThread: Binding<ThreadSelectionInfo?>)-> some View
- public func makeThreadsListErrorBannerView(onRefreshAction: @escaping () -> Void)-> some View
+ public func makeThreadsListErrorBannerView(onRefreshAction: @escaping @MainActor () -> Void)-> some View
- public func makeAddUsersView(options: AddUsersOptions,onUserTap: @escaping (ChatUser) -> Void)-> some View
+ public func makeAddUsersView(options: AddUsersOptions,onUserTap: @escaping @MainActor (ChatUser) -> Void)-> some View
- public class PhotoAssetLoader: NSObject, ObservableObject
+ @MainActor public class PhotoAssetLoader: NSObject, ObservableObject
- public struct ChannelSelectionInfo: Identifiable
+ public struct ChannelSelectionInfo: Identifiable, Sendable
- public struct MessageActionInfo
+ public struct MessageActionInfo: Sendable
open class WaveformView: UIView
- public struct Content: Equatable
+ public struct Content: Equatable, Sendable
- public protocol CommandHandler
+ @MainActor public protocol CommandHandler
public struct AppearanceKey: EnvironmentKey
- public static let defaultValue: Appearance
+ public static var defaultValue: Appearance
- public struct InjectedChannelInfo
+ public struct InjectedChannelInfo: Sendable
extension CommandHandler
- public func executeOnMessageSent(composerCommand: ComposerCommand,completion: @escaping (Error?) -> Void)
+ public func executeOnMessageSent(composerCommand: ComposerCommand,completion: @escaping @MainActor (Error?) -> Void)
- public struct AudioRecordingInfo: Equatable
+ public struct AudioRecordingInfo: Equatable, Sendable
public struct AttachmentPickerView: View
- public init(viewFactory: Factory,selectedPickerState: Binding<AttachmentPickerState>,filePickerShown: Binding<Bool>,cameraPickerShown: Binding<Bool>,addedFileURLs: Binding<[URL]>,onPickerStateChange: @escaping (AttachmentPickerState) -> Void,photoLibraryAssets: PHFetchResult<PHAsset>? = nil,onAssetTap: @escaping (AddedAsset) -> Void,onCustomAttachmentTap: @escaping (CustomAttachment) -> Void,isAssetSelected: @escaping (String) -> Bool,addedCustomAttachments: [CustomAttachment],cameraImageAdded: @escaping (AddedAsset) -> Void,askForAssetsAccessPermissions: @escaping () -> Void,isDisplayed: Bool,height: CGFloat)
+ public init(viewFactory: Factory,selectedPickerState: Binding<AttachmentPickerState>,filePickerShown: Binding<Bool>,cameraPickerShown: Binding<Bool>,addedFileURLs: Binding<[URL]>,onPickerStateChange: @escaping @MainActor (AttachmentPickerState) -> Void,photoLibraryAssets: PHFetchResult<PHAsset>? = nil,onAssetTap: @escaping @MainActor (AddedAsset) -> Void,onCustomAttachmentTap: @escaping @MainActor (CustomAttachment) -> Void,isAssetSelected: @escaping @MainActor (String) -> Bool,addedCustomAttachments: [CustomAttachment],cameraImageAdded: @escaping @MainActor (AddedAsset) -> Void,askForAssetsAccessPermissions: @escaping () -> Void,isDisplayed: Bool,height: CGFloat)
- open class MessageActionsViewModel: ObservableObject
+ @MainActor open class MessageActionsViewModel: ObservableObject
- open class ChannelHeaderLoader: ObservableObject
+ @MainActor open class ChannelHeaderLoader: ObservableObject
public struct MessageAction: Identifiable, Equatable
- public let action: () -> Void
+ public let action: @MainActor () -> Void
- public init(id: String = UUID().uuidString,title: String,iconName: String,action: @escaping () -> Void,confirmationPopup: ConfirmationPopup?,isDestructive: Bool)
+ public init(id: String = UUID().uuidString,title: String,iconName: String,action: @escaping @MainActor () -> Void,confirmationPopup: ConfirmationPopup?,isDestructive: Bool)
- public struct Fonts
+ @MainActor public struct Fonts
- public struct PollsConfig
+ public struct PollsConfig: Sendable
- public class ChannelAvatarsMerger: ChannelAvatarsMerging
+ public final class ChannelAvatarsMerger: ChannelAvatarsMerging
- public func createMergedAvatar(from avatars: [UIImage])-> UIImage?
+ public func createMergedAvatar(from avatars: [UIImage],options: ChannelAvatarsMergerOptions)-> UIImage?
- public struct TypingSuggestion
+ public struct TypingSuggestion: Sendable
public struct StreamChatError: Error
- public let additionalInfo: [String: Any]?
+ public nonisolated let additionalInfo: [String: Any]?
public struct MessageDisplayOptions
- public let messageLinkDisplayResolver: (ChatMessage) -> [NSAttributedString.Key: Any]
+ public let messageLinkDisplayResolver: @MainActor (ChatMessage) -> [NSAttributedString.Key: Any]
- public static var defaultLinkDisplay: (ChatMessage) -> [NSAttributedString.Key: Any]
+ public static var defaultLinkDisplay: @MainActor (ChatMessage) -> [NSAttributedString.Key: Any]
- 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
+ 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 @MainActor (ChatMessage) -> [NSAttributedString.Key: Any] = MessageDisplayOptions
public struct ComposerInputView: View, KeyboardReadable
- public init(factory: Factory,text: Binding<String>,selectedRangeLocation: Binding<Int>,command: Binding<ComposerCommand?>,addedAssets: [AddedAsset],addedFileURLs: [URL],addedCustomAttachments: [CustomAttachment],quotedMessage: Binding<ChatMessage?>,maxMessageLength: Int? = nil,cooldownDuration: Int,onCustomAttachmentTap: @escaping (CustomAttachment) -> Void,removeAttachmentWithId: @escaping (String) -> Void)
+ public init(factory: Factory,text: Binding<String>,selectedRangeLocation: Binding<Int>,command: Binding<ComposerCommand?>,addedAssets: [AddedAsset],addedFileURLs: [URL],addedCustomAttachments: [CustomAttachment],quotedMessage: Binding<ChatMessage?>,maxMessageLength: Int? = nil,cooldownDuration: Int,onCustomAttachmentTap: @escaping @MainActor (CustomAttachment) -> Void,removeAttachmentWithId: @escaping (String) -> Void)
- public class Images
+ @MainActor public class Images
- public struct CustomAttachment: Identifiable, Equatable
+ public struct CustomAttachment: Identifiable, Equatable, Sendable
- public struct PaddingsConfig
+ public struct PaddingsConfig: Sendable
- public protocol MarkdownFormatter
+ @MainActor public protocol MarkdownFormatter
- public class PollAttachmentViewModel: ObservableObject, PollControllerDelegate
+ @MainActor public class PollAttachmentViewModel: ObservableObject, PollControllerDelegate
extension ChannelAction
- public static func defaultActions(for channel: ChatChannel,chatClient: ChatClient,onDismiss: @escaping () -> Void,onError: @escaping (Error) -> Void)-> [ChannelAction]
+ @MainActor public static func defaultActions(for channel: ChatChannel,chatClient: ChatClient,onDismiss: @escaping @MainActor () -> Void,onError: @escaping @MainActor (Error) -> Void)-> [ChannelAction]
- open class MessageComposerViewModel: ObservableObject
+ @MainActor open class MessageComposerViewModel: ObservableObject
- open func sendMessage(quotedMessage: ChatMessage?,editedMessage: ChatMessage?,isSilent: Bool = false,skipPush: Bool = false,skipEnrichUrl: Bool = false,extraData: [String: RawJSON] = [:],completion: @escaping () -> Void)
+ open func sendMessage(quotedMessage: ChatMessage?,editedMessage: ChatMessage?,isSilent: Bool = false,skipPush: Bool = false,skipEnrichUrl: Bool = false,extraData: [String: RawJSON] = [:],completion: @escaping @MainActor () -> Void)
public final class DefaultVideoPreviewLoader: VideoPreviewLoader
- public func loadPreviewForVideo(at url: URL,completion: @escaping (Result<UIImage, Error>) -> Void)
+ public func loadPreviewForVideo(at url: URL,completion: @escaping @MainActor (Result<UIImage, Error>) -> Void)
public struct ChannelList: View
- public init(factory: Factory,channels: LazyCachedMapCollection<ChatChannel>,selectedChannel: Binding<ChannelSelectionInfo?>,swipedChannelId: Binding<String?>,scrolledChannelId: Binding<String?> = .constant(nil),scrollable: Bool = true,onlineIndicatorShown: ((ChatChannel) -> Bool)? = nil,imageLoader: ((ChatChannel) -> UIImage)? = nil,onItemTap: @escaping (ChatChannel) -> Void,onItemAppear: @escaping (Int) -> Void,channelNaming: ((ChatChannel) -> String)? = nil,channelDestination: @escaping (ChannelSelectionInfo) -> Factory.ChannelDestination,trailingSwipeRightButtonTapped: @escaping (ChatChannel) -> Void = { _ in },trailingSwipeLeftButtonTapped: @escaping (ChatChannel) -> Void = { _ in },leadingSwipeButtonTapped: @escaping (ChatChannel) -> Void = { _ in })
+ public init(factory: Factory,channels: LazyCachedMapCollection<ChatChannel>,selectedChannel: Binding<ChannelSelectionInfo?>,swipedChannelId: Binding<String?>,scrolledChannelId: Binding<String?> = .constant(nil),scrollable: Bool = true,onlineIndicatorShown: (@MainActor (ChatChannel) -> Bool)? = nil,imageLoader: (@MainActor (ChatChannel) -> UIImage)? = nil,onItemTap: @escaping @MainActor (ChatChannel) -> Void,onItemAppear: @escaping @MainActor (Int) -> Void,channelNaming: (@MainActor (ChatChannel) -> String)? = nil,channelDestination: @escaping @MainActor (ChannelSelectionInfo) -> Factory.ChannelDestination,trailingSwipeRightButtonTapped: @escaping @MainActor (ChatChannel) -> Void = { _ in },trailingSwipeLeftButtonTapped: @escaping @MainActor (ChatChannel) -> Void = { _ in },leadingSwipeButtonTapped: @escaping @MainActor (ChatChannel) -> Void = { _ in })
public struct ChatChannelListView: View
- public init(viewFactory: Factory = DefaultViewFactory.shared,viewModel: ChatChannelListViewModel? = nil,channelListController: ChatChannelListController? = nil,title: String = "Stream Chat",onItemTap: ((ChatChannel) -> Void)? = nil,selectedChannelId: String? = nil,handleTabBarVisibility: Bool = true,embedInNavigationView: Bool = true,searchType: ChannelListSearchType = .messages)
+ public init(viewFactory: Factory = DefaultViewFactory.shared,viewModel: ChatChannelListViewModel? = nil,channelListController: ChatChannelListController? = nil,title: String = "Stream Chat",onItemTap: (@MainActor (ChatChannel) -> Void)? = nil,selectedChannelId: String? = nil,handleTabBarVisibility: Bool = true,embedInNavigationView: Bool = true,searchType: ChannelListSearchType = .messages)
- public protocol ChannelAvatarsMerging
+ public protocol ChannelAvatarsMerging: Sendable
- open class ChatThreadListViewModel: ObservableObject, ChatThreadListControllerDelegate, EventsControllerDelegate
+ @MainActor open class ChatThreadListViewModel: ObservableObject, ChatThreadListControllerDelegate, EventsControllerDelegate
public struct ComposerConfig
- public static var defaultAttachmentPayloadConverter: (ChatMessage) -> [AnyAttachmentPayload]
+ public nonisolated static var defaultAttachmentPayloadConverter: (ChatMessage) -> [AnyAttachmentPayload]
- public struct ChannelItemMutedLayoutStyle: Hashable
+ public struct ChannelItemMutedLayoutStyle: Hashable, Sendable
- public static var `default`: ChannelItemMutedLayoutStyle
+ public static let `default`: ChannelItemMutedLayoutStyle
- public static var topRightCorner: ChannelItemMutedLayoutStyle
+ public static let topRightCorner: ChannelItemMutedLayoutStyle
- public static var afterChannelName: ChannelItemMutedLayoutStyle
+ public static let afterChannelName: ChannelItemMutedLayoutStyle
- public struct ChannelListSearchType: Equatable
+ public struct ChannelListSearchType: Equatable, Sendable
- public static var channels
+ public static let channels
- public static var messages
+ public static let messages
- public struct AddedAsset: Identifiable, Equatable
+ public struct AddedAsset: Identifiable, Equatable, Sendable
open class StreamImageCDN: ImageCDN
- public static var streamCDNURL
+ public static let streamCDNURL
- open class ReactionsOverlayViewModel: ObservableObject, ChatMessageControllerDelegate
+ @MainActor open class ReactionsOverlayViewModel: ObservableObject, ChatMessageControllerDelegate
- public class ViewModelsFactory
+ @MainActor public class ViewModelsFactory
- public class Utils
+ @MainActor public class Utils
- public lazy var audioSessionFeedbackGenerator: AudioSessionFeedbackGenerator
+ @MainActor public lazy var audioSessionFeedbackGenerator: AudioSessionFeedbackGenerator
- public struct PollsEntryConfig
+ public struct PollsEntryConfig: Sendable
- public struct ChatThreadListItemViewModel
+ @MainActor public struct ChatThreadListItemViewModel
- public protocol ImageMerging
+ public protocol ImageMerging: Sendable
public struct ChannelsLazyVStack: View
- public init(factory: Factory,channels: LazyCachedMapCollection<ChatChannel>,selectedChannel: Binding<ChannelSelectionInfo?>,swipedChannelId: Binding<String?>,onlineIndicatorShown: @escaping (ChatChannel) -> Bool,imageLoader: @escaping (ChatChannel) -> UIImage,onItemTap: @escaping (ChatChannel) -> Void,onItemAppear: @escaping (Int) -> Void,channelNaming: @escaping (ChatChannel) -> String,channelDestination: @escaping (ChannelSelectionInfo) -> Factory.ChannelDestination,trailingSwipeRightButtonTapped: @escaping (ChatChannel) -> Void,trailingSwipeLeftButtonTapped: @escaping (ChatChannel) -> Void,leadingSwipeButtonTapped: @escaping (ChatChannel) -> Void)
+ public init(factory: Factory,channels: LazyCachedMapCollection<ChatChannel>,selectedChannel: Binding<ChannelSelectionInfo?>,swipedChannelId: Binding<String?>,onlineIndicatorShown: @escaping @MainActor (ChatChannel) -> Bool,imageLoader: @escaping @MainActor (ChatChannel) -> UIImage,onItemTap: @escaping @MainActor (ChatChannel) -> Void,onItemAppear: @escaping @MainActor (Int) -> Void,channelNaming: @escaping @MainActor (ChatChannel) -> String,channelDestination: @escaping @MainActor (ChannelSelectionInfo) -> Factory.ChannelDestination,trailingSwipeRightButtonTapped: @escaping @MainActor (ChatChannel) -> Void,trailingSwipeLeftButtonTapped: @escaping @MainActor (ChatChannel) -> Void,leadingSwipeButtonTapped: @escaping @MainActor (ChatChannel) -> Void)
- open class MessagePreviewFormatter
+ @MainActor open class MessagePreviewFormatter
- open class ChatChannelInfoViewModel: ObservableObject, ChatChannelControllerDelegate
+ @MainActor open class ChatChannelInfoViewModel: ObservableObject, ChatChannelControllerDelegate
- public func leaveConversationTapped(completion: @escaping () -> Void)
+ public func leaveConversationTapped(completion: @escaping @MainActor () -> Void)
- public struct ConfirmationPopup
+ public struct ConfirmationPopup: Sendable
- public enum StreamChatErrorCode: Int
+ public enum StreamChatErrorCode: Int, Sendable
- public protocol VideoPreviewLoader: AnyObject
+ @MainActor public protocol VideoPreviewLoader: AnyObject
- public protocol ViewFactory: AnyObject
+ @MainActor public protocol ViewFactory: AnyObject
- public class StreamChat
+ @MainActor public class StreamChat
public struct MediaItem: Identifiable
- public var mediaAttachment: MediaAttachment?
+ @MainActor public var mediaAttachment: MediaAttachment?
- public struct AddedVoiceRecording: Identifiable, Equatable
+ public struct AddedVoiceRecording: Identifiable, Equatable, Sendable
- public protocol SnapshotCreator
+ @MainActor public protocol SnapshotCreator
- open class NukeImageProcessor: ImageProcessor
+ open class NukeImageProcessor: ImageProcessor, @unchecked Sendable
public class UnmuteCommandHandler: TwoStepMentionCommand
- override public func executeOnMessageSent(composerCommand: ComposerCommand,completion: @escaping (Error?) -> Void)
+ override public func executeOnMessageSent(composerCommand: ComposerCommand,completion: @escaping @MainActor (Error?) -> Void)
- public struct InjectedValues
+ @MainActor public struct InjectedValues
public class MuteCommandHandler: TwoStepMentionCommand
- override public func executeOnMessageSent(composerCommand: ComposerCommand,completion: @escaping (Error?) -> Void)
+ override public func executeOnMessageSent(composerCommand: ComposerCommand,completion: @escaping @MainActor (Error?) -> Void)
public struct SearchResultsView: View
- public init(factory: Factory,selectedChannel: Binding<ChannelSelectionInfo?>,searchResults: [ChannelSelectionInfo],loadingSearchResults: Bool,onlineIndicatorShown: @escaping (ChatChannel) -> Bool,channelNaming: @escaping (ChatChannel) -> String,imageLoader: @escaping (ChatChannel) -> UIImage,onSearchResultTap: @escaping (ChannelSelectionInfo) -> Void,onItemAppear: @escaping (Int) -> Void)
+ public init(factory: Factory,selectedChannel: Binding<ChannelSelectionInfo?>,searchResults: [ChannelSelectionInfo],loadingSearchResults: Bool,onlineIndicatorShown: @escaping @MainActor (ChatChannel) -> Bool,channelNaming: @escaping @MainActor (ChatChannel) -> String,imageLoader: @escaping @MainActor (ChatChannel) -> UIImage,onSearchResultTap: @escaping @MainActor (ChannelSelectionInfo) -> Void,onItemAppear: @escaping @MainActor (Int) -> Void)
- public protocol InjectionKey
+ @MainActor public protocol InjectionKey
- public class PinnedMessagesViewModel: ObservableObject
+ @MainActor public class PinnedMessagesViewModel: ObservableObject
- open class DefaultImageMerger: ImageMerging
+ open class DefaultImageMerger: ImageMerging, @unchecked Sendable
public struct ChatChannelListContentView: View
- public init(viewFactory: Factory,viewModel: ChatChannelListViewModel,onItemTap: ((ChatChannel) -> Void)? = nil)
+ public init(viewFactory: Factory,viewModel: ChatChannelListViewModel,onItemTap: (@MainActor (ChatChannel) -> Void)? = nil)
open class TwoStepMentionCommand: CommandHandler
- open func executeOnMessageSent(composerCommand: ComposerCommand,completion: @escaping (Error?) -> Void)
+ open func executeOnMessageSent(composerCommand: ComposerCommand,completion: @escaping @MainActor (Error?) -> Void)
public struct ChatChannelSwipeableListItem: View
- public init(factory: Factory,channelListItem: ChannelListItem,swipedChannelId: Binding<String?>,channel: ChatChannel,numberOfTrailingItems: Int = 2,widthOfTrailingItem: CGFloat = 60,trailingRightButtonTapped: @escaping (ChatChannel) -> Void,trailingLeftButtonTapped: @escaping (ChatChannel) -> Void,leadingSwipeButtonTapped: @escaping (ChatChannel) -> Void)
+ public init(factory: Factory,channelListItem: ChannelListItem,swipedChannelId: Binding<String?>,channel: ChatChannel,numberOfTrailingItems: Int = 2,widthOfTrailingItem: CGFloat = 60,trailingRightButtonTapped: @escaping @MainActor (ChatChannel) -> Void,trailingLeftButtonTapped: @escaping @MainActor (ChatChannel) -> Void,leadingSwipeButtonTapped: @escaping @MainActor (ChatChannel) -> Void)
public class CommandsHandler: CommandHandler
- public func executeOnMessageSent(composerCommand: ComposerCommand,completion: @escaping (Error?) -> Void)
+ public func executeOnMessageSent(composerCommand: ComposerCommand,completion: @escaping @MainActor (Error?) -> Void)
- open class MessageViewModel: ObservableObject
+ @MainActor open class MessageViewModel: ObservableObject
- public struct ColorPalette
+ @MainActor public struct ColorPalette
open class NukeImageLoader: ImageLoading
- open func loadImage(using urlRequest: URLRequest,cachingKey: String?,completion: @escaping ((Result<UIImage, Error>) -> Void))
+ open func loadImage(using urlRequest: URLRequest,cachingKey: String?,completion: @escaping @MainActor (Result<UIImage, Error>) -> Void)
- open func loadImages(from urls: [URL],placeholders: [UIImage],loadThumbnails: Bool,thumbnailSize: CGSize,imageCDN: ImageCDN,completion: @escaping (([UIImage]) -> Void))
+ open func loadImages(from urls: [URL],placeholders: [UIImage],loadThumbnails: Bool,thumbnailSize: CGSize,imageCDN: ImageCDN,completion: @escaping @MainActor ([UIImage]) -> Void)
- open func loadImage(url: URL?,imageCDN: ImageCDN,resize: Bool = true,preferredSize: CGSize? = nil,completion: @escaping ((Result<UIImage, Error>) -> Void))
+ open func loadImage(url: URL?,imageCDN: ImageCDN,resize: Bool = true,preferredSize: CGSize? = nil,completion: @escaping @MainActor (Result<UIImage, Error>) -> Void)
- public protocol ImageProcessor
+ public protocol ImageProcessor: Sendable
- open class ChatChannelViewModel: ObservableObject, MessagesDataSource
+ @MainActor open class ChatChannelViewModel: ObservableObject, MessagesDataSource
public class InstantCommandsHandler: CommandHandler
- public func executeOnMessageSent(composerCommand: ComposerCommand,completion: @escaping (Error?) -> Void)
+ public func executeOnMessageSent(composerCommand: ComposerCommand,completion: @escaping @MainActor (Error?) -> Void)
- public struct ChannelAction: Identifiable
+ public struct ChannelAction: Identifiable, @unchecked Sendable
- public let action: () -> Void
+ public let action: @MainActor () -> Void
- public init(title: String,iconName: String,action: @escaping () -> Void,confirmationPopup: ConfirmationPopup?,isDestructive: Bool)
+ public init(title: String,iconName: String,action: @escaping @MainActor () -> Void,confirmationPopup: ConfirmationPopup?,isDestructive: Bool) |
/// Provider for custom localization which is dependent on App Bundle. | ||
nonisolated(unsafe) | ||
public static var localizationProvider: @Sendable(_ key: String, _ table: String) -> String = { key, table in | ||
public nonisolated(unsafe) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is the nonisolated(unsafe) still needed here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed it, but internally we will have StreamConcurrency.onMain
call for avoiding making too much MainActor (L10n is used so many places and it was hard to handle it in UI-tests)
/// Provides the default value of the `Appearance` class. | ||
public struct AppearanceKey: EnvironmentKey { | ||
public static var defaultValue: Appearance { Appearance() } | ||
public static var defaultValue: Appearance { StreamConcurrency.onMain { Appearance() } } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can't we make the AppearanceKey
struct main actor instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only when we bump to Swift 6.2. Issue here is that EnvironmentKey protocol is nonisolated so I can't make this MainActor. Swift 6.2 allows writing public struct AppearanceKey: @MainActor EnvironmentKey
(especially for solving issues like that)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For now we need to live with this.
Sources/StreamChatSwiftUI/ChatChannel/ChatChannelViewModel.swift
Outdated
Show resolved
Hide resolved
Sources/StreamChatSwiftUI/ChatChannel/MessageList/ImageAttachmentView.swift
Outdated
Show resolved
Hide resolved
Sources/StreamChatSwiftUI/ChatChannelList/ChannelAvatarsMerger.swift
Outdated
Show resolved
Hide resolved
Sources/StreamChatSwiftUI/ChatChannelList/ChannelAvatarsMerger.swift
Outdated
Show resolved
Hide resolved
Sources/StreamChatSwiftUI/Utils/Common/NukeImageProcessor.swift
Outdated
Show resolved
Hide resolved
5a93672
to
cb562f5
Compare
c54925d
to
fa6eca0
Compare
fa6eca0
to
d02596d
Compare
7a033b2
to
398cf19
Compare
|
🔗 Issue Links
Resolves: https://linear.app/stream/issue/IOS-1171
🎯 Goal
Use MainActor in StreamChat, Images, Fonts, Appearance, Utils
📝 Summary
🛠 Implementation
🎨 Showcase
🧪 Manual Testing Notes
☑️ Contributor Checklist
docs-content
repo