diff --git a/README.md b/README.md index 40e49cae..0cabed7d 100644 --- a/README.md +++ b/README.md @@ -208,6 +208,20 @@ ChatView(messages: viewModel.messages) { draft in When implementing your own `MessageMenuActionClosure`, write a switch statement passing through all the cases of your `MessageMenuAction`, inside each case write your own action handler, or call the default one. NOTE: not all default actions work out of the box - e.g. for `.edit` you'll still need to provide a closure to save the edited text on your BE. Please see CommentsExampleView in ChatExample project for MessageMenuActionClosure usage example. +## Configure default menu options + +By default, the menu includes all options defined in AvailableMessageMenuType(edit, reply, copy). To customize which options are shown, use setAvailableMessageMenuItems: + +```swift + +ChatView(messages: viewModel.messages) { draft in + viewModel.send(draft: draft) +} +.setAvailableMessageMenuItems([.edit, .copy]) + + +``` + ## Custom swipe actions ```swift diff --git a/Sources/ExyteChat/Views/ChatView.swift b/Sources/ExyteChat/Views/ChatView.swift index 24c3b0f4..a8707af3 100644 --- a/Sources/ExyteChat/Views/ChatView.swift +++ b/Sources/ExyteChat/Views/ChatView.swift @@ -129,6 +129,7 @@ public struct ChatView ChatView { + var view = self + view.availableMessageMenuItems = types + return view + } + func setRecorderSettings(_ settings: RecorderSettings) -> ChatView { var view = self view.recorderSettings = settings diff --git a/Sources/ExyteChat/Views/InputView/InputView.swift b/Sources/ExyteChat/Views/InputView/InputView.swift index 5eca6efa..8b5c1c51 100644 --- a/Sources/ExyteChat/Views/InputView/InputView.swift +++ b/Sources/ExyteChat/Views/InputView/InputView.swift @@ -56,6 +56,12 @@ public enum InputViewState: Sendable { } } +public enum AvailableMesssageMenuType: Sendable { + case edit + case reply + case copy +} + public enum AvailableInputType: Sendable { case text case media diff --git a/Sources/ExyteChat/Views/MessageView/MessageMenu/MessageMenu+Action.swift b/Sources/ExyteChat/Views/MessageView/MessageMenu/MessageMenu+Action.swift index c3ca8a6a..afed1f3d 100644 --- a/Sources/ExyteChat/Views/MessageView/MessageMenu/MessageMenu+Action.swift +++ b/Sources/ExyteChat/Views/MessageView/MessageMenu/MessageMenu+Action.swift @@ -9,11 +9,11 @@ public protocol MessageMenuAction: Equatable, CaseIterable { func title() -> String func icon() -> Image - static func menuItems(for message: Message) -> [Self] + static func menuItems(for message: Message, availableMessageMenuItems: [AvailableMesssageMenuType]) -> [Self] } extension MessageMenuAction { - public static func menuItems(for message: Message) -> [Self] { + public static func menuItems(for message: Message, availableMessageMenuItems: [AvailableMesssageMenuType]) -> [Self] { Self.allCases.map { $0 } } } @@ -65,11 +65,30 @@ public enum DefaultMessageMenuAction: MessageMenuAction, Sendable { .copy, .reply, .edit(saveClosure: {_ in}) ] - static public func menuItems(for message: Message) -> [DefaultMessageMenuAction] { + static public func menuItems( + for message: Message, availableMessageMenuItems: [AvailableMesssageMenuType] + ) -> [DefaultMessageMenuAction] { + + var menuItems: [DefaultMessageMenuAction] = [] if message.user.isCurrentUser { - return allCases + if availableMessageMenuItems.contains(.copy) { + menuItems.append(.copy) + } + if availableMessageMenuItems.contains(.reply) { + menuItems.append(.reply) + } + if availableMessageMenuItems.contains(.edit) { + menuItems.append(.edit(saveClosure: { _ in })) + } + return menuItems } else { - return [.copy, .reply] + if availableMessageMenuItems.contains(.copy) { + menuItems.append(.copy) + } + if availableMessageMenuItems.contains(.reply) { + menuItems.append(.reply) + } + return menuItems } } } diff --git a/Sources/ExyteChat/Views/MessageView/MessageMenu/MessageMenu.swift b/Sources/ExyteChat/Views/MessageView/MessageMenu/MessageMenu.swift index 2cd2c11a..6b2d7e8b 100644 --- a/Sources/ExyteChat/Views/MessageView/MessageMenu/MessageMenu.swift +++ b/Sources/ExyteChat/Views/MessageView/MessageMenu/MessageMenu.swift @@ -39,6 +39,8 @@ struct MessageMenu: View { /// The vertical spacing between the main three components in out VStack (ReactionSelection, Message and Menu) let verticalSpacing:CGFloat = 0 + /// The menu items to display on long press + let availableMessageMenuItems: [AvailableMesssageMenuType] /// The message whose menu we're presenting var message: Message /// The original message frame (the row / cell) @@ -506,7 +508,8 @@ struct MessageMenu: View { @ViewBuilder func menuView() -> some View { - let buttons = ActionEnum.menuItems(for: message).enumerated().map { MenuButton(id: $0, action: $1) } + let buttons = ActionEnum.menuItems(for: message, availableMessageMenuItems: availableMessageMenuItems) + .enumerated().map { MenuButton(id: $0, action: $1) } HStack { if alignment == .right { Spacer() }