diff --git a/Chatto/Source/ChatController/BaseChatViewController.swift b/Chatto/Source/ChatController/BaseChatViewController.swift index e94221ce..3654b44c 100644 --- a/Chatto/Source/ChatController/BaseChatViewController.swift +++ b/Chatto/Source/ChatController/BaseChatViewController.swift @@ -318,6 +318,21 @@ open class BaseChatViewController: UIViewController, self.keyboardTracker = KeyboardTracker(viewController: self, inputBarContainer: self.inputBarContainer, heightBlock: heightBlock, notificationCenter: self.notificationCenter) (self.view as? BaseChatViewControllerViewProtocol)?.bmaInputAccessoryView = self.keyboardTracker?.trackingView + + if #available(iOS 26, *) { + notificationCenter.removeObserver(self.keyboardTracker!) + inputContainerBottomConstraint.isActive = false + inputBarContainer.translatesAutoresizingMaskIntoConstraints = false + + NSLayoutConstraint.activate([ + inputBarContainer.leadingAnchor.constraint(equalTo: view.leadingAnchor), + inputBarContainer.trailingAnchor.constraint(equalTo: view.trailingAnchor), + inputBarContainer.bottomAnchor.constraint( + equalTo: view.keyboardLayoutGuide.topAnchor + ) + ]) + view.keyboardLayoutGuide.followsUndockedKeyboard = true + } } var notificationCenter = NotificationCenter.default diff --git a/ChattoAdditions/Source/Input/ChatInputBarPresenter.swift b/ChattoAdditions/Source/Input/ChatInputBarPresenter.swift index e2dad253..ee25029e 100644 --- a/ChattoAdditions/Source/Input/ChatInputBarPresenter.swift +++ b/ChattoAdditions/Source/Input/ChatInputBarPresenter.swift @@ -107,6 +107,15 @@ public class BasicChatInputBarPresenter: NSObject, ChatInputBarPresenter { private var lastKnownKeyboardHeight: CGFloat? private var allowListenToChangeFrameEvents = true + /// iOS 26 adds a grabber/separator above custom input views. + /// No public API exists to query this value. + private var inputViewGrabberHeight: CGFloat { + if #available(iOS 26, *) { + return 17.0 + } + return 0 + } + // MARK: Input View private weak var currentInputView: InputContainerView? @@ -114,7 +123,7 @@ public class BasicChatInputBarPresenter: NSObject, ChatInputBarPresenter { private func updateHeight(for inputView: InputContainerView) { inputView.contentHeight = { if let keyboardHeight = self.lastKnownKeyboardHeight, keyboardHeight > 0 { - return keyboardHeight + return keyboardHeight - self.inputViewGrabberHeight } else { if UIScreen.main.portraitOrientation { return UIScreen.main.defaultPortraitKeyboardHeight @@ -135,7 +144,17 @@ public class BasicChatInputBarPresenter: NSObject, ChatInputBarPresenter { guard self.focusedItem != nil else { return } guard let value = (notification as NSNotification).userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else { return } guard value.cgRectValue.height > 0 else { return } - self.lastKnownKeyboardHeight = value.cgRectValue.height - self.chatInputBar.bounds.height + var keyboardHeight: CGFloat + if #available(iOS 26, *) { + // iOS 26 no longer includes the input accessory view (chat bar) + // in the reported keyboard frame, so we skip the subtraction. + // Note that for custom intput views, the grabber height is still included in the keyboard frame, + // so we have to subtract it out. + keyboardHeight = value.cgRectValue.height + } else { + keyboardHeight = value.cgRectValue.height - self.chatInputBar.bounds.height + } + self.lastKnownKeyboardHeight = keyboardHeight } @objc