Add server-based localization of subscription names and badge information.
This commit is contained in:
parent
56c502c9bf
commit
70355aa70e
10 changed files with 40 additions and 29 deletions
|
@ -10,6 +10,7 @@ import org.whispersystems.signalservice.api.subscriptions.ActiveSubscription
|
||||||
import org.whispersystems.signalservice.api.subscriptions.SubscriptionLevels
|
import org.whispersystems.signalservice.api.subscriptions.SubscriptionLevels
|
||||||
import org.whispersystems.signalservice.internal.ServiceResponse
|
import org.whispersystems.signalservice.internal.ServiceResponse
|
||||||
import java.util.Currency
|
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,
|
* 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<List<Subscription>> = donationsService.subscriptionLevels
|
fun getSubscriptions(currency: Currency): Single<List<Subscription>> = donationsService.getSubscriptionLevels(Locale.getDefault())
|
||||||
.flatMap(ServiceResponse<SubscriptionLevels>::flattenResult)
|
.flatMap(ServiceResponse<SubscriptionLevels>::flattenResult)
|
||||||
.map { subscriptionLevels ->
|
.map { subscriptionLevels ->
|
||||||
subscriptionLevels.levels.map { (code, level) ->
|
subscriptionLevels.levels.map { (code, level) ->
|
||||||
Subscription(
|
Subscription(
|
||||||
id = code,
|
id = code,
|
||||||
|
name = level.name,
|
||||||
badge = Badges.fromServiceBadge(level.badge),
|
badge = Badges.fromServiceBadge(level.badge),
|
||||||
price = FiatMoney(level.currencies[currency.currencyCode]!!, currency),
|
price = FiatMoney(level.currencies[currency.currencyCode]!!, currency),
|
||||||
level = code.toInt()
|
level = code.toInt()
|
||||||
|
|
|
@ -56,7 +56,7 @@ class BoostFragment : DSLSettingsBottomSheetFragment(
|
||||||
.append(" ")
|
.append(" ")
|
||||||
.append(
|
.append(
|
||||||
SpanUtil.learnMore(requireContext(), ContextCompat.getColor(requireContext(), R.color.signal_accent_primary)) {
|
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))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import org.whispersystems.signalservice.api.services.DonationsService
|
||||||
import org.whispersystems.signalservice.internal.ServiceResponse
|
import org.whispersystems.signalservice.internal.ServiceResponse
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
import java.util.Currency
|
import java.util.Currency
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
class BoostRepository(private val donationsService: DonationsService) {
|
class BoostRepository(private val donationsService: DonationsService) {
|
||||||
|
|
||||||
|
@ -22,7 +23,7 @@ class BoostRepository(private val donationsService: DonationsService) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getBoostBadge(): Single<Badge> {
|
fun getBoostBadge(): Single<Badge> {
|
||||||
return donationsService.boostBadge
|
return donationsService.getBoostBadge(Locale.getDefault())
|
||||||
.flatMap(ServiceResponse<SignalServiceProfile.Badge>::flattenResult)
|
.flatMap(ServiceResponse<SignalServiceProfile.Badge>::flattenResult)
|
||||||
.map(Badges::fromServiceBadge)
|
.map(Badges::fromServiceBadge)
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ object ActiveSubscriptionPreference {
|
||||||
|
|
||||||
override fun bind(model: Model) {
|
override fun bind(model: Model) {
|
||||||
badge.setBadge(model.subscription.badge)
|
badge.setBadge(model.subscription.badge)
|
||||||
title.text = model.subscription.getTitle(context)
|
title.text = model.subscription.name
|
||||||
|
|
||||||
price.text = context.getString(
|
price.text = context.getString(
|
||||||
R.string.MySupportPreference__s_per_month,
|
R.string.MySupportPreference__s_per_month,
|
||||||
|
|
|
@ -199,7 +199,7 @@ class SubscribeViewModel(
|
||||||
store.update { it.copy(stage = SubscribeState.Stage.TOKEN_REQUEST) }
|
store.update { it.copy(stage = SubscribeState.Stage.TOKEN_REQUEST) }
|
||||||
|
|
||||||
subscriptionToPurchase = snapshot.selectedSubscription
|
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) {
|
fun setSelectedSubscription(subscription: Subscription) {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package org.thoughtcrime.securesms.subscription
|
package org.thoughtcrime.securesms.subscription
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
|
@ -21,20 +20,12 @@ import java.util.Locale
|
||||||
*/
|
*/
|
||||||
data class Subscription(
|
data class Subscription(
|
||||||
val id: String,
|
val id: String,
|
||||||
|
val name: String,
|
||||||
val badge: Badge,
|
val badge: Badge,
|
||||||
val price: FiatMoney,
|
val price: FiatMoney,
|
||||||
val level: Int,
|
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 {
|
companion object {
|
||||||
fun register(adapter: MappingAdapter) {
|
fun register(adapter: MappingAdapter) {
|
||||||
adapter.registerFactory(Model::class.java, MappingAdapter.LayoutFactory({ ViewHolder(it) }, R.layout.subscription_preference))
|
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)
|
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)
|
tagline.text = context.getString(R.string.Subscription__earn_a_s_badge, model.subscription.badge.name)
|
||||||
|
|
||||||
val formattedPrice = FiatMoneyUtil.format(
|
val formattedPrice = FiatMoneyUtil.format(
|
||||||
|
|
|
@ -3947,9 +3947,6 @@
|
||||||
<string name="SubscribeFragment__update">Update</string>
|
<string name="SubscribeFragment__update">Update</string>
|
||||||
<string name="SubscribeFragment__you_will_be_charged_the_full_amount">You will be charged the full amount of the new subscription price today. Your subscription will renew %1$s.</string>
|
<string name="SubscribeFragment__you_will_be_charged_the_full_amount">You will be charged the full amount of the new subscription price today. Your subscription will renew %1$s.</string>
|
||||||
<string name="SubscribeFragment__you_will_be_charged_the_full_amount_s_of">You will be charged the full amount (%1$s) of the new subscription price today. Your subscription will renew monthly.</string>
|
<string name="SubscribeFragment__you_will_be_charged_the_full_amount_s_of">You will be charged the full amount (%1$s) of the new subscription price today. Your subscription will renew monthly.</string>
|
||||||
<string name="SubscribeFragment__sustainer_i">Sustainer I</string>
|
|
||||||
<string name="SubscribeFragment__sustainer_ii">Sustainer II</string>
|
|
||||||
<string name="SubscribeFragment__sustainer_iii">Sustainer III</string>
|
|
||||||
|
|
||||||
<string name="Subscription__s_per_month">%s/month</string>
|
<string name="Subscription__s_per_month">%s/month</string>
|
||||||
<string name="Subscription__s_per_month_dot_renews_s">%1$s/month · Renews %2$s</string>
|
<string name="Subscription__s_per_month_dot_renews_s">%1$s/month · Renews %2$s</string>
|
||||||
|
|
|
@ -22,6 +22,7 @@ import org.whispersystems.signalservice.internal.push.PushServiceSocket;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import io.reactivex.rxjava3.annotations.NonNull;
|
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.
|
* @return The badge configuration for signal boost. Expect for right now only a single level numbered 1.
|
||||||
*/
|
*/
|
||||||
public Single<ServiceResponse<SignalServiceProfile.Badge>> getBoostBadge() {
|
public Single<ServiceResponse<SignalServiceProfile.Badge>> getBoostBadge(Locale locale) {
|
||||||
return createServiceResponse(() -> new Pair<>(pushServiceSocket.getBoostLevels().getLevels().get("1").getBadge(), 200));
|
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
|
* Returns the subscription levels that are available for the client to choose from along with currencies and current prices
|
||||||
*/
|
*/
|
||||||
public Single<ServiceResponse<SubscriptionLevels>> getSubscriptionLevels() {
|
public Single<ServiceResponse<SubscriptionLevels>> getSubscriptionLevels(Locale locale) {
|
||||||
return createServiceResponse(() -> new Pair<>(pushServiceSocket.getSubscriptionLevels(), 200));
|
return createServiceResponse(() -> new Pair<>(pushServiceSocket.getSubscriptionLevels(locale), 200));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -28,17 +28,24 @@ public final class SubscriptionLevels {
|
||||||
* An available subscription level
|
* An available subscription level
|
||||||
*/
|
*/
|
||||||
public static final class Level {
|
public static final class Level {
|
||||||
|
private final String name;
|
||||||
private final SignalServiceProfile.Badge badge;
|
private final SignalServiceProfile.Badge badge;
|
||||||
private final Map<String, BigDecimal> currencies;
|
private final Map<String, BigDecimal> currencies;
|
||||||
|
|
||||||
@JsonCreator
|
@JsonCreator
|
||||||
public Level(@JsonProperty("badge") SignalServiceProfile.Badge badge,
|
public Level(@JsonProperty("name") String name,
|
||||||
|
@JsonProperty("badge") SignalServiceProfile.Badge badge,
|
||||||
@JsonProperty("currencies") Map<String, BigDecimal> currencies)
|
@JsonProperty("currencies") Map<String, BigDecimal> currencies)
|
||||||
{
|
{
|
||||||
|
this.name = name;
|
||||||
this.badge = badge;
|
this.badge = badge;
|
||||||
this.currencies = currencies;
|
this.currencies = currencies;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
public SignalServiceProfile.Badge getBadge() {
|
public SignalServiceProfile.Badge getBadge() {
|
||||||
return badge;
|
return badge;
|
||||||
}
|
}
|
||||||
|
|
|
@ -888,8 +888,8 @@ public class PushServiceSocket {
|
||||||
return JsonUtil.fromJsonResponse(result, typeRef);
|
return JsonUtil.fromJsonResponse(result, typeRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SubscriptionLevels getBoostLevels() throws IOException {
|
public SubscriptionLevels getBoostLevels(Locale locale) throws IOException {
|
||||||
String result = makeServiceRequestWithoutAuthentication(BOOST_BADGES, "GET", null);
|
String result = makeServiceRequestWithoutAuthentication(BOOST_BADGES, "GET", null, AcceptLanguagesUtil.getHeadersWithAcceptLanguage(locale));
|
||||||
return JsonUtil.fromJsonResponse(result, SubscriptionLevels.class);
|
return JsonUtil.fromJsonResponse(result, SubscriptionLevels.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -912,8 +912,8 @@ public class PushServiceSocket {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public SubscriptionLevels getSubscriptionLevels() throws IOException {
|
public SubscriptionLevels getSubscriptionLevels(Locale locale) throws IOException {
|
||||||
String result = makeServiceRequestWithoutAuthentication(SUBSCRIPTION_LEVELS, "GET", null);
|
String result = makeServiceRequestWithoutAuthentication(SUBSCRIPTION_LEVELS, "GET", null, AcceptLanguagesUtil.getHeadersWithAcceptLanguage(locale));
|
||||||
return JsonUtil.fromJsonResponse(result, SubscriptionLevels.class);
|
return JsonUtil.fromJsonResponse(result, SubscriptionLevels.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1530,7 +1530,19 @@ public class PushServiceSocket {
|
||||||
private String makeServiceRequestWithoutAuthentication(String urlFragment, String method, String jsonBody, ResponseCodeHandler responseCodeHandler)
|
private String makeServiceRequestWithoutAuthentication(String urlFragment, String method, String jsonBody, ResponseCodeHandler responseCodeHandler)
|
||||||
throws NonSuccessfulResponseCodeException, PushNetworkException, MalformedResponseException
|
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<String, String> headers)
|
||||||
|
throws NonSuccessfulResponseCodeException, PushNetworkException, MalformedResponseException
|
||||||
|
{
|
||||||
|
return makeServiceRequestWithoutAuthentication(urlFragment, method, jsonBody, headers, NO_HANDLER);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String makeServiceRequestWithoutAuthentication(String urlFragment, String method, String jsonBody, Map<String, String> headers, ResponseCodeHandler responseCodeHandler)
|
||||||
|
throws NonSuccessfulResponseCodeException, PushNetworkException, MalformedResponseException
|
||||||
|
{
|
||||||
|
ResponseBody responseBody = makeServiceRequest(urlFragment, method, jsonRequestBody(jsonBody), headers, responseCodeHandler, Optional.absent(), true).body();
|
||||||
try {
|
try {
|
||||||
return responseBody.string();
|
return responseBody.string();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue