diff --git a/apps/ios/Shared/Model/AppAPITypes.swift b/apps/ios/Shared/Model/AppAPITypes.swift index 2844d5b9cf..5a32493d24 100644 --- a/apps/ios/Shared/Model/AppAPITypes.swift +++ b/apps/ios/Shared/Model/AppAPITypes.swift @@ -756,7 +756,7 @@ enum ServicePayment: Encodable { } } -struct BadgeStorePurchase: Decodable { +struct OpenStorePurchase: Decodable { var invoiceId: String? var transactionRef: String? } @@ -1094,7 +1094,7 @@ enum ChatResponse2: Decodable, ChatAPIResult { // the full user, not UserRef: its profile carries the badge that setUserBadge just stored case badgeRedeemed(user: User, redeemedBadge: LocalBadge, newBadge: Bool, badgeState: BadgeState?) case badgeInvoice(user: UserRef, invoiceId: String) - case badgeState(user: UserRef, badgeState: BadgeState?, storePurchases: [BadgeStorePurchase]?) + case badgeState(user: UserRef, badgeState: BadgeState?, storePurchases: [OpenStorePurchase]?) case badgeLedger(user: UserRef, badgeLedger: [StatementEntry]) var responseType: String { diff --git a/apps/ios/Shared/Model/SimpleXAPI.swift b/apps/ios/Shared/Model/SimpleXAPI.swift index 6d47eb81a5..62760b043a 100644 --- a/apps/ios/Shared/Model/SimpleXAPI.swift +++ b/apps/ios/Shared/Model/SimpleXAPI.swift @@ -2245,13 +2245,13 @@ func redeemErrorText(_ error: Error) -> String { return String.localizedStringWithFormat(NSLocalizedString("Error: %@", comment: "alert message"), responseError(error)) } -func apiGetBadgeState(_ userId: Int64) async throws -> (badgeState: BadgeState?, storePurchases: [BadgeStorePurchase]) { +func apiGetBadgeState(_ userId: Int64) async throws -> (badgeState: BadgeState?, storePurchases: [OpenStorePurchase]) { let r: ChatResponse2 = try await chatSendCmd(.apiGetBadgeState(userId: userId)) if case let .badgeState(_, badgeState, storePurchases) = r { return (badgeState, storePurchases ?? []) } throw r.unexpected } -func apiGetBadgeStateSync(_ userId: Int64) throws -> (badgeState: BadgeState?, storePurchases: [BadgeStorePurchase]) { +func apiGetBadgeStateSync(_ userId: Int64) throws -> (badgeState: BadgeState?, storePurchases: [OpenStorePurchase]) { let r: ChatResponse2 = try chatSendCmdSync(.apiGetBadgeState(userId: userId)) if case let .badgeState(_, badgeState, storePurchases) = r { return (badgeState, storePurchases ?? []) } throw r.unexpected diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt index 3bb2bd1000..596df2ca0b 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt @@ -632,7 +632,7 @@ object ChatController { return "${generalGetString(MR.strings.error_prefix)}: ${err?.string ?: generalGetString(MR.strings.badges_error_unknown)}" } - suspend fun apiGetBadgeState(rh: Long?, userId: Long): Pair> { + suspend fun apiGetBadgeState(rh: Long?, userId: Long): Pair> { val r = sendCmd(rh, CC.ApiGetBadgeState(userId)) if (r is API.Result && r.res is CR.BadgeStateR) return r.res.badgeState to r.res.storePurchases throw Exception("apiGetBadgeState: unexpected ${r.responseType}") @@ -3919,7 +3919,7 @@ sealed class BadgeRedeemResult { } @Serializable -data class BadgeStorePurchase(val invoiceId: String? = null, val transactionRef: String? = null) +data class OpenStorePurchase(val invoiceId: String? = null, val transactionRef: String? = null) sealed class BadgePurchaseResult { class Redeemed(val user: User, val badgeState: BadgeState?): BadgePurchaseResult() @@ -6929,7 +6929,7 @@ sealed class CR { // the full user, not UserRef: its profile carries the badge that setUserBadge just stored @Serializable @SerialName("badgeRedeemed") class BadgeRedeemed(val user: User, val redeemedBadge: LocalBadge, val newBadge: Boolean, val badgeState: BadgeState?): CR() @Serializable @SerialName("badgeInvoice") class BadgeInvoice(val user: UserRef, val invoiceId: String): CR() - @Serializable @SerialName("badgeState") class BadgeStateR(val user: UserRef, val badgeState: BadgeState?, val storePurchases: List = emptyList()): CR() + @Serializable @SerialName("badgeState") class BadgeStateR(val user: UserRef, val badgeState: BadgeState?, val storePurchases: List = emptyList()): CR() @Serializable @SerialName("badgeLedger") class BadgeLedger(val user: UserRef, val badgeLedger: List): CR() @Serializable @SerialName("badgeChanged") class BadgeChanged(val user: User, val badgeState: BadgeState?): CR() @Serializable @SerialName("badgeAlert") class BadgeAlertR(val user: UserRef, val badgeAlert: BadgeAlert): CR() diff --git a/src/Simplex/Chat/Badges/Types.hs b/src/Simplex/Chat/Badges/Types.hs index 66c55b4f31..dacf5e80f8 100644 --- a/src/Simplex/Chat/Badges/Types.hs +++ b/src/Simplex/Chat/Badges/Types.hs @@ -30,7 +30,7 @@ module Simplex.Chat.Badges.Types BadgeAlert (..), BadgeAlertPrice (..), BadgeState (..), - BadgeStorePurchase (..), + OpenStorePurchase (..), ) where import Control.Applicative ((<|>)) @@ -286,7 +286,7 @@ data BadgeState = BadgeState -- | One of a profile's open store purchases, neither credited nor closed. The app matches invoiceId -- against the transactions its store still holds; transactionRef is set once a receipt arrived. -- Neither reference is a secret: Apple's is the transaction id, Google's is a hash of the token. -data BadgeStorePurchase = BadgeStorePurchase +data OpenStorePurchase = OpenStorePurchase { invoiceId :: Maybe Text, transactionRef :: Maybe Text } @@ -424,4 +424,4 @@ $(JQ.deriveJSON defaultJSON ''BadgeIssueError) $(JQ.deriveJSON defaultJSON ''BadgeState) -$(JQ.deriveJSON defaultJSON ''BadgeStorePurchase) +$(JQ.deriveJSON defaultJSON ''OpenStorePurchase) diff --git a/src/Simplex/Chat/Controller.hs b/src/Simplex/Chat/Controller.hs index 48ef80bae1..4cf1b19f8f 100644 --- a/src/Simplex/Chat/Controller.hs +++ b/src/Simplex/Chat/Controller.hs @@ -85,7 +85,7 @@ import Simplex.Messaging.Client (HostMode (..), SMPProxyFallback (..), SMPProxyM import qualified Simplex.Messaging.Crypto as C import Simplex.Chat.Badges (BadgeCredential, FileSizeLimits, LocalBadge) import Simplex.Chat.Badges.Service (BadgeServiceErrorCode, StatementEntry) -import Simplex.Chat.Badges.Types (BadgeAlert (..), BadgeAlertKind, BadgeState (..), BadgeStorePurchase (..)) +import Simplex.Chat.Badges.Types (BadgeAlert (..), BadgeAlertKind, BadgeState (..), OpenStorePurchase (..)) import Simplex.Chat.PaymentService (ServicePayment) import Simplex.Messaging.Crypto.BBS (BBSPublicKey) import Simplex.Messaging.Crypto.File (CryptoFile (..)) @@ -874,7 +874,7 @@ data ChatResponse | CRServiceReplyAccepted {user :: User, connectionId :: AgentConnId} | CRBadgeRedeemed {user :: User, redeemedBadge :: LocalBadge, newBadge :: Bool, badgeState :: Maybe BadgeState} | CRBadgeInvoice {user :: User, invoiceId :: Text} - | CRBadgeState {user :: User, badgeState :: Maybe BadgeState, storePurchases :: [BadgeStorePurchase]} + | CRBadgeState {user :: User, badgeState :: Maybe BadgeState, storePurchases :: [OpenStorePurchase]} | CRBadgeLedger {user :: User, badgeLedger :: [StatementEntry]} | CRUserAcceptedGroupSent {user :: User, groupInfo :: GroupInfo, hostContact :: Maybe Contact} | CRUserDeletedMembers {user :: User, groupInfo :: GroupInfo, members :: [GroupMember], withMessages :: Bool, msgSigned :: Bool} diff --git a/src/Simplex/Chat/Library/Commands.hs b/src/Simplex/Chat/Library/Commands.hs index ec967563cc..3d9362033f 100644 --- a/src/Simplex/Chat/Library/Commands.hs +++ b/src/Simplex/Chat/Library/Commands.hs @@ -5502,7 +5502,7 @@ emitBadgeAlert user emitted p@UserBadgePurchase {alertSnoozeUntil} shownCred now badgeStateResponse :: User -> CM ChatResponse badgeStateResponse user = do badgeState <- getUserBadgeState user - CRBadgeState user badgeState <$> withStore' (`getOpenBadgeStorePurchases` user) + CRBadgeState user badgeState <$> withStore' (`getOpenStorePurchases` user) -- | Read from stored rows alone; the worker's results follow as CEvtBadgeChanged. getUserBadgeState :: User -> CM (Maybe BadgeState) diff --git a/src/Simplex/Chat/Store/Badges.hs b/src/Simplex/Chat/Store/Badges.hs index e17ab89038..484d634d79 100644 --- a/src/Simplex/Chat/Store/Badges.hs +++ b/src/Simplex/Chat/Store/Badges.hs @@ -23,7 +23,7 @@ module Simplex.Chat.Store.Badges getBadgeStoreReceiptUserId, attachBadgeStoreReceipt, closeBadgeStoreInvoice, - getOpenBadgeStorePurchases, + getOpenStorePurchases, getBadgeStoreReceipt, createBadgeStoreReceipt, deleteBadgeStash, @@ -51,7 +51,7 @@ import Data.Time.Clock (UTCTime) import Simplex.Chat.Badges import Simplex.Chat.Badges.Ledger import Simplex.Chat.Badges.Service (StatementCreditType (..), StatementDebitType (..), StatementEntry (..), StatementEntryType (..)) -import Simplex.Chat.Badges.Types (BadgeAlertKind, BadgeIssueError (..), BadgeIssueFailure, BadgePurchaseStatus (..), BadgeStorePurchase (..)) +import Simplex.Chat.Badges.Types (BadgeAlertKind, BadgeIssueError (..), BadgeIssueFailure, BadgePurchaseStatus (..), OpenStorePurchase (..)) import Simplex.Chat.Store.Shared (insertedRowId) import Simplex.Chat.Types import Simplex.Messaging.Agent.Protocol (UserId) @@ -145,9 +145,9 @@ closeBadgeStoreInvoice db User {userId} invoiceId now = "UPDATE badge_store_receipts SET closed_at = ? WHERE user_id = ? AND invoice_id = ? AND transaction_ref IS NULL" (now, userId, invoiceId) -getOpenBadgeStorePurchases :: DB.Connection -> User -> IO [BadgeStorePurchase] -getOpenBadgeStorePurchases db User {userId} = - map (uncurry BadgeStorePurchase) +getOpenStorePurchases :: DB.Connection -> User -> IO [OpenStorePurchase] +getOpenStorePurchases db User {userId} = + map (uncurry OpenStorePurchase) <$> DB.query db [sql| diff --git a/src/Simplex/Chat/View.hs b/src/Simplex/Chat/View.hs index 63d38e6f32..13cdb539a2 100644 --- a/src/Simplex/Chat/View.hs +++ b/src/Simplex/Chat/View.hs @@ -46,7 +46,7 @@ import Simplex.Chat.Markdown import Simplex.Chat.Badges (BadgeInfo (..), BadgeStatus (..), BadgeType (..), LocalBadge, localBadgeInfo, localBadgeStatus) import Simplex.Chat.Badges.Ledger (creditTypeTag, debitTypeTag) import Simplex.Chat.Badges.Service (StatementEntry (..), StatementEntryType (..)) -import Simplex.Chat.Badges.Types (BadgeAlert (..), BadgeIssueError (..), BadgeState (..), BadgeStorePurchase (..)) +import Simplex.Chat.Badges.Types (BadgeAlert (..), BadgeIssueError (..), BadgeState (..), OpenStorePurchase (..)) import Simplex.Chat.Messages hiding (NewChatItem (..)) import Simplex.Chat.Messages.CIContent import Simplex.Chat.Operators @@ -194,7 +194,7 @@ chatResponseToView hu cfg@ChatConfig {logLevel, showReactions, showFullLinks, te -- the badge is only shown when it is the one now on the profile; a replayed code's badge may not be CRBadgeRedeemed u badge newBadge _ -> ttyUser u $ if newBadge then "badge redeemed" : viewContactBadge (Just badge) else ["badge already redeemed"] CRBadgeInvoice u invoiceId -> ttyUser u ["badge invoice: " <> plain invoiceId] - CRBadgeState u st storePurchases -> ttyUser u $ viewUserBadgeState st <> map viewBadgeStorePurchase storePurchases + CRBadgeState u st storePurchases -> ttyUser u $ viewUserBadgeState st <> map viewOpenStorePurchase storePurchases CRBadgeLedger u entries -> ttyUser u $ viewBadgeLedger entries CRGroupCreated u g -> ttyUser u $ viewGroupCreated g testView CRPublicGroupCreated u g _groupLink _relays -> ttyUser u $ viewGroupCreated g testView @@ -1864,8 +1864,8 @@ viewBadgeIssueError BadgeIssueError {failedSince, lastAttemptAt, reason} = viewBadgeAlert :: BadgeAlert -> [StyledString] viewBadgeAlert BadgeAlert {kind, date} = [plain $ "badge alert: " <> textEncode kind <> " " <> day date] -viewBadgeStorePurchase :: BadgeStorePurchase -> StyledString -viewBadgeStorePurchase BadgeStorePurchase {invoiceId, transactionRef} = +viewOpenStorePurchase :: OpenStorePurchase -> StyledString +viewOpenStorePurchase OpenStorePurchase {invoiceId, transactionRef} = plain $ "store purchase open: invoice " <> fromMaybe "none" invoiceId <> maybe "" (", transaction " <>) transactionRef viewBadgeLedger :: [StatementEntry] -> [StyledString]