diff --git a/Sources/ChatUI/ChatInChannel/MessageField/MessageField.swift b/Sources/ChatUI/ChatInChannel/MessageField/MessageField.swift index cec756a..76b3139 100644 --- a/Sources/ChatUI/ChatInChannel/MessageField/MessageField.swift +++ b/Sources/ChatUI/ChatInChannel/MessageField/MessageField.swift @@ -76,6 +76,7 @@ public struct MessageField: View { let options: [MessageOption] let showsSendButtonAlways: Bool + let characterLimit: Int? let onSend: (_ messageStyle: MessageStyle) -> () private var leftSideOptions: [MessageOption] { @@ -146,7 +147,7 @@ public struct MessageField: View { // TextField HStack(alignment: .bottom) { - MessageTextField(text: $text, height: $textFieldHeight) + MessageTextField(text: $text, height: $textFieldHeight, characterLimit: characterLimit) .frame(height: textFieldHeight < 90 ? textFieldHeight : 90) .padding(.leading, 9) .padding(.trailing, 4) @@ -206,11 +207,13 @@ public struct MessageField: View { public init( options: [MessageOption] = MessageOption.all, showsSendButtonAlways: Bool = false, + characterLimit: Int? = nil, isMenuItemPresented: Binding = .constant(false), onSend: @escaping (_ messageStyle: MessageStyle) -> () ) { self.options = options self.showsSendButtonAlways = showsSendButtonAlways + self.characterLimit = characterLimit self._isMenuItemPresented = isMenuItemPresented self.onSend = onSend } diff --git a/Sources/ChatUI/ChatInChannel/MessageField/MessageTextField.swift b/Sources/ChatUI/ChatInChannel/MessageField/MessageTextField.swift index 25971f2..ddfce41 100644 --- a/Sources/ChatUI/ChatInChannel/MessageField/MessageTextField.swift +++ b/Sources/ChatUI/ChatInChannel/MessageField/MessageTextField.swift @@ -14,6 +14,7 @@ struct MessageTextField: UIViewRepresentable { @State private var isEditing: Bool = false let placeholder: String = String.MessageField.placeholder + let characterLimit: Int? func makeUIView(context: UIViewRepresentableContext) -> UITextView { let view = UITextView() @@ -67,7 +68,7 @@ struct MessageTextField: UIViewRepresentable { } func textViewDidChange(_ textView: UITextView) { - if textView.text.count > 300 { + if let characterLimit = parent.characterLimit, textView.text.count > characterLimit { let start = textView.text.index(textView.text.startIndex, offsetBy: 0) let end = textView.text.index(textView.text.startIndex, offsetBy: 300) textView.text = String(textView.text[start..: View { let showsDate: Bool let showsProfileImage: Bool let showsReadReceiptStatus: Bool + let lineLimit: Int? @State private var isSelected: Bool = false @@ -80,7 +81,7 @@ public struct MessageRow: View { } // MARK: Message bubble - MessageView(style: message.style, isMyMessage: isMyMessage) + MessageView(style: message.style, isMyMessage: isMyMessage, lineLimit: lineLimit) .zIndex(0) .onLongPressGesture { withAnimation(.easeInOut) { @@ -147,13 +148,15 @@ public struct MessageRow: View { showsUsername: Bool = true, showsDate: Bool = true, showsProfileImage: Bool = true, - showsReadReceiptStatus: Bool = true + showsReadReceiptStatus: Bool = true, + lineLimit: Int? = nil ) { self.message = message self.showsUsername = showsUsername self.showsDate = showsDate self.showsProfileImage = showsProfileImage self.showsReadReceiptStatus = showsReadReceiptStatus + self.lineLimit = lineLimit } var formatter: DateFormatter { diff --git a/Sources/ChatUI/ChatInChannel/MessageViews/MessageView.swift b/Sources/ChatUI/ChatInChannel/MessageViews/MessageView.swift index c739eeb..b473784 100644 --- a/Sources/ChatUI/ChatInChannel/MessageViews/MessageView.swift +++ b/Sources/ChatUI/ChatInChannel/MessageViews/MessageView.swift @@ -12,6 +12,7 @@ struct MessageView: View { let style: MessageStyle let isMyMessage: Bool + let lineLimit: Int? var body: some View { switch style { @@ -19,12 +20,12 @@ struct MessageView: View { let markdown = LocalizedStringKey(text) Text(markdown) .tint(isMyMessage ? appearance.prominentLink : appearance.link) - .messageStyle(isMyMessage ? .localBody : .remoteBody) + .messageStyle(isMyMessage ? .localBody(lineLimit) : .remoteBody(lineLimit)) case .media(let mediaType): switch mediaType { case .emoji(let key): Text(key) - .messageStyle(isMyMessage ? .localBody : .remoteBody) + .messageStyle(isMyMessage ? .localBody(lineLimit) : .remoteBody(lineLimit)) case .gif(let key): GiphyStyleView(id: key) case .photo(let data): @@ -32,18 +33,18 @@ struct MessageView: View { case .video(let data): Text("\(data)") .lineLimit(5) - .messageStyle(isMyMessage ? .localBody : .remoteBody) + .messageStyle(isMyMessage ? .localBody(lineLimit) : .remoteBody(lineLimit)) case .document(let data): Text("\(data)") .lineLimit(5) - .messageStyle(isMyMessage ? .localBody : .remoteBody) + .messageStyle(isMyMessage ? .localBody(lineLimit) : .remoteBody(lineLimit)) case .contact(let contact): let markdown = """ Name: **\(contact.givenName) \(contact.familyName)** Phone: \(contact.phoneNumbers) """ Text(.init(markdown)) - .messageStyle(isMyMessage ? .localBody : .remoteBody) + .messageStyle(isMyMessage ? .localBody(lineLimit) : .remoteBody(lineLimit)) case .location(let latitude, let longitude): LocationStyleView( latitude: latitude, @@ -52,7 +53,7 @@ struct MessageView: View { } case .voice(let data): VoiceStyleView(data: data) - .messageStyle(isMyMessage ? .localBody : .remoteBody) + .messageStyle(isMyMessage ? .localBody(lineLimit) : .remoteBody(lineLimit)) } } } diff --git a/Sources/ChatUI/ViewModifiers/MessageModifier.swift b/Sources/ChatUI/ViewModifiers/MessageModifier.swift index 83a31e9..c61a2cb 100644 --- a/Sources/ChatUI/ViewModifiers/MessageModifier.swift +++ b/Sources/ChatUI/ViewModifiers/MessageModifier.swift @@ -9,17 +9,21 @@ import SwiftUI public class MessageModifier { public enum Style { - case remoteBody - case localBody + case remoteBody(_ lineLimit: Int?) + case localBody(_ lineLimit: Int?) case date case receipt case senderName case senderProfile } - public static var remoteBodyStyle = RemoteBody() + public static func remoteBodyStyle(_ lineLimit: Int?) -> RemoteBody { + RemoteBody(lineLimit: lineLimit) + } - public static var localBodyStyle = LocalBody() + public static func localBodyStyle(_ lineLimit: Int?) -> LocalBody { + LocalBody(lineLimit: lineLimit) + } public static var dateStyle = Date() @@ -32,9 +36,11 @@ public class MessageModifier { public struct RemoteBody: ViewModifier { @Environment(\.appearance) var appearance + let lineLimit: Int? + public func body(content: Content) -> some View { content - .lineLimit(10) + .lineLimit(lineLimit) .font(appearance.messageBody) .frame(minWidth: 18) /// To make the bubble to be a circle shape, when the text is too short .padding(12) @@ -47,9 +53,11 @@ public class MessageModifier { public struct LocalBody: ViewModifier { @Environment(\.appearance) var appearance + let lineLimit: Int? + public func body(content: Content) -> some View { content - .lineLimit(10) + .lineLimit(lineLimit) .font(appearance.messageBody) .frame(minWidth: 18) /// To make the bubble to be a circle shape, when the text is too short .padding(12) @@ -107,10 +115,10 @@ public class MessageModifier { extension View { public func messageStyle(_ style: MessageModifier.Style) -> some View { switch style { - case .remoteBody: - return AnyView(modifier(MessageModifier.remoteBodyStyle)) - case .localBody: - return AnyView(modifier(MessageModifier.localBodyStyle)) + case .remoteBody(let lineLimit): + return AnyView(modifier(MessageModifier.remoteBodyStyle(lineLimit))) + case .localBody(let lineLimit): + return AnyView(modifier(MessageModifier.localBodyStyle(lineLimit))) case .date: return AnyView(modifier(MessageModifier.dateStyle)) case .receipt: @@ -122,5 +130,3 @@ extension View { } } } - -