mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-09-29 04:43:32 +00:00
core, plan: correct badge purchase type references
This commit is contained in:
@@ -209,9 +209,17 @@ data BadgeAlert = BadgeAlert
|
||||
-- network.
|
||||
--
|
||||
-- @monthsLeft@ and @paidThrough@ come from the purchase's LAST ledger entry: the balance the
|
||||
-- client believes it holds, and 'Simplex.Chat.Badges.Months.addMonths' applied to it. Both are
|
||||
-- absent from a purchase with no ledger entry yet. @paidThrough@ is deliberately not the
|
||||
-- credential's expiry (UX §2.11 forbids presenting one as the other).
|
||||
-- client believes it holds, and 'Simplex.Chat.Badges.Months.addMonths' applied to it.
|
||||
--
|
||||
-- __They differ on a purchase with no ledger entry.__ @paidThrough@ is 'Nothing' — no entry, no
|
||||
-- date — while @monthsLeft@ is @0@, which is indistinguishable from a balance that has run out.
|
||||
-- Only @paidThrough@ separates "nothing is known yet" from "nothing is left", so a caller
|
||||
-- rendering both must branch on @paidThrough@, not on @monthsLeft == 0@. @monthsLeft@ is not a
|
||||
-- 'Maybe' because every other reader wants a number, and the one distinction it would carry is
|
||||
-- already carried next to it.
|
||||
--
|
||||
-- @paidThrough@ is deliberately not the credential's expiry (UX §2.11 forbids presenting one as
|
||||
-- the other).
|
||||
data UserBadge = UserBadge
|
||||
{ badgePurchaseId :: Int64,
|
||||
badgeType :: BadgeType,
|
||||
|
||||
@@ -1562,9 +1562,9 @@ data ChatErrorType
|
||||
-- @retryAfter@ is seconds, populated by the service's @rate_limited@. A failure with no
|
||||
-- service involved (a credential that does not verify) uses 'BSEInternal'.
|
||||
--
|
||||
-- The message field is named apart from the @message :: String@ that the rest of this union
|
||||
-- carries: a record field has one type across a whole data type, and this one is the wire's
|
||||
-- optional 'Text'.
|
||||
-- The message field is named apart from the @message :: String@ that 15 other constructors
|
||||
-- of this union carry: a record field has one type across a whole data type, and this one is
|
||||
-- the wire's optional 'Text'.
|
||||
CEBadgeServiceError {badgeError :: BadgeServiceErrorCode, badgeErrorMessage :: Maybe Text, retryAfter :: Maybe Word32}
|
||||
| CEInternalError {message :: String}
|
||||
| CEException {message :: String}
|
||||
|
||||
@@ -5205,7 +5205,7 @@ presentUserBadgeToContacts :: User -> CM ()
|
||||
presentUserBadgeToContacts user' = do
|
||||
cxt <- asks $ mkStoreCxt . config
|
||||
contacts <- withFastStore' $ \db -> getUserContacts db cxt user'
|
||||
withChatLock "addUserBadge" $ forM_ contacts $ \ct ->
|
||||
withChatLock "presentUserBadgeToContacts" $ forM_ contacts $ \ct ->
|
||||
case contactSendConn_ ct of
|
||||
Right conn
|
||||
| not (connIncognito conn) -> do
|
||||
|
||||
@@ -100,12 +100,15 @@ import Database.SQLite.Simple.QQ (sql)
|
||||
-- | The client's own projection of a @badge_purchases@ row: exactly its columns, with the
|
||||
-- client-only @user_id@ and @purchase_priv_key@ that the service's table does not have.
|
||||
--
|
||||
-- This is deliberately NOT 'Simplex.Chat.Badges.Types.BadgePurchase'. That record declares
|
||||
-- @priceId@, @offerId@ and @credential@, none of which is a column of this table: the price and
|
||||
-- offer of a purchase live on its @badge_invoices@ rows (one per invoice, so not a function of
|
||||
-- the purchase), and the credential lives on its @badge_issuances@ rows (one per period). A row
|
||||
-- type that had to invent three fields to be constructed would report a purchase the database
|
||||
-- does not hold. 'BadgeService.Store.BadgePurchaseRow' is the same decision on the service side.
|
||||
-- This is deliberately NOT the single shared purchase record core §3 drafted as
|
||||
-- @Badges.Types.BadgePurchase@. That draft declared @priceId@, @offerId@ and @credential@, none
|
||||
-- of which is a column of this table: the price and offer of a purchase live on its
|
||||
-- @badge_invoices@ rows (one per invoice, so not a function of the purchase), and the credential
|
||||
-- lives on its @badge_issuances@ rows (one per period). A row type that had to invent three
|
||||
-- fields to be constructed would report a purchase the database does not hold.
|
||||
-- 'BadgeService.Store.BadgePurchaseRow' is the same decision on the service side. C2 deleted the
|
||||
-- draft once both row types existed and split its API half off as
|
||||
-- 'Simplex.Chat.Badges.Types.UserBadge', which carries no secrets and so may cross the FFI.
|
||||
data UserBadgePurchase = UserBadgePurchase
|
||||
{ badgePurchaseId :: Int64,
|
||||
userId :: UserId,
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
module Simplex.Chat.Terminal.Main where
|
||||
|
||||
import Control.Applicative ((<|>))
|
||||
import Control.Concurrent (forkIO, threadDelay)
|
||||
import Control.Concurrent.STM
|
||||
import Control.Monad
|
||||
@@ -37,7 +38,7 @@ simplexChatCLI cfg server_ = do
|
||||
badgeOptsOverride :: ChatConfig -> ChatOpts -> ChatConfig
|
||||
badgeOptsOverride cfg ChatOpts {optBadgeServiceAddress, optBadgeWebUrl, optBadgeIssuerKeys} =
|
||||
cfg
|
||||
{ badgeServiceAddress = maybe (badgeServiceAddress cfg) Just optBadgeServiceAddress,
|
||||
{ badgeServiceAddress = optBadgeServiceAddress <|> badgeServiceAddress cfg,
|
||||
badgeWebBaseUrl = fromMaybe (badgeWebBaseUrl cfg) optBadgeWebUrl,
|
||||
badgePublicKeys = if null optBadgeIssuerKeys then badgePublicKeys cfg else M.fromList optBadgeIssuerKeys
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user