From 3940987dcde4ae04fc315ba31f14ef5c2b293a8e Mon Sep 17 00:00:00 2001 From: Chumva Date: Fri, 20 Apr 2018 19:28:21 +0300 Subject: [PATCH 01/38] add explore cards to wikivoyage --- OsmAnd/res/layout/bottom_buttons.xml | 57 +++++ OsmAnd/res/layout/fragment_explore_tab.xml | 24 +- OsmAnd/res/layout/wikivoyage_base_card.xml | 57 +++++ .../layout/wikivoyage_start_editing_card.xml | 66 +++++ OsmAnd/res/values/sizes.xml | 3 +- OsmAnd/res/values/strings.xml | 6 + .../explore/ExploreTabFragment.java | 36 ++- .../explore/travelcards/BaseTravelCard.java | 233 ++++++++++++++++++ 8 files changed, 474 insertions(+), 8 deletions(-) create mode 100644 OsmAnd/res/layout/bottom_buttons.xml create mode 100644 OsmAnd/res/layout/wikivoyage_base_card.xml create mode 100644 OsmAnd/res/layout/wikivoyage_start_editing_card.xml create mode 100644 OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/BaseTravelCard.java diff --git a/OsmAnd/res/layout/bottom_buttons.xml b/OsmAnd/res/layout/bottom_buttons.xml new file mode 100644 index 0000000000..1832c3ecdc --- /dev/null +++ b/OsmAnd/res/layout/bottom_buttons.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/fragment_explore_tab.xml b/OsmAnd/res/layout/fragment_explore_tab.xml index 3ca1310a18..0b0bbb1324 100644 --- a/OsmAnd/res/layout/fragment_explore_tab.xml +++ b/OsmAnd/res/layout/fragment_explore_tab.xml @@ -1,14 +1,26 @@ - - + + + + + + + diff --git a/OsmAnd/res/layout/wikivoyage_base_card.xml b/OsmAnd/res/layout/wikivoyage_base_card.xml new file mode 100644 index 0000000000..53aa729cd3 --- /dev/null +++ b/OsmAnd/res/layout/wikivoyage_base_card.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/wikivoyage_start_editing_card.xml b/OsmAnd/res/layout/wikivoyage_start_editing_card.xml new file mode 100644 index 0000000000..176ca94ab3 --- /dev/null +++ b/OsmAnd/res/layout/wikivoyage_start_editing_card.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/values/sizes.xml b/OsmAnd/res/values/sizes.xml index a516f00b0f..c8a818cff9 100644 --- a/OsmAnd/res/values/sizes.xml +++ b/OsmAnd/res/values/sizes.xml @@ -281,6 +281,7 @@ 36dp 80dp 40dp - + 144dp + 0.01 \ No newline at end of file diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index 29c4269687..117657f643 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -9,6 +9,12 @@ 3. All your modified/created strings are in the top of the file (to make easier find what\'s translated). PLEASE: Have a look at http://code.google.com/p/osmand/wiki/UIConsistency, it may really improve your and our work :-) Thx - Hardy --> + The free worldwide travel guide that anyone can edit. + Travel is based on Wikivoyage. During open beta testing you have the opportunity to evaluate all the features for free. After the end of the beta period, Travel will be available to subscribers of OsmAnd Unlimited and the owners of OsmAnd+ + You can edit any article on Wikivoyage, and we hope that you do. We need your knowledge, your experience, your talent, and your attention + Start editing + Get unlimited access + Welcome, to the open beta! Choose plan To read Travel articles offline, you need to purchase one of the following items. Choose suitable item: diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/ExploreTabFragment.java b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/ExploreTabFragment.java index 907519efac..b6f46e7255 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/ExploreTabFragment.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/ExploreTabFragment.java @@ -6,15 +6,49 @@ import android.support.annotation.Nullable; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.LinearLayout; +import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.base.BaseOsmAndFragment; +import net.osmand.plus.wikivoyage.explore.travelcards.BaseTravelCard; + +import java.util.ArrayList; public class ExploreTabFragment extends BaseOsmAndFragment { @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - return inflater.inflate(R.layout.fragment_explore_tab, container, false); + OsmandApplication app = getMyApplication(); + boolean nightMode = app.getDaynightHelper().isNightModeForMapControls(); + + final View mainView = inflater.inflate(R.layout.fragment_explore_tab, container, false); + + LinearLayout linearLayout = (LinearLayout) mainView.findViewById(R.id.cards_list); + ArrayList items = new ArrayList<>(); + + BaseTravelCard openBeta = new BaseTravelCard.Builder() + .setLayoutId(R.layout.wikivoyage_base_card) + .setBackgroundImage(getIconsCache().getIcon(R.drawable.img_help_wikivoyage_articles)) + .setLeftButtonText(getString(R.string.get_unlimited_access)) + .setDescription(getString(R.string.welcome_to_open_beta_description)) + .setTitle(getString(R.string.welcome_to_open_beta)) + .create(); + items.add(openBeta); + + BaseTravelCard startEditing = new BaseTravelCard.Builder() + .setLayoutId(R.layout.wikivoyage_start_editing_card) + .setBackgroundImage(getIconsCache().getIcon(R.drawable.img_help_wikivoyage_contribute)) + .setLeftButtonText(getString(R.string.start_editing)) + .setDescription(getString(R.string.start_editing_card_description)) + .create(); + items.add(startEditing); + + for (BaseTravelCard item : items) { + item.inflate(app, linearLayout, nightMode); + } + + return mainView; } } diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/BaseTravelCard.java b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/BaseTravelCard.java new file mode 100644 index 0000000000..47ace4950d --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/BaseTravelCard.java @@ -0,0 +1,233 @@ +package net.osmand.plus.wikivoyage.explore.travelcards; + +import android.graphics.drawable.Drawable; +import android.support.annotation.ColorInt; +import android.support.annotation.ColorRes; +import android.support.annotation.LayoutRes; +import android.support.v4.content.ContextCompat; +import android.view.ContextThemeWrapper; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.R; + +public class BaseTravelCard { + + private static final int INVALID_POSITION = -1; + private static final int DEFAULT_VALUE = -1; + + protected View view; + private View.OnClickListener onLeftButtonClickListener; + private View.OnClickListener onRightButtonClickListener; + + @LayoutRes + protected int layoutId; + @ColorRes + protected int bottomDividerColorId; + + private Object tag; + private OsmandApplication app; + + protected Drawable image; + protected String rightBottomButtonText; + protected String leftBottomButtonText; + protected String description; + protected String title; + + protected int position; + + public View getView() { + return view; + } + + public Object getTag() { + return tag; + } + + public BaseTravelCard(View view, + @LayoutRes int layoutId, + Object tag, + Drawable image, + View.OnClickListener onLeftButtonClickListener, + View.OnClickListener onRightButtonClickListener, + int position, + String rightBottomButtonText, + String leftBottomButtonText, + @ColorRes int bottomDividerColorId, + String description, + String title) { + this.view = view; + this.layoutId = layoutId; + this.image = image; + this.tag = tag; + this.onLeftButtonClickListener = onLeftButtonClickListener; + this.onRightButtonClickListener = onRightButtonClickListener; + this.position = position; + this.rightBottomButtonText = rightBottomButtonText; + this.leftBottomButtonText = leftBottomButtonText; + this.bottomDividerColorId = bottomDividerColorId; + this.description = description; + this.title = title; + } + + protected BaseTravelCard() { + + } + + public void inflate(OsmandApplication app, ViewGroup container, boolean nightMode) { + View view = getView(app, container, nightMode); + if (image != null) { + ImageView imageView = (ImageView) view.findViewById(R.id.background_image); + imageView.setImageDrawable(image); + } + if (title != null) { + ((TextView) view.findViewById(R.id.title)).setText(title); + } + if (description != null) { + ((TextView) view.findViewById(R.id.description)).setText(description); + } + if (bottomDividerColorId != DEFAULT_VALUE) { + view.findViewById(R.id.bottom_divider).setBackgroundColor(getResolvedColor(bottomDividerColorId)); + } + if (leftBottomButtonText != null) { + view.findViewById(R.id.left_bottom_button).setOnClickListener(onLeftButtonClickListener); + ((TextView) view.findViewById(R.id.left_bottom_button_text)).setText(leftBottomButtonText); + } + if (rightBottomButtonText != null) { + + if (bottomDividerColorId != DEFAULT_VALUE) { + View buttonsDivider = view.findViewById(R.id.bottom_buttons_divider); + buttonsDivider.setVisibility(View.VISIBLE); + buttonsDivider.setBackgroundColor(getResolvedColor(bottomDividerColorId)); + } + + View rightButton = view.findViewById(R.id.right_bottom_button); + rightButton.setVisibility(View.VISIBLE); + rightButton.setOnClickListener(onRightButtonClickListener); + ((TextView) rightButton.findViewById(R.id.right_bottom_button_text)).setText(rightBottomButtonText); + } + if (position != INVALID_POSITION) { + container.addView(view, position); + } else { + container.addView(view); + } + } + + private View getView(OsmandApplication app, ViewGroup parent, boolean nightMode) { + if (view != null) { + return view; + } + this.app = app; + if (layoutId != DEFAULT_VALUE) { + final int themeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme; + return view = LayoutInflater.from(new ContextThemeWrapper(app, themeRes)) + .inflate(layoutId, parent, false); + } + throw new RuntimeException("BaseTravelCard must have specified view or layoutId."); + } + + @ColorInt + protected int getResolvedColor(@ColorRes int colorId) { + return ContextCompat.getColor(app, colorId); + } + + public static class Builder { + + protected View customView; + protected View.OnClickListener onLeftButtonClickListener; + protected View.OnClickListener onRightButtonClickListener; + + @LayoutRes + protected int layoutId = DEFAULT_VALUE; + @ColorRes + protected int dividerColorId = DEFAULT_VALUE; + + protected Drawable image; + protected String rightBottomButtonText; + protected String leftBottomButtonText; + protected String description; + protected String title; + protected Object tag; + + protected int position = INVALID_POSITION; + + public Builder setCustomView(View customView) { + this.customView = customView; + return this; + } + + public Builder setTag(Object tag) { + this.tag = tag; + return this; + } + + public Builder setLayoutId(@LayoutRes int layoutId) { + this.layoutId = layoutId; + return this; + } + + public Builder setBackgroundImage(Drawable image) { + this.image = image; + return this; + } + + public Builder setOnLeftButtonClickListener(View.OnClickListener onLeftButtonClickListener) { + this.onLeftButtonClickListener = onLeftButtonClickListener; + return this; + } + + public Builder setOnRightButtonClickListener(View.OnClickListener onRightButtonClickListener) { + this.onRightButtonClickListener = onRightButtonClickListener; + return this; + } + + public Builder setRightButtonText(String rightBottomButtonText) { + this.rightBottomButtonText = rightBottomButtonText; + return this; + } + + public Builder setLeftButtonText(String leftBottomButtonText) { + this.leftBottomButtonText = leftBottomButtonText; + return this; + } + + public Builder setTitle(String title) { + this.title = title; + return this; + } + + public Builder setDescription(String description) { + this.description = description; + return this; + } + + public Builder setPosition(int position) { + this.position = position; + return this; + } + + public Builder setBottomDividerColorId(@ColorRes int dividerColorId) { + this.dividerColorId = dividerColorId; + return this; + } + + public BaseTravelCard create() { + return new BaseTravelCard(customView, + layoutId, + tag, + image, + onLeftButtonClickListener, + onRightButtonClickListener, + position, + rightBottomButtonText, + leftBottomButtonText, + dividerColorId, + description, + title); + } + } +} From e3aa2fc19cc7cf5cb6323aa29ac695c7a3e5935c Mon Sep 17 00:00:00 2001 From: Chumva Date: Fri, 20 Apr 2018 20:15:36 +0300 Subject: [PATCH 02/38] fix night mode --- .../net/osmand/plus/wikivoyage/explore/ExploreTabFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/ExploreTabFragment.java b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/ExploreTabFragment.java index b6f46e7255..7c5014308f 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/ExploreTabFragment.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/ExploreTabFragment.java @@ -21,7 +21,7 @@ public class ExploreTabFragment extends BaseOsmAndFragment { @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { OsmandApplication app = getMyApplication(); - boolean nightMode = app.getDaynightHelper().isNightModeForMapControls(); + boolean nightMode = app.getDaynightHelper().isNightMode(); final View mainView = inflater.inflate(R.layout.fragment_explore_tab, container, false); From eb484d2486491aaac45632285d77b32884e21a44 Mon Sep 17 00:00:00 2001 From: PaulStets Date: Sat, 21 Apr 2018 16:07:11 +0300 Subject: [PATCH 03/38] Wiki links dialog --- .../wikivoyage_wikipedia_link_dialog.xml | 160 ++++++++++++++++++ OsmAnd/res/values/strings.xml | 4 + .../plus/resources/ResourceManager.java | 15 +- .../wikivoyage/WikivoyageWebViewClient.java | 90 ++++++++-- .../WikivoyageArticleWikiLinkFragment.java | 125 ++++++++++++++ 5 files changed, 383 insertions(+), 11 deletions(-) create mode 100644 OsmAnd/res/layout/wikivoyage_wikipedia_link_dialog.xml create mode 100644 OsmAnd/src/net/osmand/plus/wikivoyage/article/WikivoyageArticleWikiLinkFragment.java diff --git a/OsmAnd/res/layout/wikivoyage_wikipedia_link_dialog.xml b/OsmAnd/res/layout/wikivoyage_wikipedia_link_dialog.xml new file mode 100644 index 0000000000..65968a6148 --- /dev/null +++ b/OsmAnd/res/layout/wikivoyage_wikipedia_link_dialog.xml @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index 7a5379661e..a3704db35c 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -2839,4 +2839,8 @@ Location has no name Tunnel ahead Tunnels + Download the Wikipedia articles for %1$s to read them offline. + Download Wikipedia data + Open article online + View this article in a browser. diff --git a/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java b/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java index a41fbfea9b..a55fbc7ae1 100644 --- a/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java +++ b/OsmAnd/src/net/osmand/plus/resources/ResourceManager.java @@ -850,7 +850,20 @@ public class ResourceManager { } return map; } - + + public List getWikiAmenityRepository(double lat, double lon) { + List repos = new ArrayList<>(); + for (String filename : amenityRepositories.keySet()) { + if (filename.contains("_wiki") + || filename.contains(IndexConstants.BINARY_WIKI_MAP_INDEX_EXT)) { + AmenityIndexRepository repository = amenityRepositories.get(filename); + if (repository.checkContains(lat, lon) && repository instanceof AmenityIndexRepositoryBinary) { + repos.add((AmenityIndexRepositoryBinary) repository); + } + } + } + return repos; + } ////////////////////////////////////////////// Working with address /////////////////////////////////////////// diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/WikivoyageWebViewClient.java b/OsmAnd/src/net/osmand/plus/wikivoyage/WikivoyageWebViewClient.java index 705a6fc14e..e3f90ebe40 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/WikivoyageWebViewClient.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/WikivoyageWebViewClient.java @@ -5,27 +5,44 @@ import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.net.Uri; +import android.support.annotation.NonNull; +import android.support.v4.app.Fragment; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; import android.support.v7.app.AlertDialog; +import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.webkit.WebView; import android.webkit.WebViewClient; +import net.osmand.binary.BinaryMapDataObject; +import net.osmand.binary.BinaryMapIndexReader; +import net.osmand.data.Amenity; import net.osmand.data.PointDescription; +import net.osmand.data.QuadRect; +import net.osmand.map.OsmandRegions; +import net.osmand.osm.PoiCategory; import net.osmand.plus.GPXUtilities; import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandSettings; import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.mapcontextmenu.WikipediaDialogFragment; +import net.osmand.plus.resources.AmenityIndexRepository; +import net.osmand.plus.resources.AmenityIndexRepositoryBinary; import net.osmand.plus.wikivoyage.article.WikivoyageArticleDialogFragment; +import net.osmand.plus.wikivoyage.article.WikivoyageArticleWikiLinkFragment; import net.osmand.plus.wikivoyage.data.TravelArticle; import net.osmand.plus.wikivoyage.explore.WikivoyageExploreDialogFragment; +import net.osmand.util.MapUtils; import java.io.File; +import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.List; import static android.support.v4.app.FragmentManager.POP_BACK_STACK_INCLUSIVE; @@ -37,6 +54,7 @@ import static android.support.v4.app.FragmentManager.POP_BACK_STACK_INCLUSIVE; public class WikivoyageWebViewClient extends WebViewClient { private static final String TAG = WikivoyageWebViewClient.class.getSimpleName(); + private static final String REGIONS_OCBF = "regions.ocbf"; private OsmandApplication app; private FragmentManager fragmentManager; @@ -47,7 +65,8 @@ public class WikivoyageWebViewClient extends WebViewClient { private static final String PREFIX_GEO = "geo:"; private static final String PAGE_PREFIX_HTTP = "http://"; private static final String PAGE_PREFIX_HTTPS = "https://"; - private static final String WEB_DOMAIN = ".wikivoyage.com/wiki/"; + private static final String WIKIVOAYAGE_DOMAIN = ".wikivoyage.com/wiki/"; + private static final String WIKI_DOMAIN = ".wikipedia.org/wiki/"; public WikivoyageWebViewClient(FragmentActivity context, FragmentManager fm, boolean nightMode) { app = (OsmandApplication) context.getApplication(); @@ -58,15 +77,9 @@ public class WikivoyageWebViewClient extends WebViewClient { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { - if (url.contains(WEB_DOMAIN)) { - String lang = url.substring(url.startsWith(PAGE_PREFIX_HTTPS) ? PAGE_PREFIX_HTTPS.length() : 0, url.indexOf(".")); - String articleName = url.replace(PAGE_PREFIX_HTTPS + lang + WEB_DOMAIN, "") - .replaceAll("_", " "); - try { - articleName = URLDecoder.decode(articleName, "UTF-8"); - } catch (UnsupportedEncodingException e) { - Log.w(TAG, e.getMessage(), e); - } + if (url.contains(WIKIVOAYAGE_DOMAIN)) { + String lang = getLang(url); + String articleName = getArticleNameFromUrl(url, lang); long articleId = app.getTravelDbHelper().getArticleId(articleName, lang); if (articleId != 0) { WikivoyageArticleDialogFragment.showInstance(app, fragmentManager, articleId, lang); @@ -74,6 +87,9 @@ public class WikivoyageWebViewClient extends WebViewClient { warnAboutExternalLoad(url); } return true; + } else if (url.contains(WIKI_DOMAIN)) { + String articleName = getArticleNameFromUrl(url, getLang(url)); + getWikiArticle(articleName, url); } else if (url.startsWith(PAGE_PREFIX_HTTP) || url.startsWith(PAGE_PREFIX_HTTPS)) { warnAboutExternalLoad(url); } else if (url.startsWith(PREFIX_GEO)) { @@ -120,6 +136,23 @@ public class WikivoyageWebViewClient extends WebViewClient { return true; } + @NonNull + private String getLang(String url) { + return url.substring(url.startsWith(PAGE_PREFIX_HTTPS) ? PAGE_PREFIX_HTTPS.length() : 0, url.indexOf(".")); + } + + private String getArticleNameFromUrl(String url, String lang) { + String domain = url.contains(WIKIVOAYAGE_DOMAIN) ? WIKIVOAYAGE_DOMAIN : WIKI_DOMAIN; + String articleName = url.replace(PAGE_PREFIX_HTTPS + lang + domain, "") + .replaceAll("_", " "); + try { + articleName = URLDecoder.decode(articleName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + Log.w(TAG, e.getMessage(), e); + } + return articleName; + } + private void warnAboutExternalLoad(final String url) { new AlertDialog.Builder(context) .setTitle(url) @@ -137,4 +170,41 @@ public class WikivoyageWebViewClient extends WebViewClient { public void setArticle(TravelArticle article) { this.article = article; } + + protected void getWikiArticle(String name, String url) { + List found = new ArrayList<>(); + List indexes = app.getResourceManager() + .getWikiAmenityRepository(article.getLat(), article.getLon()); + if (indexes.isEmpty()) { + String reg = ""; + try { + reg = getRegion(article.getLat(), article.getLon()); + } catch (IOException e) { + Log.e(TAG, e.getMessage(), e); + } + WikivoyageArticleWikiLinkFragment.showInstance(fragmentManager, reg, url); + } else { + for (AmenityIndexRepositoryBinary repo : indexes) { + found.addAll(repo.searchAmenitiesByName(0, 0, 0, 0, + Integer.MAX_VALUE, Integer.MAX_VALUE, name, null)); + } + WikipediaDialogFragment.showInstance((AppCompatActivity) context, found.get(0)); + } + + } + + private String getRegion(double lat, double lon) throws IOException { + OsmandRegions regions = new OsmandRegions(); + regions.prepareFile(app.getAppPath(REGIONS_OCBF).getAbsolutePath()); + regions.cacheAllCountries(); + int x31 = MapUtils.get31TileNumberX(lon); + int y31 = MapUtils.get31TileNumberY(lat); + List cs = regions.query(x31, y31); + for (BinaryMapDataObject b : cs) { + if(regions.contain(b, x31, y31)) { + return regions.getFullName(b); + } + } + return ""; + } } diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/article/WikivoyageArticleWikiLinkFragment.java b/OsmAnd/src/net/osmand/plus/wikivoyage/article/WikivoyageArticleWikiLinkFragment.java new file mode 100644 index 0000000000..c8d17d120a --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/article/WikivoyageArticleWikiLinkFragment.java @@ -0,0 +1,125 @@ +package net.osmand.plus.wikivoyage.article; + +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentActivity; +import android.support.v4.app.FragmentManager; +import android.view.ContextThemeWrapper; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import net.osmand.plus.R; +import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.base.MenuBottomSheetDialogFragment; +import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem; +import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem; +import net.osmand.plus.mapcontextmenu.WikipediaDialogFragment; + +public class WikivoyageArticleWikiLinkFragment extends MenuBottomSheetDialogFragment { + + public static final String TAG = WikivoyageArticleWikiLinkFragment.class.getSimpleName(); + + public static final String ARTICLE_URL_KEY = "article_url"; + private static final String WIKI_REGION = "region"; + + private String articleUrl; + private String wikiRegion; + + @Override + public void createMenuItems(Bundle savedInstanceState) { + Context ctx = getContext(); + if (ctx == null) { + return; + } + if (savedInstanceState != null) { + articleUrl = savedInstanceState.getString(ARTICLE_URL_KEY); + wikiRegion = savedInstanceState.getString(WIKI_REGION); + } else { + Bundle args = getArguments(); + if (args != null) { + articleUrl = args.getString(ARTICLE_URL_KEY); + wikiRegion = args.getString(WIKI_REGION); + } + } + items.add(new TitleItem("How to open Wikipedia articles?\n" + articleUrl)); + final int themeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme; + final View wikiLinkDialog = View.inflate(new ContextThemeWrapper(getContext(), themeRes), + R.layout.wikivoyage_wikipedia_link_dialog, null); + + LinearLayout downloadWikiSection = wikiLinkDialog.findViewById(R.id.download_wikimaps); + LinearLayout openOnlineSection = wikiLinkDialog.findViewById(R.id.view_in_browser); + + downloadWikiSection.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + MapActivity mapActivity = (MapActivity) getActivity(); + Intent newIntent = new Intent(mapActivity, mapActivity.getMyApplication().getAppCustomization() + .getDownloadActivity()); + newIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); + mapActivity.startActivity(newIntent); + } + }); + + openOnlineSection.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + WikipediaDialogFragment.showFullArticle(getContext(), Uri.parse(articleUrl), nightMode); + } + }); + + TextView tw = wikiLinkDialog.findViewById(R.id.content_download); + tw.setText(ctx.getString(R.string.download_wikipedia_description, wikiRegion)); + + ImageView downloadWiki = wikiLinkDialog.findViewById(R.id.icon_download); + ImageView openInBrowser = wikiLinkDialog.findViewById(R.id.icon_browser); + + downloadWiki.setImageDrawable(getIcon(R.drawable.ic_action_import, nightMode + ? R.color.wikivoyage_contents_parent_icon_dark : R.color.wikivoyage_contents_parent_icon_light)); + openInBrowser.setImageDrawable(getIcon(R.drawable.ic_browse_map, nightMode + ? R.color.wikivoyage_contents_parent_icon_dark : R.color.wikivoyage_contents_parent_icon_light)); + + items.add(new SimpleBottomSheetItem.Builder().setCustomView(wikiLinkDialog).create()); + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putString(ARTICLE_URL_KEY, articleUrl); + outState.putString(WIKI_REGION, wikiRegion); + } + + @Override + protected boolean useScrollableItemsContainer() { + return false; + } + + @Override + protected int getBgColorId() { + return nightMode ? R.color.wikivoyage_bottom_bar_bg_dark : R.color.bg_color_light; + } + + public static boolean showInstance(@NonNull FragmentManager fm, + @NonNull String region, + @NonNull String articleUrl) { + try { + Bundle args = new Bundle(); + args.putString(ARTICLE_URL_KEY, articleUrl); + args.putString(WIKI_REGION, region); + WikivoyageArticleWikiLinkFragment fragment = new WikivoyageArticleWikiLinkFragment(); + + fragment.setArguments(args); + fragment.show(fm, TAG); + return true; + } catch (RuntimeException e) { + return false; + } + } +} From 6ae461ff2064c13534b261119f35d68c6c8777e1 Mon Sep 17 00:00:00 2001 From: Chumva Date: Mon, 23 Apr 2018 13:42:02 +0300 Subject: [PATCH 04/38] delete builder for cards --- ...card.xml => wikivoyage_open_beta_card.xml} | 2 +- .../layout/wikivoyage_start_editing_card.xml | 6 +- .../explore/ExploreTabFragment.java | 22 +- .../explore/travelcards/BaseTravelCard.java | 243 ++++-------------- .../travelcards/OpenBetaTravelCard.java | 90 +++++++ .../travelcards/StartEditingTravelCard.java | 96 +++++++ 6 files changed, 243 insertions(+), 216 deletions(-) rename OsmAnd/res/layout/{wikivoyage_base_card.xml => wikivoyage_open_beta_card.xml} (93%) create mode 100644 OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/OpenBetaTravelCard.java create mode 100644 OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java diff --git a/OsmAnd/res/layout/wikivoyage_base_card.xml b/OsmAnd/res/layout/wikivoyage_open_beta_card.xml similarity index 93% rename from OsmAnd/res/layout/wikivoyage_base_card.xml rename to OsmAnd/res/layout/wikivoyage_open_beta_card.xml index 53aa729cd3..833e48bb06 100644 --- a/OsmAnd/res/layout/wikivoyage_base_card.xml +++ b/OsmAnd/res/layout/wikivoyage_open_beta_card.xml @@ -42,7 +42,7 @@ android:layout_marginLeft="@dimen/list_content_padding" android:layout_marginRight="@dimen/list_content_padding" android:layout_marginStart="@dimen/list_content_padding" - tools:text="Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard." /> + tools:text="@string/welcome_to_open_beta_description" /> + android:textColor="@color/primary_text_dark" + tools:text="@string/start_editing_card_image_text" /> @@ -51,7 +51,7 @@ android:layout_marginRight="@dimen/list_content_padding" android:layout_marginStart="@dimen/list_content_padding" android:layout_marginTop="@dimen/list_content_padding" - android:text="@string/start_editing_card_description" /> + tools:text="@string/start_editing_card_description" /> items = new ArrayList<>(); - BaseTravelCard openBeta = new BaseTravelCard.Builder() - .setLayoutId(R.layout.wikivoyage_base_card) - .setBackgroundImage(getIconsCache().getIcon(R.drawable.img_help_wikivoyage_articles)) - .setLeftButtonText(getString(R.string.get_unlimited_access)) - .setDescription(getString(R.string.welcome_to_open_beta_description)) - .setTitle(getString(R.string.welcome_to_open_beta)) - .create(); - items.add(openBeta); - - BaseTravelCard startEditing = new BaseTravelCard.Builder() - .setLayoutId(R.layout.wikivoyage_start_editing_card) - .setBackgroundImage(getIconsCache().getIcon(R.drawable.img_help_wikivoyage_contribute)) - .setLeftButtonText(getString(R.string.start_editing)) - .setDescription(getString(R.string.start_editing_card_description)) - .create(); - items.add(startEditing); + BaseTravelCard openBetaTravelCard = new OpenBetaTravelCard(getMyActivity()); + BaseTravelCard startEditingTravelCard = new StartEditingTravelCard(getMyActivity()); + items.add(openBetaTravelCard); + items.add(startEditingTravelCard); for (BaseTravelCard item : items) { item.inflate(app, linearLayout, nightMode); diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/BaseTravelCard.java b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/BaseTravelCard.java index 47ace4950d..0f3a43df2c 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/BaseTravelCard.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/BaseTravelCard.java @@ -3,231 +3,82 @@ package net.osmand.plus.wikivoyage.explore.travelcards; import android.graphics.drawable.Drawable; import android.support.annotation.ColorInt; import android.support.annotation.ColorRes; +import android.support.annotation.DrawableRes; import android.support.annotation.LayoutRes; +import android.support.annotation.StringRes; import android.support.v4.content.ContextCompat; -import android.view.ContextThemeWrapper; -import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.TextView; import net.osmand.plus.OsmandApplication; -import net.osmand.plus.R; +import net.osmand.plus.activities.OsmandActionBarActivity; -public class BaseTravelCard { +public abstract class BaseTravelCard { - private static final int INVALID_POSITION = -1; - private static final int DEFAULT_VALUE = -1; + protected static final int INVALID_POSITION = -1; + protected static final int DEFAULT_VALUE = -1; protected View view; - private View.OnClickListener onLeftButtonClickListener; - private View.OnClickListener onRightButtonClickListener; + protected OsmandActionBarActivity activity; - @LayoutRes - protected int layoutId; - @ColorRes - protected int bottomDividerColorId; + protected int position = INVALID_POSITION; - private Object tag; - private OsmandApplication app; + public abstract void inflate(OsmandApplication app, ViewGroup container, boolean nightMode); - protected Drawable image; - protected String rightBottomButtonText; - protected String leftBottomButtonText; - protected String description; - protected String title; - - protected int position; - - public View getView() { - return view; - } - - public Object getTag() { - return tag; - } - - public BaseTravelCard(View view, - @LayoutRes int layoutId, - Object tag, - Drawable image, - View.OnClickListener onLeftButtonClickListener, - View.OnClickListener onRightButtonClickListener, - int position, - String rightBottomButtonText, - String leftBottomButtonText, - @ColorRes int bottomDividerColorId, - String description, - String title) { - this.view = view; - this.layoutId = layoutId; - this.image = image; - this.tag = tag; - this.onLeftButtonClickListener = onLeftButtonClickListener; - this.onRightButtonClickListener = onRightButtonClickListener; - this.position = position; - this.rightBottomButtonText = rightBottomButtonText; - this.leftBottomButtonText = leftBottomButtonText; - this.bottomDividerColorId = bottomDividerColorId; - this.description = description; - this.title = title; - } - - protected BaseTravelCard() { - - } - - public void inflate(OsmandApplication app, ViewGroup container, boolean nightMode) { - View view = getView(app, container, nightMode); - if (image != null) { - ImageView imageView = (ImageView) view.findViewById(R.id.background_image); - imageView.setImageDrawable(image); - } - if (title != null) { - ((TextView) view.findViewById(R.id.title)).setText(title); - } - if (description != null) { - ((TextView) view.findViewById(R.id.description)).setText(description); - } - if (bottomDividerColorId != DEFAULT_VALUE) { - view.findViewById(R.id.bottom_divider).setBackgroundColor(getResolvedColor(bottomDividerColorId)); - } - if (leftBottomButtonText != null) { - view.findViewById(R.id.left_bottom_button).setOnClickListener(onLeftButtonClickListener); - ((TextView) view.findViewById(R.id.left_bottom_button_text)).setText(leftBottomButtonText); - } - if (rightBottomButtonText != null) { - - if (bottomDividerColorId != DEFAULT_VALUE) { - View buttonsDivider = view.findViewById(R.id.bottom_buttons_divider); - buttonsDivider.setVisibility(View.VISIBLE); - buttonsDivider.setBackgroundColor(getResolvedColor(bottomDividerColorId)); - } - - View rightButton = view.findViewById(R.id.right_bottom_button); - rightButton.setVisibility(View.VISIBLE); - rightButton.setOnClickListener(onRightButtonClickListener); - ((TextView) rightButton.findViewById(R.id.right_bottom_button_text)).setText(rightBottomButtonText); - } - if (position != INVALID_POSITION) { - container.addView(view, position); - } else { - container.addView(view); - } - } - - private View getView(OsmandApplication app, ViewGroup parent, boolean nightMode) { - if (view != null) { - return view; - } - this.app = app; - if (layoutId != DEFAULT_VALUE) { - final int themeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme; - return view = LayoutInflater.from(new ContextThemeWrapper(app, themeRes)) - .inflate(layoutId, parent, false); - } - throw new RuntimeException("BaseTravelCard must have specified view or layoutId."); - } + protected abstract View getView(OsmandApplication app, ViewGroup parent, boolean nightMode); @ColorInt protected int getResolvedColor(@ColorRes int colorId) { - return ContextCompat.getColor(app, colorId); + return ContextCompat.getColor(activity, colorId); } - public static class Builder { + protected Drawable getIcon(@DrawableRes int drawableRes, @ColorRes int color) { + return activity.getMyApplication().getIconsCache().getIcon(drawableRes, color); + } - protected View customView; - protected View.OnClickListener onLeftButtonClickListener; - protected View.OnClickListener onRightButtonClickListener; + protected Drawable getBackgroundIcon(@DrawableRes int drawableRes) { + return activity.getMyApplication().getIconsCache().getIcon(drawableRes); + } - @LayoutRes - protected int layoutId = DEFAULT_VALUE; - @ColorRes - protected int dividerColorId = DEFAULT_VALUE; + @StringRes + protected int getTitleId() { + return DEFAULT_VALUE; + } - protected Drawable image; - protected String rightBottomButtonText; - protected String leftBottomButtonText; - protected String description; - protected String title; - protected Object tag; + @StringRes + protected int getDescriptionId() { + return DEFAULT_VALUE; + } - protected int position = INVALID_POSITION; + @StringRes + protected int getLeftButtonTextId() { + return DEFAULT_VALUE; + } - public Builder setCustomView(View customView) { - this.customView = customView; - return this; - } + protected void onLeftButtonClickAction() { - public Builder setTag(Object tag) { - this.tag = tag; - return this; - } + } - public Builder setLayoutId(@LayoutRes int layoutId) { - this.layoutId = layoutId; - return this; - } + @StringRes + protected int getRightButtonTextId() { + return DEFAULT_VALUE; + } - public Builder setBackgroundImage(Drawable image) { - this.image = image; - return this; - } + protected void onRightButtonClickAction() { - public Builder setOnLeftButtonClickListener(View.OnClickListener onLeftButtonClickListener) { - this.onLeftButtonClickListener = onLeftButtonClickListener; - return this; - } + } - public Builder setOnRightButtonClickListener(View.OnClickListener onRightButtonClickListener) { - this.onRightButtonClickListener = onRightButtonClickListener; - return this; - } + @ColorRes + protected int getBottomDividerColorId() { + return DEFAULT_VALUE; + } - public Builder setRightButtonText(String rightBottomButtonText) { - this.rightBottomButtonText = rightBottomButtonText; - return this; - } + @LayoutRes + protected int getLayoutId() { + return DEFAULT_VALUE; + } - public Builder setLeftButtonText(String leftBottomButtonText) { - this.leftBottomButtonText = leftBottomButtonText; - return this; - } - - public Builder setTitle(String title) { - this.title = title; - return this; - } - - public Builder setDescription(String description) { - this.description = description; - return this; - } - - public Builder setPosition(int position) { - this.position = position; - return this; - } - - public Builder setBottomDividerColorId(@ColorRes int dividerColorId) { - this.dividerColorId = dividerColorId; - return this; - } - - public BaseTravelCard create() { - return new BaseTravelCard(customView, - layoutId, - tag, - image, - onLeftButtonClickListener, - onRightButtonClickListener, - position, - rightBottomButtonText, - leftBottomButtonText, - dividerColorId, - description, - title); - } + protected boolean isNightMode() { + return !activity.getMyApplication().getSettings().isLightContent(); } } diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/OpenBetaTravelCard.java b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/OpenBetaTravelCard.java new file mode 100644 index 0000000000..6e1ef1a1ba --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/OpenBetaTravelCard.java @@ -0,0 +1,90 @@ +package net.osmand.plus.wikivoyage.explore.travelcards; + +import android.graphics.drawable.Drawable; +import android.view.ContextThemeWrapper; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.R; +import net.osmand.plus.activities.OsmandActionBarActivity; +import net.osmand.plus.dialogs.ChoosePlanDialogFragment; + +public class OpenBetaTravelCard extends BaseTravelCard { + + + public OpenBetaTravelCard(OsmandActionBarActivity activity) { + this.activity = activity; + } + + public OpenBetaTravelCard(OsmandActionBarActivity activity, int position) { + this.activity = activity; + this.position = position; + } + + @Override + public void inflate(OsmandApplication app, ViewGroup container, boolean nightMode) { + View view = getView(app, container, isNightMode()); + ImageView imageView = (ImageView) view.findViewById(R.id.background_image); + imageView.setImageDrawable(getBackgroundIcon(R.drawable.img_help_wikivoyage_articles)); + ((TextView) view.findViewById(R.id.title)).setText(getTitleId()); + ((TextView) view.findViewById(R.id.description)).setText(getDescriptionId()); + + ((TextView) view.findViewById(R.id.left_bottom_button_text)).setText(getLeftButtonTextId()); + + view.findViewById(R.id.left_bottom_button).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + onLeftButtonClickAction(); + } + }); + if (position != INVALID_POSITION) { + container.addView(view, position); + } else { + container.addView(view); + } + } + + protected View getView(OsmandApplication app, ViewGroup parent, boolean nightMode) { + if (view != null) { + return view; + } + final int themeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme; + return view = LayoutInflater.from(new ContextThemeWrapper(app, themeRes)) + .inflate(getLayoutId(), parent, false); + } + + @Override + protected int getTitleId() { + return R.string.welcome_to_open_beta; + } + + @Override + protected int getDescriptionId() { + return R.string.welcome_to_open_beta_description; + } + + @Override + protected Drawable getBackgroundIcon(int drawableRes) { + return super.getBackgroundIcon(drawableRes); + } + + @Override + protected int getLayoutId() { + return R.layout.wikivoyage_open_beta_card; + } + + @Override + protected int getLeftButtonTextId() { + return R.string.get_unlimited_access; + } + + @Override + protected void onLeftButtonClickAction() { + ChoosePlanDialogFragment.showFreeVersionInstance(activity.getSupportFragmentManager()); + + } +} diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java new file mode 100644 index 0000000000..5d0d89b689 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java @@ -0,0 +1,96 @@ +package net.osmand.plus.wikivoyage.explore.travelcards; + + +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.support.customtabs.CustomTabsIntent; +import android.support.v4.content.ContextCompat; +import android.view.ContextThemeWrapper; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.R; +import net.osmand.plus.activities.OsmandActionBarActivity; + +public class StartEditingTravelCard extends BaseTravelCard { + + public StartEditingTravelCard(OsmandActionBarActivity activity) { + this.activity = activity; + + } + + public StartEditingTravelCard(OsmandActionBarActivity activity, int position) { + this.activity = activity; + this.position = position; + } + + @Override + public void inflate(OsmandApplication app, ViewGroup container, boolean nightMode) { + View view = getView(app, container, isNightMode()); + ImageView imageView = (ImageView) view.findViewById(R.id.background_image); + imageView.setImageDrawable(getBackgroundIcon(R.drawable.img_help_wikivoyage_contribute)); + ((TextView) view.findViewById(R.id.title)).setText(getTitleId()); + ((TextView) view.findViewById(R.id.description)).setText(getDescriptionId()); + + ((TextView) view.findViewById(R.id.left_bottom_button_text)).setText(getLeftButtonTextId()); + + view.findViewById(R.id.left_bottom_button).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + onLeftButtonClickAction(); + } + }); + if (position != INVALID_POSITION) { + container.addView(view, position); + } else { + container.addView(view); + } + } + + protected View getView(OsmandApplication app, ViewGroup parent, boolean nightMode) { + if (view != null) { + return view; + } + final int themeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme; + return view = LayoutInflater.from(new ContextThemeWrapper(app, themeRes)) + .inflate(getLayoutId(), parent, false); + } + + @Override + protected int getTitleId() { + return R.string.start_editing_card_image_text; + } + + @Override + protected int getDescriptionId() { + return R.string.start_editing_card_description; + } + + @Override + protected Drawable getBackgroundIcon(int drawableRes) { + return super.getBackgroundIcon(drawableRes); + } + + @Override + protected int getLayoutId() { + return R.layout.wikivoyage_start_editing_card; + } + + @Override + protected int getLeftButtonTextId() { + return R.string.start_editing; + } + + @Override + protected void onLeftButtonClickAction() { + CustomTabsIntent customTabsIntent = new CustomTabsIntent.Builder() + .setToolbarColor(ContextCompat.getColor(activity, isNightMode() ? R.color.actionbar_dark_color : R.color.actionbar_light_color)) + .build(); + String text = "https://" + activity.getMyApplication().getLanguage().toLowerCase() + ".m.wikivoyage.org"; + customTabsIntent.launchUrl(activity, Uri.parse(text)); + } +} From fdb8977197eb96ac2468ab1b625992898d00c5cc Mon Sep 17 00:00:00 2001 From: Chumva Date: Mon, 23 Apr 2018 14:00:55 +0300 Subject: [PATCH 05/38] removed unnecessary xml changes --- OsmAnd/res/layout/fragment_explore_tab.xml | 7 +++---- OsmAnd/res/layout/wikivoyage_start_editing_card.xml | 1 - OsmAnd/res/values/strings.xml | 12 ++++++------ 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/OsmAnd/res/layout/fragment_explore_tab.xml b/OsmAnd/res/layout/fragment_explore_tab.xml index 0b0bbb1324..34316e6ef0 100644 --- a/OsmAnd/res/layout/fragment_explore_tab.xml +++ b/OsmAnd/res/layout/fragment_explore_tab.xml @@ -1,6 +1,6 @@ - + android:paddingBottom="@dimen/map_markers_recycler_view_padding_bottom"> diff --git a/OsmAnd/res/layout/wikivoyage_start_editing_card.xml b/OsmAnd/res/layout/wikivoyage_start_editing_card.xml index 7530aa594f..ca8c968c90 100644 --- a/OsmAnd/res/layout/wikivoyage_start_editing_card.xml +++ b/OsmAnd/res/layout/wikivoyage_start_editing_card.xml @@ -1,6 +1,5 @@ + The free worldwide travel guide that anyone can edit. + Travel is based on Wikivoyage. During open beta testing you have the opportunity to evaluate all the features for free. After the end of the beta period, Travel will be available to subscribers of OsmAnd Unlimited and the owners of OsmAnd+ + You can edit any article on Wikivoyage, and we hope that you do. We need your knowledge, your experience, your talent, and your attention + Start editing + Get unlimited access + Welcome, to the open beta! Travel Guide Browse the Wikivoyage guides to the most interesting places on the planet inside OsmAnd without an internet connection. Map updates: every month @@ -26,12 +32,6 @@ Contour lines + Sea depth Unlock all OsmAnd features - The free worldwide travel guide that anyone can edit. - Travel is based on Wikivoyage. During open beta testing you have the opportunity to evaluate all the features for free. After the end of the beta period, Travel will be available to subscribers of OsmAnd Unlimited and the owners of OsmAnd+ - You can edit any article on Wikivoyage, and we hope that you do. We need your knowledge, your experience, your talent, and your attention - Start editing - Get unlimited access - Welcome, to the open beta! Choose plan To read Travel articles offline, you need to purchase one of the following items. Choose suitable item: From 5446665d886b9a616915b56d464272e7002d5d35 Mon Sep 17 00:00:00 2001 From: PaulStets Date: Mon, 23 Apr 2018 14:18:42 +0300 Subject: [PATCH 06/38] Wiki links menu and behavior improvements --- .../wikivoyage_wikipedia_link_dialog.xml | 160 ------------------ OsmAnd/res/values/strings.xml | 3 + .../wikivoyage/WikivoyageWebViewClient.java | 95 ++++++++--- .../WikivoyageArticleWikiLinkFragment.java | 89 ++++++---- 4 files changed, 128 insertions(+), 219 deletions(-) delete mode 100644 OsmAnd/res/layout/wikivoyage_wikipedia_link_dialog.xml diff --git a/OsmAnd/res/layout/wikivoyage_wikipedia_link_dialog.xml b/OsmAnd/res/layout/wikivoyage_wikipedia_link_dialog.xml deleted file mode 100644 index 65968a6148..0000000000 --- a/OsmAnd/res/layout/wikivoyage_wikipedia_link_dialog.xml +++ /dev/null @@ -1,160 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index 575d96ca6c..27e174ae2b 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -2856,4 +2856,7 @@ Download Wikipedia data Open article online View this article in a browser. + this region + Searching for the necessary wiki article + Article not found diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/WikivoyageWebViewClient.java b/OsmAnd/src/net/osmand/plus/wikivoyage/WikivoyageWebViewClient.java index e3f90ebe40..6bef80faee 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/WikivoyageWebViewClient.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/WikivoyageWebViewClient.java @@ -1,12 +1,15 @@ package net.osmand.plus.wikivoyage; +import android.app.Activity; +import android.app.Dialog; +import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.net.Uri; +import android.os.AsyncTask; import android.support.annotation.NonNull; -import android.support.v4.app.Fragment; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; import android.support.v7.app.AlertDialog; @@ -14,21 +17,20 @@ import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.webkit.WebView; import android.webkit.WebViewClient; +import android.widget.Toast; import net.osmand.binary.BinaryMapDataObject; -import net.osmand.binary.BinaryMapIndexReader; import net.osmand.data.Amenity; import net.osmand.data.PointDescription; -import net.osmand.data.QuadRect; import net.osmand.map.OsmandRegions; -import net.osmand.osm.PoiCategory; import net.osmand.plus.GPXUtilities; import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandSettings; import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.dialogs.ProgressDialogFragment; import net.osmand.plus.mapcontextmenu.WikipediaDialogFragment; -import net.osmand.plus.resources.AmenityIndexRepository; +import net.osmand.plus.quickaction.actions.FavoriteAction; import net.osmand.plus.resources.AmenityIndexRepositoryBinary; import net.osmand.plus.wikivoyage.article.WikivoyageArticleDialogFragment; import net.osmand.plus.wikivoyage.article.WikivoyageArticleWikiLinkFragment; @@ -39,10 +41,9 @@ import net.osmand.util.MapUtils; import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; +import java.lang.ref.WeakReference; import java.net.URLDecoder; import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; import java.util.List; import static android.support.v4.app.FragmentManager.POP_BACK_STACK_INCLUSIVE; @@ -54,7 +55,6 @@ import static android.support.v4.app.FragmentManager.POP_BACK_STACK_INCLUSIVE; public class WikivoyageWebViewClient extends WebViewClient { private static final String TAG = WikivoyageWebViewClient.class.getSimpleName(); - private static final String REGIONS_OCBF = "regions.ocbf"; private OsmandApplication app; private FragmentManager fragmentManager; @@ -172,7 +172,6 @@ public class WikivoyageWebViewClient extends WebViewClient { } protected void getWikiArticle(String name, String url) { - List found = new ArrayList<>(); List indexes = app.getResourceManager() .getWikiAmenityRepository(article.getLat(), article.getLon()); if (indexes.isEmpty()) { @@ -184,27 +183,77 @@ public class WikivoyageWebViewClient extends WebViewClient { } WikivoyageArticleWikiLinkFragment.showInstance(fragmentManager, reg, url); } else { - for (AmenityIndexRepositoryBinary repo : indexes) { - found.addAll(repo.searchAmenitiesByName(0, 0, 0, 0, - Integer.MAX_VALUE, Integer.MAX_VALUE, name, null)); - } - WikipediaDialogFragment.showInstance((AppCompatActivity) context, found.get(0)); + new WikiArticleSearchTask(name, indexes, (MapActivity) context).execute(); } } private String getRegion(double lat, double lon) throws IOException { - OsmandRegions regions = new OsmandRegions(); - regions.prepareFile(app.getAppPath(REGIONS_OCBF).getAbsolutePath()); - regions.cacheAllCountries(); - int x31 = MapUtils.get31TileNumberX(lon); - int y31 = MapUtils.get31TileNumberY(lat); - List cs = regions.query(x31, y31); - for (BinaryMapDataObject b : cs) { - if(regions.contain(b, x31, y31)) { - return regions.getFullName(b); + OsmandRegions osmandRegions = app.getRegions(); + if (osmandRegions != null) { + int x31 = MapUtils.get31TileNumberX(lon); + int y31 = MapUtils.get31TileNumberY(lat); + List cs = osmandRegions.query(x31, y31); + for (BinaryMapDataObject b : cs) { + if(osmandRegions.contain(b, x31, y31)) { + return osmandRegions.getLocaleName(osmandRegions.getDownloadName(b), false); + } } } return ""; } + + private static class WikiArticleSearchTask extends AsyncTask> { + private ProgressDialog dialog; + private String name; + private List indexes; + private WeakReference weakContext; + + WikiArticleSearchTask(String articleName, List indexes, MapActivity context) { + name = articleName; + this.indexes = indexes; + weakContext = new WeakReference<>(context); + dialog = createProgressDialog(); + } + + @Override + protected void onPreExecute() { + if (dialog != null) { + dialog.show(); + } + } + + @Override + protected List doInBackground(Void... voids) { + List found = new ArrayList<>(); + for (AmenityIndexRepositoryBinary repo : indexes) { + found.addAll(repo.searchAmenitiesByName(0, 0, 0, 0, + Integer.MAX_VALUE, Integer.MAX_VALUE, name, null)); + } + return found; + } + + @Override + protected void onPostExecute(List found) { + if (!weakContext.get().isActivityDestroyed()) { + dialog.dismiss(); + if (!found.isEmpty()) { + WikipediaDialogFragment.showInstance((AppCompatActivity) weakContext.get(), found.get(0)); + } else { + Toast.makeText(weakContext.get(), R.string.wiki_article_not_found, Toast.LENGTH_LONG).show(); + } + } + } + + private ProgressDialog createProgressDialog() { + MapActivity activity = weakContext.get(); + if (!activity.isActivityDestroyed()) { + ProgressDialog dialog = new ProgressDialog(activity); + dialog.setCancelable(false); + dialog.setMessage(activity.getString(R.string.wiki_article_search_text)); + return dialog; + } + return null; + } + } } diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/article/WikivoyageArticleWikiLinkFragment.java b/OsmAnd/src/net/osmand/plus/wikivoyage/article/WikivoyageArticleWikiLinkFragment.java index c8d17d120a..902ccde9e8 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/article/WikivoyageArticleWikiLinkFragment.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/article/WikivoyageArticleWikiLinkFragment.java @@ -2,15 +2,12 @@ package net.osmand.plus.wikivoyage.article; import android.content.Context; import android.content.Intent; +import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; import android.view.ContextThemeWrapper; -import android.view.LayoutInflater; import android.view.View; import android.widget.ImageView; import android.widget.LinearLayout; @@ -19,9 +16,15 @@ import android.widget.TextView; import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.base.MenuBottomSheetDialogFragment; +import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem; +import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithDescription; import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem; +import net.osmand.plus.base.bottomsheetmenu.simpleitems.DescriptionItem; +import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerHalfItem; +import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleDividerItem; import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem; import net.osmand.plus.mapcontextmenu.WikipediaDialogFragment; +import net.osmand.plus.osmedit.OsmEditsFragment; public class WikivoyageArticleWikiLinkFragment extends MenuBottomSheetDialogFragment { @@ -49,44 +52,58 @@ public class WikivoyageArticleWikiLinkFragment extends MenuBottomSheetDialogFrag wikiRegion = args.getString(WIKI_REGION); } } - items.add(new TitleItem("How to open Wikipedia articles?\n" + articleUrl)); - final int themeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme; - final View wikiLinkDialog = View.inflate(new ContextThemeWrapper(getContext(), themeRes), - R.layout.wikivoyage_wikipedia_link_dialog, null); + items.add(new TitleItem("How to open Wikipedia articles?")); - LinearLayout downloadWikiSection = wikiLinkDialog.findViewById(R.id.download_wikimaps); - LinearLayout openOnlineSection = wikiLinkDialog.findViewById(R.id.view_in_browser); + BaseBottomSheetItem wikiLinkitem = new TitleItem.Builder().setTitle(articleUrl) + .setTitleColorId(nightMode + ? R.color.wikivoyage_contents_parent_icon_dark : R.color.wikivoyage_contents_parent_icon_light) + .setLayoutId(R.layout.bottom_sheet_item_title) + .create(); + items.add(wikiLinkitem); + items.add(new TitleDividerItem(getContext())); - downloadWikiSection.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - MapActivity mapActivity = (MapActivity) getActivity(); - Intent newIntent = new Intent(mapActivity, mapActivity.getMyApplication().getAppCustomization() - .getDownloadActivity()); - newIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); - mapActivity.startActivity(newIntent); - } - }); + Drawable downloadIcon = getIcon(R.drawable.ic_action_import, nightMode + ? R.color.wikivoyage_contents_parent_icon_dark : R.color.wikivoyage_contents_parent_icon_light); - openOnlineSection.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - WikipediaDialogFragment.showFullArticle(getContext(), Uri.parse(articleUrl), nightMode); - } - }); + Drawable viewOnlineIcon = getIcon(R.drawable.ic_world_globe_dark, nightMode + ? R.color.wikivoyage_contents_parent_icon_dark : R.color.wikivoyage_contents_parent_icon_light); - TextView tw = wikiLinkDialog.findViewById(R.id.content_download); - tw.setText(ctx.getString(R.string.download_wikipedia_description, wikiRegion)); + BaseBottomSheetItem wikiDownloadItem = new BottomSheetItemWithDescription.Builder() + .setDescription(getString(R.string.download_wikipedia_description, wikiRegion.isEmpty() ? + getString(R.string.download_wiki_region_placeholder) : wikiRegion)) + .setIcon(downloadIcon) + .setTitle(getString(R.string.download_wikipedia_label)) + .setLayoutId(R.layout.bottom_sheet_item_with_descr_56dp) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + MapActivity mapActivity = (MapActivity) getActivity(); + Intent newIntent = new Intent(mapActivity, mapActivity.getMyApplication().getAppCustomization() + .getDownloadActivity()); + newIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); + mapActivity.startActivity(newIntent); + dismiss(); + } + }) + .create(); + items.add(wikiDownloadItem); - ImageView downloadWiki = wikiLinkDialog.findViewById(R.id.icon_download); - ImageView openInBrowser = wikiLinkDialog.findViewById(R.id.icon_browser); + items.add(new DividerHalfItem(getContext())); - downloadWiki.setImageDrawable(getIcon(R.drawable.ic_action_import, nightMode - ? R.color.wikivoyage_contents_parent_icon_dark : R.color.wikivoyage_contents_parent_icon_light)); - openInBrowser.setImageDrawable(getIcon(R.drawable.ic_browse_map, nightMode - ? R.color.wikivoyage_contents_parent_icon_dark : R.color.wikivoyage_contents_parent_icon_light)); - - items.add(new SimpleBottomSheetItem.Builder().setCustomView(wikiLinkDialog).create()); + BaseBottomSheetItem wikiArticleOnlineItem = new BottomSheetItemWithDescription.Builder() + .setDescription(getString(R.string.open_in_browser_wiki_description)) + .setIcon(viewOnlineIcon) + .setTitle(getString(R.string.open_in_browser_wiki)) + .setLayoutId(R.layout.bottom_sheet_item_with_descr_56dp) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + WikipediaDialogFragment.showFullArticle(getContext(), Uri.parse(articleUrl), nightMode); + dismiss(); + } + }) + .create(); + items.add(wikiArticleOnlineItem); } @Override From b66a76e2c07a0673e389e883e7874512df2b0bc1 Mon Sep 17 00:00:00 2001 From: Chumva Date: Mon, 23 Apr 2018 15:34:23 +0300 Subject: [PATCH 07/38] delete unnecessary methods and change cards constructors --- OsmAnd/res/drawable/wikivoyage_card_bg.xml | 12 ++++ OsmAnd/res/layout/bottom_buttons.xml | 8 +-- .../res/layout/wikivoyage_open_beta_card.xml | 13 ++-- .../layout/wikivoyage_start_editing_card.xml | 7 +- .../explore/ExploreTabFragment.java | 6 +- .../explore/travelcards/BaseTravelCard.java | 27 ++++---- .../travelcards/OpenBetaTravelCard.java | 65 +++++++------------ .../travelcards/StartEditingTravelCard.java | 59 +++++++---------- 8 files changed, 86 insertions(+), 111 deletions(-) create mode 100644 OsmAnd/res/drawable/wikivoyage_card_bg.xml diff --git a/OsmAnd/res/drawable/wikivoyage_card_bg.xml b/OsmAnd/res/drawable/wikivoyage_card_bg.xml new file mode 100644 index 0000000000..5691ef7ce2 --- /dev/null +++ b/OsmAnd/res/drawable/wikivoyage_card_bg.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/bottom_buttons.xml b/OsmAnd/res/layout/bottom_buttons.xml index 1832c3ecdc..b388724ba9 100644 --- a/OsmAnd/res/layout/bottom_buttons.xml +++ b/OsmAnd/res/layout/bottom_buttons.xml @@ -29,9 +29,8 @@ android:id="@+id/bottom_buttons_divider" android:layout_width="1dp" android:layout_height="match_parent" - android:background="?attr/dashboard_divider" - android:visibility="gone" - tools:visibility="visible" /> + android:background="?attr/wikivoyage_card_divider_color" + android:visibility="visible" /> + android:visibility="visible"> - + android:layout_marginTop="@dimen/list_content_padding" + android:background="@drawable/wikivoyage_card_bg"> @@ -17,7 +18,7 @@ @@ -48,10 +49,10 @@ android:id="@+id/bottom_divider" android:layout_width="match_parent" android:layout_height="1dp" - android:background="?attr/dashboard_divider" /> + android:background="?attr/wikivoyage_card_divider_color" /> - \ No newline at end of file + \ No newline at end of file diff --git a/OsmAnd/res/layout/wikivoyage_start_editing_card.xml b/OsmAnd/res/layout/wikivoyage_start_editing_card.xml index ca8c968c90..a09906a0ea 100644 --- a/OsmAnd/res/layout/wikivoyage_start_editing_card.xml +++ b/OsmAnd/res/layout/wikivoyage_start_editing_card.xml @@ -1,9 +1,10 @@ - @@ -56,10 +57,10 @@ android:id="@+id/bottom_divider" android:layout_width="match_parent" android:layout_height="1dp" - android:background="?attr/dashboard_divider" /> + android:background="?attr/wikivoyage_card_divider_color" /> - \ No newline at end of file + \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/ExploreTabFragment.java b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/ExploreTabFragment.java index 0a5963d525..62eafee287 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/ExploreTabFragment.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/ExploreTabFragment.java @@ -23,15 +23,15 @@ public class ExploreTabFragment extends BaseOsmAndFragment { @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { OsmandApplication app = getMyApplication(); - boolean nightMode = app.getDaynightHelper().isNightMode(); + boolean nightMode = !getSettings().isLightContent(); final View mainView = inflater.inflate(R.layout.fragment_explore_tab, container, false); LinearLayout linearLayout = (LinearLayout) mainView.findViewById(R.id.cards_list); ArrayList items = new ArrayList<>(); - BaseTravelCard openBetaTravelCard = new OpenBetaTravelCard(getMyActivity()); - BaseTravelCard startEditingTravelCard = new StartEditingTravelCard(getMyActivity()); + BaseTravelCard openBetaTravelCard = new OpenBetaTravelCard(app, getFragmentManager(), nightMode); + BaseTravelCard startEditingTravelCard = new StartEditingTravelCard(app, nightMode); items.add(openBetaTravelCard); items.add(startEditingTravelCard); diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/BaseTravelCard.java b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/BaseTravelCard.java index 0f3a43df2c..96477e04d5 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/BaseTravelCard.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/BaseTravelCard.java @@ -11,7 +11,6 @@ import android.view.View; import android.view.ViewGroup; import net.osmand.plus.OsmandApplication; -import net.osmand.plus.activities.OsmandActionBarActivity; public abstract class BaseTravelCard { @@ -19,37 +18,33 @@ public abstract class BaseTravelCard { protected static final int DEFAULT_VALUE = -1; protected View view; - protected OsmandActionBarActivity activity; + protected OsmandApplication app; protected int position = INVALID_POSITION; + protected boolean nightMode; public abstract void inflate(OsmandApplication app, ViewGroup container, boolean nightMode); - protected abstract View getView(OsmandApplication app, ViewGroup parent, boolean nightMode); - @ColorInt protected int getResolvedColor(@ColorRes int colorId) { - return ContextCompat.getColor(activity, colorId); + return ContextCompat.getColor(app, colorId); } protected Drawable getIcon(@DrawableRes int drawableRes, @ColorRes int color) { - return activity.getMyApplication().getIconsCache().getIcon(drawableRes, color); + return app.getIconsCache().getIcon(drawableRes, color); } - protected Drawable getBackgroundIcon(@DrawableRes int drawableRes) { - return activity.getMyApplication().getIconsCache().getIcon(drawableRes); + protected Drawable getIcon(@DrawableRes int drawableRes) { + return app.getIconsCache().getIcon(drawableRes); } - @StringRes - protected int getTitleId() { - return DEFAULT_VALUE; + protected Drawable getPaintedIcon(int iconId, int color) { + return app.getIconsCache().getPaintedIcon(iconId, color); } - @StringRes - protected int getDescriptionId() { - return DEFAULT_VALUE; + protected Drawable getIcon(int iconId, int colorLightId, int colorDarkId) { + return app.getIconsCache().getIcon(iconId, nightMode ? colorLightId : colorDarkId); } - @StringRes protected int getLeftButtonTextId() { return DEFAULT_VALUE; @@ -79,6 +74,6 @@ public abstract class BaseTravelCard { } protected boolean isNightMode() { - return !activity.getMyApplication().getSettings().isLightContent(); + return !app.getSettings().isLightContent(); } } diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/OpenBetaTravelCard.java b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/OpenBetaTravelCard.java index 6e1ef1a1ba..8914aa5377 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/OpenBetaTravelCard.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/OpenBetaTravelCard.java @@ -1,6 +1,7 @@ package net.osmand.plus.wikivoyage.explore.travelcards; import android.graphics.drawable.Drawable; +import android.support.v4.app.FragmentManager; import android.view.ContextThemeWrapper; import android.view.LayoutInflater; import android.view.View; @@ -10,37 +11,44 @@ import android.widget.TextView; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; -import net.osmand.plus.activities.OsmandActionBarActivity; import net.osmand.plus.dialogs.ChoosePlanDialogFragment; public class OpenBetaTravelCard extends BaseTravelCard { + private FragmentManager fm; - - public OpenBetaTravelCard(OsmandActionBarActivity activity) { - this.activity = activity; + public OpenBetaTravelCard(OsmandApplication app, FragmentManager fm, boolean nightMode) { + this.app = app; + this.fm = fm; + this.nightMode = nightMode; } - public OpenBetaTravelCard(OsmandActionBarActivity activity, int position) { - this.activity = activity; + public OpenBetaTravelCard(OsmandApplication app, FragmentManager fm, int position, boolean nightMode) { + this.app = app; + this.fm = fm; this.position = position; + this.nightMode = nightMode; } @Override public void inflate(OsmandApplication app, ViewGroup container, boolean nightMode) { - View view = getView(app, container, isNightMode()); + final int themeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme; + view = LayoutInflater.from(new ContextThemeWrapper(app, themeRes)) + .inflate(R.layout.wikivoyage_open_beta_card, container, false); ImageView imageView = (ImageView) view.findViewById(R.id.background_image); - imageView.setImageDrawable(getBackgroundIcon(R.drawable.img_help_wikivoyage_articles)); - ((TextView) view.findViewById(R.id.title)).setText(getTitleId()); - ((TextView) view.findViewById(R.id.description)).setText(getDescriptionId()); - - ((TextView) view.findViewById(R.id.left_bottom_button_text)).setText(getLeftButtonTextId()); - + imageView.setImageDrawable(getIcon(R.drawable.img_help_wikivoyage_articles)); + ((TextView) view.findViewById(R.id.title)).setText(R.string.welcome_to_open_beta); + ((TextView) view.findViewById(R.id.description)).setText(R.string.welcome_to_open_beta_description); + ((TextView) view.findViewById(R.id.left_bottom_button_text)).setText(R.string.get_unlimited_access); view.findViewById(R.id.left_bottom_button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onLeftButtonClickAction(); } }); + if (getRightButtonTextId() == DEFAULT_VALUE) { + view.findViewById(R.id.right_bottom_button).setVisibility(View.GONE); + view.findViewById(R.id.bottom_buttons_divider).setVisibility(View.GONE); + } if (position != INVALID_POSITION) { container.addView(view, position); } else { @@ -48,33 +56,9 @@ public class OpenBetaTravelCard extends BaseTravelCard { } } - protected View getView(OsmandApplication app, ViewGroup parent, boolean nightMode) { - if (view != null) { - return view; - } - final int themeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme; - return view = LayoutInflater.from(new ContextThemeWrapper(app, themeRes)) - .inflate(getLayoutId(), parent, false); - } - @Override - protected int getTitleId() { - return R.string.welcome_to_open_beta; - } - - @Override - protected int getDescriptionId() { - return R.string.welcome_to_open_beta_description; - } - - @Override - protected Drawable getBackgroundIcon(int drawableRes) { - return super.getBackgroundIcon(drawableRes); - } - - @Override - protected int getLayoutId() { - return R.layout.wikivoyage_open_beta_card; + protected Drawable getIcon(int drawableRes) { + return super.getIcon(drawableRes); } @Override @@ -84,7 +68,6 @@ public class OpenBetaTravelCard extends BaseTravelCard { @Override protected void onLeftButtonClickAction() { - ChoosePlanDialogFragment.showFreeVersionInstance(activity.getSupportFragmentManager()); - + ChoosePlanDialogFragment.showFreeVersionInstance(fm); } } diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java index 5d0d89b689..55366b1715 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java @@ -14,36 +14,40 @@ import android.widget.TextView; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; -import net.osmand.plus.activities.OsmandActionBarActivity; public class StartEditingTravelCard extends BaseTravelCard { - public StartEditingTravelCard(OsmandActionBarActivity activity) { - this.activity = activity; - + public StartEditingTravelCard(OsmandApplication app, boolean nightMode) { + this.app = app; + this.nightMode = nightMode; } - public StartEditingTravelCard(OsmandActionBarActivity activity, int position) { - this.activity = activity; + public StartEditingTravelCard(OsmandApplication app, int position, boolean nightMode) { + this.app = app; this.position = position; + this.nightMode = nightMode; } @Override public void inflate(OsmandApplication app, ViewGroup container, boolean nightMode) { - View view = getView(app, container, isNightMode()); + final int themeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme; + view = LayoutInflater.from(new ContextThemeWrapper(app, themeRes)) + .inflate(getLayoutId(), container, false); ImageView imageView = (ImageView) view.findViewById(R.id.background_image); - imageView.setImageDrawable(getBackgroundIcon(R.drawable.img_help_wikivoyage_contribute)); - ((TextView) view.findViewById(R.id.title)).setText(getTitleId()); - ((TextView) view.findViewById(R.id.description)).setText(getDescriptionId()); - - ((TextView) view.findViewById(R.id.left_bottom_button_text)).setText(getLeftButtonTextId()); - + imageView.setImageDrawable(getIcon(R.drawable.img_help_wikivoyage_contribute)); + ((TextView) view.findViewById(R.id.title)).setText(R.string.start_editing_card_image_text); + ((TextView) view.findViewById(R.id.description)).setText(R.string.start_editing_card_description); + ((TextView) view.findViewById(R.id.left_bottom_button_text)).setText(R.string.start_editing); view.findViewById(R.id.left_bottom_button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onLeftButtonClickAction(); } }); + if (getRightButtonTextId() == DEFAULT_VALUE) { + view.findViewById(R.id.right_bottom_button).setVisibility(View.GONE); + view.findViewById(R.id.bottom_buttons_divider).setVisibility(View.GONE); + } if (position != INVALID_POSITION) { container.addView(view, position); } else { @@ -51,28 +55,9 @@ public class StartEditingTravelCard extends BaseTravelCard { } } - protected View getView(OsmandApplication app, ViewGroup parent, boolean nightMode) { - if (view != null) { - return view; - } - final int themeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme; - return view = LayoutInflater.from(new ContextThemeWrapper(app, themeRes)) - .inflate(getLayoutId(), parent, false); - } - @Override - protected int getTitleId() { - return R.string.start_editing_card_image_text; - } - - @Override - protected int getDescriptionId() { - return R.string.start_editing_card_description; - } - - @Override - protected Drawable getBackgroundIcon(int drawableRes) { - return super.getBackgroundIcon(drawableRes); + protected Drawable getIcon(int drawableRes) { + return super.getIcon(drawableRes); } @Override @@ -88,9 +73,9 @@ public class StartEditingTravelCard extends BaseTravelCard { @Override protected void onLeftButtonClickAction() { CustomTabsIntent customTabsIntent = new CustomTabsIntent.Builder() - .setToolbarColor(ContextCompat.getColor(activity, isNightMode() ? R.color.actionbar_dark_color : R.color.actionbar_light_color)) + .setToolbarColor(ContextCompat.getColor(app, isNightMode() ? R.color.actionbar_dark_color : R.color.actionbar_light_color)) .build(); - String text = "https://" + activity.getMyApplication().getLanguage().toLowerCase() + ".m.wikivoyage.org"; - customTabsIntent.launchUrl(activity, Uri.parse(text)); + String text = "https://" + app.getLanguage().toLowerCase() + ".m.wikivoyage.org"; + customTabsIntent.launchUrl(app, Uri.parse(text)); } } From d87105d1a28d89f78e2bbc54e4e10862a05e91e6 Mon Sep 17 00:00:00 2001 From: Chumva Date: Mon, 23 Apr 2018 15:42:57 +0300 Subject: [PATCH 08/38] deleted getPaintedIconMethod --- .../plus/wikivoyage/explore/travelcards/BaseTravelCard.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/BaseTravelCard.java b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/BaseTravelCard.java index 96477e04d5..27e119380e 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/BaseTravelCard.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/BaseTravelCard.java @@ -38,13 +38,10 @@ public abstract class BaseTravelCard { return app.getIconsCache().getIcon(drawableRes); } - protected Drawable getPaintedIcon(int iconId, int color) { - return app.getIconsCache().getPaintedIcon(iconId, color); - } - protected Drawable getIcon(int iconId, int colorLightId, int colorDarkId) { return app.getIconsCache().getIcon(iconId, nightMode ? colorLightId : colorDarkId); } + @StringRes protected int getLeftButtonTextId() { return DEFAULT_VALUE; From 3268eb8952ab0de0369de849be21ee8ba325ee7b Mon Sep 17 00:00:00 2001 From: Chumva Date: Mon, 23 Apr 2018 15:44:41 +0300 Subject: [PATCH 09/38] cleaned card`s xml --- OsmAnd/res/layout/wikivoyage_start_editing_card.xml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/OsmAnd/res/layout/wikivoyage_start_editing_card.xml b/OsmAnd/res/layout/wikivoyage_start_editing_card.xml index a09906a0ea..b770ca7272 100644 --- a/OsmAnd/res/layout/wikivoyage_start_editing_card.xml +++ b/OsmAnd/res/layout/wikivoyage_start_editing_card.xml @@ -4,9 +4,9 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" - android:background="@drawable/wikivoyage_card_bg" android:layout_marginBottom="@dimen/list_content_padding" - android:layout_marginTop="@dimen/list_content_padding"> + android:layout_marginTop="@dimen/list_content_padding" + android:background="@drawable/wikivoyage_card_bg"> - Date: Mon, 23 Apr 2018 15:47:32 +0300 Subject: [PATCH 10/38] deleted unnecessary methods --- .../explore/travelcards/BaseTravelCard.java | 15 --------------- .../explore/travelcards/OpenBetaTravelCard.java | 1 + .../travelcards/StartEditingTravelCard.java | 9 ++------- 3 files changed, 3 insertions(+), 22 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/BaseTravelCard.java b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/BaseTravelCard.java index 27e119380e..c295e8f46e 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/BaseTravelCard.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/BaseTravelCard.java @@ -4,7 +4,6 @@ import android.graphics.drawable.Drawable; import android.support.annotation.ColorInt; import android.support.annotation.ColorRes; import android.support.annotation.DrawableRes; -import android.support.annotation.LayoutRes; import android.support.annotation.StringRes; import android.support.v4.content.ContextCompat; import android.view.View; @@ -59,18 +58,4 @@ public abstract class BaseTravelCard { protected void onRightButtonClickAction() { } - - @ColorRes - protected int getBottomDividerColorId() { - return DEFAULT_VALUE; - } - - @LayoutRes - protected int getLayoutId() { - return DEFAULT_VALUE; - } - - protected boolean isNightMode() { - return !app.getSettings().isLightContent(); - } } diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/OpenBetaTravelCard.java b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/OpenBetaTravelCard.java index 8914aa5377..1ef2140992 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/OpenBetaTravelCard.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/OpenBetaTravelCard.java @@ -14,6 +14,7 @@ import net.osmand.plus.R; import net.osmand.plus.dialogs.ChoosePlanDialogFragment; public class OpenBetaTravelCard extends BaseTravelCard { + private FragmentManager fm; public OpenBetaTravelCard(OsmandApplication app, FragmentManager fm, boolean nightMode) { diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java index 55366b1715..57eb92cbbe 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java @@ -32,7 +32,7 @@ public class StartEditingTravelCard extends BaseTravelCard { public void inflate(OsmandApplication app, ViewGroup container, boolean nightMode) { final int themeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme; view = LayoutInflater.from(new ContextThemeWrapper(app, themeRes)) - .inflate(getLayoutId(), container, false); + .inflate(R.layout.wikivoyage_start_editing_card, container, false); ImageView imageView = (ImageView) view.findViewById(R.id.background_image); imageView.setImageDrawable(getIcon(R.drawable.img_help_wikivoyage_contribute)); ((TextView) view.findViewById(R.id.title)).setText(R.string.start_editing_card_image_text); @@ -60,11 +60,6 @@ public class StartEditingTravelCard extends BaseTravelCard { return super.getIcon(drawableRes); } - @Override - protected int getLayoutId() { - return R.layout.wikivoyage_start_editing_card; - } - @Override protected int getLeftButtonTextId() { return R.string.start_editing; @@ -73,7 +68,7 @@ public class StartEditingTravelCard extends BaseTravelCard { @Override protected void onLeftButtonClickAction() { CustomTabsIntent customTabsIntent = new CustomTabsIntent.Builder() - .setToolbarColor(ContextCompat.getColor(app, isNightMode() ? R.color.actionbar_dark_color : R.color.actionbar_light_color)) + .setToolbarColor(ContextCompat.getColor(app, nightMode ? R.color.actionbar_dark_color : R.color.actionbar_light_color)) .build(); String text = "https://" + app.getLanguage().toLowerCase() + ".m.wikivoyage.org"; customTabsIntent.launchUrl(app, Uri.parse(text)); From 091e51587b97052c961463a0f5ca48f6c51c2ffc Mon Sep 17 00:00:00 2001 From: Chumva Date: Mon, 23 Apr 2018 15:51:02 +0300 Subject: [PATCH 11/38] removed view variable --- .../plus/wikivoyage/explore/travelcards/BaseTravelCard.java | 2 -- .../plus/wikivoyage/explore/travelcards/OpenBetaTravelCard.java | 2 +- .../wikivoyage/explore/travelcards/StartEditingTravelCard.java | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/BaseTravelCard.java b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/BaseTravelCard.java index c295e8f46e..bf97dc676b 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/BaseTravelCard.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/BaseTravelCard.java @@ -6,7 +6,6 @@ import android.support.annotation.ColorRes; import android.support.annotation.DrawableRes; import android.support.annotation.StringRes; import android.support.v4.content.ContextCompat; -import android.view.View; import android.view.ViewGroup; import net.osmand.plus.OsmandApplication; @@ -16,7 +15,6 @@ public abstract class BaseTravelCard { protected static final int INVALID_POSITION = -1; protected static final int DEFAULT_VALUE = -1; - protected View view; protected OsmandApplication app; protected int position = INVALID_POSITION; diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/OpenBetaTravelCard.java b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/OpenBetaTravelCard.java index 1ef2140992..325f4e1428 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/OpenBetaTravelCard.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/OpenBetaTravelCard.java @@ -33,7 +33,7 @@ public class OpenBetaTravelCard extends BaseTravelCard { @Override public void inflate(OsmandApplication app, ViewGroup container, boolean nightMode) { final int themeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme; - view = LayoutInflater.from(new ContextThemeWrapper(app, themeRes)) + View view = LayoutInflater.from(new ContextThemeWrapper(app, themeRes)) .inflate(R.layout.wikivoyage_open_beta_card, container, false); ImageView imageView = (ImageView) view.findViewById(R.id.background_image); imageView.setImageDrawable(getIcon(R.drawable.img_help_wikivoyage_articles)); diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java index 57eb92cbbe..adf448dc96 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java @@ -31,7 +31,7 @@ public class StartEditingTravelCard extends BaseTravelCard { @Override public void inflate(OsmandApplication app, ViewGroup container, boolean nightMode) { final int themeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme; - view = LayoutInflater.from(new ContextThemeWrapper(app, themeRes)) + View view = LayoutInflater.from(new ContextThemeWrapper(app, themeRes)) .inflate(R.layout.wikivoyage_start_editing_card, container, false); ImageView imageView = (ImageView) view.findViewById(R.id.background_image); imageView.setImageDrawable(getIcon(R.drawable.img_help_wikivoyage_contribute)); From 9d572ed3b283af20f81a39f5a255af9ba3ed1eb8 Mon Sep 17 00:00:00 2001 From: Chumva Date: Mon, 23 Apr 2018 15:52:59 +0300 Subject: [PATCH 12/38] removed unnecessary override methods --- .../wikivoyage/explore/travelcards/OpenBetaTravelCard.java | 5 ----- .../explore/travelcards/StartEditingTravelCard.java | 5 ----- 2 files changed, 10 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/OpenBetaTravelCard.java b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/OpenBetaTravelCard.java index 325f4e1428..a53a5f2bbc 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/OpenBetaTravelCard.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/OpenBetaTravelCard.java @@ -57,11 +57,6 @@ public class OpenBetaTravelCard extends BaseTravelCard { } } - @Override - protected Drawable getIcon(int drawableRes) { - return super.getIcon(drawableRes); - } - @Override protected int getLeftButtonTextId() { return R.string.get_unlimited_access; diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java index adf448dc96..7f6ed7906e 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java @@ -55,11 +55,6 @@ public class StartEditingTravelCard extends BaseTravelCard { } } - @Override - protected Drawable getIcon(int drawableRes) { - return super.getIcon(drawableRes); - } - @Override protected int getLeftButtonTextId() { return R.string.start_editing; From 4f345b27e97a4f6362bbfd99dc151cc7ea2d1e6f Mon Sep 17 00:00:00 2001 From: Chumva Date: Mon, 23 Apr 2018 15:57:44 +0300 Subject: [PATCH 13/38] removed getLeftButtonTextId and getRightButtonTextId methods --- .../explore/travelcards/BaseTravelCard.java | 12 ------------ .../explore/travelcards/OpenBetaTravelCard.java | 11 +---------- .../explore/travelcards/StartEditingTravelCard.java | 12 +----------- 3 files changed, 2 insertions(+), 33 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/BaseTravelCard.java b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/BaseTravelCard.java index bf97dc676b..40d0001abf 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/BaseTravelCard.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/BaseTravelCard.java @@ -4,7 +4,6 @@ import android.graphics.drawable.Drawable; import android.support.annotation.ColorInt; import android.support.annotation.ColorRes; import android.support.annotation.DrawableRes; -import android.support.annotation.StringRes; import android.support.v4.content.ContextCompat; import android.view.ViewGroup; @@ -13,7 +12,6 @@ import net.osmand.plus.OsmandApplication; public abstract class BaseTravelCard { protected static final int INVALID_POSITION = -1; - protected static final int DEFAULT_VALUE = -1; protected OsmandApplication app; @@ -39,20 +37,10 @@ public abstract class BaseTravelCard { return app.getIconsCache().getIcon(iconId, nightMode ? colorLightId : colorDarkId); } - @StringRes - protected int getLeftButtonTextId() { - return DEFAULT_VALUE; - } - protected void onLeftButtonClickAction() { } - @StringRes - protected int getRightButtonTextId() { - return DEFAULT_VALUE; - } - protected void onRightButtonClickAction() { } diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/OpenBetaTravelCard.java b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/OpenBetaTravelCard.java index a53a5f2bbc..2dce41f604 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/OpenBetaTravelCard.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/OpenBetaTravelCard.java @@ -1,6 +1,5 @@ package net.osmand.plus.wikivoyage.explore.travelcards; -import android.graphics.drawable.Drawable; import android.support.v4.app.FragmentManager; import android.view.ContextThemeWrapper; import android.view.LayoutInflater; @@ -46,10 +45,7 @@ public class OpenBetaTravelCard extends BaseTravelCard { onLeftButtonClickAction(); } }); - if (getRightButtonTextId() == DEFAULT_VALUE) { - view.findViewById(R.id.right_bottom_button).setVisibility(View.GONE); - view.findViewById(R.id.bottom_buttons_divider).setVisibility(View.GONE); - } + if (position != INVALID_POSITION) { container.addView(view, position); } else { @@ -57,11 +53,6 @@ public class OpenBetaTravelCard extends BaseTravelCard { } } - @Override - protected int getLeftButtonTextId() { - return R.string.get_unlimited_access; - } - @Override protected void onLeftButtonClickAction() { ChoosePlanDialogFragment.showFreeVersionInstance(fm); diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java index 7f6ed7906e..5263a1ebde 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java @@ -1,7 +1,5 @@ package net.osmand.plus.wikivoyage.explore.travelcards; - -import android.graphics.drawable.Drawable; import android.net.Uri; import android.support.customtabs.CustomTabsIntent; import android.support.v4.content.ContextCompat; @@ -44,10 +42,7 @@ public class StartEditingTravelCard extends BaseTravelCard { onLeftButtonClickAction(); } }); - if (getRightButtonTextId() == DEFAULT_VALUE) { - view.findViewById(R.id.right_bottom_button).setVisibility(View.GONE); - view.findViewById(R.id.bottom_buttons_divider).setVisibility(View.GONE); - } + if (position != INVALID_POSITION) { container.addView(view, position); } else { @@ -55,11 +50,6 @@ public class StartEditingTravelCard extends BaseTravelCard { } } - @Override - protected int getLeftButtonTextId() { - return R.string.start_editing; - } - @Override protected void onLeftButtonClickAction() { CustomTabsIntent customTabsIntent = new CustomTabsIntent.Builder() From ef07dce49434b35de83126159122be776914cae8 Mon Sep 17 00:00:00 2001 From: Chumva Date: Mon, 23 Apr 2018 16:01:01 +0300 Subject: [PATCH 14/38] set right button visibility to gone --- OsmAnd/res/layout/bottom_buttons.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OsmAnd/res/layout/bottom_buttons.xml b/OsmAnd/res/layout/bottom_buttons.xml index b388724ba9..ad2e474496 100644 --- a/OsmAnd/res/layout/bottom_buttons.xml +++ b/OsmAnd/res/layout/bottom_buttons.xml @@ -30,7 +30,7 @@ android:layout_width="1dp" android:layout_height="match_parent" android:background="?attr/wikivoyage_card_divider_color" - android:visibility="visible" /> + android:visibility="gone" /> + android:visibility="gone"> Date: Mon, 23 Apr 2018 16:04:19 +0300 Subject: [PATCH 15/38] Wiki links menu improved asynctasks --- .../wikivoyage/WikivoyageWebViewClient.java | 125 ++++++++++++++---- .../WikivoyageArticleDialogFragment.java | 6 + 2 files changed, 103 insertions(+), 28 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/WikivoyageWebViewClient.java b/OsmAnd/src/net/osmand/plus/wikivoyage/WikivoyageWebViewClient.java index 6bef80faee..6bf78b3276 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/WikivoyageWebViewClient.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/WikivoyageWebViewClient.java @@ -1,8 +1,7 @@ package net.osmand.plus.wikivoyage; -import android.app.Activity; -import android.app.Dialog; + import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; @@ -13,7 +12,6 @@ import android.support.annotation.NonNull; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; import android.support.v7.app.AlertDialog; -import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.webkit.WebView; import android.webkit.WebViewClient; @@ -28,9 +26,7 @@ import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandSettings; import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; -import net.osmand.plus.dialogs.ProgressDialogFragment; import net.osmand.plus.mapcontextmenu.WikipediaDialogFragment; -import net.osmand.plus.quickaction.actions.FavoriteAction; import net.osmand.plus.resources.AmenityIndexRepositoryBinary; import net.osmand.plus.wikivoyage.article.WikivoyageArticleDialogFragment; import net.osmand.plus.wikivoyage.article.WikivoyageArticleWikiLinkFragment; @@ -48,11 +44,15 @@ import java.util.List; import static android.support.v4.app.FragmentManager.POP_BACK_STACK_INCLUSIVE; + +interface RegionCallback { + void onRegionFound(String s); +} /** * Custom WebView client to handle the internal links. */ -public class WikivoyageWebViewClient extends WebViewClient { +public class WikivoyageWebViewClient extends WebViewClient implements RegionCallback { private static final String TAG = WikivoyageWebViewClient.class.getSimpleName(); @@ -61,12 +61,16 @@ public class WikivoyageWebViewClient extends WebViewClient { private Context context; private TravelArticle article; private boolean nightMode; + private String regionName; private static final String PREFIX_GEO = "geo:"; private static final String PAGE_PREFIX_HTTP = "http://"; private static final String PAGE_PREFIX_HTTPS = "https://"; private static final String WIKIVOAYAGE_DOMAIN = ".wikivoyage.com/wiki/"; private static final String WIKI_DOMAIN = ".wikipedia.org/wiki/"; + private FetchWikiRegion fetchRegionTask; + private WikiArticleSearchTask articleSearchTask; + public WikivoyageWebViewClient(FragmentActivity context, FragmentManager fm, boolean nightMode) { app = (OsmandApplication) context.getApplication(); @@ -169,38 +173,92 @@ public class WikivoyageWebViewClient extends WebViewClient { public void setArticle(TravelArticle article) { this.article = article; + if (this.article != null && app != null) { + fetchRegionTask = new FetchWikiRegion(this, app.getRegions(), article.getLat(), article.getLon()); + fetchRegionTask.execute(); + } } - protected void getWikiArticle(String name, String url) { + private void getWikiArticle(String name, String url) { List indexes = app.getResourceManager() .getWikiAmenityRepository(article.getLat(), article.getLon()); if (indexes.isEmpty()) { - String reg = ""; - try { - reg = getRegion(article.getLat(), article.getLon()); - } catch (IOException e) { - Log.e(TAG, e.getMessage(), e); - } - WikivoyageArticleWikiLinkFragment.showInstance(fragmentManager, reg, url); + WikivoyageArticleWikiLinkFragment.showInstance(fragmentManager, regionName == null ? + "" : regionName, url); } else { - new WikiArticleSearchTask(name, indexes, (MapActivity) context).execute(); + articleSearchTask = new WikiArticleSearchTask(name, indexes, (MapActivity) context); + articleSearchTask.execute(); } } - private String getRegion(double lat, double lon) throws IOException { - OsmandRegions osmandRegions = app.getRegions(); - if (osmandRegions != null) { - int x31 = MapUtils.get31TileNumberX(lon); - int y31 = MapUtils.get31TileNumberY(lat); - List cs = osmandRegions.query(x31, y31); - for (BinaryMapDataObject b : cs) { - if(osmandRegions.contain(b, x31, y31)) { - return osmandRegions.getLocaleName(osmandRegions.getDownloadName(b), false); + @Override + public void onRegionFound(String s) { + regionName = s; + } + + public void stopRunningAsyncTasks() { + if (articleSearchTask != null && articleSearchTask.getStatus() == AsyncTask.Status.RUNNING) { + articleSearchTask.cancel(true); + } + if (fetchRegionTask != null && fetchRegionTask.getStatus() == AsyncTask.Status.RUNNING) { + fetchRegionTask.cancel(true); + } + } + + private static class FetchWikiRegion extends AsyncTask { + + private RegionCallback callback; + private OsmandRegions osmandRegions; + private double lat; + private double lon; + + FetchWikiRegion(RegionCallback callback, OsmandRegions osmandRegions, double lat, double lon) { + this.callback = callback; + this.osmandRegions = osmandRegions; + this.lat = lat; + this.lon = lon; + } + + @Override + protected String doInBackground(Void... voids) { + if (osmandRegions != null) { + int x31 = MapUtils.get31TileNumberX(lon); + int y31 = MapUtils.get31TileNumberY(lat); + List dataObjects = null; + try { + if (isCancelled()) { + return null; + } + dataObjects = osmandRegions.query(x31, y31); + } catch (IOException e) { + e.printStackTrace(); + } + if (dataObjects != null) { + for (BinaryMapDataObject b : dataObjects) { + if (isCancelled()) { + break; + } + if(osmandRegions.contain(b, x31, y31)) { + return osmandRegions.getLocaleName(osmandRegions.getDownloadName(b), false); + } + } } } + return ""; + } + + @Override + protected void onCancelled(){ + callback = null; + } + + @Override + protected void onPostExecute(String result) { + if (callback != null) { + callback.onRegionFound(result); + } } - return ""; } private static class WikiArticleSearchTask extends AsyncTask> { @@ -227,20 +285,31 @@ public class WikivoyageWebViewClient extends WebViewClient { protected List doInBackground(Void... voids) { List found = new ArrayList<>(); for (AmenityIndexRepositoryBinary repo : indexes) { + if (isCancelled()) { + break; + } found.addAll(repo.searchAmenitiesByName(0, 0, 0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE, name, null)); } return found; } + @Override + protected void onCancelled(){ + dialog = null; + indexes.clear(); + weakContext.clear(); + } + @Override protected void onPostExecute(List found) { - if (!weakContext.get().isActivityDestroyed()) { + MapActivity activity = weakContext.get(); + if (!activity.isActivityDestroyed() && dialog != null) { dialog.dismiss(); if (!found.isEmpty()) { - WikipediaDialogFragment.showInstance((AppCompatActivity) weakContext.get(), found.get(0)); + WikipediaDialogFragment.showInstance(activity, found.get(0)); } else { - Toast.makeText(weakContext.get(), R.string.wiki_article_not_found, Toast.LENGTH_LONG).show(); + Toast.makeText(activity, R.string.wiki_article_not_found, Toast.LENGTH_LONG).show(); } } } diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/article/WikivoyageArticleDialogFragment.java b/OsmAnd/src/net/osmand/plus/wikivoyage/article/WikivoyageArticleDialogFragment.java index b12b7803e2..3567f6a535 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/article/WikivoyageArticleDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/article/WikivoyageArticleDialogFragment.java @@ -247,6 +247,12 @@ public class WikivoyageArticleDialogFragment extends WikivoyageBaseDialogFragmen } } + @Override + public void onPause() { + super.onPause(); + webViewClient.stopRunningAsyncTasks(); + } + @Override public void onResume() { super.onResume(); From 868dc4d3048fdccc4e3b363c988019ef82c50e2c Mon Sep 17 00:00:00 2001 From: Dmitriy Prodchenko Date: Mon, 23 Apr 2018 17:38:25 +0300 Subject: [PATCH 16/38] Fix image for Start Editing card --- OsmAnd/assets/article_style.css | 2 +- .../img_help_wikivoyage_contribute.png | Bin 0 -> 15474 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 OsmAnd/res/drawable-xxhdpi/img_help_wikivoyage_contribute.png diff --git a/OsmAnd/assets/article_style.css b/OsmAnd/assets/article_style.css index 0b73c5cc34..d2c1dc8b34 100755 --- a/OsmAnd/assets/article_style.css +++ b/OsmAnd/assets/article_style.css @@ -174,7 +174,7 @@ pre { @font-face { font-family: RobotoSlab-Regular; - src: url("file:///assets/fonts/RobotoSlab-Regular.ttf") + src: url("fonts/RobotoSlab-Regular.ttf") } td { diff --git a/OsmAnd/res/drawable-xxhdpi/img_help_wikivoyage_contribute.png b/OsmAnd/res/drawable-xxhdpi/img_help_wikivoyage_contribute.png new file mode 100644 index 0000000000000000000000000000000000000000..f93cfd38cb57311de0a3c7f0e216df7aeca20de2 GIT binary patch literal 15474 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 Ku}t0~ Date: Tue, 24 Apr 2018 10:06:17 +0300 Subject: [PATCH 17/38] Fix dimen name --- OsmAnd/res/layout/travel_download_update_card.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OsmAnd/res/layout/travel_download_update_card.xml b/OsmAnd/res/layout/travel_download_update_card.xml index 7904955c4e..091b0772ce 100644 --- a/OsmAnd/res/layout/travel_download_update_card.xml +++ b/OsmAnd/res/layout/travel_download_update_card.xml @@ -48,7 +48,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="@color/wikivoyage_secondary_text" - android:textSize="@dimen/travel_card_title_size" + android:textSize="@dimen/travel_card_title_text_size" osmand:typeface="@string/font_roboto_regular" tools:text="Download this Wikivoyage travel guides file to view articles about places around the world without an internet connection."/> From 8571e6ffad148690919166066e0ce47ac2818813 Mon Sep 17 00:00:00 2001 From: PaulStets Date: Tue, 24 Apr 2018 10:47:43 +0300 Subject: [PATCH 18/38] Missing Wiki links sow browser warning and article short description fix --- .../wikivoyage/WikivoyageWebViewClient.java | 17 +++++++++------ .../plus/wikivoyage/data/TravelArticle.java | 21 +++++++++++++++---- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/WikivoyageWebViewClient.java b/OsmAnd/src/net/osmand/plus/wikivoyage/WikivoyageWebViewClient.java index 6bf78b3276..170f33bf92 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/WikivoyageWebViewClient.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/WikivoyageWebViewClient.java @@ -88,14 +88,14 @@ public class WikivoyageWebViewClient extends WebViewClient implements RegionCall if (articleId != 0) { WikivoyageArticleDialogFragment.showInstance(app, fragmentManager, articleId, lang); } else { - warnAboutExternalLoad(url); + warnAboutExternalLoad(url, context, nightMode); } return true; } else if (url.contains(WIKI_DOMAIN)) { String articleName = getArticleNameFromUrl(url, getLang(url)); getWikiArticle(articleName, url); } else if (url.startsWith(PAGE_PREFIX_HTTP) || url.startsWith(PAGE_PREFIX_HTTPS)) { - warnAboutExternalLoad(url); + warnAboutExternalLoad(url, context, nightMode); } else if (url.startsWith(PREFIX_GEO)) { if (article != null) { List points = article.getGpxFile().getPoints(); @@ -157,7 +157,7 @@ public class WikivoyageWebViewClient extends WebViewClient implements RegionCall return articleName; } - private void warnAboutExternalLoad(final String url) { + private static void warnAboutExternalLoad(final String url, final Context context, final boolean nightMode) { new AlertDialog.Builder(context) .setTitle(url) .setMessage(R.string.online_webpage_warning) @@ -186,7 +186,7 @@ public class WikivoyageWebViewClient extends WebViewClient implements RegionCall WikivoyageArticleWikiLinkFragment.showInstance(fragmentManager, regionName == null ? "" : regionName, url); } else { - articleSearchTask = new WikiArticleSearchTask(name, indexes, (MapActivity) context); + articleSearchTask = new WikiArticleSearchTask(name, indexes, (MapActivity) context, nightMode, url); articleSearchTask.execute(); } @@ -266,12 +266,17 @@ public class WikivoyageWebViewClient extends WebViewClient implements RegionCall private String name; private List indexes; private WeakReference weakContext; + private boolean isNightMode; + private String url; - WikiArticleSearchTask(String articleName, List indexes, MapActivity context) { + WikiArticleSearchTask(String articleName, List indexes, + MapActivity context, boolean isNightMode, String url) { name = articleName; this.indexes = indexes; weakContext = new WeakReference<>(context); dialog = createProgressDialog(); + this.isNightMode = isNightMode; + this.url = url; } @Override @@ -309,7 +314,7 @@ public class WikivoyageWebViewClient extends WebViewClient implements RegionCall if (!found.isEmpty()) { WikipediaDialogFragment.showInstance(activity, found.get(0)); } else { - Toast.makeText(activity, R.string.wiki_article_not_found, Toast.LENGTH_LONG).show(); + warnAboutExternalLoad(url, weakContext.get(), isNightMode); } } } diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/data/TravelArticle.java b/OsmAnd/src/net/osmand/plus/wikivoyage/data/TravelArticle.java index 14b2e9e482..3cdc56b73a 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/data/TravelArticle.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/data/TravelArticle.java @@ -91,14 +91,27 @@ public class TravelArticle { return null; } - int firstParagraphStart = content.indexOf("

"); - int firstParagraphEnd = content.indexOf("

"); + String pOpened = "

"; + String pClosed = "

"; + + int firstParagraphStart = content.indexOf(pOpened); + int firstParagraphEnd = content.indexOf(pClosed); if (firstParagraphStart == -1 || firstParagraphEnd == -1) { return null; } + int pClosedLength = pClosed.length(); + String firstParagraphHtml = content.substring(firstParagraphStart, firstParagraphEnd + pClosedLength); + while (firstParagraphHtml.length() == (pOpened.length() + pClosedLength) + && (firstParagraphEnd + pClosedLength) < content.length()) { + firstParagraphStart = content.indexOf(pOpened, firstParagraphEnd); + firstParagraphEnd = firstParagraphStart == -1 ? -1 : content.indexOf(pClosed, firstParagraphStart); + if (firstParagraphStart != -1 && firstParagraphEnd != -1) { + firstParagraphHtml = content.substring(firstParagraphStart, firstParagraphEnd + pClosedLength); + } else { + break; + } + } - // 4 is the length of

tag - String firstParagraphHtml = content.substring(firstParagraphStart, firstParagraphEnd + 4); String firstParagraphText = Html.fromHtml(firstParagraphHtml).toString().trim(); String[] phrases = firstParagraphText.split("\\. "); From ca4e50d8050148f033b34363f02d066cec56bd26 Mon Sep 17 00:00:00 2001 From: PaulStets Date: Tue, 24 Apr 2018 10:53:42 +0300 Subject: [PATCH 19/38] Small wiki links asynctask improvement --- .../wikivoyage/article/WikivoyageArticleDialogFragment.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/article/WikivoyageArticleDialogFragment.java b/OsmAnd/src/net/osmand/plus/wikivoyage/article/WikivoyageArticleDialogFragment.java index 3567f6a535..fb2b9eea91 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/article/WikivoyageArticleDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/article/WikivoyageArticleDialogFragment.java @@ -250,7 +250,9 @@ public class WikivoyageArticleDialogFragment extends WikivoyageBaseDialogFragmen @Override public void onPause() { super.onPause(); - webViewClient.stopRunningAsyncTasks(); + if (webViewClient != null) { + webViewClient.stopRunningAsyncTasks(); + } } @Override From 2dd22197a64b0224e5716c75c2a7cdda24b8bdb4 Mon Sep 17 00:00:00 2001 From: PaulStets Date: Tue, 24 Apr 2018 11:46:31 +0300 Subject: [PATCH 20/38] Refactored string resource --- .../wikivoyage/article/WikivoyageArticleWikiLinkFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/article/WikivoyageArticleWikiLinkFragment.java b/OsmAnd/src/net/osmand/plus/wikivoyage/article/WikivoyageArticleWikiLinkFragment.java index 902ccde9e8..e73859859e 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/article/WikivoyageArticleWikiLinkFragment.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/article/WikivoyageArticleWikiLinkFragment.java @@ -52,7 +52,7 @@ public class WikivoyageArticleWikiLinkFragment extends MenuBottomSheetDialogFrag wikiRegion = args.getString(WIKI_REGION); } } - items.add(new TitleItem("How to open Wikipedia articles?")); + items.add(new TitleItem(getString(R.string.how_to_open_wiki_title))); BaseBottomSheetItem wikiLinkitem = new TitleItem.Builder().setTitle(articleUrl) .setTitleColorId(nightMode From ad270721141712a5976f3ec655e9ac6cb086b1e7 Mon Sep 17 00:00:00 2001 From: PaulStets Date: Tue, 24 Apr 2018 11:46:51 +0300 Subject: [PATCH 21/38] Refactored string resource --- OsmAnd/res/values/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index 8627ba2842..eb7e571e39 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -2861,4 +2861,5 @@ this region Searching for the necessary wiki article Article not found + How to open Wikipedia articles? From e237a90389ae951de11c1a5ddc57b9dc9d5c161f Mon Sep 17 00:00:00 2001 From: PaulStets Date: Tue, 24 Apr 2018 11:54:38 +0300 Subject: [PATCH 22/38] Removed unused imports --- .../osmand/plus/wikivoyage/WikivoyageWebViewClient.java | 1 - .../article/WikivoyageArticleWikiLinkFragment.java | 7 ------- 2 files changed, 8 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/WikivoyageWebViewClient.java b/OsmAnd/src/net/osmand/plus/wikivoyage/WikivoyageWebViewClient.java index 170f33bf92..72bd99e06c 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/WikivoyageWebViewClient.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/WikivoyageWebViewClient.java @@ -15,7 +15,6 @@ import android.support.v7.app.AlertDialog; import android.util.Log; import android.webkit.WebView; import android.webkit.WebViewClient; -import android.widget.Toast; import net.osmand.binary.BinaryMapDataObject; import net.osmand.data.Amenity; diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/article/WikivoyageArticleWikiLinkFragment.java b/OsmAnd/src/net/osmand/plus/wikivoyage/article/WikivoyageArticleWikiLinkFragment.java index e73859859e..f1a8c1be39 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/article/WikivoyageArticleWikiLinkFragment.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/article/WikivoyageArticleWikiLinkFragment.java @@ -7,24 +7,17 @@ import android.net.Uri; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.v4.app.FragmentManager; -import android.view.ContextThemeWrapper; import android.view.View; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.base.MenuBottomSheetDialogFragment; import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem; import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithDescription; -import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem; -import net.osmand.plus.base.bottomsheetmenu.simpleitems.DescriptionItem; import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerHalfItem; import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleDividerItem; import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem; import net.osmand.plus.mapcontextmenu.WikipediaDialogFragment; -import net.osmand.plus.osmedit.OsmEditsFragment; public class WikivoyageArticleWikiLinkFragment extends MenuBottomSheetDialogFragment { From 54ea3782e86e9f770875f8f071f4f351495398bd Mon Sep 17 00:00:00 2001 From: Alex Sytnyk Date: Tue, 24 Apr 2018 12:06:48 +0300 Subject: [PATCH 23/38] Polish travel_download_update_card --- .../res/layout/travel_download_update_card.xml | 18 ++++++++++++------ OsmAnd/res/values-large/sizes.xml | 2 +- OsmAnd/res/values/sizes.xml | 2 +- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/OsmAnd/res/layout/travel_download_update_card.xml b/OsmAnd/res/layout/travel_download_update_card.xml index 091b0772ce..3ef484826b 100644 --- a/OsmAnd/res/layout/travel_download_update_card.xml +++ b/OsmAnd/res/layout/travel_download_update_card.xml @@ -30,7 +30,7 @@ android:ellipsize="end" android:maxLines="1" android:textColor="?attr/wikivoyage_primary_text_color" - android:textSize="@dimen/travel_card_title_text_size" + android:textSize="@dimen/travel_card_primary_text_size" osmand:typeface="@string/font_roboto_medium" tools:text="Download file"/> @@ -48,7 +48,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="@color/wikivoyage_secondary_text" - android:textSize="@dimen/travel_card_title_text_size" + android:textSize="@dimen/travel_card_primary_text_size" osmand:typeface="@string/font_roboto_regular" tools:text="Download this Wikivoyage travel guides file to view articles about places around the world without an internet connection."/> @@ -81,7 +81,7 @@ android:layout_weight="1" android:orientation="vertical"> - -
@@ -119,17 +121,19 @@ android:background="@drawable/wikivoyage_secondary_btn_bg">
@@ -145,17 +149,19 @@ android:background="@drawable/wikivoyage_primary_btn_bg"> diff --git a/OsmAnd/res/values-large/sizes.xml b/OsmAnd/res/values-large/sizes.xml index b3e8e0e4c9..cf7e713f02 100644 --- a/OsmAnd/res/values-large/sizes.xml +++ b/OsmAnd/res/values-large/sizes.xml @@ -101,7 +101,7 @@ 12sp 27sp 22sp - 22sp + 22sp 24sp diff --git a/OsmAnd/res/values/sizes.xml b/OsmAnd/res/values/sizes.xml index cfde311852..6ba8597d0a 100644 --- a/OsmAnd/res/values/sizes.xml +++ b/OsmAnd/res/values/sizes.xml @@ -175,7 +175,7 @@ 10sp 23sp 15sp - 15sp + 15sp 13sp 13sp From 4384f4ddd50f996ecd4db36f787e1b810d167f81 Mon Sep 17 00:00:00 2001 From: PaulStets Date: Tue, 24 Apr 2018 12:14:53 +0300 Subject: [PATCH 24/38] Added null check for weakreference --- .../osmand/plus/wikivoyage/WikivoyageWebViewClient.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/WikivoyageWebViewClient.java b/OsmAnd/src/net/osmand/plus/wikivoyage/WikivoyageWebViewClient.java index 72bd99e06c..ebd163a948 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/WikivoyageWebViewClient.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/WikivoyageWebViewClient.java @@ -157,6 +157,9 @@ public class WikivoyageWebViewClient extends WebViewClient implements RegionCall } private static void warnAboutExternalLoad(final String url, final Context context, final boolean nightMode) { + if (context == null) { + return; + } new AlertDialog.Builder(context) .setTitle(url) .setMessage(R.string.online_webpage_warning) @@ -302,13 +305,12 @@ public class WikivoyageWebViewClient extends WebViewClient implements RegionCall protected void onCancelled(){ dialog = null; indexes.clear(); - weakContext.clear(); } @Override protected void onPostExecute(List found) { MapActivity activity = weakContext.get(); - if (!activity.isActivityDestroyed() && dialog != null) { + if (activity != null && !activity.isActivityDestroyed() && dialog != null) { dialog.dismiss(); if (!found.isEmpty()) { WikipediaDialogFragment.showInstance(activity, found.get(0)); @@ -320,7 +322,7 @@ public class WikivoyageWebViewClient extends WebViewClient implements RegionCall private ProgressDialog createProgressDialog() { MapActivity activity = weakContext.get(); - if (!activity.isActivityDestroyed()) { + if (activity != null && !activity.isActivityDestroyed()) { ProgressDialog dialog = new ProgressDialog(activity); dialog.setCancelable(false); dialog.setMessage(activity.getString(R.string.wiki_article_search_text)); From 668449c0afb3876b93426aec813dc2e8602f83f7 Mon Sep 17 00:00:00 2001 From: PaulStets Date: Tue, 24 Apr 2018 12:20:15 +0300 Subject: [PATCH 25/38] Changed asynktask's cancel to false --- .../net/osmand/plus/wikivoyage/WikivoyageWebViewClient.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/WikivoyageWebViewClient.java b/OsmAnd/src/net/osmand/plus/wikivoyage/WikivoyageWebViewClient.java index ebd163a948..adfc31841b 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/WikivoyageWebViewClient.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/WikivoyageWebViewClient.java @@ -201,10 +201,10 @@ public class WikivoyageWebViewClient extends WebViewClient implements RegionCall public void stopRunningAsyncTasks() { if (articleSearchTask != null && articleSearchTask.getStatus() == AsyncTask.Status.RUNNING) { - articleSearchTask.cancel(true); + articleSearchTask.cancel(false); } if (fetchRegionTask != null && fetchRegionTask.getStatus() == AsyncTask.Status.RUNNING) { - fetchRegionTask.cancel(true); + fetchRegionTask.cancel(false); } } From aa97a1b7c69b17a365f19efb036cd7187886d9c3 Mon Sep 17 00:00:00 2001 From: Dmitriy Prodchenko Date: Tue, 24 Apr 2018 12:35:39 +0300 Subject: [PATCH 26/38] Fix img for wikivoyage contribute card --- .../img_help_wikivoyage_contribute.png | Bin 15474 -> 0 bytes .../img_help_wikivoyage_contribute.webp | Bin 8858 -> 7894 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 OsmAnd/res/drawable-xxhdpi/img_help_wikivoyage_contribute.png diff --git a/OsmAnd/res/drawable-xxhdpi/img_help_wikivoyage_contribute.png b/OsmAnd/res/drawable-xxhdpi/img_help_wikivoyage_contribute.png deleted file mode 100644 index f93cfd38cb57311de0a3c7f0e216df7aeca20de2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15474 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 z zkEwB7@@suRQ=vMoDbt5~5%_V-Iam=4tbyu@7^2O&gnaPdmrYNNi9Y717?82Z$aqEj zw_nnonq`3ITt-wB@gQZ-uBQ6XhrWzG7BQ0(`g)Aw=hBCz3ArxS(2u4oxk!qMKBsD4 zizbU%#-p#_!P#e3fu2glxrmtSjyLltfh*L(!$?aixB<2|^1C89v zkaQh-FwxO4IhR6g^z&5@zSi5&MaiA06Y~_+A&b~%410S9Lwg=NL_-#F$>CUcGXs2o zY-_FbD_`ne$RLhc7z!)626~u;N}zfeWekbA@WCN&Vg~w`b{e31c;w|x@&tui1zoy? zgLn({Fr~yq(JKu?B#7)Eas|`84N@vTG7`npnptI$o_n;55xz=_ zV3Ub@#q|{Uqn(i7tKts$rCLb^H0N?B+V*z${ln1~!10*7A5{u#i`~&W9%T+u80A^XF z>7y<8vqMt;k{wH6|E9120Q|F`hHlALDH4D`z&2IVfiv3!aLy!!Y0Lv~gh2sqGle7< zg96HK$6$fM3|`?M3=(LYlr0PrD1XFYus|Xh`M>&K{qGEYc?4Ku2AeVbWCYAuI;WKY z#bD(B>VH2{Cz_xCr~X&}tN&FcE;dZzyRmY^@&mVJ^C^0r<*6Gh|NYo2s{hshz9-fj zue1D<`d|I8{#XASai9x@Vy*Jg$#JvAFK}E3ZJlh13eo{AB9t*gPGK0KNf)5;gA9zI zg4h723@Fk8GV6cD(~c1A$&FA?R&yo%S4BR7DFTYv0GYLAjQOXoWFpw&WHmQ}?&0lE z4^b+eltuWlD*NZNA_s^BI6ZYZFtwC&wlRs$(bOljoCc$gD&M0C{l1sb-2JaRtQICNI=&K^ Date: Tue, 24 Apr 2018 12:35:59 +0300 Subject: [PATCH 27/38] added recyclerview and improve travel cards --- OsmAnd/res/layout/fragment_explore_tab.xml | 19 +++----- .../res/layout/wikivoyage_open_beta_card.xml | 14 +++++- .../layout/wikivoyage_start_editing_card.xml | 20 +++++++-- OsmAnd/res/values/colors.xml | 1 + .../explore/ExploreTabFragment.java | 12 ++--- .../explore/travelcards/BaseTravelCard.java | 39 ++++++++-------- .../travelcards/OpenBetaTravelCard.java | 36 +++++---------- .../travelcards/StartEditingTravelCard.java | 44 +++++++------------ 8 files changed, 88 insertions(+), 97 deletions(-) diff --git a/OsmAnd/res/layout/fragment_explore_tab.xml b/OsmAnd/res/layout/fragment_explore_tab.xml index 34316e6ef0..8a663f6d42 100644 --- a/OsmAnd/res/layout/fragment_explore_tab.xml +++ b/OsmAnd/res/layout/fragment_explore_tab.xml @@ -6,20 +6,11 @@ android:gravity="center" android:orientation="vertical"> - - - - - - - + android:layout_height="match_parent" + android:clipToPadding="false" + android:paddingBottom="@dimen/map_markers_recycler_view_padding_bottom"/> diff --git a/OsmAnd/res/layout/wikivoyage_open_beta_card.xml b/OsmAnd/res/layout/wikivoyage_open_beta_card.xml index 19812ccf03..93b709dd03 100644 --- a/OsmAnd/res/layout/wikivoyage_open_beta_card.xml +++ b/OsmAnd/res/layout/wikivoyage_open_beta_card.xml @@ -7,7 +7,7 @@ android:layout_gravity="center_horizontal" android:layout_marginBottom="@dimen/list_content_padding" android:layout_marginTop="@dimen/list_content_padding" - android:background="@drawable/wikivoyage_card_bg"> + android:background="@drawable/travel_card_bg"> - + diff --git a/OsmAnd/res/layout/wikivoyage_start_editing_card.xml b/OsmAnd/res/layout/wikivoyage_start_editing_card.xml index b770ca7272..c2b9a4b6c0 100644 --- a/OsmAnd/res/layout/wikivoyage_start_editing_card.xml +++ b/OsmAnd/res/layout/wikivoyage_start_editing_card.xml @@ -1,12 +1,13 @@ + android:background="@drawable/travel_card_bg"> + android:layout_height="wrap_content" + android:background="@color/wikivoyage_start_editing_background"> @@ -58,7 +60,17 @@ android:layout_height="1dp" android:background="?attr/wikivoyage_card_divider_color" /> - + diff --git a/OsmAnd/res/values/colors.xml b/OsmAnd/res/values/colors.xml index eaa0b79144..f5b86303db 100644 --- a/OsmAnd/res/values/colors.xml +++ b/OsmAnd/res/values/colors.xml @@ -428,5 +428,6 @@ #212121 #cccccc #727272 + #339966 \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/ExploreTabFragment.java b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/ExploreTabFragment.java index 62eafee287..7bf579e6fc 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/ExploreTabFragment.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/ExploreTabFragment.java @@ -3,6 +3,8 @@ package net.osmand.plus.wikivoyage.explore; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -27,18 +29,16 @@ public class ExploreTabFragment extends BaseOsmAndFragment { final View mainView = inflater.inflate(R.layout.fragment_explore_tab, container, false); - LinearLayout linearLayout = (LinearLayout) mainView.findViewById(R.id.cards_list); + ArrayList items = new ArrayList<>(); - BaseTravelCard openBetaTravelCard = new OpenBetaTravelCard(app, getFragmentManager(), nightMode); + BaseTravelCard openBetaTravelCard = new OpenBetaTravelCard(app, nightMode, getFragmentManager()); BaseTravelCard startEditingTravelCard = new StartEditingTravelCard(app, nightMode); items.add(openBetaTravelCard); items.add(startEditingTravelCard); - for (BaseTravelCard item : items) { - item.inflate(app, linearLayout, nightMode); - } - + final RecyclerView rv = (RecyclerView) mainView.findViewById(R.id.recycler_view); + rv.setLayoutManager(new LinearLayoutManager(getContext())); return mainView; } } diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/BaseTravelCard.java b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/BaseTravelCard.java index 40d0001abf..5acc09860d 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/BaseTravelCard.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/BaseTravelCard.java @@ -4,44 +4,45 @@ import android.graphics.drawable.Drawable; import android.support.annotation.ColorInt; import android.support.annotation.ColorRes; import android.support.annotation.DrawableRes; +import android.support.annotation.NonNull; import android.support.v4.content.ContextCompat; -import android.view.ViewGroup; +import android.support.v7.widget.RecyclerView; import net.osmand.plus.OsmandApplication; +import net.osmand.plus.R; public abstract class BaseTravelCard { - protected static final int INVALID_POSITION = -1; - protected OsmandApplication app; - - protected int position = INVALID_POSITION; protected boolean nightMode; - public abstract void inflate(OsmandApplication app, ViewGroup container, boolean nightMode); + public BaseTravelCard(OsmandApplication app, boolean nightMode) { + this.app = app; + this.nightMode = nightMode; + } + + public abstract void bindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder); + + public abstract int getCardType(); @ColorInt protected int getResolvedColor(@ColorRes int colorId) { return ContextCompat.getColor(app, colorId); } - protected Drawable getIcon(@DrawableRes int drawableRes, @ColorRes int color) { - return app.getIconsCache().getIcon(drawableRes, color); + protected Drawable getContentIcon(@DrawableRes int icon) { + return getColoredIcon(icon, R.color.icon_color); } - protected Drawable getIcon(@DrawableRes int drawableRes) { - return app.getIconsCache().getIcon(drawableRes); + protected Drawable getActiveIcon(@DrawableRes int icon) { + return getColoredIcon(icon, R.color.wikivoyage_active_light, R.color.wikivoyage_active_dark); } - protected Drawable getIcon(int iconId, int colorLightId, int colorDarkId) { - return app.getIconsCache().getIcon(iconId, nightMode ? colorLightId : colorDarkId); + protected Drawable getColoredIcon(@DrawableRes int icon, @ColorRes int colorLight, @ColorRes int colorDark) { + return getColoredIcon(icon, nightMode ? colorDark : colorLight); } - protected void onLeftButtonClickAction() { - + protected Drawable getColoredIcon(@DrawableRes int icon, @ColorRes int color) { + return app.getIconsCache().getIcon(icon, color); } - - protected void onRightButtonClickAction() { - - } -} +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/OpenBetaTravelCard.java b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/OpenBetaTravelCard.java index 2dce41f604..86aa1a1247 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/OpenBetaTravelCard.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/OpenBetaTravelCard.java @@ -1,10 +1,11 @@ package net.osmand.plus.wikivoyage.explore.travelcards; +import android.support.annotation.NonNull; import android.support.v4.app.FragmentManager; +import android.support.v7.widget.RecyclerView; import android.view.ContextThemeWrapper; import android.view.LayoutInflater; import android.view.View; -import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; @@ -14,47 +15,34 @@ import net.osmand.plus.dialogs.ChoosePlanDialogFragment; public class OpenBetaTravelCard extends BaseTravelCard { - private FragmentManager fm; + private FragmentManager fragmentManager; - public OpenBetaTravelCard(OsmandApplication app, FragmentManager fm, boolean nightMode) { - this.app = app; - this.fm = fm; - this.nightMode = nightMode; + public OpenBetaTravelCard(OsmandApplication app, boolean nightMode, FragmentManager fragmentManager) { + super(app, nightMode); + this.fragmentManager = fragmentManager; } - public OpenBetaTravelCard(OsmandApplication app, FragmentManager fm, int position, boolean nightMode) { - this.app = app; - this.fm = fm; - this.position = position; - this.nightMode = nightMode; - } @Override - public void inflate(OsmandApplication app, ViewGroup container, boolean nightMode) { + public void bindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder) { final int themeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme; View view = LayoutInflater.from(new ContextThemeWrapper(app, themeRes)) - .inflate(R.layout.wikivoyage_open_beta_card, container, false); + .inflate(R.layout.wikivoyage_open_beta_card, null, false); ImageView imageView = (ImageView) view.findViewById(R.id.background_image); - imageView.setImageDrawable(getIcon(R.drawable.img_help_wikivoyage_articles)); + imageView.setImageResource(R.drawable.img_help_wikivoyage_articles); ((TextView) view.findViewById(R.id.title)).setText(R.string.welcome_to_open_beta); ((TextView) view.findViewById(R.id.description)).setText(R.string.welcome_to_open_beta_description); ((TextView) view.findViewById(R.id.left_bottom_button_text)).setText(R.string.get_unlimited_access); view.findViewById(R.id.left_bottom_button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - onLeftButtonClickAction(); + ChoosePlanDialogFragment.showFreeVersionInstance(fragmentManager); } }); - - if (position != INVALID_POSITION) { - container.addView(view, position); - } else { - container.addView(view); - } } @Override - protected void onLeftButtonClickAction() { - ChoosePlanDialogFragment.showFreeVersionInstance(fm); + public int getCardType() { + return 0; } } diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java index 5263a1ebde..44082c160b 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java @@ -1,12 +1,13 @@ package net.osmand.plus.wikivoyage.explore.travelcards; import android.net.Uri; +import android.support.annotation.NonNull; import android.support.customtabs.CustomTabsIntent; import android.support.v4.content.ContextCompat; +import android.support.v7.widget.RecyclerView; import android.view.ContextThemeWrapper; import android.view.LayoutInflater; import android.view.View; -import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; @@ -16,46 +17,33 @@ import net.osmand.plus.R; public class StartEditingTravelCard extends BaseTravelCard { public StartEditingTravelCard(OsmandApplication app, boolean nightMode) { - this.app = app; - this.nightMode = nightMode; - } - - public StartEditingTravelCard(OsmandApplication app, int position, boolean nightMode) { - this.app = app; - this.position = position; - this.nightMode = nightMode; + super(app, nightMode); } @Override - public void inflate(OsmandApplication app, ViewGroup container, boolean nightMode) { + public void bindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder) { final int themeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme; View view = LayoutInflater.from(new ContextThemeWrapper(app, themeRes)) - .inflate(R.layout.wikivoyage_start_editing_card, container, false); + .inflate(R.layout.wikivoyage_open_beta_card, null, false); ImageView imageView = (ImageView) view.findViewById(R.id.background_image); - imageView.setImageDrawable(getIcon(R.drawable.img_help_wikivoyage_contribute)); - ((TextView) view.findViewById(R.id.title)).setText(R.string.start_editing_card_image_text); - ((TextView) view.findViewById(R.id.description)).setText(R.string.start_editing_card_description); - ((TextView) view.findViewById(R.id.left_bottom_button_text)).setText(R.string.start_editing); + imageView.setImageResource(R.drawable.img_help_wikivoyage_articles); + ((TextView) view.findViewById(R.id.title)).setText(R.string.welcome_to_open_beta); + ((TextView) view.findViewById(R.id.description)).setText(R.string.welcome_to_open_beta_description); + ((TextView) view.findViewById(R.id.left_bottom_button_text)).setText(R.string.get_unlimited_access); view.findViewById(R.id.left_bottom_button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - onLeftButtonClickAction(); + CustomTabsIntent customTabsIntent = new CustomTabsIntent.Builder() + .setToolbarColor(ContextCompat.getColor(app, nightMode ? R.color.actionbar_dark_color : R.color.actionbar_light_color)) + .build(); + String text = "https://" + app.getLanguage().toLowerCase() + ".m.wikivoyage.org"; + customTabsIntent.launchUrl(app, Uri.parse(text)); } }); - - if (position != INVALID_POSITION) { - container.addView(view, position); - } else { - container.addView(view); - } } @Override - protected void onLeftButtonClickAction() { - CustomTabsIntent customTabsIntent = new CustomTabsIntent.Builder() - .setToolbarColor(ContextCompat.getColor(app, nightMode ? R.color.actionbar_dark_color : R.color.actionbar_light_color)) - .build(); - String text = "https://" + app.getLanguage().toLowerCase() + ".m.wikivoyage.org"; - customTabsIntent.launchUrl(app, Uri.parse(text)); + public int getCardType() { + return 1; } } From cf0f9b32744f21bb5f7244d712af2e517df6b652 Mon Sep 17 00:00:00 2001 From: Alex Sytnyk Date: Tue, 24 Apr 2018 13:13:59 +0300 Subject: [PATCH 28/38] Add missing elements to travel_download_update_card --- .../res/layout/travel_download_update_card.xml | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/OsmAnd/res/layout/travel_download_update_card.xml b/OsmAnd/res/layout/travel_download_update_card.xml index 3ef484826b..d2958d5ba6 100644 --- a/OsmAnd/res/layout/travel_download_update_card.xml +++ b/OsmAnd/res/layout/travel_download_update_card.xml @@ -25,7 +25,7 @@ android:layout_height="wrap_content" android:layout_marginEnd="@dimen/content_padding" android:layout_marginRight="@dimen/content_padding" - android:layout_marginTop="2dp" + android:layout_marginTop="4dp" android:layout_weight="1" android:ellipsize="end" android:maxLines="1" @@ -56,11 +56,12 @@ @@ -103,6 +104,16 @@ osmand:typeface="@string/font_roboto_regular" tools:text="255 Mb • Update 11 April"/> + + @@ -139,6 +150,7 @@ From 6c222d94b60939f7d2b173c824f93aa28af18617 Mon Sep 17 00:00:00 2001 From: Chumva Date: Tue, 24 Apr 2018 13:47:26 +0300 Subject: [PATCH 29/38] fix text on background image --- .../layout/wikivoyage_start_editing_card.xml | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/OsmAnd/res/layout/wikivoyage_start_editing_card.xml b/OsmAnd/res/layout/wikivoyage_start_editing_card.xml index c2b9a4b6c0..da3d54da58 100644 --- a/OsmAnd/res/layout/wikivoyage_start_editing_card.xml +++ b/OsmAnd/res/layout/wikivoyage_start_editing_card.xml @@ -15,21 +15,15 @@ android:layout_gravity="center_horizontal" android:orientation="vertical"> - - - + android:background="@color/wikivoyage_start_editing_background" + android:orientation="horizontal"> - + + + Date: Tue, 24 Apr 2018 13:49:58 +0300 Subject: [PATCH 30/38] rename color for image background --- OsmAnd/res/layout/wikivoyage_start_editing_card.xml | 3 ++- OsmAnd/res/values/colors.xml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/OsmAnd/res/layout/wikivoyage_start_editing_card.xml b/OsmAnd/res/layout/wikivoyage_start_editing_card.xml index da3d54da58..3cda6efb73 100644 --- a/OsmAnd/res/layout/wikivoyage_start_editing_card.xml +++ b/OsmAnd/res/layout/wikivoyage_start_editing_card.xml @@ -18,7 +18,7 @@ #212121 #cccccc #727272 - #339966 + #339966 \ No newline at end of file From ad514f2d2900fe90659ceac01d4fbffd3d13a52c Mon Sep 17 00:00:00 2001 From: Chumva Date: Tue, 24 Apr 2018 14:08:05 +0300 Subject: [PATCH 31/38] add holders for cards --- OsmAnd/res/layout/bottom_buttons.xml | 55 ------------------- .../res/layout/wikivoyage_open_beta_card.xml | 2 +- .../layout/wikivoyage_start_editing_card.xml | 2 +- .../explore/ExploreTabFragment.java | 1 - .../travelcards/OpenBetaTravelCard.java | 46 ++++++++++------ .../travelcards/StartEditingTravelCard.java | 53 +++++++++++------- 6 files changed, 64 insertions(+), 95 deletions(-) delete mode 100644 OsmAnd/res/layout/bottom_buttons.xml diff --git a/OsmAnd/res/layout/bottom_buttons.xml b/OsmAnd/res/layout/bottom_buttons.xml deleted file mode 100644 index ad2e474496..0000000000 --- a/OsmAnd/res/layout/bottom_buttons.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/OsmAnd/res/layout/wikivoyage_open_beta_card.xml b/OsmAnd/res/layout/wikivoyage_open_beta_card.xml index 93b709dd03..5ba3eefd55 100644 --- a/OsmAnd/res/layout/wikivoyage_open_beta_card.xml +++ b/OsmAnd/res/layout/wikivoyage_open_beta_card.xml @@ -52,7 +52,7 @@ android:background="?attr/wikivoyage_card_divider_color" /> items = new ArrayList<>(); BaseTravelCard openBetaTravelCard = new OpenBetaTravelCard(app, nightMode, getFragmentManager()); diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/OpenBetaTravelCard.java b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/OpenBetaTravelCard.java index 86aa1a1247..44ac5ba3f3 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/OpenBetaTravelCard.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/OpenBetaTravelCard.java @@ -3,8 +3,6 @@ package net.osmand.plus.wikivoyage.explore.travelcards; import android.support.annotation.NonNull; import android.support.v4.app.FragmentManager; import android.support.v7.widget.RecyclerView; -import android.view.ContextThemeWrapper; -import android.view.LayoutInflater; import android.view.View; import android.widget.ImageView; import android.widget.TextView; @@ -22,23 +20,37 @@ public class OpenBetaTravelCard extends BaseTravelCard { this.fragmentManager = fragmentManager; } - @Override public void bindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder) { - final int themeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme; - View view = LayoutInflater.from(new ContextThemeWrapper(app, themeRes)) - .inflate(R.layout.wikivoyage_open_beta_card, null, false); - ImageView imageView = (ImageView) view.findViewById(R.id.background_image); - imageView.setImageResource(R.drawable.img_help_wikivoyage_articles); - ((TextView) view.findViewById(R.id.title)).setText(R.string.welcome_to_open_beta); - ((TextView) view.findViewById(R.id.description)).setText(R.string.welcome_to_open_beta_description); - ((TextView) view.findViewById(R.id.left_bottom_button_text)).setText(R.string.get_unlimited_access); - view.findViewById(R.id.left_bottom_button).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - ChoosePlanDialogFragment.showFreeVersionInstance(fragmentManager); - } - }); + if (viewHolder instanceof OpenBetaTravelVH) { + final OpenBetaTravelVH holder = (OpenBetaTravelVH) viewHolder; + holder.title.setText(R.string.welcome_to_open_beta); + holder.description.setText(R.string.welcome_to_open_beta_description); + holder.backgroundImage.setImageResource(R.drawable.img_help_wikivoyage_articles); + holder.button.setText(R.string.get_unlimited_access); + holder.button.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ChoosePlanDialogFragment.showFreeVersionInstance(fragmentManager); + } + }); + } + } + + class OpenBetaTravelVH extends RecyclerView.ViewHolder { + + final TextView title; + final TextView description; + final TextView button; + final ImageView backgroundImage; + + OpenBetaTravelVH(final View itemView) { + super(itemView); + title = (TextView) itemView.findViewById(R.id.title); + description = (TextView) itemView.findViewById(R.id.description); + button = (TextView) itemView.findViewById(R.id.bottom_button_text); + backgroundImage = (ImageView) itemView.findViewById(R.id.background_image); + } } @Override diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java index 44082c160b..c8ef49aa16 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java @@ -5,8 +5,6 @@ import android.support.annotation.NonNull; import android.support.customtabs.CustomTabsIntent; import android.support.v4.content.ContextCompat; import android.support.v7.widget.RecyclerView; -import android.view.ContextThemeWrapper; -import android.view.LayoutInflater; import android.view.View; import android.widget.ImageView; import android.widget.TextView; @@ -22,24 +20,39 @@ public class StartEditingTravelCard extends BaseTravelCard { @Override public void bindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder) { - final int themeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme; - View view = LayoutInflater.from(new ContextThemeWrapper(app, themeRes)) - .inflate(R.layout.wikivoyage_open_beta_card, null, false); - ImageView imageView = (ImageView) view.findViewById(R.id.background_image); - imageView.setImageResource(R.drawable.img_help_wikivoyage_articles); - ((TextView) view.findViewById(R.id.title)).setText(R.string.welcome_to_open_beta); - ((TextView) view.findViewById(R.id.description)).setText(R.string.welcome_to_open_beta_description); - ((TextView) view.findViewById(R.id.left_bottom_button_text)).setText(R.string.get_unlimited_access); - view.findViewById(R.id.left_bottom_button).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - CustomTabsIntent customTabsIntent = new CustomTabsIntent.Builder() - .setToolbarColor(ContextCompat.getColor(app, nightMode ? R.color.actionbar_dark_color : R.color.actionbar_light_color)) - .build(); - String text = "https://" + app.getLanguage().toLowerCase() + ".m.wikivoyage.org"; - customTabsIntent.launchUrl(app, Uri.parse(text)); - } - }); + if (viewHolder instanceof OpenBetaTravelVH) { + final OpenBetaTravelVH holder = (OpenBetaTravelVH) viewHolder; + holder.title.setText(R.string.start_editing_card_image_text); + holder.description.setText(R.string.start_editing_card_description); + holder.backgroundImage.setImageResource(R.drawable.img_help_wikivoyage_contribute); + holder.button.setText(R.string.start_editing); + holder.button.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + CustomTabsIntent customTabsIntent = new CustomTabsIntent.Builder() + .setToolbarColor(ContextCompat.getColor(app, nightMode ? R.color.actionbar_dark_color : R.color.actionbar_light_color)) + .build(); + String text = "https://" + app.getLanguage().toLowerCase() + ".m.wikivoyage.org"; + customTabsIntent.launchUrl(app, Uri.parse(text)); + } + }); + } + } + + class OpenBetaTravelVH extends RecyclerView.ViewHolder { + + final TextView title; + final TextView description; + final TextView button; + final ImageView backgroundImage; + + OpenBetaTravelVH(final View itemView) { + super(itemView); + title = (TextView) itemView.findViewById(R.id.title); + description = (TextView) itemView.findViewById(R.id.description); + button = (TextView) itemView.findViewById(R.id.bottom_button_text); + backgroundImage = (ImageView) itemView.findViewById(R.id.background_image); + } } @Override From 1fbebc10f3fe52d87cccf16c5ade160edd0d2df5 Mon Sep 17 00:00:00 2001 From: Chumva Date: Tue, 24 Apr 2018 14:09:45 +0300 Subject: [PATCH 32/38] remove unused xml bg file --- OsmAnd/res/drawable/wikivoyage_card_bg.xml | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 OsmAnd/res/drawable/wikivoyage_card_bg.xml diff --git a/OsmAnd/res/drawable/wikivoyage_card_bg.xml b/OsmAnd/res/drawable/wikivoyage_card_bg.xml deleted file mode 100644 index 5691ef7ce2..0000000000 --- a/OsmAnd/res/drawable/wikivoyage_card_bg.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file From befed088979d8f8914fc0fd5ab5a369939d6376c Mon Sep 17 00:00:00 2001 From: Chumva Date: Tue, 24 Apr 2018 14:18:23 +0300 Subject: [PATCH 33/38] change holder in StartEditingTravelCard --- .../explore/travelcards/StartEditingTravelCard.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java index c8ef49aa16..cce59cd217 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java @@ -20,8 +20,8 @@ public class StartEditingTravelCard extends BaseTravelCard { @Override public void bindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder) { - if (viewHolder instanceof OpenBetaTravelVH) { - final OpenBetaTravelVH holder = (OpenBetaTravelVH) viewHolder; + if (viewHolder instanceof StartEditingTravelVH) { + final StartEditingTravelVH holder = (StartEditingTravelVH) viewHolder; holder.title.setText(R.string.start_editing_card_image_text); holder.description.setText(R.string.start_editing_card_description); holder.backgroundImage.setImageResource(R.drawable.img_help_wikivoyage_contribute); @@ -39,14 +39,14 @@ public class StartEditingTravelCard extends BaseTravelCard { } } - class OpenBetaTravelVH extends RecyclerView.ViewHolder { + class StartEditingTravelVH extends RecyclerView.ViewHolder { final TextView title; final TextView description; final TextView button; final ImageView backgroundImage; - OpenBetaTravelVH(final View itemView) { + StartEditingTravelVH(final View itemView) { super(itemView); title = (TextView) itemView.findViewById(R.id.title); description = (TextView) itemView.findViewById(R.id.description); From 1656154b7a74a0fa7011214c39602faae938ad09 Mon Sep 17 00:00:00 2001 From: Chumva Date: Tue, 24 Apr 2018 14:37:00 +0300 Subject: [PATCH 34/38] refactored ExploreTabFragment --- .../osmand/plus/wikivoyage/explore/ExploreTabFragment.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/ExploreTabFragment.java b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/ExploreTabFragment.java index 38f7f4af52..0a584c615a 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/ExploreTabFragment.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/ExploreTabFragment.java @@ -31,8 +31,8 @@ public class ExploreTabFragment extends BaseOsmAndFragment { ArrayList items = new ArrayList<>(); - BaseTravelCard openBetaTravelCard = new OpenBetaTravelCard(app, nightMode, getFragmentManager()); - BaseTravelCard startEditingTravelCard = new StartEditingTravelCard(app, nightMode); + OpenBetaTravelCard openBetaTravelCard = new OpenBetaTravelCard(app, nightMode, getFragmentManager()); + StartEditingTravelCard startEditingTravelCard = new StartEditingTravelCard(app, nightMode); items.add(openBetaTravelCard); items.add(startEditingTravelCard); From 9e916d50f1d92487f41705935d78825ae9df960b Mon Sep 17 00:00:00 2001 From: Dmitriy Prodchenko Date: Tue, 24 Apr 2018 17:25:58 +0300 Subject: [PATCH 35/38] Change headline font weight, change line height, Open on map and Wikipedia buttons padding --- OsmAnd/assets/article_style.css | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/OsmAnd/assets/article_style.css b/OsmAnd/assets/article_style.css index d2c1dc8b34..68e84add81 100755 --- a/OsmAnd/assets/article_style.css +++ b/OsmAnd/assets/article_style.css @@ -50,8 +50,8 @@ body { h1 { font-size: 2em; color: #212121; - font-family: serif; - letter-spacing: 0.03em; + font-family: RobotoSlab-Regular; + letter-spacing: 0.02em; word-wrap: break-word; padding-top: 5%; font-weight: normal; @@ -59,14 +59,14 @@ h1 { h2 { font-size: 1.5em; - color: #575757; + color: #454545; font-family: RobotoSlab-Regular; + font-weight:100; word-wrap: break-word; - margin-top: 3%; - padding-bottom: 3%; - /* font-weight: bold; */ + padding-top: 2%; + padding-bottom: 4%; line-height: 1.6em; - letter-spacing: 0.01em; + letter-spacing: 0.015em; border-bottom: 1px solid #eaecf0; width: 100%; } @@ -105,7 +105,7 @@ h3 { font-family: sans-serif; word-wrap: break-word; font-weight: bold; - margin-top: 3%; + margin-top: 5%; margin-bottom: 3%; line-height: 1.6em; } @@ -113,7 +113,7 @@ h3 { p { font-family: sans-serif; font-size: 1.1em; - line-height: 1.5em; + line-height: 1.6em; } ul { @@ -162,8 +162,8 @@ pre { .geo { background-color: #fafafa; border: 1px solid #e6e6e6; - border-radius: 5px; - padding: 3% 3% 3% 3%; + border-radius: 4px; + padding: 10px 10px 10px 10px; color: #237bff; font-size: 0.9em; font-weight: bold; @@ -178,8 +178,8 @@ pre { } td { - display: inline-block; - word-wrap: break-word; + display: inline-block; + word-wrap: break-word; } .thumb-tright, .thumbinner { @@ -196,6 +196,6 @@ td { } .content { - display: none; - overflow: hidden; + display: none; + overflow: hidden; } From 78cf001d3230947007a4d42758d89c892eb5bb37 Mon Sep 17 00:00:00 2001 From: Alexey Kulish Date: Tue, 24 Apr 2018 18:21:05 +0300 Subject: [PATCH 36/38] Fix choose plan UI. Refactored InAppHelper. --- OsmAnd/res/layout/free_version_banner.xml | 232 +------ .../layout/purchase_dialog_card_button.xml | 8 + .../res/layout/purchase_dialog_fragment.xml | 33 +- OsmAnd/res/values/sizes.xml | 3 +- OsmAnd/res/values/strings.xml | 2 +- OsmAnd/res/values/styles.xml | 4 + .../src/net/osmand/plus/AppInitializer.java | 2 + .../net/osmand/plus/OsmandApplication.java | 9 +- .../src/net/osmand/plus/OsmandSettings.java | 2 + .../osmand/plus/activities/MapActivity.java | 50 +- .../activities/OsmandActionBarActivity.java | 8 +- .../OsmandInAppPurchaseActivity.java | 166 +++++ .../dialogs/ChoosePlanDialogFragment.java | 360 ++++++---- .../plus/download/DownloadActivity.java | 298 ++------ .../ui/DownloadResourceGroupFragment.java | 23 +- .../ui/FreeVersionDialogFragment.java | 44 -- .../osmand/plus/helpers/DiscountHelper.java | 19 +- ...ppHelper.java => InAppPurchaseHelper.java} | 653 ++++++++---------- .../plus/liveupdates/LiveUpdatesFragment.java | 64 +- .../plus/liveupdates/OsmLiveActivity.java | 38 +- .../liveupdates/SubscriptionFragment.java | 73 +- 21 files changed, 963 insertions(+), 1128 deletions(-) create mode 100644 OsmAnd/src/net/osmand/plus/activities/OsmandInAppPurchaseActivity.java delete mode 100644 OsmAnd/src/net/osmand/plus/download/ui/FreeVersionDialogFragment.java rename OsmAnd/src/net/osmand/plus/inapp/{InAppHelper.java => InAppPurchaseHelper.java} (55%) diff --git a/OsmAnd/res/layout/free_version_banner.xml b/OsmAnd/res/layout/free_version_banner.xml index b63fa910ef..e7aaf90465 100644 --- a/OsmAnd/res/layout/free_version_banner.xml +++ b/OsmAnd/res/layout/free_version_banner.xml @@ -1,10 +1,9 @@ - + android:orientation="vertical" + android:paddingLeft="@dimen/list_content_padding" + android:paddingRight="@dimen/list_content_padding"> - - - - - - - + android:padding="4dp"> - - - - - - - + android:layout_weight="1" + android:text="@string/free_version_title"/> + - + android:layout_margin="4dp" + tools:text="@string/free_version_message"/> - + + + android:layout_height="match_parent" + android:max="10" + android:progressDrawable="@drawable/number_of_downloads_progress_bar_drawable" + android:saveEnabled="false" + tools:progress="6"/> + android:layout_height="match_parent" + android:orientation="horizontal"/> + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/OsmAnd/res/layout/purchase_dialog_card_button.xml b/OsmAnd/res/layout/purchase_dialog_card_button.xml index 82efb29fd2..7e70c781ac 100644 --- a/OsmAnd/res/layout/purchase_dialog_card_button.xml +++ b/OsmAnd/res/layout/purchase_dialog_card_button.xml @@ -13,11 +13,19 @@ android:background="?attr/selectableItemBackground" android:minHeight="@dimen/card_button_min_size" android:orientation="vertical" + android:gravity="center" android:paddingBottom="@dimen/list_header_padding" android:paddingLeft="@dimen/list_content_padding" android:paddingRight="@dimen/list_content_padding" android:paddingTop="@dimen/list_header_padding"> + + + + - - - - diff --git a/OsmAnd/res/values/sizes.xml b/OsmAnd/res/values/sizes.xml index 8e64ef25e5..a27a0f0ca0 100644 --- a/OsmAnd/res/values/sizes.xml +++ b/OsmAnd/res/values/sizes.xml @@ -7,7 +7,8 @@ 28sp 64dp 48dp - 52dp + 58dp + 32dp 36dp 6dp diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index 6de7ce50e6..abc6573c3d 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -23,7 +23,7 @@ Unlimited downloads Wikipedia offline - Contour lines + Sea depth + Contour lines & Hillshade maps Unlock all OsmAnd features Choose plan diff --git a/OsmAnd/res/values/styles.xml b/OsmAnd/res/values/styles.xml index 452ed64aae..066abeb850 100644 --- a/OsmAnd/res/values/styles.xml +++ b/OsmAnd/res/values/styles.xml @@ -575,6 +575,10 @@ true + + diff --git a/OsmAnd/src/net/osmand/plus/AppInitializer.java b/OsmAnd/src/net/osmand/plus/AppInitializer.java index 2355e3c986..b844e88320 100644 --- a/OsmAnd/src/net/osmand/plus/AppInitializer.java +++ b/OsmAnd/src/net/osmand/plus/AppInitializer.java @@ -31,6 +31,7 @@ import net.osmand.plus.download.DownloadActivity; import net.osmand.plus.download.ui.AbstractLoadLocalIndexTask; import net.osmand.plus.helpers.AvoidSpecificRoads; import net.osmand.plus.helpers.WaypointHelper; +import net.osmand.plus.inapp.InAppPurchaseHelper; import net.osmand.plus.liveupdates.LiveUpdatesHelper; import net.osmand.plus.mapmarkers.MapMarkersDbHelper; import net.osmand.plus.monitoring.LiveMonitoringHelper; @@ -421,6 +422,7 @@ public class AppInitializer implements IProgress { e.printStackTrace(); } app.applyTheme(app); + app.inAppPurchaseHelper = startupInit(new InAppPurchaseHelper(app), InAppPurchaseHelper.class); app.poiTypes = startupInit(MapPoiTypes.getDefaultNoInit(), MapPoiTypes.class); app.routingHelper = startupInit(new RoutingHelper(app), RoutingHelper.class); app.resourceManager = startupInit(new ResourceManager(app), ResourceManager.class); diff --git a/OsmAnd/src/net/osmand/plus/OsmandApplication.java b/OsmAnd/src/net/osmand/plus/OsmandApplication.java index 48b0755ec8..1bc966c65d 100644 --- a/OsmAnd/src/net/osmand/plus/OsmandApplication.java +++ b/OsmAnd/src/net/osmand/plus/OsmandApplication.java @@ -19,7 +19,6 @@ import android.support.multidex.MultiDex; import android.support.multidex.MultiDexApplication; import android.support.v7.app.AlertDialog; import android.text.format.DateFormat; -import android.util.Log; import android.view.View; import android.view.accessibility.AccessibilityManager; import android.widget.ImageView; @@ -46,7 +45,7 @@ import net.osmand.plus.dialogs.RateUsBottomSheetDialog; import net.osmand.plus.download.DownloadIndexesThread; import net.osmand.plus.helpers.AvoidSpecificRoads; import net.osmand.plus.helpers.WaypointHelper; -import net.osmand.plus.inapp.InAppHelper; +import net.osmand.plus.inapp.InAppPurchaseHelper; import net.osmand.plus.mapcontextmenu.other.RoutePreferencesMenu; import net.osmand.plus.mapmarkers.MapMarkersDbHelper; import net.osmand.plus.monitoring.LiveMonitoringHelper; @@ -120,6 +119,7 @@ public class OsmandApplication extends MultiDexApplication { GeocodingLookupService geocodingLookupService; QuickSearchHelper searchUICore; TravelDbHelper travelDbHelper; + InAppPurchaseHelper inAppPurchaseHelper; RoutingConfiguration.Builder defaultRoutingConfig; private Locale preferredLocale = null; @@ -166,7 +166,6 @@ public class OsmandApplication extends MultiDexApplication { // if(!osmandSettings.FOLLOW_THE_ROUTE.get()) { // targetPointsHelper.clearPointToNavigate(false); // } - InAppHelper.initialize(this); initExternalLibs(); startApplication(); System.out.println("Time to start application " + (System.currentTimeMillis() - timeToStart) + " ms. Should be less < 800 ms"); @@ -396,6 +395,10 @@ public class OsmandApplication extends MultiDexApplication { return travelDbHelper; } + public InAppPurchaseHelper getInAppPurchaseHelper() { + return inAppPurchaseHelper; + } + public CommandPlayer getPlayer() { return player; } diff --git a/OsmAnd/src/net/osmand/plus/OsmandSettings.java b/OsmAnd/src/net/osmand/plus/OsmandSettings.java index 38133f48fd..a55d451289 100644 --- a/OsmAnd/src/net/osmand/plus/OsmandSettings.java +++ b/OsmAnd/src/net/osmand/plus/OsmandSettings.java @@ -976,6 +976,8 @@ public class OsmandSettings { public final OsmandPreference DISCOUNT_TOTAL_SHOW = new IntPreference("discount_total_show", 0).makeGlobal(); public final OsmandPreference DISCOUNT_SHOW_DATETIME_MS = new LongPreference("show_discount_datetime_ms", 0).makeGlobal(); + public final OsmandPreference TRAVEL_ARTICLES_PURCHASED = new BooleanPreference("travel_articles_purchased", false).makeGlobal(); + // this value string is synchronized with settings_pref.xml preference name public final OsmandPreference USER_OSM_BUG_NAME = new StringPreference("user_osm_bug_name", "NoName/OsmAnd").makeGlobal(); diff --git a/OsmAnd/src/net/osmand/plus/activities/MapActivity.java b/OsmAnd/src/net/osmand/plus/activities/MapActivity.java index 31c0075fdc..f8483d0aa8 100644 --- a/OsmAnd/src/net/osmand/plus/activities/MapActivity.java +++ b/OsmAnd/src/net/osmand/plus/activities/MapActivity.java @@ -92,7 +92,8 @@ import net.osmand.plus.helpers.ExternalApiHelper; import net.osmand.plus.helpers.ImportHelper; import net.osmand.plus.helpers.ImportHelper.ImportGpxBottomSheetDialogFragment; import net.osmand.plus.helpers.WakeLockHelper; -import net.osmand.plus.inapp.InAppHelper; +import net.osmand.plus.inapp.InAppPurchaseHelper; +import net.osmand.plus.inapp.InAppPurchaseHelper.InAppPurchaseTaskType; import net.osmand.plus.mapcontextmenu.AdditionalActionsBottomSheetDialogFragment; import net.osmand.plus.mapcontextmenu.MapContextMenu; import net.osmand.plus.mapcontextmenu.MapContextMenuFragment; @@ -204,7 +205,7 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven private boolean permissionGranted; private boolean mIsDestroyed = false; - private InAppHelper inAppHelper; + private InAppPurchaseHelper inAppPurchaseHelper; private Timer splashScreenTimer; private ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor(); @@ -1214,8 +1215,8 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven if (atlasMapRendererView != null) { atlasMapRendererView.handleOnDestroy(); } - if (inAppHelper != null) { - inAppHelper.stop(); + if (inAppPurchaseHelper != null) { + inAppPurchaseHelper.stop(); } mIsDestroyed = true; } @@ -1513,7 +1514,7 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { - if (inAppHelper != null && inAppHelper.onActivityResultHandled(requestCode, resultCode, data)) { + if (inAppPurchaseHelper != null && inAppPurchaseHelper.onActivityResultHandled(requestCode, resultCode, data)) { return; } for (ActivityResultListener listener : activityResultListeners) { @@ -1920,43 +1921,4 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven DESTINATION_SELECTION, INTERMEDIATE_SELECTION } - - public InAppHelper execInAppTask(@NonNull InAppHelper.InAppRunnable runnable) { - if (inAppHelper != null) { - inAppHelper.stop(); - } - if (Version.isGooglePlayEnabled(app)) { - inAppHelper = new InAppHelper(getMyApplication(), false); - inAppHelper.addListener(new InAppHelper.InAppListener() { - @Override - public void onError(String error) { - inAppHelper = null; - } - - @Override - public void onGetItems() { - inAppHelper = null; - } - - @Override - public void onItemPurchased(String sku) { - inAppHelper = null; - } - - @Override - public void showProgress() { - - } - - @Override - public void dismissProgress() { - - } - }); - inAppHelper.exec(runnable); - return inAppHelper; - } else { - return null; - } - } } diff --git a/OsmAnd/src/net/osmand/plus/activities/OsmandActionBarActivity.java b/OsmAnd/src/net/osmand/plus/activities/OsmandActionBarActivity.java index 19bc1c2597..5162339969 100644 --- a/OsmAnd/src/net/osmand/plus/activities/OsmandActionBarActivity.java +++ b/OsmAnd/src/net/osmand/plus/activities/OsmandActionBarActivity.java @@ -1,5 +1,6 @@ package net.osmand.plus.activities; +import android.annotation.SuppressLint; import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.support.v4.content.ContextCompat; @@ -11,7 +12,8 @@ import android.view.ViewGroup; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; -public class OsmandActionBarActivity extends AppCompatActivity { +@SuppressLint("Registered") +public class OsmandActionBarActivity extends OsmandInAppPurchaseActivity { protected boolean haveHomeButton = true; @@ -50,8 +52,4 @@ public class OsmandActionBarActivity extends AppCompatActivity { setupHomeButton(); } } - - public OsmandApplication getMyApplication() { - return (OsmandApplication) getApplication(); - } } diff --git a/OsmAnd/src/net/osmand/plus/activities/OsmandInAppPurchaseActivity.java b/OsmAnd/src/net/osmand/plus/activities/OsmandInAppPurchaseActivity.java new file mode 100644 index 0000000000..65f307d60e --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/activities/OsmandInAppPurchaseActivity.java @@ -0,0 +1,166 @@ +package net.osmand.plus.activities; + +import android.annotation.SuppressLint; +import android.content.ActivityNotFoundException; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v7.app.AppCompatActivity; + +import net.osmand.PlatformUtil; +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.Version; +import net.osmand.plus.inapp.InAppPurchaseHelper; +import net.osmand.plus.inapp.InAppPurchaseHelper.InAppPurchaseListener; +import net.osmand.plus.inapp.InAppPurchaseHelper.InAppPurchaseTaskType; + +import org.apache.commons.logging.Log; + +import static net.osmand.plus.OsmandApplication.SHOW_PLUS_VERSION_INAPP_PARAM; + +@SuppressLint("Registered") +public class OsmandInAppPurchaseActivity extends AppCompatActivity implements InAppPurchaseListener { + private static final Log LOG = PlatformUtil.getLog(OsmandInAppPurchaseActivity.class); + + private InAppPurchaseHelper purchaseHelper; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (isInAppPurchaseAllowed() && isInAppPurchaseSupported()) { + purchaseHelper = getMyApplication().getInAppPurchaseHelper(); + } + } + + @Override + protected void onResume() { + super.onResume(); + initInAppPurchaseHelper(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + deinitInAppPurchaseHelper(); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + // Pass on the activity result to the helper for handling + if (purchaseHelper == null || !purchaseHelper.onActivityResultHandled(requestCode, resultCode, data)) { + // not handled, so handle it ourselves (here's where you'd + // perform any handling of activity results not related to in-app + // billing... + super.onActivityResult(requestCode, resultCode, data); + } + } + + private void initInAppPurchaseHelper() { + deinitInAppPurchaseHelper(); + + if (purchaseHelper != null) { + purchaseHelper.addListener(this); + if (purchaseHelper.needRequestInventory()) { + purchaseHelper.requestInventory(); + } + } + } + + private void deinitInAppPurchaseHelper() { + if (purchaseHelper != null) { + purchaseHelper.removeListener(this); + purchaseHelper.stop(); + } + } + + public void purchaseFullVersion() { + OsmandApplication app = getMyApplication(); + if (Version.isFreeVersion(app)) { + if (app.getRemoteBoolean(SHOW_PLUS_VERSION_INAPP_PARAM, true)) { + if (purchaseHelper != null) { + app.logEvent(this, "in_app_purchase_redirect"); + purchaseHelper.purchaseFullVersion(this); + } + } else { + app.logEvent(this, "paid_version_redirect"); + Intent intent = new Intent(Intent.ACTION_VIEW, + Uri.parse(Version.getUrlWithUtmRef(app, "net.osmand.plus"))); + try { + startActivity(intent); + } catch (ActivityNotFoundException e) { + LOG.error("ActivityNotFoundException", e); + } + } + } + } + + public void purchaseDepthContours() { + if (purchaseHelper != null) { + getMyApplication().logEvent(this, "depth_contours_purchase_redirect"); + purchaseHelper.purchaseDepthContours(this); + } + } + + public OsmandApplication getMyApplication() { + return (OsmandApplication) getApplication(); + } + + @Nullable + public InAppPurchaseHelper getPurchaseHelper() { + return purchaseHelper; + } + + public boolean isInAppPurchaseAllowed() { + return false; + } + + public boolean isInAppPurchaseSupported() { + return Version.isGooglePlayEnabled(getMyApplication()); + } + + @Override + public void onError(InAppPurchaseTaskType taskType, String error) { + onInAppPurchaseError(taskType, error); + } + + @Override + public void onGetItems() { + onInAppPurchaseGetItems(); + } + + @Override + public void onItemPurchased(String sku) { + onInAppPurchaseItemPurchased(sku); + } + + @Override + public void showProgress(InAppPurchaseTaskType taskType) { + showInAppPurchaseProgress(taskType); + } + + @Override + public void dismissProgress(InAppPurchaseTaskType taskType) { + dismissInAppPurchaseProgress(taskType); + } + + public void onInAppPurchaseError(InAppPurchaseTaskType taskType, String error) { + // not implemented + } + + public void onInAppPurchaseGetItems() { + // not implemented + } + + public void onInAppPurchaseItemPurchased(String sku) { + // not implemented + } + + public void showInAppPurchaseProgress(InAppPurchaseTaskType taskType) { + // not implemented + } + + public void dismissInAppPurchaseProgress(InAppPurchaseTaskType taskType) { + // not implemented + } +} diff --git a/OsmAnd/src/net/osmand/plus/dialogs/ChoosePlanDialogFragment.java b/OsmAnd/src/net/osmand/plus/dialogs/ChoosePlanDialogFragment.java index bc50903aaa..737dede9e3 100644 --- a/OsmAnd/src/net/osmand/plus/dialogs/ChoosePlanDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/dialogs/ChoosePlanDialogFragment.java @@ -6,11 +6,14 @@ import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; import android.net.Uri; +import android.os.Build; import android.os.Bundle; +import android.support.annotation.ColorRes; import android.support.annotation.LayoutRes; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.FragmentManager; +import android.support.v4.content.ContextCompat; import android.text.TextUtils; import android.view.ContextThemeWrapper; import android.view.LayoutInflater; @@ -18,68 +21,117 @@ import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.widget.LinearLayout; +import android.widget.ProgressBar; import android.widget.TextView; import net.osmand.AndroidUtils; import net.osmand.PlatformUtil; import net.osmand.plus.OsmandApplication; +import net.osmand.plus.OsmandPlugin; import net.osmand.plus.R; import net.osmand.plus.Version; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.base.BaseOsmAndDialogFragment; -import net.osmand.plus.download.DownloadActivity; import net.osmand.plus.download.DownloadValidationManager; -import net.osmand.plus.inapp.InAppHelper; +import net.osmand.plus.inapp.InAppPurchaseHelper; +import net.osmand.plus.inapp.InAppPurchaseHelper.InAppPurchaseListener; +import net.osmand.plus.inapp.InAppPurchaseHelper.InAppPurchaseTaskType; import net.osmand.plus.liveupdates.OsmLiveActivity; +import net.osmand.plus.srtmplugin.SRTMPlugin; import net.osmand.plus.widgets.TextViewEx; import org.apache.commons.logging.Log; import static net.osmand.plus.OsmandApplication.SHOW_PLUS_VERSION_INAPP_PARAM; -public class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment { +public class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment implements InAppPurchaseListener { public static final String TAG = ChoosePlanDialogFragment.class.getSimpleName(); private static final Log LOG = PlatformUtil.getLog(ChoosePlanDialogFragment.class); private static final String PLAN_TYPE_KEY = "plan_type"; + private OsmandApplication app; + private InAppPurchaseHelper purchaseHelper; + private boolean nightMode; private PlanType planType; - private OsmAndFeature[] osmandLiveFeatures = { - OsmAndFeature.UNLIMITED_DOWNLOADS, - OsmAndFeature.DAILY_MAP_UPDATES, - OsmAndFeature.WIKIPEDIA_OFFLINE, - OsmAndFeature.WIKIVOYAGE_OFFLINE, - OsmAndFeature.CONTOUR_LINES_SEA_DEPTH, - OsmAndFeature.DONATION_TO_OSM, -// OsmAndFeature.UNLOCK_ALL_FEATURES, - }; - - private OsmAndFeature[] osmandUnlimitedFeatures = { - OsmAndFeature.UNLIMITED_DOWNLOADS, - OsmAndFeature.MONTHLY_MAP_UPDATES, - OsmAndFeature.WIKIPEDIA_OFFLINE, - OsmAndFeature.WIKIVOYAGE_OFFLINE, - }; + private View osmLiveCardButton; + private View planTypeCardButton; public enum PlanType { - FREE_VERSION_BANNER(OsmAndFeature.UNLIMITED_DOWNLOADS, OsmAndFeature.UNLIMITED_DOWNLOADS); + FREE_VERSION_BANNER( + new OsmAndFeature[]{ + OsmAndFeature.DAILY_MAP_UPDATES, + OsmAndFeature.UNLIMITED_DOWNLOADS, + OsmAndFeature.WIKIPEDIA_OFFLINE, + OsmAndFeature.WIKIVOYAGE_OFFLINE, + OsmAndFeature.CONTOUR_LINES_HILLSHADE_MAPS, + OsmAndFeature.SEA_DEPTH_MAPS, + OsmAndFeature.UNLOCK_ALL_FEATURES, + OsmAndFeature.DONATION_TO_OSM, + }, + new OsmAndFeature[]{ + OsmAndFeature.DAILY_MAP_UPDATES, + OsmAndFeature.UNLIMITED_DOWNLOADS, + }, + new OsmAndFeature[]{ + OsmAndFeature.WIKIPEDIA_OFFLINE, + OsmAndFeature.WIKIVOYAGE_OFFLINE, + OsmAndFeature.UNLIMITED_DOWNLOADS, + OsmAndFeature.MONTHLY_MAP_UPDATES, + }, + new OsmAndFeature[]{}); - private final OsmAndFeature osmandLiveFeature; - private final OsmAndFeature osmandUnlimitedFeature; + private final OsmAndFeature[] osmLiveFeatures; + private final OsmAndFeature[] planTypeFeatures; + private final OsmAndFeature[] selectedOsmLiveFeatures; + private final OsmAndFeature[] selectedPlanTypeFeatures; - PlanType(OsmAndFeature osmandLiveFeature, OsmAndFeature osmandUnlimitedFeature) { - this.osmandLiveFeature = osmandLiveFeature; - this.osmandUnlimitedFeature = osmandUnlimitedFeature; + PlanType(OsmAndFeature[] osmLiveFeatures, OsmAndFeature[] selectedOsmLiveFeatures, + OsmAndFeature[] planTypeFeatures, OsmAndFeature[] selectedPlanTypeFeatures) { + this.osmLiveFeatures = osmLiveFeatures; + this.planTypeFeatures = planTypeFeatures; + this.selectedOsmLiveFeatures = selectedOsmLiveFeatures; + this.selectedPlanTypeFeatures = selectedPlanTypeFeatures; } - public OsmAndFeature getOsmandLiveFeature() { - return osmandLiveFeature; + public OsmAndFeature[] getOsmLiveFeatures() { + return osmLiveFeatures; } - public OsmAndFeature getOsmandUnlimitedFeature() { - return osmandUnlimitedFeature; + public OsmAndFeature[] getPlanTypeFeatures() { + return planTypeFeatures; + } + + public OsmAndFeature[] getSelectedOsmLiveFeatures() { + return selectedOsmLiveFeatures; + } + + public OsmAndFeature[] getSelectedPlanTypeFeatures() { + return selectedPlanTypeFeatures; + } + + public boolean hasSelectedOsmLiveFeature(OsmAndFeature feature) { + if (selectedOsmLiveFeatures != null) { + for (OsmAndFeature f : selectedOsmLiveFeatures) { + if (feature == f) { + return true; + } + } + } + return false; + } + + public boolean hasSelectedPlanTypeFeature(OsmAndFeature feature) { + if (selectedPlanTypeFeatures != null) { + for (OsmAndFeature f : selectedPlanTypeFeatures) { + if (feature == f) { + return true; + } + } + } + return false; } } @@ -89,7 +141,8 @@ public class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment { MONTHLY_MAP_UPDATES(R.string.monthly_map_updates), UNLIMITED_DOWNLOADS(R.string.unlimited_downloads), WIKIPEDIA_OFFLINE(R.string.wikipedia_offline), - CONTOUR_LINES_SEA_DEPTH(R.string.contour_lines_sea_depth), + CONTOUR_LINES_HILLSHADE_MAPS(R.string.contour_lines_hillshade_maps), + SEA_DEPTH_MAPS(R.string.index_item_depth_contours_osmand_ext), UNLOCK_ALL_FEATURES(R.string.unlock_all_features), DONATION_TO_OSM(R.string.donation_to_osm); @@ -103,9 +156,27 @@ public class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment { return ctx.getString(key); } + public boolean isFeaturePurchased(OsmandApplication ctx) { + switch (this) { + case DAILY_MAP_UPDATES: + case MONTHLY_MAP_UPDATES: + case UNLIMITED_DOWNLOADS: + case WIKIPEDIA_OFFLINE: + case UNLOCK_ALL_FEATURES: + case DONATION_TO_OSM: + return false; + case WIKIVOYAGE_OFFLINE: + return ctx.getSettings().TRAVEL_ARTICLES_PURCHASED.get(); + case CONTOUR_LINES_HILLSHADE_MAPS: + boolean srtmEnabled = OsmandPlugin.getEnabledPlugin(SRTMPlugin.class) != null; + return srtmEnabled && ctx.getSettings().DEPTH_CONTOURS_PURCHASED.get(); + } + return false; + } + public static OsmAndFeature[] possibleValues() { return new OsmAndFeature[]{WIKIVOYAGE_OFFLINE, DAILY_MAP_UPDATES, MONTHLY_MAP_UPDATES, UNLIMITED_DOWNLOADS, - WIKIPEDIA_OFFLINE, CONTOUR_LINES_SEA_DEPTH, UNLOCK_ALL_FEATURES, DONATION_TO_OSM}; + WIKIPEDIA_OFFLINE, CONTOUR_LINES_HILLSHADE_MAPS, UNLOCK_ALL_FEATURES, DONATION_TO_OSM}; } } @@ -113,6 +184,9 @@ public class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + app = getMyApplication(); + purchaseHelper = app.getInAppPurchaseHelper(); + Bundle args = getArguments(); if (args == null) { args = savedInstanceState; @@ -130,13 +204,16 @@ public class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment { @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { - int themeId = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme; + int themeId = nightMode ? R.style.OsmandDarkTheme_DarkActionbar : R.style.OsmandLightTheme_DarkActionbar_LightStatusBar; Dialog dialog = new Dialog(getContext(), themeId); Window window = dialog.getWindow(); if (window != null) { if (!getSettings().DO_NOT_USE_ANIMATIONS.get()) { window.getAttributes().windowAnimations = R.style.Animations_Alpha; } + if (Build.VERSION.SDK_INT >= 21) { + window.setStatusBarColor(ContextCompat.getColor(getContext(), getStatusBarColor())); + } } return dialog; } @@ -169,68 +246,28 @@ public class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment { switch (planType) { case FREE_VERSION_BANNER: { - infoDescription.setText(ctx.getString(R.string.free_version_message, + infoDescription.setText(getString(R.string.free_version_message, DownloadValidationManager.MAXIMUM_AVAILABLE_FREE_DOWNLOADS)); - //infoDescription.setVisibility(View.GONE); - //View freeVersionInfoView = inflate(R.layout.purchase_dialog_info_free_version, infoContainer); - //initFreeVersionInfoView(ctx, freeVersionInfoView); - //infoContainer.addView(freeVersionInfoView); - break; } } - cardsContainer.addView(buildOsmAndLiveCard(ctx, cardsContainer)); - cardsContainer.addView(buildOsmAndUnlimitedCard(ctx, cardsContainer)); + cardsContainer.addView(buildOsmLiveCard(ctx, cardsContainer)); + cardsContainer.addView(buildPlanTypeCard(ctx, cardsContainer)); return view; } - /* - private void initFreeVersionInfoView(Context ctx, View freeVersionInfoView) { - TextView downloadsLeftTextView = (TextView) freeVersionInfoView.findViewById(R.id.downloadsLeftTextView); - ProgressBar downloadsLeftProgressBar = (ProgressBar) freeVersionInfoView.findViewById(R.id.downloadsLeftProgressBar); - TextView freeVersionDescriptionTextView = (TextView) freeVersionInfoView - .findViewById(R.id.freeVersionDescriptionTextView); - - OsmandSettings settings = getMyApplication().getSettings(); - final Integer mapsDownloaded = settings.NUMBER_OF_FREE_DOWNLOADS.get(); - downloadsLeftProgressBar.setProgress(mapsDownloaded); - int downloadsLeft = DownloadValidationManager.MAXIMUM_AVAILABLE_FREE_DOWNLOADS - mapsDownloaded; - downloadsLeft = Math.max(downloadsLeft, 0); - downloadsLeftTextView.setText(ctx.getString(R.string.downloads_left_template, downloadsLeft)); - downloadsLeftProgressBar.setMax(DownloadValidationManager.MAXIMUM_AVAILABLE_FREE_DOWNLOADS); - freeVersionDescriptionTextView.setText(ctx.getString(R.string.free_version_message, - DownloadValidationManager.MAXIMUM_AVAILABLE_FREE_DOWNLOADS)); - - LinearLayout marksLinearLayout = (LinearLayout) freeVersionInfoView.findViewById(R.id.marksLinearLayout); - Space spaceView = new Space(ctx); - LinearLayout.LayoutParams layoutParams = - new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT, 1); - spaceView.setLayoutParams(layoutParams); - marksLinearLayout.addView(spaceView); - int markWidth = (int) (1 * ctx.getResources().getDisplayMetrics().density); - int colorBlack = ctx.getResources().getColor(nightMode ? R.color.wikivoyage_bg_dark : R.color.wikivoyage_bg_light); - for (int i = 1; i < DownloadValidationManager.MAXIMUM_AVAILABLE_FREE_DOWNLOADS; i++) { - View markView = new View(ctx); - layoutParams = new LinearLayout.LayoutParams(markWidth, ViewGroup.LayoutParams.MATCH_PARENT); - markView.setLayoutParams(layoutParams); - markView.setBackgroundColor(colorBlack); - marksLinearLayout.addView(markView); - spaceView = new Space(ctx); - layoutParams = new LinearLayout.LayoutParams(0, - ViewGroup.LayoutParams.MATCH_PARENT, 1); - spaceView.setLayoutParams(layoutParams); - marksLinearLayout.addView(spaceView); - } + @ColorRes + protected int getStatusBarColor() { + return nightMode ? R.color.status_bar_wikivoyage_dark : R.color.status_bar_wikivoyage_light; } - */ private View inflate(@LayoutRes int layoutId, @Nullable ViewGroup container) { - int themeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme; + int themeRes = nightMode ? R.style.OsmandDarkTheme_DarkActionbar : R.style.OsmandLightTheme_DarkActionbar_LightStatusBar; return LayoutInflater.from(new ContextThemeWrapper(getContext(), themeRes)) .inflate(layoutId, container, false); } - private ViewGroup buildOsmAndLiveCard(@NonNull Context ctx, ViewGroup container) { + private ViewGroup buildOsmLiveCard(@NonNull Context ctx, ViewGroup container) { ViewGroup cardView = (ViewGroup) inflate(R.layout.purchase_dialog_active_card, container); TextView headerTitle = (TextView) cardView.findViewById(R.id.header_title); TextView headerDescr = (TextView) cardView.findViewById(R.id.header_descr); @@ -238,11 +275,10 @@ public class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment { headerDescr.setText(R.string.osm_live_subscription); ViewGroup rowsContainer = (ViewGroup) cardView.findViewById(R.id.rows_container); View featureRowDiv = null; - for (OsmAndFeature feature : osmandLiveFeatures) { + for (OsmAndFeature feature : planType.getOsmLiveFeatures()) { String featureName = feature.toHumanString(ctx); -// View featureRow = inflate(planType.osmandLiveFeature == feature -// ? R.layout.purchase_dialog_card_selected_row : R.layout.purchase_dialog_card_row, cardView); - View featureRow = inflate(R.layout.purchase_dialog_card_row, cardView); + View featureRow = inflate(planType.hasSelectedOsmLiveFeature(feature) + ? R.layout.purchase_dialog_card_selected_row : R.layout.purchase_dialog_card_row, cardView); TextViewEx titleView = (TextViewEx) featureRow.findViewById(R.id.title); titleView.setText(featureName); featureRowDiv = featureRow.findViewById(R.id.div); @@ -257,29 +293,49 @@ public class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment { TextViewEx cardDescription = (TextViewEx) cardView.findViewById(R.id.card_descr); cardDescription.setText(R.string.osm_live_payment_desc); - View cardButton = cardView.findViewById(R.id.card_button); - TextViewEx buttonTitle = (TextViewEx) cardButton.findViewById(R.id.card_button_title); - TextViewEx buttonSubtitle = (TextViewEx) cardButton.findViewById(R.id.card_button_subtitle); - if (!InAppHelper.hasPrices(getMyApplication())) { - buttonTitle.setText(ctx.getString(R.string.purchase_subscription_title, ctx.getString(R.string.osm_live_default_price))); - } else { - buttonTitle.setText(ctx.getString(R.string.purchase_subscription_title, InAppHelper.getLiveUpdatesPrice())); - } - buttonSubtitle.setText(R.string.osm_live_month_cost_desc); - cardButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - subscript(); - dismiss(); - } - }); + osmLiveCardButton = cardView.findViewById(R.id.card_button); + InAppPurchaseHelper purchaseHelper = app.getInAppPurchaseHelper(); + boolean requestingInventory = purchaseHelper != null && purchaseHelper.getActiveTask() == InAppPurchaseTaskType.REQUEST_INVENTORY; + setupOsmLiveCardButton(requestingInventory); + return cardView; } + private void setupOsmLiveCardButton(boolean progress) { + if (osmLiveCardButton != null) { + ProgressBar progressBar = (ProgressBar) osmLiveCardButton.findViewById(R.id.card_button_progress); + TextViewEx buttonTitle = (TextViewEx) osmLiveCardButton.findViewById(R.id.card_button_title); + TextViewEx buttonSubtitle = (TextViewEx) osmLiveCardButton.findViewById(R.id.card_button_subtitle); + if (!purchaseHelper.hasPrices()) { + buttonTitle.setText(getString(R.string.purchase_subscription_title, getString(R.string.osm_live_default_price))); + } else { + buttonTitle.setText(getString(R.string.purchase_subscription_title, purchaseHelper.getLiveUpdatesPrice())); + } + buttonSubtitle.setText(R.string.osm_live_month_cost_desc); + if (progress) { + buttonTitle.setVisibility(View.GONE); + buttonSubtitle.setVisibility(View.GONE); + progressBar.setVisibility(View.VISIBLE); + osmLiveCardButton.setOnClickListener(null); + } else { + buttonTitle.setVisibility(View.VISIBLE); + buttonSubtitle.setVisibility(View.VISIBLE); + progressBar.setVisibility(View.GONE); + osmLiveCardButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + subscript(); + dismiss(); + } + }); + } + } + } + private void subscript() { Activity ctx = getActivity(); if (ctx != null) { - getMyApplication().logEvent(ctx, "click_subscribe_live_osm"); + app.logEvent(ctx, "click_subscribe_live_osm"); Intent intent = new Intent(ctx, OsmLiveActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); intent.putExtra(OsmLiveActivity.OPEN_SUBSCRIPTION_INTENT_PARAM, true); @@ -287,7 +343,7 @@ public class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment { } } - private ViewGroup buildOsmAndUnlimitedCard(@NonNull Context ctx, ViewGroup container) { + private ViewGroup buildPlanTypeCard(@NonNull Context ctx, ViewGroup container) { ViewGroup cardView = (ViewGroup) inflate(R.layout.purchase_dialog_card, container); TextView headerTitle = (TextView) cardView.findViewById(R.id.header_title); TextView headerDescr = (TextView) cardView.findViewById(R.id.header_descr); @@ -295,9 +351,9 @@ public class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment { headerDescr.setText(R.string.in_app_purchase); ViewGroup rowsContainer = (ViewGroup) cardView.findViewById(R.id.rows_container); View featureRow = null; - for (OsmAndFeature feature : osmandUnlimitedFeatures) { + for (OsmAndFeature feature : planType.getPlanTypeFeatures()) { String featureName = feature.toHumanString(ctx); - featureRow = inflate(planType.osmandUnlimitedFeature == feature + featureRow = inflate(planType.hasSelectedPlanTypeFeature(feature) ? R.layout.purchase_dialog_card_selected_row : R.layout.purchase_dialog_card_row, cardView); TextViewEx titleView = (TextViewEx) featureRow.findViewById(R.id.title); titleView.setText(featureName); @@ -309,28 +365,46 @@ public class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment { TextViewEx cardDescription = (TextViewEx) cardView.findViewById(R.id.card_descr); cardDescription.setText(R.string.in_app_purchase_desc_ex); - View cardButton = cardView.findViewById(R.id.card_button); - TextViewEx buttonTitle = (TextViewEx) cardButton.findViewById(R.id.card_button_title); - TextViewEx buttonSubtitle = (TextViewEx) cardButton.findViewById(R.id.card_button_subtitle); - if (!InAppHelper.hasPrices(getMyApplication())) { - buttonTitle.setText(ctx.getString(R.string.purchase_unlim_title, ctx.getString(R.string.full_version_price))); - } else { - buttonTitle.setText(ctx.getString(R.string.purchase_unlim_title, InAppHelper.getFullVersionPrice())); - } - buttonSubtitle.setText(R.string.in_app_purchase_desc); - cardButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - purchaseFullVersion(); - dismiss(); - } - }); + planTypeCardButton = cardView.findViewById(R.id.card_button); + InAppPurchaseHelper purchaseHelper = app.getInAppPurchaseHelper(); + boolean requestingInventory = purchaseHelper != null && purchaseHelper.getActiveTask() == InAppPurchaseTaskType.REQUEST_INVENTORY; + setupPlanTypeCardButton(requestingInventory); + return cardView; } + private void setupPlanTypeCardButton(boolean progress) { + if (planTypeCardButton != null) { + ProgressBar progressBar = (ProgressBar) planTypeCardButton.findViewById(R.id.card_button_progress); + TextViewEx buttonTitle = (TextViewEx) planTypeCardButton.findViewById(R.id.card_button_title); + TextViewEx buttonSubtitle = (TextViewEx) planTypeCardButton.findViewById(R.id.card_button_subtitle); + if (!purchaseHelper.hasPrices()) { + buttonTitle.setText(getString(R.string.purchase_unlim_title, getString(R.string.full_version_price))); + } else { + buttonTitle.setText(getString(R.string.purchase_unlim_title, purchaseHelper.getFullVersionPrice())); + } + buttonSubtitle.setText(R.string.in_app_purchase_desc); + if (progress) { + buttonTitle.setVisibility(View.GONE); + buttonSubtitle.setVisibility(View.GONE); + progressBar.setVisibility(View.VISIBLE); + planTypeCardButton.setOnClickListener(null); + } else { + buttonTitle.setVisibility(View.VISIBLE); + buttonSubtitle.setVisibility(View.VISIBLE); + progressBar.setVisibility(View.GONE); + planTypeCardButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + purchaseFullVersion(); + dismiss(); + } + }); + } + } + } + public void purchaseFullVersion() { - /* - OsmandApplication app = getMyApplication(); if (app.getRemoteBoolean(SHOW_PLUS_VERSION_INAPP_PARAM, true)) { app.logEvent(getActivity(), "in_app_purchase_redirect_from_banner"); } else { @@ -338,12 +412,13 @@ public class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment { } if (Version.isFreeVersion(app)) { if (app.getRemoteBoolean(SHOW_PLUS_VERSION_INAPP_PARAM, true)) { - if (inAppHelper != null) { - app.logEvent(this, "in_app_purchase_redirect"); - inAppHelper.purchaseFullVersion(this); + InAppPurchaseHelper purchaseHelper = app.getInAppPurchaseHelper(); + if (purchaseHelper != null) { + app.logEvent(getActivity(), "in_app_purchase_redirect"); + purchaseHelper.purchaseFullVersion(getActivity()); } } else { - app.logEvent(this, "paid_version_redirect"); + app.logEvent(getActivity(), "paid_version_redirect"); Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(Version.getUrlWithUtmRef(app, "net.osmand.plus"))); try { @@ -353,7 +428,6 @@ public class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment { } } } - */ } @Override @@ -391,6 +465,38 @@ public class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment { } } + @Override + public void onError(InAppPurchaseTaskType taskType, String error) { + if (taskType == InAppPurchaseTaskType.REQUEST_INVENTORY) { + setupOsmLiveCardButton(false); + setupPlanTypeCardButton(false); + } + } + + @Override + public void onGetItems() { + } + + @Override + public void onItemPurchased(String sku) { + } + + @Override + public void showProgress(InAppPurchaseTaskType taskType) { + if (taskType == InAppPurchaseTaskType.REQUEST_INVENTORY) { + setupOsmLiveCardButton(true); + setupPlanTypeCardButton(true); + } + } + + @Override + public void dismissProgress(InAppPurchaseTaskType taskType) { + if (taskType == InAppPurchaseTaskType.REQUEST_INVENTORY) { + setupOsmLiveCardButton(false); + setupPlanTypeCardButton(false); + } + } + public static void showFreeVersionInstance(@NonNull FragmentManager fm) { PlanType planType = PlanType.FREE_VERSION_BANNER; showInstance(fm, planType); diff --git a/OsmAnd/src/net/osmand/plus/download/DownloadActivity.java b/OsmAnd/src/net/osmand/plus/download/DownloadActivity.java index 2ad07ae837..1a2fb4fddc 100644 --- a/OsmAnd/src/net/osmand/plus/download/DownloadActivity.java +++ b/OsmAnd/src/net/osmand/plus/download/DownloadActivity.java @@ -1,12 +1,11 @@ package net.osmand.plus.download; import android.Manifest; -import android.content.ActivityNotFoundException; +import android.annotation.SuppressLint; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; -import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.os.StatFs; @@ -21,7 +20,6 @@ import android.support.v4.content.ContextCompat; import android.support.v4.view.ViewPager; import android.support.v4.widget.Space; import android.support.v7.app.AlertDialog; -import android.support.v7.widget.AppCompatButton; import android.text.method.LinkMovementMethod; import android.view.LayoutInflater; import android.view.MenuItem; @@ -54,17 +52,15 @@ import net.osmand.plus.activities.TabActivity; import net.osmand.plus.base.BasicProgressAsyncTask; import net.osmand.plus.base.BottomSheetDialogFragment; import net.osmand.plus.dialogs.ChoosePlanDialogFragment; -import net.osmand.plus.dialogs.ChoosePlanDialogFragment.PlanType; import net.osmand.plus.download.DownloadIndexesThread.DownloadEvents; import net.osmand.plus.download.ui.ActiveDownloadsDialogFragment; import net.osmand.plus.download.ui.DownloadResourceGroupFragment; -import net.osmand.plus.download.ui.FreeVersionDialogFragment; import net.osmand.plus.download.ui.LocalIndexesFragment; import net.osmand.plus.download.ui.UpdatesIndexFragment; import net.osmand.plus.helpers.FileNameTranslationHelper; -import net.osmand.plus.inapp.InAppHelper; -import net.osmand.plus.inapp.InAppHelper.InAppListener; -import net.osmand.plus.liveupdates.OsmLiveActivity; +import net.osmand.plus.inapp.InAppPurchaseHelper; +import net.osmand.plus.inapp.InAppPurchaseHelper.InAppPurchaseListener; +import net.osmand.plus.inapp.InAppPurchaseHelper.InAppPurchaseTaskType; import net.osmand.plus.openseamapsplugin.NauticalMapsPlugin; import net.osmand.plus.srtmplugin.SRTMPlugin; import net.osmand.plus.views.controls.PagerSlidingTabStrip; @@ -83,10 +79,8 @@ import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import static net.osmand.plus.OsmandApplication.SHOW_PLUS_VERSION_INAPP_PARAM; - public class DownloadActivity extends AbstractDownloadActivity implements DownloadEvents, - OnRequestPermissionsResultCallback, InAppListener { + OnRequestPermissionsResultCallback { private static final Log LOG = PlatformUtil.getLog(DownloadActivity.class); public static final int UPDATES_TAB_NUMBER = 2; @@ -122,8 +116,6 @@ public class DownloadActivity extends AbstractDownloadActivity implements Downlo protected WorldRegion downloadItem; protected String downloadTargetFileName; - private InAppHelper inAppHelper; - private boolean srtmDisabled; private boolean srtmNeedsInstallation; private boolean nauticalPluginDisabled; @@ -196,11 +188,9 @@ public class DownloadActivity extends AbstractDownloadActivity implements Downlo visibleBanner = new BannerAndDownloadFreeVersion(findViewById(R.id.mainLayout), this, true); if (shouldShowFreeVersionBanner(getMyApplication())) { - visibleBanner.setUpdatingPrices(true); + visibleBanner.updateFreeVersionBanner(); } - startInAppHelper(); - final Intent intent = getIntent(); if (intent != null && intent.getExtras() != null) { filter = intent.getExtras().getString(FILTER_KEY); @@ -209,65 +199,60 @@ public class DownloadActivity extends AbstractDownloadActivity implements Downlo } } - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - // Pass on the activity result to the helper for handling - if (inAppHelper == null || !inAppHelper.onActivityResultHandled(requestCode, resultCode, data)) { - // not handled, so handle it ourselves (here's where you'd - // perform any handling of activity results not related to in-app - // billing... - super.onActivityResult(requestCode, resultCode, data); - } + public boolean isInAppPurchaseAllowed() { + return true; } @Override - public void onDestroy() { - super.onDestroy(); - stopInAppHelper(); - } - - public void startInAppHelper() { - stopInAppHelper(); - - if (Version.isGooglePlayEnabled(getMyApplication())) { - inAppHelper = new InAppHelper(getMyApplication(), true); - inAppHelper.addListener(this); - inAppHelper.start(false); - } - } - - public void stopInAppHelper() { - if (inAppHelper != null) { - inAppHelper.removeListener(this); - inAppHelper.stop(); - } - } - - public void purchaseFullVersion() { - OsmandApplication app = getMyApplication(); - if (Version.isFreeVersion(app)) { - if (app.getRemoteBoolean(SHOW_PLUS_VERSION_INAPP_PARAM, true)) { - if (inAppHelper != null) { - app.logEvent(this, "in_app_purchase_redirect"); - inAppHelper.purchaseFullVersion(this); - } - } else { - app.logEvent(this, "paid_version_redirect"); - Intent intent = new Intent(Intent.ACTION_VIEW, - Uri.parse(Version.getUrlWithUtmRef(app, "net.osmand.plus"))); - try { - startActivity(intent); - } catch (ActivityNotFoundException e) { - LOG.error("ActivityNotFoundException", e); - } + public void onInAppPurchaseError(InAppPurchaseTaskType taskType, String error) { + visibleBanner.updateFreeVersionBanner(); + for (WeakReference ref : fragSet) { + Fragment f = ref.get(); + if (f instanceof InAppPurchaseListener && f.isAdded()) { + ((InAppPurchaseListener) f).onError(taskType, error); } } } - public void purchaseDepthContours() { - if (inAppHelper != null) { - getMyApplication().logEvent(this, "depth_contours_purchase_redirect"); - inAppHelper.purchaseDepthContours(this); + @Override + public void onInAppPurchaseGetItems() { + visibleBanner.updateFreeVersionBanner(); + for (WeakReference ref : fragSet) { + Fragment f = ref.get(); + if (f instanceof InAppPurchaseListener && f.isAdded()) { + ((InAppPurchaseListener) f).onGetItems(); + } + } + } + + @Override + public void onInAppPurchaseItemPurchased(String sku) { + visibleBanner.updateFreeVersionBanner(); + for (WeakReference ref : fragSet) { + Fragment f = ref.get(); + if (f instanceof InAppPurchaseListener && f.isAdded()) { + ((InAppPurchaseListener) f).onItemPurchased(sku); + } + } + } + + @Override + public void showInAppPurchaseProgress(InAppPurchaseTaskType taskType) { + for (WeakReference ref : fragSet) { + Fragment f = ref.get(); + if (f instanceof InAppPurchaseListener && f.isAdded()) { + ((InAppPurchaseListener) f).showProgress(taskType); + } + } + } + + @Override + public void dismissInAppPurchaseProgress(InAppPurchaseTaskType taskType) { + for (WeakReference ref : fragSet) { + Fragment f = ref.get(); + if (f instanceof InAppPurchaseListener && f.isAdded()) { + ((InAppPurchaseListener) f).dismissProgress(taskType); + } } } @@ -369,59 +354,6 @@ public class DownloadActivity extends AbstractDownloadActivity implements Downlo } } - @Override - public void onError(String error) { - visibleBanner.setUpdatingPrices(false); - for (WeakReference ref : fragSet) { - Fragment f = ref.get(); - if (f instanceof InAppListener && f.isAdded()) { - ((InAppListener) f).onError(error); - } - } - } - - @Override - public void onGetItems() { - visibleBanner.setUpdatingPrices(false); - for (WeakReference ref : fragSet) { - Fragment f = ref.get(); - if (f instanceof InAppListener && f.isAdded()) { - ((InAppListener) f).onGetItems(); - } - } - } - - @Override - public void onItemPurchased(String sku) { - visibleBanner.setUpdatingPrices(false); - for (WeakReference ref : fragSet) { - Fragment f = ref.get(); - if (f instanceof InAppListener && f.isAdded()) { - ((InAppListener) f).onItemPurchased(sku); - } - } - } - - @Override - public void showProgress() { - for (WeakReference ref : fragSet) { - Fragment f = ref.get(); - if (f instanceof InAppListener && f.isAdded()) { - ((InAppListener) f).showProgress(); - } - } - } - - @Override - public void dismissProgress() { - for (WeakReference ref : fragSet) { - Fragment f = ref.get(); - if (f instanceof InAppListener && f.isAdded()) { - ((InAppListener) f).dismissProgress(); - } - } - } - @Override @UiThread public void downloadInProgress() { @@ -478,26 +410,15 @@ public class DownloadActivity extends AbstractDownloadActivity implements Downlo } - public static class FreeVersionDialog { + public static class FreeVersionBanner { private final View freeVersionBanner; private final View freeVersionBannerTitle; - private boolean updatingPrices; - private final View priceInfoLayout; private final TextView freeVersionDescriptionTextView; private final TextView downloadsLeftTextView; private final ProgressBar downloadsLeftProgressBar; -// private final View laterButton; -// private final View buttonsLinearLayout; - - private final View fullVersionProgress; - private final AppCompatButton fullVersionButton; - private final View osmLiveProgress; - private final AppCompatButton osmLiveButton; private DownloadActivity ctx; - private boolean dialog; - private OnClickListener onCollapseListener = new OnClickListener() { @Override public void onClick(View v) { @@ -511,45 +432,26 @@ public class DownloadActivity extends AbstractDownloadActivity implements Downlo } }; - public FreeVersionDialog(View view, final DownloadActivity ctx, boolean dialog) { + public FreeVersionBanner(View view, final DownloadActivity ctx) { this.ctx = ctx; - this.dialog = dialog; freeVersionBanner = view.findViewById(R.id.freeVersionBanner); downloadsLeftTextView = (TextView) freeVersionBanner.findViewById(R.id.downloadsLeftTextView); downloadsLeftProgressBar = (ProgressBar) freeVersionBanner.findViewById(R.id.downloadsLeftProgressBar); - priceInfoLayout = freeVersionBanner.findViewById(R.id.priceInfoLayout); freeVersionDescriptionTextView = (TextView) freeVersionBanner .findViewById(R.id.freeVersionDescriptionTextView); freeVersionBannerTitle = freeVersionBanner.findViewById(R.id.freeVersionBannerTitle); - // laterButton = freeVersionBanner.findViewById(R.id.laterButton); - // buttonsLinearLayout = freeVersionBanner.findViewById(R.id.buttonsLinearLayout); - - fullVersionProgress = freeVersionBanner.findViewById(R.id.fullVersionProgress); - fullVersionButton = (AppCompatButton) freeVersionBanner.findViewById(R.id.fullVersionButton); - osmLiveProgress = freeVersionBanner.findViewById(R.id.osmLiveProgress); - osmLiveButton = (AppCompatButton) freeVersionBanner.findViewById(R.id.osmLiveButton); - } - - public void setUpdatingPrices(boolean updatingPrices) { - this.updatingPrices = updatingPrices; - updateFreeVersionBanner(); } private void collapseBanner() { freeVersionDescriptionTextView.setVisibility(View.GONE); - // buttonsLinearLayout.setVisibility(View.GONE); - priceInfoLayout.setVisibility(View.GONE); freeVersionBannerTitle.setVisibility(View.VISIBLE); } public void expandBanner() { freeVersionDescriptionTextView.setVisibility(View.VISIBLE); - // buttonsLinearLayout.setVisibility(View.VISIBLE); - priceInfoLayout.setVisibility(View.VISIBLE); freeVersionBannerTitle.setVisibility(View.VISIBLE); } - public void initFreeVersionBanner() { if (!shouldShowFreeVersionBanner(ctx.getMyApplication())) { freeVersionBanner.setVisibility(View.GONE); @@ -559,33 +461,6 @@ public class DownloadActivity extends AbstractDownloadActivity implements Downlo downloadsLeftProgressBar.setMax(DownloadValidationManager.MAXIMUM_AVAILABLE_FREE_DOWNLOADS); freeVersionDescriptionTextView.setText(ctx.getString(R.string.free_version_message, DownloadValidationManager.MAXIMUM_AVAILABLE_FREE_DOWNLOADS)); - fullVersionButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - OsmandApplication app = ctx.getMyApplication(); - if (app.getRemoteBoolean(SHOW_PLUS_VERSION_INAPP_PARAM, true)) { - app.logEvent(ctx, "in_app_purchase_redirect_from_banner"); - } else { - app.logEvent(ctx, "paid_version_redirect_from_banner"); - } - ctx.purchaseFullVersion(); - DialogFragment f = (DialogFragment) ctx.getSupportFragmentManager() - .findFragmentByTag(FreeVersionDialogFragment.TAG); - if (f != null) { - f.dismiss(); - } - } - }); - osmLiveButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - ctx.getMyApplication().logEvent(ctx, "click_subscribe_live_osm"); - Intent intent = new Intent(ctx, OsmLiveActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); - intent.putExtra(OsmLiveActivity.OPEN_SUBSCRIPTION_INTENT_PARAM, true); - ctx.startActivity(intent); - } - }); LinearLayout marksLinearLayout = (LinearLayout) freeVersionBanner.findViewById(R.id.marksLinearLayout); Space spaceView = new Space(ctx); @@ -609,11 +484,7 @@ public class DownloadActivity extends AbstractDownloadActivity implements Downlo } updateFreeVersionBanner(); - if(dialog) { - expandBanner(); - } else { - collapseBanner(); - } + collapseBanner(); } public void updateFreeVersionBanner() { @@ -630,28 +501,7 @@ public class DownloadActivity extends AbstractDownloadActivity implements Downlo int downloadsLeft = DownloadValidationManager.MAXIMUM_AVAILABLE_FREE_DOWNLOADS - mapsDownloaded; downloadsLeft = Math.max(downloadsLeft, 0); downloadsLeftTextView.setText(ctx.getString(R.string.downloads_left_template, downloadsLeft)); - if(!dialog) { - freeVersionBanner.findViewById(R.id.bannerTopLayout).setOnClickListener(onCollapseListener); - } - - if (InAppHelper.hasPrices(ctx.getMyApplication()) || !updatingPrices) { - if (!InAppHelper.hasPrices(ctx.getMyApplication())) { - fullVersionButton.setText(ctx.getString(R.string.get_for, ctx.getString(R.string.full_version_price))); - osmLiveButton.setText(ctx.getString(R.string.get_for_month, ctx.getString(R.string.osm_live_default_price))); - } else { - fullVersionButton.setText(ctx.getString(R.string.get_for, InAppHelper.getFullVersionPrice())); - osmLiveButton.setText(ctx.getString(R.string.get_for_month, InAppHelper.getLiveUpdatesPrice())); - } - fullVersionProgress.setVisibility(View.GONE); - fullVersionButton.setVisibility(View.VISIBLE); - osmLiveProgress.setVisibility(View.GONE); - osmLiveButton.setVisibility(View.VISIBLE); - } else { - fullVersionProgress.setVisibility(View.VISIBLE); - fullVersionButton.setVisibility(View.GONE); - osmLiveProgress.setVisibility(View.VISIBLE); - osmLiveButton.setVisibility(View.GONE); - } + freeVersionBanner.findViewById(R.id.bannerTopLayout).setOnClickListener(onCollapseListener); } private void setMinimizedFreeVersionBanner(boolean minimize) { @@ -668,7 +518,6 @@ public class DownloadActivity extends AbstractDownloadActivity implements Downlo final Integer mapsDownloaded = settings.NUMBER_OF_FREE_DOWNLOADS.get() + activeTasks; downloadsLeftProgressBar.setProgress(mapsDownloaded); } - } public static class BannerAndDownloadFreeVersion { @@ -681,26 +530,24 @@ public class DownloadActivity extends AbstractDownloadActivity implements Downlo private final DownloadActivity ctx; private boolean showSpace; - private FreeVersionDialog freeVersionDialog; + private FreeVersionBanner freeVersionBanner; public BannerAndDownloadFreeVersion(View view, final DownloadActivity ctx, boolean showSpace) { this.ctx = ctx; this.showSpace = showSpace; - freeVersionDialog = new FreeVersionDialog(view, ctx, false); + freeVersionBanner = new FreeVersionBanner(view, ctx); downloadProgressLayout = view.findViewById(R.id.downloadProgressLayout); progressBar = (ProgressBar) view.findViewById(R.id.progressBar); leftTextView = (TextView) view.findViewById(R.id.leftTextView); rightTextView = (TextView) view.findViewById(R.id.rightTextView); - - - freeVersionDialog.initFreeVersionBanner(); + freeVersionBanner.initFreeVersionBanner(); updateBannerInProgress(); } - public void setUpdatingPrices(boolean updatingPrices) { - freeVersionDialog.setUpdatingPrices(updatingPrices); + public void updateFreeVersionBanner() { + freeVersionBanner.updateFreeVersionBanner(); } public void updateBannerInProgress() { @@ -715,13 +562,13 @@ public class DownloadActivity extends AbstractDownloadActivity implements Downlo } else { downloadProgressLayout.setVisibility(View.VISIBLE); } - freeVersionDialog.updateFreeVersionBanner(); + freeVersionBanner.updateFreeVersionBanner(); } else { boolean indeterminate = basicProgressAsyncTask.isIndeterminate(); String message = basicProgressAsyncTask.getDescription(); int percent = basicProgressAsyncTask.getProgressPercentage(); - freeVersionDialog.setMinimizedFreeVersionBanner(true); - freeVersionDialog.updateAvailableDownloads(); + freeVersionBanner.setMinimizedFreeVersionBanner(true); + freeVersionBanner.updateAvailableDownloads(); downloadProgressLayout.setVisibility(View.VISIBLE); downloadProgressLayout.setOnClickListener(new OnClickListener() { @Override @@ -735,27 +582,14 @@ public class DownloadActivity extends AbstractDownloadActivity implements Downlo rightTextView.setText(null); } else { progressBar.setProgress(percent); -// final String format = ctx.getString(R.string.downloading_number_of_files); leftTextView.setText(message); rightTextView.setText(percent + "%"); } } } - - - public void hideDownloadProgressLayout() { - downloadProgressLayout.setVisibility(View.GONE); - } - - public void showDownloadProgressLayout() { - downloadProgressLayout.setVisibility(View.VISIBLE); - } - - - - } + @SuppressLint("StaticFieldLeak") public void reloadLocalIndexes() { AsyncTask> task = new AsyncTask>() { @Override diff --git a/OsmAnd/src/net/osmand/plus/download/ui/DownloadResourceGroupFragment.java b/OsmAnd/src/net/osmand/plus/download/ui/DownloadResourceGroupFragment.java index acafce29f7..ffaf81b24b 100644 --- a/OsmAnd/src/net/osmand/plus/download/ui/DownloadResourceGroupFragment.java +++ b/OsmAnd/src/net/osmand/plus/download/ui/DownloadResourceGroupFragment.java @@ -1,5 +1,6 @@ package net.osmand.plus.download.ui; +import android.annotation.SuppressLint; import android.app.ProgressDialog; import android.content.DialogInterface; import android.content.res.Resources; @@ -41,8 +42,9 @@ import net.osmand.plus.download.DownloadResourceGroup.DownloadResourceGroupType; import net.osmand.plus.download.DownloadResources; import net.osmand.plus.download.DownloadValidationManager; import net.osmand.plus.download.IndexItem; -import net.osmand.plus.inapp.InAppHelper; -import net.osmand.plus.inapp.InAppHelper.InAppListener; +import net.osmand.plus.inapp.InAppPurchaseHelper; +import net.osmand.plus.inapp.InAppPurchaseHelper.InAppPurchaseListener; +import net.osmand.plus.inapp.InAppPurchaseHelper.InAppPurchaseTaskType; import net.osmand.util.Algorithms; import org.json.JSONException; @@ -55,7 +57,7 @@ import java.util.List; import java.util.Map; public class DownloadResourceGroupFragment extends DialogFragment implements DownloadEvents, - InAppListener, OnChildClickListener { + InAppPurchaseListener, OnChildClickListener { public static final int RELOAD_ID = 0; public static final int SEARCH_ID = 1; public static final String TAG = "RegionDialogFragment"; @@ -67,6 +69,7 @@ public class DownloadResourceGroupFragment extends DialogFragment implements Dow protected DownloadResourceGroupAdapter listAdapter; private DownloadResourceGroup group; private DownloadActivity activity; + private InAppPurchaseHelper purchaseHelper; private Toolbar toolbar; private View searchView; private View restorePurchasesView; @@ -75,6 +78,7 @@ public class DownloadResourceGroupFragment extends DialogFragment implements Dow @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + purchaseHelper = getDownloadActivity().getPurchaseHelper(); boolean isLightTheme = getMyApplication().getSettings().OSMAND_THEME.get() == OsmandSettings.OSMAND_LIGHT_THEME; int themeId = isLightTheme ? R.style.OsmandLightTheme : R.style.OsmandDarkTheme; setStyle(STYLE_NO_FRAME, themeId); @@ -152,7 +156,7 @@ public class DownloadResourceGroupFragment extends DialogFragment implements Dow } private void addRestorePurchasesRow() { - if (!openAsDialog() && !InAppHelper.isInAppIntentoryRead()) { + if (!openAsDialog() && purchaseHelper != null && !purchaseHelper.hasInventory()) { restorePurchasesView = activity.getLayoutInflater().inflate(R.layout.restore_purchases_list_footer, null); ((ImageView) restorePurchasesView.findViewById(R.id.icon)).setImageDrawable( getMyApplication().getIconsCache().getThemedIcon(R.drawable.ic_action_reset_to_default_dark)); @@ -160,7 +164,7 @@ public class DownloadResourceGroupFragment extends DialogFragment implements Dow @Override public void onClick(View v) { restorePurchasesView.findViewById(R.id.progressBar).setVisibility(View.VISIBLE); - activity.startInAppHelper(); + purchaseHelper.requestInventory(); } }); listView.addFooterView(restorePurchasesView); @@ -205,7 +209,7 @@ public class DownloadResourceGroupFragment extends DialogFragment implements Dow } } if (restorePurchasesView != null && restorePurchasesView.findViewById(R.id.container).getVisibility() == View.GONE - && !InAppHelper.isInAppIntentoryRead()) { + && purchaseHelper != null && !purchaseHelper.hasInventory()) { if (worldBaseMapItem != null && worldBaseMapItem.isDownloaded()) { restorePurchasesView.findViewById(R.id.container).setVisibility(View.VISIBLE); } @@ -260,6 +264,7 @@ public class DownloadResourceGroupFragment extends DialogFragment implements Dow alertDialog.show(); } + @SuppressLint("StaticFieldLeak") private void doSubscribe(final String email) { new AsyncTask() { @@ -329,7 +334,7 @@ public class DownloadResourceGroupFragment extends DialogFragment implements Dow } @Override - public void onError(String error) { + public void onError(InAppPurchaseTaskType taskType, String error) { } @Override @@ -346,11 +351,11 @@ public class DownloadResourceGroupFragment extends DialogFragment implements Dow } @Override - public void showProgress() { + public void showProgress(InAppPurchaseTaskType taskType) { } @Override - public void dismissProgress() { + public void dismissProgress(InAppPurchaseTaskType taskType) { if (restorePurchasesView != null && restorePurchasesView.findViewById(R.id.container).getVisibility() == View.VISIBLE) { restorePurchasesView.findViewById(R.id.progressBar).setVisibility(View.GONE); } diff --git a/OsmAnd/src/net/osmand/plus/download/ui/FreeVersionDialogFragment.java b/OsmAnd/src/net/osmand/plus/download/ui/FreeVersionDialogFragment.java deleted file mode 100644 index 5cabbd16e7..0000000000 --- a/OsmAnd/src/net/osmand/plus/download/ui/FreeVersionDialogFragment.java +++ /dev/null @@ -1,44 +0,0 @@ -package net.osmand.plus.download.ui; - -import android.app.Dialog; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.v4.app.DialogFragment; -import android.support.v7.app.AlertDialog; -import android.support.v7.view.ContextThemeWrapper; -import android.view.View; - -import net.osmand.plus.OsmandApplication; -import net.osmand.plus.R; -import net.osmand.plus.Version; -import net.osmand.plus.download.DownloadActivity; -import net.osmand.plus.download.DownloadActivity.FreeVersionDialog; - -import static net.osmand.plus.OsmandApplication.SHOW_PLUS_VERSION_INAPP_PARAM; - -public class FreeVersionDialogFragment extends DialogFragment { - public static final String TAG = "FreeVersionDialogFragment"; - private FreeVersionDialog dialog; - - @NonNull - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - OsmandApplication app = (OsmandApplication) getActivity().getApplication(); - app.activateFetchedRemoteParams(); - - AlertDialog.Builder builder = new AlertDialog.Builder(new ContextThemeWrapper(getActivity(), R.style.OsmandDarkTheme)); - builder.setNegativeButton(R.string.later, null); - View view = getActivity().getLayoutInflater().inflate(R.layout.free_version_banner, null); - builder.setView(view); - - dialog = new DownloadActivity.FreeVersionDialog(view, getDownloadActivity(), true); - dialog.initFreeVersionBanner(); - dialog.expandBanner(); - return builder.create(); - } - - DownloadActivity getDownloadActivity() { - return (DownloadActivity) getActivity(); - } - -} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/helpers/DiscountHelper.java b/OsmAnd/src/net/osmand/plus/helpers/DiscountHelper.java index f8037fa806..239eac2c6b 100644 --- a/OsmAnd/src/net/osmand/plus/helpers/DiscountHelper.java +++ b/OsmAnd/src/net/osmand/plus/helpers/DiscountHelper.java @@ -14,7 +14,7 @@ import net.osmand.plus.OsmandSettings; import net.osmand.plus.R; import net.osmand.plus.Version; import net.osmand.plus.activities.MapActivity; -import net.osmand.plus.inapp.InAppHelper; +import net.osmand.plus.inapp.InAppPurchaseHelper; import net.osmand.plus.liveupdates.OsmLiveActivity; import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarController; import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarControllerType; @@ -109,7 +109,8 @@ public class DiscountHelper { if (url.startsWith(INAPP_PREFIX) && url.length() > INAPP_PREFIX.length()) { String inAppSku = url.substring(INAPP_PREFIX.length()); - if (InAppHelper.isPurchased(app, inAppSku)) { + InAppPurchaseHelper purchaseHelper = app.getInAppPurchaseHelper(); + if (purchaseHelper != null && purchaseHelper.isPurchased(inAppSku)) { return; } } @@ -210,15 +211,11 @@ public class DiscountHelper { private static void openUrl(final MapActivity mapActivity, String url) { if (url.startsWith(INAPP_PREFIX)) { - if (url.contains(InAppHelper.SKU_FULL_VERSION_PRICE)) { - mapActivity.execInAppTask(new InAppHelper.InAppRunnable() { - @Override - public void run(InAppHelper helper) { - mapActivity.getMyApplication().logEvent(mapActivity, "in_app_purchase_redirect"); - helper.purchaseFullVersion(mapActivity); - } - }); - } else if (url.contains(InAppHelper.SKU_LIVE_UPDATES)){ + if (url.contains(InAppPurchaseHelper.SKU_FULL_VERSION_PRICE)) { + OsmandApplication app = mapActivity.getMyApplication(); + app.logEvent(mapActivity, "in_app_purchase_redirect"); + app.getInAppPurchaseHelper().purchaseFullVersion(mapActivity); + } else if (url.contains(InAppPurchaseHelper.SKU_LIVE_UPDATES)){ Intent intent = new Intent(mapActivity, OsmLiveActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); intent.putExtra(OsmLiveActivity.OPEN_SUBSCRIPTION_INTENT_PARAM, true); diff --git a/OsmAnd/src/net/osmand/plus/inapp/InAppHelper.java b/OsmAnd/src/net/osmand/plus/inapp/InAppPurchaseHelper.java similarity index 55% rename from OsmAnd/src/net/osmand/plus/inapp/InAppHelper.java rename to OsmAnd/src/net/osmand/plus/inapp/InAppPurchaseHelper.java index 51ab4e5539..65e8cb08be 100644 --- a/OsmAnd/src/net/osmand/plus/inapp/InAppHelper.java +++ b/OsmAnd/src/net/osmand/plus/inapp/InAppPurchaseHelper.java @@ -1,5 +1,6 @@ package net.osmand.plus.inapp; +import android.annotation.SuppressLint; import android.app.Activity; import android.content.Intent; import android.os.AsyncTask; @@ -26,29 +27,29 @@ import net.osmand.util.Algorithms; import org.json.JSONException; import org.json.JSONObject; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -public class InAppHelper { +public class InAppPurchaseHelper { // Debug tag, for logging - static final String TAG = "InAppHelper"; + private static final String TAG = InAppPurchaseHelper.class.getSimpleName(); boolean mDebugLog = false; - private static boolean mSubscribedToLiveUpdates = false; - private static boolean mFullVersionPurchased = false; - private static boolean mDepthContoursPurchased = false; - private static String mLiveUpdatesPrice; - private static long lastValidationCheckTime; - private static String mFullVersionPrice; - private static String mDepthContoursPrice; + private long lastValidationCheckTime; + private String liveUpdatesPrice; + private String fullVersionPrice; + private String depthContoursPrice; public static final String SKU_FULL_VERSION_PRICE = "osmand_full_version_price"; + private static final String SKU_LIVE_UPDATES_FULL = "osm_live_subscription_2"; private static final String SKU_LIVE_UPDATES_FREE = "osm_free_live_subscription_2"; private static final String SKU_DEPTH_CONTOURS_FULL = "net.osmand.seadepth_plus"; private static final String SKU_DEPTH_CONTOURS_FREE = "net.osmand.seadepth"; + public static String SKU_LIVE_UPDATES; public static String SKU_DEPTH_CONTOURS; @@ -58,27 +59,25 @@ public class InAppHelper { // The helper object private IabHelper mHelper; - private boolean stopAfterResult = false; - private boolean isDeveloperVersion = false; - private boolean forceRequestInventory = false; + private boolean isDeveloperVersion; private String token = ""; - private boolean inventoryRequesting = false; - private boolean stopRequested = false; + private InAppPurchaseTaskType activeTask; + private boolean processingTask = false; private OsmandApplication ctx; - private List listeners = new ArrayList<>(); + private List listeners = new ArrayList<>(); /* base64EncodedPublicKey should be YOUR APPLICATION'S PUBLIC KEY - * (that you got from the Google Play developer console). This is not your - * developer public key, it's the *app-specific* public key. - * - * Instead of just storing the entire literal string here embedded in the - * program, construct the key at runtime from pieces or - * use bit manipulation (for example, XOR with some other string) to hide - * the actual key. The key itself is not secret information, but we don't - * want to make it easy for an attacker to replace the public key with one - * of their own and then fake messages from the server. - */ + * (that you got from the Google Play developer console). This is not your + * developer public key, it's the *app-specific* public key. + * + * Instead of just storing the entire literal string here embedded in the + * program, construct the key at runtime from pieces or + * use bit manipulation (for example, XOR with some other string) to hide + * the actual key. The key itself is not secret information, but we don't + * want to make it easy for an attacker to replace the public key with one + * of their own and then fake messages from the server. + */ private static final String BASE64_ENCODED_PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgk8cEx" + "UO4mfEwWFLkQnX1Tkzehr4SnXLXcm2Osxs5FTJPEgyTckTh0POKVMrxeGLn0KoTY2NTgp1U/inp" + "wccWisPhVPEmw9bAVvWsOkzlyg1kv03fJdnAXRBSqDDPV6X8Z3MtkPVqZkupBsxyIllEILKHK06" + @@ -86,60 +85,64 @@ public class InAppHelper { "I+ftJO46a1XkNh1dO2anUiQ8P/H4yOTqnMsXF7biyYuiwjXPOcy0OMhEHi54Dq6Mr3u5ZALOAkc" + "YTjh1H/ZgqIHy5ZluahINuDE76qdLYMXrDMQIDAQAB"; - public interface InAppListener { - void onError(String error); + public interface InAppPurchaseListener { + void onError(InAppPurchaseTaskType taskType, String error); void onGetItems(); void onItemPurchased(String sku); - void showProgress(); + void showProgress(InAppPurchaseTaskType taskType); - void dismissProgress(); + void dismissProgress(InAppPurchaseTaskType taskType); + } + + public enum InAppPurchaseTaskType { + REQUEST_INVENTORY, + PURCHASE_FULL_VERSION, + PURCHASE_LIVE_UPDATES, + PURCHASE_DEPTH_CONTOURS } public interface InAppRunnable { - void run(InAppHelper helper); + // return true if done and false if async task started + boolean run(InAppPurchaseHelper helper); } public String getToken() { return token; } - public static boolean isSubscribedToLiveUpdates() { - return mSubscribedToLiveUpdates; + public InAppPurchaseTaskType getActiveTask() { + return activeTask; } - public static boolean isFullVersionPurchased() { - return mFullVersionPurchased; + public boolean isSubscribedToLiveUpdates() { + return ctx.getSettings().LIVE_UPDATES_PURCHASED.get(); } - public static boolean isDepthContoursPurchased() { - return mDepthContoursPurchased; + public String getLiveUpdatesPrice() { + return liveUpdatesPrice; } - public static String getLiveUpdatesPrice() { - return mLiveUpdatesPrice; + public String getFullVersionPrice() { + return fullVersionPrice; } - public static String getDepthContoursPrice() { - return mDepthContoursPrice; + public String getDepthContoursPrice() { + return depthContoursPrice; } - public static String getFullVersionPrice() { - return mFullVersionPrice; - } - - public static String getSkuLiveUpdates() { + public String getSkuLiveUpdates() { return SKU_LIVE_UPDATES; } - public static boolean hasPrices(OsmandApplication app) { - return !Algorithms.isEmpty(mLiveUpdatesPrice) - && (!Version.isFreeVersion(app) || !Algorithms.isEmpty(mFullVersionPrice)); + public boolean hasPrices() { + return !Algorithms.isEmpty(liveUpdatesPrice) + && (!Version.isFreeVersion(ctx) || !Algorithms.isEmpty(fullVersionPrice)); } - public static void initialize(OsmandApplication ctx) { + private void initialize() { if (SKU_LIVE_UPDATES == null) { if (Version.isFreeVersion(ctx)) { SKU_LIVE_UPDATES = SKU_LIVE_UPDATES_FREE; @@ -156,26 +159,22 @@ public class InAppHelper { } } - public InAppHelper(OsmandApplication ctx, boolean forceRequestInventory) { + public InAppPurchaseHelper(OsmandApplication ctx) { this.ctx = ctx; - this.forceRequestInventory = forceRequestInventory; - - isDeveloperVersion = Version.isDeveloperVersion(ctx); - if (isDeveloperVersion) { - mSubscribedToLiveUpdates = true; - mFullVersionPurchased = true; - mDepthContoursPurchased = true; + this.isDeveloperVersion = Version.isDeveloperVersion(ctx); + if (this.isDeveloperVersion) { ctx.getSettings().LIVE_UPDATES_PURCHASED.set(true); ctx.getSettings().FULL_VERSION_PURCHASED.set(true); ctx.getSettings().DEPTH_CONTOURS_PURCHASED.set(true); } + initialize(); } - public static boolean isInAppIntentoryRead() { + public boolean hasInventory() { return lastValidationCheckTime != 0; } - public static boolean isPurchased(OsmandApplication ctx, String inAppSku) { + public boolean isPurchased(String inAppSku) { OsmandSettings settings = ctx.getSettings(); if (inAppSku.equals(SKU_FULL_VERSION_PRICE)) { return settings.FULL_VERSION_PURCHASED.get(); @@ -187,11 +186,18 @@ public class InAppHelper { return false; } - public void exec(final @NonNull InAppRunnable runnable) { - this.stopAfterResult = true; + private void exec(final @NonNull InAppPurchaseTaskType taskType, final @NonNull InAppRunnable runnable) { + if (isDeveloperVersion || !Version.isGooglePlayEnabled(ctx)) { + return; + } + + if (processingTask) { + logError("Already processing task: " + taskType + ". Exit."); + return; + } // Create the helper, passing it our context and the public key to verify signatures with - logDebug("Creating InAppHelper."); + logDebug("Creating InAppPurchaseHelper."); mHelper = new IabHelper(ctx, BASE64_ENCODED_PUBLIC_KEY); // enable debug logging (for a production application, you should set this to false). @@ -201,6 +207,8 @@ public class InAppHelper { // will be called once setup completes. logDebug("Starting setup."); try { + processingTask = true; + activeTask = taskType; mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() { public void onIabSetupFinished(IabResult result) { logDebug("Setup finished."); @@ -208,166 +216,165 @@ public class InAppHelper { if (!result.isSuccess()) { // Oh noes, there was a problem. //complain("Problem setting up in-app billing: " + result); - notifyError(result.getMessage()); - if (stopAfterResult) { - stop(); - } + notifyError(taskType, result.getMessage()); + stop(true); return; } // Have we been disposed of in the meantime? If so, quit. - if (mHelper == null) return; + if (mHelper == null) { + stop(true); + return; + } - runnable.run(InAppHelper.this); + processingTask = !runnable.run(InAppPurchaseHelper.this); } }); } catch (Exception e) { logError("exec Error", e); - if (stopAfterResult) { - stop(); - } + stop(true); } } - public void start(final boolean stopAfterResult) { - this.stopAfterResult = stopAfterResult; + public boolean needRequestInventory() { + return !ctx.getSettings().BILLING_PURCHASE_TOKEN_SENT.get() + || System.currentTimeMillis() - lastValidationCheckTime > PURCHASE_VALIDATION_PERIOD_MSEC; + } - // Create the helper, passing it our context and the public key to verify signatures with - logDebug("Creating InAppHelper."); - mHelper = new IabHelper(ctx, BASE64_ENCODED_PUBLIC_KEY); - - // enable debug logging (for a production application, you should set this to false). - mHelper.enableDebugLogging(false); - - // Start setup. This is asynchronous and the specified listener - // will be called once setup completes. - logDebug("Starting setup."); - try { - mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() { - public void onIabSetupFinished(IabResult result) { - logDebug("Setup finished."); - - if (!result.isSuccess()) { - // Oh noes, there was a problem. - //complain("Problem setting up in-app billing: " + result); - notifyError(result.getMessage()); - if (stopAfterResult) { - stop(); - } - return; - } - - // Have we been disposed of in the meantime? If so, quit. - if (mHelper == null) return; - - // IAB is fully set up. Now, let's get an inventory of stuff we own if needed. - if (forceRequestInventory || (!isDeveloperVersion && - (!mSubscribedToLiveUpdates - || !ctx.getSettings().BILLING_PURCHASE_TOKEN_SENT.get() - || System.currentTimeMillis() - lastValidationCheckTime > PURCHASE_VALIDATION_PERIOD_MSEC))) { - - logDebug("Setup successful. Querying inventory."); - List skus = new ArrayList<>(); - skus.add(SKU_LIVE_UPDATES); - skus.add(SKU_DEPTH_CONTOURS); - skus.add(SKU_FULL_VERSION_PRICE); - try { - inventoryRequesting = true; - mHelper.queryInventoryAsync(true, skus, mGotInventoryListener); - } catch (Exception e) { - inventoryRequesting = false; - logError("queryInventoryAsync Error", e); - notifyDismissProgress(); - if (stopAfterResult) { - stop(); - } - } - } else { - notifyDismissProgress(); - if (stopAfterResult) { - stop(); - } - } + public void requestInventory() { + notifyShowProgress(InAppPurchaseTaskType.REQUEST_INVENTORY); + exec(InAppPurchaseTaskType.REQUEST_INVENTORY, new InAppRunnable() { + @Override + public boolean run(InAppPurchaseHelper helper) { + logDebug("Setup successful. Querying inventory."); + List skus = new ArrayList<>(); + skus.add(SKU_LIVE_UPDATES); + skus.add(SKU_DEPTH_CONTOURS); + skus.add(SKU_FULL_VERSION_PRICE); + try { + mHelper.queryInventoryAsync(true, skus, mGotInventoryListener); + return false; + } catch (Exception e) { + logError("queryInventoryAsync Error", e); + notifyDismissProgress(InAppPurchaseTaskType.REQUEST_INVENTORY); + stop(true); } - }); - } catch (Exception e) { - logError("start Error", e); - if (stopAfterResult) { - stop(); + return true; } - } + }); + } + + public void purchaseFullVersion(final Activity activity) { + notifyShowProgress(InAppPurchaseTaskType.PURCHASE_FULL_VERSION); + exec(InAppPurchaseTaskType.PURCHASE_FULL_VERSION, new InAppRunnable() { + @Override + public boolean run(InAppPurchaseHelper helper) { + try { + mHelper.launchPurchaseFlow(activity, + SKU_FULL_VERSION_PRICE, RC_REQUEST, mPurchaseFinishedListener); + return false; + } catch (Exception e) { + complain("Cannot launch full version purchase!"); + logError("purchaseFullVersion Error", e); + stop(true); + } + return true; + } + }); + } + + public void purchaseLiveUpdates(Activity activity, String email, String userName, + String countryDownloadName, boolean hideUserName) { + notifyShowProgress(InAppPurchaseTaskType.PURCHASE_LIVE_UPDATES); + new LiveUpdatesPurchaseTask(activity, email, userName, countryDownloadName, hideUserName) + .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null); + } + + public void purchaseDepthContours(final Activity activity) { + notifyShowProgress(InAppPurchaseTaskType.PURCHASE_DEPTH_CONTOURS); + exec(InAppPurchaseTaskType.PURCHASE_DEPTH_CONTOURS, new InAppRunnable() { + @Override + public boolean run(InAppPurchaseHelper helper) { + try { + mHelper.launchPurchaseFlow(activity, + SKU_DEPTH_CONTOURS, RC_REQUEST, mPurchaseFinishedListener); + return false; + } catch (Exception e) { + complain("Cannot launch depth contours purchase!"); + logError("purchaseDepthContours Error", e); + stop(true); + } + return true; + } + }); } // Listener that's called when we finish querying the items and subscriptions we own private QueryInventoryFinishedListener mGotInventoryListener = new QueryInventoryFinishedListener() { public void onQueryInventoryFinished(IabResult result, Inventory inventory) { logDebug("Query inventory finished."); - inventoryRequesting = false; // Have we been disposed of in the meantime? If so, quit. - if (mHelper == null) return; + if (mHelper == null) { + stop(true); + return; + } // Is it a failure? - if (result.isFailure() || stopRequested) { + if (result.isFailure()) { logError("Failed to query inventory: " + result); - notifyError(result.getMessage()); - if (stopAfterResult || stopRequested) { - stop(); - } + notifyError(InAppPurchaseTaskType.REQUEST_INVENTORY, result.getMessage()); + stop(true); return; } logDebug("Query inventory was successful."); - /* + /* * Check for items we own. Notice that for each purchase, we check - * the developer payload to see if it's correct! See - * verifyDeveloperPayload(). - */ + * the developer payload to see if it's correct! See + * verifyDeveloperPayload(). + */ // Do we have the live updates? Purchase liveUpdatesPurchase = inventory.getPurchase(SKU_LIVE_UPDATES); - mSubscribedToLiveUpdates = isDeveloperVersion || (liveUpdatesPurchase != null && liveUpdatesPurchase.getPurchaseState() == 0); - if (mSubscribedToLiveUpdates) { - ctx.getSettings().LIVE_UPDATES_PURCHASED.set(true); - } + boolean subscribedToLiveUpdates = (liveUpdatesPurchase != null && liveUpdatesPurchase.getPurchaseState() == 0); + //subscribedToLiveUpdates = false; + ctx.getSettings().LIVE_UPDATES_PURCHASED.set(subscribedToLiveUpdates); Purchase fullVersionPurchase = inventory.getPurchase(SKU_FULL_VERSION_PRICE); - mFullVersionPurchased = isDeveloperVersion || (fullVersionPurchase != null && fullVersionPurchase.getPurchaseState() == 0); - if (mFullVersionPurchased) { + boolean fullVersionPurchased = (fullVersionPurchase != null && fullVersionPurchase.getPurchaseState() == 0); + if (fullVersionPurchased) { ctx.getSettings().FULL_VERSION_PURCHASED.set(true); } Purchase depthContoursPurchase = inventory.getPurchase(SKU_DEPTH_CONTOURS); - mDepthContoursPurchased = isDeveloperVersion || (depthContoursPurchase != null && depthContoursPurchase.getPurchaseState() == 0); - if (mDepthContoursPurchased) { + boolean depthContoursPurchased = (depthContoursPurchase != null && depthContoursPurchase.getPurchaseState() == 0); + if (depthContoursPurchased) { ctx.getSettings().DEPTH_CONTOURS_PURCHASED.set(true); } lastValidationCheckTime = System.currentTimeMillis(); - logDebug("User " + (mSubscribedToLiveUpdates ? "HAS" : "DOES NOT HAVE") + logDebug("User " + (subscribedToLiveUpdates ? "HAS" : "DOES NOT HAVE") + " live updates purchased."); if (inventory.hasDetails(SKU_LIVE_UPDATES)) { SkuDetails liveUpdatesDetails = inventory.getSkuDetails(SKU_LIVE_UPDATES); - mLiveUpdatesPrice = liveUpdatesDetails.getPrice(); + liveUpdatesPrice = liveUpdatesDetails.getPrice(); } - - if (inventory.hasDetails(SKU_DEPTH_CONTOURS)) { - SkuDetails depthContoursDetails = inventory.getSkuDetails(SKU_DEPTH_CONTOURS); - mDepthContoursPrice = depthContoursDetails.getPrice(); - } - if (inventory.hasDetails(SKU_FULL_VERSION_PRICE)) { SkuDetails fullPriceDetails = inventory.getSkuDetails(SKU_FULL_VERSION_PRICE); - mFullVersionPrice = fullPriceDetails.getPrice(); + fullVersionPrice = fullPriceDetails.getPrice(); + } + if (inventory.hasDetails(SKU_DEPTH_CONTOURS)) { + SkuDetails depthContoursDetails = inventory.getSkuDetails(SKU_DEPTH_CONTOURS); + depthContoursPrice = depthContoursDetails.getPrice(); } - OsmandSettings settings = ctx.getSettings(); settings.INAPPS_READ.set(true); boolean needSendToken = false; - if (!isDeveloperVersion && liveUpdatesPurchase != null) { + if (liveUpdatesPurchase != null) { if ((Algorithms.isEmpty(settings.BILLING_USER_ID.get()) || Algorithms.isEmpty(settings.BILLING_USER_TOKEN.get())) && !Algorithms.isEmpty(liveUpdatesPurchase.getDeveloperPayload())) { String payload = liveUpdatesPurchase.getDeveloperPayload(); @@ -390,11 +397,9 @@ public class InAppHelper { final OnRequestResultListener listener = new OnRequestResultListener() { @Override public void onResult(String result) { - notifyDismissProgress(); + notifyDismissProgress(InAppPurchaseTaskType.REQUEST_INVENTORY); notifyGetItems(); - if (stopAfterResult || stopRequested) { - stop(); - } + stop(true); logDebug("Initial inapp query finished"); } }; @@ -407,159 +412,107 @@ public class InAppHelper { } }; - public void purchaseFullVersion(final Activity activity) { - if (mHelper == null) { - //complain("In-app hepler is not initialized!"); - notifyError("In-app hepler is not initialized!"); - if (stopAfterResult) { - stop(); - } - return; + @SuppressLint("StaticFieldLeak") + private class LiveUpdatesPurchaseTask extends AsyncTask { + + private WeakReference activity; + + private String email; + private String userName; + private String countryDownloadName; + private boolean hideUserName; + + private String userId; + + LiveUpdatesPurchaseTask(Activity activity, String email, String userName, + String countryDownloadName, boolean hideUserName) { + this.activity = new WeakReference<>(activity); + + this.email = email; + this.userName = userName; + this.countryDownloadName = countryDownloadName; + this.hideUserName = hideUserName; } - logDebug("Launching purchase flow for full version"); - if (mHelper != null) { + @Override + protected String doInBackground(Void... params) { + userId = ctx.getSettings().BILLING_USER_ID.get(); try { - mHelper.launchPurchaseFlow(activity, - SKU_FULL_VERSION_PRICE, RC_REQUEST, mPurchaseFinishedListener); + Map parameters = new HashMap<>(); + parameters.put("visibleName", hideUserName ? "" : userName); + parameters.put("preferredCountry", countryDownloadName); + parameters.put("email", email); + if (Algorithms.isEmpty(userId)) { + parameters.put("status", "new"); + } + + return AndroidNetworkUtils.sendRequest(ctx, + "http://download.osmand.net/subscription/register.php", + parameters, "Requesting userId...", true, true); + } catch (Exception e) { - complain("Cannot launch full version purchase!"); - logError("purchaseFullVersion Error", e); - if (stopAfterResult) { - stop(); - } + logError("sendRequest Error", e); + return null; } } - } - public void purchaseDepthContours(final Activity activity) { - if (mHelper == null) { - //complain("In-app hepler is not initialized!"); - notifyError("In-app hepler is not initialized!"); - if (stopAfterResult) { - stop(); - } - return; - } - - logDebug("Launching purchase flow for sea depth contours"); - if (mHelper != null) { - try { - mHelper.launchPurchaseFlow(activity, - SKU_DEPTH_CONTOURS, RC_REQUEST, mPurchaseFinishedListener); - } catch (Exception e) { - complain("Cannot launch depth contours purchase!"); - logError("purchaseDepthContours Error", e); - if (stopAfterResult) { - stop(); - } - } - } - } - - public void purchaseLiveUpdates(final Activity activity, final String email, final String userName, - final String countryDownloadName, final boolean hideUserName) { - try { - if (mHelper == null || !mHelper.subscriptionsSupported()) { - complain("Subscriptions not supported on your device yet. Sorry!"); - notifyError("Subscriptions not supported on your device yet. Sorry!"); - if (stopAfterResult) { - stop(); - } + @Override + protected void onPostExecute(String response) { + logDebug("Response=" + response); + if (response == null) { + complain("Cannot retrieve userId from server."); + notifyDismissProgress(InAppPurchaseTaskType.PURCHASE_LIVE_UPDATES); + notifyError(InAppPurchaseTaskType.PURCHASE_LIVE_UPDATES, "Cannot retrieve userId from server."); + stop(true); return; - } - } catch (Exception e) { - logError("purchaseLiveUpdates Error", e); - if (stopAfterResult) { - stop(); - } - return; - } - notifyShowProgress(); - - new AsyncTask() { - - private String userId; - - @Override - protected String doInBackground(Void... params) { - userId = ctx.getSettings().BILLING_USER_ID.get(); + } else { try { - Map parameters = new HashMap<>(); - parameters.put("visibleName", hideUserName ? "" : userName); - parameters.put("preferredCountry", countryDownloadName); - parameters.put("email", email); - if (Algorithms.isEmpty(userId)) { - parameters.put("status", "new"); - } - - return AndroidNetworkUtils.sendRequest(ctx, - "http://download.osmand.net/subscription/register.php", - parameters, "Requesting userId...", true, true); - - } catch (Exception e) { - logError("sendRequest Error", e); - return null; + JSONObject obj = new JSONObject(response); + userId = obj.getString("userid"); + ctx.getSettings().BILLING_USER_ID.set(userId); + token = obj.getString("token"); + ctx.getSettings().BILLING_USER_TOKEN.set(token); + logDebug("UserId=" + userId); + } catch (JSONException e) { + String message = "JSON parsing error: " + + (e.getMessage() == null ? "unknown" : e.getMessage()); + complain(message); + notifyDismissProgress(InAppPurchaseTaskType.PURCHASE_LIVE_UPDATES); + notifyError(InAppPurchaseTaskType.PURCHASE_LIVE_UPDATES, message); + stop(true); } } - @Override - protected void onPostExecute(String response) { - logDebug("Response=" + response); - if (response == null) { - complain("Cannot retrieve userId from server."); - notifyDismissProgress(); - notifyError("Cannot retrieve userId from server."); - if (stopAfterResult) { - stop(); - } - return; - - } else { - try { - JSONObject obj = new JSONObject(response); - userId = obj.getString("userid"); - ctx.getSettings().BILLING_USER_ID.set(userId); - token = obj.getString("token"); - ctx.getSettings().BILLING_USER_TOKEN.set(token); - logDebug("UserId=" + userId); - } catch (JSONException e) { - String message = "JSON parsing error: " - + (e.getMessage() == null ? "unknown" : e.getMessage()); - complain(message); - notifyDismissProgress(); - notifyError(message); - if (stopAfterResult) { - stop(); - } - } - } - - notifyDismissProgress(); - if (!Algorithms.isEmpty(userId)) { - logDebug("Launching purchase flow for live updates subscription for userId=" + userId); - String payload = userId + " " + token; - if (mHelper != null) { + notifyDismissProgress(InAppPurchaseTaskType.PURCHASE_LIVE_UPDATES); + if (!Algorithms.isEmpty(userId)) { + logDebug("Launching purchase flow for live updates subscription for userId=" + userId); + final String payload = userId + " " + token; + exec(InAppPurchaseTaskType.PURCHASE_LIVE_UPDATES, new InAppRunnable() { + @Override + public boolean run(InAppPurchaseHelper helper) { try { - mHelper.launchPurchaseFlow(activity, - SKU_LIVE_UPDATES, IabHelper.ITEM_TYPE_SUBS, - RC_REQUEST, mPurchaseFinishedListener, payload); + Activity a = activity.get(); + if (a != null) { + mHelper.launchPurchaseFlow(a, + SKU_LIVE_UPDATES, IabHelper.ITEM_TYPE_SUBS, + RC_REQUEST, mPurchaseFinishedListener, payload); + return false; + } else { + stop(true); + } } catch (Exception e) { logError("launchPurchaseFlow Error", e); - if (stopAfterResult) { - stop(); - } + stop(true); } + return true; } - } else { - notifyError("Empty userId"); - if (stopAfterResult) { - stop(); - } - } + }); + } else { + notifyError(InAppPurchaseTaskType.PURCHASE_LIVE_UPDATES,"Empty userId"); + stop(true); } - }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null); + } } public boolean onActivityResultHandled(int requestCode, int resultCode, Intent data) { @@ -590,15 +543,16 @@ public class InAppHelper { logDebug("Purchase finished: " + result + ", purchase: " + purchase); // if we were disposed of in the meantime, quit. - if (mHelper == null) return; + if (mHelper == null) { + stop(true); + return; + } if (result.isFailure()) { complain("Error purchasing: " + result); - notifyDismissProgress(); - notifyError("Error purchasing: " + result); - if (stopAfterResult) { - stop(); - } + notifyDismissProgress(activeTask); + notifyError(activeTask, "Error purchasing: " + result); + stop(true); return; } @@ -611,58 +565,61 @@ public class InAppHelper { @Override public void onResult(String result) { showToast(ctx.getString(R.string.osm_live_thanks)); - mSubscribedToLiveUpdates = true; ctx.getSettings().LIVE_UPDATES_PURCHASED.set(true); - notifyDismissProgress(); + notifyDismissProgress(InAppPurchaseTaskType.PURCHASE_LIVE_UPDATES); notifyItemPurchased(SKU_LIVE_UPDATES); - if (stopAfterResult) { - stop(); - } + stop(true); } }); - } - if (purchase.getSku().equals(SKU_FULL_VERSION_PRICE)) { + + } else if (purchase.getSku().equals(SKU_FULL_VERSION_PRICE)) { // bought full version logDebug("Full version purchased."); showToast(ctx.getString(R.string.full_version_thanks)); - mFullVersionPurchased = true; ctx.getSettings().FULL_VERSION_PURCHASED.set(true); - notifyDismissProgress(); + notifyDismissProgress(InAppPurchaseTaskType.PURCHASE_FULL_VERSION); notifyItemPurchased(SKU_FULL_VERSION_PRICE); - if (stopAfterResult) { - stop(); - } - } - if (purchase.getSku().equals(SKU_DEPTH_CONTOURS)) { + stop(true); + + } else if (purchase.getSku().equals(SKU_DEPTH_CONTOURS)) { // bought sea depth contours logDebug("Sea depth contours purchased."); showToast(ctx.getString(R.string.sea_depth_thanks)); - mDepthContoursPurchased = true; ctx.getSettings().DEPTH_CONTOURS_PURCHASED.set(true); ctx.getSettings().getCustomRenderBooleanProperty("depthContours").set(true); - notifyDismissProgress(); + notifyDismissProgress(InAppPurchaseTaskType.PURCHASE_DEPTH_CONTOURS); notifyItemPurchased(SKU_DEPTH_CONTOURS); - if (stopAfterResult) { - stop(); - } + stop(true); + + } else { + notifyDismissProgress(activeTask); + stop(true); } } }; // Do not forget call stop() when helper is not needed anymore public void stop() { + stop(false); + } + + private void stop(boolean taskDone) { logDebug("Destroying helper."); if (mHelper != null) { - if (!inventoryRequesting) { - stopRequested = false; + if (taskDone) { + processingTask = false; + } + if (!processingTask) { + activeTask = null; mHelper.dispose(); mHelper = null; - } else { - stopRequested = true; } + } else { + processingTask = false; + activeTask = null; } } @@ -739,46 +696,46 @@ public class InAppHelper { } } - private void notifyError(String message) { - for (InAppListener l : listeners) { - l.onError(message); + private void notifyError(InAppPurchaseTaskType taskType, String message) { + for (InAppPurchaseListener l : listeners) { + l.onError(taskType, message); } } private void notifyGetItems() { - for (InAppListener l : listeners) { + for (InAppPurchaseListener l : listeners) { l.onGetItems(); } } private void notifyItemPurchased(String sku) { - for (InAppListener l : listeners) { + for (InAppPurchaseListener l : listeners) { l.onItemPurchased(sku); } } - private void notifyShowProgress() { - for (InAppListener l : listeners) { - l.showProgress(); + private void notifyShowProgress(InAppPurchaseTaskType taskType) { + for (InAppPurchaseListener l : listeners) { + l.showProgress(taskType); } } - private void notifyDismissProgress() { - for (InAppListener l : listeners) { - l.dismissProgress(); + private void notifyDismissProgress(InAppPurchaseTaskType taskType) { + for (InAppPurchaseListener l : listeners) { + l.dismissProgress(taskType); } } - public void addListener(InAppListener listener) { + public void addListener(InAppPurchaseListener listener) { this.listeners.add(listener); } - public void removeListener(InAppListener listener) { + public void removeListener(InAppPurchaseListener listener) { this.listeners.remove(listener); } private void complain(String message) { - logError("**** InAppHelper Error: " + message); + logError("**** InAppPurchaseHelper Error: " + message); showToast(message); } @@ -787,7 +744,9 @@ public class InAppHelper { } private void logDebug(String msg) { - if (mDebugLog) Log.d(TAG, msg); + if (mDebugLog) { + Log.d(TAG, msg); + } } private void logError(String msg) { diff --git a/OsmAnd/src/net/osmand/plus/liveupdates/LiveUpdatesFragment.java b/OsmAnd/src/net/osmand/plus/liveupdates/LiveUpdatesFragment.java index 17ee435b7b..e736c96a44 100644 --- a/OsmAnd/src/net/osmand/plus/liveupdates/LiveUpdatesFragment.java +++ b/OsmAnd/src/net/osmand/plus/liveupdates/LiveUpdatesFragment.java @@ -10,10 +10,10 @@ import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.AsyncTask; -import android.os.Build; import android.os.Bundle; import android.support.annotation.DrawableRes; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.v4.app.FragmentManager; import android.support.v4.view.MenuItemCompat; import android.support.v7.app.ActionBar; @@ -45,10 +45,12 @@ import net.osmand.plus.Version; import net.osmand.plus.activities.LocalIndexHelper; import net.osmand.plus.activities.LocalIndexInfo; import net.osmand.plus.activities.OsmandBaseExpandableListAdapter; +import net.osmand.plus.activities.OsmandInAppPurchaseActivity; import net.osmand.plus.base.BaseOsmAndFragment; import net.osmand.plus.download.ui.AbstractLoadLocalIndexTask; -import net.osmand.plus.inapp.InAppHelper; -import net.osmand.plus.inapp.InAppHelper.InAppListener; +import net.osmand.plus.inapp.InAppPurchaseHelper; +import net.osmand.plus.inapp.InAppPurchaseHelper.InAppPurchaseListener; +import net.osmand.plus.inapp.InAppPurchaseHelper.InAppPurchaseTaskType; import net.osmand.plus.resources.IncrementalChangesManager; import net.osmand.util.Algorithms; @@ -73,7 +75,7 @@ import static net.osmand.plus.liveupdates.LiveUpdatesHelper.preferenceUpdateFreq import static net.osmand.plus.liveupdates.LiveUpdatesHelper.runLiveUpdate; import static net.osmand.plus.liveupdates.LiveUpdatesHelper.setAlarmForPendingIntent; -public class LiveUpdatesFragment extends BaseOsmAndFragment implements InAppListener { +public class LiveUpdatesFragment extends BaseOsmAndFragment implements InAppPurchaseListener { public static final int TITLE = R.string.live_updates; private static final int SUBSCRIPTION_SETTINGS = 5; public static final Comparator LOCAL_INDEX_INFO_COMPARATOR = new Comparator() { @@ -90,10 +92,11 @@ public class LiveUpdatesFragment extends BaseOsmAndFragment implements InAppList private ProgressBar progressBar; private boolean processing; - public InAppHelper getInAppHelper() { + @Nullable + public InAppPurchaseHelper getInAppPurchaseHelper() { Activity activity = getActivity(); - if (activity instanceof OsmLiveActivity) { - return ((OsmLiveActivity) activity).getInAppHelper(); + if (activity instanceof OsmandInAppPurchaseActivity) { + return ((OsmandInAppPurchaseActivity) activity).getPurchaseHelper(); } else { return null; } @@ -121,7 +124,8 @@ public class LiveUpdatesFragment extends BaseOsmAndFragment implements InAppList listView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() { @Override public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) { - if (!processing && InAppHelper.isSubscribedToLiveUpdates()) { + InAppPurchaseHelper purchaseHelper = getInAppPurchaseHelper(); + if (!processing && purchaseHelper != null && purchaseHelper.isSubscribedToLiveUpdates()) { final FragmentManager fragmentManager = getChildFragmentManager(); LiveUpdatesSettingsDialogFragment .createInstance(adapter.getChild(groupPosition, childPosition).getFileName()) @@ -143,7 +147,8 @@ public class LiveUpdatesFragment extends BaseOsmAndFragment implements InAppList listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { - if (position == 0 && !processing && InAppHelper.isSubscribedToLiveUpdates()) { + InAppPurchaseHelper purchaseHelper = getInAppPurchaseHelper(); + if (position == 0 && !processing && purchaseHelper != null && purchaseHelper.isSubscribedToLiveUpdates()) { SubscriptionFragment subscriptionFragment = new SubscriptionFragment(); subscriptionFragment.setEditMode(true); subscriptionFragment.show(getChildFragmentManager(), SubscriptionFragment.TAG); @@ -207,17 +212,17 @@ public class LiveUpdatesFragment extends BaseOsmAndFragment implements InAppList @Override public void onResume() { super.onResume(); - InAppHelper helper = getInAppHelper(); - if (helper != null) { - enableProgress(); - helper.addListener(this); - helper.start(false); + InAppPurchaseHelper purchaseHelper = getInAppPurchaseHelper(); + if (purchaseHelper != null) { + if (purchaseHelper.getActiveTask() == InAppPurchaseTaskType.REQUEST_INVENTORY) { + enableProgress(); + } + purchaseHelper.addListener(this); } if (((OsmLiveActivity) getActivity()).shouldOpenSubscription()) { SubscriptionFragment subscriptionFragment = new SubscriptionFragment(); subscriptionFragment.show(getChildFragmentManager(), SubscriptionFragment.TAG); } - } @Override @@ -227,11 +232,11 @@ public class LiveUpdatesFragment extends BaseOsmAndFragment implements InAppList } @Override - public void onDestroy() { - super.onDestroy(); - InAppHelper helper = getInAppHelper(); - if (helper != null) { - helper.removeListener(this); + public void onPause() { + super.onPause(); + InAppPurchaseHelper purchaseHelper = getInAppPurchaseHelper(); + if (purchaseHelper != null) { + purchaseHelper.removeListener(this); } } @@ -383,7 +388,8 @@ public class LiveUpdatesFragment extends BaseOsmAndFragment implements InAppList @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (isChecked) { - if (InAppHelper.isSubscribedToLiveUpdates()) { + InAppPurchaseHelper purchaseHelper = getInAppPurchaseHelper(); + if (purchaseHelper != null && purchaseHelper.isSubscribedToLiveUpdates()) { switchOnLiveUpdates(settings); } else { liveUpdatesSwitch.setChecked(false); @@ -578,7 +584,8 @@ public class LiveUpdatesFragment extends BaseOsmAndFragment implements InAppList descriptionTextView.setText(context.getString(R.string.last_map_change, lastCheckString)); } - if (!fragment.isProcessing() && InAppHelper.isSubscribedToLiveUpdates()) { + InAppPurchaseHelper purchaseHelper = fragment.getInAppPurchaseHelper(); + if (!fragment.isProcessing() && purchaseHelper != null && purchaseHelper.isSubscribedToLiveUpdates()) { final View.OnClickListener clickListener = new View.OnClickListener() { @Override public void onClick(View v) { @@ -673,14 +680,14 @@ public class LiveUpdatesFragment extends BaseOsmAndFragment implements InAppList } @Override - public void onError(String error) { + public void onError(InAppPurchaseTaskType taskType, String error) { disableProgress(); } @Override public void onGetItems() { - getSettings().LIVE_UPDATES_PURCHASED.set(InAppHelper.isSubscribedToLiveUpdates()); - if (!InAppHelper.isSubscribedToLiveUpdates()) { + InAppPurchaseHelper purchaseHelper = getInAppPurchaseHelper(); + if (purchaseHelper != null && !purchaseHelper.isSubscribedToLiveUpdates()) { getSettings().IS_LIVE_UPDATES_ON.set(false); adapter.enableLiveUpdates(false); } @@ -689,18 +696,19 @@ public class LiveUpdatesFragment extends BaseOsmAndFragment implements InAppList @Override public void onItemPurchased(String sku) { - if (InAppHelper.getSkuLiveUpdates().equals(sku)) { + InAppPurchaseHelper purchaseHelper = getInAppPurchaseHelper(); + if (purchaseHelper != null && purchaseHelper.getSkuLiveUpdates().equals(sku)) { updateSubscriptionHeader(); } } @Override - public void showProgress() { + public void showProgress(InAppPurchaseTaskType taskType) { enableProgress(); } @Override - public void dismissProgress() { + public void dismissProgress(InAppPurchaseTaskType taskType) { disableProgress(); } } diff --git a/OsmAnd/src/net/osmand/plus/liveupdates/OsmLiveActivity.java b/OsmAnd/src/net/osmand/plus/liveupdates/OsmLiveActivity.java index 28f8e874b4..575967477e 100644 --- a/OsmAnd/src/net/osmand/plus/liveupdates/OsmLiveActivity.java +++ b/OsmAnd/src/net/osmand/plus/liveupdates/OsmLiveActivity.java @@ -15,10 +15,8 @@ import android.view.MenuItem; import net.osmand.AndroidNetworkUtils; import net.osmand.PlatformUtil; import net.osmand.plus.R; -import net.osmand.plus.Version; import net.osmand.plus.download.AbstractDownloadActivity; -import net.osmand.plus.download.DownloadIndexesThread; -import net.osmand.plus.inapp.InAppHelper; +import net.osmand.plus.download.DownloadIndexesThread.DownloadEvents; import org.apache.commons.logging.Log; @@ -28,32 +26,21 @@ import java.util.Date; import java.util.Locale; import java.util.TimeZone; -public class OsmLiveActivity extends AbstractDownloadActivity implements DownloadIndexesThread.DownloadEvents { +public class OsmLiveActivity extends AbstractDownloadActivity implements DownloadEvents { private final static Log LOG = PlatformUtil.getLog(OsmLiveActivity.class); public final static String OPEN_SUBSCRIPTION_INTENT_PARAM = "open_subscription_intent_param"; + private LiveUpdatesFragmentPagerAdapter pagerAdapter; - private InAppHelper inAppHelper; private boolean openSubscription; private GetLastUpdateDateTask getLastUpdateDateTask; private static final String URL = "https://osmand.net/api/osmlive_status"; - public InAppHelper getInAppHelper() { - return inAppHelper; - } - @Override protected void onCreate(Bundle savedInstanceState) { getMyApplication().applyTheme(this); super.onCreate(savedInstanceState); setContentView(R.layout.activity_livie_updates); - if (Version.isGooglePlayEnabled(getMyApplication())) { - inAppHelper = new InAppHelper(getMyApplication(), false); - } - if (Version.isDeveloperVersion(getMyApplication())) { - inAppHelper = null; - } - Intent intent = getIntent(); if (intent != null && intent.getExtras() != null) { openSubscription = intent.getExtras().getBoolean(OPEN_SUBSCRIPTION_INTENT_PARAM, false); @@ -82,17 +69,6 @@ public class OsmLiveActivity extends AbstractDownloadActivity implements Downloa return super.onOptionsItemSelected(item); } - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - // Pass on the activity result to the helper for handling - if (inAppHelper == null || !inAppHelper.onActivityResultHandled(requestCode, resultCode, data)) { - // not handled, so handle it ourselves (here's where you'd - // perform any handling of activity results not related to in-app - // billing... - super.onActivityResult(requestCode, resultCode, data); - } - } - @Override protected void onPause() { super.onPause(); @@ -102,17 +78,17 @@ public class OsmLiveActivity extends AbstractDownloadActivity implements Downloa @Override protected void onDestroy() { super.onDestroy(); - if (inAppHelper != null) { - inAppHelper.stop(); - } if (getLastUpdateDateTask != null) { getLastUpdateDateTask.cancel(true); } } + public boolean isInAppPurchaseAllowed() { + return true; + } + @Override public void newDownloadIndexes() { - } @Override diff --git a/OsmAnd/src/net/osmand/plus/liveupdates/SubscriptionFragment.java b/OsmAnd/src/net/osmand/plus/liveupdates/SubscriptionFragment.java index ca04348bf1..b372196fd6 100644 --- a/OsmAnd/src/net/osmand/plus/liveupdates/SubscriptionFragment.java +++ b/OsmAnd/src/net/osmand/plus/liveupdates/SubscriptionFragment.java @@ -3,6 +3,8 @@ package net.osmand.plus.liveupdates; import android.app.Activity; import android.app.ProgressDialog; import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v7.widget.AppCompatCheckBox; import android.view.LayoutInflater; @@ -22,9 +24,11 @@ import net.osmand.AndroidUtils; import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandSettings; import net.osmand.plus.R; +import net.osmand.plus.activities.OsmandInAppPurchaseActivity; import net.osmand.plus.base.BaseOsmAndDialogFragment; -import net.osmand.plus.inapp.InAppHelper; -import net.osmand.plus.inapp.InAppHelper.InAppListener; +import net.osmand.plus.inapp.InAppPurchaseHelper; +import net.osmand.plus.inapp.InAppPurchaseHelper.InAppPurchaseListener; +import net.osmand.plus.inapp.InAppPurchaseHelper.InAppPurchaseTaskType; import net.osmand.plus.liveupdates.CountrySelectionFragment.CountryItem; import net.osmand.plus.liveupdates.CountrySelectionFragment.OnFragmentInteractionListener; import net.osmand.util.Algorithms; @@ -35,7 +39,7 @@ import org.json.JSONObject; import java.util.HashMap; import java.util.Map; -public class SubscriptionFragment extends BaseOsmAndDialogFragment implements InAppListener, OnFragmentInteractionListener { +public class SubscriptionFragment extends BaseOsmAndDialogFragment implements InAppPurchaseListener, OnFragmentInteractionListener { public static final String TAG = "SubscriptionFragment"; private static final String EDIT_MODE_ID = "edit_mode_id"; @@ -59,10 +63,11 @@ public class SubscriptionFragment extends BaseOsmAndDialogFragment implements In this.editMode = editMode; } - public InAppHelper getInAppHelper() { + @Nullable + public InAppPurchaseHelper getInAppPurchaseHelper() { Activity activity = getActivity(); - if (activity instanceof OsmLiveActivity) { - return ((OsmLiveActivity) activity).getInAppHelper(); + if (activity instanceof OsmandInAppPurchaseActivity) { + return ((OsmandInAppPurchaseActivity) activity).getPurchaseHelper(); } else { return null; } @@ -103,14 +108,9 @@ public class SubscriptionFragment extends BaseOsmAndDialogFragment implements In } @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - InAppHelper helper = getInAppHelper(); - if (helper != null) { - helper.addListener(this); - } - String userName = settings.BILLING_USER_NAME.get(); String email = settings.BILLING_USER_EMAIL.get(); String countryDownloadName = settings.BILLING_USER_COUNTRY_DOWNLOAD_NAME.get(); @@ -214,8 +214,8 @@ public class SubscriptionFragment extends BaseOsmAndDialogFragment implements In saveChangesButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - InAppHelper helper = getInAppHelper(); - if (helper != null && applySettings(userNameEdit.getText().toString().trim(), + InAppPurchaseHelper purchaseHelper = getInAppPurchaseHelper(); + if (purchaseHelper != null && applySettings(userNameEdit.getText().toString().trim(), emailEdit.getText().toString().trim(), hideUserNameCheckbox.isChecked())) { final Map parameters = new HashMap<>(); @@ -224,16 +224,16 @@ public class SubscriptionFragment extends BaseOsmAndDialogFragment implements In parameters.put("email", settings.BILLING_USER_EMAIL.get()); parameters.put("cemail", prevEmail); parameters.put("userid", settings.BILLING_USER_ID.get()); - parameters.put("token", helper.getToken()); + parameters.put("token", purchaseHelper.getToken()); - showProgress(); + showProgress(null); AndroidNetworkUtils.sendRequestAsync(getMyApplication(), "http://download.osmand.net/subscription/update.php", parameters, "Sending data...", true, true, new AndroidNetworkUtils.OnRequestResultListener() { @Override public void onResult(String result) { - dismissProgress(); + dismissProgress(null); OsmandApplication app = getMyApplication(); if (result != null) { try { @@ -283,12 +283,12 @@ public class SubscriptionFragment extends BaseOsmAndDialogFragment implements In subscribeButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - InAppHelper helper = getInAppHelper(); - if (helper != null) { + InAppPurchaseHelper purchaseHelper = getInAppPurchaseHelper(); + if (purchaseHelper != null) { if (applySettings(userNameEdit.getText().toString().trim(), emailEdit.getText().toString().trim(), hideUserNameCheckbox.isChecked())) { - helper.purchaseLiveUpdates(getActivity(), + purchaseHelper.purchaseLiveUpdates(getActivity(), settings.BILLING_USER_EMAIL.get(), settings.BILLING_USER_NAME.get(), settings.BILLING_USER_COUNTRY_DOWNLOAD_NAME.get(), @@ -308,13 +308,27 @@ public class SubscriptionFragment extends BaseOsmAndDialogFragment implements In return view; } + @Override + public void onResume() { + super.onResume(); + InAppPurchaseHelper purchaseHelper = getInAppPurchaseHelper(); + if (purchaseHelper != null) { + purchaseHelper.addListener(this); + } + } + + @Override + public void onPause() { + super.onPause(); + InAppPurchaseHelper purchaseHelper = getInAppPurchaseHelper(); + if (purchaseHelper != null) { + purchaseHelper.removeListener(this); + } + } + @Override public void onDestroy() { super.onDestroy(); - InAppHelper helper = getInAppHelper(); - if (helper != null) { - helper.removeListener(this); - } if (dlg != null && dlg.isShowing()) { dlg.hide(); } @@ -350,7 +364,7 @@ public class SubscriptionFragment extends BaseOsmAndDialogFragment implements In } @Override - public void onError(String error) { + public void onError(InAppPurchaseTaskType taskType, String error) { } @Override @@ -365,7 +379,7 @@ public class SubscriptionFragment extends BaseOsmAndDialogFragment implements In } @Override - public void showProgress() { + public void showProgress(InAppPurchaseTaskType taskType) { if (dlg != null) { dlg.dismiss(); } @@ -377,7 +391,7 @@ public class SubscriptionFragment extends BaseOsmAndDialogFragment implements In } @Override - public void dismissProgress() { + public void dismissProgress(InAppPurchaseTaskType taskType) { if (dlg != null) { dlg.dismiss(); dlg = null; @@ -402,8 +416,9 @@ public class SubscriptionFragment extends BaseOsmAndDialogFragment implements In } if (view != null) { TextView priceTextView = (TextView) view.findViewById(R.id.priceTextView); - if (InAppHelper.getLiveUpdatesPrice() != null) { - priceTextView.setText(InAppHelper.getLiveUpdatesPrice()); + InAppPurchaseHelper purchaseHelper = getInAppPurchaseHelper(); + if (purchaseHelper.getLiveUpdatesPrice() != null) { + priceTextView.setText(purchaseHelper.getLiveUpdatesPrice()); } } } From b539069fed2e6b6344c6210ab22cd9cde018e84b Mon Sep 17 00:00:00 2001 From: Dmitriy Prodchenko Date: Tue, 24 Apr 2018 18:54:28 +0300 Subject: [PATCH 37/38] Add icon for Sea Depth in-app purchase --- .../drawable-xxhdpi/img_logo_38dp_sea_depth.png | Bin 0 -> 9150 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 OsmAnd/res/drawable-xxhdpi/img_logo_38dp_sea_depth.png diff --git a/OsmAnd/res/drawable-xxhdpi/img_logo_38dp_sea_depth.png b/OsmAnd/res/drawable-xxhdpi/img_logo_38dp_sea_depth.png new file mode 100644 index 0000000000000000000000000000000000000000..0d1aea1b6e6f100dd58421f33004ad69c3badfda GIT binary patch literal 9150 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 literal 0 HcmV?d00001 From dc33d0848b7bbf5414cf6e2120d0c00413e52dc5 Mon Sep 17 00:00:00 2001 From: Alex Sytnyk Date: Tue, 24 Apr 2018 19:02:10 +0300 Subject: [PATCH 38/38] Create TravelDownloadUpdateCard --- .../layout/travel_download_update_card.xml | 1 + OsmAnd/res/values/strings.xml | 4 + .../travelcards/TravelDownloadUpdateCard.java | 154 ++++++++++++++++++ 3 files changed, 159 insertions(+) create mode 100644 OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/TravelDownloadUpdateCard.java diff --git a/OsmAnd/res/layout/travel_download_update_card.xml b/OsmAnd/res/layout/travel_download_update_card.xml index d2958d5ba6..957351187e 100644 --- a/OsmAnd/res/layout/travel_download_update_card.xml +++ b/OsmAnd/res/layout/travel_download_update_card.xml @@ -66,6 +66,7 @@ android:paddingRight="@dimen/content_padding"> + We prepared updates and fixes in the Wikivoyage data, update the file to see them. + Download this Wikivoyage travel guides file to view articles about places around the world without an internet connection. + Update is available + Download file The free worldwide travel guide that anyone can edit. Travel is based on Wikivoyage. During open beta testing you have the opportunity to evaluate all the features for free. After the end of the beta period, Travel will be available to subscribers of OsmAnd Unlimited and the owners of OsmAnd+ You can edit any article on Wikivoyage, and we hope that you do. We need your knowledge, your experience, your talent, and your attention diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/TravelDownloadUpdateCard.java b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/TravelDownloadUpdateCard.java new file mode 100644 index 0000000000..b229528496 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/TravelDownloadUpdateCard.java @@ -0,0 +1,154 @@ +package net.osmand.plus.wikivoyage.explore.travelcards; + +import android.graphics.drawable.Drawable; +import android.support.annotation.NonNull; +import android.support.v4.content.ContextCompat; +import android.support.v7.widget.RecyclerView; +import android.view.View; +import android.widget.ImageView; +import android.widget.ProgressBar; +import android.widget.TextView; + +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.R; + +public class TravelDownloadUpdateCard extends BaseTravelCard { + + public static final int TYPE = 50; + + private boolean download; + private boolean loadingInProgress; + + public TravelDownloadUpdateCard(OsmandApplication app, boolean nightMode, boolean download) { + super(app, nightMode); + this.download = download; + } + + @Override + public void bindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder) { + if (viewHolder instanceof CardViewHolder) { + CardViewHolder holder = (CardViewHolder) viewHolder; + holder.title.setText(getTitle()); + holder.icon.setImageDrawable(getIcon()); + holder.description.setText(getDescription()); + holder.fileIcon.setImageDrawable(getFileIcon()); + holder.fileTitle.setText(getFileTitle()); + holder.fileDescription.setText(getFileDescription()); + boolean primaryBtnVisible = updatePrimaryButton(holder.primaryButton); + boolean secondaryBtnVisible = updateSecondaryButton(holder.secondaryBtn); + holder.buttonsDivider.setVisibility(primaryBtnVisible && secondaryBtnVisible ? View.VISIBLE : View.GONE); + } + } + + @Override + public int getCardType() { + return TYPE; + } + + @NonNull + private String getTitle() { + if (loadingInProgress) { + return app.getString(R.string.shared_string_downloading) + "..."; + } + return app.getString(download ? R.string.download_file : R.string.update_is_available); + } + + private Drawable getIcon() { + int id = download ? R.drawable.travel_card_download_icon : R.drawable.travel_card_update_icon; + return ContextCompat.getDrawable(app, id); + } + + @NonNull + private String getDescription() { + return app.getString(download ? R.string.travel_card_download_descr : R.string.travel_card_update_descr); + } + + @NonNull + private String getFileTitle() { + return "Some file"; // TODO + } + + @NonNull + private String getFileDescription() { + return "Some description"; // TODO + } + + private Drawable getFileIcon() { + return getActiveIcon(R.drawable.ic_action_read_article); + } + + /** + * @return true if button is visible, false otherwise. + */ + private boolean updateSecondaryButton(TextView btn) { + if (loadingInProgress || !download) { + btn.setText(loadingInProgress ? R.string.shared_string_cancel : R.string.later); + btn.setVisibility(View.VISIBLE); + btn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + onSecondaryBtnClick(); + } + }); + return true; + } + btn.setVisibility(View.GONE); + return false; + } + + /** + * @return true if button is visible, false otherwise. + */ + private boolean updatePrimaryButton(TextView btn) { + if (!loadingInProgress) { + btn.setText(download ? R.string.shared_string_download : R.string.shared_string_update); + btn.setVisibility(View.VISIBLE); + btn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + onPrimaryBtnClick(); + } + }); + return true; + } + btn.setVisibility(View.GONE); + return false; + } + + private void onSecondaryBtnClick() { + + } + + private void onPrimaryBtnClick() { + + } + + public class CardViewHolder extends RecyclerView.ViewHolder { + + final TextView title; + final ImageView icon; + final TextView description; + final ImageView fileIcon; + final TextView fileTitle; + final TextView fileDescription; + final ProgressBar progressBar; + final TextView secondaryBtn; + final View buttonsDivider; + final TextView primaryButton; + + @SuppressWarnings("RedundantCast") + public CardViewHolder(View itemView) { + super(itemView); + title = (TextView) itemView.findViewById(R.id.title); + icon = (ImageView) itemView.findViewById(R.id.icon); + description = (TextView) itemView.findViewById(R.id.description); + fileIcon = (ImageView) itemView.findViewById(R.id.file_icon); + fileTitle = (TextView) itemView.findViewById(R.id.file_title); + fileDescription = (TextView) itemView.findViewById(R.id.file_description); + progressBar = (ProgressBar) itemView.findViewById(R.id.progress_bar); + secondaryBtn = (TextView) itemView.findViewById(R.id.secondary_button); + buttonsDivider = itemView.findViewById(R.id.buttons_divider); + primaryButton = (TextView) itemView.findViewById(R.id.primary_button); + } + } +}