From 984aaa36a7cd50bb7230eacd0e6b000aac3b724a Mon Sep 17 00:00:00 2001 From: androiddevkotlin <64539346+androiddevkotlin@users.noreply.github.com> Date: Sun, 21 Mar 2021 19:20:50 +0200 Subject: [PATCH 01/11] init --- OsmAnd/res/layout/empty_purchases_layout.xml | 220 ++++++++++++ .../profile_preference_toolbar_with_icon.xml | 1 + OsmAnd/res/layout/purchases_layout.xml | 338 ++++++++++++++++++ OsmAnd/res/values/strings.xml | 7 + OsmAnd/res/xml/settings_main_screen.xml | 8 + .../fragments/MainSettingsFragment.java | 6 +- .../settings/fragments/PurchasesFragment.java | 101 ++++++ .../fragments/PurchasesFragmentEmpty.java | 148 ++++++++ 8 files changed, 827 insertions(+), 2 deletions(-) create mode 100644 OsmAnd/res/layout/empty_purchases_layout.xml create mode 100644 OsmAnd/res/layout/purchases_layout.xml create mode 100644 OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragment.java create mode 100644 OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragmentEmpty.java diff --git a/OsmAnd/res/layout/empty_purchases_layout.xml b/OsmAnd/res/layout/empty_purchases_layout.xml new file mode 100644 index 0000000000..7a19918581 --- /dev/null +++ b/OsmAnd/res/layout/empty_purchases_layout.xml @@ -0,0 +1,220 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/profile_preference_toolbar_with_icon.xml b/OsmAnd/res/layout/profile_preference_toolbar_with_icon.xml index 98f2b0966d..3890b58e8f 100644 --- a/OsmAnd/res/layout/profile_preference_toolbar_with_icon.xml +++ b/OsmAnd/res/layout/profile_preference_toolbar_with_icon.xml @@ -69,6 +69,7 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index 2bc271e8dd..74cea426f4 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -11,6 +11,13 @@ Thx - Hardy --> + + support@osmand.net + Contact support + If your purchases don\'t show up here, tap on “Restore purchases”, or contact our support team. + If you have any questions, please contact us at %1$s. + New device / new account + You don\'t have any purchases Please select another type of colorization. The track does not contain speed data. The track does not contain altitude data. diff --git a/OsmAnd/res/xml/settings_main_screen.xml b/OsmAnd/res/xml/settings_main_screen.xml index ba31622bf4..610b675747 100644 --- a/OsmAnd/res/xml/settings_main_screen.xml +++ b/OsmAnd/res/xml/settings_main_screen.xml @@ -13,6 +13,14 @@ app:fragment="net.osmand.plus.settings.fragments.GlobalSettingsFragment" tools:icon="@drawable/ic_action_settings" /> + + diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/MainSettingsFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/MainSettingsFragment.java index 225ed389e7..1dd498a4c2 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/MainSettingsFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/MainSettingsFragment.java @@ -70,10 +70,12 @@ public class MainSettingsFragment extends BaseSettingsFragment implements OnSele availableAppModes = new LinkedHashSet<>(ApplicationMode.values(getMyApplication())); Preference globalSettings = findPreference("global_settings"); globalSettings.setIcon(getContentIcon(R.drawable.ic_action_settings)); - PreferenceCategory selectedProfile = (PreferenceCategory) findPreference(SELECTED_PROFILE); + Preference purchasesSettings = findPreference("purchases_settings"); + purchasesSettings.setIcon(getContentIcon(R.drawable.ic_action_purchases)); + PreferenceCategory selectedProfile = findPreference(SELECTED_PROFILE); selectedProfile.setIconSpaceReserved(false); setupConfigureProfilePref(); - PreferenceCategory appProfiles = (PreferenceCategory) findPreference(APP_PROFILES); + PreferenceCategory appProfiles = findPreference(APP_PROFILES); appProfiles.setIconSpaceReserved(false); setupAppProfiles(appProfiles); profileManagementPref(); diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragment.java new file mode 100644 index 0000000000..8f96c68fa6 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragment.java @@ -0,0 +1,101 @@ +package net.osmand.plus.settings.fragments; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageButton; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.FragmentActivity; + +import com.google.android.material.appbar.AppBarLayout; + +import net.osmand.plus.R; +import net.osmand.plus.UiUtilities; +import net.osmand.plus.activities.OsmandInAppPurchaseActivity; +import net.osmand.plus.base.BaseOsmAndFragment; +import net.osmand.plus.chooseplan.ChoosePlanDialogFragment; +import net.osmand.plus.inapp.InAppPurchaseHelper; + +public class PurchasesFragment extends BaseOsmAndFragment { + public static final String TAG = PurchasesFragmentEmpty.class.getName(); + private InAppPurchaseHelper purchaseHelper; + private View mainView; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + Context context = requireContext(); + purchaseHelper = getInAppPurchaseHelper(); + boolean nightMode = !getMyApplication().getSettings().isLightContent(); + LayoutInflater themedInflater = UiUtilities.getInflater(context, nightMode); + mainView = themedInflater.inflate(R.layout.purchases_layout, container, false); + AppBarLayout appbar = mainView.findViewById(R.id.appbar); + View toolbar = themedInflater.inflate(R.layout.profile_preference_toolbar_with_icon, container, false); + appbar.addView(toolbar); + + TextView toolbarTitle = appbar.findViewById(R.id.toolbar_title); + View iconToolbarContainer = appbar.findViewById(R.id.icon_toolbar); + toolbarTitle.setText(getString(R.string.purchases)); + ImageView icon = iconToolbarContainer.findViewById(R.id.profile_icon); + icon.setImageResource(R.drawable.ic_action_help_online); + icon.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Uri uri = Uri.parse("https://docs.osmand.net/en/main@latest/osmand/purchases"); + Intent intent = new Intent(Intent.ACTION_VIEW, uri); + startActivity(intent); + } + }); + ImageButton backButton = mainView.findViewById(R.id.close_button); + backButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + FragmentActivity fragmentActivity = getActivity(); + if (fragmentActivity != null) { + fragmentActivity.onBackPressed(); + } + } + }); + LinearLayout purchasesRestore = mainView.findViewById(R.id.restore_purchases); + purchasesRestore.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (purchaseHelper != null && !purchaseHelper.hasInventory()) { + purchaseHelper.requestInventory(); + } + } + }); + LinearLayout osmandLive = mainView.findViewById(R.id.osmand_live); + osmandLive.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { +// ChoosePlanDialogFragment.showOsmLiveInstance(getMyActivity().getSupportFragmentManager()); + } + }); + return mainView; + } + + @Nullable + public InAppPurchaseHelper getInAppPurchaseHelper() { + Activity activity = getActivity(); + if (activity instanceof OsmandInAppPurchaseActivity) { + return ((OsmandInAppPurchaseActivity) activity).getPurchaseHelper(); + } else { + return null; + } + } +} diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragmentEmpty.java b/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragmentEmpty.java new file mode 100644 index 0000000000..f3fc5621fb --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragmentEmpty.java @@ -0,0 +1,148 @@ +package net.osmand.plus.settings.fragments; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.graphics.Typeface; +import android.net.Uri; +import android.os.Bundle; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.Spanned; +import android.text.method.LinkMovementMethod; +import android.text.style.StyleSpan; +import android.text.style.URLSpan; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageButton; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.FragmentActivity; + +import com.google.android.material.appbar.AppBarLayout; + +import net.osmand.AndroidUtils; +import net.osmand.plus.R; +import net.osmand.plus.UiUtilities; +import net.osmand.plus.activities.OsmandInAppPurchaseActivity; +import net.osmand.plus.base.BaseOsmAndFragment; +import net.osmand.plus.chooseplan.ChoosePlanDialogFragment; +import net.osmand.plus.inapp.InAppPurchaseHelper; + +public class PurchasesFragmentEmpty extends BaseOsmAndFragment { + public static final String TAG = PurchasesFragmentEmpty.class.getName(); + private InAppPurchaseHelper purchaseHelper; + private View mainView; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + Context context = requireContext(); + purchaseHelper = getInAppPurchaseHelper(); + boolean nightMode = !getMyApplication().getSettings().isLightContent(); + LayoutInflater themedInflater = UiUtilities.getInflater(context, nightMode); + mainView = themedInflater.inflate(R.layout.empty_purchases_layout, container, false); + createToolbar(mainView, nightMode); + LinearLayout purchasesRestore = mainView.findViewById(R.id.restore_purchases); + purchasesRestore.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (purchaseHelper != null && !purchaseHelper.hasInventory()) { + purchaseHelper.requestInventory(); + } + } + }); + LinearLayout osmandLive = mainView.findViewById(R.id.osmand_live); + osmandLive.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ChoosePlanDialogFragment.showDialogInstance(getMyApplication(), getMyActivity().getSupportFragmentManager(), ChoosePlanDialogFragment.ChoosePlanDialogType.OSM_LIVE); + } + }); + setFormatLink(); + return mainView; + } + + @Nullable + public InAppPurchaseHelper getInAppPurchaseHelper() { + Activity activity = getActivity(); + if (activity instanceof OsmandInAppPurchaseActivity) { + return ((OsmandInAppPurchaseActivity) activity).getPurchaseHelper(); + } else { + return null; + } + } + + private void createToolbar(View mainView, boolean nightMode) { + AppBarLayout appbar = mainView.findViewById(R.id.appbar); + View toolbar = UiUtilities.getInflater(getContext(), nightMode).inflate(R.layout.profile_preference_toolbar_with_icon, appbar, false); + + View iconToolbarContainer = toolbar.findViewById(R.id.icon_toolbar); + ImageView icon = iconToolbarContainer.findViewById(R.id.profile_icon); + icon.setImageResource(R.drawable.ic_action_help_online); + icon.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Uri uri = Uri.parse("https://docs.osmand.net/en/main@latest/osmand/purchases"); + Intent intent = new Intent(Intent.ACTION_VIEW, uri); + startActivity(intent); + } + }); + ImageButton backButton = toolbar.findViewById(R.id.close_button); + backButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + FragmentActivity fragmentActivity = getActivity(); + if (fragmentActivity != null) { + fragmentActivity.onBackPressed(); + } + } + }); + TextView toolbarTitle = toolbar.findViewById(R.id.toolbar_title); + toolbarTitle.setText(getString(R.string.purchases)); + appbar.addView(toolbar); + } + + public void setFormatLink() { + TextView newDeviceAccountLink = mainView.findViewById(R.id.new_device_account_title); + TextView contactSupportLink = mainView.findViewById(R.id.contact_support_title); + TextView supportDescription = mainView.findViewById(R.id.support_link_title); + + SpannableString spannableStringSupport = new SpannableString(getString(R.string.contact_support)); + String urlSupport = "mailto:support@osmand.net"; + spannableStringSupport.setSpan(new URLSpan(urlSupport), 0, spannableStringSupport.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + + SpannableString spannableStringNewDeviceAccount = new SpannableString(getString(R.string.new_device_account)); + String urlNewDeviceAccount = "https://docs.osmand.net/en/main@latest/osmand/purchases#new-device--new-account"; + spannableStringNewDeviceAccount.setSpan(new URLSpan(urlNewDeviceAccount), 0, spannableStringNewDeviceAccount.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + + String emailString = getString(R.string.contact_support_mail); + String supportDescriptionString = getString(R.string.contact_support_description, emailString); + SpannableString spannableStringMail = new SpannableString(supportDescriptionString); + int startIndex = supportDescriptionString.indexOf(emailString); + int endIndex = startIndex + emailString.length(); + StyleSpan boldSpan = new StyleSpan(Typeface.BOLD); + spannableStringMail.setSpan(boldSpan, startIndex, endIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + + contactSupportLink.setText(spannableStringSupport); + newDeviceAccountLink.setText(spannableStringNewDeviceAccount); + supportDescription.setText(spannableStringMail); + + AndroidUtils.removeLinkUnderline(contactSupportLink); + AndroidUtils.removeLinkUnderline(newDeviceAccountLink); + + contactSupportLink.setMovementMethod(LinkMovementMethod.getInstance()); + newDeviceAccountLink.setMovementMethod(LinkMovementMethod.getInstance()); + + } + +} From ac370efcd95adbcdf8c741cc93073bdeb6577316 Mon Sep 17 00:00:00 2001 From: androiddevkotlin <64539346+androiddevkotlin@users.noreply.github.com> Date: Mon, 22 Mar 2021 01:48:00 +0200 Subject: [PATCH 02/11] First iteration --- OsmAnd/res/layout/purchases_layout.xml | 47 ++--- OsmAnd/res/values/attrs.xml | 1 + OsmAnd/res/values/strings.xml | 2 + OsmAnd/res/values/styles.xml | 2 + OsmAnd/res/xml/settings_main_screen.xml | 2 +- .../fragments/MainSettingsFragment.java | 3 +- .../settings/fragments/PurchasesFragment.java | 160 ++++++++++++++---- .../fragments/PurchasesFragmentEmpty.java | 4 +- 8 files changed, 163 insertions(+), 58 deletions(-) diff --git a/OsmAnd/res/layout/purchases_layout.xml b/OsmAnd/res/layout/purchases_layout.xml index dfab75ff90..b0c12c905d 100644 --- a/OsmAnd/res/layout/purchases_layout.xml +++ b/OsmAnd/res/layout/purchases_layout.xml @@ -11,21 +11,16 @@ android:layout_width="match_parent" android:layout_height="wrap_content"> + + + - - - - + app:tint="?attr/active_color_basic_green" /> @@ -189,18 +185,14 @@ android:layout_height="wrap_content" android:layout_marginEnd="@dimen/card_button_progress_size_small" android:layout_marginRight="@dimen/card_button_progress_size_small" - android:letterSpacing="@dimen/text_button_letter_spacing" - android:text="@string/live_updates" - android:textColor="?attr/active_color_basic" - android:textSize="@dimen/default_list_text_size" - app:typeface="@string/font_roboto_medium" /> + android:letterSpacing="@dimen/description_letter_spacing" + android:text="@string/troubleshooting_description" + android:textColor="?android:textColorSecondary" + android:textSize="@dimen/default_desc_text_size" + app:typeface="@string/font_roboto_regular" /> - - + + + + + diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index 74cea426f4..b18a660072 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -12,6 +12,8 @@ --> + Please follow this link if you any issues with purchases. + Troubleshooting support@osmand.net Contact support If your purchases don\'t show up here, tap on “Restore purchases”, or contact our support team. diff --git a/OsmAnd/res/values/styles.xml b/OsmAnd/res/values/styles.xml index 7f16bc4586..81c73d5697 100644 --- a/OsmAnd/res/values/styles.xml +++ b/OsmAnd/res/values/styles.xml @@ -218,6 +218,7 @@ @color/divider_color_light @color/text_color_primary_light @color/active_color_primary_light + @color/profile_icon_color_green_light @color/card_and_list_background_light @color/activity_background_light @drawable/pages_bg_light @@ -519,6 +520,7 @@ @color/divider_color_dark @color/text_color_primary_dark @color/active_color_primary_dark + @color/profile_icon_color_green_dark @color/card_and_list_background_dark @color/activity_background_dark @drawable/pages_bg_dark diff --git a/OsmAnd/res/xml/settings_main_screen.xml b/OsmAnd/res/xml/settings_main_screen.xml index 610b675747..b71907f71c 100644 --- a/OsmAnd/res/xml/settings_main_screen.xml +++ b/OsmAnd/res/xml/settings_main_screen.xml @@ -18,7 +18,7 @@ android:layout="@layout/preference_with_descr" android:persistent="false" android:title="@string/purchases" - app:fragment="net.osmand.plus.settings.fragments.PurchasesFragmentEmpty" + app:fragment="net.osmand.plus.settings.fragments.PurchasesFragment" tools:icon="@drawable/ic_action_purchases" /> (ApplicationMode.values(getMyApplication())); Preference globalSettings = findPreference("global_settings"); globalSettings.setIcon(getContentIcon(R.drawable.ic_action_settings)); - Preference purchasesSettings = findPreference("purchases_settings"); + Preference purchasesSettings = findPreference(PURCHASES_SETTINGS); purchasesSettings.setIcon(getContentIcon(R.drawable.ic_action_purchases)); PreferenceCategory selectedProfile = findPreference(SELECTED_PROFILE); selectedProfile.setIconSpaceReserved(false); diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragment.java index 8f96c68fa6..9fe813fa1f 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragment.java @@ -3,8 +3,15 @@ package net.osmand.plus.settings.fragments; import android.app.Activity; import android.content.Context; import android.content.Intent; +import android.graphics.Typeface; import android.net.Uri; import android.os.Bundle; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.Spanned; +import android.text.method.LinkMovementMethod; +import android.text.style.StyleSpan; +import android.text.style.URLSpan; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -19,17 +26,27 @@ import androidx.fragment.app.FragmentActivity; import com.google.android.material.appbar.AppBarLayout; +import net.osmand.AndroidUtils; +import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.UiUtilities; +import net.osmand.plus.activities.MapActivity; import net.osmand.plus.activities.OsmandInAppPurchaseActivity; import net.osmand.plus.base.BaseOsmAndFragment; -import net.osmand.plus.chooseplan.ChoosePlanDialogFragment; import net.osmand.plus.inapp.InAppPurchaseHelper; +import net.osmand.plus.liveupdates.OsmLiveActivity; public class PurchasesFragment extends BaseOsmAndFragment { - public static final String TAG = PurchasesFragmentEmpty.class.getName(); + + public static final String TAG = PurchasesFragment.class.getName(); private InAppPurchaseHelper purchaseHelper; private View mainView; + private Context context; + private OsmandApplication app; + private String url; + private static final String PLAY_STORE_SUBSCRIPTION_URL = "https://play.google.com/store/account/subscriptions"; + private static final String PLAY_STORE_SUBSCRIPTION_DEEPLINK_URL = "https://play.google.com/store/account/subscriptions?sku=%s&package=%s"; + @Override public void onCreate(Bundle savedInstanceState) { @@ -38,38 +55,15 @@ public class PurchasesFragment extends BaseOsmAndFragment { @Override public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - Context context = requireContext(); + app = getMyApplication(); + context = requireContext(); purchaseHelper = getInAppPurchaseHelper(); + final MapActivity mapActivity = (MapActivity) getActivity(); boolean nightMode = !getMyApplication().getSettings().isLightContent(); LayoutInflater themedInflater = UiUtilities.getInflater(context, nightMode); mainView = themedInflater.inflate(R.layout.purchases_layout, container, false); - AppBarLayout appbar = mainView.findViewById(R.id.appbar); - View toolbar = themedInflater.inflate(R.layout.profile_preference_toolbar_with_icon, container, false); - appbar.addView(toolbar); - TextView toolbarTitle = appbar.findViewById(R.id.toolbar_title); - View iconToolbarContainer = appbar.findViewById(R.id.icon_toolbar); - toolbarTitle.setText(getString(R.string.purchases)); - ImageView icon = iconToolbarContainer.findViewById(R.id.profile_icon); - icon.setImageResource(R.drawable.ic_action_help_online); - icon.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - Uri uri = Uri.parse("https://docs.osmand.net/en/main@latest/osmand/purchases"); - Intent intent = new Intent(Intent.ACTION_VIEW, uri); - startActivity(intent); - } - }); - ImageButton backButton = mainView.findViewById(R.id.close_button); - backButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - FragmentActivity fragmentActivity = getActivity(); - if (fragmentActivity != null) { - fragmentActivity.onBackPressed(); - } - } - }); + createToolbar(mainView, nightMode); LinearLayout purchasesRestore = mainView.findViewById(R.id.restore_purchases); purchasesRestore.setOnClickListener(new View.OnClickListener() { @Override @@ -79,13 +73,28 @@ public class PurchasesFragment extends BaseOsmAndFragment { } } }); - LinearLayout osmandLive = mainView.findViewById(R.id.osmand_live); - osmandLive.setOnClickListener(new View.OnClickListener() { + LinearLayout reportContainer = mainView.findViewById(R.id.report_container); + reportContainer.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { -// ChoosePlanDialogFragment.showOsmLiveInstance(getMyActivity().getSupportFragmentManager()); + Intent intent = new Intent(mapActivity, OsmLiveActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); + if (mapActivity != null) { + mapActivity.startActivity(intent); + } } }); + LinearLayout liveUpdatesContainer = mainView.findViewById(R.id.live_updates_container); + liveUpdatesContainer.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { +// Fragment parent = getParentFragment(); +// if (parent != null) { +// ((LiveUpdatesFragment) parent).updateSubscriptionHeader(); +// } + } + }); + setFormatLink(); return mainView; } @@ -98,4 +107,91 @@ public class PurchasesFragment extends BaseOsmAndFragment { return null; } } + + private void createToolbar(View mainView, boolean nightMode) { + AppBarLayout appbar = mainView.findViewById(R.id.appbar); + View toolbar = UiUtilities.getInflater(getContext(), nightMode).inflate(R.layout.profile_preference_toolbar_with_icon, appbar, false); + + View iconToolbarContainer = toolbar.findViewById(R.id.icon_toolbar); + ImageView icon = iconToolbarContainer.findViewById(R.id.profile_icon); + icon.setImageResource(R.drawable.ic_action_help_online); + icon.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Uri uri = Uri.parse("https://docs.osmand.net/en/main@latest/osmand/purchases"); + Intent intent = new Intent(Intent.ACTION_VIEW, uri); + if (AndroidUtils.isIntentSafe(context, intent)) { + startActivity(intent); + } + } + }); + ImageButton backButton = toolbar.findViewById(R.id.close_button); + backButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + FragmentActivity fragmentActivity = getActivity(); + if (fragmentActivity != null) { + fragmentActivity.onBackPressed(); + } + } + }); + getSkuAppId(); + LinearLayout manageSubscriptionContainer = mainView.findViewById(R.id.manage_subscription_container); + manageSubscriptionContainer.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setData(Uri.parse(url)); + if (AndroidUtils.isIntentSafe(context, intent)) { + startActivity(intent); + } + } + }); + TextView toolbarTitle = toolbar.findViewById(R.id.toolbar_title); + toolbarTitle.setText(getString(R.string.purchases)); + appbar.addView(toolbar); + } + + public void setFormatLink() { + TextView newDeviceAccountLink = mainView.findViewById(R.id.new_device_account_title); + TextView contactSupportLink = mainView.findViewById(R.id.contact_support_title); + TextView supportDescription = mainView.findViewById(R.id.support_link_title); + + SpannableString spannableStringSupport = new SpannableString(getString(R.string.contact_support)); + String urlSupport = "mailto:support@osmand.net"; + spannableStringSupport.setSpan(new URLSpan(urlSupport), 0, spannableStringSupport.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + + SpannableString spannableStringNewDeviceAccount = new SpannableString(getString(R.string.new_device_account)); + String urlNewDeviceAccount = "https://docs.osmand.net/en/main@latest/osmand/purchases#new-device--new-account"; + spannableStringNewDeviceAccount.setSpan(new URLSpan(urlNewDeviceAccount), 0, spannableStringNewDeviceAccount.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + + String emailString = getString(R.string.contact_support_mail); + String supportDescriptionString = getString(R.string.contact_support_description, emailString); + SpannableString spannableStringMail = new SpannableString(supportDescriptionString); + int startIndex = supportDescriptionString.indexOf(emailString); + int endIndex = startIndex + emailString.length(); + StyleSpan boldSpan = new StyleSpan(Typeface.BOLD); + spannableStringMail.setSpan(boldSpan, startIndex, endIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + + contactSupportLink.setText(spannableStringSupport); + newDeviceAccountLink.setText(spannableStringNewDeviceAccount); + supportDescription.setText(spannableStringMail); + + AndroidUtils.removeLinkUnderline(contactSupportLink); + AndroidUtils.removeLinkUnderline(newDeviceAccountLink); + + contactSupportLink.setMovementMethod(LinkMovementMethod.getInstance()); + newDeviceAccountLink.setMovementMethod(LinkMovementMethod.getInstance()); + } + + private void getSkuAppId() { + InAppPurchaseHelper purchaseHelper = app.getInAppPurchaseHelper(); + if (purchaseHelper != null) { + String sku = purchaseHelper.getFullVersion().getSku(); + url = String.format(PLAY_STORE_SUBSCRIPTION_DEEPLINK_URL, + sku, context.getPackageName()); + } else { + url = PLAY_STORE_SUBSCRIPTION_URL; + } + } } diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragmentEmpty.java b/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragmentEmpty.java index f3fc5621fb..8fe8676cdc 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragmentEmpty.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragmentEmpty.java @@ -65,7 +65,9 @@ public class PurchasesFragmentEmpty extends BaseOsmAndFragment { osmandLive.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - ChoosePlanDialogFragment.showDialogInstance(getMyApplication(), getMyActivity().getSupportFragmentManager(), ChoosePlanDialogFragment.ChoosePlanDialogType.OSM_LIVE); + if (getMyApplication() != null && getMyActivity() != null) { + ChoosePlanDialogFragment.showDialogInstance(getMyApplication(), getMyActivity().getSupportFragmentManager(), ChoosePlanDialogFragment.ChoosePlanDialogType.OSM_LIVE); + } } }); setFormatLink(); From 8de07a2c59a42f9eecd5c5170bca4de132b0bbab Mon Sep 17 00:00:00 2001 From: androiddevkotlin <64539346+androiddevkotlin@users.noreply.github.com> Date: Mon, 22 Mar 2021 14:36:32 +0200 Subject: [PATCH 03/11] Second Iteration --- OsmAnd/res/layout/purchases_layout.xml | 7 +- OsmAnd/res/xml/settings_main_screen.xml | 1 - .../fragments/MainSettingsFragment.java | 8 ++- .../settings/fragments/PurchasesFragment.java | 64 ++++++++++++------- 4 files changed, 52 insertions(+), 28 deletions(-) diff --git a/OsmAnd/res/layout/purchases_layout.xml b/OsmAnd/res/layout/purchases_layout.xml index b0c12c905d..c5f9bb471b 100644 --- a/OsmAnd/res/layout/purchases_layout.xml +++ b/OsmAnd/res/layout/purchases_layout.xml @@ -11,11 +11,8 @@ android:layout_width="match_parent" android:layout_height="wrap_content"> - - - + android:paddingBottom="@dimen/card_padding" + android:clickable="true" + android:focusable="true"> Date: Tue, 23 Mar 2021 01:02:19 +0200 Subject: [PATCH 04/11] Review --- OsmAnd/res/layout/empty_purchases_layout.xml | 12 +- OsmAnd/res/layout/purchases_layout.xml | 25 +-- OsmAnd/res/values/attrs.xml | 2 +- OsmAnd/res/values/strings.xml | 1 - OsmAnd/res/values/styles.xml | 4 +- .../plus/activities/MapActivityActions.java | 16 -- .../settings/fragments/PurchasesFragment.java | 81 +++++++--- .../fragments/PurchasesFragmentEmpty.java | 150 ------------------ 8 files changed, 81 insertions(+), 210 deletions(-) delete mode 100644 OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragmentEmpty.java diff --git a/OsmAnd/res/layout/empty_purchases_layout.xml b/OsmAnd/res/layout/empty_purchases_layout.xml index 7a19918581..ca7fdef2dd 100644 --- a/OsmAnd/res/layout/empty_purchases_layout.xml +++ b/OsmAnd/res/layout/empty_purchases_layout.xml @@ -12,13 +12,11 @@ android:layout_width="match_parent" android:layout_height="wrap_content"> - - + + + + app:tint="?attr/profile_icon_color_green" /> + + - + diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index b18a660072..30b850dba0 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -14,7 +14,6 @@ Please follow this link if you any issues with purchases. Troubleshooting - support@osmand.net Contact support If your purchases don\'t show up here, tap on “Restore purchases”, or contact our support team. If you have any questions, please contact us at %1$s. diff --git a/OsmAnd/res/values/styles.xml b/OsmAnd/res/values/styles.xml index 81c73d5697..113454ae88 100644 --- a/OsmAnd/res/values/styles.xml +++ b/OsmAnd/res/values/styles.xml @@ -218,7 +218,7 @@ @color/divider_color_light @color/text_color_primary_light @color/active_color_primary_light - @color/profile_icon_color_green_light + @color/profile_icon_color_green_light @color/card_and_list_background_light @color/activity_background_light @drawable/pages_bg_light @@ -520,7 +520,7 @@ @color/divider_color_dark @color/text_color_primary_dark @color/active_color_primary_dark - @color/profile_icon_color_green_dark + @color/profile_icon_color_green_dark @color/card_and_list_background_dark @color/activity_background_dark @drawable/pages_bg_dark diff --git a/OsmAnd/src/net/osmand/plus/activities/MapActivityActions.java b/OsmAnd/src/net/osmand/plus/activities/MapActivityActions.java index c0fec48168..01ae04a0d8 100644 --- a/OsmAnd/src/net/osmand/plus/activities/MapActivityActions.java +++ b/OsmAnd/src/net/osmand/plus/activities/MapActivityActions.java @@ -1030,22 +1030,6 @@ public class MapActivityActions implements DialogProvider { }).createItem()); */ - if (Version.isGooglePlayEnabled() || Version.isHuawei() || Version.isDeveloperVersion(app)) { - optionsMenuHelper.addItem(new ItemBuilder().setTitleId(R.string.purchases, mapActivity) - .setId(DRAWER_OSMAND_LIVE_ID) - .setIcon(R.drawable.ic_action_purchases) - .setListener(new ItemClickListener() { - @Override - public boolean onContextMenuClick(ArrayAdapter adapter, int itemId, int pos, boolean isChecked, int[] viewCoordinates) { - app.logEvent("drawer_osm_live_open"); - Intent intent = new Intent(mapActivity, OsmLiveActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); - mapActivity.startActivity(intent); - return true; - } - }).createItem()); - } - optionsMenuHelper.addItem(new ItemBuilder().setTitleId(R.string.shared_string_help, mapActivity) .setId(DRAWER_HELP_ID) .setIcon(R.drawable.ic_action_help) diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragment.java index c70b7a8cc4..fccfd40d48 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragment.java @@ -32,9 +32,11 @@ import net.osmand.AndroidUtils; import net.osmand.plus.OsmandApplication; 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.activities.OsmandInAppPurchaseActivity; import net.osmand.plus.base.BaseOsmAndFragment; +import net.osmand.plus.chooseplan.ChoosePlanDialogFragment; import net.osmand.plus.inapp.InAppPurchaseHelper; import net.osmand.plus.liveupdates.LiveUpdatesFragmentNew; import net.osmand.plus.liveupdates.OsmLiveActivity; @@ -43,6 +45,7 @@ import net.osmand.plus.wikipedia.WikipediaDialogFragment; public class PurchasesFragment extends BaseOsmAndFragment { public static final String TAG = PurchasesFragment.class.getName(); + public static final String KEY_IS_SUBSCRIBER = "action_is_new"; private static final String PLAY_STORE_SUBSCRIPTION_URL = "https://play.google.com/store/account/subscriptions"; private static final String PLAY_STORE_SUBSCRIPTION_DEEPLINK_URL = "https://play.google.com/store/account/subscriptions?sku=%s&package=%s"; private InAppPurchaseHelper purchaseHelper; @@ -50,6 +53,7 @@ public class PurchasesFragment extends BaseOsmAndFragment { private Context context; private OsmandApplication app; private String url; + private Boolean isSubscriber; public static boolean showInstance(FragmentManager fragmentManager) { try { @@ -74,12 +78,26 @@ public class PurchasesFragment extends BaseOsmAndFragment { app = getMyApplication(); context = requireContext(); purchaseHelper = getInAppPurchaseHelper(); - - + isSubscriber = Version.isPaidVersion(app); final MapActivity mapActivity = (MapActivity) getActivity(); final boolean nightMode = !getMyApplication().getSettings().isLightContent(); LayoutInflater themedInflater = UiUtilities.getInflater(context, nightMode); - mainView = themedInflater.inflate(R.layout.purchases_layout, container, false); + + if (!isSubscriber) { + mainView = themedInflater.inflate(R.layout.purchases_layout, container, false); + setSubscriptionClick(mapActivity); + } else { + mainView = themedInflater.inflate(R.layout.empty_purchases_layout, container, false); + LinearLayout osmandLive = mainView.findViewById(R.id.osmand_live); + osmandLive.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (getMyApplication() != null && getMyActivity() != null) { + ChoosePlanDialogFragment.showDialogInstance(getMyApplication(), getMyActivity().getSupportFragmentManager(), ChoosePlanDialogFragment.ChoosePlanDialogType.OSM_LIVE); + } + } + }); + } AndroidUtils.addStatusBarPadding21v(getActivity(), mainView); createToolbar(mainView, nightMode); mainView.setOnTouchListener(new View.OnTouchListener() { @@ -87,7 +105,6 @@ public class PurchasesFragment extends BaseOsmAndFragment { return true; } }); - LinearLayout purchasesRestore = mainView.findViewById(R.id.restore_purchases); purchasesRestore.setOnClickListener(new View.OnClickListener() { @Override @@ -97,6 +114,33 @@ public class PurchasesFragment extends BaseOsmAndFragment { } } }); + LinearLayout newDeviceAccountContainer = mainView.findViewById(R.id.new_device_account_container); + newDeviceAccountContainer.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + WikipediaDialogFragment.showFullArticle(context, Uri.parse("https://docs.osmand.net/en/main@latest/osmand/purchases#new-device--new-account"), nightMode); + } + }); + + setFormatLink(); + return mainView; + } + + @Override + public void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + outState.putBoolean(KEY_IS_SUBSCRIBER, isSubscriber); + } + + @Override + public void onViewStateRestored(@Nullable Bundle savedInstanceState) { + super.onViewStateRestored(savedInstanceState); + if (savedInstanceState != null) { + savedInstanceState.getBoolean(KEY_IS_SUBSCRIBER); + } + } + + private void setSubscriptionClick(final MapActivity mapActivity) { LinearLayout reportContainer = mainView.findViewById(R.id.report_container); reportContainer.setOnClickListener(new View.OnClickListener() { @Override @@ -118,16 +162,18 @@ public class PurchasesFragment extends BaseOsmAndFragment { } } }); - LinearLayout newDeviceAccountContainer = mainView.findViewById(R.id.new_device_account_container); - newDeviceAccountContainer.setOnClickListener(new View.OnClickListener() { + getSkuAppId(); + LinearLayout manageSubscriptionContainer = mainView.findViewById(R.id.manage_subscription_container); + manageSubscriptionContainer.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - WikipediaDialogFragment.showFullArticle(context, Uri.parse("https://docs.osmand.net/en/main@latest/osmand/purchases#new-device--new-account"), nightMode); + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setData(Uri.parse(url)); + if (AndroidUtils.isIntentSafe(context, intent)) { + startActivity(intent); + } } }); - - setFormatLink(); - return mainView; } @Nullable @@ -163,18 +209,7 @@ public class PurchasesFragment extends BaseOsmAndFragment { } } }); - getSkuAppId(); - LinearLayout manageSubscriptionContainer = mainView.findViewById(R.id.manage_subscription_container); - manageSubscriptionContainer.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - Intent intent = new Intent(Intent.ACTION_VIEW); - intent.setData(Uri.parse(url)); - if (AndroidUtils.isIntentSafe(context, intent)) { - startActivity(intent); - } - } - }); + TextView toolbarTitle = toolbar.findViewById(R.id.toolbar_title); toolbarTitle.setText(getString(R.string.purchases)); appbar.addView(toolbar); @@ -188,7 +223,7 @@ public class PurchasesFragment extends BaseOsmAndFragment { String urlSupport = "mailto:support@osmand.net"; spannableStringSupport.setSpan(new URLSpan(urlSupport), 0, spannableStringSupport.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - String emailString = getString(R.string.contact_support_mail); + String emailString = "support@osmand.net"; String supportDescriptionString = getString(R.string.contact_support_description, emailString); SpannableString spannableStringMail = new SpannableString(supportDescriptionString); int startIndex = supportDescriptionString.indexOf(emailString); diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragmentEmpty.java b/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragmentEmpty.java deleted file mode 100644 index 8fe8676cdc..0000000000 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragmentEmpty.java +++ /dev/null @@ -1,150 +0,0 @@ -package net.osmand.plus.settings.fragments; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.graphics.Typeface; -import android.net.Uri; -import android.os.Bundle; -import android.text.Spannable; -import android.text.SpannableString; -import android.text.Spanned; -import android.text.method.LinkMovementMethod; -import android.text.style.StyleSpan; -import android.text.style.URLSpan; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageButton; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.FragmentActivity; - -import com.google.android.material.appbar.AppBarLayout; - -import net.osmand.AndroidUtils; -import net.osmand.plus.R; -import net.osmand.plus.UiUtilities; -import net.osmand.plus.activities.OsmandInAppPurchaseActivity; -import net.osmand.plus.base.BaseOsmAndFragment; -import net.osmand.plus.chooseplan.ChoosePlanDialogFragment; -import net.osmand.plus.inapp.InAppPurchaseHelper; - -public class PurchasesFragmentEmpty extends BaseOsmAndFragment { - public static final String TAG = PurchasesFragmentEmpty.class.getName(); - private InAppPurchaseHelper purchaseHelper; - private View mainView; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - Context context = requireContext(); - purchaseHelper = getInAppPurchaseHelper(); - boolean nightMode = !getMyApplication().getSettings().isLightContent(); - LayoutInflater themedInflater = UiUtilities.getInflater(context, nightMode); - mainView = themedInflater.inflate(R.layout.empty_purchases_layout, container, false); - createToolbar(mainView, nightMode); - LinearLayout purchasesRestore = mainView.findViewById(R.id.restore_purchases); - purchasesRestore.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - if (purchaseHelper != null && !purchaseHelper.hasInventory()) { - purchaseHelper.requestInventory(); - } - } - }); - LinearLayout osmandLive = mainView.findViewById(R.id.osmand_live); - osmandLive.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - if (getMyApplication() != null && getMyActivity() != null) { - ChoosePlanDialogFragment.showDialogInstance(getMyApplication(), getMyActivity().getSupportFragmentManager(), ChoosePlanDialogFragment.ChoosePlanDialogType.OSM_LIVE); - } - } - }); - setFormatLink(); - return mainView; - } - - @Nullable - public InAppPurchaseHelper getInAppPurchaseHelper() { - Activity activity = getActivity(); - if (activity instanceof OsmandInAppPurchaseActivity) { - return ((OsmandInAppPurchaseActivity) activity).getPurchaseHelper(); - } else { - return null; - } - } - - private void createToolbar(View mainView, boolean nightMode) { - AppBarLayout appbar = mainView.findViewById(R.id.appbar); - View toolbar = UiUtilities.getInflater(getContext(), nightMode).inflate(R.layout.profile_preference_toolbar_with_icon, appbar, false); - - View iconToolbarContainer = toolbar.findViewById(R.id.icon_toolbar); - ImageView icon = iconToolbarContainer.findViewById(R.id.profile_icon); - icon.setImageResource(R.drawable.ic_action_help_online); - icon.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - Uri uri = Uri.parse("https://docs.osmand.net/en/main@latest/osmand/purchases"); - Intent intent = new Intent(Intent.ACTION_VIEW, uri); - startActivity(intent); - } - }); - ImageButton backButton = toolbar.findViewById(R.id.close_button); - backButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - FragmentActivity fragmentActivity = getActivity(); - if (fragmentActivity != null) { - fragmentActivity.onBackPressed(); - } - } - }); - TextView toolbarTitle = toolbar.findViewById(R.id.toolbar_title); - toolbarTitle.setText(getString(R.string.purchases)); - appbar.addView(toolbar); - } - - public void setFormatLink() { - TextView newDeviceAccountLink = mainView.findViewById(R.id.new_device_account_title); - TextView contactSupportLink = mainView.findViewById(R.id.contact_support_title); - TextView supportDescription = mainView.findViewById(R.id.support_link_title); - - SpannableString spannableStringSupport = new SpannableString(getString(R.string.contact_support)); - String urlSupport = "mailto:support@osmand.net"; - spannableStringSupport.setSpan(new URLSpan(urlSupport), 0, spannableStringSupport.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - - SpannableString spannableStringNewDeviceAccount = new SpannableString(getString(R.string.new_device_account)); - String urlNewDeviceAccount = "https://docs.osmand.net/en/main@latest/osmand/purchases#new-device--new-account"; - spannableStringNewDeviceAccount.setSpan(new URLSpan(urlNewDeviceAccount), 0, spannableStringNewDeviceAccount.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - - String emailString = getString(R.string.contact_support_mail); - String supportDescriptionString = getString(R.string.contact_support_description, emailString); - SpannableString spannableStringMail = new SpannableString(supportDescriptionString); - int startIndex = supportDescriptionString.indexOf(emailString); - int endIndex = startIndex + emailString.length(); - StyleSpan boldSpan = new StyleSpan(Typeface.BOLD); - spannableStringMail.setSpan(boldSpan, startIndex, endIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - - contactSupportLink.setText(spannableStringSupport); - newDeviceAccountLink.setText(spannableStringNewDeviceAccount); - supportDescription.setText(spannableStringMail); - - AndroidUtils.removeLinkUnderline(contactSupportLink); - AndroidUtils.removeLinkUnderline(newDeviceAccountLink); - - contactSupportLink.setMovementMethod(LinkMovementMethod.getInstance()); - newDeviceAccountLink.setMovementMethod(LinkMovementMethod.getInstance()); - - } - -} From 294bc53ecde2393e25337226aad07a87c5921fd4 Mon Sep 17 00:00:00 2001 From: androiddevkotlin <64539346+androiddevkotlin@users.noreply.github.com> Date: Tue, 23 Mar 2021 14:01:11 +0200 Subject: [PATCH 05/11] Minor addition strings format --- OsmAnd/res/values/strings.xml | 2 +- .../plus/settings/fragments/PurchasesFragment.java | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index 30b850dba0..1117181317 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -15,7 +15,7 @@ Please follow this link if you any issues with purchases. Troubleshooting Contact support - If your purchases don\'t show up here, tap on “Restore purchases”, or contact our support team. + If your purchases don\'t show up here, tap on “%1$s”, or contact our support team. If you have any questions, please contact us at %1$s. New device / new account You don\'t have any purchases diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragment.java index fccfd40d48..32b0bf2f38 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragment.java @@ -122,7 +122,7 @@ public class PurchasesFragment extends BaseOsmAndFragment { } }); - setFormatLink(); + setFormatStrings(); return mainView; } @@ -215,9 +215,14 @@ public class PurchasesFragment extends BaseOsmAndFragment { appbar.addView(toolbar); } - public void setFormatLink() { + public void setFormatStrings() { TextView contactSupportLink = mainView.findViewById(R.id.contact_support_title); TextView supportDescription = mainView.findViewById(R.id.support_link_title); + TextView infoDescription = mainView.findViewById(R.id.info_description); + + String restorePurchases = getString(R.string.restore_purchases); + String infoPurchases = String.format(getString(R.string.empty_purchases_description), restorePurchases); + infoDescription.setText(infoPurchases); SpannableString spannableStringSupport = new SpannableString(getString(R.string.contact_support)); String urlSupport = "mailto:support@osmand.net"; From edc741e84fcec133bd3b5a553ccdb1f23f7b5ec1 Mon Sep 17 00:00:00 2001 From: androiddevkotlin <64539346+androiddevkotlin@users.noreply.github.com> Date: Tue, 23 Mar 2021 14:26:15 +0200 Subject: [PATCH 06/11] NPE fix --- OsmAnd/res/layout/empty_purchases_layout.xml | 8 ++++---- .../plus/settings/fragments/PurchasesFragment.java | 11 ++++++----- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/OsmAnd/res/layout/empty_purchases_layout.xml b/OsmAnd/res/layout/empty_purchases_layout.xml index ca7fdef2dd..56bfb82b6f 100644 --- a/OsmAnd/res/layout/empty_purchases_layout.xml +++ b/OsmAnd/res/layout/empty_purchases_layout.xml @@ -69,7 +69,7 @@ android:id="@+id/restore_purchases" android:layout_width="match_parent" android:layout_height="wrap_content" - android:background="@android:drawable/list_selector_background" + android:background="?android:attr/selectableItemBackground" android:minHeight="@dimen/list_item_height" android:paddingStart="@dimen/list_content_padding" android:paddingLeft="@dimen/list_content_padding" @@ -115,7 +115,7 @@ android:id="@+id/new_device_account_container" android:layout_width="match_parent" android:layout_height="wrap_content" - android:background="@android:drawable/list_selector_background" + android:background="?android:attr/selectableItemBackground" android:minHeight="@dimen/list_item_height" android:paddingStart="@dimen/list_content_padding" android:paddingLeft="@dimen/list_content_padding" @@ -153,7 +153,7 @@ android:id="@+id/support_link_container" android:layout_width="match_parent" android:layout_height="wrap_content" - android:background="@android:drawable/list_selector_background" + android:background="?android:attr/selectableItemBackground" android:minHeight="@dimen/list_item_height" android:paddingStart="@dimen/list_content_padding" android:paddingLeft="@dimen/list_content_padding" @@ -189,7 +189,7 @@ android:id="@+id/contact_support_container" android:layout_width="match_parent" android:layout_height="wrap_content" - android:background="@android:drawable/list_selector_background" + android:background="?android:attr/selectableItemBackground" android:paddingStart="@dimen/action_bar_image_side_margin" android:paddingLeft="@dimen/action_bar_image_side_margin" android:paddingTop="@dimen/card_padding" diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragment.java index 32b0bf2f38..9fb4047ca5 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragment.java @@ -97,6 +97,11 @@ public class PurchasesFragment extends BaseOsmAndFragment { } } }); + TextView infoDescription = mainView.findViewById(R.id.info_description); + + String restorePurchases = getString(R.string.restore_purchases); + String infoPurchases = String.format(getString(R.string.empty_purchases_description), restorePurchases); + infoDescription.setText(infoPurchases); } AndroidUtils.addStatusBarPadding21v(getActivity(), mainView); createToolbar(mainView, nightMode); @@ -174,6 +179,7 @@ public class PurchasesFragment extends BaseOsmAndFragment { } } }); + } @Nullable @@ -218,11 +224,6 @@ public class PurchasesFragment extends BaseOsmAndFragment { public void setFormatStrings() { TextView contactSupportLink = mainView.findViewById(R.id.contact_support_title); TextView supportDescription = mainView.findViewById(R.id.support_link_title); - TextView infoDescription = mainView.findViewById(R.id.info_description); - - String restorePurchases = getString(R.string.restore_purchases); - String infoPurchases = String.format(getString(R.string.empty_purchases_description), restorePurchases); - infoDescription.setText(infoPurchases); SpannableString spannableStringSupport = new SpannableString(getString(R.string.contact_support)); String urlSupport = "mailto:support@osmand.net"; From 3e4153a5cb885d7957be18ac261ffea4a5c35e9f Mon Sep 17 00:00:00 2001 From: cepprice Date: Tue, 23 Mar 2021 23:36:38 +0500 Subject: [PATCH 07/11] Add subscription card --- OsmAnd/res/drawable/bg_osmand_live_active.xml | 5 + .../res/drawable/bg_osmand_live_cancelled.xml | 5 + OsmAnd/res/drawable/btn_solid_border_dark.xml | 7 + .../res/drawable/btn_solid_border_light.xml | 7 + .../layout/dialog_edit_gpx_description.xml | 4 +- OsmAnd/res/layout/purchases_layout.xml | 586 +++++++++--------- OsmAnd/res/layout/subscription_layout.xml | 108 ++++ OsmAnd/res/layout/subscriptions_card.xml | 5 + OsmAnd/res/values/colors.xml | 2 + OsmAnd/res/values/strings.xml | 10 + .../net/osmand/plus/inapp/InAppPurchases.java | 34 +- .../settings/fragments/PurchasesFragment.java | 39 +- .../settings/fragments/SubscriptionsCard.java | 179 ++++++ .../GpxEditDescriptionDialogFragment.java | 15 +- 14 files changed, 703 insertions(+), 303 deletions(-) create mode 100644 OsmAnd/res/drawable/bg_osmand_live_active.xml create mode 100644 OsmAnd/res/drawable/bg_osmand_live_cancelled.xml create mode 100644 OsmAnd/res/drawable/btn_solid_border_dark.xml create mode 100644 OsmAnd/res/drawable/btn_solid_border_light.xml create mode 100644 OsmAnd/res/layout/subscription_layout.xml create mode 100644 OsmAnd/res/layout/subscriptions_card.xml create mode 100644 OsmAnd/src/net/osmand/plus/settings/fragments/SubscriptionsCard.java diff --git a/OsmAnd/res/drawable/bg_osmand_live_active.xml b/OsmAnd/res/drawable/bg_osmand_live_active.xml new file mode 100644 index 0000000000..8544f60004 --- /dev/null +++ b/OsmAnd/res/drawable/bg_osmand_live_active.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/OsmAnd/res/drawable/bg_osmand_live_cancelled.xml b/OsmAnd/res/drawable/bg_osmand_live_cancelled.xml new file mode 100644 index 0000000000..2774bc263a --- /dev/null +++ b/OsmAnd/res/drawable/bg_osmand_live_cancelled.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/OsmAnd/res/drawable/btn_solid_border_dark.xml b/OsmAnd/res/drawable/btn_solid_border_dark.xml new file mode 100644 index 0000000000..5f0ecb368b --- /dev/null +++ b/OsmAnd/res/drawable/btn_solid_border_dark.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/drawable/btn_solid_border_light.xml b/OsmAnd/res/drawable/btn_solid_border_light.xml new file mode 100644 index 0000000000..528f174597 --- /dev/null +++ b/OsmAnd/res/drawable/btn_solid_border_light.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/dialog_edit_gpx_description.xml b/OsmAnd/res/layout/dialog_edit_gpx_description.xml index 66c0d57f0a..a2997960b9 100644 --- a/OsmAnd/res/layout/dialog_edit_gpx_description.xml +++ b/OsmAnd/res/layout/dialog_edit_gpx_description.xml @@ -45,7 +45,7 @@ osmand:typeface="@string/font_roboto_medium" /> - + android:layout_height="match_parent"> - - - + android:orientation="vertical"> - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/subscription_layout.xml b/OsmAnd/res/layout/subscription_layout.xml new file mode 100644 index 0000000000..de35b80f4a --- /dev/null +++ b/OsmAnd/res/layout/subscription_layout.xml @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/OsmAnd/res/layout/subscriptions_card.xml b/OsmAnd/res/layout/subscriptions_card.xml new file mode 100644 index 0000000000..278f381933 --- /dev/null +++ b/OsmAnd/res/layout/subscriptions_card.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/OsmAnd/res/values/colors.xml b/OsmAnd/res/values/colors.xml index 410723dc79..8d9f9dc24a 100644 --- a/OsmAnd/res/values/colors.xml +++ b/OsmAnd/res/values/colors.xml @@ -75,6 +75,8 @@ #d28521 #237bff #d28521 + #14CC70 + #EE5622 #505050 diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index 1117181317..3e81d699c3 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -12,6 +12,16 @@ --> + Expired + On hold + In grace period + Renew subscription + Cancelled + Next billing date: %1$s + Three months subscription + Monthly subscription + Annual subscription + OsmAnd Live Please follow this link if you any issues with purchases. Troubleshooting Contact support diff --git a/OsmAnd/src/net/osmand/plus/inapp/InAppPurchases.java b/OsmAnd/src/net/osmand/plus/inapp/InAppPurchases.java index e6ec431187..8a6d5a0128 100644 --- a/OsmAnd/src/net/osmand/plus/inapp/InAppPurchases.java +++ b/OsmAnd/src/net/osmand/plus/inapp/InAppPurchases.java @@ -8,8 +8,10 @@ import android.text.SpannableStringBuilder; import android.text.style.ForegroundColorSpan; import androidx.annotation.ColorInt; +import androidx.annotation.DrawableRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.annotation.StringRes; import net.osmand.AndroidUtils; import net.osmand.Period; @@ -580,24 +582,40 @@ public abstract class InAppPurchases { private InAppSubscriptionIntroductoryInfo introductoryInfo; public enum SubscriptionState { - UNDEFINED("undefined"), - ACTIVE("active"), - CANCELLED("cancelled"), - IN_GRACE_PERIOD("in_grace_period"), - ON_HOLD("on_hold"), - PAUSED("paused"), - EXPIRED("expired"); + UNDEFINED("undefined", 0, 0), + ACTIVE("active", R.string.osm_live_active, R.drawable.bg_osmand_live_active), + CANCELLED("cancelled", R.string.osmand_live_cancelled, R.drawable.bg_osmand_live_cancelled), + IN_GRACE_PERIOD("in_grace_period", R.string.in_grace_period, R.drawable.bg_osmand_live_active), + ON_HOLD("on_hold", R.string.on_hold, R.drawable.bg_osmand_live_cancelled), + PAUSED("paused", R.string.shared_string_paused, R.drawable.bg_osmand_live_cancelled), + EXPIRED("expired", R.string.expired, R.drawable.bg_osmand_live_cancelled); private final String stateStr; + @StringRes + private final int stringRes; + @DrawableRes + private final int backgroundRes; - SubscriptionState(@NonNull String stateStr) { + SubscriptionState(@NonNull String stateStr, @StringRes int stringRes, @DrawableRes int backgroundRes) { this.stateStr = stateStr; + this.stringRes = stringRes; + this.backgroundRes = backgroundRes; } public String getStateStr() { return stateStr; } + @StringRes + public int getStringRes() { + return stringRes; + } + + @DrawableRes + public int getBackgroundRes() { + return backgroundRes; + } + @NonNull public static SubscriptionState getByStateStr(@NonNull String stateStr) { for (SubscriptionState state : SubscriptionState.values()) { diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragment.java index 9fb4047ca5..6b5a9c5d5f 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragment.java @@ -38,11 +38,12 @@ import net.osmand.plus.activities.OsmandInAppPurchaseActivity; import net.osmand.plus.base.BaseOsmAndFragment; import net.osmand.plus.chooseplan.ChoosePlanDialogFragment; import net.osmand.plus.inapp.InAppPurchaseHelper; +import net.osmand.plus.inapp.InAppPurchaseHelper.InAppPurchaseListener; import net.osmand.plus.liveupdates.LiveUpdatesFragmentNew; import net.osmand.plus.liveupdates.OsmLiveActivity; import net.osmand.plus.wikipedia.WikipediaDialogFragment; -public class PurchasesFragment extends BaseOsmAndFragment { +public class PurchasesFragment extends BaseOsmAndFragment implements InAppPurchaseListener { public static final String TAG = PurchasesFragment.class.getName(); public static final String KEY_IS_SUBSCRIBER = "action_is_new"; @@ -50,6 +51,7 @@ public class PurchasesFragment extends BaseOsmAndFragment { private static final String PLAY_STORE_SUBSCRIPTION_DEEPLINK_URL = "https://play.google.com/store/account/subscriptions?sku=%s&package=%s"; private InAppPurchaseHelper purchaseHelper; private View mainView; + private SubscriptionsCard subscriptionsCard; private Context context; private OsmandApplication app; private String url; @@ -83,9 +85,14 @@ public class PurchasesFragment extends BaseOsmAndFragment { final boolean nightMode = !getMyApplication().getSettings().isLightContent(); LayoutInflater themedInflater = UiUtilities.getInflater(context, nightMode); - if (!isSubscriber) { + if (isSubscriber) { mainView = themedInflater.inflate(R.layout.purchases_layout, container, false); setSubscriptionClick(mapActivity); + if (mapActivity != null && purchaseHelper != null) { + ViewGroup subscriptionsCardContainer = mainView.findViewById(R.id.subscriptions_card_container); + subscriptionsCard = new SubscriptionsCard(mapActivity, purchaseHelper); + subscriptionsCardContainer.addView(subscriptionsCard.build(mapActivity)); + } } else { mainView = themedInflater.inflate(R.layout.empty_purchases_layout, container, false); LinearLayout osmandLive = mainView.findViewById(R.id.osmand_live); @@ -114,7 +121,7 @@ public class PurchasesFragment extends BaseOsmAndFragment { purchasesRestore.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - if (purchaseHelper != null && !purchaseHelper.hasInventory()) { + if (purchaseHelper != null) { purchaseHelper.requestInventory(); } } @@ -255,4 +262,30 @@ public class PurchasesFragment extends BaseOsmAndFragment { url = PLAY_STORE_SUBSCRIPTION_URL; } } + + @Override + public void onError(InAppPurchaseHelper.InAppPurchaseTaskType taskType, String error) { + } + + @Override + public void onGetItems() { + if (subscriptionsCard != null) { + subscriptionsCard.update(); + } + } + + @Override + public void onItemPurchased(String sku, boolean active) { + if (purchaseHelper != null) { + purchaseHelper.requestInventory(); + } + } + + @Override + public void showProgress(InAppPurchaseHelper.InAppPurchaseTaskType taskType) { + } + + @Override + public void dismissProgress(InAppPurchaseHelper.InAppPurchaseTaskType taskType) { + } } diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/SubscriptionsCard.java b/OsmAnd/src/net/osmand/plus/settings/fragments/SubscriptionsCard.java new file mode 100644 index 0000000000..40ef081602 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/SubscriptionsCard.java @@ -0,0 +1,179 @@ +package net.osmand.plus.settings.fragments; + +import android.os.Build; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; +import android.widget.Toast; + +import net.osmand.AndroidUtils; +import net.osmand.Period; +import net.osmand.plus.R; +import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.helpers.AndroidUiHelper; +import net.osmand.plus.inapp.InAppPurchaseHelper; +import net.osmand.plus.inapp.InAppPurchases.InAppSubscription; +import net.osmand.plus.inapp.InAppPurchases.InAppSubscription.SubscriptionState; +import net.osmand.plus.routepreparationmenu.cards.BaseCard; +import net.osmand.plus.settings.backend.OsmandSettings; +import net.osmand.util.Algorithms; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; + +import androidx.annotation.NonNull; +import androidx.appcompat.view.ContextThemeWrapper; +import androidx.core.content.ContextCompat; + +public class SubscriptionsCard extends BaseCard { + + private final InAppPurchaseHelper purchaseHelper; + + @Override + public int getCardLayoutId() { + return R.layout.subscriptions_card; + } + + public SubscriptionsCard(@NonNull MapActivity mapActivity, @NonNull InAppPurchaseHelper purchaseHelper) { + super(mapActivity); + this.purchaseHelper = purchaseHelper; + } + + @Override + protected void updateContent() { + if (mapActivity == null) { + return; + } + + List subscriptions = getActiveAndCancelledSubscriptions(); + if (Algorithms.isEmpty(subscriptions)) { + return; + } + + ContextThemeWrapper ctx = new ContextThemeWrapper(mapActivity, !nightMode ? R.style.OsmandLightTheme : R.style.OsmandDarkTheme); + LayoutInflater inflater = LayoutInflater.from(ctx); + ((ViewGroup) view).removeAllViews(); + + for (int i = 0; i < subscriptions.size(); i++) { + InAppSubscription subscription = subscriptions.get(i); + SubscriptionState state = subscription.getState(); + boolean autoRenewed = SubscriptionState.ACTIVE.equals(state) || SubscriptionState.IN_GRACE_PERIOD.equals(state); + + View card = inflater.inflate(R.layout.subscription_layout, null, false); + ((ViewGroup) view).addView(card); + + TextView subscriptionPeriod = card.findViewById(R.id.subscription_type); + String period = getSubscriptionPeriod(subscription.getSubscriptionPeriod()); + if (!Algorithms.isEmpty(period)) { + subscriptionPeriod.setText(period); + AndroidUiHelper.updateVisibility(subscriptionPeriod, true); + } + + if (autoRenewed) { + TextView nextBillingDate = card.findViewById(R.id.next_billing_date); + String date = getHumanDate(subscription.getPurchaseTime(), subscription.getSubscriptionPeriod()); + if (!Algorithms.isEmpty(date)) { + nextBillingDate.setText(app.getString(R.string.next_billing_date, date)); + AndroidUiHelper.updateVisibility(nextBillingDate, true); + } + } + + TextView status = card.findViewById(R.id.status); + status.setText(app.getString(state.getStringRes())); + status.setBackgroundDrawable(ContextCompat.getDrawable(mapActivity, state.getBackgroundRes())); + + if (!autoRenewed) { + View renewContainer = card.findViewById(R.id.renewContainer); + AndroidUiHelper.updateVisibility(renewContainer, true); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + AndroidUtils.setBackground(ctx, renewContainer, nightMode, R.drawable.ripple_light, R.drawable.ripple_dark); + } else { + AndroidUtils.setBackground(ctx, renewContainer, nightMode, R.drawable.btn_unstroked_light, R.drawable.btn_unstroked_dark); + } + final String sku = subscription.getSku(); + renewContainer.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + subscribe(sku); + } + }); + + View renew = card.findViewById(R.id.renew); + AndroidUtils.setBackground(ctx, renew, nightMode, + R.drawable.btn_solid_border_light, R.drawable.btn_solid_border_dark); + } + + int dividerLayout = i + 1 == subscriptions.size() ? R.layout.simple_divider_item : R.layout.divider_half_item; + View divider = inflater.inflate(dividerLayout, (ViewGroup) view, false); + ((ViewGroup) view).addView(divider); + } + } + + private String getHumanDate(long time, Period period) { + Date date = new Date(time); + int monthsCount; + if (period == null || period.getUnit() == null) { + return ""; + } else if (period.getUnit().equals(Period.PeriodUnit.YEAR)) { + monthsCount = 12; + } else { + monthsCount = period.getNumberOfUnits(); + } + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + calendar.add(Calendar.MONTH, monthsCount); + date = calendar.getTime(); + SimpleDateFormat format = new SimpleDateFormat("MMM d, yyyy", app.getLocaleHelper().getPreferredLocale()); + return format.format(date); + } + + private void subscribe(String sku) { + if (app == null) { + return; + } + if (!app.getSettings().isInternetConnectionAvailable(true)) { + Toast.makeText(app, R.string.internet_not_available, Toast.LENGTH_LONG).show(); + } else if (mapActivity != null && purchaseHelper != null) { + OsmandSettings settings = app.getSettings(); + purchaseHelper.purchaseLiveUpdates(mapActivity, sku, + settings.BILLING_USER_EMAIL.get(), + settings.BILLING_USER_NAME.get(), + settings.BILLING_USER_COUNTRY_DOWNLOAD_NAME.get(), + settings.BILLING_HIDE_USER_NAME.get()); + } + } + + private String getSubscriptionPeriod(Period period) { + if (period == null || period.getUnit() == null) { + return ""; + } else if (period.getUnit().equals(Period.PeriodUnit.YEAR)) { + return app.getString(R.string.annual_subscription); + } else if (period.getUnit().equals(Period.PeriodUnit.MONTH)) { + int unitsNumber = period.getNumberOfUnits(); + if (unitsNumber == 1) { + return app.getString(R.string.monthly_subscription); + } else if (unitsNumber == 3) { + return app.getString(R.string.three_months_subscription); + } + } + return ""; + } + + private List getActiveAndCancelledSubscriptions() { + List subscriptions = new ArrayList<>(); + for (InAppSubscription subscription : purchaseHelper.getLiveUpdates().getVisibleSubscriptions()) { + if (shouldShowSubscription(subscription)) { + subscriptions.add(subscription); + } + } + return subscriptions; + } + + private boolean shouldShowSubscription(InAppSubscription s) { + return s.getState() != null && !SubscriptionState.UNDEFINED.equals(s.getState()); + } +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/track/GpxEditDescriptionDialogFragment.java b/OsmAnd/src/net/osmand/plus/track/GpxEditDescriptionDialogFragment.java index b8ef1c24d2..52536316b8 100644 --- a/OsmAnd/src/net/osmand/plus/track/GpxEditDescriptionDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/track/GpxEditDescriptionDialogFragment.java @@ -110,9 +110,8 @@ public class GpxEditDescriptionDialogFragment extends BaseOsmAndDialogFragment { } private void setupSaveButton(View view) { - View btnSave = view.findViewById(R.id.btn_save); - - btnSave.setOnClickListener(new View.OnClickListener() { + View btnSaveContainer = view.findViewById(R.id.btn_save_container); + btnSaveContainer.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Editable editable = editableHtml.getText(); @@ -122,12 +121,16 @@ public class GpxEditDescriptionDialogFragment extends BaseOsmAndDialogFragment { } }); - Context ctx = btnSave.getContext(); + Context ctx = btnSaveContainer.getContext(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - AndroidUtils.setBackground(ctx, btnSave, isNightMode(true), R.drawable.ripple_light, R.drawable.ripple_dark); + AndroidUtils.setBackground(ctx, btnSaveContainer, isNightMode(true), R.drawable.ripple_light, R.drawable.ripple_dark); } else { - AndroidUtils.setBackground(ctx, btnSave, isNightMode(true), R.drawable.btn_unstroked_light, R.drawable.btn_unstroked_dark); + AndroidUtils.setBackground(ctx, btnSaveContainer, isNightMode(true), R.drawable.btn_unstroked_light, R.drawable.btn_unstroked_dark); } + + View btnSave = view.findViewById(R.id.btn_save); + int drawableRes = isNightMode(true) ? R.drawable.btn_solid_border_dark : R.drawable.btn_solid_border_light; + btnSave.setBackgroundDrawable(ContextCompat.getDrawable(ctx, drawableRes)); } private void showDismissDialog() { From 03f0f19caef2f496a4630f58b6b436c12c668583 Mon Sep 17 00:00:00 2001 From: cepprice Date: Wed, 24 Mar 2021 02:41:47 +0500 Subject: [PATCH 08/11] Add UI of support region setting --- OsmAnd/res/layout/purchases_layout.xml | 66 ++++++++++ .../plus/inapp/InAppPurchaseHelper.java | 12 ++ .../liveupdates/CountrySelectionFragment.java | 2 + .../plus/liveupdates/LiveUpdatesFragment.java | 26 +--- .../liveupdates/SubscriptionFragment.java | 2 +- .../settings/fragments/PurchasesFragment.java | 121 +++++++++++++++--- .../settings/fragments/SubscriptionsCard.java | 18 +-- 7 files changed, 192 insertions(+), 55 deletions(-) diff --git a/OsmAnd/res/layout/purchases_layout.xml b/OsmAnd/res/layout/purchases_layout.xml index 306f37f690..2140d2cc5c 100644 --- a/OsmAnd/res/layout/purchases_layout.xml +++ b/OsmAnd/res/layout/purchases_layout.xml @@ -1,6 +1,8 @@ + + + + + + + + + + + + + + + + + + getEverMadeSubscriptions() { + List subscriptions = new ArrayList<>(); + for (InAppSubscription subscription : getLiveUpdates().getVisibleSubscriptions()) { + SubscriptionState state = subscription.getState(); + if (state != null && !SubscriptionState.UNDEFINED.equals(state)) { + subscriptions.add(subscription); + } + } + return subscriptions; + } + public abstract void isInAppPurchaseSupported(@NonNull final Activity activity, @Nullable final InAppPurchaseInitCallback callback); public boolean hasInventory() { diff --git a/OsmAnd/src/net/osmand/plus/liveupdates/CountrySelectionFragment.java b/OsmAnd/src/net/osmand/plus/liveupdates/CountrySelectionFragment.java index f070559121..9c29e9762b 100644 --- a/OsmAnd/src/net/osmand/plus/liveupdates/CountrySelectionFragment.java +++ b/OsmAnd/src/net/osmand/plus/liveupdates/CountrySelectionFragment.java @@ -35,6 +35,8 @@ import java.util.List; public class CountrySelectionFragment extends BaseOsmAndDialogFragment { + public static final String TAG = CountrySelectionFragment.class.getSimpleName(); + private List countryItems = new ArrayList<>(); private OnFragmentInteractionListener mListener; diff --git a/OsmAnd/src/net/osmand/plus/liveupdates/LiveUpdatesFragment.java b/OsmAnd/src/net/osmand/plus/liveupdates/LiveUpdatesFragment.java index 02bdad0a43..631b1a7f07 100644 --- a/OsmAnd/src/net/osmand/plus/liveupdates/LiveUpdatesFragment.java +++ b/OsmAnd/src/net/osmand/plus/liveupdates/LiveUpdatesFragment.java @@ -49,6 +49,7 @@ import net.osmand.plus.inapp.InAppPurchaseHelper.InAppPurchaseListener; import net.osmand.plus.inapp.InAppPurchaseHelper.InAppPurchaseTaskType; import net.osmand.plus.inapp.InAppPurchases.InAppSubscription; import net.osmand.plus.resources.IncrementalChangesManager; +import net.osmand.plus.settings.fragments.PurchasesFragment; import net.osmand.util.Algorithms; import java.io.File; @@ -181,28 +182,9 @@ public class LiveUpdatesFragment extends BaseOsmAndFragment implements InAppPurc statusTextView.setText(getString(R.string.osm_live_active)); statusIcon.setImageDrawable(app.getUIUtilities().getThemedIcon(R.drawable.ic_action_done)); - regionNameHeaderTextView.setText(R.string.osm_live_support_region); - String countryName = app.getSettings().BILLING_USER_COUNTRY.get(); - InAppPurchaseHelper purchaseHelper = getInAppPurchaseHelper(); - if (purchaseHelper != null) { - InAppSubscription monthlyPurchased = purchaseHelper.getPurchasedMonthlyLiveUpdates(); - if (monthlyPurchased != null && monthlyPurchased.isDonationSupported()) { - if (Algorithms.isEmpty(countryName)) { - if (app.getSettings().BILLING_USER_COUNTRY_DOWNLOAD_NAME.get().equals(OsmandSettings.BILLING_USER_DONATION_NONE_PARAMETER)) { - regionNameHeaderTextView.setText(R.string.default_buttons_support); - countryName = getString(R.string.osmand_team); - } else { - countryName = getString(R.string.shared_string_world); - } - } - } else { - regionNameHeaderTextView.setText(R.string.default_buttons_support); - countryName = getString(R.string.osmand_team); - } - } else { - regionNameHeaderTextView.setText(R.string.default_buttons_support); - countryName = getString(R.string.osmand_team); - } + String countryName = PurchasesFragment.getSupportRegionName(app, getInAppPurchaseHelper()); + String header = PurchasesFragment.getSupportRegionHeader(app, countryName); + regionNameHeaderTextView.setText(header); regionNameTextView.setText(countryName); View subscriptionsButton = subscriptionHeader.findViewById(R.id.button_subscriptions); diff --git a/OsmAnd/src/net/osmand/plus/liveupdates/SubscriptionFragment.java b/OsmAnd/src/net/osmand/plus/liveupdates/SubscriptionFragment.java index a2afb3d933..b73bf20c6e 100644 --- a/OsmAnd/src/net/osmand/plus/liveupdates/SubscriptionFragment.java +++ b/OsmAnd/src/net/osmand/plus/liveupdates/SubscriptionFragment.java @@ -177,7 +177,7 @@ public class SubscriptionFragment extends BaseOsmAndDialogFragment implements In CountrySelectionFragment countryCountrySelectionFragment = countrySelectionFragment; countryCountrySelectionFragment - .show(getChildFragmentManager(), "CountriesSearchSelectionFragment"); + .show(getChildFragmentManager(), CountrySelectionFragment.TAG); } return false; } diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragment.java index 6b5a9c5d5f..af834f73b8 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragment.java @@ -21,11 +21,6 @@ import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.FragmentActivity; -import androidx.fragment.app.FragmentManager; - import com.google.android.material.appbar.AppBarLayout; import net.osmand.AndroidUtils; @@ -39,21 +34,37 @@ import net.osmand.plus.base.BaseOsmAndFragment; import net.osmand.plus.chooseplan.ChoosePlanDialogFragment; import net.osmand.plus.inapp.InAppPurchaseHelper; import net.osmand.plus.inapp.InAppPurchaseHelper.InAppPurchaseListener; +import net.osmand.plus.inapp.InAppPurchases.InAppSubscription; +import net.osmand.plus.liveupdates.CountrySelectionFragment; +import net.osmand.plus.liveupdates.CountrySelectionFragment.CountryItem; +import net.osmand.plus.liveupdates.CountrySelectionFragment.OnFragmentInteractionListener; import net.osmand.plus.liveupdates.LiveUpdatesFragmentNew; import net.osmand.plus.liveupdates.OsmLiveActivity; +import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.wikipedia.WikipediaDialogFragment; +import net.osmand.util.Algorithms; -public class PurchasesFragment extends BaseOsmAndFragment implements InAppPurchaseListener { +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.FragmentActivity; +import androidx.fragment.app.FragmentManager; + +public class PurchasesFragment extends BaseOsmAndFragment implements InAppPurchaseListener, OnFragmentInteractionListener { public static final String TAG = PurchasesFragment.class.getName(); public static final String KEY_IS_SUBSCRIBER = "action_is_new"; private static final String PLAY_STORE_SUBSCRIPTION_URL = "https://play.google.com/store/account/subscriptions"; private static final String PLAY_STORE_SUBSCRIPTION_DEEPLINK_URL = "https://play.google.com/store/account/subscriptions?sku=%s&package=%s"; + + private OsmandApplication app; + private Context context; private InAppPurchaseHelper purchaseHelper; + private View mainView; private SubscriptionsCard subscriptionsCard; - private Context context; - private OsmandApplication app; + + private CountrySelectionFragment countrySelectionFragment = new CountrySelectionFragment(); + private String url; private Boolean isSubscriber; @@ -79,20 +90,14 @@ public class PurchasesFragment extends BaseOsmAndFragment implements InAppPurcha public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { app = getMyApplication(); context = requireContext(); - purchaseHelper = getInAppPurchaseHelper(); isSubscriber = Version.isPaidVersion(app); - final MapActivity mapActivity = (MapActivity) getActivity(); - final boolean nightMode = !getMyApplication().getSettings().isLightContent(); + final MapActivity mapActivity = getMapActivity(); + final boolean nightMode = !app.getSettings().isLightContent(); LayoutInflater themedInflater = UiUtilities.getInflater(context, nightMode); if (isSubscriber) { mainView = themedInflater.inflate(R.layout.purchases_layout, container, false); setSubscriptionClick(mapActivity); - if (mapActivity != null && purchaseHelper != null) { - ViewGroup subscriptionsCardContainer = mainView.findViewById(R.id.subscriptions_card_container); - subscriptionsCard = new SubscriptionsCard(mapActivity, purchaseHelper); - subscriptionsCardContainer.addView(subscriptionsCard.build(mapActivity)); - } } else { mainView = themedInflater.inflate(R.layout.empty_purchases_layout, container, false); LinearLayout osmandLive = mainView.findViewById(R.id.osmand_live); @@ -138,6 +143,21 @@ public class PurchasesFragment extends BaseOsmAndFragment implements InAppPurcha return mainView; } + @Override + public void onResume() { + super.onResume(); + purchaseHelper = getInAppPurchaseHelper(); + if (isSubscriber) { + MapActivity mapActivity = getMapActivity(); + if (getMapActivity() != null && purchaseHelper != null) { + ViewGroup subscriptionsCardContainer = mainView.findViewById(R.id.subscriptions_card_container); + subscriptionsCard = new SubscriptionsCard(mapActivity, purchaseHelper); + subscriptionsCardContainer.addView(subscriptionsCard.build(mapActivity)); + } + setupSupportRegion(); + } + } + @Override public void onSaveInstanceState(@NonNull Bundle outState) { super.onSaveInstanceState(outState); @@ -189,6 +209,54 @@ public class PurchasesFragment extends BaseOsmAndFragment implements InAppPurcha } + private void setupSupportRegion() { + String region = getSupportRegionName(app, purchaseHelper); + String header = getSupportRegionHeader(app, region); + TextView supportRegionHeader = mainView.findViewById(R.id.support_region_header); + TextView supportRegion = mainView.findViewById(R.id.support_region); + supportRegionHeader.setText(header); + supportRegion.setText(region); + + View supportRegionContainer = mainView.findViewById(R.id.support_region_container); + supportRegionContainer.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + CountrySelectionFragment countryCountrySelectionFragment = countrySelectionFragment; + countryCountrySelectionFragment.show(getChildFragmentManager(), CountrySelectionFragment.TAG); + } + }); + + countrySelectionFragment.initCountries(app); + } + + public static String getSupportRegionName(OsmandApplication app, InAppPurchaseHelper purchaseHelper) { + OsmandSettings settings = app.getSettings(); + String countryName = settings.BILLING_USER_COUNTRY.get(); + if (purchaseHelper != null) { + InAppSubscription monthlyPurchased = purchaseHelper.getPurchasedMonthlyLiveUpdates(); + if (monthlyPurchased != null && monthlyPurchased.isDonationSupported()) { + if (Algorithms.isEmpty(countryName)) { + if (OsmandSettings.BILLING_USER_DONATION_NONE_PARAMETER.equals(settings.BILLING_USER_COUNTRY_DOWNLOAD_NAME.get())) { + countryName = app.getString(R.string.osmand_team); + } else { + countryName = app.getString(R.string.shared_string_world); + } + } + } else { + countryName = app.getString(R.string.osmand_team); + } + } else { + countryName = app.getString(R.string.osmand_team); + } + return countryName; + } + + public static String getSupportRegionHeader(OsmandApplication app, String supportRegion) { + return supportRegion.equals(app.getString(R.string.osmand_team)) ? + app.getString(R.string.default_buttons_support) : + app.getString(R.string.osm_live_support_region); + } + @Nullable public InAppPurchaseHelper getInAppPurchaseHelper() { Activity activity = getActivity(); @@ -263,6 +331,23 @@ public class PurchasesFragment extends BaseOsmAndFragment implements InAppPurcha } } + @Override + public void onSearchResult(CountryItem selectedCountryItem) { + String countryName = selectedCountryItem != null ? selectedCountryItem.getLocalName() : ""; + String countryDownloadName = selectedCountryItem != null ? + selectedCountryItem.getDownloadName() : OsmandSettings.BILLING_USER_DONATION_WORLD_PARAMETER; + + OsmandApplication app = getMyApplication(); + if (app != null) { + TextView supportRegionHeader = mainView.findViewById(R.id.support_region_header); + TextView supportRegion = mainView.findViewById(R.id.support_region); + supportRegionHeader.setText(getSupportRegionHeader(app, countryName)); + supportRegion.setText(countryName); + app.getSettings().BILLING_USER_COUNTRY.set(countryName); + app.getSettings().BILLING_USER_COUNTRY_DOWNLOAD_NAME.set(countryDownloadName); + } + } + @Override public void onError(InAppPurchaseHelper.InAppPurchaseTaskType taskType, String error) { } @@ -288,4 +373,8 @@ public class PurchasesFragment extends BaseOsmAndFragment implements InAppPurcha @Override public void dismissProgress(InAppPurchaseHelper.InAppPurchaseTaskType taskType) { } + + private MapActivity getMapActivity() { + return (MapActivity) getActivity(); + } } diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/SubscriptionsCard.java b/OsmAnd/src/net/osmand/plus/settings/fragments/SubscriptionsCard.java index 40ef081602..c8c0d5202b 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/SubscriptionsCard.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/SubscriptionsCard.java @@ -45,11 +45,11 @@ public class SubscriptionsCard extends BaseCard { @Override protected void updateContent() { - if (mapActivity == null) { + if (mapActivity == null || purchaseHelper == null) { return; } - List subscriptions = getActiveAndCancelledSubscriptions(); + List subscriptions = purchaseHelper.getEverMadeSubscriptions(); if (Algorithms.isEmpty(subscriptions)) { return; } @@ -162,18 +162,4 @@ public class SubscriptionsCard extends BaseCard { } return ""; } - - private List getActiveAndCancelledSubscriptions() { - List subscriptions = new ArrayList<>(); - for (InAppSubscription subscription : purchaseHelper.getLiveUpdates().getVisibleSubscriptions()) { - if (shouldShowSubscription(subscription)) { - subscriptions.add(subscription); - } - } - return subscriptions; - } - - private boolean shouldShowSubscription(InAppSubscription s) { - return s.getState() != null && !SubscriptionState.UNDEFINED.equals(s.getState()); - } } \ No newline at end of file From 67449365b482eba07447e26d1946f7a8357ed3b0 Mon Sep 17 00:00:00 2001 From: cepprice Date: Fri, 26 Mar 2021 11:01:37 +0500 Subject: [PATCH 09/11] Small fixes and corrections --- .../src/main/java/net/osmand/Period.java | 17 ++-- OsmAnd/res/layout/purchases_layout.xml | 2 +- OsmAnd/res/layout/subscription_layout.xml | 1 - .../osmand/plus/inapp/InAppPurchasesImpl.java | 11 ++- .../chooseplan/ChoosePlanDialogFragment.java | 38 ++++---- .../plus/inapp/InAppPurchaseHelper.java | 8 +- .../net/osmand/plus/inapp/InAppPurchases.java | 30 +++++-- .../settings/fragments/PurchasesFragment.java | 45 +++++----- .../settings/fragments/SubscriptionsCard.java | 90 +++++-------------- .../GpxEditDescriptionDialogFragment.java | 2 +- 10 files changed, 119 insertions(+), 125 deletions(-) diff --git a/OsmAnd-java/src/main/java/net/osmand/Period.java b/OsmAnd-java/src/main/java/net/osmand/Period.java index d6bd911257..b529fdb6db 100644 --- a/OsmAnd-java/src/main/java/net/osmand/Period.java +++ b/OsmAnd-java/src/main/java/net/osmand/Period.java @@ -1,20 +1,23 @@ package net.osmand; import java.text.ParseException; +import java.util.Calendar; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Period { public enum PeriodUnit { - YEAR("Y"), - MONTH("M"), - WEEK("W"), - DAY("D"); + YEAR("Y", Calendar.YEAR), + MONTH("M", Calendar.MONTH), + WEEK("W", Calendar.WEEK_OF_YEAR), + DAY("D", Calendar.DATE); private String unitStr; + private int calendarIdx; - PeriodUnit(String unitStr) { + PeriodUnit(String unitStr, int calendarIdx) { + this.calendarIdx = calendarIdx; this.unitStr = unitStr; } @@ -22,6 +25,10 @@ public class Period { return unitStr; } + public int getCalendarIdx() { + return calendarIdx; + } + public double getMonthsValue() { switch (this) { case YEAR: diff --git a/OsmAnd/res/layout/purchases_layout.xml b/OsmAnd/res/layout/purchases_layout.xml index 2140d2cc5c..d4bb5a3465 100644 --- a/OsmAnd/res/layout/purchases_layout.xml +++ b/OsmAnd/res/layout/purchases_layout.xml @@ -4,7 +4,7 @@ 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_height="match_parent" android:background="?attr/bg_color" android:orientation="vertical"> diff --git a/OsmAnd/res/layout/subscription_layout.xml b/OsmAnd/res/layout/subscription_layout.xml index de35b80f4a..411e49db31 100644 --- a/OsmAnd/res/layout/subscription_layout.xml +++ b/OsmAnd/res/layout/subscription_layout.xml @@ -7,7 +7,6 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" - android:background="@android:drawable/list_selector_background" android:paddingStart="@dimen/content_padding" android:paddingLeft="@dimen/content_padding" android:paddingRight="@dimen/content_padding" diff --git a/OsmAnd/src-google/net/osmand/plus/inapp/InAppPurchasesImpl.java b/OsmAnd/src-google/net/osmand/plus/inapp/InAppPurchasesImpl.java index a2a0f8d680..9c7ee92758 100644 --- a/OsmAnd/src-google/net/osmand/plus/inapp/InAppPurchasesImpl.java +++ b/OsmAnd/src-google/net/osmand/plus/inapp/InAppPurchasesImpl.java @@ -2,15 +2,15 @@ package net.osmand.plus.inapp; import android.content.Context; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - import com.android.billingclient.api.SkuDetails; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.Version; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + public class InAppPurchasesImpl extends InAppPurchases { private static final InAppPurchase FULL_VERSION = new InAppPurchaseFullVersion(); @@ -285,6 +285,11 @@ public class InAppPurchasesImpl extends InAppPurchases { this.details = details; } + @Override + public int getPeriodTypeString() { + return R.string.monthly_subscription; + } + @Override public String getDefaultPrice(Context ctx) { return ""; diff --git a/OsmAnd/src/net/osmand/plus/chooseplan/ChoosePlanDialogFragment.java b/OsmAnd/src/net/osmand/plus/chooseplan/ChoosePlanDialogFragment.java index 8488daf0f5..814fe15871 100644 --- a/OsmAnd/src/net/osmand/plus/chooseplan/ChoosePlanDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/chooseplan/ChoosePlanDialogFragment.java @@ -22,17 +22,6 @@ import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; -import androidx.annotation.ColorRes; -import androidx.annotation.DrawableRes; -import androidx.annotation.LayoutRes; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.appcompat.widget.AppCompatImageView; -import androidx.core.content.ContextCompat; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentActivity; -import androidx.fragment.app.FragmentManager; - import net.osmand.AndroidUtils; import net.osmand.PlatformUtil; import net.osmand.plus.OsmandApplication; @@ -59,6 +48,17 @@ import org.apache.commons.logging.Log; import java.util.List; +import androidx.annotation.ColorRes; +import androidx.annotation.DrawableRes; +import androidx.annotation.LayoutRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.widget.AppCompatImageView; +import androidx.core.content.ContextCompat; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentActivity; +import androidx.fragment.app.FragmentManager; + public abstract class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment implements InAppPurchaseListener { public static final String TAG = ChoosePlanDialogFragment.class.getSimpleName(); private static final Log LOG = PlatformUtil.getLog(ChoosePlanDialogFragment.class); @@ -489,14 +489,18 @@ public abstract class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment buttonView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { - subscribe(s.getSku()); + if (getActivity() != null) { + subscribe(app, getActivity(), purchaseHelper, s.getSku()); + } } }); } else { buttonExView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { - subscribe(s.getSku()); + if (getActivity() != null) { + subscribe(app, getActivity(), purchaseHelper, s.getSku()); + } } }); } @@ -526,14 +530,14 @@ public abstract class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment } } - private void subscribe(String sku) { + public static void subscribe(@NonNull OsmandApplication app, Activity activity, + InAppPurchaseHelper purchaseHelper, String sku) { if (!app.getSettings().isInternetConnectionAvailable(true)) { Toast.makeText(app, R.string.internet_not_available, Toast.LENGTH_LONG).show(); } else { - FragmentActivity ctx = getActivity(); - if (ctx != null && purchaseHelper != null) { + if (activity != null && purchaseHelper != null) { OsmandSettings settings = app.getSettings(); - purchaseHelper.purchaseLiveUpdates(ctx, sku, + purchaseHelper.purchaseLiveUpdates(activity, sku, settings.BILLING_USER_EMAIL.get(), settings.BILLING_USER_NAME.get(), settings.BILLING_USER_COUNTRY_DOWNLOAD_NAME.get(), diff --git a/OsmAnd/src/net/osmand/plus/inapp/InAppPurchaseHelper.java b/OsmAnd/src/net/osmand/plus/inapp/InAppPurchaseHelper.java index dfa3f55c84..5136cd1f73 100644 --- a/OsmAnd/src/net/osmand/plus/inapp/InAppPurchaseHelper.java +++ b/OsmAnd/src/net/osmand/plus/inapp/InAppPurchaseHelper.java @@ -8,9 +8,6 @@ import android.os.AsyncTask; import android.text.TextUtils; import android.util.Log; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - import net.osmand.AndroidNetworkUtils; import net.osmand.AndroidNetworkUtils.OnRequestResultListener; import net.osmand.AndroidNetworkUtils.OnRequestsResultListener; @@ -43,6 +40,9 @@ import java.util.List; import java.util.Map; import java.util.Set; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + public abstract class InAppPurchaseHelper { // Debug tag, for logging protected static final org.apache.commons.logging.Log LOG = PlatformUtil.getLog(InAppPurchaseHelper.class); @@ -203,7 +203,7 @@ public abstract class InAppPurchaseHelper { List subscriptions = new ArrayList<>(); for (InAppSubscription subscription : getLiveUpdates().getVisibleSubscriptions()) { SubscriptionState state = subscription.getState(); - if (state != null && !SubscriptionState.UNDEFINED.equals(state)) { + if (state != SubscriptionState.UNDEFINED) { subscriptions.add(subscription); } } diff --git a/OsmAnd/src/net/osmand/plus/inapp/InAppPurchases.java b/OsmAnd/src/net/osmand/plus/inapp/InAppPurchases.java index 8a6d5a0128..27d359630e 100644 --- a/OsmAnd/src/net/osmand/plus/inapp/InAppPurchases.java +++ b/OsmAnd/src/net/osmand/plus/inapp/InAppPurchases.java @@ -7,12 +7,6 @@ import android.text.Spannable; import android.text.SpannableStringBuilder; import android.text.style.ForegroundColorSpan; -import androidx.annotation.ColorInt; -import androidx.annotation.DrawableRes; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.StringRes; - import net.osmand.AndroidUtils; import net.osmand.Period; import net.osmand.Period.PeriodUnit; @@ -34,6 +28,12 @@ import java.util.Locale; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import androidx.annotation.ColorInt; +import androidx.annotation.DrawableRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.StringRes; + public abstract class InAppPurchases { protected InAppPurchase fullVersion; @@ -645,6 +645,9 @@ public abstract class InAppPurchases { this.skuNoVersion = sku; } + @StringRes + public abstract int getPeriodTypeString(); + @NonNull private List getUpgrades() { return new ArrayList<>(upgrades.values()); @@ -835,6 +838,11 @@ public abstract class InAppPurchases { this(sku, false); } + @Override + public int getPeriodTypeString() { + return R.string.monthly_subscription; + } + @Override public void setPriceValue(double priceValue) { super.setPriceValue(priceValue); @@ -883,6 +891,11 @@ public abstract class InAppPurchases { super(sku, false); } + @Override + public int getPeriodTypeString() { + return R.string.three_months_subscription; + } + @Override public void setPriceValue(double priceValue) { super.setPriceValue(priceValue); @@ -926,6 +939,11 @@ public abstract class InAppPurchases { super(sku, false); } + @Override + public int getPeriodTypeString() { + return R.string.annual_subscription; + } + @Override public void setPriceValue(double priceValue) { super.setPriceValue(priceValue); diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragment.java index af834f73b8..00a15b3071 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragment.java @@ -24,6 +24,7 @@ import android.widget.TextView; import com.google.android.material.appbar.AppBarLayout; import net.osmand.AndroidUtils; +import net.osmand.PlatformUtil; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.UiUtilities; @@ -44,6 +45,8 @@ import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.wikipedia.WikipediaDialogFragment; import net.osmand.util.Algorithms; +import org.apache.commons.logging.Log; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.FragmentActivity; @@ -51,10 +54,17 @@ import androidx.fragment.app.FragmentManager; public class PurchasesFragment extends BaseOsmAndFragment implements InAppPurchaseListener, OnFragmentInteractionListener { + private static final Log log = PlatformUtil.getLog(PurchasesFragment.class); public static final String TAG = PurchasesFragment.class.getName(); + public static final String KEY_IS_SUBSCRIBER = "action_is_new"; + private static final String PLAY_STORE_SUBSCRIPTION_URL = "https://play.google.com/store/account/subscriptions"; private static final String PLAY_STORE_SUBSCRIPTION_DEEPLINK_URL = "https://play.google.com/store/account/subscriptions?sku=%s&package=%s"; + private static final String EMAIL_DEEPLINK_URI = "mailto:support@osmand.net"; + private static final String OSMAND_EMAIL = "support@osmand.net"; + private static final String OSMAND_NEW_DEVICE_URL = "https://docs.osmand.net/en/main@latest/osmand/purchases#new-device--new-account"; + private static final String OSMAND_PURCHASES_URL = "https://docs.osmand.net/en/main@latest/osmand/purchases"; private OsmandApplication app; private Context context; @@ -66,17 +76,18 @@ public class PurchasesFragment extends BaseOsmAndFragment implements InAppPurcha private CountrySelectionFragment countrySelectionFragment = new CountrySelectionFragment(); private String url; - private Boolean isSubscriber; + private Boolean isPaidVersion; public static boolean showInstance(FragmentManager fragmentManager) { try { PurchasesFragment fragment = new PurchasesFragment(); fragmentManager.beginTransaction() - .add(R.id.fragmentContainer, fragment, TAG) + .replace(R.id.fragmentContainer, fragment, TAG) .addToBackStack(TAG) .commitAllowingStateLoss(); return true; } catch (Exception e) { + log.error(e); return false; } } @@ -90,12 +101,12 @@ public class PurchasesFragment extends BaseOsmAndFragment implements InAppPurcha public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { app = getMyApplication(); context = requireContext(); - isSubscriber = Version.isPaidVersion(app); + isPaidVersion = Version.isPaidVersion(app); final MapActivity mapActivity = getMapActivity(); final boolean nightMode = !app.getSettings().isLightContent(); LayoutInflater themedInflater = UiUtilities.getInflater(context, nightMode); - if (isSubscriber) { + if (isPaidVersion) { mainView = themedInflater.inflate(R.layout.purchases_layout, container, false); setSubscriptionClick(mapActivity); } else { @@ -117,11 +128,6 @@ public class PurchasesFragment extends BaseOsmAndFragment implements InAppPurcha } AndroidUtils.addStatusBarPadding21v(getActivity(), mainView); createToolbar(mainView, nightMode); - mainView.setOnTouchListener(new View.OnTouchListener() { - public boolean onTouch(View v, MotionEvent event) { - return true; - } - }); LinearLayout purchasesRestore = mainView.findViewById(R.id.restore_purchases); purchasesRestore.setOnClickListener(new View.OnClickListener() { @Override @@ -135,7 +141,7 @@ public class PurchasesFragment extends BaseOsmAndFragment implements InAppPurcha newDeviceAccountContainer.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - WikipediaDialogFragment.showFullArticle(context, Uri.parse("https://docs.osmand.net/en/main@latest/osmand/purchases#new-device--new-account"), nightMode); + WikipediaDialogFragment.showFullArticle(context, Uri.parse(OSMAND_NEW_DEVICE_URL), nightMode); } }); @@ -147,10 +153,11 @@ public class PurchasesFragment extends BaseOsmAndFragment implements InAppPurcha public void onResume() { super.onResume(); purchaseHelper = getInAppPurchaseHelper(); - if (isSubscriber) { + if (isPaidVersion) { MapActivity mapActivity = getMapActivity(); if (getMapActivity() != null && purchaseHelper != null) { ViewGroup subscriptionsCardContainer = mainView.findViewById(R.id.subscriptions_card_container); + subscriptionsCardContainer.removeAllViews(); subscriptionsCard = new SubscriptionsCard(mapActivity, purchaseHelper); subscriptionsCardContainer.addView(subscriptionsCard.build(mapActivity)); } @@ -161,7 +168,7 @@ public class PurchasesFragment extends BaseOsmAndFragment implements InAppPurcha @Override public void onSaveInstanceState(@NonNull Bundle outState) { super.onSaveInstanceState(outState); - outState.putBoolean(KEY_IS_SUBSCRIBER, isSubscriber); + outState.putBoolean(KEY_IS_SUBSCRIBER, isPaidVersion); } @Override @@ -277,7 +284,7 @@ public class PurchasesFragment extends BaseOsmAndFragment implements InAppPurcha icon.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - WikipediaDialogFragment.showFullArticle(context, Uri.parse("https://docs.osmand.net/en/main@latest/osmand/purchases"), nightMode); + WikipediaDialogFragment.showFullArticle(context, Uri.parse(OSMAND_PURCHASES_URL), nightMode); } }); ImageButton backButton = toolbar.findViewById(R.id.close_button); @@ -301,14 +308,12 @@ public class PurchasesFragment extends BaseOsmAndFragment implements InAppPurcha TextView supportDescription = mainView.findViewById(R.id.support_link_title); SpannableString spannableStringSupport = new SpannableString(getString(R.string.contact_support)); - String urlSupport = "mailto:support@osmand.net"; - spannableStringSupport.setSpan(new URLSpan(urlSupport), 0, spannableStringSupport.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + spannableStringSupport.setSpan(new URLSpan(EMAIL_DEEPLINK_URI), 0, spannableStringSupport.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - String emailString = "support@osmand.net"; - String supportDescriptionString = getString(R.string.contact_support_description, emailString); + String supportDescriptionString = getString(R.string.contact_support_description, OSMAND_EMAIL); SpannableString spannableStringMail = new SpannableString(supportDescriptionString); - int startIndex = supportDescriptionString.indexOf(emailString); - int endIndex = startIndex + emailString.length(); + int startIndex = supportDescriptionString.indexOf(OSMAND_EMAIL); + int endIndex = startIndex + OSMAND_EMAIL.length(); StyleSpan boldSpan = new StyleSpan(Typeface.BOLD); spannableStringMail.setSpan(boldSpan, startIndex, endIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); @@ -322,7 +327,7 @@ public class PurchasesFragment extends BaseOsmAndFragment implements InAppPurcha private void getSkuAppId() { InAppPurchaseHelper purchaseHelper = app.getInAppPurchaseHelper(); - if (purchaseHelper != null) { + if (purchaseHelper != null && purchaseHelper.getFullVersion() != null) { String sku = purchaseHelper.getFullVersion().getSku(); url = String.format(PLAY_STORE_SUBSCRIPTION_DEEPLINK_URL, sku, context.getPackageName()); diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/SubscriptionsCard.java b/OsmAnd/src/net/osmand/plus/settings/fragments/SubscriptionsCard.java index c8c0d5202b..1cc422b3ff 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/SubscriptionsCard.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/SubscriptionsCard.java @@ -5,34 +5,34 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; -import android.widget.Toast; import net.osmand.AndroidUtils; import net.osmand.Period; import net.osmand.plus.R; +import net.osmand.plus.UiUtilities; import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.chooseplan.ChoosePlanDialogFragment; import net.osmand.plus.helpers.AndroidUiHelper; import net.osmand.plus.inapp.InAppPurchaseHelper; import net.osmand.plus.inapp.InAppPurchases.InAppSubscription; import net.osmand.plus.inapp.InAppPurchases.InAppSubscription.SubscriptionState; import net.osmand.plus.routepreparationmenu.cards.BaseCard; -import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.util.Algorithms; import java.text.SimpleDateFormat; -import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; +import java.util.Locale; import androidx.annotation.NonNull; -import androidx.appcompat.view.ContextThemeWrapper; -import androidx.core.content.ContextCompat; public class SubscriptionsCard extends BaseCard { private final InAppPurchaseHelper purchaseHelper; + private final SimpleDateFormat dateFormat; + @Override public int getCardLayoutId() { return R.layout.subscriptions_card; @@ -41,33 +41,29 @@ public class SubscriptionsCard extends BaseCard { public SubscriptionsCard(@NonNull MapActivity mapActivity, @NonNull InAppPurchaseHelper purchaseHelper) { super(mapActivity); this.purchaseHelper = purchaseHelper; + this.dateFormat = new SimpleDateFormat("MMM d, yyyy", Locale.getDefault()); } @Override protected void updateContent() { - if (mapActivity == null || purchaseHelper == null) { + if (purchaseHelper == null || Algorithms.isEmpty(purchaseHelper.getEverMadeSubscriptions())) { return; } - List subscriptions = purchaseHelper.getEverMadeSubscriptions(); - if (Algorithms.isEmpty(subscriptions)) { - return; - } - - ContextThemeWrapper ctx = new ContextThemeWrapper(mapActivity, !nightMode ? R.style.OsmandLightTheme : R.style.OsmandDarkTheme); - LayoutInflater inflater = LayoutInflater.from(ctx); + LayoutInflater inflater = UiUtilities.getInflater(mapActivity, nightMode); ((ViewGroup) view).removeAllViews(); + List subscriptions = purchaseHelper.getEverMadeSubscriptions(); for (int i = 0; i < subscriptions.size(); i++) { InAppSubscription subscription = subscriptions.get(i); SubscriptionState state = subscription.getState(); - boolean autoRenewed = SubscriptionState.ACTIVE.equals(state) || SubscriptionState.IN_GRACE_PERIOD.equals(state); + boolean autoRenewed = state == SubscriptionState.ACTIVE || state == SubscriptionState.IN_GRACE_PERIOD; View card = inflater.inflate(R.layout.subscription_layout, null, false); ((ViewGroup) view).addView(card); TextView subscriptionPeriod = card.findViewById(R.id.subscription_type); - String period = getSubscriptionPeriod(subscription.getSubscriptionPeriod()); + String period = app.getString(subscription.getPeriodTypeString()); if (!Algorithms.isEmpty(period)) { subscriptionPeriod.setText(period); AndroidUiHelper.updateVisibility(subscriptionPeriod, true); @@ -80,33 +76,31 @@ public class SubscriptionsCard extends BaseCard { nextBillingDate.setText(app.getString(R.string.next_billing_date, date)); AndroidUiHelper.updateVisibility(nextBillingDate, true); } - } - - TextView status = card.findViewById(R.id.status); - status.setText(app.getString(state.getStringRes())); - status.setBackgroundDrawable(ContextCompat.getDrawable(mapActivity, state.getBackgroundRes())); - - if (!autoRenewed) { + } else { View renewContainer = card.findViewById(R.id.renewContainer); AndroidUiHelper.updateVisibility(renewContainer, true); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - AndroidUtils.setBackground(ctx, renewContainer, nightMode, R.drawable.ripple_light, R.drawable.ripple_dark); + AndroidUtils.setBackground(mapActivity, renewContainer, nightMode, R.drawable.ripple_light, R.drawable.ripple_dark); } else { - AndroidUtils.setBackground(ctx, renewContainer, nightMode, R.drawable.btn_unstroked_light, R.drawable.btn_unstroked_dark); + AndroidUtils.setBackground(mapActivity, renewContainer, nightMode, R.drawable.btn_unstroked_light, R.drawable.btn_unstroked_dark); } final String sku = subscription.getSku(); renewContainer.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - subscribe(sku); + ChoosePlanDialogFragment.subscribe(app, mapActivity, purchaseHelper, sku); } }); View renew = card.findViewById(R.id.renew); - AndroidUtils.setBackground(ctx, renew, nightMode, + AndroidUtils.setBackground(mapActivity, renew, nightMode, R.drawable.btn_solid_border_light, R.drawable.btn_solid_border_dark); } + TextView status = card.findViewById(R.id.status); + status.setText(app.getString(state.getStringRes())); + AndroidUtils.setBackground(status, app.getUIUtilities().getIcon(state.getBackgroundRes())); + int dividerLayout = i + 1 == subscriptions.size() ? R.layout.simple_divider_item : R.layout.divider_half_item; View divider = inflater.inflate(dividerLayout, (ViewGroup) view, false); ((ViewGroup) view).addView(divider); @@ -114,52 +108,14 @@ public class SubscriptionsCard extends BaseCard { } private String getHumanDate(long time, Period period) { - Date date = new Date(time); - int monthsCount; if (period == null || period.getUnit() == null) { return ""; - } else if (period.getUnit().equals(Period.PeriodUnit.YEAR)) { - monthsCount = 12; - } else { - monthsCount = period.getNumberOfUnits(); } + Date date = new Date(time); Calendar calendar = Calendar.getInstance(); calendar.setTime(date); - calendar.add(Calendar.MONTH, monthsCount); + calendar.add(period.getUnit().getCalendarIdx(), period.getNumberOfUnits()); date = calendar.getTime(); - SimpleDateFormat format = new SimpleDateFormat("MMM d, yyyy", app.getLocaleHelper().getPreferredLocale()); - return format.format(date); - } - - private void subscribe(String sku) { - if (app == null) { - return; - } - if (!app.getSettings().isInternetConnectionAvailable(true)) { - Toast.makeText(app, R.string.internet_not_available, Toast.LENGTH_LONG).show(); - } else if (mapActivity != null && purchaseHelper != null) { - OsmandSettings settings = app.getSettings(); - purchaseHelper.purchaseLiveUpdates(mapActivity, sku, - settings.BILLING_USER_EMAIL.get(), - settings.BILLING_USER_NAME.get(), - settings.BILLING_USER_COUNTRY_DOWNLOAD_NAME.get(), - settings.BILLING_HIDE_USER_NAME.get()); - } - } - - private String getSubscriptionPeriod(Period period) { - if (period == null || period.getUnit() == null) { - return ""; - } else if (period.getUnit().equals(Period.PeriodUnit.YEAR)) { - return app.getString(R.string.annual_subscription); - } else if (period.getUnit().equals(Period.PeriodUnit.MONTH)) { - int unitsNumber = period.getNumberOfUnits(); - if (unitsNumber == 1) { - return app.getString(R.string.monthly_subscription); - } else if (unitsNumber == 3) { - return app.getString(R.string.three_months_subscription); - } - } - return ""; + return dateFormat.format(date); } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/track/GpxEditDescriptionDialogFragment.java b/OsmAnd/src/net/osmand/plus/track/GpxEditDescriptionDialogFragment.java index 52536316b8..0d8e91e26c 100644 --- a/OsmAnd/src/net/osmand/plus/track/GpxEditDescriptionDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/track/GpxEditDescriptionDialogFragment.java @@ -130,7 +130,7 @@ public class GpxEditDescriptionDialogFragment extends BaseOsmAndDialogFragment { View btnSave = view.findViewById(R.id.btn_save); int drawableRes = isNightMode(true) ? R.drawable.btn_solid_border_dark : R.drawable.btn_solid_border_light; - btnSave.setBackgroundDrawable(ContextCompat.getDrawable(ctx, drawableRes)); + AndroidUtils.setBackground(btnSave, getMyApplication().getUIUtilities().getIcon(drawableRes)); } private void showDismissDialog() { From d22edfd9ae044bb65e585c5c1749ee37c4f86745 Mon Sep 17 00:00:00 2001 From: cepprice Date: Fri, 26 Mar 2021 20:28:30 +0500 Subject: [PATCH 10/11] Split layout to cards --- OsmAnd/res/layout/contact_support.xml | 73 ++++ OsmAnd/res/layout/empty_purchases_layout.xml | 220 ---------- .../layout/new_device_or_account_button.xml | 34 ++ OsmAnd/res/layout/no_purchases_card.xml | 92 ++++ OsmAnd/res/layout/purchases_layout.xml | 407 +----------------- .../res/layout/restore_purchases_button.xml | 34 ++ OsmAnd/res/layout/subscriptions_card.xml | 204 ++++++++- OsmAnd/res/layout/subscriptions_list_card.xml | 6 + OsmAnd/res/layout/troubleshooting_card.xml | 96 +++++ .../plus/liveupdates/LiveUpdatesFragment.java | 64 ++- .../settings/fragments/PurchasesFragment.java | 245 ++--------- .../settings/fragments/SubscriptionsCard.java | 173 ++++---- .../fragments/SubscriptionsListCard.java | 124 ++++++ .../TroubleshootingOrPurchasingCard.java | 126 ++++++ 14 files changed, 975 insertions(+), 923 deletions(-) create mode 100644 OsmAnd/res/layout/contact_support.xml delete mode 100644 OsmAnd/res/layout/empty_purchases_layout.xml create mode 100644 OsmAnd/res/layout/new_device_or_account_button.xml create mode 100644 OsmAnd/res/layout/no_purchases_card.xml create mode 100644 OsmAnd/res/layout/restore_purchases_button.xml create mode 100644 OsmAnd/res/layout/subscriptions_list_card.xml create mode 100644 OsmAnd/res/layout/troubleshooting_card.xml create mode 100644 OsmAnd/src/net/osmand/plus/settings/fragments/SubscriptionsListCard.java create mode 100644 OsmAnd/src/net/osmand/plus/settings/fragments/TroubleshootingOrPurchasingCard.java diff --git a/OsmAnd/res/layout/contact_support.xml b/OsmAnd/res/layout/contact_support.xml new file mode 100644 index 0000000000..30e45c4ea4 --- /dev/null +++ b/OsmAnd/res/layout/contact_support.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/empty_purchases_layout.xml b/OsmAnd/res/layout/empty_purchases_layout.xml deleted file mode 100644 index 56bfb82b6f..0000000000 --- a/OsmAnd/res/layout/empty_purchases_layout.xml +++ /dev/null @@ -1,220 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/OsmAnd/res/layout/new_device_or_account_button.xml b/OsmAnd/res/layout/new_device_or_account_button.xml new file mode 100644 index 0000000000..d6afc440ef --- /dev/null +++ b/OsmAnd/res/layout/new_device_or_account_button.xml @@ -0,0 +1,34 @@ + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/no_purchases_card.xml b/OsmAnd/res/layout/no_purchases_card.xml new file mode 100644 index 0000000000..7bb787d4ab --- /dev/null +++ b/OsmAnd/res/layout/no_purchases_card.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/purchases_layout.xml b/OsmAnd/res/layout/purchases_layout.xml index d4bb5a3465..c4f361eca5 100644 --- a/OsmAnd/res/layout/purchases_layout.xml +++ b/OsmAnd/res/layout/purchases_layout.xml @@ -1,12 +1,10 @@ + android:background="?attr/activity_background_color" + android:orientation="vertical" + android:focusableInTouchMode="false"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:orientation="vertical"/> diff --git a/OsmAnd/res/layout/restore_purchases_button.xml b/OsmAnd/res/layout/restore_purchases_button.xml new file mode 100644 index 0000000000..a4a34bcd6c --- /dev/null +++ b/OsmAnd/res/layout/restore_purchases_button.xml @@ -0,0 +1,34 @@ + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/subscriptions_card.xml b/OsmAnd/res/layout/subscriptions_card.xml index 278f381933..b4deb45ffc 100644 --- a/OsmAnd/res/layout/subscriptions_card.xml +++ b/OsmAnd/res/layout/subscriptions_card.xml @@ -1,5 +1,207 @@ \ No newline at end of file + android:background="?attr/bg_color" + android:orientation="vertical"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/subscriptions_list_card.xml b/OsmAnd/res/layout/subscriptions_list_card.xml new file mode 100644 index 0000000000..54c8480c4e --- /dev/null +++ b/OsmAnd/res/layout/subscriptions_list_card.xml @@ -0,0 +1,6 @@ + + \ No newline at end of file diff --git a/OsmAnd/res/layout/troubleshooting_card.xml b/OsmAnd/res/layout/troubleshooting_card.xml new file mode 100644 index 0000000000..96e6b3627d --- /dev/null +++ b/OsmAnd/res/layout/troubleshooting_card.xml @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/liveupdates/LiveUpdatesFragment.java b/OsmAnd/src/net/osmand/plus/liveupdates/LiveUpdatesFragment.java index 631b1a7f07..f6c3bd4b66 100644 --- a/OsmAnd/src/net/osmand/plus/liveupdates/LiveUpdatesFragment.java +++ b/OsmAnd/src/net/osmand/plus/liveupdates/LiveUpdatesFragment.java @@ -22,19 +22,7 @@ import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.TextView; -import androidx.annotation.DrawableRes; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.appcompat.widget.SwitchCompat; -import androidx.core.content.ContextCompat; -import androidx.fragment.app.FragmentActivity; -import androidx.fragment.app.FragmentManager; -import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; - import net.osmand.plus.OsmandApplication; -import net.osmand.plus.chooseplan.ChoosePlanDialogFragment.ChoosePlanDialogType; -import net.osmand.plus.settings.backend.CommonPreference; -import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.R; import net.osmand.plus.Version; import net.osmand.plus.activities.LocalIndexHelper; @@ -43,13 +31,15 @@ import net.osmand.plus.activities.OsmandBaseExpandableListAdapter; import net.osmand.plus.activities.OsmandInAppPurchaseActivity; import net.osmand.plus.base.BaseOsmAndFragment; import net.osmand.plus.chooseplan.ChoosePlanDialogFragment; +import net.osmand.plus.chooseplan.ChoosePlanDialogFragment.ChoosePlanDialogType; import net.osmand.plus.download.ui.AbstractLoadLocalIndexTask; import net.osmand.plus.inapp.InAppPurchaseHelper; import net.osmand.plus.inapp.InAppPurchaseHelper.InAppPurchaseListener; import net.osmand.plus.inapp.InAppPurchaseHelper.InAppPurchaseTaskType; import net.osmand.plus.inapp.InAppPurchases.InAppSubscription; import net.osmand.plus.resources.IncrementalChangesManager; -import net.osmand.plus.settings.fragments.PurchasesFragment; +import net.osmand.plus.settings.backend.CommonPreference; +import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.util.Algorithms; import java.io.File; @@ -60,6 +50,15 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +import androidx.annotation.DrawableRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.widget.SwitchCompat; +import androidx.core.content.ContextCompat; +import androidx.fragment.app.FragmentActivity; +import androidx.fragment.app.FragmentManager; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; + import static net.osmand.plus.liveupdates.LiveUpdatesFragmentNew.showUpdateDialog; import static net.osmand.plus.liveupdates.LiveUpdatesHelper.DEFAULT_LAST_CHECK; import static net.osmand.plus.liveupdates.LiveUpdatesHelper.TimeOfDay; @@ -182,8 +181,8 @@ public class LiveUpdatesFragment extends BaseOsmAndFragment implements InAppPurc statusTextView.setText(getString(R.string.osm_live_active)); statusIcon.setImageDrawable(app.getUIUtilities().getThemedIcon(R.drawable.ic_action_done)); - String countryName = PurchasesFragment.getSupportRegionName(app, getInAppPurchaseHelper()); - String header = PurchasesFragment.getSupportRegionHeader(app, countryName); + String countryName = getSupportRegionName(app, getInAppPurchaseHelper()); + String header = getSupportRegionHeader(app, countryName); regionNameHeaderTextView.setText(header); regionNameTextView.setText(countryName); @@ -279,6 +278,41 @@ public class LiveUpdatesFragment extends BaseOsmAndFragment implements InAppPurc subscriptionFragment.show(getChildFragmentManager(), SubscriptionFragment.TAG); } + public static String getSupportRegionName(OsmandApplication app, InAppPurchaseHelper purchaseHelper) { + OsmandSettings settings = app.getSettings(); + String countryName = settings.BILLING_USER_COUNTRY.get(); + if (purchaseHelper != null) { + List subscriptions = purchaseHelper.getLiveUpdates().getVisibleSubscriptions(); + boolean donationSupported = false; + for (InAppSubscription s : subscriptions) { + if (s.isDonationSupported()) { + donationSupported = true; + break; + } + } + if (donationSupported) { + if (Algorithms.isEmpty(countryName)) { + if (OsmandSettings.BILLING_USER_DONATION_NONE_PARAMETER.equals(settings.BILLING_USER_COUNTRY_DOWNLOAD_NAME.get())) { + countryName = app.getString(R.string.osmand_team); + } else { + countryName = app.getString(R.string.shared_string_world); + } + } + } else { + countryName = app.getString(R.string.osmand_team); + } + } else { + countryName = app.getString(R.string.osmand_team); + } + return countryName; + } + + public static String getSupportRegionHeader(OsmandApplication app, String supportRegion) { + return supportRegion.equals(app.getString(R.string.osmand_team)) ? + app.getString(R.string.default_buttons_support) : + app.getString(R.string.osm_live_support_region); + } + protected class LocalIndexesAdapter extends OsmandBaseExpandableListAdapter { public static final int SHOULD_UPDATE_GROUP_POSITION = 0; public static final int SHOULD_NOT_UPDATE_GROUP_POSITION = 1; diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragment.java index 00a15b3071..d08cf6f892 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragment.java @@ -2,23 +2,13 @@ package net.osmand.plus.settings.fragments; import android.app.Activity; import android.content.Context; -import android.content.Intent; -import android.graphics.Typeface; import android.net.Uri; import android.os.Bundle; -import android.text.Spannable; -import android.text.SpannableString; -import android.text.Spanned; -import android.text.method.LinkMovementMethod; -import android.text.style.StyleSpan; -import android.text.style.URLSpan; import android.view.LayoutInflater; -import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.ImageButton; import android.widget.ImageView; -import android.widget.LinearLayout; import android.widget.TextView; import com.google.android.material.appbar.AppBarLayout; @@ -32,16 +22,10 @@ import net.osmand.plus.Version; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.activities.OsmandInAppPurchaseActivity; import net.osmand.plus.base.BaseOsmAndFragment; -import net.osmand.plus.chooseplan.ChoosePlanDialogFragment; import net.osmand.plus.inapp.InAppPurchaseHelper; import net.osmand.plus.inapp.InAppPurchaseHelper.InAppPurchaseListener; -import net.osmand.plus.inapp.InAppPurchases.InAppSubscription; import net.osmand.plus.liveupdates.CountrySelectionFragment; -import net.osmand.plus.liveupdates.CountrySelectionFragment.CountryItem; import net.osmand.plus.liveupdates.CountrySelectionFragment.OnFragmentInteractionListener; -import net.osmand.plus.liveupdates.LiveUpdatesFragmentNew; -import net.osmand.plus.liveupdates.OsmLiveActivity; -import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.wikipedia.WikipediaDialogFragment; import net.osmand.util.Algorithms; @@ -59,11 +43,6 @@ public class PurchasesFragment extends BaseOsmAndFragment implements InAppPurcha public static final String KEY_IS_SUBSCRIBER = "action_is_new"; - private static final String PLAY_STORE_SUBSCRIPTION_URL = "https://play.google.com/store/account/subscriptions"; - private static final String PLAY_STORE_SUBSCRIPTION_DEEPLINK_URL = "https://play.google.com/store/account/subscriptions?sku=%s&package=%s"; - private static final String EMAIL_DEEPLINK_URI = "mailto:support@osmand.net"; - private static final String OSMAND_EMAIL = "support@osmand.net"; - private static final String OSMAND_NEW_DEVICE_URL = "https://docs.osmand.net/en/main@latest/osmand/purchases#new-device--new-account"; private static final String OSMAND_PURCHASES_URL = "https://docs.osmand.net/en/main@latest/osmand/purchases"; private OsmandApplication app; @@ -71,18 +50,16 @@ public class PurchasesFragment extends BaseOsmAndFragment implements InAppPurcha private InAppPurchaseHelper purchaseHelper; private View mainView; + ViewGroup cardsContainer; private SubscriptionsCard subscriptionsCard; - private CountrySelectionFragment countrySelectionFragment = new CountrySelectionFragment(); - - private String url; private Boolean isPaidVersion; public static boolean showInstance(FragmentManager fragmentManager) { try { PurchasesFragment fragment = new PurchasesFragment(); fragmentManager.beginTransaction() - .replace(R.id.fragmentContainer, fragment, TAG) + .add(R.id.fragmentContainer, fragment, TAG) .addToBackStack(TAG) .commitAllowingStateLoss(); return true; @@ -102,67 +79,39 @@ public class PurchasesFragment extends BaseOsmAndFragment implements InAppPurcha app = getMyApplication(); context = requireContext(); isPaidVersion = Version.isPaidVersion(app); - final MapActivity mapActivity = getMapActivity(); final boolean nightMode = !app.getSettings().isLightContent(); LayoutInflater themedInflater = UiUtilities.getInflater(context, nightMode); - if (isPaidVersion) { - mainView = themedInflater.inflate(R.layout.purchases_layout, container, false); - setSubscriptionClick(mapActivity); - } else { - mainView = themedInflater.inflate(R.layout.empty_purchases_layout, container, false); - LinearLayout osmandLive = mainView.findViewById(R.id.osmand_live); - osmandLive.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - if (getMyApplication() != null && getMyActivity() != null) { - ChoosePlanDialogFragment.showDialogInstance(getMyApplication(), getMyActivity().getSupportFragmentManager(), ChoosePlanDialogFragment.ChoosePlanDialogType.OSM_LIVE); - } - } - }); - TextView infoDescription = mainView.findViewById(R.id.info_description); - - String restorePurchases = getString(R.string.restore_purchases); - String infoPurchases = String.format(getString(R.string.empty_purchases_description), restorePurchases); - infoDescription.setText(infoPurchases); - } + mainView = themedInflater.inflate(R.layout.purchases_layout, container, false); AndroidUtils.addStatusBarPadding21v(getActivity(), mainView); createToolbar(mainView, nightMode); - LinearLayout purchasesRestore = mainView.findViewById(R.id.restore_purchases); - purchasesRestore.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - if (purchaseHelper != null) { - purchaseHelper.requestInventory(); - } - } - }); - LinearLayout newDeviceAccountContainer = mainView.findViewById(R.id.new_device_account_container); - newDeviceAccountContainer.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - WikipediaDialogFragment.showFullArticle(context, Uri.parse(OSMAND_NEW_DEVICE_URL), nightMode); - } - }); + cardsContainer = mainView.findViewById(R.id.cards_container); - setFormatStrings(); return mainView; } @Override public void onResume() { super.onResume(); + updateCards(); + } + + private void updateCards() { + MapActivity mapActivity = getMapActivity(); purchaseHelper = getInAppPurchaseHelper(); - if (isPaidVersion) { - MapActivity mapActivity = getMapActivity(); - if (getMapActivity() != null && purchaseHelper != null) { - ViewGroup subscriptionsCardContainer = mainView.findViewById(R.id.subscriptions_card_container); - subscriptionsCardContainer.removeAllViews(); - subscriptionsCard = new SubscriptionsCard(mapActivity, purchaseHelper); - subscriptionsCardContainer.addView(subscriptionsCard.build(mapActivity)); - } - setupSupportRegion(); + cardsContainer.removeAllViews(); + if (mapActivity == null || purchaseHelper == null) { + return; } + + boolean hasSubscriptions = !Algorithms.isEmpty(purchaseHelper.getEverMadeSubscriptions()); + if (hasSubscriptions) { + subscriptionsCard = new SubscriptionsCard(mapActivity, this, purchaseHelper); + cardsContainer.addView(subscriptionsCard.build(mapActivity)); + } + + cardsContainer.addView(new TroubleshootingOrPurchasingCard(mapActivity, purchaseHelper, isPaidVersion) + .build(mapActivity)); } @Override @@ -175,95 +124,10 @@ public class PurchasesFragment extends BaseOsmAndFragment implements InAppPurcha public void onViewStateRestored(@Nullable Bundle savedInstanceState) { super.onViewStateRestored(savedInstanceState); if (savedInstanceState != null) { - savedInstanceState.getBoolean(KEY_IS_SUBSCRIBER); + isPaidVersion = savedInstanceState.getBoolean(KEY_IS_SUBSCRIBER); } } - private void setSubscriptionClick(final MapActivity mapActivity) { - LinearLayout reportContainer = mainView.findViewById(R.id.report_container); - reportContainer.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - Intent intent = new Intent(mapActivity, OsmLiveActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); - if (mapActivity != null) { - mapActivity.startActivity(intent); - } - } - }); - LinearLayout liveUpdatesContainer = mainView.findViewById(R.id.live_updates_container); - liveUpdatesContainer.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - FragmentActivity activity = getActivity(); - if (activity != null) { - LiveUpdatesFragmentNew.showInstance(activity.getSupportFragmentManager(), PurchasesFragment.this); - } - } - }); - getSkuAppId(); - LinearLayout manageSubscriptionContainer = mainView.findViewById(R.id.manage_subscription_container); - manageSubscriptionContainer.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - Intent intent = new Intent(Intent.ACTION_VIEW); - intent.setData(Uri.parse(url)); - if (AndroidUtils.isIntentSafe(context, intent)) { - startActivity(intent); - } - } - }); - - } - - private void setupSupportRegion() { - String region = getSupportRegionName(app, purchaseHelper); - String header = getSupportRegionHeader(app, region); - TextView supportRegionHeader = mainView.findViewById(R.id.support_region_header); - TextView supportRegion = mainView.findViewById(R.id.support_region); - supportRegionHeader.setText(header); - supportRegion.setText(region); - - View supportRegionContainer = mainView.findViewById(R.id.support_region_container); - supportRegionContainer.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - CountrySelectionFragment countryCountrySelectionFragment = countrySelectionFragment; - countryCountrySelectionFragment.show(getChildFragmentManager(), CountrySelectionFragment.TAG); - } - }); - - countrySelectionFragment.initCountries(app); - } - - public static String getSupportRegionName(OsmandApplication app, InAppPurchaseHelper purchaseHelper) { - OsmandSettings settings = app.getSettings(); - String countryName = settings.BILLING_USER_COUNTRY.get(); - if (purchaseHelper != null) { - InAppSubscription monthlyPurchased = purchaseHelper.getPurchasedMonthlyLiveUpdates(); - if (monthlyPurchased != null && monthlyPurchased.isDonationSupported()) { - if (Algorithms.isEmpty(countryName)) { - if (OsmandSettings.BILLING_USER_DONATION_NONE_PARAMETER.equals(settings.BILLING_USER_COUNTRY_DOWNLOAD_NAME.get())) { - countryName = app.getString(R.string.osmand_team); - } else { - countryName = app.getString(R.string.shared_string_world); - } - } - } else { - countryName = app.getString(R.string.osmand_team); - } - } else { - countryName = app.getString(R.string.osmand_team); - } - return countryName; - } - - public static String getSupportRegionHeader(OsmandApplication app, String supportRegion) { - return supportRegion.equals(app.getString(R.string.osmand_team)) ? - app.getString(R.string.default_buttons_support) : - app.getString(R.string.osm_live_support_region); - } - @Nullable public InAppPurchaseHelper getInAppPurchaseHelper() { Activity activity = getActivity(); @@ -303,69 +167,21 @@ public class PurchasesFragment extends BaseOsmAndFragment implements InAppPurcha appbar.addView(toolbar); } - public void setFormatStrings() { - TextView contactSupportLink = mainView.findViewById(R.id.contact_support_title); - TextView supportDescription = mainView.findViewById(R.id.support_link_title); - - SpannableString spannableStringSupport = new SpannableString(getString(R.string.contact_support)); - spannableStringSupport.setSpan(new URLSpan(EMAIL_DEEPLINK_URI), 0, spannableStringSupport.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - - String supportDescriptionString = getString(R.string.contact_support_description, OSMAND_EMAIL); - SpannableString spannableStringMail = new SpannableString(supportDescriptionString); - int startIndex = supportDescriptionString.indexOf(OSMAND_EMAIL); - int endIndex = startIndex + OSMAND_EMAIL.length(); - StyleSpan boldSpan = new StyleSpan(Typeface.BOLD); - spannableStringMail.setSpan(boldSpan, startIndex, endIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - - contactSupportLink.setText(spannableStringSupport); - supportDescription.setText(spannableStringMail); - - AndroidUtils.removeLinkUnderline(contactSupportLink); - - contactSupportLink.setMovementMethod(LinkMovementMethod.getInstance()); - } - - private void getSkuAppId() { - InAppPurchaseHelper purchaseHelper = app.getInAppPurchaseHelper(); - if (purchaseHelper != null && purchaseHelper.getFullVersion() != null) { - String sku = purchaseHelper.getFullVersion().getSku(); - url = String.format(PLAY_STORE_SUBSCRIPTION_DEEPLINK_URL, - sku, context.getPackageName()); - } else { - url = PLAY_STORE_SUBSCRIPTION_URL; - } - } - - @Override - public void onSearchResult(CountryItem selectedCountryItem) { - String countryName = selectedCountryItem != null ? selectedCountryItem.getLocalName() : ""; - String countryDownloadName = selectedCountryItem != null ? - selectedCountryItem.getDownloadName() : OsmandSettings.BILLING_USER_DONATION_WORLD_PARAMETER; - - OsmandApplication app = getMyApplication(); - if (app != null) { - TextView supportRegionHeader = mainView.findViewById(R.id.support_region_header); - TextView supportRegion = mainView.findViewById(R.id.support_region); - supportRegionHeader.setText(getSupportRegionHeader(app, countryName)); - supportRegion.setText(countryName); - app.getSettings().BILLING_USER_COUNTRY.set(countryName); - app.getSettings().BILLING_USER_COUNTRY_DOWNLOAD_NAME.set(countryDownloadName); - } - } - @Override public void onError(InAppPurchaseHelper.InAppPurchaseTaskType taskType, String error) { } @Override public void onGetItems() { - if (subscriptionsCard != null) { - subscriptionsCard.update(); + if (app != null) { + isPaidVersion = Version.isPaidVersion(app); } + updateCards(); } @Override public void onItemPurchased(String sku, boolean active) { + isPaidVersion = true; if (purchaseHelper != null) { purchaseHelper.requestInventory(); } @@ -379,7 +195,14 @@ public class PurchasesFragment extends BaseOsmAndFragment implements InAppPurcha public void dismissProgress(InAppPurchaseHelper.InAppPurchaseTaskType taskType) { } + @Override + public void onSearchResult(CountrySelectionFragment.CountryItem name) { + if (subscriptionsCard != null) { + subscriptionsCard.onSupportRegionSelected(name); + } + } + private MapActivity getMapActivity() { return (MapActivity) getActivity(); } -} +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/SubscriptionsCard.java b/OsmAnd/src/net/osmand/plus/settings/fragments/SubscriptionsCard.java index 1cc422b3ff..100bab00df 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/SubscriptionsCard.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/SubscriptionsCard.java @@ -1,121 +1,146 @@ package net.osmand.plus.settings.fragments; -import android.os.Build; -import android.view.LayoutInflater; +import android.content.Intent; +import android.net.Uri; import android.view.View; import android.view.ViewGroup; +import android.widget.LinearLayout; import android.widget.TextView; import net.osmand.AndroidUtils; -import net.osmand.Period; import net.osmand.plus.R; -import net.osmand.plus.UiUtilities; import net.osmand.plus.activities.MapActivity; -import net.osmand.plus.chooseplan.ChoosePlanDialogFragment; import net.osmand.plus.helpers.AndroidUiHelper; import net.osmand.plus.inapp.InAppPurchaseHelper; -import net.osmand.plus.inapp.InAppPurchases.InAppSubscription; -import net.osmand.plus.inapp.InAppPurchases.InAppSubscription.SubscriptionState; +import net.osmand.plus.liveupdates.CountrySelectionFragment; +import net.osmand.plus.liveupdates.LiveUpdatesFragment; +import net.osmand.plus.liveupdates.LiveUpdatesFragmentNew; +import net.osmand.plus.liveupdates.OsmLiveActivity; import net.osmand.plus.routepreparationmenu.cards.BaseCard; +import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.util.Algorithms; -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.Date; -import java.util.List; -import java.util.Locale; - import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; public class SubscriptionsCard extends BaseCard { - private final InAppPurchaseHelper purchaseHelper; + private static final String PLAY_STORE_SUBSCRIPTION_URL = "https://play.google.com/store/account/subscriptions"; + private static final String PLAY_STORE_SUBSCRIPTION_DEEPLINK_URL = "https://play.google.com/store/account/subscriptions?sku=%s&package=%s"; - private final SimpleDateFormat dateFormat; + private Fragment target; + private CountrySelectionFragment countrySelectionFragment = new CountrySelectionFragment(); + private SubscriptionsListCard subscriptionsListCard; + + private InAppPurchaseHelper purchaseHelper; @Override public int getCardLayoutId() { return R.layout.subscriptions_card; } - public SubscriptionsCard(@NonNull MapActivity mapActivity, @NonNull InAppPurchaseHelper purchaseHelper) { + public SubscriptionsCard(@NonNull MapActivity mapActivity, @NonNull Fragment target, @NonNull InAppPurchaseHelper purchaseHelper) { super(mapActivity); + this.target = target; this.purchaseHelper = purchaseHelper; - this.dateFormat = new SimpleDateFormat("MMM d, yyyy", Locale.getDefault()); } @Override protected void updateContent() { if (purchaseHelper == null || Algorithms.isEmpty(purchaseHelper.getEverMadeSubscriptions())) { + AndroidUiHelper.updateVisibility(view, false); return; + } else { + AndroidUiHelper.updateVisibility(view, true); } - LayoutInflater inflater = UiUtilities.getInflater(mapActivity, nightMode); - ((ViewGroup) view).removeAllViews(); + updateSubscriptionsListCard(); + setupSupportRegion(); - List subscriptions = purchaseHelper.getEverMadeSubscriptions(); - for (int i = 0; i < subscriptions.size(); i++) { - InAppSubscription subscription = subscriptions.get(i); - SubscriptionState state = subscription.getState(); - boolean autoRenewed = state == SubscriptionState.ACTIVE || state == SubscriptionState.IN_GRACE_PERIOD; - - View card = inflater.inflate(R.layout.subscription_layout, null, false); - ((ViewGroup) view).addView(card); - - TextView subscriptionPeriod = card.findViewById(R.id.subscription_type); - String period = app.getString(subscription.getPeriodTypeString()); - if (!Algorithms.isEmpty(period)) { - subscriptionPeriod.setText(period); - AndroidUiHelper.updateVisibility(subscriptionPeriod, true); + LinearLayout reportContainer = view.findViewById(R.id.report_container); + reportContainer.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(mapActivity, OsmLiveActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); + mapActivity.startActivity(intent); } + }); - if (autoRenewed) { - TextView nextBillingDate = card.findViewById(R.id.next_billing_date); - String date = getHumanDate(subscription.getPurchaseTime(), subscription.getSubscriptionPeriod()); - if (!Algorithms.isEmpty(date)) { - nextBillingDate.setText(app.getString(R.string.next_billing_date, date)); - AndroidUiHelper.updateVisibility(nextBillingDate, true); - } - } else { - View renewContainer = card.findViewById(R.id.renewContainer); - AndroidUiHelper.updateVisibility(renewContainer, true); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - AndroidUtils.setBackground(mapActivity, renewContainer, nightMode, R.drawable.ripple_light, R.drawable.ripple_dark); - } else { - AndroidUtils.setBackground(mapActivity, renewContainer, nightMode, R.drawable.btn_unstroked_light, R.drawable.btn_unstroked_dark); - } - final String sku = subscription.getSku(); - renewContainer.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - ChoosePlanDialogFragment.subscribe(app, mapActivity, purchaseHelper, sku); - } - }); - - View renew = card.findViewById(R.id.renew); - AndroidUtils.setBackground(mapActivity, renew, nightMode, - R.drawable.btn_solid_border_light, R.drawable.btn_solid_border_dark); + LinearLayout liveUpdatesContainer = view.findViewById(R.id.live_updates_container); + liveUpdatesContainer.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + LiveUpdatesFragmentNew.showInstance(mapActivity.getSupportFragmentManager(), target); } + }); - TextView status = card.findViewById(R.id.status); - status.setText(app.getString(state.getStringRes())); - AndroidUtils.setBackground(status, app.getUIUtilities().getIcon(state.getBackgroundRes())); + final String subscriptionUrl = getSubscriptionUrl(); + LinearLayout manageSubscriptionContainer = view.findViewById(R.id.manage_subscription_container); + manageSubscriptionContainer.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setData(Uri.parse(subscriptionUrl)); + if (AndroidUtils.isIntentSafe(mapActivity, intent)) { + target.startActivity(intent); + } + } + }); + } - int dividerLayout = i + 1 == subscriptions.size() ? R.layout.simple_divider_item : R.layout.divider_half_item; - View divider = inflater.inflate(dividerLayout, (ViewGroup) view, false); - ((ViewGroup) view).addView(divider); + public void updateSubscriptionsListCard() { + if (subscriptionsListCard == null) { + ViewGroup subscriptionsListContainer = view.findViewById(R.id.subscriptions_list_container); + subscriptionsListContainer.removeAllViews(); + subscriptionsListCard = new SubscriptionsListCard(mapActivity, purchaseHelper); + subscriptionsListContainer.addView(subscriptionsListCard.build(mapActivity)); + } else { + subscriptionsListCard.update(); } } - private String getHumanDate(long time, Period period) { - if (period == null || period.getUnit() == null) { - return ""; + private void setupSupportRegion() { + String region = LiveUpdatesFragment.getSupportRegionName(app, purchaseHelper); + String header = LiveUpdatesFragment.getSupportRegionHeader(app, region); + TextView supportRegionHeader = view.findViewById(R.id.support_region_header); + TextView supportRegion = view.findViewById(R.id.support_region); + supportRegionHeader.setText(header); + supportRegion.setText(region); + + View supportRegionContainer = view.findViewById(R.id.support_region_container); + supportRegionContainer.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + CountrySelectionFragment countryCountrySelectionFragment = countrySelectionFragment; + countryCountrySelectionFragment.show(target.getChildFragmentManager(), CountrySelectionFragment.TAG); + } + }); + + countrySelectionFragment.initCountries(app); + } + + private String getSubscriptionUrl() { + InAppPurchaseHelper purchaseHelper = app.getInAppPurchaseHelper(); + if (purchaseHelper != null && purchaseHelper.getFullVersion() != null) { + String sku = purchaseHelper.getFullVersion().getSku(); + return String.format(PLAY_STORE_SUBSCRIPTION_DEEPLINK_URL, + sku, mapActivity.getPackageName()); + } else { + return PLAY_STORE_SUBSCRIPTION_URL; } - Date date = new Date(time); - Calendar calendar = Calendar.getInstance(); - calendar.setTime(date); - calendar.add(period.getUnit().getCalendarIdx(), period.getNumberOfUnits()); - date = calendar.getTime(); - return dateFormat.format(date); + } + + public void onSupportRegionSelected(CountrySelectionFragment.CountryItem selectedCountryItem) { + String countryName = selectedCountryItem != null ? selectedCountryItem.getLocalName() : ""; + String countryDownloadName = selectedCountryItem != null ? + selectedCountryItem.getDownloadName() : OsmandSettings.BILLING_USER_DONATION_WORLD_PARAMETER; + + TextView supportRegionHeader = view.findViewById(R.id.support_region_header); + TextView supportRegion = view.findViewById(R.id.support_region); + supportRegionHeader.setText(LiveUpdatesFragment.getSupportRegionHeader(app, countryName)); + supportRegion.setText(countryName); + app.getSettings().BILLING_USER_COUNTRY.set(countryName); + app.getSettings().BILLING_USER_COUNTRY_DOWNLOAD_NAME.set(countryDownloadName); } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/SubscriptionsListCard.java b/OsmAnd/src/net/osmand/plus/settings/fragments/SubscriptionsListCard.java new file mode 100644 index 0000000000..9d8d4f9568 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/SubscriptionsListCard.java @@ -0,0 +1,124 @@ +package net.osmand.plus.settings.fragments; + +import android.os.Build; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import net.osmand.AndroidUtils; +import net.osmand.Period; +import net.osmand.plus.R; +import net.osmand.plus.UiUtilities; +import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.chooseplan.ChoosePlanDialogFragment; +import net.osmand.plus.helpers.AndroidUiHelper; +import net.osmand.plus.inapp.InAppPurchaseHelper; +import net.osmand.plus.inapp.InAppPurchases.InAppSubscription; +import net.osmand.plus.inapp.InAppPurchases.InAppSubscription.SubscriptionState; +import net.osmand.plus.routepreparationmenu.cards.BaseCard; +import net.osmand.util.Algorithms; + +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.Locale; + +import androidx.annotation.NonNull; + +public class SubscriptionsListCard extends BaseCard { + + private final InAppPurchaseHelper purchaseHelper; + + private final SimpleDateFormat dateFormat; + + @Override + public int getCardLayoutId() { + return R.layout.subscriptions_list_card; + } + + public SubscriptionsListCard(@NonNull MapActivity mapActivity, @NonNull InAppPurchaseHelper purchaseHelper) { + super(mapActivity); + this.purchaseHelper = purchaseHelper; + this.dateFormat = new SimpleDateFormat("MMM d, yyyy", Locale.getDefault()); + } + + @Override + protected void updateContent() { + if (purchaseHelper == null || Algorithms.isEmpty(purchaseHelper.getEverMadeSubscriptions())) { + AndroidUiHelper.updateVisibility(view, false); + return; + } else { + AndroidUiHelper.updateVisibility(view, true); + } + + LayoutInflater inflater = UiUtilities.getInflater(mapActivity, nightMode); + ((ViewGroup) view).removeAllViews(); + + List subscriptions = purchaseHelper.getEverMadeSubscriptions(); + for (int i = 0; i < subscriptions.size(); i++) { + InAppSubscription subscription = subscriptions.get(i); + SubscriptionState state = subscription.getState(); + boolean autoRenewed = state == SubscriptionState.ACTIVE || state == SubscriptionState.IN_GRACE_PERIOD; + + View card = inflater.inflate(R.layout.subscription_layout, null, false); + ((ViewGroup) view).addView(card); + + TextView subscriptionPeriod = card.findViewById(R.id.subscription_type); + String period = app.getString(subscription.getPeriodTypeString()); + if (!Algorithms.isEmpty(period)) { + subscriptionPeriod.setText(period); + AndroidUiHelper.updateVisibility(subscriptionPeriod, true); + } + + if (autoRenewed) { + TextView nextBillingDate = card.findViewById(R.id.next_billing_date); + String date = getHumanDate(subscription.getPurchaseTime(), subscription.getSubscriptionPeriod()); + if (!Algorithms.isEmpty(date)) { + nextBillingDate.setText(app.getString(R.string.next_billing_date, date)); + AndroidUiHelper.updateVisibility(nextBillingDate, true); + } + } else { + View renewContainer = card.findViewById(R.id.renewContainer); + AndroidUiHelper.updateVisibility(renewContainer, true); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + AndroidUtils.setBackground(mapActivity, renewContainer, nightMode, R.drawable.ripple_light, R.drawable.ripple_dark); + } else { + AndroidUtils.setBackground(mapActivity, renewContainer, nightMode, R.drawable.btn_unstroked_light, R.drawable.btn_unstroked_dark); + } + final String sku = subscription.getSku(); + renewContainer.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ChoosePlanDialogFragment.subscribe(app, mapActivity, purchaseHelper, sku); + } + }); + + View renew = card.findViewById(R.id.renew); + AndroidUtils.setBackground(mapActivity, renew, nightMode, + R.drawable.btn_solid_border_light, R.drawable.btn_solid_border_dark); + } + + TextView status = card.findViewById(R.id.status); + status.setText(app.getString(state.getStringRes())); + AndroidUtils.setBackground(status, app.getUIUtilities().getIcon(state.getBackgroundRes())); + + int dividerLayout = i + 1 == subscriptions.size() ? R.layout.simple_divider_item : R.layout.divider_half_item; + View divider = inflater.inflate(dividerLayout, (ViewGroup) view, false); + ((ViewGroup) view).addView(divider); + } + } + + private String getHumanDate(long time, Period period) { + if (period == null || period.getUnit() == null) { + return ""; + } + Date date = new Date(time); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + calendar.add(period.getUnit().getCalendarIdx(), period.getNumberOfUnits()); + date = calendar.getTime(); + return dateFormat.format(date); + } +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/TroubleshootingOrPurchasingCard.java b/OsmAnd/src/net/osmand/plus/settings/fragments/TroubleshootingOrPurchasingCard.java new file mode 100644 index 0000000000..c53950ee2b --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/TroubleshootingOrPurchasingCard.java @@ -0,0 +1,126 @@ +package net.osmand.plus.settings.fragments; + +import android.graphics.Typeface; +import android.net.Uri; +import android.os.Build; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.Spanned; +import android.text.method.LinkMovementMethod; +import android.text.style.StyleSpan; +import android.text.style.URLSpan; +import android.view.View; +import android.widget.TextView; + +import net.osmand.AndroidUtils; +import net.osmand.plus.R; +import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.chooseplan.ChoosePlanDialogFragment; +import net.osmand.plus.inapp.InAppPurchaseHelper; +import net.osmand.plus.routepreparationmenu.cards.BaseCard; +import net.osmand.plus.wikipedia.WikipediaDialogFragment; + +import androidx.annotation.IdRes; +import androidx.annotation.NonNull; +import androidx.cardview.widget.CardView; +import androidx.core.content.ContextCompat; + +public class TroubleshootingOrPurchasingCard extends BaseCard { + + private static final String OSMAND_NEW_DEVICE_URL = "https://docs.osmand.net/en/main@latest/osmand/purchases#new-device--new-account"; + private static final String OSMAND_EMAIL = "support@osmand.net"; + private static final String EMAIL_DEEPLINK_URI = "mailto:support@osmand.net"; + + protected InAppPurchaseHelper purchaseHelper; + + private final boolean isPaidVersion; + + @Override + public int getCardLayoutId() { + return isPaidVersion ? R.layout.troubleshooting_card : R.layout.no_purchases_card; + } + + public TroubleshootingOrPurchasingCard(@NonNull MapActivity mapActivity, @NonNull InAppPurchaseHelper purchaseHelper, boolean isPaidVersion) { + super(mapActivity); + this.purchaseHelper = purchaseHelper; + this.isPaidVersion = isPaidVersion; + } + + @Override + protected void updateContent() { + setupRestorePurchasesBtn(R.id.restore_purchases); + setupNewDeviceOrAccountBtn(R.id.new_device_account_container); + setupSupportDescription(); + setupContactUsLink(); + + if (!isPaidVersion) { + TextView infoDescription = view.findViewById(R.id.info_description); + String restorePurchases = app.getString(R.string.restore_purchases); + String infoPurchases = String.format(app.getString(R.string.empty_purchases_description), restorePurchases); + infoDescription.setText(infoPurchases); + + View osmandLive = view.findViewById(R.id.osmand_live); + osmandLive.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ChoosePlanDialogFragment.showDialogInstance(getMyApplication(), + mapActivity.getSupportFragmentManager(), + ChoosePlanDialogFragment.ChoosePlanDialogType.OSM_LIVE); + } + }); + + CardView getItButtonContainer = view.findViewById(R.id.card_view); + int colorRes = nightMode ? R.color.switch_button_active_dark : R.color.switch_button_active_light; + getItButtonContainer.setCardBackgroundColor(ContextCompat.getColor(mapActivity, colorRes)); + + View getItButton = view.findViewById(R.id.card_container); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + AndroidUtils.setBackground(mapActivity, getItButton, nightMode, R.drawable.ripple_light, R.drawable.ripple_dark); + } else { + AndroidUtils.setBackground(mapActivity, getItButton, nightMode, R.drawable.btn_unstroked_light, R.drawable.btn_unstroked_dark); + } + } + } + + protected void setupRestorePurchasesBtn(@IdRes int btnId) { + View purchasesRestore = view.findViewById(btnId); + purchasesRestore.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (purchaseHelper != null) { + purchaseHelper.requestInventory(); + } + } + }); + } + + protected void setupNewDeviceOrAccountBtn(@IdRes int btnId) { + View newDeviceAccountContainer = view.findViewById(btnId); + newDeviceAccountContainer.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + WikipediaDialogFragment.showFullArticle(mapActivity, Uri.parse(OSMAND_NEW_DEVICE_URL), nightMode); + } + }); + } + + protected void setupSupportDescription() { + TextView supportDescription = view.findViewById(R.id.support_link_title); + String supportDescriptionString = app.getString(R.string.contact_support_description, OSMAND_EMAIL); + SpannableString spannableStringMail = new SpannableString(supportDescriptionString); + int startIndex = supportDescriptionString.indexOf(OSMAND_EMAIL); + int endIndex = startIndex + OSMAND_EMAIL.length(); + StyleSpan boldSpan = new StyleSpan(Typeface.BOLD); + spannableStringMail.setSpan(boldSpan, startIndex, endIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + supportDescription.setText(spannableStringMail); + } + + protected void setupContactUsLink() { + TextView contactSupportLink = view.findViewById(R.id.contact_support_title); + SpannableString spannableStringSupport = new SpannableString(app.getString(R.string.contact_support)); + spannableStringSupport.setSpan(new URLSpan(EMAIL_DEEPLINK_URI), 0, spannableStringSupport.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + contactSupportLink.setText(spannableStringSupport); + AndroidUtils.removeLinkUnderline(contactSupportLink); + contactSupportLink.setMovementMethod(LinkMovementMethod.getInstance()); + } +} \ No newline at end of file From d190da742acd61d226dfe25b24b2b29cd1786136 Mon Sep 17 00:00:00 2001 From: cepprice Date: Mon, 29 Mar 2021 18:13:56 +0500 Subject: [PATCH 11/11] Huawei fix and small corrections --- .../osmand/plus/inapp/InAppPurchasesImpl.java | 5 +++++ .../settings/fragments/PurchasesFragment.java | 16 ++++++++-------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/OsmAnd/src-huawei/net/osmand/plus/inapp/InAppPurchasesImpl.java b/OsmAnd/src-huawei/net/osmand/plus/inapp/InAppPurchasesImpl.java index 4ed0021b6f..59d97daed0 100644 --- a/OsmAnd/src-huawei/net/osmand/plus/inapp/InAppPurchasesImpl.java +++ b/OsmAnd/src-huawei/net/osmand/plus/inapp/InAppPurchasesImpl.java @@ -165,6 +165,11 @@ public class InAppPurchasesImpl extends InAppPurchases { this.info = info; } + @Override + public int getPeriodTypeString() { + return R.string.monthly_subscription; + } + @Override public String getDefaultPrice(Context ctx) { return ""; diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragment.java index d08cf6f892..e3bbb85f04 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/PurchasesFragment.java @@ -46,13 +46,12 @@ public class PurchasesFragment extends BaseOsmAndFragment implements InAppPurcha private static final String OSMAND_PURCHASES_URL = "https://docs.osmand.net/en/main@latest/osmand/purchases"; private OsmandApplication app; - private Context context; private InAppPurchaseHelper purchaseHelper; - private View mainView; - ViewGroup cardsContainer; + private ViewGroup cardsContainer; private SubscriptionsCard subscriptionsCard; + private boolean nightMode; private Boolean isPaidVersion; public static boolean showInstance(FragmentManager fragmentManager) { @@ -77,12 +76,11 @@ public class PurchasesFragment extends BaseOsmAndFragment implements InAppPurcha @Override public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { app = getMyApplication(); - context = requireContext(); isPaidVersion = Version.isPaidVersion(app); - final boolean nightMode = !app.getSettings().isLightContent(); - LayoutInflater themedInflater = UiUtilities.getInflater(context, nightMode); + nightMode = !app.getSettings().isLightContent(); + LayoutInflater themedInflater = UiUtilities.getInflater(getContext(), nightMode); - mainView = themedInflater.inflate(R.layout.purchases_layout, container, false); + View mainView = themedInflater.inflate(R.layout.purchases_layout, container, false); AndroidUtils.addStatusBarPadding21v(getActivity(), mainView); createToolbar(mainView, nightMode); cardsContainer = mainView.findViewById(R.id.cards_container); @@ -148,7 +146,9 @@ public class PurchasesFragment extends BaseOsmAndFragment implements InAppPurcha icon.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - WikipediaDialogFragment.showFullArticle(context, Uri.parse(OSMAND_PURCHASES_URL), nightMode); + if (getContext() != null) { + WikipediaDialogFragment.showFullArticle(getContext(), Uri.parse(OSMAND_PURCHASES_URL), nightMode); + } } }); ImageButton backButton = toolbar.findViewById(R.id.close_button);