mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-10-15 22:01:01 +00:00
iterate on /goal
This commit is contained in:
-15
@@ -5252,21 +5252,6 @@ enum class SimplexTLD {
|
||||
@SerialName("web") web
|
||||
}
|
||||
|
||||
@Serializable
|
||||
sealed class NameWarning {
|
||||
@Serializable @SerialName("expired") class Expired(val expiredAt: Instant, val graceUntil: Instant? = null): NameWarning()
|
||||
@Serializable @SerialName("ownExpired") class OwnExpired(val expiredAt: Instant, val graceUntil: Instant? = null): NameWarning()
|
||||
@Serializable @SerialName("available") class Available(val price: NamePrice): NameWarning()
|
||||
@Serializable @SerialName("noLongerRegistered") class NoLongerRegistered(val price: NamePrice): NameWarning()
|
||||
@Serializable @SerialName("ownAvailable") class OwnAvailable(val price: NamePrice): NameWarning()
|
||||
@Serializable @SerialName("reservedForCommunity") object ReservedForCommunity: NameWarning()
|
||||
@Serializable @SerialName("notRegistered") object NotRegistered: NameWarning()
|
||||
@Serializable @SerialName("noValidLink") object NoValidLink: NameWarning()
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class NamePrice(val amount: Long, val years: Int)
|
||||
|
||||
@Serializable
|
||||
enum class SimplexNameType {
|
||||
@SerialName("publicGroup") publicGroup,
|
||||
|
||||
+15
@@ -7454,6 +7454,21 @@ sealed class ConnectionPlan {
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
sealed class NameWarning {
|
||||
@Serializable @SerialName("expired") class Expired(val expiredAt: Instant, val graceUntil: Instant? = null): NameWarning()
|
||||
@Serializable @SerialName("ownExpired") class OwnExpired(val expiredAt: Instant, val graceUntil: Instant? = null): NameWarning()
|
||||
@Serializable @SerialName("available") class Available(val price: NamePrice): NameWarning()
|
||||
@Serializable @SerialName("noLongerRegistered") class NoLongerRegistered(val price: NamePrice): NameWarning()
|
||||
@Serializable @SerialName("ownAvailable") class OwnAvailable(val price: NamePrice): NameWarning()
|
||||
@Serializable @SerialName("reservedForCommunity") object ReservedForCommunity: NameWarning()
|
||||
@Serializable @SerialName("notRegistered") object NotRegistered: NameWarning()
|
||||
@Serializable @SerialName("noValidLink") object NoValidLink: NameWarning()
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class NamePrice(val amount: Long, val years: Int)
|
||||
|
||||
@Serializable
|
||||
sealed class InvitationLinkPlan {
|
||||
@Serializable @SerialName("ok") class Ok(val contactSLinkData_: ContactShortLinkData? = null, val ownerVerification: OwnerVerification? = null): InvitationLinkPlan()
|
||||
|
||||
+5
-13
@@ -1021,7 +1021,7 @@ private fun BoxScope.ChatList(searchText: MutableState<TextFieldValue>, listStat
|
||||
TagsOrConnectByName(searchText, searchChatFilteredBySimplexLink, connectNameCandidate) { candidate ->
|
||||
TagsView(searchText)
|
||||
Divider()
|
||||
ConnectByNameRow(candidate, searchChatFilteredBySimplexLink, close = null)
|
||||
ConnectByNameRow(candidate) { connect(candidate, searchChatFilteredBySimplexLink, cleanup = null) }
|
||||
}
|
||||
ChatListSearchBar(listState, searchText, searchShowingSimplexLink, searchChatFilteredBySimplexLink, connectNameCandidate)
|
||||
Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.ime))
|
||||
@@ -1030,7 +1030,7 @@ private fun BoxScope.ChatList(searchText: MutableState<TextFieldValue>, listStat
|
||||
ChatListSearchBar(listState, searchText, searchShowingSimplexLink, searchChatFilteredBySimplexLink, connectNameCandidate)
|
||||
// top toolbar: search bar above, so on desktop the connect row goes above the tags
|
||||
TagsOrConnectByName(searchText, searchChatFilteredBySimplexLink, connectNameCandidate) { candidate ->
|
||||
ConnectByNameRow(candidate, searchChatFilteredBySimplexLink, close = null)
|
||||
ConnectByNameRow(candidate) { connect(candidate, searchChatFilteredBySimplexLink, cleanup = null) }
|
||||
Divider()
|
||||
TagsView(searchText)
|
||||
}
|
||||
@@ -1199,28 +1199,20 @@ private fun TagsOrConnectByName(
|
||||
val candidate = connectNameCandidate.value
|
||||
when {
|
||||
candidate == null -> TagsView(searchText)
|
||||
!appPlatform.isDesktop -> ConnectByNameRow(candidate, searchChatFilteredBySimplexLink, close = null)
|
||||
!appPlatform.isDesktop -> ConnectByNameRow(candidate) { connect(candidate, searchChatFilteredBySimplexLink, cleanup = null) }
|
||||
else -> desktopView(candidate)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun ConnectByNameRow(name: String, searchChatFilteredBySimplexLink: MutableState<Set<String>>, close: (() -> Unit)?) {
|
||||
internal fun ConnectByNameRow(name: String, onClick: () -> Unit) {
|
||||
val view = LocalMultiplatformView()
|
||||
Row(
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable {
|
||||
hideKeyboard(view)
|
||||
withBGApi {
|
||||
planAndConnect(
|
||||
chatModel.remoteHostId(),
|
||||
name,
|
||||
close = close,
|
||||
filterKnownContact = { searchChatFilteredBySimplexLink.value = setOf(it.id) },
|
||||
filterKnownGroup = { searchChatFilteredBySimplexLink.value = setOf(it.id) },
|
||||
)
|
||||
}
|
||||
onClick()
|
||||
}
|
||||
.padding(vertical = DEFAULT_PADDING_HALF),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
|
||||
+17
-19
@@ -75,6 +75,7 @@ private fun openNameHowTo(uriHandler: UriHandler) = openBrowserAlert(SIMPLEX_NAM
|
||||
private const val SIMPLEX_NAMES_HOWTO_URL = "https://simplex.domains/#testing"
|
||||
|
||||
private fun showNameWarningAlert(
|
||||
rhId: Long?,
|
||||
domain: SimplexDomain,
|
||||
warning: NameWarning,
|
||||
openExistingChat: (() -> Unit)?,
|
||||
@@ -90,12 +91,12 @@ private fun showNameWarningAlert(
|
||||
val uriHandler = LocalUriHandler.current
|
||||
Column {
|
||||
if (action != null) {
|
||||
SectionItemView({ AlertManager.privacySensitive.hideAlert(); action.second(uriHandler) }) {
|
||||
SectionItemView({ dismiss(); action.second(uriHandler) }) {
|
||||
Text(action.first, Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = MaterialTheme.colors.primary)
|
||||
}
|
||||
}
|
||||
if (openExistingChat != null) {
|
||||
SectionItemView({ AlertManager.privacySensitive.hideAlert(); openExistingChat() }) {
|
||||
SectionItemView({ dismiss(); openExistingChat() }) {
|
||||
Text(generalGetString(MR.strings.connect_plan_open_existing_chat), Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = MaterialTheme.colors.primary)
|
||||
}
|
||||
}
|
||||
@@ -105,7 +106,7 @@ private fun showNameWarningAlert(
|
||||
}
|
||||
}
|
||||
fun alert(title: String, text: String, action: Pair<String, (UriHandler) -> Unit>? = null) {
|
||||
AlertManager.privacySensitive.showAlertDialogButtonsColumn(title = title, text = text, onDismissRequest = { cleanup?.invoke() }, buttons = buttons(action))
|
||||
AlertManager.privacySensitive.showAlertDialogButtonsColumn(title = title, text = text, onDismissRequest = { cleanup?.invoke() }, hostDevice = hostDevice(rhId), buttons = buttons(action))
|
||||
}
|
||||
val register = generalGetString(MR.strings.simplex_name_register) to { uh: UriHandler -> openNameHowTo(uh) }
|
||||
when (warning) {
|
||||
@@ -172,7 +173,7 @@ 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) = result
|
||||
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
|
||||
@@ -203,10 +204,10 @@ private suspend fun planAndConnectTask(
|
||||
if (filterKnownGroup != null) filterKnownGroup(knownGroup)
|
||||
else openExisting = { openKnownGroup(chatModel, rhId, close, knownGroup) }
|
||||
}
|
||||
showNameWarningAlert(nameDomain, nameWarning, openExisting, cleanup)
|
||||
showNameWarningAlert(rhId, nameDomain, nameWarning, openExisting, cleanup)
|
||||
return completable
|
||||
}
|
||||
val connectionLink = connectionLink_ ?: run {
|
||||
if (connectionLink == null) {
|
||||
cleanup()
|
||||
return completable
|
||||
}
|
||||
@@ -288,7 +289,7 @@ private suspend fun planAndConnectTask(
|
||||
connectOtherButton = connectOtherButton,
|
||||
connectOtherLink = connectOtherLink,
|
||||
addressChanged = connectionPlan.contactAddressPlan.addressChanged,
|
||||
openExistingChat = if (filterKnownContact == null && connectionPlan.contactAddressPlan.addressChanged) openNameChat(rhId, planSimplexName, close, cleanup) else null,
|
||||
openExistingChat = if (filterKnownContact == null && connectionPlan.contactAddressPlan.addressChanged) localNameChat(rhId, planSimplexName)?.let { chat -> { openChat_(chatModel, rhId, close, chat); cleanup() } } else null,
|
||||
close,
|
||||
cleanup
|
||||
)
|
||||
@@ -350,7 +351,7 @@ private suspend fun planAndConnectTask(
|
||||
}
|
||||
if (filterKnownContact != null) {
|
||||
filterKnownContact(contact)
|
||||
if (planSimplexName != null && otherSimplexName != null && connectOtherButton != null) showOtherNameAlert(rhId, planSimplexName, otherSimplexName, connectOtherButton, close, cleanup)
|
||||
if (otherSimplexName != null && connectOtherButton != null) showOtherNameAlert(rhId, otherSimplexName, connectOtherButton, close, cleanup)
|
||||
} else {
|
||||
showOpenKnownContactAlert(chatModel, rhId, close, contact, planSimplexName = planSimplexName, connectOtherButton = connectOtherButton, connectOtherLink = connectOtherLink)
|
||||
cleanup()
|
||||
@@ -386,7 +387,7 @@ private suspend fun planAndConnectTask(
|
||||
connectOtherButton = connectOtherButton,
|
||||
connectOtherLink = connectOtherLink,
|
||||
addressChanged = connectionPlan.groupLinkPlan.addressChanged,
|
||||
openExistingChat = if (filterKnownGroup == null && connectionPlan.groupLinkPlan.addressChanged) openNameChat(rhId, planSimplexName, close, cleanup) else null,
|
||||
openExistingChat = if (filterKnownGroup == null && connectionPlan.groupLinkPlan.addressChanged) localNameChat(rhId, planSimplexName)?.let { chat -> { openChat_(chatModel, rhId, close, chat); cleanup() } } else null,
|
||||
close,
|
||||
cleanup
|
||||
)
|
||||
@@ -458,7 +459,7 @@ private suspend fun planAndConnectTask(
|
||||
}
|
||||
if (filterKnownGroup != null) {
|
||||
filterKnownGroup(groupInfo)
|
||||
if (planSimplexName != null && otherSimplexName != null && connectOtherButton != null) showOtherNameAlert(rhId, planSimplexName, otherSimplexName, connectOtherButton, close, cleanup)
|
||||
if (otherSimplexName != null && connectOtherButton != null) showOtherNameAlert(rhId, otherSimplexName, connectOtherButton, close, cleanup)
|
||||
} else {
|
||||
showOpenKnownGroupAlert(chatModel, rhId, close, groupInfo, planSimplexName = planSimplexName, connectOtherButton = connectOtherButton, connectOtherLink = connectOtherLink)
|
||||
cleanup()
|
||||
@@ -885,20 +886,17 @@ fun showPrepareContactAlert(
|
||||
)
|
||||
}
|
||||
|
||||
// a name tapped in a message has no filtered list behind the alert, so the chat the name had is opened from it, if there is one
|
||||
private suspend fun openNameChat(rhId: Long?, name: SimplexNameInfo?, close: (() -> Unit)?, cleanup: (() -> Unit)?): (() -> Unit)? {
|
||||
val chat = name?.let { knownChatId(rhId, chatModel.controller.apiConnectPlan(rhId, it.shortStr, PlanResolveMode.PRMNever, inProgress = mutableStateOf(false))) }?.let { chatModel.getChat(it) }
|
||||
return chat?.let { { openChat_(chatModel, rhId, close, it); cleanup?.invoke() } }
|
||||
}
|
||||
private suspend fun localNameChat(rhId: Long?, name: SimplexNameInfo?): Chat? =
|
||||
name?.let { knownChatId(rhId, chatModel.controller.apiConnectPlan(rhId, it.shortStr, PlanResolveMode.PRMNever, inProgress = mutableStateOf(false))) }?.let { chatModel.getChat(it) }
|
||||
|
||||
// a bare name found as a local chat also leads to the other kind, which the user does not have
|
||||
private fun showOtherNameAlert(rhId: Long?, planSimplexName: SimplexNameInfo, otherSimplexName: SimplexNameInfo, connectOtherButton: String, close: (() -> Unit)?, cleanup: (() -> Unit)?) {
|
||||
private fun showOtherNameAlert(rhId: Long?, otherSimplexName: SimplexNameInfo, connectOtherButton: String, close: (() -> Unit)?, cleanup: (() -> Unit)?) {
|
||||
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),
|
||||
planSimplexName.nameDomain.fullDomainName,
|
||||
otherSimplexName.nameDomain.fullDomainName,
|
||||
otherSimplexName.shortStr
|
||||
),
|
||||
hostDevice = hostDevice(rhId),
|
||||
buttons = {
|
||||
Column {
|
||||
SectionItemView({
|
||||
@@ -949,7 +947,7 @@ fun showPrepareGroupAlert(
|
||||
).joinToString("\n").ifEmpty { null },
|
||||
confirmText = generalGetString(
|
||||
if (isChannel) (if (addressChanged) MR.strings.connect_plan_open_new_channel else MR.strings.connect_plan_open_channel)
|
||||
else (if (addressChanged) MR.strings.connect_plan_open_new_group else MR.strings.connect_plan_open_group)
|
||||
else MR.strings.connect_plan_open_group
|
||||
),
|
||||
onConfirm = {
|
||||
AlertManager.privacySensitive.hideAlert()
|
||||
|
||||
+2
-2
@@ -319,7 +319,7 @@ private fun ModalData.NewChatSheetLayout(
|
||||
)
|
||||
connectNameCandidate.value?.let { candidate ->
|
||||
Divider()
|
||||
ConnectByNameRow(candidate, searchChatFilteredBySimplexLink, close = close)
|
||||
ConnectByNameRow(candidate) { withBGApi { planAndConnect(chatModel.remoteHostId(), candidate, close = close) } }
|
||||
}
|
||||
Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.ime))
|
||||
}
|
||||
@@ -410,7 +410,7 @@ private fun ModalData.NewChatSheetLayout(
|
||||
)
|
||||
connectNameCandidate.value?.let { candidate ->
|
||||
Divider()
|
||||
ConnectByNameRow(candidate, searchChatFilteredBySimplexLink, close = close)
|
||||
ConnectByNameRow(candidate) { withBGApi { planAndConnect(chatModel.remoteHostId(), candidate, close = close) } }
|
||||
}
|
||||
Divider()
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
<string name="connect_plan_open_group">Open group</string>
|
||||
<string name="connect_plan_open_new_group">Open new group</string>
|
||||
<string name="connect_plan_open_new_channel">Open new channel</string>
|
||||
<string name="connect_plan_open_existing_chat">Open existing chat</string>
|
||||
<string name="connect_plan_you_are_observer">You are an observer</string>
|
||||
<string name="connect_plan_you_are_member">You are a member</string>
|
||||
<string name="connect_plan_you_are_moderator">You are a moderator</string>
|
||||
@@ -205,7 +206,6 @@
|
||||
<string name="simplex_name_resolver_error_desc">Resolver error: %1$s</string>
|
||||
<string name="simplex_name_no_valid_link">No valid link</string>
|
||||
<string name="simplex_name_no_valid_link_desc">The SimpleX name %1$s is registered, but it has no valid link.</string>
|
||||
<!-- SimpleX name lookup - ConnectPlan.kt -->
|
||||
<string name="simplex_name_expired">Name expired</string>
|
||||
<string name="simplex_name_expired_desc">%1$s expired on %2$s. Its owner can renew it until %3$s.</string>
|
||||
<string name="simplex_name_expired_no_date_desc">%1$s expired on %2$s.</string>
|
||||
@@ -226,7 +226,6 @@
|
||||
<string name="simplex_name_re_register">Re-register</string>
|
||||
<string name="simplex_name_renew">Renew</string>
|
||||
<string name="simplex_name_connect_simplex_team">Connect to SimpleX team</string>
|
||||
<string name="connect_plan_open_existing_chat">Open existing chat</string>
|
||||
<string name="simplex_name_unconfirmed">Unconfirmed name</string>
|
||||
<string name="simplex_name_unconfirmed_desc">The SimpleX name %1$s is registered, but not added to profile. Please add it to your address or channel profile, if you are the owner.</string>
|
||||
<string name="channel_temporarily_unavailable">Channel temporarily unavailable</string>
|
||||
|
||||
Reference in New Issue
Block a user