mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-10-10 22:18:16 +00:00
align and simplify core/UI/UXcanvas
This commit is contained in:
+6
-4
@@ -1633,7 +1633,7 @@ object ChatController {
|
||||
suspend fun apiConnectPlan(rh: Long?, connLink: String, resolveMode: PlanResolveMode = PlanResolveMode.PRMUnknown, linkOwnerSig: LinkOwnerSig? = null, inProgress: MutableState<Boolean>): ConnectionPlanResult? {
|
||||
val userId = kotlin.runCatching { currentUserId("apiConnectPlan") }.getOrElse { return null }
|
||||
val r = sendCmdWithRetry(rh, CC.APIConnectPlan(userId, connLink, resolveMode, linkOwnerSig), inProgress = inProgress)
|
||||
if (r is API.Result && r.res is CR.CRConnectionPlan) return ConnectionPlanResult(r.res.connLink, r.res.planSimplexName, r.res.otherSimplexName, r.res.connectionPlan)
|
||||
if (r is API.Result && r.res is CR.CRConnectionPlan) return ConnectionPlanResult(r.res.connLink, r.res.planSimplexName, r.res.otherSimplexName, r.res.connectionPlan, r.res.localChats, r.res.offerLookup)
|
||||
// a PRMNever (typing) search that matches nothing locally is not an error to surface
|
||||
if (r is API.Error && r.err is ChatError.ChatErrorChat && r.err.errorType is ChatErrorType.NotResolvedLocally) return null
|
||||
if (inProgress.value && r != null) apiConnectResponseAlert(r)
|
||||
@@ -6712,7 +6712,7 @@ sealed class CR {
|
||||
@Serializable @SerialName("invitation") class Invitation(val user: UserRef, val connLinkInvitation: CreatedConnLink, val connection: PendingContactConnection): CR()
|
||||
@Serializable @SerialName("connectionIncognitoUpdated") class ConnectionIncognitoUpdated(val user: UserRef, val toConnection: PendingContactConnection): CR()
|
||||
@Serializable @SerialName("connectionUserChanged") class ConnectionUserChanged(val user: UserRef, val fromConnection: PendingContactConnection, val toConnection: PendingContactConnection, val newUser: UserRef): CR()
|
||||
@Serializable @SerialName("connectionPlan") class CRConnectionPlan(val user: UserRef, val connLink: CreatedConnLink? = null, val planSimplexName: SimplexNameInfo? = null, val otherSimplexName: SimplexNameInfo? = null, val connectionPlan: ConnectionPlan): CR()
|
||||
@Serializable @SerialName("connectionPlan") class CRConnectionPlan(val user: UserRef, val connLink: CreatedConnLink? = null, val planSimplexName: SimplexNameInfo? = null, val otherSimplexName: SimplexNameInfo? = null, val connectionPlan: ConnectionPlan, val localChats: List<ChatInfo> = emptyList(), val offerLookup: Boolean = false): CR()
|
||||
@Serializable @SerialName("newPreparedChat") class NewPreparedChat(val user: UserRef, val chat: Chat): CR()
|
||||
@Serializable @SerialName("contactUserChanged") class ContactUserChanged(val user: UserRef, val fromContact: Contact, val newUser: UserRef, val toContact: Contact): CR()
|
||||
@Serializable @SerialName("groupUserChanged") class GroupUserChanged(val user: UserRef, val fromGroup: GroupInfo, val newUser: UserRef, val toGroup: GroupInfo): CR()
|
||||
@@ -7426,6 +7426,8 @@ data class ConnectionPlanResult(
|
||||
val planSimplexName: SimplexNameInfo?,
|
||||
val otherSimplexName: SimplexNameInfo?,
|
||||
val connectionPlan: ConnectionPlan,
|
||||
val localChats: List<ChatInfo>,
|
||||
val offerLookup: Boolean,
|
||||
)
|
||||
|
||||
// APIConnectPlan resolution scope; PRMNever is local-store-only (no network), used for per-keystroke name search
|
||||
@@ -7472,7 +7474,7 @@ sealed class InvitationLinkPlan {
|
||||
|
||||
@Serializable
|
||||
sealed class ContactAddressPlan {
|
||||
@Serializable @SerialName("ok") class Ok(val contactSLinkData_: ContactShortLinkData? = null, val ownerVerification: OwnerVerification? = null, val addressChanged: Boolean = false, val existingChat_: ChatInfo? = null): ContactAddressPlan()
|
||||
@Serializable @SerialName("ok") class Ok(val contactSLinkData_: ContactShortLinkData? = null, val ownerVerification: OwnerVerification? = null, val addressChanged: Boolean = false): ContactAddressPlan()
|
||||
@Serializable @SerialName("ownLink") object OwnLink: ContactAddressPlan()
|
||||
@Serializable @SerialName("connectingConfirmReconnect") object ConnectingConfirmReconnect: ContactAddressPlan()
|
||||
@Serializable @SerialName("connectingProhibit") class ConnectingProhibit(val contact: Contact): ContactAddressPlan()
|
||||
@@ -7482,7 +7484,7 @@ sealed class ContactAddressPlan {
|
||||
|
||||
@Serializable
|
||||
sealed class GroupLinkPlan {
|
||||
@Serializable @SerialName("ok") class Ok(val groupSLinkInfo_: GroupShortLinkInfo? = null, val groupSLinkData_: GroupShortLinkData? = null, val ownerVerification: OwnerVerification? = null, val addressChanged: Boolean = false, val existingChat_: ChatInfo? = null): GroupLinkPlan()
|
||||
@Serializable @SerialName("ok") class Ok(val groupSLinkInfo_: GroupShortLinkInfo? = null, val groupSLinkData_: GroupShortLinkData? = null, val ownerVerification: OwnerVerification? = null, val addressChanged: Boolean = false): GroupLinkPlan()
|
||||
@Serializable @SerialName("ownLink") class OwnLink(val groupInfo: GroupInfo): GroupLinkPlan()
|
||||
@Serializable @SerialName("connectingConfirmReconnect") object ConnectingConfirmReconnect: GroupLinkPlan()
|
||||
@Serializable @SerialName("connectingProhibit") class ConnectingProhibit(val groupInfo_: GroupInfo? = null): GroupLinkPlan()
|
||||
|
||||
+10
-33
@@ -850,17 +850,16 @@ private fun ChatListSearchBar(listState: LazyListState, searchText: MutableState
|
||||
searchChatFilteredBySimplexLink.value = emptySet()
|
||||
if (candidate != null) {
|
||||
// resolve the name locally on each keystroke, debounced; collectLatest cancels the in-flight
|
||||
// search when the next keystroke arrives. A bare name can be a contact or a channel, so search
|
||||
// both and filter every known chat found; drop the row only when both types are already known.
|
||||
// search when the next keystroke arrives.
|
||||
delay(NAME_SEARCH_DEBOUNCE_MS)
|
||||
val rhId = chatModel.remoteHostId()
|
||||
val inProgress = mutableStateOf(false) // background search: no spinner, no error alerts
|
||||
val targets = if (candidate.startsWith("@") || candidate.startsWith("#")) listOf(candidate) else listOf("@$candidate", "#$candidate")
|
||||
val ids = targets.mapNotNull { name ->
|
||||
knownChatId(rhId, chatModel.controller.apiConnectPlan(rhId, name, PlanResolveMode.PRMNever, inProgress = inProgress))
|
||||
val result = chatModel.controller.apiConnectPlan(rhId, candidate, PlanResolveMode.PRMNever, inProgress = inProgress)
|
||||
if (result != null) {
|
||||
addMissingChats(rhId, result.localChats)
|
||||
searchChatFilteredBySimplexLink.value = result.localChats.map { it.id }.toSet()
|
||||
if (!result.offerLookup) connectNameCandidate.value = null
|
||||
}
|
||||
searchChatFilteredBySimplexLink.value = ids.toSet()
|
||||
if (ids.size == targets.size) connectNameCandidate.value = null
|
||||
} else if (!searchShowingSimplexLink.value || it.isEmpty()) {
|
||||
if (it.isNotEmpty()) {
|
||||
focusRequester.requestFocus()
|
||||
@@ -889,8 +888,10 @@ private fun connect(link: String, searchChatFilteredBySimplexLink: MutableState<
|
||||
planAndConnect(
|
||||
chatModel.remoteHostId(),
|
||||
link,
|
||||
filterKnownContact = { searchChatFilteredBySimplexLink.value = setOf(it.id) },
|
||||
filterKnownGroup = { searchChatFilteredBySimplexLink.value = setOf(it.id) },
|
||||
filterChats = { chats ->
|
||||
searchChatFilteredBySimplexLink.value = chats.map { it.id }.toSet()
|
||||
true
|
||||
},
|
||||
close = null,
|
||||
cleanup = cleanup,
|
||||
)
|
||||
@@ -1162,30 +1163,6 @@ internal fun nameSearchCandidate(str: String): String? {
|
||||
}
|
||||
}
|
||||
|
||||
// The chat id a local (PRMNever) search resolved to — a contact, a business, or a channel — or null on a miss.
|
||||
// The core returns the correct type for @ vs # (getContactToConnect / type-filtered getGroupToConnect), so no
|
||||
// client-side type check is needed.
|
||||
internal suspend fun knownChatId(rhId: Long?, result: ConnectionPlanResult?): String? = when (val plan = result?.connectionPlan) {
|
||||
is ConnectionPlan.ContactAddress -> (plan.contactAddressPlan as? ContactAddressPlan.Known)?.contact?.let { contact ->
|
||||
// a name-resolved chat may be prepared in the store but not yet listed, so add it (as the tap path does)
|
||||
if (chatModel.getContactChat(contact.contactId) == null) {
|
||||
chatModel.chatsContext.addChat(Chat(remoteHostId = rhId, chatInfo = ChatInfo.Direct(contact), chatItems = emptyList()))
|
||||
}
|
||||
contact.id
|
||||
}
|
||||
is ConnectionPlan.GroupLink -> (when (val g = plan.groupLinkPlan) {
|
||||
is GroupLinkPlan.Known -> g.groupInfo
|
||||
is GroupLinkPlan.OwnLink -> g.groupInfo
|
||||
else -> null
|
||||
})?.let { gInfo ->
|
||||
if (chatModel.getGroupChat(gInfo.groupId) == null) {
|
||||
chatModel.chatsContext.addChat(Chat(remoteHostId = rhId, chatInfo = ChatInfo.Group(gInfo, groupChatScope = null), chatItems = emptyList()))
|
||||
}
|
||||
gInfo.id
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
|
||||
// The list tags and the connect-by-name row share one slot. When there is no name, the tags show; on
|
||||
// mobile the row replaces the tags while shown. On desktop both show, arranged by the caller (which
|
||||
// knows whether the search bar is above or below), passed as desktopView.
|
||||
|
||||
+57
-79
@@ -34,8 +34,7 @@ suspend fun planAndConnect(
|
||||
linkOwnerSig: LinkOwnerSig? = null,
|
||||
close: (() -> Unit)?,
|
||||
cleanup: (() -> Unit)? = null,
|
||||
filterKnownContact: ((Contact) -> Unit)? = null,
|
||||
filterKnownGroup: ((GroupInfo) -> Unit)? = null,
|
||||
filterChats: ((List<ChatInfo>) -> Boolean)? = null,
|
||||
): CompletableDeferred<Boolean> {
|
||||
when (val target = strConnectTarget(shortOrFullLink.trim())) {
|
||||
is ConnectTarget.Link -> {
|
||||
@@ -58,7 +57,7 @@ suspend fun planAndConnect(
|
||||
inProgress.value = false
|
||||
cleanup?.invoke()
|
||||
}
|
||||
return planAndConnectTask(rhId, shortOrFullLink, linkOwnerSig, close, cleanup, filterKnownContact, filterKnownGroup, inProgress)
|
||||
return planAndConnectTask(rhId, shortOrFullLink, linkOwnerSig, close, cleanup, filterChats, inProgress)
|
||||
}
|
||||
|
||||
private fun nameDate(t: Instant): String =
|
||||
@@ -156,8 +155,7 @@ private suspend fun planAndConnectTask(
|
||||
linkOwnerSig: LinkOwnerSig? = null,
|
||||
close: (() -> Unit)?,
|
||||
cleanup: (() -> Unit)? = null,
|
||||
filterKnownContact: ((Contact) -> Unit)? = null,
|
||||
filterKnownGroup: ((GroupInfo) -> Unit)? = null,
|
||||
filterChats: ((List<ChatInfo>) -> Boolean)? = null,
|
||||
inProgress: MutableState<Boolean>
|
||||
): CompletableDeferred<Boolean> {
|
||||
val completable = CompletableDeferred<Boolean>()
|
||||
@@ -174,7 +172,8 @@ private suspend fun planAndConnectTask(
|
||||
connectProgressManager.stopConnectProgress()
|
||||
if (!inProgress.value) { return completable }
|
||||
if (result != null) {
|
||||
val (connectionLink, planSimplexName, otherSimplexName, connectionPlan) = result
|
||||
val (connectionLink, planSimplexName, otherSimplexName, connectionPlan, localChats) = result
|
||||
addMissingChats(rhId, localChats)
|
||||
val target = strConnectTarget(shortOrFullLink.trim())
|
||||
val linkText = if (target is ConnectTarget.Link) "<br><br><u>${target.linkText}</u>" else ""
|
||||
// the name can also resolve to the other kind; its type picks the verb, its short form the label and target
|
||||
@@ -190,22 +189,7 @@ private suspend fun planAndConnectTask(
|
||||
else -> null to null
|
||||
}
|
||||
if (nameWarning != null && nameDomain != null) {
|
||||
val knownContact = ((connectionPlan as? ConnectionPlan.ContactAddress)?.contactAddressPlan as? ContactAddressPlan.Known)?.contact
|
||||
val knownGroup = ((connectionPlan as? ConnectionPlan.GroupLink)?.groupLinkPlan as? GroupLinkPlan.Known)?.groupInfo
|
||||
var openExisting: (() -> Unit)? = null
|
||||
if (knownContact != null) {
|
||||
if (chatModel.getContactChat(knownContact.contactId) == null) {
|
||||
chatModel.chatsContext.addChat(Chat(remoteHostId = rhId, chatInfo = ChatInfo.Direct(knownContact), chatItems = emptyList()))
|
||||
}
|
||||
if (filterKnownContact != null) filterKnownContact(knownContact)
|
||||
else openExisting = { openKnownContact(chatModel, rhId, close, knownContact) }
|
||||
} else if (knownGroup != null) {
|
||||
if (chatModel.getGroupChat(knownGroup.groupId) == null) {
|
||||
chatModel.chatsContext.addChat(Chat(remoteHostId = rhId, chatInfo = ChatInfo.Group(knownGroup, groupChatScope = null), chatItems = emptyList()))
|
||||
}
|
||||
if (filterKnownGroup != null) filterKnownGroup(knownGroup)
|
||||
else openExisting = { openKnownGroup(chatModel, rhId, close, knownGroup) }
|
||||
}
|
||||
val openExisting: (() -> Unit)? = localChats.firstOrNull()?.takeIf { filterChats?.invoke(localChats) != true }?.let { chatInfo -> { openChat_(chatModel, rhId, close, Chat(remoteHostId = rhId, chatInfo = chatInfo, chatItems = emptyList())) } }
|
||||
showNameWarningAlert(rhId, nameDomain, nameWarning, openExisting, cleanup)
|
||||
return completable
|
||||
}
|
||||
@@ -251,9 +235,7 @@ private suspend fun planAndConnectTask(
|
||||
Log.d(TAG, "planAndConnect, .InvitationLink, .Connecting")
|
||||
val contact = connectionPlan.invitationLinkPlan.contact_
|
||||
if (contact != null) {
|
||||
if (filterKnownContact != null) {
|
||||
filterKnownContact(contact)
|
||||
} else {
|
||||
if (filterChats?.invoke(localChats) != true) {
|
||||
showOpenKnownContactAlert(chatModel, rhId, close, contact)
|
||||
cleanup()
|
||||
}
|
||||
@@ -269,9 +251,7 @@ private suspend fun planAndConnectTask(
|
||||
is InvitationLinkPlan.Known -> {
|
||||
Log.d(TAG, "planAndConnect, .InvitationLink, .Known")
|
||||
val contact = connectionPlan.invitationLinkPlan.contact
|
||||
if (filterKnownContact != null) {
|
||||
filterKnownContact(contact)
|
||||
} else {
|
||||
if (filterChats?.invoke(localChats) != true) {
|
||||
showOpenKnownContactAlert(chatModel, rhId, close, contact)
|
||||
cleanup()
|
||||
}
|
||||
@@ -290,9 +270,10 @@ private suspend fun planAndConnectTask(
|
||||
connectOtherButton = connectOtherButton,
|
||||
connectOtherLink = connectOtherLink,
|
||||
addressChanged = connectionPlan.contactAddressPlan.addressChanged,
|
||||
openExistingChat = if (filterKnownContact == null) connectionPlan.contactAddressPlan.existingChat_?.let { chatInfo -> { openChat_(chatModel, rhId, close, Chat(remoteHostId = rhId, chatInfo = chatInfo, chatItems = emptyList())); cleanup() } } else null,
|
||||
openExistingChat = localChats.firstOrNull()?.takeIf { filterChats?.invoke(localChats) != true }?.let { chatInfo -> { openChat_(chatModel, rhId, close, Chat(remoteHostId = rhId, chatInfo = chatInfo, chatItems = emptyList())); cleanup() } },
|
||||
close,
|
||||
cleanup
|
||||
cleanup,
|
||||
filterChats
|
||||
)
|
||||
} else {
|
||||
Log.d(TAG, "planAndConnect, .ContactAddress, .Ok, no short link data")
|
||||
@@ -305,6 +286,7 @@ private suspend fun planAndConnectTask(
|
||||
ownerVerification = connectionPlan.contactAddressPlan.ownerVerification,
|
||||
connectOtherButton = connectOtherButton,
|
||||
connectOtherLink = connectOtherLink,
|
||||
filterChats = filterChats,
|
||||
)
|
||||
}
|
||||
ContactAddressPlan.OwnLink -> {
|
||||
@@ -317,6 +299,7 @@ private suspend fun planAndConnectTask(
|
||||
cleanup = cleanup,
|
||||
connectOtherButton = connectOtherButton,
|
||||
connectOtherLink = connectOtherLink,
|
||||
filterChats = filterChats,
|
||||
)
|
||||
}
|
||||
ContactAddressPlan.ConnectingConfirmReconnect -> {
|
||||
@@ -329,32 +312,24 @@ private suspend fun planAndConnectTask(
|
||||
cleanup = cleanup,
|
||||
connectOtherButton = connectOtherButton,
|
||||
connectOtherLink = connectOtherLink,
|
||||
filterChats = filterChats,
|
||||
)
|
||||
}
|
||||
is ContactAddressPlan.ConnectingProhibit -> {
|
||||
Log.d(TAG, "planAndConnect, .ContactAddress, .ConnectingProhibit")
|
||||
val contact = connectionPlan.contactAddressPlan.contact
|
||||
if (filterKnownContact != null) {
|
||||
filterKnownContact(contact)
|
||||
} else {
|
||||
showOpenKnownContactAlert(chatModel, rhId, close, contact, planSimplexName = planSimplexName, connectOtherButton = connectOtherButton, connectOtherLink = connectOtherLink)
|
||||
if (filterChats?.invoke(localChats) != true) {
|
||||
showOpenKnownContactAlert(chatModel, rhId, close, contact, planSimplexName = planSimplexName, connectOtherButton = connectOtherButton, connectOtherLink = connectOtherLink, filterChats = filterChats)
|
||||
cleanup()
|
||||
}
|
||||
}
|
||||
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)
|
||||
if (otherSimplexName != null && connectOtherButton != null) showOtherNameAlert(rhId, otherSimplexName, connectOtherButton, close, cleanup)
|
||||
if (filterChats?.invoke(localChats) == true) {
|
||||
if (otherSimplexName != null && connectOtherButton != null) showOtherNameAlert(rhId, otherSimplexName, connectOtherButton, close, cleanup, filterChats)
|
||||
} else {
|
||||
showOpenKnownContactAlert(chatModel, rhId, close, contact, planSimplexName = planSimplexName, connectOtherButton = connectOtherButton, connectOtherLink = connectOtherLink)
|
||||
showOpenKnownContactAlert(chatModel, rhId, close, contact, planSimplexName = planSimplexName, connectOtherButton = connectOtherButton, connectOtherLink = connectOtherLink, filterChats = filterChats)
|
||||
cleanup()
|
||||
}
|
||||
}
|
||||
@@ -362,14 +337,9 @@ private suspend fun planAndConnectTask(
|
||||
Log.d(TAG, "planAndConnect, .ContactAddress, .ContactViaAddress")
|
||||
val contact = connectionPlan.contactAddressPlan.contact
|
||||
// the contact is already prepared in the store, so open the existing chat instead of sending a new
|
||||
// connection request; surface it in the chat list first if it is not there yet (as for Known above)
|
||||
if (chatModel.getContactChat(contact.contactId) == null) {
|
||||
chatModel.chatsContext.addChat(Chat(remoteHostId = rhId, chatInfo = ChatInfo.Direct(contact), chatItems = emptyList()))
|
||||
}
|
||||
if (filterKnownContact != null) {
|
||||
filterKnownContact(contact)
|
||||
} else {
|
||||
showOpenKnownContactAlert(chatModel, rhId, close, contact, planSimplexName = planSimplexName, connectOtherButton = connectOtherButton, connectOtherLink = connectOtherLink)
|
||||
// connection request
|
||||
if (filterChats?.invoke(localChats) != true) {
|
||||
showOpenKnownContactAlert(chatModel, rhId, close, contact, planSimplexName = planSimplexName, connectOtherButton = connectOtherButton, connectOtherLink = connectOtherLink, filterChats = filterChats)
|
||||
cleanup()
|
||||
}
|
||||
}
|
||||
@@ -388,9 +358,10 @@ private suspend fun planAndConnectTask(
|
||||
connectOtherButton = connectOtherButton,
|
||||
connectOtherLink = connectOtherLink,
|
||||
addressChanged = connectionPlan.groupLinkPlan.addressChanged,
|
||||
openExistingChat = if (filterKnownGroup == null) connectionPlan.groupLinkPlan.existingChat_?.let { chatInfo -> { openChat_(chatModel, rhId, close, Chat(remoteHostId = rhId, chatInfo = chatInfo, chatItems = emptyList())); cleanup() } } else null,
|
||||
openExistingChat = localChats.firstOrNull()?.takeIf { filterChats?.invoke(localChats) != true }?.let { chatInfo -> { openChat_(chatModel, rhId, close, Chat(remoteHostId = rhId, chatInfo = chatInfo, chatItems = emptyList())); cleanup() } },
|
||||
close,
|
||||
cleanup
|
||||
cleanup,
|
||||
filterChats
|
||||
)
|
||||
} else {
|
||||
Log.d(TAG, "planAndConnect, .GroupLink, .Ok, no short link data")
|
||||
@@ -403,16 +374,16 @@ private suspend fun planAndConnectTask(
|
||||
ownerVerification = connectionPlan.groupLinkPlan.ownerVerification,
|
||||
connectOtherButton = connectOtherButton,
|
||||
connectOtherLink = connectOtherLink,
|
||||
filterChats = filterChats,
|
||||
)
|
||||
}
|
||||
is GroupLinkPlan.OwnLink -> {
|
||||
Log.d(TAG, "planAndConnect, .GroupLink, .OwnLink")
|
||||
val groupInfo = connectionPlan.groupLinkPlan.groupInfo
|
||||
if (filterKnownGroup != null) {
|
||||
filterKnownGroup(groupInfo)
|
||||
if (otherSimplexName != null && connectOtherButton != null) showOtherNameAlert(rhId, otherSimplexName, connectOtherButton, close, cleanup)
|
||||
if (filterChats?.invoke(localChats) == true) {
|
||||
if (otherSimplexName != null && connectOtherButton != null) showOtherNameAlert(rhId, otherSimplexName, connectOtherButton, close, cleanup, filterChats)
|
||||
} else {
|
||||
ownGroupLinkConfirmConnect(chatModel, rhId, connectionLink, linkText, connectionPlan, groupInfo, close, cleanup, planSimplexName = planSimplexName, connectOtherButton = connectOtherButton, connectOtherLink = connectOtherLink)
|
||||
ownGroupLinkConfirmConnect(chatModel, rhId, connectionLink, linkText, connectionPlan, groupInfo, close, cleanup, planSimplexName = planSimplexName, connectOtherButton = connectOtherButton, connectOtherLink = connectOtherLink, filterChats = filterChats)
|
||||
}
|
||||
}
|
||||
GroupLinkPlan.ConnectingConfirmReconnect -> {
|
||||
@@ -425,6 +396,7 @@ private suspend fun planAndConnectTask(
|
||||
cleanup = cleanup,
|
||||
connectOtherButton = connectOtherButton,
|
||||
connectOtherLink = connectOtherLink,
|
||||
filterChats = filterChats,
|
||||
)
|
||||
}
|
||||
is GroupLinkPlan.ConnectingProhibit -> {
|
||||
@@ -454,16 +426,10 @@ 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)
|
||||
if (otherSimplexName != null && connectOtherButton != null) showOtherNameAlert(rhId, otherSimplexName, connectOtherButton, close, cleanup)
|
||||
if (filterChats?.invoke(localChats) == true) {
|
||||
if (otherSimplexName != null && connectOtherButton != null) showOtherNameAlert(rhId, otherSimplexName, connectOtherButton, close, cleanup, filterChats)
|
||||
} else {
|
||||
showOpenKnownGroupAlert(chatModel, rhId, close, groupInfo, planSimplexName = planSimplexName, connectOtherButton = connectOtherButton, connectOtherLink = connectOtherLink)
|
||||
showOpenKnownGroupAlert(chatModel, rhId, close, groupInfo, planSimplexName = planSimplexName, connectOtherButton = connectOtherButton, connectOtherLink = connectOtherLink, filterChats = filterChats)
|
||||
cleanup()
|
||||
}
|
||||
}
|
||||
@@ -593,6 +559,7 @@ fun askCurrentOrIncognitoProfileAlert(
|
||||
ownerVerification: OwnerVerification? = null,
|
||||
connectOtherButton: String? = null,
|
||||
connectOtherLink: String? = null,
|
||||
filterChats: ((List<ChatInfo>) -> Boolean)? = null,
|
||||
) {
|
||||
val fullText = listOfNotNull(text, ownerVerificationMessage(ownerVerification)).joinToString("\n\n").ifEmpty { null }
|
||||
AlertManager.privacySensitive.showAlertDialogButtonsColumn(
|
||||
@@ -620,7 +587,7 @@ fun askCurrentOrIncognitoProfileAlert(
|
||||
if (connectOtherButton != null && connectOtherLink != null) {
|
||||
SectionItemView({
|
||||
AlertManager.privacySensitive.hideAlert()
|
||||
withBGApi { planAndConnect(rhId, connectOtherLink, close = close, cleanup = cleanup) }
|
||||
withBGApi { planAndConnect(rhId, connectOtherLink, close = close, cleanup = cleanup, filterChats = filterChats) }
|
||||
}) {
|
||||
Text(connectOtherButton, Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = MaterialTheme.colors.primary)
|
||||
}
|
||||
@@ -638,6 +605,14 @@ fun askCurrentOrIncognitoProfileAlert(
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun addMissingChats(rhId: Long?, chats: List<ChatInfo>) {
|
||||
chats.forEach {
|
||||
if (!chatModel.chatsContext.hasChat(rhId, it.id)) {
|
||||
chatModel.chatsContext.addChat(Chat(remoteHostId = rhId, chatInfo = it, chatItems = emptyList()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun openChat_(chatModel: ChatModel, rhId: Long?, close: (() -> Unit)?, chat: Chat) {
|
||||
withBGApi {
|
||||
close?.invoke()
|
||||
@@ -651,7 +626,7 @@ val alertProfileImageSize = 138.dp
|
||||
private fun nameWithDomain(name: String, planSimplexName: SimplexNameInfo?): String =
|
||||
name + (planSimplexName?.let { " (${it.shortStr})" } ?: "")
|
||||
|
||||
private fun showOpenKnownContactAlert(chatModel: ChatModel, rhId: Long?, close: (() -> Unit)?, contact: Contact, planSimplexName: SimplexNameInfo? = null, connectOtherButton: String? = null, connectOtherLink: String? = null) {
|
||||
private fun showOpenKnownContactAlert(chatModel: ChatModel, rhId: Long?, close: (() -> Unit)?, contact: Contact, planSimplexName: SimplexNameInfo? = null, connectOtherButton: String? = null, connectOtherLink: String? = null, filterChats: ((List<ChatInfo>) -> Boolean)? = null) {
|
||||
AlertManager.privacySensitive.showOpenChatAlert(
|
||||
profileName = contact.profile.displayName,
|
||||
profileFullName = contact.profile.fullName,
|
||||
@@ -670,7 +645,7 @@ private fun showOpenKnownContactAlert(chatModel: ChatModel, rhId: Long?, close:
|
||||
openKnownContact(chatModel, rhId, close, contact)
|
||||
},
|
||||
connectOtherButton = connectOtherButton,
|
||||
onConnectOther = connectOtherLink?.let { link -> { withBGApi { planAndConnect(rhId, link, close = close) } } },
|
||||
onConnectOther = connectOtherLink?.let { link -> { withBGApi { planAndConnect(rhId, link, close = close, filterChats = filterChats) } } },
|
||||
onDismiss = null
|
||||
)
|
||||
}
|
||||
@@ -697,6 +672,7 @@ fun ownGroupLinkConfirmConnect(
|
||||
planSimplexName: SimplexNameInfo? = null,
|
||||
connectOtherButton: String? = null,
|
||||
connectOtherLink: String? = null,
|
||||
filterChats: ((List<ChatInfo>) -> Boolean)? = null,
|
||||
) {
|
||||
if (groupInfo.useRelays) {
|
||||
AlertManager.privacySensitive.showAlertDialogButtonsColumn(
|
||||
@@ -714,7 +690,7 @@ fun ownGroupLinkConfirmConnect(
|
||||
if (connectOtherButton != null && connectOtherLink != null) {
|
||||
SectionItemView({
|
||||
AlertManager.privacySensitive.hideAlert()
|
||||
withBGApi { planAndConnect(rhId, connectOtherLink, close = close, cleanup = cleanup) }
|
||||
withBGApi { planAndConnect(rhId, connectOtherLink, close = close, cleanup = cleanup, filterChats = filterChats) }
|
||||
}) {
|
||||
Text(connectOtherButton, Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = MaterialTheme.colors.primary)
|
||||
}
|
||||
@@ -777,7 +753,7 @@ fun ownGroupLinkConfirmConnect(
|
||||
}
|
||||
}
|
||||
|
||||
private fun showOpenKnownGroupAlert(chatModel: ChatModel, rhId: Long?, close: (() -> Unit)?, groupInfo: GroupInfo, planSimplexName: SimplexNameInfo? = null, connectOtherButton: String? = null, connectOtherLink: String? = null) {
|
||||
private fun showOpenKnownGroupAlert(chatModel: ChatModel, rhId: Long?, close: (() -> Unit)?, groupInfo: GroupInfo, planSimplexName: SimplexNameInfo? = null, connectOtherButton: String? = null, connectOtherLink: String? = null, filterChats: ((List<ChatInfo>) -> Boolean)? = null) {
|
||||
val subscriberCount = if (groupInfo.useRelays) groupInfo.groupSummary.publicMemberCount?.let { subscriberCountStr(it) } else null
|
||||
AlertManager.privacySensitive.showOpenChatAlert(
|
||||
profileName = groupInfo.groupProfile.displayName,
|
||||
@@ -817,7 +793,7 @@ private fun showOpenKnownGroupAlert(chatModel: ChatModel, rhId: Long?, close: ((
|
||||
openKnownGroup(chatModel, rhId, close, groupInfo)
|
||||
},
|
||||
connectOtherButton = connectOtherButton,
|
||||
onConnectOther = connectOtherLink?.let { link -> { withBGApi { planAndConnect(rhId, link, close = close) } } },
|
||||
onConnectOther = connectOtherLink?.let { link -> { withBGApi { planAndConnect(rhId, link, close = close, filterChats = filterChats) } } },
|
||||
onDismiss = null
|
||||
)
|
||||
}
|
||||
@@ -843,7 +819,8 @@ fun showPrepareContactAlert(
|
||||
addressChanged: Boolean = false,
|
||||
openExistingChat: (() -> Unit)? = null,
|
||||
close: (() -> Unit)?,
|
||||
cleanup: (() -> Unit)?
|
||||
cleanup: (() -> Unit)?,
|
||||
filterChats: ((List<ChatInfo>) -> Boolean)? = null
|
||||
) {
|
||||
AlertManager.privacySensitive.showOpenChatAlert(
|
||||
profileName = contactShortLinkData.profile.displayName,
|
||||
@@ -880,7 +857,7 @@ fun showPrepareContactAlert(
|
||||
}
|
||||
},
|
||||
connectOtherButton = connectOtherButton,
|
||||
onConnectOther = connectOtherLink?.let { link -> { withBGApi { planAndConnect(rhId, link, close = close, cleanup = cleanup) } } },
|
||||
onConnectOther = connectOtherLink?.let { link -> { withBGApi { planAndConnect(rhId, link, close = close, cleanup = cleanup, filterChats = filterChats) } } },
|
||||
dismissText = generalGetString(if (openExistingChat != null) MR.strings.connect_plan_open_existing_chat else MR.strings.cancel_verb),
|
||||
onDismissButton = openExistingChat,
|
||||
onDismiss = {
|
||||
@@ -889,7 +866,7 @@ fun showPrepareContactAlert(
|
||||
)
|
||||
}
|
||||
|
||||
private fun showOtherNameAlert(rhId: Long?, otherSimplexName: SimplexNameInfo, connectOtherButton: String, close: (() -> Unit)?, cleanup: (() -> Unit)?) {
|
||||
private fun showOtherNameAlert(rhId: Long?, otherSimplexName: SimplexNameInfo, connectOtherButton: String, close: (() -> Unit)?, cleanup: (() -> Unit)?, filterChats: ((List<ChatInfo>) -> Boolean)?) {
|
||||
AlertManager.privacySensitive.showAlertDialogButtonsColumn(
|
||||
title = String.format(
|
||||
generalGetString(if (otherSimplexName.nameType == SimplexNameType.publicGroup) MR.strings.simplex_name_also_leads_to_channel else MR.strings.simplex_name_also_leads_to_contact),
|
||||
@@ -901,7 +878,7 @@ private fun showOtherNameAlert(rhId: Long?, otherSimplexName: SimplexNameInfo, c
|
||||
Column {
|
||||
SectionItemView({
|
||||
AlertManager.privacySensitive.hideAlert()
|
||||
withBGApi { planAndConnect(rhId, otherSimplexName.shortStr, close = close, cleanup = cleanup) }
|
||||
withBGApi { planAndConnect(rhId, otherSimplexName.shortStr, close = close, cleanup = cleanup, filterChats = filterChats) }
|
||||
}) {
|
||||
Text(connectOtherButton, Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = MaterialTheme.colors.primary)
|
||||
}
|
||||
@@ -925,7 +902,8 @@ fun showPrepareGroupAlert(
|
||||
addressChanged: Boolean = false,
|
||||
openExistingChat: (() -> Unit)? = null,
|
||||
close: (() -> Unit)?,
|
||||
cleanup: (() -> Unit)?
|
||||
cleanup: (() -> Unit)?,
|
||||
filterChats: ((List<ChatInfo>) -> Boolean)? = null
|
||||
) {
|
||||
val isChannel = !(groupShortLinkInfo?.direct ?: true)
|
||||
val subscriberCount = if (isChannel) groupShortLinkData.publicGroupData?.publicMemberCount?.let { subscriberCountStr(it) } else null
|
||||
@@ -971,7 +949,7 @@ fun showPrepareGroupAlert(
|
||||
}
|
||||
},
|
||||
connectOtherButton = connectOtherButton,
|
||||
onConnectOther = connectOtherLink?.let { link -> { withBGApi { planAndConnect(rhId, link, close = close, cleanup = cleanup) } } },
|
||||
onConnectOther = connectOtherLink?.let { link -> { withBGApi { planAndConnect(rhId, link, close = close, cleanup = cleanup, filterChats = filterChats) } } },
|
||||
dismissText = generalGetString(if (openExistingChat != null) MR.strings.connect_plan_open_existing_chat else MR.strings.cancel_verb),
|
||||
onDismissButton = openExistingChat,
|
||||
onDismiss = {
|
||||
|
||||
+5
-1
@@ -598,7 +598,11 @@ private fun connect(link: String, searchChatFilteredBySimplexLink: MutableState<
|
||||
planAndConnect(
|
||||
chatModel.remoteHostId(),
|
||||
link,
|
||||
filterKnownContact = { searchChatFilteredBySimplexLink.value = setOf(it.id) },
|
||||
filterChats = { chats ->
|
||||
val contacts = chats.all { it is ChatInfo.Direct }
|
||||
if (contacts) searchChatFilteredBySimplexLink.value = chats.map { it.id }.toSet()
|
||||
contacts
|
||||
},
|
||||
close = close,
|
||||
cleanup = cleanup,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user