Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the
β¨ Finishing touchesπ§ͺ Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Generated by π« Danger |
Co-authored-by: Stream Bot <ci@getstream.io>
nuno-vieira
left a comment
There was a problem hiding this comment.
Looks good overall, just a couple of comments π
| private var commandItems: [CommandItem] { | ||
| let commandSymbol = utils.commandsConfig.instantCommandsSymbol | ||
| return [ | ||
| CommandItem( | ||
| id: "\(commandSymbol)giphy", | ||
| displayInfo: CommandDisplayInfo( | ||
| displayName: L10n.Composer.Commands.giphy, | ||
| icon: images.commandGiphy, | ||
| format: "\(commandSymbol)giphy [\(L10n.Composer.Commands.Format.text)]", | ||
| isInstant: true | ||
| ), | ||
| replacesMessageSent: false, | ||
| usesTintedIcon: false | ||
| ), | ||
| CommandItem( | ||
| id: "\(commandSymbol)mute", | ||
| displayInfo: CommandDisplayInfo( | ||
| displayName: L10n.Composer.Commands.mute, | ||
| icon: UIImage(systemName: "speaker.slash") ?? images.commandMute, | ||
| format: "\(commandSymbol)mute [\(L10n.Composer.Commands.Format.username)]", | ||
| isInstant: true | ||
| ), | ||
| replacesMessageSent: true, | ||
| usesTintedIcon: true | ||
| ), | ||
| CommandItem( | ||
| id: "\(commandSymbol)unmute", | ||
| displayInfo: CommandDisplayInfo( | ||
| displayName: L10n.Composer.Commands.unmute, | ||
| icon: UIImage(systemName: "speaker.wave.1") ?? images.commandUnmute, | ||
| format: "\(commandSymbol)unmute [\(L10n.Composer.Commands.Format.username)]", | ||
| isInstant: true | ||
| ), | ||
| replacesMessageSent: true, | ||
| usesTintedIcon: true | ||
| ) | ||
| ] | ||
| } |
There was a problem hiding this comment.
The customer won't be able to easily change this for something else. It would be nice if this came from a View Model or something that can be overridden. It is also not using the channel config commands and capabilities
There was a problem hiding this comment.
updated, it now uses the same config from the composer vm
| icon: UIImage(systemName: "speaker.slash") ?? images.commandMute, | ||
| format: "\(commandSymbol)mute [\(L10n.Composer.Commands.Format.username)]", | ||
| isInstant: true | ||
| ), | ||
| replacesMessageSent: true, | ||
| usesTintedIcon: true | ||
| ), | ||
| CommandItem( | ||
| id: "\(commandSymbol)unmute", | ||
| displayInfo: CommandDisplayInfo( | ||
| displayName: L10n.Composer.Commands.unmute, | ||
| icon: UIImage(systemName: "speaker.wave.1") ?? images.commandUnmute, |
There was a problem hiding this comment.
These 2 images are hard-coded and not coming from images config
| private struct CommandItem: Identifiable { | ||
| let id: String | ||
| let displayInfo: CommandDisplayInfo | ||
| let replacesMessageSent: Bool | ||
| let usesTintedIcon: Bool | ||
| } |
There was a problem hiding this comment.
Any reason why this is private?
There was a problem hiding this comment.
not really, updated it
β¦into commands-attachment-picker
SDK Size
|
StreamChatSwiftUI XCSize
Show 14 more objects
|
Public Interface+ public struct AttachmentCommandsPickerView: View
+
+ public var body: some View
+
+
+ public init(instantCommands: [CommandHandler] = [],onCommandSelected: @escaping @MainActor (ComposerCommand) -> Void)
+ public final class AttachmentCommandsPickerViewOptions: Sendable
+
+ public let instantCommands: [CommandHandler]
+ public let onCommandSelected: @MainActor (ComposerCommand) -> Void
+
+
+ public init(instantCommands: [CommandHandler] = [],onCommandSelected: @escaping @MainActor (ComposerCommand) -> Void)
public class InstantCommandsHandler: CommandHandler
-
+ public let commands: [CommandHandler]
-
+
- public init(commands: [CommandHandler],symbol: String = "/",id: String = "instantCommands")
+
-
+ public init(commands: [CommandHandler],symbol: String = "/",id: String = "instantCommands")
-
+
- public func canHandleCommand(in text: String,caretLocation: Int)-> ComposerCommand?
+
- public func commandHandler(for command: ComposerCommand)-> CommandHandler?
+ public func canHandleCommand(in text: String,caretLocation: Int)-> ComposerCommand?
- public func showSuggestions(for command: ComposerCommand)-> Future<SuggestionInfo, Error>
+ public func commandHandler(for command: ComposerCommand)-> CommandHandler?
- public func handleCommand(for text: Binding<String>,selectedRangeLocation: Binding<Int>,command: Binding<ComposerCommand?>,extraData: [String: Any])
+ public func showSuggestions(for command: ComposerCommand)-> Future<SuggestionInfo, Error>
- public func executeOnMessageSent(composerCommand: ComposerCommand,completion: @escaping @MainActor (Error?) -> Void)
+ public func handleCommand(for text: Binding<String>,selectedRangeLocation: Binding<Int>,command: Binding<ComposerCommand?>,extraData: [String: Any])
- public func canBeExecuted(composerCommand: ComposerCommand)-> Bool
+ public func executeOnMessageSent(composerCommand: ComposerCommand,completion: @escaping @MainActor (Error?) -> Void)
+ public func canBeExecuted(composerCommand: ComposerCommand)-> Bool
public struct AttachmentPickerView: View
- 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,selectedAssetIds: [String]? = nil,channelController: ChatChannelController,messageController: ChatMessageController?,canSendPoll: Bool)
+ 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,selectedAssetIds: [String]? = nil,channelController: ChatChannelController,messageController: ChatMessageController?,canSendPoll: Bool,instantCommands: [CommandHandler],onCommandSelected: @escaping @MainActor (ComposerCommand) -> Void)
@MainActor open class MessageComposerViewModel: ObservableObject
- public var mentionedUsers
+ public var instantCommands: [CommandHandler]
- public var isSendMessageEnabled: Bool
+ public var mentionedUsers
- public var sendButtonEnabled: Bool
+ public var isSendMessageEnabled: Bool
- public var sendInChannelShown: Bool
+ public var sendButtonEnabled: Bool
- public var isDirectChannel: Bool
+ public var sendInChannelShown: Bool
- public var showCommandsOverlay: Bool
+ public var isDirectChannel: Bool
- public var inputComposerShouldScroll: Bool
+ public var showCommandsOverlay: Bool
-
+ public var inputComposerShouldScroll: Bool
-
+
- public init(channelController: ChatChannelController,messageController: ChatMessageController?,eventsController: EventsController? = nil,quotedMessage: Binding<ChatMessage?>? = nil)
+
-
+ public init(channelController: ChatChannelController,messageController: ChatMessageController?,eventsController: EventsController? = nil,quotedMessage: Binding<ChatMessage?>? = nil)
-
+
- public func fillEditedMessage(_ editedMessage: ChatMessage?)
+
- public func fillDraftMessage()
+ public func fillEditedMessage(_ editedMessage: ChatMessage?)
- public func updateDraftMessage(quotedMessage: ChatMessage?,isSilent: Bool = false,extraData: [String: RawJSON] = [:])
+ public func fillDraftMessage()
- public func deleteDraftMessage()
+ public func updateDraftMessage(quotedMessage: ChatMessage?,isSilent: Bool = false,extraData: [String: RawJSON] = [:])
- open func sendMessage(quotedMessage: ChatMessage?,editedMessage: ChatMessage?,isSilent: Bool = false,skipPush: Bool = false,skipEnrichUrl: Bool = false,extraData: [String: RawJSON] = [:],completion: @escaping @MainActor () -> Void)
+ public func deleteDraftMessage()
- public func change(pickerState: AttachmentPickerState)
+ open func sendMessage(quotedMessage: ChatMessage?,editedMessage: ChatMessage?,isSilent: Bool = false,skipPush: Bool = false,skipEnrichUrl: Bool = false,extraData: [String: RawJSON] = [:],completion: @escaping @MainActor () -> Void)
- public func imageTapped(_ addedAsset: AddedAsset)
+ public func change(pickerState: AttachmentPickerState)
- public func imagePasted(_ image: UIImage)
+ public func imageTapped(_ addedAsset: AddedAsset)
- public func removeAttachment(with id: String)
+ public func imagePasted(_ image: UIImage)
- public func cameraImageAdded(_ image: AddedAsset)
+ public func removeAttachment(with id: String)
- public func isImageSelected(with id: String)-> Bool
+ public func cameraImageAdded(_ image: AddedAsset)
- public func customAttachmentTapped(_ attachment: CustomAttachment)
+ public func isImageSelected(with id: String)-> Bool
- public func isCustomAttachmentSelected(_ attachment: CustomAttachment)-> Bool
+ public func customAttachmentTapped(_ attachment: CustomAttachment)
- public func askForPhotosPermission()
+ public func isCustomAttachmentSelected(_ attachment: CustomAttachment)-> Bool
- public func handleCommand(for text: Binding<String>,selectedRangeLocation: Binding<Int>,command: Binding<ComposerCommand?>,extraData: [String: Any])
+ public func askForPhotosPermission()
- open func convertAddedAssetsToPayloads()throws -> [AnyAttachmentPayload]
+ public func handleCommand(for text: Binding<String>,selectedRangeLocation: Binding<Int>,command: Binding<ComposerCommand?>,extraData: [String: Any])
- public func checkForMentionedUsers(commandId: String?,extraData: [String: Any])
+ open func convertAddedAssetsToPayloads()throws -> [AnyAttachmentPayload]
- public func clearRemovedMentions()
+ public func checkForMentionedUsers(commandId: String?,extraData: [String: Any])
- public func clearInputData()
+ public func clearRemovedMentions()
- public func checkChannelCooldown()
+ public func clearInputData()
- public func updateAddedAssets(_ assets: [AddedAsset])
+ public func checkChannelCooldown()
+ public func updateAddedAssets(_ assets: [AddedAsset])
public final class AttachmentPickerViewOptions: Sendable
-
+ public let instantCommands: [CommandHandler]
-
+ public let onCommandSelected: @MainActor (ComposerCommand) -> Void
- public init(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,selectedAssetIds: [String]? = nil,channelController: ChatChannelController,messageController: ChatMessageController?,canSendPoll: Bool)
+
+
+ public init(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,selectedAssetIds: [String]? = nil,channelController: ChatChannelController,messageController: ChatMessageController?,canSendPoll: Bool,instantCommands: [CommandHandler],onCommandSelected: @escaping @MainActor (ComposerCommand) -> Void)
public class CommandsHandler: CommandHandler
- public let id: String
+ public let commands: [CommandHandler]
- public var displayInfo: CommandDisplayInfo?
+ public let id: String
-
+ public var displayInfo: CommandDisplayInfo?
-
+
- public init(commands: [CommandHandler])
+
-
+ public init(commands: [CommandHandler])
-
+
- public func canHandleCommand(in text: String,caretLocation: Int)-> ComposerCommand?
+
- public func commandHandler(for command: ComposerCommand)-> CommandHandler?
+ public func canHandleCommand(in text: String,caretLocation: Int)-> ComposerCommand?
- public func showSuggestions(for command: ComposerCommand)-> Future<SuggestionInfo, Error>
+ public func commandHandler(for command: ComposerCommand)-> CommandHandler?
- public func handleCommand(for text: Binding<String>,selectedRangeLocation: Binding<Int>,command: Binding<ComposerCommand?>,extraData: [String: Any])
+ public func showSuggestions(for command: ComposerCommand)-> Future<SuggestionInfo, Error>
- public func executeOnMessageSent(composerCommand: ComposerCommand,completion: @escaping @MainActor (Error?) -> Void)
+ public func handleCommand(for text: Binding<String>,selectedRangeLocation: Binding<Int>,command: Binding<ComposerCommand?>,extraData: [String: Any])
- public func canBeExecuted(composerCommand: ComposerCommand)-> Bool
+ public func executeOnMessageSent(composerCommand: ComposerCommand,completion: @escaping @MainActor (Error?) -> Void)
+ public func canBeExecuted(composerCommand: ComposerCommand)-> Bool
public enum AttachmentPickerState: Sendable
- case custom
+ case commands
+ case custom
extension ViewFactory
- public func makeVoiceRecordingView(options: VoiceRecordingViewOptions)-> some View
+ public func makeAttachmentCommandsPickerView(options: AttachmentCommandsPickerViewOptions)-> some View
- public func makeCustomAttachmentView(options: CustomComposerAttachmentViewOptions)-> some View
+ public func makeVoiceRecordingView(options: VoiceRecordingViewOptions)-> some View
- public func makeCustomAttachmentPreviewView(options: CustomAttachmentPreviewViewOptions)-> some View
+ public func makeCustomAttachmentView(options: CustomComposerAttachmentViewOptions)-> some View
- public func makeAttachmentSourcePickerView(options: AttachmentSourcePickerViewOptions)-> some View
+ public func makeCustomAttachmentPreviewView(options: CustomAttachmentPreviewViewOptions)-> some View
- public func makePhotoAttachmentPickerView(options: PhotoAttachmentPickerViewOptions)-> some View
+ public func makeAttachmentSourcePickerView(options: AttachmentSourcePickerViewOptions)-> some View
- public func makeFilePickerView(options: FilePickerViewOptions)-> some View
+ public func makePhotoAttachmentPickerView(options: PhotoAttachmentPickerViewOptions)-> some View
- public func makeCameraPickerView(options: CameraPickerViewOptions)-> some View
+ public func makeFilePickerView(options: FilePickerViewOptions)-> some View
- public func makeAssetsAccessPermissionView(options: AssetsAccessPermissionViewOptions)-> some View
+ public func makeCameraPickerView(options: CameraPickerViewOptions)-> some View
- public func makeSendInChannelView(options: SendInChannelViewOptions)-> some View
+ public func makeAssetsAccessPermissionView(options: AssetsAccessPermissionViewOptions)-> some View
- public func makeMessageActionsView(options: MessageActionsViewOptions)-> some View
+ public func makeSendInChannelView(options: SendInChannelViewOptions)-> some View
- public func makeReactionsUsersView(options: ReactionsUsersViewOptions)-> some View
+ public func makeMessageActionsView(options: MessageActionsViewOptions)-> some View
- public func makeBottomReactionsView(options: ReactionsBottomViewOptions)-> some View
+ public func makeReactionsUsersView(options: ReactionsUsersViewOptions)-> some View
- public func makeMessageReactionView(options: MessageReactionViewOptions)-> some View
+ public func makeBottomReactionsView(options: ReactionsBottomViewOptions)-> some View
- public func makeReactionsOverlayView(options: ReactionsOverlayViewOptions)-> some View
+ public func makeMessageReactionView(options: MessageReactionViewOptions)-> some View
- public func makeReactionsContentView(options: ReactionsContentViewOptions)-> some View
+ public func makeReactionsOverlayView(options: ReactionsOverlayViewOptions)-> some View
- public func makeReactionsBackgroundView(options: ReactionsBackgroundOptions)-> some View
+ public func makeReactionsContentView(options: ReactionsContentViewOptions)-> some View
- public func makeMoreReactionsView(options: MoreReactionsViewOptions)-> some View
+ public func makeReactionsBackgroundView(options: ReactionsBackgroundOptions)-> some View
- public func makeComposerQuotedMessageView(options: ComposerQuotedMessageViewOptions)-> some View
+ public func makeMoreReactionsView(options: MoreReactionsViewOptions)-> some View
- public func makeChatQuotedMessageView(options: ChatQuotedMessageViewOptions)-> some View
+ public func makeComposerQuotedMessageView(options: ComposerQuotedMessageViewOptions)-> some View
- public func makeQuotedMessageView(options: QuotedMessageViewOptions)-> some View
+ public func makeChatQuotedMessageView(options: ChatQuotedMessageViewOptions)-> some View
- public func makeQuotedMessageAttachmentPreviewView(options: QuotedMessageAttachmentPreviewViewOptions)-> some View
+ public func makeQuotedMessageView(options: QuotedMessageViewOptions)-> some View
- public func makeCommandsContainerView(options: CommandsContainerViewOptions)-> some View
+ public func makeQuotedMessageAttachmentPreviewView(options: QuotedMessageAttachmentPreviewViewOptions)-> some View
- public func makeMessageReadIndicatorView(options: MessageReadIndicatorViewOptions)-> some View
+ public func makeCommandsContainerView(options: CommandsContainerViewOptions)-> some View
- public func makeNewMessagesIndicatorView(options: NewMessagesIndicatorViewOptions)-> some View
+ public func makeMessageReadIndicatorView(options: MessageReadIndicatorViewOptions)-> some View
- public func makeJumpToUnreadButton(options: JumpToUnreadButtonOptions)-> some View
+ public func makeNewMessagesIndicatorView(options: NewMessagesIndicatorViewOptions)-> some View
- public func makeComposerPollView(options: ComposerPollViewOptions)-> some View
+ public func makeJumpToUnreadButton(options: JumpToUnreadButtonOptions)-> some View
- public func makePollView(options: PollViewOptions)-> some View
+ public func makeComposerPollView(options: ComposerPollViewOptions)-> some View
- public func makeThreadDestination(options: ThreadDestinationOptions)-> @MainActor (ChatThread) -> ChatChannelView<Self>
+ public func makePollView(options: PollViewOptions)-> some View
- public func makeThreadListItem(options: ThreadListItemOptions<ThreadDestination>)-> some View
+ public func makeThreadDestination(options: ThreadDestinationOptions)-> @MainActor (ChatThread) -> ChatChannelView<Self>
- public func makeNoThreadsView(options: NoThreadsViewOptions)-> some View
+ public func makeThreadListItem(options: ThreadListItemOptions<ThreadDestination>)-> some View
- public func makeThreadsListErrorBannerView(options: ThreadListErrorBannerViewOptions)-> some View
+ public func makeNoThreadsView(options: NoThreadsViewOptions)-> some View
- public func makeThreadListLoadingView(options: ThreadListLoadingViewOptions)-> some View
+ public func makeThreadsListErrorBannerView(options: ThreadListErrorBannerViewOptions)-> some View
- public func makeThreadListContainerViewModifier(options: ThreadListContainerModifierOptions)-> some ViewModifier
+ public func makeThreadListLoadingView(options: ThreadListLoadingViewOptions)-> some View
- public func makeThreadListHeaderViewModifier(options: ThreadListHeaderViewModifierOptions)-> some ViewModifier
+ public func makeThreadListContainerViewModifier(options: ThreadListContainerModifierOptions)-> some ViewModifier
- public func makeThreadListHeaderView(options: ThreadListHeaderViewOptions)-> some View
+ public func makeThreadListHeaderViewModifier(options: ThreadListHeaderViewModifierOptions)-> some ViewModifier
- public func makeThreadListFooterView(options: ThreadListFooterViewOptions)-> some View
+ public func makeThreadListHeaderView(options: ThreadListHeaderViewOptions)-> some View
- public func makeThreadListBackground(options: ThreadListBackgroundOptions)-> some View
+ public func makeThreadListFooterView(options: ThreadListFooterViewOptions)-> some View
- public func makeThreadListItemBackground(options: ThreadListItemBackgroundOptions)-> some View
+ public func makeThreadListBackground(options: ThreadListBackgroundOptions)-> some View
- public func makeThreadListDividerItem(options: ThreadListDividerItemOptions)-> some View
+ public func makeThreadListItemBackground(options: ThreadListItemBackgroundOptions)-> some View
- public func makeAddUsersView(options: AddUsersViewOptions)-> some View
+ public func makeThreadListDividerItem(options: ThreadListDividerItemOptions)-> some View
- public func makeAttachmentTextView(options: AttachmentTextViewOptions)-> some View
+ public func makeAddUsersView(options: AddUsersViewOptions)-> some View
+ public func makeAttachmentTextView(options: AttachmentTextViewOptions)-> some View
- @MainActor public protocol CommandHandler
+ @MainActor public protocol CommandHandler: Sendable |
|


π Issue Links
Resolves https://linear.app/stream/issue/IOS-1398/implement-commands-attachment-picker.
π― 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.
π§ͺ Manual Testing Notes
Explain how this change can be tested manually, if applicable.
βοΈ Contributor Checklist
docs-contentrepo