mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-17 02:58:07 +00:00
Add mentions to DynamicLinkText in ChatBubbleView
This commit is contained in:
parent
8d5c0ce79b
commit
990d2f36af
6 changed files with 101 additions and 25 deletions
|
|
@ -2,6 +2,6 @@ import Foundation
|
|||
|
||||
public enum AppGitInfo {
|
||||
public static let branch = "master"
|
||||
public static let commit = "61931138b"
|
||||
public static let commit = "8d5c0ce79"
|
||||
public static let tag = "6.1.0-alpha"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,16 @@
|
|||
<dict>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>org.linphone.phone</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>linphone-mention</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
|
|
|
|||
|
|
@ -179,7 +179,7 @@ struct ChatBubbleView: View {
|
|||
}
|
||||
|
||||
if !eventLogMessage.message.text.isEmpty {
|
||||
DynamicLinkText(text: eventLogMessage.message.text)
|
||||
DynamicLinkText(text: eventLogMessage.message.text, participantConversationModel: conversationViewModel.participantConversationModel)
|
||||
} else if eventLogMessage.message.isRetracted {
|
||||
Text(eventLogMessage.message.isOutgoing ? "conversation_message_content_deleted_by_us_label" : "conversation_message_content_deleted_label")
|
||||
.italic()
|
||||
|
|
@ -946,42 +946,81 @@ struct ChatBubbleView: View {
|
|||
|
||||
struct DynamicLinkText: View {
|
||||
let text: String
|
||||
let participantConversationModel: [ContactAvatarModel]
|
||||
|
||||
var body: some View {
|
||||
let components = text.components(separatedBy: " ")
|
||||
|
||||
Text(makeAttributedString(from: components))
|
||||
Text(makeAttributedString(from: text))
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
.multilineTextAlignment(.leading)
|
||||
.lineLimit(nil)
|
||||
.foregroundStyle(Color.grayMain2c700)
|
||||
.default_text_style(styleSize: 14)
|
||||
}
|
||||
|
||||
// Function to create an AttributedString with clickable links
|
||||
private func makeAttributedString(from components: [String]) -> AttributedString {
|
||||
var result = AttributedString("")
|
||||
for (index, component) in components.enumerated() {
|
||||
if let url = URL(string: component.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? ""),
|
||||
url.scheme == "http" || url.scheme == "https" {
|
||||
var attributedText = AttributedString(component)
|
||||
attributedText.link = url
|
||||
attributedText.foregroundColor = .blue
|
||||
attributedText.underlineStyle = .single
|
||||
result.append(attributedText)
|
||||
private func makeAttributedString(from text: String) -> AttributedString {
|
||||
var result = AttributedString()
|
||||
var currentWord = ""
|
||||
|
||||
for char in text {
|
||||
if char == " " || char == "\n" {
|
||||
appendWord(currentWord, to: &result)
|
||||
result.append(AttributedString(String(char)))
|
||||
currentWord = ""
|
||||
} else {
|
||||
result.append(AttributedString(component))
|
||||
}
|
||||
|
||||
// Add space between words except for the last one
|
||||
if index < components.count - 1 {
|
||||
result.append(AttributedString(" "))
|
||||
currentWord.append(char)
|
||||
}
|
||||
}
|
||||
|
||||
appendWord(currentWord, to: &result)
|
||||
return result
|
||||
}
|
||||
|
||||
private func appendWord(_ word: String, to result: inout AttributedString) {
|
||||
guard !word.isEmpty else { return }
|
||||
|
||||
// URL
|
||||
if
|
||||
let encoded = word.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed),
|
||||
let url = URL(string: encoded),
|
||||
["http", "https"].contains(url.scheme)
|
||||
{
|
||||
var link = AttributedString(word)
|
||||
link.link = url
|
||||
link.foregroundColor = .blue
|
||||
link.underlineStyle = .single
|
||||
result.append(link)
|
||||
return
|
||||
}
|
||||
|
||||
// Mention
|
||||
if isMention(word),
|
||||
let participant = participantConversationModel.first(where: {($0.address.dropFirst(4).split(separator: "@").first ?? "") == word.dropFirst()}),
|
||||
let mentionURL = URL(string: "linphone-mention://\(participant.address)")
|
||||
{
|
||||
var mention = AttributedString("@" + participant.name)
|
||||
mention.link = mentionURL
|
||||
mention.foregroundColor = Color.orangeMain500
|
||||
mention.font = .system(size: 14, weight: .semibold)
|
||||
result.append(mention)
|
||||
return
|
||||
}
|
||||
|
||||
// Text
|
||||
var normal = AttributedString(word)
|
||||
normal.foregroundColor = Color.grayMain2c700
|
||||
result.append(normal)
|
||||
}
|
||||
|
||||
private func isMention(_ word: String) -> Bool {
|
||||
guard word.first == "@", word.count > 1 else { return false }
|
||||
|
||||
let username = word.dropFirst()
|
||||
return username.allSatisfy {
|
||||
$0.isLetter || $0.isNumber || $0 == "." || $0 == "_"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
enum URLType {
|
||||
case name(String) // local file name of gif
|
||||
case url(URL) // remote url
|
||||
|
|
|
|||
|
|
@ -368,7 +368,6 @@ struct ConversationInfoFragment: View {
|
|||
let friendIndex = contactsManager.avatarListModel.first(
|
||||
where: {$0.addresses.contains(where: {$0 == addressConv})})
|
||||
|
||||
SharedMainViewModel.shared.displayedCall = nil
|
||||
SharedMainViewModel.shared.changeIndexView(indexViewInt: 0)
|
||||
|
||||
if friendIndex != nil {
|
||||
|
|
@ -381,6 +380,8 @@ struct ConversationInfoFragment: View {
|
|||
isShowEditContactFragmentAddress = String(participantConversationModel.address.dropFirst(4))
|
||||
}
|
||||
}
|
||||
|
||||
SharedMainViewModel.shared.displayedConversation = nil
|
||||
},
|
||||
label: {
|
||||
HStack {
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
import Foundation
|
||||
import linphonesw
|
||||
import Combine
|
||||
import SwiftUI
|
||||
|
||||
class URIHandler {
|
||||
|
||||
|
|
@ -28,6 +29,7 @@ class URIHandler {
|
|||
private static let secureCallSchemes = ["sips", "sips-linphone", "linphone-sips"]
|
||||
private static let configurationSchemes = ["linphone-config"]
|
||||
private static let sharedExtensionSchemes = ["linphone-message"]
|
||||
private static let mentionSchemes = ["linphone-mention"]
|
||||
|
||||
private static var uriHandlerCoreDelegate: CoreDelegateStub?
|
||||
|
||||
|
|
@ -66,6 +68,8 @@ class URIHandler {
|
|||
initiateConfiguration(url: url)
|
||||
} else if sharedExtensionSchemes.contains(scheme) {
|
||||
processReceivedFiles(url: url)
|
||||
} else if mentionSchemes.contains(scheme) {
|
||||
openContact(url: url)
|
||||
} else if scheme == SingleSignOnManager.shared.ssoRedirectUri.scheme {
|
||||
continueSSO(url: url)
|
||||
} else {
|
||||
|
|
@ -131,6 +135,28 @@ class URIHandler {
|
|||
SharedMainViewModel.shared.changeIndexView(indexViewInt: 2)
|
||||
}
|
||||
|
||||
private static func openContact(url: URL) {
|
||||
Log.info("[URIHandler] open contact from URL: \(url.resourceSpecifier)")
|
||||
|
||||
var urlString = url.resourceSpecifier
|
||||
if urlString.starts(with: "//") {
|
||||
urlString = String(urlString.dropFirst(2))
|
||||
}
|
||||
|
||||
print("[URIHandler] urlStringurlString : \(urlString)")
|
||||
|
||||
let friendIndex = ContactsManager.shared.avatarListModel.first(
|
||||
where: {$0.addresses.contains(where: {$0 == urlString})})
|
||||
|
||||
if friendIndex != nil {
|
||||
SharedMainViewModel.shared.displayedConversation = nil
|
||||
SharedMainViewModel.shared.changeIndexView(indexViewInt: 0)
|
||||
withAnimation {
|
||||
SharedMainViewModel.shared.displayedFriend = friendIndex
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static func continueSSO(url: URL) {
|
||||
if let authorizationFlow = SingleSignOnManager.shared.currentAuthorizationFlow,
|
||||
authorizationFlow.resumeExternalUserAgentFlow(with: url) {
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@
|
|||
"location" : "https://gitlab.linphone.org/BC/public/linphone-sdk-swift-ios.git",
|
||||
"state" : {
|
||||
"branch" : "alpha",
|
||||
"revision" : "81cb4712da29fffda8d7fb673685f6add05cf325"
|
||||
"revision" : "9e5a562e218530b2a38b858b5183446ceb1d6e35"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue