Various improvements

This commit is contained in:
Ilya Laktyushin 2024-05-28 13:06:02 +04:00
parent 27afb74b62
commit 51b262afac
8 changed files with 83 additions and 7 deletions

View File

@ -7799,6 +7799,7 @@ Sorry for the inconvenience.";
"Premium.Purchase.ErrorNetwork" = "Please check your internet connection and try again.";
"Premium.Purchase.ErrorNotAllowed" = "The device is not not allowed to make the payment.";
"Premium.Purchase.ErrorCantMakePayments" = "In-app purchases are not allowed on this device.";
"Premium.Purchase.ErrorTryLater" = "An error occurred. Please try again.";
"Premium.Restore.Success" = "Done";
"Premium.Restore.ErrorUnknown" = "An error occurred. Please try again.";
@ -12286,6 +12287,7 @@ Sorry for the inconvenience.";
"Stars.Transaction.FragmentTopUp.Title" = "Stars Top-Up";
"Stars.Transaction.FragmentTopUp.Subtitle" = "Fragment";
"Stars.Transaction.Unsupported.Title" = "Unsupported";
"Stars.Transaction.Refund" = "Refund";
"Stars.Transfer.Title" = "Confirm Your Purchase";
"Stars.Transfer.Info" = "Do you want to buy **%1$@** in **%2$@** for **%3$@**?";

View File

@ -184,6 +184,7 @@ public final class InAppPurchaseManager: NSObject {
case notAllowed
case cantMakePayments
case assignFailed
case tryLater
}
public enum RestoreState {
@ -219,6 +220,8 @@ public final class InAppPurchaseManager: NSObject {
private let stateQueue = Queue()
private var paymentContexts: [String: PaymentTransactionContext] = [:]
private var finishedSuccessfulTransactions = Set<String>()
private var onRestoreCompletion: ((RestoreState) -> Void)?
@ -315,6 +318,12 @@ public final class InAppPurchaseManager: NSObject {
mappedError = .network
case .paymentNotAllowed, .clientInvalid:
mappedError = .notAllowed
case .unknown:
if let _ = error.userInfo["tryLater"] {
mappedError = .tryLater
} else {
mappedError = .generic
}
default:
mappedError = .generic
}
@ -400,9 +409,15 @@ extension InAppPurchaseManager: SKPaymentTransactionObserver {
let transactionState: TransactionState?
switch transaction.transactionState {
case .purchased:
Logger.shared.log("InAppPurchaseManager", "Account \(accountPeerId), transaction \(transaction.transactionIdentifier ?? ""), original transaction \(transaction.original?.transactionIdentifier ?? "none") purchased")
transactionState = .purchased(transactionId: transaction.transactionIdentifier)
transactionsToAssign.append(transaction)
if transaction.payment.productIdentifier.contains(".topup."), let transactionIdentifier = transaction.transactionIdentifier, self.finishedSuccessfulTransactions.contains(transactionIdentifier) {
Logger.shared.log("InAppPurchaseManager", "Account \(accountPeerId), transaction \(transaction.transactionIdentifier ?? ""), original transaction \(transaction.original?.transactionIdentifier ?? "none") seems to be already reported, ask to try later")
transactionState = .failed(error: SKError(SKError.Code.unknown, userInfo: ["tryLater": true]))
queue.finishTransaction(transaction)
} else {
Logger.shared.log("InAppPurchaseManager", "Account \(accountPeerId), transaction \(transaction.transactionIdentifier ?? ""), original transaction \(transaction.original?.transactionIdentifier ?? "none") purchased")
transactionState = .purchased(transactionId: transaction.transactionIdentifier)
transactionsToAssign.append(transaction)
}
case .restored:
Logger.shared.log("InAppPurchaseManager", "Account \(accountPeerId), transaction \(transaction.transactionIdentifier ?? ""), original transaction \(transaction.original?.transactionIdentifier ?? "") restroring")
let transactionIdentifier = transaction.transactionIdentifier
@ -490,6 +505,12 @@ extension InAppPurchaseManager: SKPaymentTransactionObserver {
self.debugSaveReceipt(receiptData: receiptData)
#endif
for transaction in transactionsToAssign {
if let transactionIdentifier = transaction.transactionIdentifier {
self.finishedSuccessfulTransactions.insert(transactionIdentifier)
}
}
self.disposableSet.set(
(purpose
|> castError(AssignAppStoreTransactionError.self)

View File

@ -1163,6 +1163,8 @@ public func createGiveawayController(context: AccountContext, updatedPresentatio
errorText = presentationData.strings.Premium_Purchase_ErrorCantMakePayments
case .assignFailed:
errorText = presentationData.strings.Premium_Purchase_ErrorUnknown
case .tryLater:
errorText = presentationData.strings.Premium_Purchase_ErrorUnknown
case .cancelled:
break
}

View File

@ -955,6 +955,8 @@ private final class PremiumGiftScreenComponent: CombinedComponent {
errorText = presentationData.strings.Premium_Purchase_ErrorCantMakePayments
case .assignFailed:
errorText = presentationData.strings.Premium_Purchase_ErrorUnknown
case .tryLater:
errorText = presentationData.strings.Premium_Purchase_ErrorUnknown
case .cancelled:
break
}

View File

@ -3113,6 +3113,8 @@ private final class PremiumIntroScreenComponent: CombinedComponent {
errorText = presentationData.strings.Premium_Purchase_ErrorCantMakePayments
case .assignFailed:
errorText = presentationData.strings.Premium_Purchase_ErrorUnknown
case .tryLater:
errorText = presentationData.strings.Premium_Purchase_ErrorUnknown
case .cancelled:
break
}

View File

@ -231,7 +231,7 @@ private final class StarsContextImpl {
private extension StarsContext.State.Transaction {
init?(apiTransaction: Api.StarsTransaction, transaction: Transaction) {
switch apiTransaction {
case let .starsTransaction(_, id, stars, date, transactionPeer, title, description, photo):
case let .starsTransaction(apiFlags, id, stars, date, transactionPeer, title, description, photo):
let parsedPeer: StarsContext.State.Transaction.Peer
switch transactionPeer {
case .starsTransactionPeerAppStore:
@ -250,7 +250,12 @@ private extension StarsContext.State.Transaction {
}
parsedPeer = .peer(EnginePeer(peer))
}
self.init(flags: [], id: id, count: stars, date: date, peer: parsedPeer, title: title, description: description, photo: photo.flatMap(TelegramMediaWebFile.init))
var flags: Flags = []
if (apiFlags & (1 << 3)) != 0 {
flags.insert(.isRefund)
}
self.init(flags: flags, id: id, count: stars, date: date, peer: parsedPeer, title: title, description: description, photo: photo.flatMap(TelegramMediaWebFile.init))
}
}
}

View File

@ -663,6 +663,8 @@ private final class StarsPurchaseScreenComponent: CombinedComponent {
errorText = presentationData.strings.Premium_Purchase_ErrorCantMakePayments
case .assignFailed:
errorText = presentationData.strings.Premium_Purchase_ErrorUnknown
case .tryLater:
errorText = presentationData.strings.Premium_Purchase_ErrorTryLater
case .cancelled:
break
}

View File

@ -125,6 +125,9 @@ private final class StarsTransactionSheetContent: CombinedComponent {
let additional = Child(BalancedTextComponent.self)
let button = Child(SolidRoundedButtonComponent.self)
let refundBackgound = Child(RoundedRectangle.self)
let refundText = Child(MultilineTextComponent.self)
return { context in
let environment = context.environment[ViewControllerComponentContainer.Environment.self].value
let controller = environment.controller
@ -172,6 +175,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
let toPeer: EnginePeer?
let transactionPeer: StarsContext.State.Transaction.Peer?
let photo: TelegramMediaWebFile?
let isRefund: Bool
var delayedCloseOnOpenPeer = true
switch subject {
@ -208,6 +212,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
}
transactionPeer = transaction.peer
photo = transaction.photo
isRefund = transaction.flags.contains(.isRefund)
case let .receipt(receipt):
titleText = receipt.invoiceMedia.title
descriptionText = receipt.invoiceMedia.description
@ -222,6 +227,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
}
transactionPeer = nil
photo = receipt.invoiceMedia.photo
isRefund = false
delayedCloseOnOpenPeer = false
}
@ -455,11 +461,45 @@ private final class StarsTransactionSheetContent: CombinedComponent {
originY += description.size.height + 10.0
}
let amountSpacing: CGFloat = 3.0
var totalAmountWidth: CGFloat = amount.size.width + amountSpacing + amountStar.size.width
var amountOriginX: CGFloat = floor(context.availableSize.width - totalAmountWidth) / 2.0
if isRefund {
let refundText = refundText.update(
component: MultilineTextComponent(
text: .plain(NSAttributedString(
string: strings.Stars_Transaction_Refund,
font: Font.medium(14.0),
textColor: theme.list.itemDisclosureActions.constructive.fillColor
))
),
availableSize: context.availableSize,
transition: .immediate
)
let refundBackground = refundBackgound.update(
component: RoundedRectangle(
color: theme.list.itemDisclosureActions.constructive.fillColor.withAlphaComponent(0.1),
cornerRadius: 6.0
),
availableSize: CGSize(width: refundText.size.width + 10.0, height: refundText.size.height + 4.0),
transition: .immediate
)
totalAmountWidth += amountSpacing * 2.0 + refundBackground.size.width
amountOriginX = floor(context.availableSize.width - totalAmountWidth) / 2.0
context.add(refundBackground
.position(CGPoint(x: amountOriginX + amount.size.width + amountSpacing + amountStar.size.width + amountSpacing * 2.0 + refundBackground.size.width / 2.0, y: originY + refundBackground.size.height / 2.0))
)
context.add(refundText
.position(CGPoint(x: amountOriginX + amount.size.width + amountSpacing + amountStar.size.width + amountSpacing * 2.0 + refundBackground.size.width / 2.0, y: originY + refundBackground.size.height / 2.0))
)
}
context.add(amount
.position(CGPoint(x: context.availableSize.width / 2.0 - 10.0, y: originY + amount.size.height / 2.0))
.position(CGPoint(x: amountOriginX + amount.size.width / 2.0, y: originY + amount.size.height / 2.0))
)
context.add(amountStar
.position(CGPoint(x: context.availableSize.width / 2.0 + amount.size.width / 2.0 + amountStar.size.width / 2.0 - 7.0, y: originY + amountStar.size.height / 2.0))
.position(CGPoint(x: amountOriginX + amount.size.width + amountSpacing + amountStar.size.width / 2.0, y: originY + amountStar.size.height / 2.0))
)
originY += amount.size.height + 20.0