mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-07-02 04:51:49 +00:00
android, desktop, ios: open known contact on name lookup; surface prepared contact
Name search opens the contact (not list-filter); resolved/prepared contacts and groups are added to the chat list so they're visible and openable. Kotlin compile-verified; iOS edits pattern-matched, pending Xcode build.
This commit is contained in:
@@ -216,8 +216,9 @@ private func handleTextTaps(
|
||||
if index >= range.location && index < range.location + range.length {
|
||||
if attrs[nameAttrKey] is SimplexNameInfo {
|
||||
// Route the tapped name through the same connect flow as a link;
|
||||
// planAndConnect resolves it on the core (name target).
|
||||
planAndConnect(s.attributedSubstring(from: range).string, theme: theme, dismiss: false)
|
||||
// planAndConnect resolves it on the core (name target). This runs
|
||||
// in a free function with no view context, so use the global theme.
|
||||
planAndConnect(s.attributedSubstring(from: range).string, theme: AppTheme.shared, dismiss: false)
|
||||
} else if let url = attrs[linkAttrKey] as? String {
|
||||
linkURL = url
|
||||
browser = attrs[webLinkAttrKey] != nil
|
||||
|
||||
@@ -684,8 +684,18 @@ struct ChatListSearchBar: View {
|
||||
searchChatFilteredBySimplexLink = nil
|
||||
connect(text)
|
||||
case let .name(text, _):
|
||||
// A name lookup means "take me to this contact": open it (visible prompt),
|
||||
// unlike a pasted link in search which filters the list — so no filterKnownContact.
|
||||
searchFocussed = false
|
||||
connect(text)
|
||||
planAndConnect(
|
||||
text,
|
||||
theme: theme,
|
||||
dismiss: false,
|
||||
cleanup: {
|
||||
searchText = ""
|
||||
searchFocussed = false
|
||||
}
|
||||
)
|
||||
case .none:
|
||||
if t != "" {
|
||||
searchFocussed = true
|
||||
|
||||
@@ -390,8 +390,18 @@ struct ContactsListSearchBar: View {
|
||||
searchChatFilteredBySimplexLink = nil
|
||||
connect(text)
|
||||
case let .name(text, _):
|
||||
// A name lookup means "take me to this contact": open it (visible prompt),
|
||||
// unlike a pasted link in search which filters the list — so no filterKnownContact.
|
||||
searchFocussed = false
|
||||
connect(text)
|
||||
planAndConnect(
|
||||
text,
|
||||
theme: theme,
|
||||
dismiss: true,
|
||||
cleanup: {
|
||||
searchText = ""
|
||||
searchFocussed = false
|
||||
}
|
||||
)
|
||||
case .none:
|
||||
if t != "" {
|
||||
searchFocussed = true
|
||||
|
||||
@@ -1463,6 +1463,12 @@ func planAndConnect(
|
||||
case let .known(contact):
|
||||
logger.debug("planAndConnect, .contactAddress, .known")
|
||||
await MainActor.run {
|
||||
// A name-resolved contact is prepared in the store but not yet in the
|
||||
// chat list (link-prepared chats arrive via NewPreparedChat). Surface it
|
||||
// so it's visible and openable; no-op if already present.
|
||||
if ChatModel.shared.getContactChat(contact.contactId) == nil {
|
||||
ChatModel.shared.addChat(Chat(chatInfo: .direct(contact: contact)))
|
||||
}
|
||||
if let f = filterKnownContact {
|
||||
f(contact)
|
||||
} else {
|
||||
@@ -1542,6 +1548,11 @@ func planAndConnect(
|
||||
case let .known(groupInfo):
|
||||
logger.debug("planAndConnect, .groupLink, .known")
|
||||
await MainActor.run {
|
||||
// Same as .contactAddress .known: surface a name-resolved (prepared)
|
||||
// group in the chat list so it's visible and openable.
|
||||
if ChatModel.shared.getGroupChat(groupInfo.groupId) == nil {
|
||||
ChatModel.shared.addChat(Chat(chatInfo: .group(groupInfo: groupInfo, groupChatScope: nil)))
|
||||
}
|
||||
if let f = filterKnownGroup {
|
||||
f(groupInfo)
|
||||
} else {
|
||||
|
||||
+11
-1
@@ -801,8 +801,18 @@ private fun ChatListSearchBar(listState: LazyListState, searchText: MutableState
|
||||
connect(target.text, searchChatFilteredBySimplexLink) { searchText.value = TextFieldValue() }
|
||||
}
|
||||
is ConnectTarget.Name -> {
|
||||
// A name lookup means "take me to this contact": open the chat if
|
||||
// it's already known (visible prompt), unlike a pasted link which
|
||||
// filters the list. So no filterKnownContact here.
|
||||
hideKeyboard(view)
|
||||
connect(target.text, searchChatFilteredBySimplexLink) { searchText.value = TextFieldValue() }
|
||||
withBGApi {
|
||||
planAndConnect(
|
||||
chatModel.remoteHostId(),
|
||||
target.text,
|
||||
close = null,
|
||||
cleanup = { searchText.value = TextFieldValue() },
|
||||
)
|
||||
}
|
||||
}
|
||||
null -> if (!searchShowingSimplexLink.value || it.isEmpty()) {
|
||||
if (it.isNotEmpty()) {
|
||||
|
||||
+11
@@ -201,6 +201,12 @@ private suspend fun planAndConnectTask(
|
||||
is ContactAddressPlan.Known -> {
|
||||
Log.d(TAG, "planAndConnect, .ContactAddress, .Known")
|
||||
val contact = connectionPlan.contactAddressPlan.contact
|
||||
// A name-resolved contact is prepared in the store but not yet in the
|
||||
// chat list (link-prepared chats arrive via NewPreparedChat). Surface it
|
||||
// so it's visible and openable; no-op if already present.
|
||||
if (chatModel.getContactChat(contact.contactId) == null) {
|
||||
chatModel.chatsContext.addChat(Chat(remoteHostId = rhId, chatInfo = ChatInfo.Direct(contact), chatItems = emptyList()))
|
||||
}
|
||||
if (filterKnownContact != null) {
|
||||
filterKnownContact(contact)
|
||||
} else {
|
||||
@@ -285,6 +291,11 @@ private suspend fun planAndConnectTask(
|
||||
is GroupLinkPlan.Known -> {
|
||||
Log.d(TAG, "planAndConnect, .GroupLink, .Known")
|
||||
val groupInfo = connectionPlan.groupLinkPlan.groupInfo
|
||||
// Same as ContactAddress.Known: surface a name-resolved (prepared)
|
||||
// group in the chat list so it's visible and openable.
|
||||
if (chatModel.getGroupChat(groupInfo.groupId) == null) {
|
||||
chatModel.chatsContext.addChat(Chat(remoteHostId = rhId, chatInfo = ChatInfo.Group(groupInfo, groupChatScope = null), chatItems = emptyList()))
|
||||
}
|
||||
if (filterKnownGroup != null) {
|
||||
filterKnownGroup(groupInfo)
|
||||
} else {
|
||||
|
||||
+11
-6
@@ -537,13 +537,18 @@ private fun ContactsSearchBar(
|
||||
)
|
||||
}
|
||||
is ConnectTarget.Name -> {
|
||||
// A name lookup means "take me to this contact": open the chat if
|
||||
// it's already known (visible prompt), unlike a pasted link which
|
||||
// filters the list. So no filterKnownContact here.
|
||||
hideKeyboard(view)
|
||||
connect(
|
||||
link = target.text,
|
||||
searchChatFilteredBySimplexLink = searchChatFilteredBySimplexLink,
|
||||
close = close,
|
||||
cleanup = { searchText.value = TextFieldValue() }
|
||||
)
|
||||
withBGApi {
|
||||
planAndConnect(
|
||||
chatModel.remoteHostId(),
|
||||
target.text,
|
||||
close = close,
|
||||
cleanup = { searchText.value = TextFieldValue() },
|
||||
)
|
||||
}
|
||||
}
|
||||
null -> if (!searchShowingSimplexLink.value || it.isEmpty()) {
|
||||
if (it.isNotEmpty()) {
|
||||
|
||||
Reference in New Issue
Block a user