Fix merge
This commit is contained in:
parent
ef52f119d7
commit
30056e5dea
10 changed files with 596 additions and 182 deletions
171
OsmAnd-java/src/main/java/net/osmand/Period.java
Normal file
171
OsmAnd-java/src/main/java/net/osmand/Period.java
Normal file
|
@ -0,0 +1,171 @@
|
|||
package net.osmand;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class Period {
|
||||
|
||||
public enum PeriodUnit {
|
||||
YEAR("Y"),
|
||||
MONTH("M"),
|
||||
WEEK("W"),
|
||||
DAY("D");
|
||||
|
||||
private String unitStr;
|
||||
|
||||
PeriodUnit(String unitStr) {
|
||||
this.unitStr = unitStr;
|
||||
}
|
||||
|
||||
public String getUnitStr() {
|
||||
return unitStr;
|
||||
}
|
||||
|
||||
public double getMonthsValue() {
|
||||
switch (this) {
|
||||
case YEAR:
|
||||
return 12d;
|
||||
case MONTH:
|
||||
return 1d;
|
||||
case WEEK:
|
||||
return 1/4d;
|
||||
case DAY:
|
||||
return 1/30d;
|
||||
}
|
||||
return 0d;
|
||||
}
|
||||
|
||||
public static PeriodUnit parseUnit(String unitStr) {
|
||||
for (PeriodUnit unit : values()) {
|
||||
if (unit.unitStr.equals(unitStr)) {
|
||||
return unit;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static final Pattern PATTERN =
|
||||
Pattern.compile("^P(?:([-+]?[0-9]+)([YMWD]))?$", Pattern.CASE_INSENSITIVE);
|
||||
|
||||
private PeriodUnit unit;
|
||||
|
||||
private final int numberOfUnits;
|
||||
|
||||
public static Period ofYears(int years) {
|
||||
return new Period(PeriodUnit.YEAR, years);
|
||||
}
|
||||
|
||||
public static Period ofMonths(int months) {
|
||||
return new Period(PeriodUnit.MONTH, months);
|
||||
}
|
||||
|
||||
public static Period ofWeeks(int weeks) {
|
||||
return new Period(PeriodUnit.WEEK, weeks);
|
||||
}
|
||||
|
||||
public static Period ofDays(int days) {
|
||||
return new Period(PeriodUnit.DAY, days);
|
||||
}
|
||||
|
||||
public PeriodUnit getUnit() {
|
||||
return unit;
|
||||
}
|
||||
|
||||
public int getNumberOfUnits() {
|
||||
return numberOfUnits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a {@code Period} from a text string such as {@code PnY PnM PnD PnW}.
|
||||
* <p>
|
||||
* This will parse the string produced by {@code toString()} which is
|
||||
* based on the ISO-8601 period formats {@code PnY PnM PnD PnW}.
|
||||
* <p>
|
||||
* The string cannot start with negative sign.
|
||||
* The ASCII letter "P" is next in upper or lower case.
|
||||
* <p>
|
||||
* For example, the following are valid inputs:
|
||||
* <pre>
|
||||
* "P2Y" -- Period.ofYears(2)
|
||||
* "P3M" -- Period.ofMonths(3)
|
||||
* "P4W" -- Period.ofWeeks(4)
|
||||
* "P5D" -- Period.ofDays(5)
|
||||
* </pre>
|
||||
*
|
||||
* @param text the text to parse, not null
|
||||
* @return the parsed period, not null
|
||||
* @throws ParseException if the text cannot be parsed to a period
|
||||
*/
|
||||
public static Period parse(CharSequence text) throws ParseException {
|
||||
Matcher matcher = PATTERN.matcher(text);
|
||||
if (matcher.matches()) {
|
||||
String numberOfUnitsMatch = matcher.group(1);
|
||||
String unitMatch = matcher.group(2);
|
||||
if (numberOfUnitsMatch != null && unitMatch != null) {
|
||||
try {
|
||||
int numberOfUnits = parseNumber(numberOfUnitsMatch);
|
||||
PeriodUnit unit = PeriodUnit.parseUnit(unitMatch);
|
||||
return new Period(unit, numberOfUnits);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
throw new ParseException("Text cannot be parsed to a Period: " + text, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new ParseException("Text cannot be parsed to a Period: " + text, 0);
|
||||
}
|
||||
|
||||
private static int parseNumber(String str) throws ParseException {
|
||||
if (str == null) {
|
||||
return 0;
|
||||
}
|
||||
return Integer.parseInt(str);
|
||||
}
|
||||
|
||||
public Period(PeriodUnit unit, int numberOfUnits) {
|
||||
if (unit == null) {
|
||||
throw new IllegalArgumentException("PeriodUnit cannot be null");
|
||||
}
|
||||
this.unit = unit;
|
||||
this.numberOfUnits = numberOfUnits;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof Period) {
|
||||
Period other = (Period) obj;
|
||||
return unit.ordinal() == other.unit.ordinal() && numberOfUnits == other.numberOfUnits;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return unit.ordinal() + Integer.rotateLeft(numberOfUnits, 8);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
buf.append('P').append(numberOfUnits);
|
||||
switch (unit) {
|
||||
case YEAR:
|
||||
buf.append('Y');
|
||||
break;
|
||||
case MONTH:
|
||||
buf.append('M');
|
||||
break;
|
||||
case WEEK:
|
||||
buf.append('W');
|
||||
break;
|
||||
case DAY:
|
||||
buf.append('D');
|
||||
break;
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
|
@ -6,35 +6,28 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="1dp"
|
||||
android:layout_marginRight="1dp"
|
||||
android:background="?attr/subscription_active_bg_color"
|
||||
android:orientation="vertical">
|
||||
|
||||
<View
|
||||
android:id="@+id/div_top"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?attr/subscription_active_div_color"
|
||||
android:visibility="gone" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/button_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:baselineAligned="false"
|
||||
android:minHeight="@dimen/dialog_button_ex_height"
|
||||
android:orientation="horizontal"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="@dimen/card_padding"
|
||||
android:paddingRight="@dimen/card_padding">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="@dimen/list_header_padding"
|
||||
android:layout_marginEnd="@dimen/list_content_padding"
|
||||
android:layout_marginRight="@dimen/list_content_padding"
|
||||
android:layout_marginBottom="@dimen/list_header_padding"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
|
@ -48,10 +41,16 @@
|
|||
osmand:typeface="@string/font_roboto_regular"
|
||||
tools:text="Pay monthly" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/description_contribute"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
android:text="@string/osm_live_payment_contribute_descr"
|
||||
android:textColor="?attr/card_description_text_color"
|
||||
android:textSize="@dimen/default_desc_text_size"
|
||||
android:visibility="gone"
|
||||
osmand:typeface="@string/font_roboto_regular"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/description"
|
||||
|
@ -64,11 +63,20 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
<android.support.v7.widget.AppCompatImageView
|
||||
android:id="@+id/right_image"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginStart="@dimen/list_header_padding"
|
||||
android:layout_marginLeft="@dimen/list_header_padding"
|
||||
android:src="@drawable/ic_action_singleselect" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/button_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:background="?attr/wikivoyage_secondary_btn_bg">
|
||||
|
@ -76,7 +84,7 @@
|
|||
<LinearLayout
|
||||
android:id="@+id/button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/dialog_button_height"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
android:padding="@dimen/list_header_padding">
|
||||
|
@ -100,7 +108,7 @@
|
|||
|
||||
<LinearLayout
|
||||
android:id="@+id/button_cancel_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:background="?attr/wikivoyage_primary_btn_bg">
|
||||
|
@ -108,7 +116,8 @@
|
|||
<LinearLayout
|
||||
android:id="@+id/button_cancel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/dialog_button_height"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
android:padding="@dimen/list_header_padding">
|
||||
|
@ -121,7 +130,7 @@
|
|||
android:letterSpacing="@dimen/text_button_letter_spacing"
|
||||
android:maxWidth="@dimen/dialog_button_ex_max_width"
|
||||
android:minWidth="@dimen/dialog_button_ex_min_width"
|
||||
android:text="@string/shared_string_cancel"
|
||||
android:text="@string/cancel_subscription"
|
||||
android:textColor="@color/color_white"
|
||||
android:textSize="@dimen/text_button_text_size"
|
||||
osmand:typeface="@string/font_roboto_medium" />
|
||||
|
@ -136,16 +145,8 @@
|
|||
android:id="@+id/div"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginLeft="@dimen/card_padding"
|
||||
android:layout_marginRight="@dimen/card_padding"
|
||||
android:background="?attr/subscription_active_div_color"
|
||||
android:visibility="gone" />
|
||||
|
||||
<View
|
||||
android:id="@+id/div_bottom"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?attr/subscription_active_div_color"
|
||||
android:layout_marginTop="@dimen/content_padding_small"
|
||||
android:background="?attr/wikivoyage_card_divider_color"
|
||||
android:visibility="gone" />
|
||||
|
||||
</LinearLayout>
|
||||
|
|
|
@ -12,82 +12,52 @@
|
|||
android:id="@+id/button_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:baselineAligned="false"
|
||||
android:minHeight="@dimen/dialog_button_ex_height"
|
||||
android:orientation="horizontal"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="@dimen/card_padding"
|
||||
android:paddingRight="@dimen/card_padding">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="@dimen/list_header_padding"
|
||||
android:layout_marginEnd="@dimen/list_content_padding"
|
||||
android:layout_marginRight="@dimen/list_content_padding"
|
||||
android:layout_marginBottom="@dimen/list_header_padding"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:textColor="?attr/dialog_title_color"
|
||||
android:textSize="@dimen/default_list_text_size"
|
||||
osmand:typeface="@string/font_roboto_regular"
|
||||
tools:text="Pay monthly" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/description_contribute"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
android:text="@string/osm_live_payment_contribute_descr"
|
||||
android:textColor="?attr/card_description_text_color"
|
||||
android:textSize="@dimen/default_desc_text_size"
|
||||
android:visibility="gone"
|
||||
osmand:typeface="@string/font_roboto_regular"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/description"
|
||||
android:layout_width="0dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:textColor="?attr/card_description_text_color"
|
||||
android:textSize="@dimen/default_desc_text_size"
|
||||
osmand:typeface="@string/font_roboto_regular"
|
||||
tools:text="Monthly payment" />
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/discount_banner_regular"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:layout_marginStart="@dimen/list_item_button_padding"
|
||||
android:layout_marginLeft="@dimen/list_item_button_padding"
|
||||
android:background="?attr/text_rounded_bg_regular"
|
||||
android:textColor="?attr/card_description_text_color"
|
||||
android:textSize="@dimen/default_desc_text_size"
|
||||
osmand:typeface="@string/font_roboto_regular"
|
||||
tools:text=" Save 20%! " />
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/discount_banner_active"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:layout_marginStart="@dimen/list_item_button_padding"
|
||||
android:layout_marginLeft="@dimen/list_item_button_padding"
|
||||
android:background="?attr/text_rounded_bg_active"
|
||||
android:textColor="@color/osmand_orange"
|
||||
android:textSize="@dimen/default_desc_text_size"
|
||||
osmand:typeface="@string/font_roboto_regular"
|
||||
tools:text=" Save 20%! " />
|
||||
|
||||
</LinearLayout>
|
||||
tools:text="$0.62 / month • Save 68%" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/button_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:background="?attr/btn_round_border_2">
|
||||
|
@ -95,7 +65,7 @@
|
|||
<LinearLayout
|
||||
android:id="@+id/button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/dialog_button_height"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
|
@ -119,7 +89,7 @@
|
|||
android:textColor="?attr/color_dialog_buttons"
|
||||
android:textSize="@dimen/text_button_text_size"
|
||||
osmand:typeface="@string/font_roboto_medium"
|
||||
tools:text="7,99€" />
|
||||
tools:text="7,99€ / year" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
@ -127,7 +97,7 @@
|
|||
|
||||
<LinearLayout
|
||||
android:id="@+id/button_ex_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:background="?attr/wikivoyage_primary_btn_bg">
|
||||
|
@ -135,7 +105,7 @@
|
|||
<LinearLayout
|
||||
android:id="@+id/button_ex"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/dialog_button_height"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
|
@ -152,7 +122,7 @@
|
|||
android:textColor="@color/color_white"
|
||||
android:textSize="@dimen/text_button_text_size"
|
||||
osmand:typeface="@string/font_roboto_medium"
|
||||
tools:text="7,99€" />
|
||||
tools:text="$3.99 for six month\nthan $7.49 / year" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
@ -164,8 +134,7 @@
|
|||
android:id="@+id/div"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginLeft="@dimen/card_padding"
|
||||
android:layout_marginRight="@dimen/card_padding"
|
||||
android:layout_marginTop="@dimen/content_padding_small"
|
||||
android:background="?attr/wikivoyage_card_divider_color"
|
||||
android:visibility="gone" />
|
||||
|
||||
|
|
|
@ -64,6 +64,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="2dp"
|
||||
android:paddingBottom="@dimen/content_padding_small"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone" />
|
||||
|
||||
|
|
|
@ -1,5 +1,26 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="day">День</string>
|
||||
<string name="days_2_4">Дня</string>
|
||||
<string name="days_5">Дней</string>
|
||||
<string name="week">Неделя</string>
|
||||
<string name="weeks_2_4">Недели</string>
|
||||
<string name="weeks_5">Недель</string>
|
||||
<string name="month">Месяц</string>
|
||||
<string name="months_2_4">Месяца</string>
|
||||
<string name="months_5">Месяцев</string>
|
||||
<string name="year">Год</string>
|
||||
<string name="years_2_4">Года</string>
|
||||
<string name="years_5">Лет</string>
|
||||
<string name="months_3">Три месяца</string>
|
||||
<string name="price_free">Бесплатно</string>
|
||||
<string name="get_discount_title">Получите %1$d %2$s со скидкой %3$s.</string>
|
||||
<string name="get_free_trial_title">Начать бесплатный период в %1$d %2$s.</string>
|
||||
<string name="get_discount_first_part">%1$s за первый %2$s</string>
|
||||
<string name="get_discount_first_few_part">%1$s за первые %2$s</string>
|
||||
<string name="get_discount_second_part">затем %1$s</string>
|
||||
<string name="cancel_subscription">Отменить подписку</string>
|
||||
<string name="price_and_discount">%1$s • Экономия %2$s</string>
|
||||
<string name="rendering_attr_winter_road_name">Автозимник</string>
|
||||
<string name="rendering_attr_ice_road_name">Ледовый автозимник</string>
|
||||
<string name="routeInfo_winter_ice_road_name">Зимники</string>
|
||||
|
|
|
@ -11,6 +11,30 @@
|
|||
Thx - Hardy
|
||||
|
||||
-->
|
||||
<string name="day">Day</string>
|
||||
<string name="days_2_4">Days</string>
|
||||
<string name="days_5">Days</string>
|
||||
<string name="week">Week</string>
|
||||
<string name="weeks_2_4">Weeks</string>
|
||||
<string name="weeks_5">Weeks</string>
|
||||
<string name="month">Month</string>
|
||||
<string name="months_2_4">Months</string>
|
||||
<string name="months_5">Months</string>
|
||||
<string name="year">Year</string>
|
||||
<string name="years_2_4">Years</string>
|
||||
<string name="years_5">Years</string>
|
||||
<string name="months_3">Three months</string>
|
||||
<string name="price_free">Free</string>
|
||||
<string name="get_discount_title">Get %1$d %2$s at %3$s off.</string>
|
||||
<string name="get_free_trial_title">Start your %1$d %2$s free trial.</string>
|
||||
<string name="get_discount_first_part">%1$s for first %2$s</string>
|
||||
<string name="get_discount_first_few_part">%1$s for first %2$s</string>
|
||||
<string name="get_discount_second_part">then %1$s</string>
|
||||
<string name="cancel_subscription">Cancel subscription</string>
|
||||
<string name="price_and_discount">%1$s • Save %2$s</string>
|
||||
<string name="app_mode_wagon">Wagon</string>
|
||||
<string name="app_mode_pickup_truck">Pickup truck</string>
|
||||
<string name="shared_string_default">Default</string>
|
||||
<string name="gpx_join_gaps">Join gaps</string>
|
||||
<string name="app_mode_camper">Camper</string>
|
||||
<string name="app_mode_campervan">Campervan</string>
|
||||
|
|
|
@ -30,6 +30,9 @@ import android.support.annotation.NonNull;
|
|||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v4.content.FileProvider;
|
||||
import android.support.v4.text.TextUtilsCompat;
|
||||
import android.support.v4.view.ViewCompat;
|
||||
import android.text.ParcelableSpan;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.SpannableStringBuilder;
|
||||
|
@ -60,6 +63,7 @@ import java.util.Date;
|
|||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import static android.content.Context.POWER_SERVICE;
|
||||
|
@ -576,4 +580,8 @@ public class AndroidUtils {
|
|||
return baseString;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isRTL() {
|
||||
return TextUtilsCompat.getLayoutDirectionFromLocale(Locale.getDefault()) == ViewCompat.LAYOUT_DIRECTION_RTL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@ import net.osmand.plus.inapp.InAppPurchaseHelper.InAppPurchaseListener;
|
|||
import net.osmand.plus.inapp.InAppPurchaseHelper.InAppPurchaseTaskType;
|
||||
import net.osmand.plus.inapp.InAppPurchases.InAppPurchase;
|
||||
import net.osmand.plus.inapp.InAppPurchases.InAppSubscription;
|
||||
import net.osmand.plus.inapp.InAppPurchases.InAppSubscriptionIntroductoryInfo;
|
||||
import net.osmand.plus.liveupdates.SubscriptionFragment;
|
||||
import net.osmand.plus.srtmplugin.SRTMPlugin;
|
||||
import net.osmand.plus.widgets.TextViewEx;
|
||||
|
@ -341,38 +342,40 @@ public abstract class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment
|
|||
} else if (osmLiveCardButtonsContainer != null) {
|
||||
osmLiveCardButtonsContainer.removeAllViews();
|
||||
View lastBtn = null;
|
||||
InAppSubscription monthlyLiveUpdates = purchaseHelper.getMonthlyLiveUpdates();
|
||||
double regularMonthlyPrice = monthlyLiveUpdates.getPriceValue();
|
||||
List<InAppSubscription> visibleSubscriptions = purchaseHelper.getLiveUpdates().getVisibleSubscriptions();
|
||||
boolean anyPurchased = false;
|
||||
boolean anyPurchasedOrIntroducted = false;
|
||||
for (final InAppSubscription s : visibleSubscriptions) {
|
||||
if (s.isPurchased()) {
|
||||
anyPurchased = true;
|
||||
if (s.isPurchased() || s.getIntroductoryInfo() != null) {
|
||||
anyPurchasedOrIntroducted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (final InAppSubscription s : visibleSubscriptions) {
|
||||
InAppSubscriptionIntroductoryInfo introductoryInfo = s.getIntroductoryInfo();
|
||||
boolean hasIntroductoryInfo = introductoryInfo != null;
|
||||
CharSequence priceTitle = hasIntroductoryInfo ? introductoryInfo.getFormattedDescription(ctx) : s.getPrice(ctx);
|
||||
CharSequence descriptionText = hasIntroductoryInfo ?
|
||||
introductoryInfo.getDescriptionTitle(ctx) : s.getDescription(ctx, purchaseHelper.getMonthlyLiveUpdates());
|
||||
if (s.isPurchased()) {
|
||||
View buttonPurchased = inflate(R.layout.purchase_dialog_card_button_active_ex, osmLiveCardButtonsContainer);
|
||||
View buttonContainer = buttonPurchased.findViewById(R.id.button_container);
|
||||
TextViewEx title = (TextViewEx) buttonPurchased.findViewById(R.id.title);
|
||||
TextViewEx description = (TextViewEx) buttonPurchased.findViewById(R.id.description);
|
||||
TextViewEx descriptionContribute = (TextViewEx) buttonPurchased.findViewById(R.id.description_contribute);
|
||||
descriptionContribute.setVisibility(s.isDonationSupported() ? View.VISIBLE : View.GONE);
|
||||
TextViewEx buttonTitle = (TextViewEx) buttonPurchased.findViewById(R.id.button_title);
|
||||
View buttonView = buttonPurchased.findViewById(R.id.button_view);
|
||||
View buttonCancelView = buttonPurchased.findViewById(R.id.button_cancel_view);
|
||||
View divTop = buttonPurchased.findViewById(R.id.div_top);
|
||||
View divBottom = buttonPurchased.findViewById(R.id.div_bottom);
|
||||
View div = buttonPurchased.findViewById(R.id.div);
|
||||
AppCompatImageView rightImage = buttonPurchased.findViewById(R.id.right_image);
|
||||
|
||||
title.setText(s.getTitle(ctx));
|
||||
description.setText(s.getDescription(ctx));
|
||||
buttonTitle.setText(s.getPrice(ctx));
|
||||
description.setText(descriptionText);
|
||||
buttonTitle.setText(priceTitle);
|
||||
buttonView.setVisibility(View.VISIBLE);
|
||||
buttonCancelView.setVisibility(View.GONE);
|
||||
buttonPurchased.setOnClickListener(null);
|
||||
divTop.setVisibility(View.VISIBLE);
|
||||
div.setVisibility(View.VISIBLE);
|
||||
divBottom.setVisibility(View.GONE);
|
||||
div.setVisibility(View.GONE);
|
||||
rightImage.setVisibility(View.GONE);
|
||||
if (s.isDonationSupported()) {
|
||||
buttonPurchased.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
|
@ -387,14 +390,12 @@ public abstract class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment
|
|||
osmLiveCardButtonsContainer.addView(buttonPurchased);
|
||||
|
||||
View buttonCancel = inflate(R.layout.purchase_dialog_card_button_active_ex, osmLiveCardButtonsContainer);
|
||||
buttonContainer = buttonCancel.findViewById(R.id.button_container);
|
||||
title = (TextViewEx) buttonCancel.findViewById(R.id.title);
|
||||
description = (TextViewEx) buttonCancel.findViewById(R.id.description);
|
||||
buttonView = buttonCancel.findViewById(R.id.button_view);
|
||||
buttonCancelView = buttonCancel.findViewById(R.id.button_cancel_view);
|
||||
divTop = buttonCancel.findViewById(R.id.div_top);
|
||||
divBottom = buttonCancel.findViewById(R.id.div_bottom);
|
||||
div = buttonCancel.findViewById(R.id.div);
|
||||
rightImage = buttonPurchased.findViewById(R.id.right_image);
|
||||
|
||||
title.setText(getString(R.string.osm_live_payment_current_subscription));
|
||||
description.setText(s.getRenewDescription(ctx));
|
||||
|
@ -406,70 +407,34 @@ public abstract class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment
|
|||
manageSubscription(ctx, s.getSku());
|
||||
}
|
||||
});
|
||||
divTop.setVisibility(View.GONE);
|
||||
div.setVisibility(View.GONE);
|
||||
divBottom.setVisibility(View.VISIBLE);
|
||||
div.setVisibility(View.VISIBLE);
|
||||
rightImage.setVisibility(View.VISIBLE);
|
||||
osmLiveCardButtonsContainer.addView(buttonCancel);
|
||||
|
||||
if (lastBtn != null) {
|
||||
View lastBtnDiv = lastBtn.findViewById(R.id.div);
|
||||
if (lastBtnDiv != null) {
|
||||
lastBtnDiv.setVisibility(View.GONE);
|
||||
}
|
||||
View lastBtnDivBottom = lastBtn.findViewById(R.id.div_bottom);
|
||||
if (lastBtnDivBottom != null) {
|
||||
lastBtnDivBottom.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
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);
|
||||
buttonView.setVisibility(anyPurchased ? View.VISIBLE : View.GONE);
|
||||
buttonExView.setVisibility(!anyPurchased ? View.VISIBLE : View.GONE);
|
||||
boolean showSolidButton = !anyPurchasedOrIntroducted || hasIntroductoryInfo;
|
||||
buttonView.setVisibility(!showSolidButton ? View.VISIBLE : View.GONE);
|
||||
buttonExView.setVisibility(showSolidButton ? View.VISIBLE : View.GONE);
|
||||
|
||||
TextViewEx discountRegular = (TextViewEx) button.findViewById(R.id.discount_banner_regular);
|
||||
TextViewEx discountActive = (TextViewEx) button.findViewById(R.id.discount_banner_active);
|
||||
View div = button.findViewById(R.id.div);
|
||||
|
||||
title.setText(s.getTitle(ctx));
|
||||
description.setText(s.getDescription(ctx));
|
||||
buttonTitle.setText(s.getPrice(ctx));
|
||||
buttonExTitle.setText(s.getPrice(ctx));
|
||||
description.setText(descriptionText);
|
||||
buttonTitle.setText(priceTitle);
|
||||
buttonExTitle.setText(priceTitle);
|
||||
|
||||
if (regularMonthlyPrice > 0 && s.getMonthlyPriceValue() > 0 && s.getMonthlyPriceValue() < regularMonthlyPrice) {
|
||||
int discount = (int) ((1 - s.getMonthlyPriceValue() / regularMonthlyPrice) * 100d);
|
||||
String discountStr = discount + "%";
|
||||
if (discount > 50) {
|
||||
discountActive.setText(String.format(" %s ", getString(R.string.osm_live_payment_discount_descr, discountStr)));
|
||||
discountActive.setVisibility(View.VISIBLE);
|
||||
discountRegular.setVisibility(View.GONE);
|
||||
} else if (discount > 0) {
|
||||
discountActive.setVisibility(View.GONE);
|
||||
discountRegular.setText(String.format(" %s ", getString(R.string.osm_live_payment_discount_descr, discountStr)));
|
||||
discountRegular.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
discountActive.setVisibility(View.GONE);
|
||||
discountRegular.setVisibility(View.GONE);
|
||||
}
|
||||
} else {
|
||||
discountActive.setVisibility(View.GONE);
|
||||
discountRegular.setVisibility(View.GONE);
|
||||
}
|
||||
button.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
subscribe(s.getSku());
|
||||
}
|
||||
});
|
||||
if (anyPurchased) {
|
||||
if (!showSolidButton) {
|
||||
buttonView.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
@ -494,10 +459,6 @@ public abstract class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment
|
|||
if (div != null) {
|
||||
div.setVisibility(View.GONE);
|
||||
}
|
||||
View divBottom = lastBtn.findViewById(R.id.div_bottom);
|
||||
if (divBottom != null) {
|
||||
divBottom.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
if (osmLiveCardProgress != null) {
|
||||
osmLiveCardProgress.setVisibility(View.GONE);
|
||||
|
|
|
@ -27,6 +27,7 @@ import net.osmand.plus.inapp.InAppPurchases.InAppPurchase;
|
|||
import net.osmand.plus.inapp.InAppPurchases.InAppPurchase.PurchaseState;
|
||||
import net.osmand.plus.inapp.InAppPurchases.InAppPurchaseLiveUpdatesOldSubscription;
|
||||
import net.osmand.plus.inapp.InAppPurchases.InAppSubscription;
|
||||
import net.osmand.plus.inapp.InAppPurchases.InAppSubscriptionIntroductoryInfo;
|
||||
import net.osmand.plus.inapp.InAppPurchases.InAppSubscriptionList;
|
||||
import net.osmand.plus.inapp.util.BillingManager;
|
||||
import net.osmand.plus.inapp.util.BillingManager.BillingUpdatesListener;
|
||||
|
@ -39,6 +40,7 @@ import org.json.JSONException;
|
|||
import org.json.JSONObject;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
@ -603,7 +605,26 @@ public class InAppPurchaseHelper {
|
|||
String subscriptionPeriod = skuDetails.getSubscriptionPeriod();
|
||||
if (!Algorithms.isEmpty(subscriptionPeriod)) {
|
||||
if (inAppPurchase instanceof InAppSubscription) {
|
||||
((InAppSubscription) inAppPurchase).setSubscriptionPeriod(subscriptionPeriod);
|
||||
try {
|
||||
((InAppSubscription) inAppPurchase).setSubscriptionPeriodString(subscriptionPeriod);
|
||||
} catch (ParseException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (inAppPurchase instanceof InAppSubscription) {
|
||||
String introductoryPrice = skuDetails.getIntroductoryPrice();
|
||||
String introductoryPricePeriod = skuDetails.getIntroductoryPricePeriod();
|
||||
String introductoryPriceCycles = skuDetails.getIntroductoryPriceCycles();
|
||||
long introductoryPriceAmountMicros = skuDetails.getIntroductoryPriceAmountMicros();
|
||||
if (!Algorithms.isEmpty(introductoryPrice)) {
|
||||
InAppSubscription s = (InAppSubscription) inAppPurchase;
|
||||
try {
|
||||
s.setIntroductoryInfo(new InAppSubscriptionIntroductoryInfo(s, introductoryPrice,
|
||||
introductoryPriceAmountMicros, introductoryPricePeriod, introductoryPriceCycles));
|
||||
} catch (ParseException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,28 @@
|
|||
package net.osmand.plus.inapp;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Typeface;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.style.StyleSpan;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
|
||||
import com.android.billingclient.api.SkuDetails;
|
||||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.Period;
|
||||
import net.osmand.Period.PeriodUnit;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.Version;
|
||||
import net.osmand.plus.helpers.FontCache;
|
||||
import net.osmand.plus.widgets.style.CustomTypefaceSpan;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Currency;
|
||||
|
@ -169,7 +177,7 @@ public class InAppPurchases {
|
|||
private List<InAppSubscription> subscriptions;
|
||||
|
||||
InAppSubscriptionList(@NonNull InAppSubscription[] subscriptionsArray) {
|
||||
this.subscriptions = Arrays.asList(subscriptionsArray);;
|
||||
this.subscriptions = Arrays.asList(subscriptionsArray);
|
||||
}
|
||||
|
||||
private List<InAppSubscription> getSubscriptions() {
|
||||
|
@ -427,13 +435,204 @@ public class InAppPurchases {
|
|||
}
|
||||
}
|
||||
|
||||
public static class InAppSubscriptionIntroductoryInfo {
|
||||
|
||||
private InAppSubscription subscription;
|
||||
|
||||
private String introductoryPrice;
|
||||
private long introductoryPriceAmountMicros;
|
||||
private String introductoryPeriodString;
|
||||
private int introductoryCycles;
|
||||
|
||||
private double introductoryPriceValue;
|
||||
private Period introductoryPeriod;
|
||||
|
||||
public InAppSubscriptionIntroductoryInfo(@NonNull InAppSubscription subscription,
|
||||
String introductoryPrice,
|
||||
long introductoryPriceAmountMicros,
|
||||
String introductoryPeriodString,
|
||||
String introductoryCycles) throws ParseException {
|
||||
this.subscription = subscription;
|
||||
this.introductoryPrice = introductoryPrice;
|
||||
this.introductoryPriceAmountMicros = introductoryPriceAmountMicros;
|
||||
this.introductoryPeriodString = introductoryPeriodString;
|
||||
try {
|
||||
this.introductoryCycles = Integer.parseInt(introductoryCycles);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new ParseException("Cannot parse introductoryCycles = " + introductoryCycles, 0);
|
||||
}
|
||||
introductoryPriceValue = introductoryPriceAmountMicros / 1000000d;
|
||||
introductoryPeriod = Period.parse(introductoryPeriodString);
|
||||
}
|
||||
|
||||
public String getIntroductoryPrice() {
|
||||
return introductoryPrice;
|
||||
}
|
||||
|
||||
public long getIntroductoryPriceAmountMicros() {
|
||||
return introductoryPriceAmountMicros;
|
||||
}
|
||||
|
||||
public String getIntroductoryPeriodString() {
|
||||
return introductoryPeriodString;
|
||||
}
|
||||
|
||||
public int getIntroductoryCycles() {
|
||||
return introductoryCycles;
|
||||
}
|
||||
|
||||
public double getIntroductoryPriceValue() {
|
||||
return introductoryPriceValue;
|
||||
}
|
||||
|
||||
public double getIntroductoryMonthlyPriceValue() {
|
||||
return introductoryPriceValue /
|
||||
(introductoryPeriod.getUnit().getMonthsValue() * introductoryPeriod.getNumberOfUnits());
|
||||
}
|
||||
|
||||
public Period getIntroductoryPeriod() {
|
||||
return introductoryPeriod;
|
||||
}
|
||||
|
||||
public long getTotalPeriods() {
|
||||
return introductoryPeriod.getNumberOfUnits() * introductoryCycles;
|
||||
}
|
||||
|
||||
private String getTotalUnitsString(@NonNull Context ctx, boolean original) {
|
||||
String unitStr = "";
|
||||
Period subscriptionPeriod = subscription.getSubscriptionPeriod();
|
||||
PeriodUnit unit = original && subscriptionPeriod != null ? subscriptionPeriod.getUnit() : introductoryPeriod.getUnit();
|
||||
long totalPeriods = original && subscriptionPeriod != null ? subscriptionPeriod.getNumberOfUnits() : getTotalPeriods();
|
||||
switch (unit) {
|
||||
case YEAR:
|
||||
unitStr = ctx.getString(R.string.year);
|
||||
break;
|
||||
case MONTH:
|
||||
if (totalPeriods == 1) {
|
||||
unitStr = ctx.getString(R.string.month);
|
||||
} else if (totalPeriods < 5) {
|
||||
unitStr = ctx.getString(R.string.months_2_4);
|
||||
} else {
|
||||
unitStr = ctx.getString(R.string.months_5);
|
||||
}
|
||||
break;
|
||||
case WEEK:
|
||||
if (totalPeriods == 1) {
|
||||
unitStr = ctx.getString(R.string.week);
|
||||
} else if (totalPeriods < 5) {
|
||||
unitStr = ctx.getString(R.string.weeks_2_4);
|
||||
} else {
|
||||
unitStr = ctx.getString(R.string.weeks_5);
|
||||
}
|
||||
break;
|
||||
case DAY:
|
||||
if (totalPeriods == 1) {
|
||||
unitStr = ctx.getString(R.string.day);
|
||||
} else if (totalPeriods < 5) {
|
||||
unitStr = ctx.getString(R.string.days_2_4);
|
||||
} else {
|
||||
unitStr = ctx.getString(R.string.days_5);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return unitStr;
|
||||
}
|
||||
|
||||
private String getUnitString(@NonNull Context ctx) {
|
||||
PeriodUnit unit = introductoryPeriod.getUnit();
|
||||
switch (unit) {
|
||||
case YEAR:
|
||||
return ctx.getString(R.string.year);
|
||||
case MONTH:
|
||||
return ctx.getString(R.string.month);
|
||||
case WEEK:
|
||||
return ctx.getString(R.string.week);
|
||||
case DAY:
|
||||
return ctx.getString(R.string.day);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private String getDisountPeriodString(String unitStr, long totalPeriods) {
|
||||
if (totalPeriods == 1)
|
||||
return unitStr;
|
||||
if (AndroidUtils.isRTL()) {
|
||||
return unitStr + " " + totalPeriods;
|
||||
} else {
|
||||
return totalPeriods + " " + unitStr;
|
||||
}
|
||||
}
|
||||
|
||||
public CharSequence getDescriptionTitle(@NonNull Context ctx) {
|
||||
long totalPeriods = getTotalPeriods();
|
||||
String unitStr = getTotalUnitsString(ctx, false).toLowerCase();
|
||||
int discountPercent = subscription.getDiscountPercent(null);
|
||||
return ctx.getString(R.string.get_discount_title, totalPeriods, unitStr, discountPercent + "%");
|
||||
}
|
||||
|
||||
public CharSequence getFormattedDescription(@NonNull Context ctx) {
|
||||
long totalPeriods = getTotalPeriods();
|
||||
String singleUnitStr = getUnitString(ctx).toLowerCase();
|
||||
String unitStr = getTotalUnitsString(ctx, false).toLowerCase();
|
||||
long numberOfUnits = introductoryPeriod.getNumberOfUnits();
|
||||
Period subscriptionPeriod = subscription.getSubscriptionPeriod();
|
||||
long originalNumberOfUnits = subscriptionPeriod != null ? subscriptionPeriod.getNumberOfUnits() : 1;
|
||||
String originalUnitsStr = getTotalUnitsString(ctx, true).toLowerCase();
|
||||
String originalPriceStr = subscription.getPrice(ctx);
|
||||
String priceStr = introductoryPrice;
|
||||
|
||||
String pricePeriod;
|
||||
String originalPricePeriod;
|
||||
|
||||
if (AndroidUtils.isRTL()) {
|
||||
pricePeriod = singleUnitStr + " / " + priceStr;
|
||||
originalPricePeriod = originalUnitsStr + " / " + originalPriceStr;
|
||||
if (numberOfUnits > 1) {
|
||||
pricePeriod = unitStr + " " + numberOfUnits + " / " + priceStr;
|
||||
}
|
||||
if (originalNumberOfUnits == 3 && subscriptionPeriod.getUnit() == PeriodUnit.MONTH) {
|
||||
originalPricePeriod = ctx.getString(R.string.months_3).toLowerCase() + " / " + originalPriceStr;
|
||||
} else if (originalNumberOfUnits > 1) {
|
||||
originalPricePeriod = originalUnitsStr + " " + originalNumberOfUnits + " / " + originalPriceStr;
|
||||
}
|
||||
} else {
|
||||
pricePeriod = priceStr + " / " + singleUnitStr;
|
||||
originalPricePeriod = originalPriceStr + " / " + originalUnitsStr;
|
||||
if (numberOfUnits > 1) {
|
||||
pricePeriod = priceStr + " / " + numberOfUnits + " " + unitStr;
|
||||
}
|
||||
if (originalNumberOfUnits == 3 && subscriptionPeriod.getUnit() == PeriodUnit.MONTH) {
|
||||
originalPricePeriod = originalPriceStr + " / " + ctx.getString(R.string.months_3).toLowerCase();
|
||||
} else if (originalNumberOfUnits > 1) {
|
||||
originalPricePeriod = originalPriceStr + " / " + originalNumberOfUnits + " " + originalUnitsStr;
|
||||
}
|
||||
}
|
||||
String periodPriceStr = introductoryCycles == 1 ? priceStr : pricePeriod;
|
||||
|
||||
int firstPartRes = totalPeriods == 1 ? R.string.get_discount_first_part : R.string.get_discount_first_few_part;
|
||||
SpannableStringBuilder mainPart = new SpannableStringBuilder(ctx.getString(firstPartRes, periodPriceStr, getDisountPeriodString(unitStr, totalPeriods)));
|
||||
SpannableStringBuilder thenPart = new SpannableStringBuilder(ctx.getString(R.string.get_discount_second_part, originalPricePeriod));
|
||||
Typeface typefaceRegular = FontCache.getRobotoRegular(ctx);
|
||||
Typeface typefaceBold = FontCache.getRobotoMedium(ctx);
|
||||
mainPart.setSpan(new CustomTypefaceSpan(typefaceBold), 0, mainPart.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
int textColor = ContextCompat.getColor(ctx, R.color.white_50_transparent);
|
||||
thenPart.setSpan(new ForegroundColorSpan(textColor), 0, thenPart.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
thenPart.setSpan(new CustomTypefaceSpan(typefaceRegular), 0, thenPart.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
|
||||
return new SpannableStringBuilder(mainPart).append("\n").append(thenPart);
|
||||
}
|
||||
}
|
||||
|
||||
public static abstract class InAppSubscription extends InAppPurchase {
|
||||
|
||||
private Map<String, InAppSubscription> upgrades = new ConcurrentHashMap<>();
|
||||
private String skuNoVersion;
|
||||
private String subscriptionPeriod;
|
||||
private String subscriptionPeriodString;
|
||||
private Period subscriptionPeriod;
|
||||
private boolean upgrade = false;
|
||||
|
||||
private InAppSubscriptionIntroductoryInfo introductoryInfo;
|
||||
|
||||
InAppSubscription(@NonNull String skuNoVersion, int version) {
|
||||
super(skuNoVersion + "_v" + version);
|
||||
this.skuNoVersion = skuNoVersion;
|
||||
|
@ -482,12 +681,36 @@ public class InAppPurchases {
|
|||
return skuNoVersion;
|
||||
}
|
||||
|
||||
public String getSubscriptionPeriod() {
|
||||
@Nullable
|
||||
public String getSubscriptionPeriodString() {
|
||||
return subscriptionPeriodString;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Period getSubscriptionPeriod() {
|
||||
return subscriptionPeriod;
|
||||
}
|
||||
|
||||
public void setSubscriptionPeriod(String subscriptionPeriod) {
|
||||
this.subscriptionPeriod = subscriptionPeriod;
|
||||
public void setSubscriptionPeriodString(String subscriptionPeriodString) throws ParseException {
|
||||
this.subscriptionPeriodString = subscriptionPeriodString;
|
||||
this.subscriptionPeriod = Period.parse(subscriptionPeriodString);
|
||||
}
|
||||
|
||||
public InAppSubscriptionIntroductoryInfo getIntroductoryInfo() {
|
||||
/*
|
||||
try {
|
||||
if (subscriptionPeriod != null && subscriptionPeriod.getUnit() == PeriodUnit.YEAR) {
|
||||
introductoryInfo = new InAppSubscriptionIntroductoryInfo(this, "30 грн.", 30000000L, "P1Y", "1");
|
||||
}
|
||||
} catch (ParseException e) {
|
||||
//
|
||||
}
|
||||
*/
|
||||
return introductoryInfo;
|
||||
}
|
||||
|
||||
public void setIntroductoryInfo(InAppSubscriptionIntroductoryInfo introductoryInfo) {
|
||||
this.introductoryInfo = introductoryInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -504,12 +727,34 @@ 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 "";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected abstract InAppSubscription newInstance(@NonNull String sku);
|
||||
|
||||
public int getDiscountPercent(@Nullable InAppSubscription monthlyLiveUpdates) {
|
||||
double monthlyPriceValue = getMonthlyPriceValue();
|
||||
if (monthlyLiveUpdates != null) {
|
||||
double regularMonthlyPrice = monthlyLiveUpdates.getPriceValue();
|
||||
if (regularMonthlyPrice > 0 && monthlyPriceValue > 0 && monthlyPriceValue < regularMonthlyPrice) {
|
||||
return (int) ((1 - monthlyPriceValue / regularMonthlyPrice) * 100d);
|
||||
}
|
||||
} else if (introductoryInfo != null) {
|
||||
double introductoryMonthlyPrice = introductoryInfo.getIntroductoryMonthlyPriceValue();
|
||||
if (introductoryMonthlyPrice > 0 && monthlyPriceValue > 0 && monthlyPriceValue > introductoryMonthlyPrice) {
|
||||
return (int) ((1 - introductoryMonthlyPrice / monthlyPriceValue) * 100d);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static class InAppPurchaseFullVersion extends InAppPurchase {
|
||||
|
@ -623,14 +868,6 @@ public class InAppPurchases {
|
|||
return ctx.getString(R.string.osm_live_payment_monthly_title);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getDescription(@NonNull Context ctx) {
|
||||
CharSequence descr = super.getDescription(ctx);
|
||||
SpannableStringBuilder text = new SpannableStringBuilder(descr).append(". ").append(ctx.getString(R.string.osm_live_payment_contribute_descr));
|
||||
text.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), descr.length() + 1, text.length() - 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
return text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getRenewDescription(@NonNull Context ctx) {
|
||||
return ctx.getString(R.string.osm_live_payment_renews_monthly);
|
||||
|
|
Loading…
Reference in a new issue