From 9d6495d14a412bc14c955baee00bbb752abcf07b Mon Sep 17 00:00:00 2001 From: Aleksandrs Proskurins Date: Fri, 18 Nov 2022 17:43:03 +0200 Subject: [PATCH] Send messages on return (#325) * Send messages on return * Formating * Changelog --- .../RoomScreen/View/MessageComposer.swift | 5 +- .../View/MessageComposerTextField.swift | 69 +++++++++++++++---- changelog.d/314.feature | 1 + 3 files changed, 62 insertions(+), 13 deletions(-) create mode 100644 changelog.d/314.feature diff --git a/ElementX/Sources/Screens/RoomScreen/View/MessageComposer.swift b/ElementX/Sources/Screens/RoomScreen/View/MessageComposer.swift index c308c7976..3875fbae7 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/MessageComposer.swift +++ b/ElementX/Sources/Screens/RoomScreen/View/MessageComposer.swift @@ -34,7 +34,10 @@ struct MessageComposer: View { MessageComposerTextField(placeholder: ElementL10n.roomMessagePlaceholder, text: $text, focused: $focused, - maxHeight: 300) + maxHeight: 300, + onEnterKeyHandler: { + sendAction() + }) Button { sendAction() diff --git a/ElementX/Sources/Screens/RoomScreen/View/MessageComposerTextField.swift b/ElementX/Sources/Screens/RoomScreen/View/MessageComposerTextField.swift index 64ad4e875..8723651a1 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/MessageComposerTextField.swift +++ b/ElementX/Sources/Screens/RoomScreen/View/MessageComposerTextField.swift @@ -16,6 +16,8 @@ import SwiftUI +typealias OnEnterKeyHandler = () -> Void + struct MessageComposerTextField: View { @Binding private var text: String @Binding private var focused: Bool @@ -24,16 +26,22 @@ struct MessageComposerTextField: View { private let placeholder: String private let maxHeight: CGFloat + private let onEnterKeyHandler: OnEnterKeyHandler private var showingPlaceholder: Bool { text.isEmpty } - - init(placeholder: String, text: Binding, focused: Binding, maxHeight: CGFloat) { + + init(placeholder: String, + text: Binding, + focused: Binding, + maxHeight: CGFloat, + onEnterKeyHandler: @escaping OnEnterKeyHandler) { self.placeholder = placeholder _text = text _focused = focused self.maxHeight = maxHeight + self.onEnterKeyHandler = onEnterKeyHandler } private var placeholderColor: Color { @@ -44,7 +52,8 @@ struct MessageComposerTextField: View { UITextViewWrapper(text: $text, calculatedHeight: $dynamicHeight, focused: $focused, - maxHeight: maxHeight) + maxHeight: maxHeight, + onEnterKeyHandler: onEnterKeyHandler) .frame(minHeight: dynamicHeight, maxHeight: dynamicHeight) .background(placeholderView, alignment: .topLeading) } @@ -67,10 +76,12 @@ private struct UITextViewWrapper: UIViewRepresentable { let maxHeight: CGFloat + let onEnterKeyHandler: OnEnterKeyHandler + func makeUIView(context: UIViewRepresentableContext) -> UITextView { - let textView = UITextView() + let textView = TextViewWithKeyDetection() textView.delegate = context.coordinator - + textView.keyDelegate = context.coordinator textView.textColor = .element.primaryContent textView.isEditable = true textView.font = UIFont.preferredFont(forTextStyle: .body) @@ -80,7 +91,7 @@ private struct UITextViewWrapper: UIViewRepresentable { textView.returnKeyType = .default textView.textContainer.lineFragmentPadding = 0.0 textView.textContainerInset = .zero - textView.keyboardType = .twitter + textView.keyboardType = .default textView.setContentCompressionResistancePriority(.defaultLow, for: .horizontal) @@ -95,10 +106,10 @@ private struct UITextViewWrapper: UIViewRepresentable { // text cleared, probably because the written text is sent // reload keyboard type if textView.isFirstResponder { - textView.keyboardType = .default - textView.reloadInputViews() textView.keyboardType = .twitter textView.reloadInputViews() + textView.keyboardType = .default + textView.reloadInputViews() } } } @@ -116,7 +127,8 @@ private struct UITextViewWrapper: UIViewRepresentable { Coordinator(text: $text, height: $calculatedHeight, focused: $focused, - maxHeight: maxHeight) + maxHeight: maxHeight, + onEnterKeyHandler: onEnterKeyHandler) } fileprivate static func recalculateHeight(view: UIView, result: Binding, maxHeight: CGFloat) { @@ -131,18 +143,21 @@ private struct UITextViewWrapper: UIViewRepresentable { } } - final class Coordinator: NSObject, UITextViewDelegate { + final class Coordinator: NSObject, UITextViewDelegate, TextViewWithKeyDetectionDelegate { private var text: Binding private var calculatedHeight: Binding private var focused: Binding private let maxHeight: CGFloat - init(text: Binding, height: Binding, focused: Binding, maxHeight: CGFloat) { + private let onEnterKeyHandler: OnEnterKeyHandler + + init(text: Binding, height: Binding, focused: Binding, maxHeight: CGFloat, onEnterKeyHandler: @escaping OnEnterKeyHandler) { self.text = text calculatedHeight = height self.focused = focused self.maxHeight = maxHeight + self.onEnterKeyHandler = onEnterKeyHandler } func textViewDidChange(_ textView: UITextView) { @@ -159,6 +174,36 @@ private struct UITextViewWrapper: UIViewRepresentable { func textViewDidEndEditing(_ textView: UITextView) { focused.wrappedValue = false } + + func enterKeyWasPressed(textView: UITextView) { + onEnterKeyHandler() + } + + func shiftEnterKeyPressed(textView: UITextView) { + textView.insertText("\n") + } + } +} + +private protocol TextViewWithKeyDetectionDelegate: AnyObject { + func enterKeyWasPressed(textView: UITextView) + func shiftEnterKeyPressed(textView: UITextView) +} + +private class TextViewWithKeyDetection: UITextView { + weak var keyDelegate: TextViewWithKeyDetectionDelegate? + + override var keyCommands: [UIKeyCommand]? { + [UIKeyCommand(input: "\r", modifierFlags: .shift, action: #selector(shiftEnterKeyPressed)), + UIKeyCommand(input: "\r", modifierFlags: [], action: #selector(enterKeyPressed))] + } + + @objc func shiftEnterKeyPressed(sender: UIKeyCommand) { + keyDelegate?.shiftEnterKeyPressed(textView: self) + } + + @objc func enterKeyPressed(sender: UIKeyCommand) { + keyDelegate?.enterKeyWasPressed(textView: self) } } @@ -186,7 +231,7 @@ struct MessageComposerTextField_Previews: PreviewProvider { } var body: some View { - MessageComposerTextField(placeholder: "Placeholder", text: $text, focused: $focused, maxHeight: 300) + MessageComposerTextField(placeholder: "Placeholder", text: $text, focused: $focused, maxHeight: 300, onEnterKeyHandler: { }) } } } diff --git a/changelog.d/314.feature b/changelog.d/314.feature new file mode 100644 index 000000000..f0bad19bd --- /dev/null +++ b/changelog.d/314.feature @@ -0,0 +1 @@ +Send messages on return.