Merge pull request #5365 from osmandapp/WikipediaInContextMenu

Wikipedia in context menu
This commit is contained in:
Alexey 2018-05-10 12:01:13 +03:00 committed by GitHub
commit 69e5bf894b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 255 additions and 233 deletions

View file

@ -31,9 +31,12 @@ import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
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.helpers.FontCache;
import net.osmand.plus.mapcontextmenu.MenuBuilder;
import net.osmand.plus.wikipedia.WikiArticleHelper;
import net.osmand.plus.wikipedia.WikipediaArticleWikiLinkFragment;
import net.osmand.plus.wikipedia.WikipediaDialogFragment;
import net.osmand.plus.osmedit.OsmEditingPlugin;
import net.osmand.plus.poi.PoiUIFilter;
@ -291,11 +294,14 @@ public class AmenityMenuBuilder extends MenuBuilder {
@Override
public void onClick(View v) {
if (text.contains(".wikipedia.org/w")) {
WikipediaDialogFragment.showFullArticle(v.getContext(), Uri.parse(text), !light);
if (Version.isPaidVersion(app)) {
WikiArticleHelper wikiArticleHelper = new WikiArticleHelper(mapActivity, !light);
wikiArticleHelper.showWikiArticle(amenity.getLocation(), text);
} else {
WikipediaArticleWikiLinkFragment.showInstance(mapActivity.getSupportFragmentManager(), text);
}
} else {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(text));
v.getContext().startActivity(intent);
WikipediaDialogFragment.showInstance(mapActivity, amenity, text);
}
}
});

View file

@ -0,0 +1,233 @@
package net.osmand.plus.wikipedia;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.net.Uri;
import android.os.AsyncTask;
import android.support.annotation.NonNull;
import android.util.Log;
import net.osmand.IndexConstants;
import net.osmand.data.Amenity;
import net.osmand.data.LatLon;
import net.osmand.map.OsmandRegions;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.download.DownloadActivityType;
import net.osmand.plus.download.DownloadResources;
import net.osmand.plus.download.IndexItem;
import net.osmand.plus.resources.AmenityIndexRepositoryBinary;
import net.osmand.plus.wikivoyage.article.WikivoyageArticleWikiLinkFragment;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.ref.WeakReference;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;
public class WikiArticleHelper {
private static final String TAG = WikiArticleHelper.class.getSimpleName();
private static final String ZIP_EXT = ".zip";
private static final String PAGE_PREFIX_HTTP = "http://";
private static final String PAGE_PREFIX_HTTPS = "https://";
private static final String WIKIVOAYAGE_DOMAIN = ".wikivoyage.org/wiki/";
private static final String WIKI_DOMAIN = ".wikipedia.org/wiki/";
private WikiArticleSearchTask articleSearchTask;
private MapActivity mapActivity;
private boolean nightMode;
public WikiArticleHelper(MapActivity mapActivity, boolean nightMode) {
this.mapActivity = mapActivity;
this.nightMode = nightMode;
}
public static class WikiArticleSearchTask extends AsyncTask<Void, Void, List<Amenity>> {
private ProgressDialog dialog;
private WeakReference<MapActivity> weakMapActivity;
private LatLon articleLatLon;
private String regionName;
private String url;
private String lang;
private String name;
private boolean isNightMode;
WikiArticleSearchTask(LatLon articleLatLon,
MapActivity mapActivity,
boolean nightMode,
String url) {
this.articleLatLon = articleLatLon;
weakMapActivity = new WeakReference<>(mapActivity);
this.isNightMode = nightMode;
this.url = url;
dialog = createProgressDialog(mapActivity);
}
@Override
protected void onPreExecute() {
lang = getLang(url);
name = getArticleNameFromUrl(url, lang);
if (dialog != null) {
dialog.show();
}
}
@Override
protected List<Amenity> doInBackground(Void... voids) {
MapActivity activity = weakMapActivity.get();
OsmandApplication application = activity.getMyApplication();
List<Amenity> results = new ArrayList<>();
if (application != null && !isCancelled()) {
IndexItem item = null;
try {
if (articleLatLon != null) {
item = DownloadResources.findSmallestIndexItemAt(application,
articleLatLon, DownloadActivityType.WIKIPEDIA_FILE);
}
} catch (IOException e) {
Log.e(TAG, e.getMessage(), e);
}
String filename = null;
if (item != null && item.isDownloaded()) {
filename = getFilenameFromIndex(item.getFileName());
}
AmenityIndexRepositoryBinary repository = application.getResourceManager()
.getAmenityRepositoryByFileName(filename == null ? "" : filename);
if (repository == null) {
if ((regionName == null || regionName.isEmpty()) && item != null) {
regionName = (getRegionName(item.getFileName(), application.getRegions()));
}
return null;
} else {
if (isCancelled()) {
return null;
}
results.addAll(repository.searchAmenitiesByName(0, 0, 0, 0,
Integer.MAX_VALUE, Integer.MAX_VALUE, name, null));
}
}
return results;
}
@Override
protected void onCancelled() {
MapActivity activity = weakMapActivity.get();
if (activity != null && !activity.isActivityDestroyed() && dialog != null) {
dialog.dismiss();
}
dialog = null;
}
@Override
protected void onPostExecute(List<Amenity> found) {
MapActivity activity = weakMapActivity.get();
if (activity != null && !activity.isActivityDestroyed() && dialog != null) {
dialog.dismiss();
if (found == null) {
WikivoyageArticleWikiLinkFragment.showInstance(activity.getSupportFragmentManager(), regionName == null ?
"" : regionName, url);
} else if (!found.isEmpty()) {
WikipediaDialogFragment.showInstance(activity, found.get(0), lang);
} else {
warnAboutExternalLoad(url, weakMapActivity.get(), isNightMode);
}
}
}
}
private static String getFilenameFromIndex(String fileName) {
return fileName
.replace("_" + IndexConstants.BINARY_MAP_VERSION, "")
.replace(ZIP_EXT, "");
}
private static String getRegionName(String filename, OsmandRegions osmandRegions) {
if (osmandRegions != null && filename != null) {
String regionName = filename
.replace("_" + IndexConstants.BINARY_MAP_VERSION, "")
.replace(IndexConstants.BINARY_WIKI_MAP_INDEX_EXT_ZIP, "")
.toLowerCase();
return osmandRegions.getLocaleName(regionName, false);
}
return "";
}
private static ProgressDialog createProgressDialog(MapActivity activity) {
if (activity != null && !activity.isActivityDestroyed()) {
ProgressDialog dialog = new ProgressDialog(activity);
dialog.setCancelable(false);
dialog.setMessage(activity.getString(R.string.wiki_article_search_text));
return dialog;
}
return null;
}
public void showWikiArticle(LatLon articleLatLon, String url) {
if (articleLatLon == null) {
return;
}
articleSearchTask = new WikiArticleSearchTask(articleLatLon, mapActivity, nightMode, url);
articleSearchTask.execute();
}
@NonNull
public static String getLang(String url) {
if (url.startsWith(PAGE_PREFIX_HTTP)) {
return url.substring(url.startsWith(PAGE_PREFIX_HTTP) ? PAGE_PREFIX_HTTP.length() : 0, url.indexOf("."));
} else if (url.startsWith(PAGE_PREFIX_HTTPS)) {
return url.substring(url.startsWith(PAGE_PREFIX_HTTPS) ? PAGE_PREFIX_HTTPS.length() : 0, url.indexOf("."));
}
return "";
}
public static String getArticleNameFromUrl(String url, String lang) {
String domain = url.contains(WIKIVOAYAGE_DOMAIN) ? WIKIVOAYAGE_DOMAIN : WIKI_DOMAIN;
String articleName = "";
if (url.startsWith(PAGE_PREFIX_HTTP)) {
articleName = url.replace(PAGE_PREFIX_HTTP + lang + domain, "")
.replaceAll("_", " ");
} else if (url.startsWith(PAGE_PREFIX_HTTPS)) {
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;
}
public void stopSearchAsyncTask() {
if (articleSearchTask != null && articleSearchTask.getStatus() == AsyncTask.Status.RUNNING) {
articleSearchTask.cancel(false);
}
}
public 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)
.setPositiveButton(R.string.shared_string_ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
WikipediaDialogFragment.showFullArticle(context, Uri.parse(url), nightMode);
}
})
.setNegativeButton(R.string.shared_string_cancel, null)
.show();
}
}

View file

@ -28,28 +28,11 @@ public class WikipediaWebViewClient extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith(PAGE_PREFIX_HTTP) || url.startsWith(PAGE_PREFIX_HTTPS)) {
warnAboutExternalLoad(url, context, nightMode);
WikiArticleHelper.warnAboutExternalLoad(url, context, nightMode);
} else {
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
context.startActivity(i);
}
return true;
}
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)
.setPositiveButton(R.string.shared_string_ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
WikipediaDialogFragment.showFullArticle(context, Uri.parse(url), nightMode);
}
})
.setNegativeButton(R.string.shared_string_cancel, null)
.show();
}
}

View file

@ -1,14 +1,10 @@
package net.osmand.plus.wikivoyage;
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.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.AlertDialog;
@ -16,64 +12,45 @@ import android.util.Log;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import net.osmand.IndexConstants;
import net.osmand.data.Amenity;
import net.osmand.data.LatLon;
import net.osmand.data.PointDescription;
import net.osmand.map.OsmandRegions;
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.download.DownloadActivityType;
import net.osmand.plus.download.DownloadResources;
import net.osmand.plus.download.IndexItem;
import net.osmand.plus.wikipedia.WikiArticleHelper;
import net.osmand.plus.wikipedia.WikipediaDialogFragment;
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 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;
interface RegionCallback {
void onRegionFound(String s);
}
/**
* Custom WebView client to handle the internal links.
*/
public class WikivoyageWebViewClient extends WebViewClient implements RegionCallback {
public class WikivoyageWebViewClient extends WebViewClient {
private static final String TAG = WikivoyageWebViewClient.class.getSimpleName();
private static final String ZIP_EXT = ".zip";
private OsmandApplication app;
private FragmentManager fragmentManager;
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.org/wiki/";
private static final String WIKI_DOMAIN = ".wikipedia.org/wiki/";
private WikiArticleSearchTask articleSearchTask;
private WikiArticleHelper wikiArticleHelper;
public WikivoyageWebViewClient(FragmentActivity context, FragmentManager fm, boolean nightMode) {
@ -81,27 +58,26 @@ public class WikivoyageWebViewClient extends WebViewClient implements RegionCall
fragmentManager = fm;
this.context = context;
this.nightMode = nightMode;
wikiArticleHelper = new WikiArticleHelper((MapActivity) context, nightMode);
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
boolean isWebPage = url.startsWith(PAGE_PREFIX_HTTP) || url.startsWith(PAGE_PREFIX_HTTPS);
if (url.contains(WIKIVOAYAGE_DOMAIN) && isWebPage) {
String lang = getLang(url);
String articleName = getArticleNameFromUrl(url, lang);
String lang = WikiArticleHelper.getLang(url);
String articleName = WikiArticleHelper.getArticleNameFromUrl(url, lang);
long articleId = app.getTravelDbHelper().getArticleId(articleName, lang);
if (articleId != 0) {
WikivoyageArticleDialogFragment.showInstance(app, fragmentManager, articleId, lang);
} else {
warnAboutExternalLoad(url, context, nightMode);
WikiArticleHelper.warnAboutExternalLoad(url, context, nightMode);
}
return true;
} else if (url.contains(WIKI_DOMAIN) && isWebPage) {
String lang = getLang(url);
String articleName = getArticleNameFromUrl(url, lang);
getWikiArticle(articleName, lang, url);
wikiArticleHelper.showWikiArticle(new LatLon(article.getLat(), article.getLon()), url);
} else if (isWebPage) {
warnAboutExternalLoad(url, context, nightMode);
WikiArticleHelper.warnAboutExternalLoad(url, context, nightMode);
} else if (url.startsWith(PREFIX_GEO)) {
if (article != null) {
List<GPXUtilities.WptPt> points = article.getGpxFile().getPoints();
@ -146,189 +122,13 @@ public class WikivoyageWebViewClient extends WebViewClient implements RegionCall
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 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)
.setPositiveButton(R.string.shared_string_ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
WikipediaDialogFragment.showFullArticle(context, Uri.parse(url), nightMode);
}
})
.setNegativeButton(R.string.shared_string_cancel, null)
.show();
}
public void setArticle(TravelArticle article) {
this.article = article;
}
private void getWikiArticle(String name, String lang, String url) {
if (article == null) {
return;
}
articleSearchTask = new WikiArticleSearchTask(this, article, name, regionName, fragmentManager,
lang, (MapActivity) context, nightMode, url);
articleSearchTask.execute();
}
@Override
public void onRegionFound(String s) {
regionName = s;
}
public void stopRunningAsyncTasks() {
if (articleSearchTask != null && articleSearchTask.getStatus() == AsyncTask.Status.RUNNING) {
articleSearchTask.cancel(false);
}
}
private static class WikiArticleSearchTask extends AsyncTask<Void, Void, List<Amenity>> {
private ProgressDialog dialog;
private RegionCallback callback;
private String name;
private String regionName;
private WeakReference<MapActivity> weakContext;
private WeakReference<OsmandApplication> applicationReference;
private boolean isNightMode;
private String url;
private String lang;
private TravelArticle article;
private FragmentManager fragmentManager;
WikiArticleSearchTask(RegionCallback callback, TravelArticle article, String articleName,
String regionName, FragmentManager fragmentManager,
String lang, MapActivity context, boolean nightMode, String url) {
this.fragmentManager = fragmentManager;
this.regionName = regionName;
name = articleName;
this.lang = lang;
weakContext = new WeakReference<>(context);
OsmandApplication app = (OsmandApplication) context.getApplication();
applicationReference = new WeakReference<>(app);
dialog = createProgressDialog();
this.isNightMode = nightMode;
this.url = url;
this.article = article;
this.callback = callback;
}
@Override
protected void onPreExecute() {
if (dialog != null) {
dialog.show();
}
}
@Override
protected List<Amenity> doInBackground(Void... voids) {
OsmandApplication application = applicationReference.get();
List<Amenity> results = new ArrayList<>();
if (application != null && !isCancelled()) {
IndexItem item = null;
try {
item = DownloadResources.findSmallestIndexItemAt(application,
new LatLon(article.getLat(), article.getLon()), DownloadActivityType.WIKIPEDIA_FILE);
} catch (IOException e) {
Log.e(TAG, e.getMessage(), e);
}
String filename = null;
if (item != null && item.isDownloaded()) {
filename = getFilenameFromIndex(item.getFileName());
}
AmenityIndexRepositoryBinary repository = application.getResourceManager()
.getAmenityRepositoryByFileName(filename == null ? "" : filename);
if (repository == null) {
if ((regionName == null || regionName.isEmpty()) && item != null) {
regionName = (getRegionName(item.getFileName(), application.getRegions()));
callback.onRegionFound(regionName);
}
return null;
} else {
if (isCancelled()) {
return null;
}
results.addAll(repository.searchAmenitiesByName(0, 0, 0, 0,
Integer.MAX_VALUE, Integer.MAX_VALUE, name, null));
}
}
return results;
}
@Override
protected void onCancelled() {
MapActivity activity = weakContext.get();
if (activity != null && !activity.isActivityDestroyed() && dialog != null) {
dialog.dismiss();
}
dialog = null;
callback = null;
}
@Override
protected void onPostExecute(List<Amenity> found) {
MapActivity activity = weakContext.get();
if (activity != null && !activity.isActivityDestroyed() && dialog != null) {
dialog.dismiss();
if (found == null) {
WikivoyageArticleWikiLinkFragment.showInstance(fragmentManager, regionName == null ?
"" : regionName, url);
} else if (!found.isEmpty()) {
WikipediaDialogFragment.showInstance(activity, found.get(0), lang);
} else {
warnAboutExternalLoad(url, weakContext.get(), isNightMode);
}
}
}
private String getFilenameFromIndex(String fileName) {
return fileName
.replace("_" + IndexConstants.BINARY_MAP_VERSION, "")
.replace(ZIP_EXT, "");
}
private String getRegionName(String filename, OsmandRegions osmandRegions) {
if (osmandRegions != null && filename != null) {
String regionName = filename
.replace("_" + IndexConstants.BINARY_MAP_VERSION, "")
.replace(IndexConstants.BINARY_WIKI_MAP_INDEX_EXT_ZIP, "")
.toLowerCase();
return osmandRegions.getLocaleName(regionName, false);
}
return "";
}
private ProgressDialog createProgressDialog() {
MapActivity activity = weakContext.get();
if (activity != null && !activity.isActivityDestroyed()) {
ProgressDialog dialog = new ProgressDialog(activity);
dialog.setCancelable(false);
dialog.setMessage(activity.getString(R.string.wiki_article_search_text));
return dialog;
}
return null;
if (wikiArticleHelper != null) {
wikiArticleHelper.stopSearchAsyncTask();
}
}
}