diff options
| author | Bananeweizen <bananeweizen@gmx.de> | 2013-10-26 14:52:38 +0200 |
|---|---|---|
| committer | Bananeweizen <bananeweizen@gmx.de> | 2013-10-26 14:52:38 +0200 |
| commit | e054988257da663b6c998cc2c0da84cf264bc23b (patch) | |
| tree | 97d9aba71e004ad590b9519d50e5c715c7f8d6b2 /main | |
| parent | 88d07a7a59fa7e8ceb93d2b219fd8e2c593caecd (diff) | |
| parent | bd09f1887a8e6a8e9b919d4605c04155a3e73760 (diff) | |
| download | cgeo-e054988257da663b6c998cc2c0da84cf264bc23b.zip cgeo-e054988257da663b6c998cc2c0da84cf264bc23b.tar.gz cgeo-e054988257da663b6c998cc2c0da84cf264bc23b.tar.bz2 | |
Merge remote-tracking branch 'mucek4/fix2830'
* fix HTML parsing
* simplify activity API
* disable the action for non premium members
Diffstat (limited to 'main')
| -rw-r--r-- | main/res/values/strings.xml | 5 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/CacheListActivity.java | 20 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/Intents.java | 1 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/MainActivity.java | 21 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/PocketQueryList.java | 125 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/connector/gc/GCConstants.java | 1 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/connector/gc/GCParser.java | 50 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/enumerations/CacheListType.java | 1 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/loaders/AbstractSearchLoader.java | 1 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/loaders/PocketGeocacheListLoader.java | 28 |
10 files changed, 253 insertions, 0 deletions
diff --git a/main/res/values/strings.xml b/main/res/values/strings.xml index 68de736..a4e7350 100644 --- a/main/res/values/strings.xml +++ b/main/res/values/strings.xml @@ -226,6 +226,8 @@ <string name="warn_deprecated_mapfile">You are using a deprecated version of map file (0.2.4).\nConsider switching to a version 0.3.0 map.\nWe will drop support for version 0.2.4 in the next release.</string> <string name="warn_nonexistant_mapfile">The selected map file does not exist.\nOffline maps are not available.</string> <string name="warn_rendertheme_missing">Map theme not found.</string> + <string name="warn_pocket_query_select">No Pocket query selected.</string> + <string name="warn_no_pocket_query_found">No Pocket query found online.</string> <string name="info_log_posted">c:geo successfully submitted the log.</string> <string name="info_log_saved">c:geo successfully saved the log.</string> <string name="info_log_cleared">Log was cleared.</string> @@ -843,6 +845,9 @@ <string name="search_address_started">Searching for places</string> <string name="search_address_result">Found places</string> <string name="search_own_caches">Search my caches</string> + <string name="search_pocket_title">Pocket Query</string> + <string name="search_pocket_loading">Loading a list of Pocket Queries</string> + <string name="search_pocket_select">Choose Pocket Query</string> <!-- trackable --> <string name="trackable">Trackable</string> diff --git a/main/src/cgeo/geocaching/CacheListActivity.java b/main/src/cgeo/geocaching/CacheListActivity.java index 33535ad..59f7297 100644 --- a/main/src/cgeo/geocaching/CacheListActivity.java +++ b/main/src/cgeo/geocaching/CacheListActivity.java @@ -26,6 +26,7 @@ import cgeo.geocaching.loaders.KeywordGeocacheListLoader; import cgeo.geocaching.loaders.NextPageGeocacheListLoader; import cgeo.geocaching.loaders.OfflineGeocacheListLoader; import cgeo.geocaching.loaders.OwnerGeocacheListLoader; +import cgeo.geocaching.loaders.PocketGeocacheListLoader; import cgeo.geocaching.loaders.RemoveFromHistoryLoader; import cgeo.geocaching.loaders.UsernameGeocacheListLoader; import cgeo.geocaching.maps.CGeoMap; @@ -1570,6 +1571,19 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA context.startActivity(cachesIntent); } + public static void startActivityPocket(final AbstractActivity context, final @NonNull PocketQueryList pq) { + final String guid = pq.getGuid(); + if (guid == null) { + context.showToast(CgeoApplication.getInstance().getString(R.string.warn_pocket_query_select)); + return; + } + final Intent cachesIntent = new Intent(context, CacheListActivity.class); + cachesIntent.putExtra(Intents.EXTRA_LIST_TYPE, CacheListType.POCKET); + cachesIntent.putExtra(Intents.EXTRA_NAME, pq.getName()); + cachesIntent.putExtra(Intents.EXTRA_POCKET_GUID, guid); + context.startActivity(cachesIntent); + } + // Loaders @Override @@ -1650,6 +1664,12 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA case NEXT_PAGE: loader = new NextPageGeocacheListLoader(app, search); break; + case POCKET: + final String guid = extras.getString(Intents.EXTRA_POCKET_GUID); + final String pocket_name = extras.getString(Intents.EXTRA_NAME); + title = pocket_name; + loader = new PocketGeocacheListLoader(app, guid); + break; default: throw new IllegalStateException(); } diff --git a/main/src/cgeo/geocaching/Intents.java b/main/src/cgeo/geocaching/Intents.java index a700451..d9d9829 100644 --- a/main/src/cgeo/geocaching/Intents.java +++ b/main/src/cgeo/geocaching/Intents.java @@ -28,4 +28,5 @@ public class Intents { public static final String EXTRA_USERNAME = PREFIX + "username"; public static final String EXTRA_WAYPOINT_ID = PREFIX + "waypoint_id"; public static final String EXTRA_CACHELIST = PREFIX + "cache_list"; + public static final String EXTRA_POCKET_GUID = PREFIX + "pocket_guid"; } diff --git a/main/src/cgeo/geocaching/MainActivity.java b/main/src/cgeo/geocaching/MainActivity.java index 8a79786..0daa124 100644 --- a/main/src/cgeo/geocaching/MainActivity.java +++ b/main/src/cgeo/geocaching/MainActivity.java @@ -27,6 +27,7 @@ import com.google.zxing.integration.android.IntentResult; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; import android.app.AlertDialog; import android.app.AlertDialog.Builder; @@ -512,6 +513,26 @@ public class MainActivity extends AbstractActivity { } }); nearestView.setBackgroundResource(R.drawable.main_nearby); + + nearestView.setOnLongClickListener(new View.OnLongClickListener() { + + @Override + public boolean onLongClick(View v) { + if (!Settings.isPremiumMember()) { + return true; + } + new PocketQueryList.UserInterface(MainActivity.this).promptForListSelection(new RunnableWithArgument<PocketQueryList>() { + + @Override + public void run(final @NonNull PocketQueryList pql) { + CacheListActivity.startActivityPocket(MainActivity.this, pql); + } + }); + return true; + } + }); + nearestView.setLongClickable(true); + } navType.setText(res.getString(geo.getLocationProvider().resourceId)); diff --git a/main/src/cgeo/geocaching/PocketQueryList.java b/main/src/cgeo/geocaching/PocketQueryList.java new file mode 100644 index 0000000..e1a921c --- /dev/null +++ b/main/src/cgeo/geocaching/PocketQueryList.java @@ -0,0 +1,125 @@ +package cgeo.geocaching; + +import cgeo.geocaching.activity.ActivityMixin; +import cgeo.geocaching.connector.gc.GCParser; +import cgeo.geocaching.utils.RunnableWithArgument; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.ProgressDialog; +import android.content.DialogInterface; +import android.content.res.Resources; +import android.os.Handler; +import android.os.Message; + +import java.util.List; + +public final class PocketQueryList { + + private final String guid; + private final int maxCaches; + private final String name; + + public PocketQueryList(String guid, String name, int maxCaches) { + this.guid = guid; + this.name = name; + this.maxCaches = maxCaches; + } + + public static class UserInterface { + + List<PocketQueryList> pocketQueryList = null; + RunnableWithArgument<PocketQueryList> runAfterwards; + + private Handler loadPocketQueryHandler = new Handler() { + + @Override + public void handleMessage(Message msg) { + if ((pocketQueryList == null) || (pocketQueryList.size() == 0)) { + if (waitDialog != null) { + waitDialog.dismiss(); + } + + ActivityMixin.showToast(activity, res.getString(R.string.warn_no_pocket_query_found)); + + return; + } + + if (waitDialog != null) { + waitDialog.dismiss(); + } + + final CharSequence[] items = new CharSequence[pocketQueryList.size()]; + + for (int i = 0; i < pocketQueryList.size(); i++) { + PocketQueryList pq = pocketQueryList.get(i); + + items[i] = pq.name + " (" + pq.maxCaches + ")"; + } + + AlertDialog.Builder builder = new AlertDialog.Builder(activity); + builder.setTitle(res.getString(R.string.search_pocket_select)); + builder.setItems(items, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int itemId) { + final PocketQueryList query = pocketQueryList.get(itemId); + dialogInterface.dismiss(); + runAfterwards.run(query); + } + }); + builder.create().show(); + + } + }; + + private class LoadPocketQueryListThread extends Thread { + final private Handler handler; + + public LoadPocketQueryListThread(Handler handlerIn) { + handler = handlerIn; + } + + @Override + public void run() { + pocketQueryList = GCParser.searchPocketQueryList(); + handler.sendMessage(Message.obtain()); + } + } + + private final Activity activity; + private final CgeoApplication app; + private final Resources res; + private ProgressDialog waitDialog = null; + + public UserInterface(final Activity activity) { + this.activity = activity; + app = CgeoApplication.getInstance(); + res = app.getResources(); + } + + public void promptForListSelection(final RunnableWithArgument<PocketQueryList> runAfterwards) { + + this.runAfterwards = runAfterwards; + + waitDialog = ProgressDialog.show(activity, res.getString(R.string.search_pocket_title), res.getString(R.string.search_pocket_loading), true, true); + + LoadPocketQueryListThread thread = new LoadPocketQueryListThread(loadPocketQueryHandler); + thread.start(); + } + + + } + + public String getGuid() { + return guid; + } + + public int getMaxCaches() { + return maxCaches; + } + + public String getName() { + return name; + } + +} diff --git a/main/src/cgeo/geocaching/connector/gc/GCConstants.java b/main/src/cgeo/geocaching/connector/gc/GCConstants.java index 601bebe..152b8a2 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCConstants.java +++ b/main/src/cgeo/geocaching/connector/gc/GCConstants.java @@ -158,6 +158,7 @@ public final class GCConstants { public final static Pattern PATTERN_VIEWSTATEFIELDCOUNT = Pattern.compile("id=\"__VIEWSTATEFIELDCOUNT\"[^(value)]+value=\"(\\d+)\"[^>]+>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); public final static Pattern PATTERN_VIEWSTATES = Pattern.compile("id=\"__VIEWSTATE(\\d*)\"[^(value)]+value=\"([^\"]+)\"[^>]+>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); public final static Pattern PATTERN_USERTOKEN = Pattern.compile("userToken\\s*=\\s*'([^']+)'"); + public final static Pattern PATTERN_LIST_PQ = Pattern.compile(Pattern.quote("pocket_query.png") + ".*?" + Pattern.quote("(") + "(.*?)" + Pattern.quote(")") + ".*?guid=([^\"]*)\".*?>([^<]*)<"); /** Live Map since 14.02.2012 */ public final static Pattern PATTERN_USERSESSION = Pattern.compile("UserSession\\('([^']+)'"); diff --git a/main/src/cgeo/geocaching/connector/gc/GCParser.java b/main/src/cgeo/geocaching/connector/gc/GCParser.java index bfbcaa4..869d27d 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCParser.java +++ b/main/src/cgeo/geocaching/connector/gc/GCParser.java @@ -5,6 +5,7 @@ import cgeo.geocaching.DataStore; import cgeo.geocaching.Geocache; import cgeo.geocaching.Image; import cgeo.geocaching.LogEntry; +import cgeo.geocaching.PocketQueryList; import cgeo.geocaching.R; import cgeo.geocaching.SearchResult; import cgeo.geocaching.Trackable; @@ -906,6 +907,17 @@ public abstract class GCParser { return searchByAny(cacheType, isSearchForMyCaches(userName), showCaptcha, params, recaptchaReceiver); } + public static SearchResult searchByPocket(final String pocketGuid, final CacheType cacheType, final boolean showCaptcha, RecaptchaReceiver recaptchaReceiver) { + if (StringUtils.isBlank(pocketGuid)) { + Log.e("GCParser.searchByPocket: No guid name given"); + return null; + } + + final Parameters params = new Parameters("pq", pocketGuid); + + return searchByAny(cacheType, false, showCaptcha, params, recaptchaReceiver); + } + public static SearchResult searchByOwner(final String userName, final CacheType cacheType, final boolean showCaptcha, RecaptchaReceiver recaptchaReceiver) { if (StringUtils.isBlank(userName)) { Log.e("GCParser.searchByOwner: No user name given"); @@ -980,6 +992,44 @@ public abstract class GCParser { return trackable; } + public static List<PocketQueryList> searchPocketQueryList() { + + final Parameters params = new Parameters(); + + final String page = Login.getRequestLogged("http://www.geocaching.com/pocket/default.aspx", params); + + if (StringUtils.isBlank(page)) { + Log.e("GCParser.searchPocketQueryList: No data from server"); + return null; + } + + String subPage = StringUtils.substringAfter(page, "class=\"PocketQueryListTable"); + if (StringUtils.isEmpty(subPage)) { + Log.e("GCParser.searchPocketQueryList: class \"PocketQueryListTable\" not found on page"); + return Collections.emptyList(); + } + + List<PocketQueryList> list = new ArrayList<PocketQueryList>(); + + final MatcherWrapper matcherPocket = new MatcherWrapper(GCConstants.PATTERN_LIST_PQ, subPage); + + while (matcherPocket.find()) { + int maxCaches; + try { + maxCaches = Integer.parseInt(matcherPocket.group(1)); + } catch (NumberFormatException e) { + maxCaches = 0; + Log.e("GCParser.searchPocketQueryList: Unable to parse max caches", e); + } + final String guid = Html.fromHtml(matcherPocket.group(2)).toString(); + final String name = Html.fromHtml(matcherPocket.group(3)).toString(); + final PocketQueryList pqList = new PocketQueryList(guid, name, maxCaches); + list.add(pqList); + } + + return list; + } + public static ImmutablePair<StatusCode, String> postLog(final String geocode, final String cacheid, final String[] viewstates, final LogType logType, final int year, final int month, final int day, final String log, final List<TrackableLog> trackables) { diff --git a/main/src/cgeo/geocaching/enumerations/CacheListType.java b/main/src/cgeo/geocaching/enumerations/CacheListType.java index b75c118..f482d5b 100644 --- a/main/src/cgeo/geocaching/enumerations/CacheListType.java +++ b/main/src/cgeo/geocaching/enumerations/CacheListType.java @@ -2,6 +2,7 @@ package cgeo.geocaching.enumerations; public enum CacheListType { OFFLINE(true), + POCKET(false), HISTORY(true), NEAREST(false), COORDINATE(false), diff --git a/main/src/cgeo/geocaching/loaders/AbstractSearchLoader.java b/main/src/cgeo/geocaching/loaders/AbstractSearchLoader.java index ebf29d1..1cc9706 100644 --- a/main/src/cgeo/geocaching/loaders/AbstractSearchLoader.java +++ b/main/src/cgeo/geocaching/loaders/AbstractSearchLoader.java @@ -17,6 +17,7 @@ public abstract class AbstractSearchLoader extends AsyncTaskLoader<SearchResult> public enum CacheListLoaderType { OFFLINE, + POCKET, HISTORY, NEAREST, COORDINATE, diff --git a/main/src/cgeo/geocaching/loaders/PocketGeocacheListLoader.java b/main/src/cgeo/geocaching/loaders/PocketGeocacheListLoader.java new file mode 100644 index 0000000..9256189 --- /dev/null +++ b/main/src/cgeo/geocaching/loaders/PocketGeocacheListLoader.java @@ -0,0 +1,28 @@ +package cgeo.geocaching.loaders; + +import cgeo.geocaching.SearchResult; +import cgeo.geocaching.connector.gc.GCParser; +import cgeo.geocaching.settings.Settings; + +import android.content.Context; + +public class PocketGeocacheListLoader extends AbstractSearchLoader { + private final String guid; + + public PocketGeocacheListLoader(Context context, String guid) { + super(context); + this.guid = guid; + } + + @Override + public SearchResult runSearch() { + + if (Settings.isGCConnectorActive()) { + return GCParser.searchByPocket(guid, Settings.getCacheType(), Settings.isShowCaptcha(), this); + } + + return new SearchResult(); + + } + +} |
