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:
Frank Rotermund
2022-12-19 14:36:30 +01:00
245 changed files with 5346 additions and 1952 deletions
@@ -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
}
}