mirror of
https://gitlab.opencode.de/bwi/bundesmessenger/clients/bundesmessenger-ios.git
synced 2026-04-17 15:09:31 +02:00
Merge pull request #7711 from vector-im/nicolas/update-RTE-2.15
Bump RTE version to 2.18.0
This commit is contained in:
@@ -26,7 +26,7 @@ KEYCHAIN_ACCESS_GROUP = $(AppIdentifierPrefix)$(BASE_BUNDLE_IDENTIFIER).keychain
|
||||
BROADCAST_UPLOAD_EXTENSION_BUNDLE_IDENTIFIER = $(BASE_BUNDLE_IDENTIFIER).broadcastUploadExtension
|
||||
|
||||
// Build settings
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0
|
||||
SDKROOT = iphoneos
|
||||
TARGETED_DEVICE_FAMILY = 1,2
|
||||
SWIFT_VERSION = 5.6
|
||||
|
||||
2
Podfile
2
Podfile
@@ -1,7 +1,7 @@
|
||||
source 'https://cdn.cocoapods.org/'
|
||||
|
||||
# Uncomment this line to define a global platform for your project
|
||||
platform :ios, '14.0'
|
||||
platform :ios, '15.0'
|
||||
|
||||
# By default, ignore all warnings from any pod
|
||||
inhibit_all_warnings!
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/Cocoanetics/DTCoreText",
|
||||
"state" : {
|
||||
"revision" : "9d2d4d2296e5d2d852a7d3c592b817d913a5d020",
|
||||
"version" : "1.6.27"
|
||||
"revision" : "b664664825da565b4c2b7a17dbe2369f68ae43d9",
|
||||
"version" : "1.6.26"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -50,8 +50,8 @@
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/matrix-org/matrix-wysiwyg-composer-swift",
|
||||
"state" : {
|
||||
"revision" : "1100b217c04d096dfe072afb4484660ff794d805",
|
||||
"version" : "2.2.2"
|
||||
"revision" : "dfb74c89bf54b41ea000d564d6435ac6444ba6b4",
|
||||
"version" : "2.18.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -47,7 +47,9 @@ class HTMLFormatter: NSObject {
|
||||
|
||||
var options: [AnyHashable: Any] = [
|
||||
DTUseiOS6Attributes: true,
|
||||
DTDefaultFontDescriptor: font.fontDescriptor,
|
||||
DTDefaultFontFamily: font.familyName,
|
||||
DTDefaultFontName: font.fontName,
|
||||
DTDefaultFontSize: font.pointSize,
|
||||
DTDefaultLinkDecoration: false,
|
||||
DTDefaultLinkColor: ThemeService.shared().theme.colors.links,
|
||||
DTWillFlushBlockCallBack: sanitizeCallback
|
||||
|
||||
@@ -200,15 +200,7 @@ extension RoomViewController {
|
||||
optionalTextView?.becomeFirstResponder()
|
||||
originalRect = wysiwygInputToolbar.convert(wysiwygInputToolbar.frame, to: view)
|
||||
}
|
||||
// This tirggers a SwiftUI update that is handled correctly on iOS 16, but needs to be dispatchted async on older versions
|
||||
// Dispatching on iOS 16 instead causes some weird SwiftUI update behaviours
|
||||
if #available(iOS 16, *) {
|
||||
wysiwygInputToolbar.showKeyboard()
|
||||
} else {
|
||||
DispatchQueue.main.async {
|
||||
wysiwygInputToolbar.showKeyboard()
|
||||
}
|
||||
}
|
||||
|
||||
roomInputToolbarContainer.removeFromSuperview()
|
||||
let dimmingView = UIView()
|
||||
dimmingView.translatesAutoresizingMaskIntoConstraints = false
|
||||
@@ -235,7 +227,18 @@ extension RoomViewController {
|
||||
}
|
||||
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(didPanRoomToolbarContainer(_ :)))
|
||||
roomInputToolbarContainer.addGestureRecognizer(panGesture)
|
||||
optionalTextView?.removeFromSuperview()
|
||||
if let optionalTextView {
|
||||
// This tirggers a SwiftUI update that is handled correctly on iOS 16, but needs to be dispatchted async on older versions
|
||||
// Dispatching on iOS 16 instead causes some weird SwiftUI update behaviours
|
||||
if #available(iOS 16, *) {
|
||||
wysiwygInputToolbar.showKeyboard()
|
||||
} else {
|
||||
DispatchQueue.main.async {
|
||||
wysiwygInputToolbar.showKeyboard()
|
||||
}
|
||||
}
|
||||
optionalTextView.removeFromSuperview()
|
||||
}
|
||||
} else {
|
||||
let originalRect = wysiwygInputToolbar.convert(wysiwygInputToolbar.frame, to: view)
|
||||
var optionalTextView: UITextView?
|
||||
@@ -244,7 +247,6 @@ extension RoomViewController {
|
||||
optionalTextView = textView
|
||||
self.view.window?.addSubview(textView)
|
||||
optionalTextView?.becomeFirstResponder()
|
||||
wysiwygInputToolbar.showKeyboard()
|
||||
}
|
||||
self.roomInputToolbarContainer.removeFromSuperview()
|
||||
maximisedToolbarDimmingView?.removeFromSuperview()
|
||||
@@ -257,7 +259,10 @@ extension RoomViewController {
|
||||
self.view.layoutIfNeeded()
|
||||
}
|
||||
roomInputToolbarContainer.gestureRecognizers?.removeAll()
|
||||
optionalTextView?.removeFromSuperview()
|
||||
if let optionalTextView {
|
||||
wysiwygInputToolbar.showKeyboard()
|
||||
optionalTextView.removeFromSuperview()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -384,8 +389,8 @@ extension RoomViewController: ComposerLinkActionBridgePresenterDelegate {
|
||||
}
|
||||
|
||||
// MARK: - PermalinkReplacer
|
||||
extension RoomViewController: PermalinkReplacer {
|
||||
public func replacementForLink(_ url: String, text: String) -> NSAttributedString? {
|
||||
extension RoomViewController: MentionReplacer {
|
||||
public func replacementForMention(_ url: String, text: String) -> NSAttributedString? {
|
||||
guard #available(iOS 15.0, *),
|
||||
let url = URL(string: url),
|
||||
let session = roomDataSource.mxSession,
|
||||
|
||||
@@ -140,6 +140,20 @@ class WysiwygInputToolbarView: MXKRoomInputToolbarView, NibLoadable, HtmlRoomInp
|
||||
wysiwygViewModel.maxCompressedHeight
|
||||
}
|
||||
|
||||
override func paste(_ sender: Any?) {
|
||||
let pasteboard = MXKPasteboardManager.shared.pasteboard
|
||||
let types = pasteboard.types.map { UTI(rawValue: $0) }
|
||||
|
||||
// Minimise the composer and dismiss the keyboard if it's an image, a video or a file
|
||||
if types.contains(where: { $0.conforms(to: .image) || $0.conforms(to: .movie) || $0.conforms(to: .video) || $0.conforms(to: .application) }) {
|
||||
wysiwygViewModel.maximised = false
|
||||
DispatchQueue.main.async {
|
||||
self.viewModel.dismissKeyboard()
|
||||
}
|
||||
}
|
||||
super.paste(sender)
|
||||
}
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
override class func instantiate() -> MXKRoomInputToolbarView! {
|
||||
@@ -150,8 +164,8 @@ class WysiwygInputToolbarView: MXKRoomInputToolbarView, NibLoadable, HtmlRoomInp
|
||||
return (delegate as? RoomInputToolbarViewDelegate) ?? nil
|
||||
}
|
||||
|
||||
private var permalinkReplacer: PermalinkReplacer? {
|
||||
return (delegate as? PermalinkReplacer)
|
||||
private var permalinkReplacer: MentionReplacer? {
|
||||
return (delegate as? MentionReplacer)
|
||||
}
|
||||
|
||||
override func awakeFromNib() {
|
||||
@@ -192,6 +206,7 @@ class WysiwygInputToolbarView: MXKRoomInputToolbarView, NibLoadable, HtmlRoomInp
|
||||
}
|
||||
|
||||
func showKeyboard() {
|
||||
self.wysiwygViewModel.textView.becomeFirstResponder()
|
||||
self.viewModel.showKeyboard()
|
||||
}
|
||||
|
||||
@@ -238,7 +253,7 @@ class WysiwygInputToolbarView: MXKRoomInputToolbarView, NibLoadable, HtmlRoomInp
|
||||
self?.handleViewModelResult(result)
|
||||
}
|
||||
wysiwygViewModel.plainTextMode = !RiotSettings.shared.enableWysiwygTextFormatting
|
||||
wysiwygViewModel.permalinkReplacer = permalinkReplacer
|
||||
wysiwygViewModel.mentionReplacer = permalinkReplacer
|
||||
|
||||
inputAccessoryViewForKeyboard = UIView(frame: .zero)
|
||||
|
||||
|
||||
@@ -156,7 +156,7 @@ extension FormatItem {
|
||||
|
||||
extension FormatType {
|
||||
/// Convenience method to map it to the external ViewModel action
|
||||
var action: WysiwygAction {
|
||||
var action: ComposerAction {
|
||||
switch self {
|
||||
case .bold:
|
||||
return .bold
|
||||
|
||||
@@ -32,6 +32,7 @@ struct Composer: View {
|
||||
@Environment(\.theme) private var theme: ThemeSwiftUI
|
||||
|
||||
@State private var isActionButtonShowing = false
|
||||
@FocusState private var focused: Bool
|
||||
|
||||
private let horizontalPadding: CGFloat = 12
|
||||
private let borderHeight: CGFloat = 40
|
||||
@@ -58,17 +59,8 @@ struct Composer: View {
|
||||
viewModel.viewState.shouldDisplayContext ? contextBannerHeight + standardVerticalPadding + verticalComponentSpacing : 0
|
||||
}
|
||||
|
||||
/// Computes the total height of the composer (excluding the RTE formatting bar).
|
||||
/// This height includes the text view, as well as the context banner
|
||||
/// and user suggestion list when displayed.
|
||||
private var composerHeight: CGFloat {
|
||||
wysiwygViewModel.idealHeight
|
||||
+ composerTopPadding
|
||||
+ composerVerticalPadding
|
||||
// Extra padding added on top of the VStack containing the composer
|
||||
+ standardVerticalPadding
|
||||
+ additionalHeightForContextBanner
|
||||
}
|
||||
/// the total height of the composer (excluding the RTE formatting bar).
|
||||
@State private var composerHeight: CGFloat = .zero
|
||||
|
||||
private var cornerRadius: CGFloat {
|
||||
if shouldFixRoundCorner {
|
||||
@@ -139,20 +131,39 @@ struct Composer: View {
|
||||
.padding(.horizontal, horizontalPadding)
|
||||
}
|
||||
HStack(alignment: shouldFixRoundCorner ? .top : .center, spacing: 0) {
|
||||
WysiwygComposerView(
|
||||
focused: $viewModel.focused,
|
||||
viewModel: wysiwygViewModel
|
||||
)
|
||||
.tintColor(theme.colors.accent)
|
||||
.placeholder(viewModel.viewState.placeholder, color: theme.colors.tertiaryContent)
|
||||
.onAppear {
|
||||
if wysiwygViewModel.isContentEmpty {
|
||||
wysiwygViewModel.setup()
|
||||
// Use a GeometryReader to force the composer to fill the HStack
|
||||
GeometryReader { _ in
|
||||
WysiwygComposerView(
|
||||
placeholder: viewModel.viewState.placeholder ?? "",
|
||||
viewModel: wysiwygViewModel,
|
||||
itemProviderHelper: nil,
|
||||
keyCommandHandler: handleKeyCommand,
|
||||
pasteHandler: nil
|
||||
)
|
||||
.clipped()
|
||||
.tint(theme.colors.accent)
|
||||
.focused($focused)
|
||||
.onChange(of: focused) { newValue in
|
||||
viewModel.focused = newValue
|
||||
}
|
||||
.onChange(of: viewModel.focused) { newValue in
|
||||
guard focused != newValue else { return }
|
||||
focused = newValue
|
||||
}
|
||||
.onAppear {
|
||||
if wysiwygViewModel.isContentEmpty {
|
||||
wysiwygViewModel.setup()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !viewModel.viewState.isMinimiseForced {
|
||||
Button {
|
||||
wysiwygViewModel.maximised.toggle()
|
||||
viewModel.focused = true
|
||||
// Use a dispatched block so the focus state will be up to date when the composer size changes.
|
||||
DispatchQueue.main.async {
|
||||
wysiwygViewModel.maximised.toggle()
|
||||
}
|
||||
} label: {
|
||||
Image(toggleButtonImageName)
|
||||
.resizable()
|
||||
@@ -167,15 +178,14 @@ struct Composer: View {
|
||||
.padding(.horizontal, horizontalPadding)
|
||||
.padding(.top, composerTopPadding)
|
||||
.padding(.bottom, composerVerticalPadding)
|
||||
.layoutPriority(1)
|
||||
}
|
||||
.clipShape(rect)
|
||||
.overlay(rect.stroke(borderColor, lineWidth: 1))
|
||||
.animation(.easeInOut(duration: resizeAnimationDuration), value: wysiwygViewModel.idealHeight)
|
||||
.padding(.top, standardVerticalPadding)
|
||||
.onTapGesture {
|
||||
if viewModel.focused {
|
||||
viewModel.focused = true
|
||||
}
|
||||
viewModel.focused = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,6 +228,29 @@ struct Composer: View {
|
||||
}
|
||||
}
|
||||
|
||||
func handleKeyCommand(_ keyCommand: WysiwygKeyCommand) -> Bool {
|
||||
switch keyCommand {
|
||||
case .enter:
|
||||
sendMessageAction(wysiwygViewModel.content)
|
||||
wysiwygViewModel.clearContent()
|
||||
return true
|
||||
case .shiftEnter:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes the total height of the composer (excluding the RTE formatting bar).
|
||||
/// This height includes the text view, as well as the context banner
|
||||
/// and user suggestion list when displayed.
|
||||
private func updateComposerHeight(idealHeight: CGFloat) {
|
||||
composerHeight = idealHeight
|
||||
+ composerTopPadding
|
||||
+ composerVerticalPadding
|
||||
// Extra padding added on top of the VStack containing the composer
|
||||
+ standardVerticalPadding
|
||||
+ additionalHeightForContextBanner
|
||||
}
|
||||
|
||||
// MARK: Public
|
||||
|
||||
init(
|
||||
@@ -287,6 +320,15 @@ struct Composer: View {
|
||||
.onChange(of: wysiwygViewModel.suggestionPattern) { newValue in
|
||||
sendMentionPattern(pattern: newValue)
|
||||
}
|
||||
.onChange(of: wysiwygViewModel.idealHeight) { newValue in
|
||||
updateComposerHeight(idealHeight: newValue)
|
||||
}
|
||||
.onChange(of: viewModel.viewState.shouldDisplayContext) { _ in
|
||||
updateComposerHeight(idealHeight: wysiwygViewModel.idealHeight)
|
||||
}
|
||||
.task {
|
||||
updateComposerHeight(idealHeight: wysiwygViewModel.idealHeight)
|
||||
}
|
||||
}
|
||||
|
||||
private func storeCurrentSelection() {
|
||||
|
||||
1
changelog.d/7681.bugfix
Normal file
1
changelog.d/7681.bugfix
Normal file
@@ -0,0 +1 @@
|
||||
Editing a message that ends with an emoji now works as expected.
|
||||
@@ -59,10 +59,10 @@ packages:
|
||||
branch: 0.0.1
|
||||
WysiwygComposer:
|
||||
url: https://github.com/matrix-org/matrix-wysiwyg-composer-swift
|
||||
version: 2.2.2
|
||||
version: 2.18.0
|
||||
DeviceKit:
|
||||
url: https://github.com/devicekit/DeviceKit
|
||||
majorVersion: 4.7.0
|
||||
DTCoreText:
|
||||
url: https://github.com/Cocoanetics/DTCoreText
|
||||
version: 1.6.27
|
||||
version: 1.6.26
|
||||
|
||||
Reference in New Issue
Block a user