-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
AdaptyPrice localizedString removes 2nd decimal if it is 0
in .getPaywallProducts
#123
Comments
0
0
in .getPaywallProducts
I've chatted with support about this, they had no clue what is going on. I used import * as RNLocalize from 'react-native-localize';
export function normalizePrice(amount: number, currencyCode: string) {
const locale = RNLocalize.getLocales()[0].languageTag;
return new Intl.NumberFormat(locale, {
style: 'currency',
currency: currencyCode,
minimumFractionDigits: 2
}).format(amount);
} usage: normalizePrice(
product?.price?.amount as number,
product?.price?.currencyCode as string
) |
Is anyone home? It's been 3 weeks since the issue was raised and the Intl method is prone to issues. You know we're paying (tons of) money for your product right? We expect support to be optimal at least. I've opened a ticket through Adapty's dashboard Help but the operators had no clue about this and they didn't even tried to forward this to your technical team. 👎 |
Day 35 and noone from adapty team has replied. Terrible support. |
Yes just a timeline or at least a response on this could be great 😕 |
@pkiler @efstathiosntonas hey, we sincerely apologize for the inconvenience we're investigating the issue now and will update you as soon as we have more information |
@vladd-g any update on this, it's been 1.5 months..... |
@efstathiosntonas, sorry for the wait. We'll let you know as soon as it's resolved |
@vladd-g any updates on this one? I hope you guys realize how IMPORTANT price formatting is for the buyers, right? |
@efstathiosntonas expecting to release it within 2 weeks |
@efstathiosntonas @pkiler could you please update to v2.11.3? and to v2.11.1 of AdaptyUI if you use it |
@vladd-g same thing, price should be {
"vendorProductId": "xxxxx",
"adaptyId": "xxxxx",
"localizedDescription": "xxxxxx,
"localizedTitle": "xxxxx",
"regionCode": "US",
"variationId": "xxxx",
"paywallABTestName": "Subscriptions",
"paywallName": "Subscriptions",
"price": {
"amount": 44,
"currencyCode": "USD",
"currencySymbol": "$",
"localizedString": "$44"
},
"subscriptionDetails": {
"subscriptionPeriod": {
"unit": "month",
"numberOfUnits": 1
},
"localizedSubscriptionPeriod": "1 month",
"ios": {
"subscriptionGroupIdentifier": "xxxx"
},
"android": {
"renewalType": "autorenewable"
}
},
"ios": {
"isFamilyShareable": false
}
} |
@efstathiosntonas We've studied how people and e-commerce in general display prices and found out that having decimal zeroes for whole prices isn't exactly a universal practice. Some services do display it, some don't. In our library we opted for a cleaner look for all the platforms. Also, when considering prices in App Store/Play Store in US/Europe — those typically have decimals of ".99" anyway, so this is rarely an issue. But there are countries with whole prices of in-app purchases in the range of hundreds, where having trailing ".00" takes up too much space. In summary: we opted for having 2 decimals for fractional prices for most cases and displaying whole numbers without the zero decimal part. However, you can alter the price rendering logic for your app should you decide to do so. |
@vladd-g What you studied versus the monetization standards for years is a totally different thing. This:
can be easily solved with an one line to strip out trailing fractions while the other way around is way harder and might lead to inaccurate results. A simple question to ChatGPT throws a bunch of reasons why prices should include decimals, even .00 ones. At least give us a config option to always display .00 decimals or not. |
|
@pkiler since they don't seem to understand the importance of this in favor of UI issues with long prices (lol) and my request to add a config value about it fell into void, use
diff --git a/node_modules/react-native-adapty/dist/adapty-handler.js b/node_modules/react-native-adapty/dist/adapty-handler.js
index c478d1e..f0087a5 100644
--- a/node_modules/react-native-adapty/dist/adapty-handler.js
+++ b/node_modules/react-native-adapty/dist/adapty-handler.js
@@ -110,6 +110,7 @@ class Adapty {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
// call before log ctx calls, so no logs are lost
const logLevel = params.logLevel;
+ const integers = params.integers;
logger_1.Log.logLevel = logLevel || null;
const ctx = new logger_1.LogContext();
const log = ctx.call({ methodName: 'activate' });
@@ -128,6 +129,9 @@ class Adapty {
if (logLevel) {
body.set('log_level', logLevel);
}
+ if (react_native_1.Platform.OS === 'ios') {
+ body.set('integers', integers);
+ }
if (react_native_1.Platform.OS === 'ios') {
if ((_a = params.ios) === null || _a === void 0 ? void 0 : _a.idfaCollectionDisabled) {
body.set('idfa_collection_disabled', params.ios.idfaCollectionDisabled);
diff --git a/node_modules/react-native-adapty/dist/bridge.d.ts b/node_modules/react-native-adapty/dist/bridge.d.ts
index aed9fbe..fdb5731 100644
--- a/node_modules/react-native-adapty/dist/bridge.d.ts
+++ b/node_modules/react-native-adapty/dist/bridge.d.ts
@@ -13,5 +13,5 @@ export declare const MODULE_NAME = "RNAdapty";
export declare class ParamMap extends GenericParamMap<ParamKey> {
constructor();
}
-export declare const $bridge: NativeRequestHandler<"activate" | "get_paywall" | "get_paywall_for_default_audience" | "get_paywall_products" | "get_products_introductory_offer_eligibility" | "get_profile" | "identify" | "log_show_onboarding" | "log_show_paywall" | "logout" | "make_purchase" | "not_implemented" | "present_code_redemption_sheet" | "restore_purchases" | "set_fallback_paywalls" | "set_log_level" | "set_variation_id" | "update_attribution" | "update_profile" | "__test__", ParamMap>;
+export declare const $bridge: NativeRequestHandler<"activate" | "get_paywall" | "get_paywall_for_default_audience" | "get_paywall_products" | "get_products_introductory_offer_eligibility" | "get_profile" | "identify" | "log_show_onboarding" | "log_show_paywall" | "logout" | "make_purchase" | "not_implemented" | "present_code_redemption_sheet" | "restore_purchases" | "set_fallback_paywalls" | "set_log_level" | "set_variation_id" | "update_attribution" | "update_profile" | "__test__", "integers", ParamMap>;
//# sourceMappingURL=bridge.d.ts.map
diff --git a/node_modules/react-native-adapty/dist/types/inputs.d.ts b/node_modules/react-native-adapty/dist/types/inputs.d.ts
index a1dda54..dc9b7ec 100644
--- a/node_modules/react-native-adapty/dist/types/inputs.d.ts
+++ b/node_modules/react-native-adapty/dist/types/inputs.d.ts
@@ -133,6 +133,11 @@ export interface ActivateParamsInput {
*/
idfaCollectionDisabled?: boolean;
};
+ /**
+ * if set to false then prices that have .00 will be displayed
+ * $1.00 instead of $1, defaults to true
+ */
+ integers?: boolean;
}
export interface GetPaywallProductsParamsInput {
}
diff --git a/node_modules/react-native-adapty/lib/ios/RNAConstants.swift b/node_modules/react-native-adapty/lib/ios/RNAConstants.swift
index 3efe59f..824c58c 100644
--- a/node_modules/react-native-adapty/lib/ios/RNAConstants.swift
+++ b/node_modules/react-native-adapty/lib/ios/RNAConstants.swift
@@ -28,6 +28,7 @@ public enum ParamKey: String {
case prefetch_products = "prefetch_products"
case custom_tags = "custom_tags"
case view_id = "view_id"
+ case integers = "integers"
}
public enum MethodName: String {
diff --git a/node_modules/react-native-adapty/lib/ios/RNAdapty.swift b/node_modules/react-native-adapty/lib/ios/RNAdapty.swift
index e546b50..165c465 100644
--- a/node_modules/react-native-adapty/lib/ios/RNAdapty.swift
+++ b/node_modules/react-native-adapty/lib/ios/RNAdapty.swift
@@ -217,6 +217,7 @@ class RNAdapty: RCTEventEmitter, AdaptyDelegate {
let observerMode: Bool? = ctx.params.getOptionalValue(for: .observerMode)
let idfaCollectionDisabled: Bool? = ctx.params.getOptionalValue(for: .idfaDisabled)
let ipAddressCollectionDisabled: Bool? = ctx.params.getOptionalValue(for: .ipAddressCollectionDisabled)
+ let integers: Bool? = ctx.params.getOptionalValue(for: .integers)
// Memoize activation args
MEMO_ACTIVATION_ARGS[ParamKey.sdkKey.rawValue] = apiKey
@@ -236,6 +237,7 @@ class RNAdapty: RCTEventEmitter, AdaptyDelegate {
.with(customerUserId: customerUserId)
.with(ipAddressCollectionDisabled: ipAddressCollectionDisabled ?? false)
.with(idfaCollectionDisabled: idfaCollectionDisabled ?? false)
+ .with(integers: integers ?? true)
.build()
Adapty.activate(with: configuration) { maybeErr in ctx.okOrForwardError(maybeErr) }
place this under diff --git a/cocoapods-patch-20240914-20930-9fo5ec/Adapty/Sources/Adapty+ChangeState.swift b/Pods/Adapty/Sources/Adapty+ChangeState.swift
index 791ae422d..93fe01185 100644
--- a/cocoapods-patch-20240914-20930-9fo5ec/Adapty/Sources/Adapty+ChangeState.swift
+++ b/Pods/Adapty/Sources/Adapty+ChangeState.swift
@@ -12,6 +12,7 @@ public final class Adapty {
let profileStorage: ProfileStorage
let apiKeyPrefix: String
let backend: Backend
+ let integers: Bool
let httpSession: HTTPSession
lazy var httpFallbackSession: HTTPSession = {
@@ -34,10 +35,12 @@ public final class Adapty {
profileStorage: ProfileStorage,
vendorIdsStorage: ProductVendorIdsStorage,
backend: Backend,
- customerUserId: String?
+ customerUserId: String?,
+ integers: Bool
) {
self.apiKeyPrefix = apiKeyPrefix
self.backend = backend
+ self.integers = integers
self.profileStorage = profileStorage
vendorIdsCache = ProductVendorIdsCache(storage: vendorIdsStorage)
diff --git a/cocoapods-patch-20240914-20930-9fo5ec/Adapty/Sources/Adapty.swift b/Pods/Adapty/Sources/Adapty.swift
index d36426398..245900e91 100644
--- a/cocoapods-patch-20240914-20930-9fo5ec/Adapty/Sources/Adapty.swift
+++ b/Pods/Adapty/Sources/Adapty.swift
@@ -71,7 +71,7 @@ extension Adapty {
"observer_mode": .value(configuration.observerMode),
"has_customer_user_id": .value(configuration.customerUserId != nil),
"idfa_collection_disabled": .value(configuration.idfaCollectionDisabled),
- "ip_address_collection_disabled": .value(configuration.ipAddressCollectionDisabled),
+ "ip_address_collection_disabled": .value(configuration.ipAddressCollectionDisabled)
]
async(completion, logName: logName, logParams: logParams) { completion in
@@ -88,6 +88,7 @@ extension Adapty {
Configuration.idfaCollectionDisabled = configuration.idfaCollectionDisabled
Configuration.ipAddressCollectionDisabled = configuration.ipAddressCollectionDisabled
Configuration.observerMode = configuration.observerMode
+ Configuration.integers = configuration.integers
let backend = Backend(with: configuration)
@@ -98,12 +99,13 @@ extension Adapty {
profileStorage: UserDefaults.standard,
vendorIdsStorage: UserDefaults.standard,
backend: backend,
- customerUserId: configuration.customerUserId
+ customerUserId: configuration.customerUserId,
+ integers: configuration.integers
)
LifecycleManager.shared.initialize()
- Log.info("Adapty activated withObserverMode:\(configuration.observerMode), withCustomerUserId: \(configuration.customerUserId != nil)")
+ Log.info("Adapty activated withObserverMode:\(configuration.observerMode), withCustomerUserId: \(configuration.customerUserId != nil), integers: \(configuration.integers)")
completion(nil)
}
}
diff --git a/cocoapods-patch-20240914-20930-9fo5ec/Adapty/Sources/Configuration.Builder.swift b/Pods/Adapty/Sources/Configuration.Builder.swift
index c8699b067..1ec16a9ad 100644
--- a/cocoapods-patch-20240914-20930-9fo5ec/Adapty/Sources/Configuration.Builder.swift
+++ b/Pods/Adapty/Sources/Configuration.Builder.swift
@@ -19,7 +19,8 @@ extension Adapty.Configuration {
backendBaseUrl: builder.backendBaseUrl,
backendFallbackBaseUrl: builder.backendFallbackBaseUrl,
backendConfigsBaseUrl: builder.backendConfigsBaseUrl,
- backendProxy: builder.backendProxy
+ backendProxy: builder.backendProxy,
+ integers: builder.integers
)
}
@@ -38,6 +39,7 @@ extension Adapty.Configuration {
public private(set) var backendFallbackBaseUrl: URL
public private(set) var backendConfigsBaseUrl: URL
public private(set) var backendProxy: (host: String, port: Int)?
+ public private(set) var integers: Bool
public convenience init(withAPIKey key: String) {
assert(key.count >= 41 && key.starts(with: "public_live"), "It looks like you have passed the wrong apiKey value to the Adapty SDK.")
@@ -56,6 +58,7 @@ extension Adapty.Configuration {
self.backendFallbackBaseUrl = configuration.backendFallbackBaseUrl
self.backendConfigsBaseUrl = configuration.backendConfigsBaseUrl
self.backendProxy = configuration.backendProxy
+ self.integers = configuration.integers
}
/// Call this method to get the ``Adapty.Configuration`` object.
@@ -117,5 +120,11 @@ extension Adapty.Configuration {
backendProxy = (host: host, port: port)
return self
}
+
+ /// - Parameter integers: A boolean value controlling prices format eg. $1.00 vs $1
+ public func with(integers value: Bool) -> Builder {
+ integers = value
+ return self
+ }
}
}
diff --git a/cocoapods-patch-20240914-20930-9fo5ec/Adapty/Sources/Configuration.swift b/Pods/Adapty/Sources/Configuration.swift
index 732a87542..ec7451631 100644
--- a/cocoapods-patch-20240914-20930-9fo5ec/Adapty/Sources/Configuration.swift
+++ b/Pods/Adapty/Sources/Configuration.swift
@@ -19,7 +19,8 @@ extension Adapty {
backendBaseUrl: Backend.publicEnvironmentBaseUrl,
backendFallbackBaseUrl: Backend.publicEnvironmentFallbackBaseUrl,
backendConfigsBaseUrl: Backend.publicEnvironmentConfigsBaseUrl,
- backendProxy: nil
+ backendProxy: nil,
+ integers: true
)
let apiKey: String
@@ -32,6 +33,7 @@ extension Adapty {
let backendFallbackBaseUrl: URL
let backendConfigsBaseUrl: URL
let backendProxy: (host: String, port: Int)?
+ let integers: Bool
}
}
@@ -39,6 +41,7 @@ extension Adapty.Configuration {
static var idfaCollectionDisabled: Bool = `default`.idfaCollectionDisabled
static var ipAddressCollectionDisabled: Bool = `default`.ipAddressCollectionDisabled
static var observerMode: Bool = `default`.observerMode
+ static var integers: Bool = `default`.integers
}
extension Adapty {
@@ -71,6 +74,8 @@ extension Adapty.Configuration: Decodable {
case backendProxyHost = "backend_proxy_host"
case backendProxyPort = "backend_proxy_port"
+
+ case integers = "integers"
}
public init(from decoder: any Decoder) throws {
@@ -97,5 +102,7 @@ extension Adapty.Configuration: Decodable {
} else {
backendProxy = Self.default.backendProxy
}
+ integers = try container.decodeIfPresent(Bool.self, forKey: .integers)
+ ?? Self.default.integers
}
}
diff --git a/cocoapods-patch-20240914-20930-9fo5ec/Adapty/Sources/Extensions/Locale+Extensions.swift b/Pods/Adapty/Sources/Extensions/Locale+Extensions.swift
index 7e6a5ed56..7ad3209a7 100644
--- a/cocoapods-patch-20240914-20930-9fo5ec/Adapty/Sources/Extensions/Locale+Extensions.swift
+++ b/Pods/Adapty/Sources/Extensions/Locale+Extensions.swift
@@ -22,6 +22,7 @@ public extension Locale {
}
}
+
extension AdaptyExtension where Extended == Locale {
var currencyCode: String? {
guard #available(macOS 13, iOS 16, tvOS 16, watchOS 9, visionOS 1.0, *) else {
@@ -41,8 +42,9 @@ extension AdaptyExtension where Extended == Locale {
let formatter = NumberFormatter()
formatter.numberStyle = .currency
formatter.locale = this
-
- if price.isInteger {
+ let integers = Adapty.shared?.integers ?? true
+
+ if integers && price.isInteger {
formatter.minimumFractionDigits = 0
formatter.maximumFractionDigits = 0
} On On then enter usage: await adapty.activate(<apiKey>, {
__debugDeferActivation: __DEV__,
integers: false <--- add this, setting it to true will show $1 as $1.00
}); Note that if you change the |
@vladd-g this is not stable because the device locale could be different from the Apple account region causing big issues with our customers seing prices in $ instead of € or vice versa or every other possible currency mismatch. example: I live in Europe but my Apple account is US based |
@vladd-g thank you for the update, 2.11.3 fixed the issue for us, our |
@efstathiosntonas thank you for sharing your detailed work around, in my case no prices are only whole numbers, so it was really only the second decimal that was missing from the localizedString. That said I would agree having the option to choose between displaying the |
Description
Currently, requesting paywall products that have prices with their 2nd decimal as
0
seems to truncate this decimal.Example response from
fetch/get-paywall-products
(callingAdapty.getPaywallProducts
):But calling
Adapty.makePurchase
opens the native purchase window, with the price displayed with its 2 decimals as expected:Currency in the screenshot is PEN, but might be a general issue with other currencies.
Version
2.10.1
What platforms are you seeing the problem on?
iOS
System info
The text was updated successfully, but these errors were encountered: