Fixed link rects in RTL text

Fixed url validation for links containing Arabic
This commit is contained in:
Ilya Laktyushin 2019-08-10 23:34:55 +03:00
parent 555b1d8ede
commit d28434636d
6 changed files with 13 additions and 17 deletions

View File

@ -401,11 +401,11 @@ public final class TextNodeLayout: NSObject {
let lineRange = NSIntersectionRange(range, line.range) let lineRange = NSIntersectionRange(range, line.range)
if lineRange.length != 0 { if lineRange.length != 0 {
var leftOffset: CGFloat = 0.0 var leftOffset: CGFloat = 0.0
if lineRange.location != line.range.location { if lineRange.location != line.range.location || line.isRTL {
leftOffset = floor(CTLineGetOffsetForStringIndex(line.line, lineRange.location, nil)) leftOffset = floor(CTLineGetOffsetForStringIndex(line.line, lineRange.location, nil))
} }
var rightOffset: CGFloat = line.frame.width var rightOffset: CGFloat = line.frame.width
if lineRange.location + lineRange.length != line.range.length { if lineRange.location + lineRange.length != line.range.length || line.isRTL {
var secondaryOffset: CGFloat = 0.0 var secondaryOffset: CGFloat = 0.0
let rawOffset = CTLineGetOffsetForStringIndex(line.line, lineRange.location + lineRange.length, &secondaryOffset) let rawOffset = CTLineGetOffsetForStringIndex(line.line, lineRange.location + lineRange.length, &secondaryOffset)
rightOffset = ceil(rawOffset) rightOffset = ceil(rawOffset)
@ -417,7 +417,10 @@ public final class TextNodeLayout: NSObject {
lineFrame = displayLineFrame(frame: lineFrame, isRTL: line.isRTL, boundingRect: CGRect(origin: CGPoint(), size: self.size), cutout: self.cutout) lineFrame = displayLineFrame(frame: lineFrame, isRTL: line.isRTL, boundingRect: CGRect(origin: CGPoint(), size: self.size), cutout: self.cutout)
rects.append((lineFrame, CGRect(origin: CGPoint(x: lineFrame.minX + leftOffset + self.insets.left, y: lineFrame.minY + self.insets.top), size: CGSize(width: rightOffset - leftOffset, height: lineFrame.size.height)))) let width = abs(rightOffset - leftOffset)
if width > 1.0 {
rects.append((lineFrame, CGRect(origin: CGPoint(x: lineFrame.minX + (leftOffset < rightOffset ? leftOffset : rightOffset) + self.insets.left, y: lineFrame.minY + self.insets.top), size: CGSize(width: width, height: lineFrame.size.height))))
}
} }
} }
if !rects.isEmpty { if !rects.isEmpty {

View File

@ -105,8 +105,6 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
self.pickerView.timeZone = TimeZone.current self.pickerView.timeZone = TimeZone.current
self.pickerView.minuteInterval = 5 self.pickerView.minuteInterval = 5
self.pickerView.maximumDate = Date(timeIntervalSince1970: Double(Int32.max - 1))
self.pickerView.setValue(self.presentationData.theme.actionSheet.primaryTextColor, forKey: "textColor") self.pickerView.setValue(self.presentationData.theme.actionSheet.primaryTextColor, forKey: "textColor")
self.contentContainerNode.view.addSubview(self.pickerView) self.contentContainerNode.view.addSubview(self.pickerView)
@ -137,6 +135,10 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
components.second = 0 components.second = 0
let minute = (components.minute ?? 0) % 5 let minute = (components.minute ?? 0) % 5
if let date = calendar.date(byAdding: .day, value: 365, to: currentDate) {
self.pickerView.maximumDate = date
}
if let date = calendar.date(byAdding: .minute, value: 5 - minute, to: calendar.date(from: components)!) { if let date = calendar.date(byAdding: .minute, value: 5 - minute, to: calendar.date(from: components)!) {
self.pickerView.minimumDate = date self.pickerView.minimumDate = date
self.pickerView.date = date self.pickerView.date = date

View File

@ -178,7 +178,7 @@ class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDelegate, It
} }
let leftInset: CGFloat = 16.0 + params.leftInset let leftInset: CGFloat = 16.0 + params.leftInset
var rightInset: CGFloat = params.rightInset var rightInset: CGFloat = 16.0 + params.rightInset
if item.clearButton { if item.clearButton {
rightInset += 32.0 rightInset += 32.0

View File

@ -1,6 +0,0 @@
import Foundation
import UIKit
import AsyncDisplayKit
import Display
import Postbox

View File

@ -857,7 +857,6 @@
D0EC6D2C1EB9F58800EBF1C3 /* TouchDownGestureRecognizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0F69CFB1D6B87D30046BCD6 /* TouchDownGestureRecognizer.swift */; }; D0EC6D2C1EB9F58800EBF1C3 /* TouchDownGestureRecognizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0F69CFB1D6B87D30046BCD6 /* TouchDownGestureRecognizer.swift */; };
D0EC6D301EB9F58800EBF1C3 /* RadialProgressNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0F69DC41D6B89E10046BCD6 /* RadialProgressNode.swift */; }; D0EC6D301EB9F58800EBF1C3 /* RadialProgressNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0F69DC41D6B89E10046BCD6 /* RadialProgressNode.swift */; };
D0EC6D311EB9F58800EBF1C3 /* RadialTimeoutNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D00C7CE51E378FD00080C3D5 /* RadialTimeoutNode.swift */; }; D0EC6D311EB9F58800EBF1C3 /* RadialTimeoutNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D00C7CE51E378FD00080C3D5 /* RadialTimeoutNode.swift */; };
D0EC6D321EB9F58800EBF1C3 /* TextNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0F69DC21D6B89DA0046BCD6 /* TextNode.swift */; };
D0EC6D351EB9F58800EBF1C3 /* SearchBarNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0F69DCB1D6B8A0D0046BCD6 /* SearchBarNode.swift */; }; D0EC6D351EB9F58800EBF1C3 /* SearchBarNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0F69DCB1D6B8A0D0046BCD6 /* SearchBarNode.swift */; };
D0EC6D361EB9F58800EBF1C3 /* SearchBarPlaceholderNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0F69DCC1D6B8A0D0046BCD6 /* SearchBarPlaceholderNode.swift */; }; D0EC6D361EB9F58800EBF1C3 /* SearchBarPlaceholderNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0F69DCC1D6B8A0D0046BCD6 /* SearchBarPlaceholderNode.swift */; };
D0EC6D371EB9F58800EBF1C3 /* SearchDisplayController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0F69DCD1D6B8A0D0046BCD6 /* SearchDisplayController.swift */; }; D0EC6D371EB9F58800EBF1C3 /* SearchDisplayController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0F69DCD1D6B8A0D0046BCD6 /* SearchDisplayController.swift */; };
@ -2293,7 +2292,6 @@
D0F69CD61D6B87D30046BCD6 /* MediaManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MediaManager.swift; sourceTree = "<group>"; }; D0F69CD61D6B87D30046BCD6 /* MediaManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MediaManager.swift; sourceTree = "<group>"; };
D0F69CFB1D6B87D30046BCD6 /* TouchDownGestureRecognizer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TouchDownGestureRecognizer.swift; sourceTree = "<group>"; }; D0F69CFB1D6B87D30046BCD6 /* TouchDownGestureRecognizer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TouchDownGestureRecognizer.swift; sourceTree = "<group>"; };
D0F69DB91D6B88190046BCD6 /* TelegramUI.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = TelegramUI.xcconfig; path = TelegramUI/Config/TelegramUI.xcconfig; sourceTree = "<group>"; }; D0F69DB91D6B88190046BCD6 /* TelegramUI.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = TelegramUI.xcconfig; path = TelegramUI/Config/TelegramUI.xcconfig; sourceTree = "<group>"; };
D0F69DC21D6B89DA0046BCD6 /* TextNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextNode.swift; sourceTree = "<group>"; };
D0F69DC41D6B89E10046BCD6 /* RadialProgressNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RadialProgressNode.swift; sourceTree = "<group>"; }; D0F69DC41D6B89E10046BCD6 /* RadialProgressNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RadialProgressNode.swift; sourceTree = "<group>"; };
D0F69DCB1D6B8A0D0046BCD6 /* SearchBarNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchBarNode.swift; sourceTree = "<group>"; }; D0F69DCB1D6B8A0D0046BCD6 /* SearchBarNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchBarNode.swift; sourceTree = "<group>"; };
D0F69DCC1D6B8A0D0046BCD6 /* SearchBarPlaceholderNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchBarPlaceholderNode.swift; sourceTree = "<group>"; }; D0F69DCC1D6B8A0D0046BCD6 /* SearchBarPlaceholderNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchBarPlaceholderNode.swift; sourceTree = "<group>"; };
@ -4398,7 +4396,6 @@
D0477D191F617E4B00412B44 /* Video */, D0477D191F617E4B00412B44 /* Video */,
D0F69DC41D6B89E10046BCD6 /* RadialProgressNode.swift */, D0F69DC41D6B89E10046BCD6 /* RadialProgressNode.swift */,
D00C7CE51E378FD00080C3D5 /* RadialTimeoutNode.swift */, D00C7CE51E378FD00080C3D5 /* RadialTimeoutNode.swift */,
D0F69DC21D6B89DA0046BCD6 /* TextNode.swift */,
D0943AF51FDAAE7E001522CC /* MultipleAvatarsNode.swift */, D0943AF51FDAAE7E001522CC /* MultipleAvatarsNode.swift */,
D0568AAC1DF198130022E7DA /* AudioWaveformNode.swift */, D0568AAC1DF198130022E7DA /* AudioWaveformNode.swift */,
D0BC38621E3F9EFA0044D6FE /* EditableTokenListNode.swift */, D0BC38621E3F9EFA0044D6FE /* EditableTokenListNode.swift */,
@ -5431,7 +5428,6 @@
D0BE30492061C0F500FBE6D8 /* SecureIdAuthHeaderNode.swift in Sources */, D0BE30492061C0F500FBE6D8 /* SecureIdAuthHeaderNode.swift in Sources */,
D0EC6D301EB9F58800EBF1C3 /* RadialProgressNode.swift in Sources */, D0EC6D301EB9F58800EBF1C3 /* RadialProgressNode.swift in Sources */,
D0EC6D311EB9F58800EBF1C3 /* RadialTimeoutNode.swift in Sources */, D0EC6D311EB9F58800EBF1C3 /* RadialTimeoutNode.swift in Sources */,
D0EC6D321EB9F58800EBF1C3 /* TextNode.swift in Sources */,
D0BFAE5020AB2A1300793CF2 /* PeerBanTimeoutController.swift in Sources */, D0BFAE5020AB2A1300793CF2 /* PeerBanTimeoutController.swift in Sources */,
09CE950A2237B93500A7D2C3 /* SettingsSearchResultItem.swift in Sources */, 09CE950A2237B93500A7D2C3 /* SettingsSearchResultItem.swift in Sources */,
D0AE303922B1D3620058D3BC /* LegacyBridgeAudio.swift in Sources */, D0AE303922B1D3620058D3BC /* LegacyBridgeAudio.swift in Sources */,

View File

@ -32,7 +32,8 @@ public extension CharacterSet {
} }
public func isValidUrl(_ url: String) -> Bool { public func isValidUrl(_ url: String) -> Bool {
if let url = URL(string: url), ["http", "https"].contains(url.scheme), let host = url.host, host.contains(".") && url.user == nil {
if let escapedUrl = url.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed), let url = URL(string: escapedUrl), ["http", "https"].contains(url.scheme), let host = url.host, host.contains(".") && url.user == nil {
let components = host.components(separatedBy: ".") let components = host.components(separatedBy: ".")
let domain = (components.first ?? "") let domain = (components.first ?? "")
if domain.isEmpty { if domain.isEmpty {