Discount badge on Choose plan

This commit is contained in:
Dima-1 2020-04-22 22:04:00 +03:00
parent 74ec8cc43a
commit c66d5601e9
12 changed files with 223 additions and 114 deletions

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/switch_button_active_dark" />
<corners android:radius="3dp" />
<stroke
android:width="1dp"
android:color="@color/active_color_primary_dark" />
</shape>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/switch_button_active_light" />
<corners android:radius="3dp" />
<stroke
android:width="1dp"
android:color="@color/active_color_primary_light" />
</shape>

View file

@ -16,10 +16,10 @@
android:layout_height="wrap_content"
android:baselineAligned="false"
android:orientation="vertical"
android:paddingLeft="@dimen/card_padding"
android:paddingRight="@dimen/card_padding"
android:paddingEnd="@dimen/card_padding"
android:paddingStart="@dimen/card_padding">
android:paddingLeft="@dimen/list_content_padding"
android:paddingRight="@dimen/list_content_padding"
android:paddingEnd="@dimen/list_content_padding"
android:paddingStart="@dimen/list_content_padding">
<LinearLayout
android:layout_width="match_parent"
@ -48,55 +48,48 @@
osmand:typeface="@string/font_roboto_regular"
tools:visibility="visible" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/description"
android:layout_width="match_parent"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="center"
android:textColor="?attr/dialog_text_description_color"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_regular"
tools:text="$0.62 / month • Save 68%" />
</LinearLayout>
tools:text="$0.62 / month" />
<LinearLayout
android:id="@+id/button_view"
android:layout_width="match_parent"
android:id="@+id/button_discount_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="?attr/btn_round_border_2">
<LinearLayout
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:gravity="center"
android:orientation="horizontal"
android:padding="@dimen/list_header_padding">
<ProgressBar
android:id="@+id/button_progress"
android:layout_width="@dimen/card_button_progress_size_small"
android:layout_height="@dimen/card_button_progress_size_small"
android:indeterminate="true"
android:visibility="gone" />
android:background="@drawable/btn_border_bg_light"
android:visibility="gone"
tools:visibility="visible">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/button_title"
android:layout_width="match_parent"
android:id="@+id/button_discount_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:paddingStart="@dimen/content_padding_small"
android:paddingLeft="@dimen/content_padding_small"
android:paddingEnd="@dimen/content_padding_small"
android:paddingRight="@dimen/content_padding_small"
android:paddingTop="@dimen/subHeaderPadding"
android:paddingBottom="@dimen/subHeaderPadding"
android:gravity="end"
android:letterSpacing="@dimen/text_button_letter_spacing"
android:maxWidth="@dimen/dialog_button_ex_max_width"
android:minWidth="@dimen/dialog_button_ex_min_width"
android:textColor="?attr/color_dialog_buttons"
android:textSize="@dimen/text_button_text_size"
osmand:typeface="@string/font_roboto_medium"
tools:text="7,99€ / year" />
android:textColor="@color/text_color_secondary_light"
android:textSize="@dimen/default_desc_text_size"
tools:text="Save 10%"
osmand:typeface="@string/font_roboto_medium" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<LinearLayout
@ -138,7 +131,7 @@
android:id="@+id/div"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="@dimen/content_padding_small"
android:layout_marginTop="@dimen/content_padding"
android:background="?attr/wikivoyage_card_divider_color"
android:visibility="gone" />

View file

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:osmand="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
@ -76,19 +75,39 @@
</LinearLayout>
<LinearLayout
android:id="@+id/cards_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
<LinearLayout
android:id="@+id/plan_info_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/list_content_padding"
android:layout_marginRight="@dimen/list_content_padding"
android:layout_marginStart="@dimen/list_content_padding"
android:layout_marginEnd="@dimen/list_content_padding"
android:orientation="vertical">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/plan_info_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/dialog_description_color"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_regular"
android:text="@string/osm_live_payment_subscription_management" />
</LinearLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/card_padding"
android:layout_marginRight="@dimen/card_padding"
android:layout_marginTop="4dp"
android:layout_marginTop="@dimen/list_header_padding"
android:background="?attr/wikivoyage_travel_card_bg"
android:layout_marginEnd="@dimen/card_padding"
android:layout_marginStart="@dimen/card_padding">

View file

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:osmand="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/card_padding"
@ -49,7 +48,7 @@
android:layout_marginRight="@dimen/card_padding"
android:layout_marginBottom="@dimen/list_header_padding"
android:text="@string/osm_live_payment_header"
android:textColor="?attr/dialog_text_description_color"
android:textColor="@color/preference_category_title"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_regular"
android:layout_marginEnd="@dimen/card_padding"
@ -74,7 +73,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:paddingBottom="@dimen/content_padding_small"
android:paddingBottom="@dimen/content_padding"
android:orientation="vertical"
android:visibility="gone" />

View file

@ -713,7 +713,7 @@
<string name="osm_live_payment_renews_monthly">Perpanjang tiap bulan</string>
<string name="osm_live_payment_renews_quarterly">Perpanjang tiap 4 bulan</string>
<string name="osm_live_payment_renews_annually">Perpanjang tiap tahun</string>
<string name="default_price_currency_format"/>
<string name="default_price_currency_format">%1$.2f %2$s</string>
<string name="osm_live_payment_header">Pilih periode pembayaran yang anda inginkan:</string>
<string name="osm_live_payment_contribute_descr">Sebagian pendapatan diberikan untuk kontributor OpenStreetMap.</string>
<string name="powered_by_osmand">Oleh OsmAnd</string>

View file

@ -103,6 +103,7 @@
<attr name="wikivoyage_secondary_btn_bg" format="reference"/>
<attr name="wikivoyage_primary_btn_bg" format="reference"/>
<attr name="purchase_dialog_shadow_btn_bg" format="reference"/>
<attr name="purchase_dialog_outline_btn_bg" format="reference"/>
<attr name="bottom_nav_shadow" format="reference"/>

View file

@ -461,7 +461,8 @@
<color name="profile_icon_color_inactive">#727272</color>
<color name="switch_button_active">#1A237BFF</color>
<color name="switch_button_active_light">#1A237BFF</color>
<color name="switch_button_active_dark">#1AD28521</color>
<color name="switch_button_active_stroke">#80237BFF</color>
<color name="empty_hint_bg">#80000000</color>

View file

@ -11,6 +11,8 @@
Thx - Hardy
-->
<string name="osm_live_payment_subscription_management">Payment will be charged to your Google Play account at the confirmation of purchase.\n\nSubscription automatically renews unless it is canceled before the renewal date. Your account will be charged for renewal period(month/three month/year) only on the renewal date.\n\nYou can manage and cancel your subscriptions by going to your Google Play settings.</string>
<string name="ltr_or_rtl_combine_via_slash_with_space">%1$s / %2$s</string>
<string name="custom_color">Custom color</string>
<string name="lang_lmo">Lombard</string>
<string name="lang_an">Aragonese</string>
@ -715,7 +717,7 @@
<string name="osm_live_payment_annual_title">Annually</string>
<string name="osm_live_payment_month_cost_descr">%1$s / month</string>
<string name="osm_live_payment_month_cost_descr_ex">%1$.2f %2$s / month</string>
<string name="osm_live_payment_discount_descr">Save %1$s.</string>
<string name="osm_live_payment_discount_descr">Save %1$s</string>
<string name="osm_live_payment_current_subscription">Current subscription</string>
<string name="osm_live_payment_renews_monthly">Renews monthly</string>
<string name="osm_live_payment_renews_quarterly">Renews quarterly</string>

View file

@ -246,6 +246,7 @@
<item name="wikivoyage_primary_btn_bg">@drawable/wikivoyage_primary_btn_bg_light</item>
<item name="purchase_dialog_active_card_bg">@drawable/dialog_active_card_bg_light</item>
<item name="purchase_dialog_shadow_btn_bg">@drawable/purchase_dialog_shadow_btn_bg_light</item>
<item name="purchase_dialog_outline_btn_bg">@drawable/purchase_dialog_outline_btn_bg_light</item>
<item name="bottom_nav_shadow">@drawable/bg_bottom_bar_shadow_with_line_day</item>
@ -512,6 +513,7 @@
<item name="wikivoyage_primary_btn_bg">@drawable/wikivoyage_primary_btn_bg_dark</item>
<item name="purchase_dialog_active_card_bg">@drawable/dialog_active_card_bg_dark</item>
<item name="purchase_dialog_shadow_btn_bg">@drawable/purchase_dialog_shadow_btn_bg_dark</item>
<item name="purchase_dialog_outline_btn_bg">@drawable/purchase_dialog_outline_btn_bg_dark</item>
<item name="bottom_nav_shadow">@drawable/bg_bottom_bar_shadow_with_line_night</item>

View file

@ -6,10 +6,12 @@ import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Resources;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.TypedValue;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.View;
@ -37,6 +39,7 @@ import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.OsmandSettings;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.Version;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.base.BaseOsmAndDialogFragment;
@ -352,18 +355,21 @@ public abstract class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment
osmLiveCardButtonsContainer.removeAllViews();
View lastBtn = null;
List<InAppSubscription> visibleSubscriptions = purchaseHelper.getLiveUpdates().getVisibleSubscriptions();
boolean anyPurchasedOrIntroducted = false;
boolean anyPurchased = false;
for (final InAppSubscription s : visibleSubscriptions) {
if (s.isPurchased() || s.getIntroductoryInfo() != null) {
anyPurchasedOrIntroducted = true;
if (s.isPurchased()) {
anyPurchased = true;
break;
}
}
InAppSubscription subscriptionMaxDiscount = purchaseHelper.getLiveUpdates()
.getSubscriptionWithMaxDiscount(purchaseHelper.getMonthlyLiveUpdates());
boolean maxDiscountAction = subscriptionMaxDiscount != null
&& (subscriptionMaxDiscount.getIntroductoryInfo() != null || subscriptionMaxDiscount.isUpgrade());
for (final InAppSubscription s : visibleSubscriptions) {
InAppSubscriptionIntroductoryInfo introductoryInfo = s.getIntroductoryInfo();
boolean hasIntroductoryInfo = introductoryInfo != null;
CharSequence descriptionText = hasIntroductoryInfo ?
introductoryInfo.getDescriptionTitle(ctx) : s.getDescription(ctx, purchaseHelper.getMonthlyLiveUpdates());
CharSequence descriptionText = s.getDescription(ctx);
if (s.isPurchased()) {
View buttonPurchased = inflate(R.layout.purchase_dialog_card_button_active_ex, osmLiveCardButtonsContainer);
TextViewEx title = (TextViewEx) buttonPurchased.findViewById(R.id.title);
@ -377,7 +383,7 @@ public abstract class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment
AppCompatImageView rightImage = (AppCompatImageView) buttonPurchased.findViewById(R.id.right_image);
CharSequence priceTitle = hasIntroductoryInfo ?
introductoryInfo.getFormattedDescription(ctx, buttonTitle.getCurrentTextColor()) : s.getPrice(ctx);
introductoryInfo.getFormattedDescription(ctx, buttonTitle.getCurrentTextColor()) : s.getPriceWithPeriod(ctx);
title.setText(s.getTitle(ctx));
description.setText(descriptionText);
buttonTitle.setText(priceTitle);
@ -421,45 +427,56 @@ public abstract class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment
rightImage.setVisibility(View.VISIBLE);
osmLiveCardButtonsContainer.addView(buttonCancel);
lastBtn = buttonCancel;
} else {
View button = inflate(R.layout.purchase_dialog_card_button_ex, osmLiveCardButtonsContainer);
TextViewEx title = (TextViewEx) button.findViewById(R.id.title);
TextViewEx description = (TextViewEx) button.findViewById(R.id.description);
TextViewEx descriptionContribute = (TextViewEx) button.findViewById(R.id.description_contribute);
descriptionContribute.setVisibility(s.isDonationSupported() ? View.VISIBLE : View.GONE);
View buttonView = button.findViewById(R.id.button_view);
View buttonExView = button.findViewById(R.id.button_ex_view);
TextViewEx buttonTitle = (TextViewEx) button.findViewById(R.id.button_title);
TextViewEx buttonExTitle = (TextViewEx) button.findViewById(R.id.button_ex_title);
boolean showSolidButton = !anyPurchasedOrIntroducted || hasIntroductoryInfo;
buttonView.setVisibility(!showSolidButton ? View.VISIBLE : View.GONE);
buttonExView.setVisibility(showSolidButton ? View.VISIBLE : View.GONE);
View div = button.findViewById(R.id.div);
CharSequence priceTitle = hasIntroductoryInfo ?
introductoryInfo.getFormattedDescription(ctx, buttonExTitle.getCurrentTextColor()) : s.getPrice(ctx);
title.setText(s.getTitle(ctx));
description.setText(descriptionText);
buttonTitle.setText(priceTitle);
buttonExTitle.setText(priceTitle);
if (!showSolidButton) {
buttonView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
subscribe(s.getSku());
if (maxDiscountAction && s.equals(subscriptionMaxDiscount)) {
createSolidButton(ctx, buttonExView, buttonExTitle);
}
});
CharSequence priceTitle = hasIntroductoryInfo ?
introductoryInfo.getFormattedDescription(ctx, buttonExTitle.getCurrentTextColor()) : s.getPriceWithPeriod(ctx);
buttonExTitle.setText(priceTitle);
title.setText(s.getTitle(ctx));
if (Algorithms.isEmpty(descriptionText.toString())) {
description.setVisibility(View.GONE);
} else {
description.setText(descriptionText);
}
TextViewEx buttonDiscountTitle = (TextViewEx) button.findViewById(R.id.button_discount_title);
View buttonDiscountView = button.findViewById(R.id.button_discount_view);
String discountTitle = s.getDiscountTitle(ctx, purchaseHelper.getMonthlyLiveUpdates());
if (!Algorithms.isEmpty(discountTitle)) {
buttonDiscountTitle.setText(discountTitle);
buttonDiscountView.setVisibility(View.VISIBLE);
}
if (s.equals(subscriptionMaxDiscount)) {
int saveTextColor = R.color.color_osm_edit_delete;
if (hasIntroductoryInfo) {
saveTextColor = R.color.active_buttons_and_links_text_light;
AndroidUtils.setBackground(buttonDiscountView, UiUtilities.tintDrawable(buttonDiscountView.getBackground(),
ContextCompat.getColor(ctx, R.color.color_osm_edit_delete)));
}
buttonDiscountTitle.setTextColor(ContextCompat.getColor(ctx, saveTextColor));
} else {
if (maxDiscountAction) {
createOutlineButton(ctx, buttonExView, buttonExTitle);
}
}
if (anyPurchased) {
createOutlineButton(ctx, buttonExView, buttonExTitle);
}
buttonExView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
subscribe(s.getSku());
}
});
}
View div = button.findViewById(R.id.div);
div.setVisibility(View.VISIBLE);
osmLiveCardButtonsContainer.addView(button);
lastBtn = button;
@ -478,6 +495,23 @@ public abstract class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment
}
}
private void createSolidButton(Context ctx, View buttonExView, TextViewEx buttonExTitle) {
Resources.Theme theme = ctx.getTheme();
TypedValue typedValue = new TypedValue();
theme.resolveAttribute(R.attr.wikivoyage_primary_btn_bg, typedValue, true);
buttonExView.setBackgroundResource(typedValue.resourceId);
buttonExTitle.setTextColor(ContextCompat.getColor(ctx, R.color.active_buttons_and_links_text_light));
}
private void createOutlineButton(Context ctx, View buttonExView, TextViewEx buttonExTitle) {
Resources.Theme theme = ctx.getTheme();
TypedValue typedValue = new TypedValue();
theme.resolveAttribute(R.attr.purchase_dialog_outline_btn_bg, typedValue, true);
buttonExView.setBackgroundResource(typedValue.resourceId);
theme.resolveAttribute(R.attr.color_dialog_buttons, typedValue, true);
buttonExTitle.setTextColor(ContextCompat.getColor(ctx, typedValue.resourceId));
}
private void showDonationSettings() {
FragmentActivity activity = getActivity();
if (activity != null) {

View file

@ -258,6 +258,20 @@ public class InAppPurchases {
}
return null;
}
@Nullable
public InAppSubscription getSubscriptionWithMaxDiscount(@Nullable InAppSubscription monthlyLiveUpdates) {
double maxDiscount = 0;
InAppSubscription subscriptionWithMaxDiscount = null;
for (InAppSubscription s : getAllSubscriptions()) {
double discount = s.getDiscountPercent(monthlyLiveUpdates);
if (discount > maxDiscount) {
subscriptionWithMaxDiscount = s;
maxDiscount = discount;
}
}
return subscriptionWithMaxDiscount;
}
}
public static class LiveUpdatesInAppPurchasesFree extends InAppSubscriptionList {
@ -677,6 +691,10 @@ public class InAppPurchases {
return s;
}
public boolean isUpgrade() {
return upgrade;
}
public boolean isAnyPurchased() {
if (isPurchased()) {
return true;
@ -728,6 +746,9 @@ public class InAppPurchases {
@Override
public CharSequence getDescription(@NonNull Context ctx) {
if (getMonthlyPriceValue() == getPriceValue()) {
return "";
}
if (getMonthlyPriceValue() == 0) {
return ctx.getString(R.string.osm_live_payment_month_cost_descr, getDefaultMonthlyPrice(ctx));
} else {
@ -740,12 +761,6 @@ public class InAppPurchases {
}
}
public CharSequence getDescription(@NonNull Context ctx, @Nullable InAppSubscription monthlyLiveUpdates) {
CharSequence descr = getDescription(ctx);
int discountPercent = getDiscountPercent(monthlyLiveUpdates);
return discountPercent > 0 ? ctx.getString(R.string.price_and_discount, descr, discountPercent + "%") : descr;
}
public CharSequence getRenewDescription(@NonNull Context ctx) {
return "";
}
@ -753,7 +768,12 @@ public class InAppPurchases {
@Nullable
protected abstract InAppSubscription newInstance(@NonNull String sku);
public int getDiscountPercent(@Nullable InAppSubscription monthlyLiveUpdates) {
public String getDiscountTitle(@NonNull Context ctx, @Nullable InAppSubscription monthlyLiveUpdates) {
int discountPercent = getDiscountPercent(monthlyLiveUpdates);
return discountPercent > 0 ? ctx.getString(R.string.osm_live_payment_discount_descr, discountPercent + "%") : "";
}
int getDiscountPercent(@Nullable InAppSubscription monthlyLiveUpdates) {
double monthlyPriceValue = getMonthlyPriceValue();
if (monthlyLiveUpdates != null) {
double regularMonthlyPrice = monthlyLiveUpdates.getPriceValue();
@ -768,6 +788,10 @@ public class InAppPurchases {
}
return 0;
}
public String getPriceWithPeriod(Context ctx) {
return getPrice(ctx);
}
}
public static class InAppPurchaseFullVersion extends InAppPurchase {
@ -881,6 +905,12 @@ public class InAppPurchases {
return ctx.getString(R.string.osm_live_payment_monthly_title);
}
@Override
public String getPriceWithPeriod(Context ctx) {
return ctx.getString(R.string.ltr_or_rtl_combine_via_slash_with_space, getPrice(ctx),
ctx.getString(R.string.month).toLowerCase());
}
@Override
public CharSequence getRenewDescription(@NonNull Context ctx) {
return ctx.getString(R.string.osm_live_payment_renews_monthly);
@ -956,6 +986,12 @@ public class InAppPurchases {
return ctx.getString(R.string.osm_live_payment_3_months_title);
}
@Override
public String getPriceWithPeriod(Context ctx) {
return ctx.getString(R.string.ltr_or_rtl_combine_via_slash_with_space, getPrice(ctx),
ctx.getString(R.string.months_3).toLowerCase());
}
@Override
public CharSequence getRenewDescription(@NonNull Context ctx) {
return ctx.getString(R.string.osm_live_payment_renews_quarterly);
@ -1031,6 +1067,12 @@ public class InAppPurchases {
return ctx.getString(R.string.osm_live_payment_annual_title);
}
@Override
public String getPriceWithPeriod(Context ctx) {
return ctx.getString(R.string.ltr_or_rtl_combine_via_slash_with_space, getPrice(ctx),
ctx.getString(R.string.year).toLowerCase());
}
@Override
public CharSequence getRenewDescription(@NonNull Context ctx) {
return ctx.getString(R.string.osm_live_payment_renews_annually);