opuse 5.5 /goal iterations

This commit is contained in:
Alain Brenzikofer committed 2026-09-24 09:37:13 +02:00
1 parent ab61d51afd
commit 0a245c67cb
10 files changed
+36 -83

No files matched your search

+1 -1
View File
@@ -1496,7 +1496,7 @@ enum NameRegistration: Hashable {
}
}
// stock derivation cannot read this: the core tags it flat as {"type": ...}, not in swift's nested shape
// stock derivation cannot decode this: the core encodes it with a flat "type" tag, not swift's nested shape
extension NameRegistration: Decodable {
private enum CodingKeys: String, CodingKey {
case type, expires, graceUntil, reservedReason_, pricing, reservedReason
@@ -1344,7 +1344,7 @@ func recordSimplexNameResolved(_ domain: SimplexDomain, _ reg: NameRegistration?
saveNamesResolvedAt(m)
}
func forgetSimplexNameResolved(_ fullDomainName: String) {
func clearSimplexNameResolved(_ fullDomainName: String) {
var m = simplexNamesResolvedAtDefault.get()
if m.removeValue(forKey: fullDomainName) != nil { saveNamesResolvedAt(m) }
}
@@ -1358,13 +1358,6 @@ private func nameCentsPerYear(_ pricing: NamePricing, _ domain: SimplexDomain) -
return "$\(cents / 100)" + (cents % 100 == 0 ? "" : String(format: ".%02lld", cents % 100))
}
private func showNameNotRegisteredAlert() {
showAlert(
NSLocalizedString("Name not registered", comment: "alert title"),
message: NSLocalizedString("This SimpleX name is not registered. Please check the name.", comment: "")
)
}
private func showNameRegistrationAlert(
domain: SimplexDomain,
reg: NameRegistration,
@@ -1520,6 +1513,7 @@ func planAndConnect(
case .contactAddress(.ownLink, _), .groupLink(.ownLink, _): true
default: false
}
let notConnectable = if case .nameNotConnectable = connectionPlan { true } else { false }
let handled = await MainActor.run {
var openExisting: (() -> Void)? = nil
if let contact = knownContact {
@@ -1545,7 +1539,7 @@ func planAndConnect(
domain: nameDomain,
reg: nameReg,
isOwn: isOwnName,
notConnectable: { if case .nameNotConnectable = connectionPlan { true } else { false } }(),
notConnectable: notConnectable,
hasLocalChat: knownContact != nil || knownGroup != nil,
openExistingChat: openExisting,
cleanup: cleanup
@@ -1554,19 +1548,12 @@ func planAndConnect(
if handled { return }
}
guard let connectionLink = result.connLink else {
await MainActor.run {
if case .nameNotConnectable = connectionPlan { showNameNotRegisteredAlert() }
cleanup?()
}
await MainActor.run { cleanup?() }
return
}
switch connectionPlan {
case .nameNotConnectable:
logger.debug("planAndConnect, .nameNotConnectable")
await MainActor.run {
showNameNotRegisteredAlert()
cleanup?()
}
break
case let .invitationLink(ilp):
switch ilp {
case let .ok(contactSLinkData_, ownerVerification):
@@ -205,7 +205,7 @@ struct UserAddressView: View {
save: { simplexDomain in
do {
let u = try await apiSetUserDomain(simplexDomain)
if let d = chatModel.currentUser?.profile.contactDomain?.domain { forgetSimplexNameResolved(d) }
if let d = chatModel.currentUser?.profile.contactDomain?.domain { clearSimplexNameResolved(d) }
await MainActor.run { chatModel.updateUser(u) }
return true
} catch {
@@ -108,7 +108,7 @@ fun recordSimplexNameResolved(domain: SimplexDomain, reg: NameRegistration?) {
saveNamesResolvedAt(m)
}
fun forgetSimplexNameResolved(fullDomainName: String) {
fun clearSimplexNameResolved(fullDomainName: String) {
val m = loadNamesResolvedAt()
if (m.remove(fullDomainName) != null) saveNamesResolvedAt(m)
}
@@ -254,12 +254,7 @@ private suspend fun planAndConnectTask(
val label = if (it.nameType == SimplexNameType.publicGroup) MR.strings.connect_plan_join_name else MR.strings.connect_plan_connect_to_name
generalGetString(label).format(it.shortStr)
}
val nameReg = when (connectionPlan) {
is ConnectionPlan.NameNotConnectable -> connectionPlan.nameRegistration
is ConnectionPlan.ContactAddress -> connectionPlan.nameRegistration_
is ConnectionPlan.GroupLink -> connectionPlan.nameRegistration_
else -> null
}
val nameReg = connectionPlan.nameRegistration()
val nameDomain = when (connectionPlan) {
is ConnectionPlan.NameNotConnectable -> connectionPlan.simplexDomain
else -> planSimplexName?.nameDomain
@@ -290,24 +285,11 @@ private suspend fun planAndConnectTask(
if (handled) return completable
}
val connectionLink = connectionLink_ ?: run {
when (connectionPlan) {
is ConnectionPlan.NameNotConnectable -> AlertManager.privacySensitive.showAlertMsg(
generalGetString(MR.strings.simplex_name_not_registered),
generalGetString(MR.strings.simplex_name_not_found_desc)
)
else -> {}
}
cleanup()
return completable
}
when (connectionPlan) {
is ConnectionPlan.NameNotConnectable -> {
AlertManager.privacySensitive.showAlertMsg(
generalGetString(MR.strings.simplex_name_not_registered),
generalGetString(MR.strings.simplex_name_not_found_desc)
)
cleanup()
}
is ConnectionPlan.NameNotConnectable -> {}
is ConnectionPlan.InvitationLink -> when (connectionPlan.invitationLinkPlan) {
is InvitationLinkPlan.Ok ->
if (connectionPlan.invitationLinkPlan.contactSLinkData_ != null) {
@@ -388,7 +388,7 @@ private fun UserAddressLayout(
save = { simplexDomain ->
try {
val u = chatModel.controller.apiSetUserDomain(user?.remoteHostId, simplexDomain)
domain?.let { forgetSimplexNameResolved(it) }
domain?.let { clearSimplexNameResolved(it) }
withContext(Dispatchers.Main) { chatModel.updateUser(u) }
true
} catch (e: Exception) {
+2 -2
View File
@@ -1150,9 +1150,9 @@ data ChatDeleteMode
data ConnectionPlan
= CPInvitationLink {invitationLinkPlan :: InvitationLinkPlan}
| CPContactAddress {contactAddressPlan :: ContactAddressPlan, nameRegistration_ :: Maybe NameRegistration} -- nameRegistration_ is set when the target was a name
| CPContactAddress {contactAddressPlan :: ContactAddressPlan, nameRegistration_ :: Maybe NameRegistration}
| CPGroupLink {groupLinkPlan :: GroupLinkPlan, nameRegistration_ :: Maybe NameRegistration}
| CPNameNotConnectable {simplexDomain :: SimplexDomain, nameRegistration :: NameRegistration} -- the name is not registered, expired or has no usable link, and no local chat has it
| CPNameNotConnectable {simplexDomain :: SimplexDomain, nameRegistration :: NameRegistration}
| CPError {chatError :: ChatError}
deriving (Show)
+15 -17
View File
@@ -4419,14 +4419,13 @@ processChatCommand cxt nm = \case
tryAllErrors (resolveNameRegistration user nm d) >>= \case
Right reg -> do
expired <- nameExpired reg
case reg of
NRRegistered {nameRecord = nr}
| not expired && isJust (firstNameLink CCTChannel (nrSimplexChannel nr)) ->
(setPlanRegistration reg <$> connectPlanName NTPublicGroup (Right reg)) `catchAllErrors` \e ->
(setPlanRegistration reg <$> connectPlanName NTContact (Right reg) `catchAllErrors` \_ -> throwError e)
| not expired && isJust (firstNameLink CCTContact (nrSimplexContact nr)) ->
setPlanRegistration reg <$> connectPlanName NTContact (Right reg)
_ -> connectPlanLocal reg
let connectable nameType = not expired && nameHasLink nameType reg
if
| connectable NTPublicGroup ->
(setPlanRegistration reg <$> connectPlanName NTPublicGroup (Right reg)) `catchAllErrors` \e ->
(setPlanRegistration reg <$> connectPlanName NTContact (Right reg) `catchAllErrors` \_ -> throwError e)
| connectable NTContact -> setPlanRegistration reg <$> connectPlanName NTContact (Right reg)
| otherwise -> connectPlanLocal reg
Left e -> connectPlanNoName e
where
connectPlanLocal reg =
@@ -4438,10 +4437,9 @@ processChatCommand cxt nm = \case
connectPlanName nameType nr_ = setOtherName <$> connectPlan user (nameTarget nameType) resolveMode sig_ (Just nr_)
where
setOtherName (l, planName, _, p) = (l, planName, otherName, p)
otherName = case nr_ of
Right NRRegistered {nameRecord = NameRecord {nrSimplexContact, nrSimplexChannel}} -> case nameType of
NTContact -> SimplexNameInfo NTPublicGroup d <$ firstNameLink CCTChannel nrSimplexChannel
NTPublicGroup -> SimplexNameInfo NTContact d <$ firstNameLink CCTContact nrSimplexContact
otherName = case (nameType, nr_) of
(NTContact, Right reg) | nameHasLink NTPublicGroup reg -> Just $ SimplexNameInfo NTPublicGroup d
(NTPublicGroup, Right reg) | nameHasLink NTContact reg -> Just $ SimplexNameInfo NTContact d
_ -> Nothing
nameTarget nameType = ACTarget SCMContact $ CTShortContact $ CTName $ SimplexNameInfo nameType d
connectPlanNoName e =
@@ -4454,10 +4452,10 @@ processChatCommand cxt nm = \case
| CTName ni <- nl, isNothing nameRec, resolveMode /= PRMNever -> do
reg <- resolveNameRegistration user nm (nameDomain ni)
expired <- nameExpired reg
if nameHasLink ni reg && not expired
then setPlanRegistration reg <$> connectPlan user (ACTarget SCMContact (CTShortContact nl)) resolveMode sig_ (Just (Right reg))
if nameHasLink (nameType ni) reg && not expired
then setPlanRegistration reg <$> connectPlan user (ACTarget SCMContact ct) resolveMode sig_ (Just (Right reg))
else
(setPlanRegistration reg <$> connectPlan user (ACTarget SCMContact (CTShortContact nl)) PRMNever sig_ (Just (Right reg)))
(setPlanRegistration reg <$> connectPlan user (ACTarget SCMContact ct) PRMNever sig_ (Just (Right reg)))
`catchAllErrors` \_ -> pure (Nothing, Nothing, Nothing, CPNameNotConnectable (nameDomain ni) reg)
CTShortContact nl ->
(\(l, p) -> (Just l, simplexName_, Nothing, p)) <$> case ctType of
@@ -5124,8 +5122,8 @@ nameExpired = \case
NRRegistered {expires = Just expires} -> (expires <) <$> liftIO getSystemSeconds
_ -> pure False
nameHasLink :: SimplexNameInfo -> NameRegistration -> Bool
nameHasLink SimplexNameInfo {nameType} = \case
nameHasLink :: SimplexNameType -> NameRegistration -> Bool
nameHasLink nameType = \case
NRRegistered {nameRecord = NameRecord {nrSimplexContact, nrSimplexChannel}} -> case nameType of
NTContact -> isJust (firstNameLink CCTContact nrSimplexContact)
NTPublicGroup -> isJust (firstNameLink CCTChannel nrSimplexChannel)
+4 -8
View File
@@ -2250,11 +2250,10 @@ viewNameRegistration = \case
["registered" <> expiryNote expires graceUntil <> maybe "" ((", reserved: " <>) . plain . textEncode) reservedReason_]
Just NRAvailable {pricing = NamePricing {basePrice = USDCents c, minLabelLength}} ->
["available: " <> plain (show c) <> " cents/year, min length " <> plain (show minLabelLength)]
Just NRReserved {reservedReason} -> ["reserved: " <> plain (textEncode reservedReason :: Text)]
Just NRReserved {reservedReason} -> ["reserved: " <> plain (textEncode reservedReason)]
Nothing -> []
expiryNote expires graceUntil = case expires of
Nothing -> ""
Just e -> ", expires " <> plain (show (roundedSeconds e)) <> maybe "" (\g -> ", grace until " <> plain (show (roundedSeconds g))) graceUntil
expiryNote expires graceUntil = maybe "" (\e -> ", expires " <> showTime e <> maybe "" ((", grace until " <>) . showTime) graceUntil) expires
showTime = plain . show . roundedSeconds
viewConnectionPlan :: ChatConfig -> Maybe ACreatedConnLink -> ConnectionPlan -> [StyledString]
viewConnectionPlan ChatConfig {logLevel, testView} _connLink = \case
@@ -2277,10 +2276,7 @@ viewConnectionPlan ChatConfig {logLevel, testView} _connLink = \case
| business -> ("business address: " <>)
_ -> ("invitation link: " <>)
CPContactAddress cap _ -> case cap of
CAPOk contactSLinkData ov addressChanged ->
[addrOrBiz contactSLinkData (if addressChanged then "ok to connect, address changed" else "ok to connect")]
<> viewSigVerification ov
<> [viewJSON contactSLinkData | testView]
CAPOk contactSLinkData ov addressChanged -> [addrOrBiz contactSLinkData ("ok to connect" <> (if addressChanged then ", address changed" else ""))] <> viewSigVerification ov <> [viewJSON contactSLinkData | testView]
CAPOwnLink -> [ctAddr "own address"]
CAPConnectingConfirmReconnect -> [ctAddr "connecting, allowed to reconnect"]
CAPConnectingProhibit ct -> [ctAddr ("connecting to contact " <> ttyContact' ct)]
+2 -2
View File
@@ -48,7 +48,7 @@ testConnectByName :: HasCallStack => TestParams -> IO ()
testConnectByName ps = withSmpServerAndNames $ \reg ->
testChat2 aliceProfile bobProfile (test reg) ps
where
aliceName = aliceSimplexName
aliceName = SimplexNameInfo NTContact (SimplexDomain TLDSimplex "alice" [])
test reg alice bob = do
mapM_ enableNamesRole [alice, bob]
alice ##> "/ad"
@@ -393,7 +393,7 @@ testPlanNameReservedOther = withAliceName $ \reg _l _alice bob -> do
testPlanNameNoValidLink :: HasCallStack => TestParams -> IO ()
testPlanNameNoValidLink = withAliceName $ \reg _l _alice bob -> do
registerName reg boogaloo (emptyNameRecord "boogaloo.simplex")
registerName reg boogaloo (emptyRecord "boogaloo.simplex")
bob ##> "/_connect plan 1 @boogaloo.simplex"
bob <## "SimpleX name boogaloo.simplex: nothing to connect to"
bob <## "registered"
+2 -12
View File
@@ -15,7 +15,7 @@ module NameResolver
registerAvailableName,
unregisterName,
failNameResolution,
emptyNameRecord,
emptyRecord,
contactNameRecord,
channelNameRecord,
contactAndChannelNameRecord,
@@ -61,16 +61,14 @@ withNameResolver action = do
Just (AnswerRegistration registration) -> (ok200, J.encode NameResponse {lastBlockTs = Nothing, registration})
Nothing -> (ok200, J.encode NameResponse {lastBlockTs = Nothing, registration = NRAvailable {pricing = testPricing 1}})
-- | Register a name's domain to resolve to the given record, as a live registration.
-- | Register a name's domain to resolve to the given record.
registerName :: NameRegistry -> SimplexNameInfo -> NameRecord -> IO ()
registerName reg ni nameRecord =
registerRegistration reg ni NRRegistered {expires = Nothing, graceUntil = Nothing, reservedReason_ = Nothing, nameRecord}
-- | Register any registration the registry could answer with.
registerRegistration :: NameRegistry -> SimplexNameInfo -> NameRegistration -> IO ()
registerRegistration reg ni r = atomically $ modifyTVar' reg $ M.insert (registryKey ni) (AnswerRegistration r)
-- | A name that expired a day ago, renewable by its owner for another 30 days.
registerExpiredName :: NameRegistry -> SimplexNameInfo -> NameRecord -> IO ()
registerExpiredName reg ni nameRecord = do
RoundedSystemTime now <- getSystemSeconds
@@ -78,19 +76,15 @@ registerExpiredName reg ni nameRecord = do
graceUntil = Just $ RoundedSystemTime (now + 30 * 86400)
registerRegistration reg ni NRRegistered {expires, graceUntil, reservedReason_ = Nothing, nameRecord}
-- | A name the registry holds back.
registerReservedName :: NameRegistry -> SimplexNameInfo -> NameReservedReason -> IO ()
registerReservedName reg ni reservedReason = registerRegistration reg ni NRReserved {reservedReason}
-- | A name that is free, priced with the given minimum label length.
registerAvailableName :: NameRegistry -> SimplexNameInfo -> Int -> IO ()
registerAvailableName reg ni minLen = registerRegistration reg ni NRAvailable {pricing = testPricing minLen}
-- | Make the resolver fail for this name, as a registry that is down or erroring would.
failNameResolution :: NameRegistry -> SimplexNameInfo -> IO ()
failNameResolution reg ni = atomically $ modifyTVar' reg $ M.insert (registryKey ni) AnswerFails
-- | Drop a name, so it resolves as available again.
unregisterName :: NameRegistry -> SimplexNameInfo -> IO ()
unregisterName reg ni = atomically $ modifyTVar' reg $ M.delete (registryKey ni)
@@ -112,10 +106,6 @@ contactAndChannelNameRecord :: Text -> Text -> Text -> NameRecord
contactAndChannelNameRecord name contactLink channelLink =
(emptyRecord name) {nrSimplexContact = [contactLink], nrSimplexChannel = [channelLink]}
-- | A registered name whose record holds no usable link.
emptyNameRecord :: Text -> NameRecord
emptyNameRecord = emptyRecord
emptyRecord :: Text -> NameRecord
emptyRecord name =
NameRecord