mirror of
https://gitlab.opencode.de/bwi/bundesmessenger/clients/bundesmessenger-ios.git
synced 2026-05-04 23:17:43 +02:00
Merge commit '35b2fdc538dfc1f8fac2585704526ab26148a9ab' into feature/3977_merge_element_1_9_13
# Conflicts: # Config/AppVersion.xcconfig # Podfile.lock # Riot/Modules/Application/LegacyAppDelegate.m # Riot/Modules/Authentication/AuthenticationCoordinator.swift # Riot/Modules/Authentication/Legacy/LegacyAuthenticationCoordinator.swift # Riot/Modules/LaunchLoading/LaunchLoadingView.swift # Riot/Modules/LaunchLoading/LaunchLoadingView.xib # Riot/Modules/MatrixKit/Models/Account/MXKAccount.m # Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellData.m # Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomTimelineCellProvider.m # Riot/Modules/Room/TimelineCells/Styles/Plain/PlainRoomTimelineCellProvider.m # Riot/Modules/TabBar/MasterTabBarController.m # fastlane/Fastfile
This commit is contained in:
@@ -75,6 +75,8 @@ typedef NS_ENUM(NSUInteger, RoomInputToolbarViewSendMode)
|
||||
*/
|
||||
- (void)roomInputToolbarView:(RoomInputToolbarView *)toolbarView sendAttributedTextMessage:(NSAttributedString *)attributedTextMessage;
|
||||
|
||||
- (void)didChangeMaximisedState: (BOOL) isMaximised;
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
|
||||
@@ -32,12 +32,23 @@ class WysiwygInputToolbarView: MXKRoomInputToolbarView, NibLoadable, HtmlRoomInp
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Private
|
||||
private var keyboardHeight: CGFloat = .zero {
|
||||
didSet {
|
||||
updateTextViewHeight()
|
||||
}
|
||||
}
|
||||
private var voiceMessageToolbarView: VoiceMessageToolbarView?
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
private var heightConstraint: NSLayoutConstraint!
|
||||
private var voiceMessageBottomConstraint: NSLayoutConstraint?
|
||||
private var hostingViewController: VectorHostingController!
|
||||
private var wysiwygViewModel = WysiwygComposerViewModel(textColor: ThemeService.shared().theme.colors.primaryContent)
|
||||
private var viewModel: ComposerViewModelProtocol = ComposerViewModel(initialViewState: ComposerViewState())
|
||||
private var viewModel: ComposerViewModelProtocol!
|
||||
|
||||
private var isLandscapePhone: Bool {
|
||||
let device = UIDevice.current
|
||||
return device.isPhone && device.orientation.isLandscape
|
||||
}
|
||||
|
||||
// MARK: Public
|
||||
|
||||
@@ -50,6 +61,35 @@ class WysiwygInputToolbarView: MXKRoomInputToolbarView, NibLoadable, HtmlRoomInp
|
||||
}
|
||||
}
|
||||
|
||||
override var isFocused: Bool {
|
||||
viewModel.isFocused
|
||||
}
|
||||
|
||||
var isMaximised: Bool {
|
||||
wysiwygViewModel.maximised
|
||||
}
|
||||
|
||||
var idealHeight: CGFloat {
|
||||
get {
|
||||
wysiwygViewModel.idealHeight
|
||||
}
|
||||
set {
|
||||
wysiwygViewModel.idealHeight = newValue
|
||||
}
|
||||
}
|
||||
|
||||
var compressedHeight: CGFloat {
|
||||
wysiwygViewModel.compressedHeight
|
||||
}
|
||||
|
||||
var maxExpandedHeight: CGFloat {
|
||||
wysiwygViewModel.maxExpandedHeight
|
||||
}
|
||||
|
||||
var maxCompressedHeight: CGFloat {
|
||||
wysiwygViewModel.maxCompressedHeight
|
||||
}
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
override class func instantiate() -> MXKRoomInputToolbarView! {
|
||||
@@ -62,15 +102,21 @@ class WysiwygInputToolbarView: MXKRoomInputToolbarView, NibLoadable, HtmlRoomInp
|
||||
|
||||
override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
viewModel = ComposerViewModel(
|
||||
initialViewState: ComposerViewState(textFormattingEnabled: RiotSettings.shared.enableWysiwygTextFormatting,
|
||||
isLandscapePhone: isLandscapePhone, bindings: ComposerBindings(focused: false)))
|
||||
|
||||
viewModel.callback = { [weak self] result in
|
||||
self?.handleViewModelResult(result)
|
||||
}
|
||||
wysiwygViewModel.plainTextMode = !RiotSettings.shared.enableWysiwygTextFormatting
|
||||
|
||||
inputAccessoryViewForKeyboard = UIView(frame: .zero)
|
||||
|
||||
let composer = Composer(viewModel: viewModel.context,
|
||||
let composer = Composer(
|
||||
viewModel: viewModel.context,
|
||||
wysiwygViewModel: wysiwygViewModel,
|
||||
resizeAnimationDuration: Double(kResizeComposerAnimationDuration),
|
||||
sendMessageAction: { [weak self] content in
|
||||
guard let self = self else { return }
|
||||
self.sendWysiwygMessage(content: content)
|
||||
@@ -97,6 +143,7 @@ class WysiwygInputToolbarView: MXKRoomInputToolbarView, NibLoadable, HtmlRoomInp
|
||||
subView.trailingAnchor.constraint(equalTo: self.trailingAnchor),
|
||||
subView.bottomAnchor.constraint(equalTo: self.bottomAnchor)
|
||||
])
|
||||
|
||||
cancellables = [
|
||||
hostingViewController.heightPublisher
|
||||
.removeDuplicates()
|
||||
@@ -109,11 +156,36 @@ class WysiwygInputToolbarView: MXKRoomInputToolbarView, NibLoadable, HtmlRoomInp
|
||||
.removeDuplicates()
|
||||
.sink { [weak hostingViewController] _ in
|
||||
hostingViewController?.view.setNeedsLayout()
|
||||
},
|
||||
|
||||
wysiwygViewModel.$maximised
|
||||
.dropFirst()
|
||||
.removeDuplicates()
|
||||
.sink { [weak self] value in
|
||||
guard let self = self else { return }
|
||||
self.toolbarViewDelegate?.didChangeMaximisedState(value)
|
||||
self.hostingViewController.view.layer.cornerRadius = value ? 20 : 0
|
||||
if !value {
|
||||
self.voiceMessageBottomConstraint?.constant = 2
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
update(theme: ThemeService.shared().theme)
|
||||
registerThemeServiceDidChangeThemeNotification()
|
||||
NotificationCenter.default.addObserver(
|
||||
self,
|
||||
selector: #selector(keyboardWillShow),
|
||||
name: UIResponder.keyboardWillShowNotification,
|
||||
object: nil
|
||||
)
|
||||
NotificationCenter.default.addObserver(
|
||||
self,
|
||||
selector: #selector(keyboardWillHide),
|
||||
name: UIResponder.keyboardWillHideNotification,
|
||||
object: nil
|
||||
)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(deviceDidRotate), name: UIDevice.orientationDidChangeNotification, object: nil)
|
||||
}
|
||||
|
||||
override func customizeRendering() {
|
||||
@@ -121,15 +193,62 @@ class WysiwygInputToolbarView: MXKRoomInputToolbarView, NibLoadable, HtmlRoomInp
|
||||
self.backgroundColor = .clear
|
||||
}
|
||||
|
||||
override func dismissKeyboard() {
|
||||
self.viewModel.dismissKeyboard()
|
||||
}
|
||||
|
||||
override func dismissValidationView(_ validationView: MXKImageView!) {
|
||||
super.dismissValidationView(validationView)
|
||||
if isMaximised {
|
||||
showKeyboard()
|
||||
}
|
||||
}
|
||||
|
||||
func showKeyboard() {
|
||||
self.viewModel.showKeyboard()
|
||||
}
|
||||
|
||||
func minimise() {
|
||||
wysiwygViewModel.maximised = false
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
@objc private func keyboardWillShow(_ notification: Notification) {
|
||||
if let keyboardFrame: NSValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue {
|
||||
let keyboardRectangle = keyboardFrame.cgRectValue
|
||||
keyboardHeight = keyboardRectangle.height
|
||||
if self.isMaximised {
|
||||
self.voiceMessageBottomConstraint?.constant = keyboardHeight - (window?.safeAreaInsets.bottom ?? 0) + 2
|
||||
} else {
|
||||
self.voiceMessageBottomConstraint?.constant = 2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func keyboardWillHide(_ notification: Notification) {
|
||||
if self.isMaximised {
|
||||
self.voiceMessageBottomConstraint?.constant = 2
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func deviceDidRotate(_ notification: Notification) {
|
||||
viewModel.isLandscapePhone = isLandscapePhone
|
||||
DispatchQueue.main.async {
|
||||
self.updateTextViewHeight()
|
||||
}
|
||||
}
|
||||
|
||||
private func updateToolbarHeight(wysiwygHeight: CGFloat) {
|
||||
self.heightConstraint.constant = wysiwygHeight
|
||||
toolbarViewDelegate?.roomInputToolbarView?(self, heightDidChanged: wysiwygHeight, completion: nil)
|
||||
}
|
||||
|
||||
private func sendWysiwygMessage(content: WysiwygComposerContent) {
|
||||
delegate?.roomInputToolbarView?(self, sendFormattedTextMessage: content.html, withRawText: content.plainText)
|
||||
delegate?.roomInputToolbarView?(self, sendFormattedTextMessage: content.html, withRawText: content.markdown)
|
||||
if isMaximised {
|
||||
minimise()
|
||||
}
|
||||
}
|
||||
|
||||
private func showSendMediaActions() {
|
||||
@@ -155,7 +274,7 @@ class WysiwygInputToolbarView: MXKRoomInputToolbarView, NibLoadable, HtmlRoomInp
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
private func registerThemeServiceDidChangeThemeNotification() {
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(themeDidChange), name: .themeServiceDidChangeTheme, object: nil)
|
||||
}
|
||||
@@ -169,6 +288,19 @@ class WysiwygInputToolbarView: MXKRoomInputToolbarView, NibLoadable, HtmlRoomInp
|
||||
wysiwygViewModel.textColor = theme.colors.primaryContent
|
||||
}
|
||||
|
||||
private func updateTextViewHeight() {
|
||||
let height = UIScreen.main.bounds.height
|
||||
let barOffset: CGFloat = 68
|
||||
let toolbarHeight: CGFloat = sendMode == .send ? 96 : 110
|
||||
let finalHeight = height - keyboardHeight - toolbarHeight - barOffset
|
||||
wysiwygViewModel.maxExpandedHeight = finalHeight
|
||||
if finalHeight < 200 {
|
||||
wysiwygViewModel.maxCompressedHeight = finalHeight > wysiwygViewModel.minHeight ? finalHeight : wysiwygViewModel.minHeight
|
||||
} else {
|
||||
wysiwygViewModel.maxCompressedHeight = 200
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - HtmlRoomInputToolbarViewProtocol
|
||||
var isEncryptionEnabled = false {
|
||||
didSet {
|
||||
@@ -204,6 +336,18 @@ class WysiwygInputToolbarView: MXKRoomInputToolbarView, NibLoadable, HtmlRoomInp
|
||||
set {
|
||||
viewModel.sendMode = ComposerSendMode(from: newValue)
|
||||
updatePlaceholderText()
|
||||
updateTextViewHeight()
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether text formatting is currently enabled in the composer.
|
||||
var textFormattingEnabled: Bool {
|
||||
get {
|
||||
self.viewModel.textFormattingEnabled
|
||||
}
|
||||
set {
|
||||
self.viewModel.textFormattingEnabled = newValue
|
||||
self.wysiwygViewModel.plainTextMode = !newValue
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,17 +359,21 @@ class WysiwygInputToolbarView: MXKRoomInputToolbarView, NibLoadable, HtmlRoomInp
|
||||
voiceMessageToolbarView.translatesAutoresizingMaskIntoConstraints = false
|
||||
NSLayoutConstraint.deactivate(voiceMessageToolbarView.containersTopConstraints)
|
||||
addSubview(voiceMessageToolbarView)
|
||||
let bottomConstraint = hostingViewController.view.bottomAnchor.constraint(equalTo: voiceMessageToolbarView.bottomAnchor, constant: 2)
|
||||
voiceMessageBottomConstraint = bottomConstraint
|
||||
NSLayoutConstraint.activate(
|
||||
[
|
||||
hostingViewController.view.topAnchor.constraint(equalTo: voiceMessageToolbarView.topAnchor),
|
||||
hostingViewController.view.leftAnchor.constraint(equalTo: voiceMessageToolbarView.leftAnchor),
|
||||
hostingViewController.view.bottomAnchor.constraint(equalTo: voiceMessageToolbarView.bottomAnchor, constant: 4),
|
||||
hostingViewController.view.rightAnchor.constraint(equalTo: voiceMessageToolbarView.rightAnchor)
|
||||
hostingViewController.view.safeAreaLayoutGuide.topAnchor.constraint(equalTo: voiceMessageToolbarView.topAnchor),
|
||||
hostingViewController.view.safeAreaLayoutGuide.leftAnchor.constraint(equalTo: voiceMessageToolbarView.leftAnchor),
|
||||
bottomConstraint,
|
||||
hostingViewController.view.safeAreaLayoutGuide.rightAnchor.constraint(equalTo: voiceMessageToolbarView.rightAnchor)
|
||||
]
|
||||
)
|
||||
} else {
|
||||
self.voiceMessageToolbarView?.removeFromSuperview()
|
||||
self.voiceMessageToolbarView = nil
|
||||
self.voiceMessageBottomConstraint?.isActive = false
|
||||
self.voiceMessageBottomConstraint = nil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user