osx: linkify text, enable selection
This commit is contained in:
@@ -67,7 +67,7 @@ struct TextBubbleItemView: View
|
|||||||
|
|
||||||
BubbleView(sender: sender, date: date) {
|
BubbleView(sender: sender, date: date) {
|
||||||
HStack {
|
HStack {
|
||||||
Text(text)
|
Text(text.linkifiedAttributedString())
|
||||||
.foregroundStyle(textColor)
|
.foregroundStyle(textColor)
|
||||||
.multilineTextAlignment(.leading)
|
.multilineTextAlignment(.leading)
|
||||||
}
|
}
|
||||||
@@ -75,6 +75,7 @@ struct TextBubbleItemView: View
|
|||||||
.padding(.horizontal, 16.0)
|
.padding(.horizontal, 16.0)
|
||||||
.padding(.vertical, 10.0)
|
.padding(.vertical, 10.0)
|
||||||
.background(bubbleColor)
|
.background(bubbleColor)
|
||||||
|
.textSelection(.enabled)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -219,14 +220,16 @@ struct SenderAttributionView: View
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fileprivate extension CGFloat {
|
fileprivate extension CGFloat
|
||||||
|
{
|
||||||
static let dominantCornerRadius = 16.0
|
static let dominantCornerRadius = 16.0
|
||||||
static let minorCornerRadius = 4.0
|
static let minorCornerRadius = 4.0
|
||||||
static let minimumBubbleHorizontalPadding = 80.0
|
static let minimumBubbleHorizontalPadding = 80.0
|
||||||
static let imageMaxWidth = 380.0
|
static let imageMaxWidth = 380.0
|
||||||
}
|
}
|
||||||
|
|
||||||
fileprivate extension CGSize {
|
fileprivate extension CGSize
|
||||||
|
{
|
||||||
var aspectRatio: CGFloat { width / height }
|
var aspectRatio: CGFloat { width / height }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,3 +242,28 @@ fileprivate func preferredBubbleWidth(forAttachmentSize attachmentSize: CGSize?,
|
|||||||
return 200.0 // fallback
|
return 200.0 // fallback
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fileprivate extension String
|
||||||
|
{
|
||||||
|
func linkifiedAttributedString() -> AttributedString {
|
||||||
|
var attributed = AttributedString(self)
|
||||||
|
guard let detector = try? NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue) else {
|
||||||
|
return attributed
|
||||||
|
}
|
||||||
|
|
||||||
|
let nsText = self as NSString
|
||||||
|
let fullRange = NSRange(location: 0, length: nsText.length)
|
||||||
|
detector.enumerateMatches(in: self, options: [], range: fullRange) { result, _, _ in
|
||||||
|
guard let result, let url = result.url,
|
||||||
|
let swiftRange = Range(result.range, in: self),
|
||||||
|
let start = AttributedString.Index(swiftRange.lowerBound, within: attributed),
|
||||||
|
let end = AttributedString.Index(swiftRange.upperBound, within: attributed) else { return }
|
||||||
|
|
||||||
|
attributed[start..<end].link = url
|
||||||
|
attributed[start..<end].foregroundColor = NSColor.textColor
|
||||||
|
attributed[start..<end].underlineStyle = .single
|
||||||
|
}
|
||||||
|
|
||||||
|
return attributed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user