element-ios/Riot/Modules/MatrixKit/Categories/NSString+MatrixKit.swift

67 lines
2.7 KiB
Swift
Raw Normal View History

//
// Copyright 2020 The Matrix.org Foundation C.I.C
//
// 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 MatrixSDK.MXLog
public extension NSString {
/// Gets the first URL contained in the string ignoring any links to hosts defined in
/// the `firstURLDetectionIgnoredHosts` property of `MXKAppSettings`.
/// - Returns: A URL if detected, otherwise nil.
@objc func mxk_firstURLDetected() -> NSURL? {
let hosts = MXKAppSettings.standard().firstURLDetectionIgnoredHosts ?? []
return mxk_firstURLDetected(ignoring: hosts)
}
/// Gets the first URL contained in the string ignoring any links to the specified hosts.
/// - Returns: A URL if detected, otherwise nil.
@objc func mxk_firstURLDetected(ignoring ignoredHosts: [String]) -> NSURL? {
guard let linkDetector = try? NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue) else {
MXLog.debug("[NSString+URLDetector]: Unable to create link detector.")
return nil
}
var detectedURL: NSURL?
// enumerate all urls that were found in the string to ensure
// detection of a valid link if there are invalid links preceding it
linkDetector.enumerateMatches(in: self as String,
options: [],
range: NSRange(location: 0, length: self.length)) { match, flags, stop in
guard let match = match else { return }
// check if the match is a valid url
let urlString = self.substring(with: match.range)
guard let url = NSURL(string: urlString) else { return }
// ensure the match is a web link
guard let scheme = url.scheme?.lowercased(),
scheme == "https" || scheme == "http"
else { return }
// discard any links to ignored hosts
guard let host = url.host?.lowercased(),
!ignoredHosts.contains(host)
else { return }
detectedURL = url
stop.pointee = true
}
return detectedURL
}
}