Make addresses, links and phone numbers clickable in messages

This commit is contained in:
Garth Vander Houwen 2022-12-23 23:05:16 -08:00
parent 81e1b61443
commit 4d8a854351
4 changed files with 21 additions and 8 deletions

View file

@ -1301,18 +1301,30 @@ func textMessageAppPacket(packet: MeshPacket, connectedNode: Int64, context: NSM
if fetchedUsers.first(where: { $0.num == packet.from }) != nil {
newMessage.fromUser = fetchedUsers.first(where: { $0.num == packet.from })
}
let detector = try! NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue)
let types: NSTextCheckingResult.CheckingType = [.address, .link, .phoneNumber]
let detector = try! NSDataDetector(types: types.rawValue)
let matches = detector.matches(in: messageText, options: [], range: NSRange(location: 0, length: messageText.utf16.count))
if matches.count > 0 {
var messageWithLink = ""
var messageWithLink = messageText
for match in matches {
guard let range = Range(match.range, in: messageText) else { continue }
let url = messageText[range]
messageWithLink = messageText.replacingOccurrences(of: url, with: "[\(String(match.url?.host ?? "Link"))](\(url))")
if match.resultType == .address {
let address = messageText[range]
let urlEncodedAddress = address.addingPercentEncoding(withAllowedCharacters: .alphanumerics)
messageWithLink = messageWithLink.replacingOccurrences(of: address, with: "[\(address)](http://maps.apple.com/?address=\(urlEncodedAddress ?? ""))")
} else if match.resultType == .phoneNumber {
let phone = messageText[range]
messageWithLink = messageWithLink.replacingOccurrences(of: phone, with: "[\(phone)](tel:\(phone))")
} else if match.resultType == .link {
let url = messageText[range]
messageWithLink = messageWithLink.replacingOccurrences(of: url, with: "[\(String(match.url?.host ?? "Link"))](\(url))")
}
}
newMessage.messagePayload = messageWithLink
newMessage.messagePayload = messageText
newMessage.messagePayloadMarkdown = messageWithLink
} else {
newMessage.messagePayload = messageText
newMessage.messagePayloadMarkdown = messageText
}
newMessage.fromUser?.objectWillChange.send()
newMessage.toUser?.objectWillChange.send()

View file

@ -96,6 +96,7 @@
<attribute name="isEmoji" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="messageId" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="messagePayload" optional="YES" attributeType="String" defaultValueString=""/>
<attribute name="messagePayloadMarkdown" optional="YES" attributeType="String"/>
<attribute name="messageTimestamp" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="receivedACK" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="replyID" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>

View file

@ -60,7 +60,7 @@ struct ChannelMessageList: View {
.offset(y: -5)
}
VStack(alignment: currentUser ? .trailing : .leading) {
let markdownText: LocalizedStringKey = LocalizedStringKey.init(message.messagePayload ?? "EMPTY MESSAGE")
let markdownText: LocalizedStringKey = LocalizedStringKey.init(message.messagePayloadMarkdown ?? (message.messagePayload ?? "EMPTY MESSAGE"))
let skyBlue = Color(red: 0.4627, green: 0.8392, blue: 1.0)
Text(markdownText)
.tint(skyBlue)

View file

@ -61,8 +61,8 @@ struct UserMessageList: View {
.offset(y: -5)
}
VStack(alignment: currentUser ? .trailing : .leading) {
let markdownText: LocalizedStringKey = LocalizedStringKey.init(message.messagePayload ?? "EMPTY MESSAGE")
let skyBlue = Color(red: 0.4627, green: 0.8392, blue: 1.0)
let markdownText: LocalizedStringKey = LocalizedStringKey.init(message.messagePayloadMarkdown ?? (message.messagePayload ?? "EMPTY MESSAGE"))
let skyBlue = Color(red: 0.4627, green: 0.8392, blue: 1.0)
Text(markdownText)
.tint(skyBlue)
.padding(10)