From 70355aa70edd77039aabef874a0b1de6a4316276 Mon Sep 17 00:00:00 2001 From: Alex Hart Date: Wed, 3 Nov 2021 09:38:42 -0300 Subject: [PATCH] Add server-based localization of subscription names and badge information. --- .../subscription/SubscriptionsRepository.kt | 4 +++- .../app/subscription/boost/BoostFragment.kt | 2 +- .../app/subscription/boost/BoostRepository.kt | 3 ++- .../manage/ActiveSubscriptionPreference.kt | 2 +- .../subscribe/SubscribeViewModel.kt | 2 +- .../securesms/subscription/Subscription.kt | 13 ++--------- app/src/main/res/values/strings.xml | 3 --- .../api/services/DonationsService.java | 9 ++++---- .../api/subscriptions/SubscriptionLevels.java | 9 +++++++- .../internal/push/PushServiceSocket.java | 22 ++++++++++++++----- 10 files changed, 40 insertions(+), 29 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/SubscriptionsRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/SubscriptionsRepository.kt index 9e34dc624e..71366a9463 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/SubscriptionsRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/SubscriptionsRepository.kt @@ -10,6 +10,7 @@ import org.whispersystems.signalservice.api.subscriptions.ActiveSubscription import org.whispersystems.signalservice.api.subscriptions.SubscriptionLevels import org.whispersystems.signalservice.internal.ServiceResponse import java.util.Currency +import java.util.Locale /** * Repository which can query for the user's active subscription as well as a list of available subscriptions, @@ -27,12 +28,13 @@ class SubscriptionsRepository(private val donationsService: DonationsService) { } } - fun getSubscriptions(currency: Currency): Single> = donationsService.subscriptionLevels + fun getSubscriptions(currency: Currency): Single> = donationsService.getSubscriptionLevels(Locale.getDefault()) .flatMap(ServiceResponse::flattenResult) .map { subscriptionLevels -> subscriptionLevels.levels.map { (code, level) -> Subscription( id = code, + name = level.name, badge = Badges.fromServiceBadge(level.badge), price = FiatMoney(level.currencies[currency.currencyCode]!!, currency), level = code.toInt() diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/boost/BoostFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/boost/BoostFragment.kt index 0cdb0b9b10..c90527c1b7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/boost/BoostFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/boost/BoostFragment.kt @@ -56,7 +56,7 @@ class BoostFragment : DSLSettingsBottomSheetFragment( .append(" ") .append( SpanUtil.learnMore(requireContext(), ContextCompat.getColor(requireContext(), R.color.signal_accent_primary)) { - CommunicationActions.openBrowserLink(requireContext(), R.string.sustainer_boost_and_badges) + CommunicationActions.openBrowserLink(requireContext(), getString(R.string.sustainer_boost_and_badges)) } ) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/boost/BoostRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/boost/BoostRepository.kt index 3418b2c888..89ee630f8f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/boost/BoostRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/boost/BoostRepository.kt @@ -9,6 +9,7 @@ import org.whispersystems.signalservice.api.services.DonationsService import org.whispersystems.signalservice.internal.ServiceResponse import java.math.BigDecimal import java.util.Currency +import java.util.Locale class BoostRepository(private val donationsService: DonationsService) { @@ -22,7 +23,7 @@ class BoostRepository(private val donationsService: DonationsService) { } fun getBoostBadge(): Single { - return donationsService.boostBadge + return donationsService.getBoostBadge(Locale.getDefault()) .flatMap(ServiceResponse::flattenResult) .map(Badges::fromServiceBadge) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/manage/ActiveSubscriptionPreference.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/manage/ActiveSubscriptionPreference.kt index 26019b32bf..3f312fc1c7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/manage/ActiveSubscriptionPreference.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/manage/ActiveSubscriptionPreference.kt @@ -45,7 +45,7 @@ object ActiveSubscriptionPreference { override fun bind(model: Model) { badge.setBadge(model.subscription.badge) - title.text = model.subscription.getTitle(context) + title.text = model.subscription.name price.text = context.getString( R.string.MySupportPreference__s_per_month, diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/subscribe/SubscribeViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/subscribe/SubscribeViewModel.kt index a858366111..1f77c94596 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/subscribe/SubscribeViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/subscribe/SubscribeViewModel.kt @@ -199,7 +199,7 @@ class SubscribeViewModel( store.update { it.copy(stage = SubscribeState.Stage.TOKEN_REQUEST) } subscriptionToPurchase = snapshot.selectedSubscription - donationPaymentRepository.requestTokenFromGooglePay(snapshot.selectedSubscription.price, snapshot.selectedSubscription.getTitle(context), fetchTokenRequestCode) + donationPaymentRepository.requestTokenFromGooglePay(snapshot.selectedSubscription.price, snapshot.selectedSubscription.name, fetchTokenRequestCode) } fun setSelectedSubscription(subscription: Subscription) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/subscription/Subscription.kt b/app/src/main/java/org/thoughtcrime/securesms/subscription/Subscription.kt index 4fe92b81ed..91834c0b06 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/subscription/Subscription.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/subscription/Subscription.kt @@ -1,6 +1,5 @@ package org.thoughtcrime.securesms.subscription -import android.content.Context import android.view.View import android.widget.ImageView import android.widget.TextView @@ -21,20 +20,12 @@ import java.util.Locale */ data class Subscription( val id: String, + val name: String, val badge: Badge, val price: FiatMoney, val level: Int, ) { - fun getTitle(context: Context): String { - return when (level) { - 500 -> context.getString(R.string.SubscribeFragment__sustainer_i) - 1000 -> context.getString(R.string.SubscribeFragment__sustainer_ii) - 2000 -> context.getString(R.string.SubscribeFragment__sustainer_iii) - else -> "" - } - } - companion object { fun register(adapter: MappingAdapter) { adapter.registerFactory(Model::class.java, MappingAdapter.LayoutFactory({ ViewHolder(it) }, R.layout.subscription_preference)) @@ -90,7 +81,7 @@ data class Subscription( badge.setBadge(model.subscription.badge) } - title.text = model.subscription.getTitle(context) + title.text = model.subscription.name tagline.text = context.getString(R.string.Subscription__earn_a_s_badge, model.subscription.badge.name) val formattedPrice = FiatMoneyUtil.format( diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9c19f6b99d..e1e497f809 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -3947,9 +3947,6 @@ Update You will be charged the full amount of the new subscription price today. Your subscription will renew %1$s. You will be charged the full amount (%1$s) of the new subscription price today. Your subscription will renew monthly. - Sustainer I - Sustainer II - Sustainer III %s/month %1$s/month ยท Renews %2$s diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/services/DonationsService.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/services/DonationsService.java index 75b76c73a9..1d22bd2c45 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/services/DonationsService.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/services/DonationsService.java @@ -22,6 +22,7 @@ import org.whispersystems.signalservice.internal.push.PushServiceSocket; import java.io.IOException; import java.math.BigDecimal; import java.util.List; +import java.util.Locale; import java.util.Map; import io.reactivex.rxjava3.annotations.NonNull; @@ -102,15 +103,15 @@ public class DonationsService { /** * @return The badge configuration for signal boost. Expect for right now only a single level numbered 1. */ - public Single> getBoostBadge() { - return createServiceResponse(() -> new Pair<>(pushServiceSocket.getBoostLevels().getLevels().get("1").getBadge(), 200)); + public Single> getBoostBadge(Locale locale) { + return createServiceResponse(() -> new Pair<>(pushServiceSocket.getBoostLevels(locale).getLevels().get("1").getBadge(), 200)); } /** * Returns the subscription levels that are available for the client to choose from along with currencies and current prices */ - public Single> getSubscriptionLevels() { - return createServiceResponse(() -> new Pair<>(pushServiceSocket.getSubscriptionLevels(), 200)); + public Single> getSubscriptionLevels(Locale locale) { + return createServiceResponse(() -> new Pair<>(pushServiceSocket.getSubscriptionLevels(locale), 200)); } /** diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/subscriptions/SubscriptionLevels.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/subscriptions/SubscriptionLevels.java index fc8237974a..afab47cde7 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/subscriptions/SubscriptionLevels.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/subscriptions/SubscriptionLevels.java @@ -28,17 +28,24 @@ public final class SubscriptionLevels { * An available subscription level */ public static final class Level { + private final String name; private final SignalServiceProfile.Badge badge; private final Map currencies; @JsonCreator - public Level(@JsonProperty("badge") SignalServiceProfile.Badge badge, + public Level(@JsonProperty("name") String name, + @JsonProperty("badge") SignalServiceProfile.Badge badge, @JsonProperty("currencies") Map currencies) { + this.name = name; this.badge = badge; this.currencies = currencies; } + public String getName() { + return name; + } + public SignalServiceProfile.Badge getBadge() { return badge; } diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java index 2cb9ce162d..d026dc2354 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java @@ -888,8 +888,8 @@ public class PushServiceSocket { return JsonUtil.fromJsonResponse(result, typeRef); } - public SubscriptionLevels getBoostLevels() throws IOException { - String result = makeServiceRequestWithoutAuthentication(BOOST_BADGES, "GET", null); + public SubscriptionLevels getBoostLevels(Locale locale) throws IOException { + String result = makeServiceRequestWithoutAuthentication(BOOST_BADGES, "GET", null, AcceptLanguagesUtil.getHeadersWithAcceptLanguage(locale)); return JsonUtil.fromJsonResponse(result, SubscriptionLevels.class); } @@ -912,8 +912,8 @@ public class PushServiceSocket { } - public SubscriptionLevels getSubscriptionLevels() throws IOException { - String result = makeServiceRequestWithoutAuthentication(SUBSCRIPTION_LEVELS, "GET", null); + public SubscriptionLevels getSubscriptionLevels(Locale locale) throws IOException { + String result = makeServiceRequestWithoutAuthentication(SUBSCRIPTION_LEVELS, "GET", null, AcceptLanguagesUtil.getHeadersWithAcceptLanguage(locale)); return JsonUtil.fromJsonResponse(result, SubscriptionLevels.class); } @@ -1530,7 +1530,19 @@ public class PushServiceSocket { private String makeServiceRequestWithoutAuthentication(String urlFragment, String method, String jsonBody, ResponseCodeHandler responseCodeHandler) throws NonSuccessfulResponseCodeException, PushNetworkException, MalformedResponseException { - ResponseBody responseBody = makeServiceRequest(urlFragment, method, jsonRequestBody(jsonBody), NO_HEADERS, responseCodeHandler, Optional.absent(), true).body(); + return makeServiceRequestWithoutAuthentication(urlFragment, method, jsonBody, NO_HEADERS, responseCodeHandler); + } + + private String makeServiceRequestWithoutAuthentication(String urlFragment, String method, String jsonBody, Map headers) + throws NonSuccessfulResponseCodeException, PushNetworkException, MalformedResponseException + { + return makeServiceRequestWithoutAuthentication(urlFragment, method, jsonBody, headers, NO_HANDLER); + } + + private String makeServiceRequestWithoutAuthentication(String urlFragment, String method, String jsonBody, Map headers, ResponseCodeHandler responseCodeHandler) + throws NonSuccessfulResponseCodeException, PushNetworkException, MalformedResponseException + { + ResponseBody responseBody = makeServiceRequest(urlFragment, method, jsonRequestBody(jsonBody), headers, responseCodeHandler, Optional.absent(), true).body(); try { return responseBody.string(); } catch (IOException e) {