mirror of
https://gitlab.opencode.de/bwi/bundesmessenger/clients/bundesmessenger-ios.git
synced 2026-04-25 11:02:48 +02:00
8a186a37d8
* commit 'd786f7bb4f37b77478a8a55df44a6e87247f96c1': (36 commits) finish version++ Release notes version++ changelog.d: Upgrade MatrixSDK version ([v0.27.4](https://github.com/matrix-org/matrix-ios-sdk/releases/tag/v0.27.4)). Fix missing placeholder. Translated using Weblate (Catalan) Translated using Weblate (Catalan) Translated using Weblate (Catalan) Translated using Weblate (Arabic) Translated using Weblate (Arabic) Translated using Weblate (Chinese (Simplified)) Translated using Weblate (Vietnamese) Translated using Weblate (Chinese (Simplified)) Translated using Weblate (Chinese (Simplified)) Fix: Remove the “Quote” action from the menu of the selected message. Update RTE to 2.18.0 to fix an issue with Speech-to-Text Code cleanup Dismiss the keyboard and minimise the composer when pasting an image, a video or a file Fix: focus, keyboard visibility, composer height Restore composer tint color ... # Conflicts: # Config/AppVersion.xcconfig # Riot/Modules/Room/RoomViewController.m
117 lines
5.3 KiB
Swift
117 lines
5.3 KiB
Swift
//
|
||
// Copyright 2021 New Vector Ltd
|
||
//
|
||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||
// you may not use this file except in compliance with the License.
|
||
// You may obtain a copy of the License at
|
||
//
|
||
// http://www.apache.org/licenses/LICENSE-2.0
|
||
//
|
||
// Unless required by applicable law or agreed to in writing, software
|
||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
// See the License for the specific language governing permissions and
|
||
// limitations under the License.
|
||
//
|
||
|
||
import Foundation
|
||
import DTCoreText
|
||
import UIKit
|
||
|
||
@objcMembers
|
||
class HTMLFormatter: NSObject {
|
||
/// Builds an attributed string from a string containing html.
|
||
///
|
||
/// - Parameters:
|
||
/// - htmlString: The html string to use.
|
||
/// - allowedTags: The html tags that should be allowed.
|
||
/// - font: The default font to use.
|
||
/// - imageHandler: The image handler for the formatted string
|
||
/// - extraOptions: Extra (or override) options to apply for the format. See DTCoreText's documentation for available options.
|
||
/// - postFormatOperations: Optional block to provide operations to apply
|
||
/// - Returns: The built `NSAttributedString`.
|
||
/// - Note: It is recommended to include "p" and "body" tags in `allowedTags` as these are often added when parsing.
|
||
static func formatHTML(_ htmlString: String,
|
||
withAllowedTags allowedTags: [String],
|
||
font: UIFont,
|
||
andImageHandler imageHandler: DTHTMLElement.ImageHandler? = nil,
|
||
extraOptions: [AnyHashable: Any] = [:],
|
||
postFormatOperations: ((NSMutableAttributedString) -> Void)? = nil) -> NSAttributedString {
|
||
guard let data = htmlString.data(using: .utf8) else {
|
||
return NSAttributedString(string: htmlString)
|
||
}
|
||
|
||
let sanitizeCallback: DTHTMLAttributedStringBuilderWillFlushCallback = { [allowedTags, font, imageHandler] (element: DTHTMLElement?) in
|
||
element?.sanitize(with: allowedTags, bodyFont: font, imageHandler: imageHandler)
|
||
}
|
||
|
||
var options: [AnyHashable: Any] = [
|
||
DTUseiOS6Attributes: true,
|
||
DTDefaultFontFamily: font.familyName,
|
||
DTDefaultFontName: font.fontName,
|
||
DTDefaultFontSize: font.pointSize,
|
||
DTDefaultLinkDecoration: false,
|
||
DTDefaultLinkColor: ThemeService.shared().theme.colors.links,
|
||
DTWillFlushBlockCallBack: sanitizeCallback
|
||
]
|
||
options.merge(extraOptions) { (_, new) in new }
|
||
|
||
guard let string = self.formatHTML(data, options: options) else {
|
||
return NSAttributedString(string: htmlString)
|
||
}
|
||
|
||
let mutableString = NSMutableAttributedString(attributedString: string)
|
||
MXKTools.removeDTCoreTextArtifacts(mutableString)
|
||
postFormatOperations?(mutableString)
|
||
|
||
// Remove CTForegroundColorFromContext attribute to fix the iOS 16 black link color issue
|
||
// REF: https://github.com/Cocoanetics/DTCoreText/issues/792
|
||
mutableString.removeAttribute(NSAttributedString.Key("CTForegroundColorFromContext"), range: NSRange(location: 0, length: mutableString.length))
|
||
|
||
return mutableString
|
||
}
|
||
|
||
/// Builds an attributed string by replacing a `%@` placeholder with the supplied link text and URL.
|
||
/// - Parameters:
|
||
/// - string: The string to be formatted.
|
||
/// - link: The link text to be inserted.
|
||
/// - url: The URL to be linked to.
|
||
/// - Returns: An attributed string.
|
||
static func format(_ string: String, with link: String, using url: URL) -> NSAttributedString {
|
||
let baseString = NSMutableAttributedString(string: string)
|
||
let attributedLink = NSAttributedString(string: link, attributes: [.link: url])
|
||
|
||
let linkRange = (baseString.string as NSString).range(of: "%@")
|
||
baseString.replaceCharacters(in: linkRange, with: attributedLink)
|
||
|
||
return baseString
|
||
}
|
||
}
|
||
|
||
extension HTMLFormatter {
|
||
/// This replicates DTCoreText's NSAttributedString `initWithHTMLData`.
|
||
/// It sets the sanitize callback on the builder from Swift to avoid EXC_BAD_ACCESS crashes.
|
||
///
|
||
/// - Parameters:
|
||
/// - data: The data in HTML format from which to create the attributed string.
|
||
/// - options: Specifies how the document should be loaded.
|
||
/// - Returns: Returns an initialized object, or `nil` if the data can’t be decoded.
|
||
@objc static func formatHTML(_ data: Data,
|
||
options: [AnyHashable: Any]) -> NSAttributedString? {
|
||
guard !data.isEmpty else {
|
||
return nil
|
||
}
|
||
|
||
let stringBuilder = DTHTMLAttributedStringBuilder(html: data,
|
||
options: options,
|
||
// DTCoreText doesn't use document attributes anyway
|
||
documentAttributes: nil)
|
||
|
||
if let willFlushCallback = options[DTWillFlushBlockCallBack] as? DTHTMLAttributedStringBuilderWillFlushCallback {
|
||
stringBuilder?.willFlushCallback = willFlushCallback
|
||
}
|
||
|
||
return stringBuilder?.generatedAttributedString()
|
||
}
|
||
}
|