mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-11-12 09:28:09 +00:00
core: alerts with information about registering names (#7653)
* minimal api change * embed status. reduce * drop fake owner change * no-valid-link fix * add UX flow for name lookups * diagram edits * corrections * update name lookup API * manual renaming * implement core + cli * implement UI * fix * build iOS app blindly * shrink diff * fix review comments * review iterations * opuse 5.5 /goal iterations * fixes EP review * fixes * fixes * short goal iterations * refactor core-UI API to NameWarning with logic in core * diff cosmetics * simplify and normalize diagram * add excalidraw normalizer script and test git hook * cosmetics * commit wireframe collab doc to repo as README * review round on UX coverage * iterate on /goal * iterate on /goal * add tests * iterate on /goal * fix freshness bug with local chats: When core marks a chat verified for a name, it now first un-verifies the user's other chats of the same kind: - a contact name covers contacts and business chats; - a channel name covers channels. * align app divergences * docs fixes * iterations on /goal * align excalidraw * align and simplify core/UI/UXcanvas * 27 rounds of /goal * review * core: simplify connect plan with name lookup * simplify * cache names in a separate table * cache names resolution * wip * all * fix * remove cache * update plans * simplify * bot types * change types * simplify * update bot types * remove review * update view, tests * simplify "unverify" * update query plan * changes * simplify * test helpers * simpler * update query plans * fix * query plans * query plans * fixes * query plans --------- Co-authored-by: Alain Brenzikofer <alain@encointer.org> Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com>
This commit is contained in:
39 files changed
+2751
-385
No files matched your search
+47
-10
@@ -73,7 +73,7 @@ import qualified Simplex.Messaging.Crypto.Ratchet as CR
|
||||
import Simplex.Messaging.Encoding
|
||||
import Simplex.Messaging.Encoding.String
|
||||
import Simplex.Messaging.Parsers (dropPrefix, taggedObjectJSON)
|
||||
import Simplex.Messaging.Protocol (AProtoServerWithAuth (..), AProtocolType, BlockingInfo (..), BlockingReason (..), NetworkError (..), ProtocolServer (..), ProtocolTypeI, SProtocolType (..), UserProtocol)
|
||||
import Simplex.Messaging.Protocol (AProtoServerWithAuth (..), AProtocolType, BlockingInfo (..), BlockingReason (..), NetworkError (..), ProtocolServer (..), ProtocolTypeI, SProtocolType (..), USDCents (..), UserProtocol)
|
||||
import qualified Simplex.Messaging.Protocol as SMP
|
||||
import Simplex.Messaging.Transport.Client (TransportHost (..))
|
||||
import Simplex.Messaging.Util (safeDecodeUtf8, tshow)
|
||||
@@ -218,7 +218,7 @@ chatResponseToView hu cfg@ChatConfig {logLevel, showReactions, showFullLinks, te
|
||||
CRInvitation u ccLink _ -> ttyUser u $ viewConnReqInvitation showFullLinks ccLink
|
||||
CRConnectionIncognitoUpdated u c customUserProfile -> ttyUser u $ viewConnectionIncognitoUpdated c customUserProfile testView
|
||||
CRConnectionUserChanged u c c' nu -> ttyUser u $ viewConnectionUserChanged showFullLinks u c nu c'
|
||||
CRConnectionPlan u connLink _ otherSimplexName connectionPlan -> ttyUser u $ viewConnectionPlan cfg connLink connectionPlan <> otherSimplexNameNote otherSimplexName
|
||||
CRConnectionPlan u connLink planSimplexName otherSimplexName connectionPlan -> ttyUser u $ viewConnectionPlan cfg connLink planSimplexName connectionPlan <> otherSimplexNameNote otherSimplexName
|
||||
CRNewPreparedChat u (AChat _ (Chat cInfo _ _)) -> ttyUser u $ case cInfo of
|
||||
DirectChat ct -> [ttyContact' ct <> ": contact is prepared"]
|
||||
GroupChat g _ -> [ttyGroup' g <> ": group is prepared"]
|
||||
@@ -474,6 +474,7 @@ chatEventToView hu ChatConfig {logLevel, showReactions, showReceipts, testView}
|
||||
CEvtRcvFileAcceptedSndCancelled u ft -> ttyUser u $ viewRcvFileSndCancelled ft
|
||||
CEvtRcvFileProgressXFTP {} -> []
|
||||
CEvtContactUpdated {user = u, fromContact = c, toContact = c'} -> ttyUser u $ viewContactUpdated c c' <> viewContactPrefsUpdated u c c'
|
||||
CEvtNameMoved {} -> []
|
||||
CEvtGroupMemberUpdated {} -> []
|
||||
CEvtReceivedContactRequest u UserContactRequest {localDisplayName = c, profile} _chat -> ttyUser u $ viewReceivedContactRequest c (fromLocalProfile profile)
|
||||
CEvtServiceRequest u reqId sigKey_ req ->
|
||||
@@ -1171,13 +1172,14 @@ viewDomainVerified nameType domain_ result =
|
||||
Just reason -> [plain nameStr <> " not verified: " <> plain reason]
|
||||
|
||||
-- §4.7: show a peer's claimed name only with its verification context — "verified" / "verification
|
||||
-- failed" when a status is recorded, "unverified" when there is a proof but no status yet, and nothing
|
||||
-- failed" / "moved" when a status is recorded, "unverified" when there is a proof but no status yet, and nothing
|
||||
-- at all when there is neither (an unproven, unverifiable claim is not shown).
|
||||
simplexDomainLine :: SimplexNameType -> Maybe SimplexDomainClaim -> Maybe Bool -> [StyledString]
|
||||
simplexDomainLine :: SimplexNameType -> Maybe SimplexDomainClaim -> Maybe DomainVerification -> [StyledString]
|
||||
simplexDomainLine _ Nothing _ = []
|
||||
simplexDomainLine nameType (Just SimplexDomainClaim {domain, proof}) status = case status of
|
||||
Just True -> [line "verified"]
|
||||
Just False -> [line "verification failed"]
|
||||
Just DVVerified -> [line "verified"]
|
||||
Just DVFailed -> [line "verification failed"]
|
||||
Just DVMoved -> [line "moved"]
|
||||
Nothing
|
||||
| isJust proof -> [line "unverified"]
|
||||
| otherwise -> []
|
||||
@@ -2235,8 +2237,8 @@ otherSimplexNameNote = \case
|
||||
Just ni@(SimplexNameInfo NTContact _) -> [plain $ "You can also connect to " <> shortNameInfoStr ni <> " in direct chat"]
|
||||
Nothing -> []
|
||||
|
||||
viewConnectionPlan :: ChatConfig -> ACreatedConnLink -> ConnectionPlan -> [StyledString]
|
||||
viewConnectionPlan ChatConfig {logLevel, testView} _connLink = \case
|
||||
viewConnectionPlan :: ChatConfig -> ACreatedConnLink -> Maybe SimplexNameInfo -> ConnectionPlan -> [StyledString]
|
||||
viewConnectionPlan ChatConfig {logLevel, testView} _connLink planSimplexName = \case
|
||||
CPInvitationLink ilp -> case ilp of
|
||||
ILPOk contactSLinkData ov -> [invOrBiz contactSLinkData "ok to connect"] <> viewSigVerification ov <> [viewJSON contactSLinkData | testView]
|
||||
ILPOwnLink -> [invLink "own link"]
|
||||
@@ -2255,7 +2257,7 @@ viewConnectionPlan ChatConfig {logLevel, testView} _connLink = \case
|
||||
Just ContactShortLinkData {business}
|
||||
| business -> ("business address: " <>)
|
||||
_ -> ("invitation link: " <>)
|
||||
CPContactAddress cap -> case cap of
|
||||
p@(CPContactAddress cap nc_) -> (<> viewNameChange (connectionPlanOwnLink p) nc_) $ case cap of
|
||||
CAPOk contactSLinkData ov -> [addrOrBiz contactSLinkData "ok to connect"] <> viewSigVerification ov <> [viewJSON contactSLinkData | testView]
|
||||
CAPOwnLink -> [ctAddr "own address"]
|
||||
CAPConnectingConfirmReconnect -> [ctAddr "connecting, allowed to reconnect"]
|
||||
@@ -2273,7 +2275,7 @@ viewConnectionPlan ChatConfig {logLevel, testView} _connLink = \case
|
||||
Just ContactShortLinkData {business}
|
||||
| business -> ("business address: " <>)
|
||||
_ -> ("contact address: " <>)
|
||||
CPGroupLink glp -> case glp of
|
||||
p@(CPGroupLink glp nc_) -> (<> viewNameChange (connectionPlanOwnLink p) nc_) $ case glp of
|
||||
GLPOk groupSLinkInfo_ groupSLinkData ov ->
|
||||
let direct = maybe True (\(GroupShortLinkInfo {direct = d}) -> d) groupSLinkInfo_
|
||||
in [grpLink $ if direct then "ok to connect directly" else "ok to connect via relays"]
|
||||
@@ -2312,6 +2314,17 @@ viewConnectionPlan ChatConfig {logLevel, testView} _connLink = \case
|
||||
Nothing -> "group"
|
||||
CPError e -> viewChatError False logLevel testView e
|
||||
where
|
||||
viewNameChange :: Bool -> Maybe NameChange -> [StyledString]
|
||||
viewNameChange own = \case
|
||||
Just (NCLapsed w) -> maybe [] (\SimplexNameInfo {nameDomain} -> [viewNameWarning own nameDomain w]) planSimplexName
|
||||
Just (NCMoved (AChatInfo _ c)) -> case c of
|
||||
DirectChat ct -> ["known contact @" <> ttyContact' ct]
|
||||
GroupChat g@GroupInfo {businessChat} _
|
||||
| isJust businessChat -> ["known business " <> ttyGroup' g]
|
||||
| useRelays' g -> ["known channel " <> ttyGroup' g]
|
||||
| otherwise -> ["known group " <> ttyGroup' g]
|
||||
_ -> []
|
||||
Nothing -> []
|
||||
nextConnectPrepared Contact {preparedContact, activeConn} = case preparedContact of
|
||||
Just _ -> maybe True (\c -> connStatus c == ConnPrepared) activeConn
|
||||
_ -> False
|
||||
@@ -2327,6 +2340,29 @@ viewConnectionPlan ChatConfig {logLevel, testView} _connLink = \case
|
||||
Just (OVFailed r) -> ["owner signature: FAILED (" <> plain r <> ")"]
|
||||
Nothing -> []
|
||||
|
||||
viewNameWarning :: Bool -> SimplexDomain -> NameWarning -> StyledString
|
||||
viewNameWarning own d = \case
|
||||
NWExpired e g -> yours <> simplexNameStr d <> " expired on " <> plain (day e) <> maybe "" ((renewal <>) . plain . day) g
|
||||
NWAvailable p -> yours <> simplexNameStr d <> " is no longer registered, available: " <> namePriceStr p
|
||||
NWReservedForCommunity -> simplexNameStr d <> " is reserved for community"
|
||||
NWNotRegistered -> simplexNameStr d <> " is not registered"
|
||||
where
|
||||
yours = if own then "your " else ""
|
||||
renewal = if own then ", renew it before " else ", its owner can renew it until "
|
||||
|
||||
viewNameNotConnectable :: SimplexDomain -> NameWarning -> StyledString
|
||||
viewNameNotConnectable d = \case
|
||||
NWAvailable p -> simplexNameStr d <> " is available: " <> namePriceStr p
|
||||
w -> viewNameWarning False d w
|
||||
|
||||
simplexNameStr :: SimplexDomain -> StyledString
|
||||
simplexNameStr d = "SimpleX name " <> plain (fullDomainName d)
|
||||
|
||||
namePriceStr :: NamePrice -> StyledString
|
||||
namePriceStr NamePrice {amount = USDCents c, years} =
|
||||
let (dollars, cents) = c `divMod` 100
|
||||
in plain $ "$" <> tshow dollars <> (if cents == 0 then "" else "." <> T.justifyRight 2 '0' (tshow cents)) <> " for " <> tshow years <> " years"
|
||||
|
||||
viewContactUpdated :: Contact -> Contact -> [StyledString]
|
||||
viewContactUpdated
|
||||
Contact {localDisplayName = n, profile = LocalProfile {fullName, shortDescr, description, contactLink}}
|
||||
@@ -2795,6 +2831,7 @@ viewChatError isCmd logLevel testView = \case
|
||||
CEChatNotStopped -> ["error: chat not stopped"]
|
||||
CEChatStoreChanged -> ["error: chat store changed, please restart chat"]
|
||||
CEInvalidConnReq -> viewInvalidConnReq
|
||||
CESimplexDomainNotReady domain (SDENameWarning w) -> [viewNameNotConnectable domain w]
|
||||
CESimplexDomainNotReady domain domainErr ->
|
||||
let reason = case domainErr of
|
||||
SDENoValidLink -> "has no valid connection link"
|
||||
|
||||
Reference in new issue
Block a user