osx: linkify text, enable selection
This commit is contained in:
@@ -58,7 +58,7 @@ struct TextBubbleItemView: View
|
||||
let date: Date
|
||||
|
||||
private var isFromMe: Bool { sender.isMe }
|
||||
|
||||
|
||||
var body: some View {
|
||||
let bubbleColor: Color = isFromMe ? .blue : Color(NSColor(name: "grayish", dynamicProvider: { appearance in
|
||||
appearance.name == .darkAqua ? .darkGray : NSColor(white: 0.78, alpha: 1.0)
|
||||
@@ -67,7 +67,7 @@ struct TextBubbleItemView: View
|
||||
|
||||
BubbleView(sender: sender, date: date) {
|
||||
HStack {
|
||||
Text(text)
|
||||
Text(text.linkifiedAttributedString())
|
||||
.foregroundStyle(textColor)
|
||||
.multilineTextAlignment(.leading)
|
||||
}
|
||||
@@ -75,6 +75,7 @@ struct TextBubbleItemView: View
|
||||
.padding(.horizontal, 16.0)
|
||||
.padding(.vertical, 10.0)
|
||||
.background(bubbleColor)
|
||||
.textSelection(.enabled)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -219,14 +220,16 @@ struct SenderAttributionView: View
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate extension CGFloat {
|
||||
fileprivate extension CGFloat
|
||||
{
|
||||
static let dominantCornerRadius = 16.0
|
||||
static let minorCornerRadius = 4.0
|
||||
static let minimumBubbleHorizontalPadding = 80.0
|
||||
static let imageMaxWidth = 380.0
|
||||
}
|
||||
|
||||
fileprivate extension CGSize {
|
||||
fileprivate extension CGSize
|
||||
{
|
||||
var aspectRatio: CGFloat { width / height }
|
||||
}
|
||||
|
||||
@@ -239,3 +242,28 @@ fileprivate func preferredBubbleWidth(forAttachmentSize attachmentSize: CGSize?,
|
||||
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