mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-10-22 13:11:55 +00:00
fix review comments
This commit is contained in:
1 parent
75b59f4dec
commit
d9d6acd97f
14 files changed
+107
-129
No files matched your search
+3
-49
@@ -5252,55 +5252,9 @@ enum class SimplexTLD {
|
||||
@SerialName("web") web
|
||||
}
|
||||
|
||||
// How recently each SimpleX name was resolved: one with a local chat resolves once a day, any other on every tap.
|
||||
object NameResolution {
|
||||
private const val DAY_SECONDS = 24 * 60 * 60L
|
||||
private val prefs: AppPreferences get() = ChatController.appPrefs
|
||||
|
||||
@Serializable
|
||||
private data class Resolved(val at: Long, val expires: Long? = null)
|
||||
|
||||
private fun load(): MutableMap<String, Resolved> =
|
||||
try {
|
||||
val s = prefs.simplexNamesResolvedAt.get() ?: return mutableMapOf()
|
||||
json.decodeFromString<Map<String, Resolved>>(s).toMutableMap()
|
||||
} catch (e: Exception) {
|
||||
mutableMapOf()
|
||||
}
|
||||
|
||||
private fun save(m: Map<String, Resolved>) {
|
||||
// only names looked up in the last week are worth remembering
|
||||
val now = nowSeconds()
|
||||
val kept = m.filterValues { now - it.at < 7 * DAY_SECONDS }
|
||||
try {
|
||||
prefs.simplexNamesResolvedAt.set(json.encodeToString<Map<String, Resolved>>(kept))
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "NameResolution.save: ${e.stackTraceToString()}")
|
||||
}
|
||||
}
|
||||
|
||||
private fun nowSeconds(): Long = Clock.System.now().epochSeconds
|
||||
|
||||
// a cached answer is stale a day after it was taken, or as soon as the name it described expired
|
||||
fun isFresh(domain: SimplexDomain): Boolean {
|
||||
val r = load()[domain.fullDomainName] ?: return false
|
||||
val now = nowSeconds()
|
||||
if (now - r.at >= DAY_SECONDS) return false
|
||||
return r.expires == null || now < r.expires
|
||||
}
|
||||
|
||||
fun record(domain: SimplexDomain, reg: NameRegistration?) {
|
||||
val m = load()
|
||||
m[domain.fullDomainName] = Resolved(nowSeconds(), (reg as? NameRegistration.Registered)?.expires)
|
||||
save(m)
|
||||
}
|
||||
|
||||
// a name registered, claimed or dropped on this device must not keep reading as it did before
|
||||
fun forget(fullDomainName: String) {
|
||||
val m = load()
|
||||
if (m.remove(fullDomainName) != null) save(m)
|
||||
}
|
||||
}
|
||||
// when a SimpleX name was last resolved from the registry, and when that registration runs out
|
||||
@Serializable
|
||||
data class SimplexNameResolved(val at: Long, val expires: Long? = null)
|
||||
|
||||
// What the registry holds for a name - the RNAME payload, "type"-tagged on every platform.
|
||||
@Serializable
|
||||
|
||||
+1
-4
@@ -1944,8 +1944,6 @@ object ChatController {
|
||||
suspend fun apiSetUserDomain(rh: Long?, simplexDomain: String?): User {
|
||||
val userId = currentUserId("apiSetUserDomain")
|
||||
val r = sendCmd(rh, CC.ApiSetUserDomain(userId, simplexDomain))
|
||||
// a name claimed or dropped here must not keep reading from the answer taken before
|
||||
chatModel.currentUser.value?.profile?.contactDomain?.let { NameResolution.forget(it.domain) }
|
||||
return when {
|
||||
r is API.Result && r.res is CR.UserProfileUpdated -> r.res.user.updateRemoteHostId(rh)
|
||||
r is API.Result && r.res is CR.UserProfileNoChange -> r.res.user.updateRemoteHostId(rh)
|
||||
@@ -7435,9 +7433,8 @@ data class ConnectionPlanResult(
|
||||
|
||||
// APIConnectPlan resolution scope; PRMNever is local-store-only (no network), used for per-keystroke name search
|
||||
enum class PlanResolveMode {
|
||||
PRMAllGroups, PRMUnknown, PRMNever, PRMAll;
|
||||
PRMUnknown, PRMNever, PRMAll;
|
||||
val cmdString: String get() = when (this) {
|
||||
PRMAllGroups -> "allGroups"
|
||||
PRMUnknown -> "unknown"
|
||||
PRMNever -> "never"
|
||||
PRMAll -> "all"
|
||||
|
||||
+45
-2
@@ -22,6 +22,7 @@ import chat.simplex.common.views.usersettings.simplexTeamUri
|
||||
import chat.simplex.res.MR
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.datetime.*
|
||||
import kotlinx.serialization.*
|
||||
|
||||
enum class ConnectionLinkType {
|
||||
INVITATION, CONTACT, GROUP
|
||||
@@ -74,6 +75,48 @@ private fun openNameHowTo(uriHandler: UriHandler) = openBrowserAlert(SIMPLEX_NAM
|
||||
|
||||
private const val SIMPLEX_NAMES_HOWTO_URL = "https://simplex.domains/#testing"
|
||||
|
||||
private const val NAME_RESOLVED_DAY_SECONDS = 24 * 60 * 60L
|
||||
|
||||
private fun loadNamesResolvedAt(): MutableMap<String, SimplexNameResolved> =
|
||||
try {
|
||||
val s = ChatController.appPrefs.simplexNamesResolvedAt.get() ?: return mutableMapOf()
|
||||
json.decodeFromString<Map<String, SimplexNameResolved>>(s).toMutableMap()
|
||||
} catch (e: Exception) {
|
||||
mutableMapOf()
|
||||
}
|
||||
|
||||
private fun saveNamesResolvedAt(m: Map<String, SimplexNameResolved>) {
|
||||
// only names looked up in the last week are worth remembering
|
||||
val now = Clock.System.now().epochSeconds
|
||||
val kept = m.filterValues { now - it.at < 7 * NAME_RESOLVED_DAY_SECONDS }
|
||||
try {
|
||||
ChatController.appPrefs.simplexNamesResolvedAt.set(json.encodeToString<Map<String, SimplexNameResolved>>(kept))
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "saveNamesResolvedAt: ${e.stackTraceToString()}")
|
||||
}
|
||||
}
|
||||
|
||||
// a cached answer is stale a day after it was taken, or as soon as the name it described expired
|
||||
fun simplexNameResolvedRecently(domain: SimplexDomain): Boolean {
|
||||
val r = loadNamesResolvedAt()[domain.fullDomainName] ?: return false
|
||||
val now = Clock.System.now().epochSeconds
|
||||
if (now - r.at >= NAME_RESOLVED_DAY_SECONDS) return false
|
||||
return r.expires == null || now < r.expires
|
||||
}
|
||||
|
||||
fun recordSimplexNameResolved(domain: SimplexDomain, reg: NameRegistration?) {
|
||||
val m = loadNamesResolvedAt()
|
||||
m[domain.fullDomainName] = SimplexNameResolved(Clock.System.now().epochSeconds, (reg as? NameRegistration.Registered)?.expires)
|
||||
saveNamesResolvedAt(m)
|
||||
}
|
||||
|
||||
// a name registered, claimed or dropped on this device must not keep reading as it did before
|
||||
fun forgetSimplexNameResolved(fullDomainName: String) {
|
||||
val m = loadNamesResolvedAt()
|
||||
if (m.remove(fullDomainName) != null) saveNamesResolvedAt(m)
|
||||
}
|
||||
|
||||
|
||||
// what the registry said, when the user can act on it; false leaves the caller to show its usual plan UI.
|
||||
private fun showNameRegistrationAlert(
|
||||
rhId: Long?,
|
||||
@@ -209,7 +252,7 @@ private suspend fun planAndConnectTask(
|
||||
}
|
||||
// A fresh name is tried against the store first; a miss falls through to a full resolution.
|
||||
val nameTarget = (strConnectTarget(shortOrFullLink.trim()) as? ConnectTarget.Name)?.nameInfo
|
||||
val freshName = nameTarget != null && NameResolution.isFresh(nameTarget.nameDomain)
|
||||
val freshName = nameTarget != null && simplexNameResolvedRecently(nameTarget.nameDomain)
|
||||
var result = if (freshName) {
|
||||
// a local probe: no spinner and no error alerts, so a miss falls through silently
|
||||
chatModel.controller.apiConnectPlan(rhId, shortOrFullLink, PlanResolveMode.PRMNever, linkOwnerSig, mutableStateOf(false))
|
||||
@@ -219,7 +262,7 @@ private suspend fun planAndConnectTask(
|
||||
result = chatModel.controller.apiConnectPlan(rhId, shortOrFullLink, mode, linkOwnerSig, inProgress)
|
||||
// remember when this name was last taken from the registry, and when its registration runs out
|
||||
if (nameTarget != null && result != null) {
|
||||
NameResolution.record(nameTarget.nameDomain, result.connectionPlan.nameRegistration())
|
||||
recordSimplexNameResolved(nameTarget.nameDomain, result.connectionPlan.nameRegistration())
|
||||
}
|
||||
}
|
||||
connectProgressManager.stopConnectProgress()
|
||||
|
||||
+2
@@ -388,6 +388,8 @@ private fun UserAddressLayout(
|
||||
save = { simplexDomain ->
|
||||
try {
|
||||
val u = chatModel.controller.apiSetUserDomain(user?.remoteHostId, simplexDomain)
|
||||
// a name claimed or dropped here must not keep reading from the answer taken before
|
||||
domain?.let { forgetSimplexNameResolved(it) }
|
||||
withContext(Dispatchers.Main) { chatModel.updateUser(u) }
|
||||
true
|
||||
} catch (e: Exception) {
|
||||
|
||||
Reference in new issue
Block a user