aboutsummaryrefslogtreecommitdiffstats
path: root/main/src/cgeo/geocaching/CacheDetailActivity.java
diff options
context:
space:
mode:
Diffstat (limited to 'main/src/cgeo/geocaching/CacheDetailActivity.java')
-rw-r--r--main/src/cgeo/geocaching/CacheDetailActivity.java264
1 files changed, 165 insertions, 99 deletions
diff --git a/main/src/cgeo/geocaching/CacheDetailActivity.java b/main/src/cgeo/geocaching/CacheDetailActivity.java
index 1662bb6..fe6693b 100644
--- a/main/src/cgeo/geocaching/CacheDetailActivity.java
+++ b/main/src/cgeo/geocaching/CacheDetailActivity.java
@@ -1,5 +1,8 @@
package cgeo.geocaching;
+import butterknife.InjectView;
+import butterknife.Views;
+
import cgeo.calendar.ICalendar;
import cgeo.geocaching.activity.AbstractViewPagerActivity;
import cgeo.geocaching.activity.Progress;
@@ -21,13 +24,14 @@ import cgeo.geocaching.network.Parameters;
import cgeo.geocaching.ui.AbstractCachingPageViewCreator;
import cgeo.geocaching.ui.AnchorAwareLinkMovementMethod;
import cgeo.geocaching.ui.CacheDetailsCreator;
+import cgeo.geocaching.ui.CoordinatesFormatSwitcher;
import cgeo.geocaching.ui.DecryptTextClickListener;
+import cgeo.geocaching.ui.EditNoteDialog;
+import cgeo.geocaching.ui.EditNoteDialog.EditNoteDialogListener;
import cgeo.geocaching.ui.Formatter;
import cgeo.geocaching.ui.ImagesList;
-import cgeo.geocaching.ui.ImagesList.ImageType;
import cgeo.geocaching.ui.LoggingUI;
import cgeo.geocaching.ui.WeakReferenceHandler;
-import cgeo.geocaching.ui.dialog.EditorDialog;
import cgeo.geocaching.utils.BaseUtils;
import cgeo.geocaching.utils.CancellableHandler;
import cgeo.geocaching.utils.ClipboardUtils;
@@ -65,12 +69,12 @@ import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
+import android.support.v4.app.FragmentManager;
import android.text.Editable;
import android.text.Html;
import android.text.Spannable;
import android.text.Spanned;
import android.text.format.DateUtils;
-import android.text.method.LinkMovementMethod;
import android.text.style.ForegroundColorSpan;
import android.text.style.StrikethroughSpan;
import android.text.style.StyleSpan;
@@ -112,7 +116,8 @@ import java.util.regex.Pattern;
*
* e.g. details, description, logs, waypoints, inventory...
*/
-public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailActivity.Page> {
+public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailActivity.Page>
+ implements EditNoteDialogListener {
private static final int MENU_FIELD_COPY = 1;
private static final int MENU_FIELD_TRANSLATE = 2;
@@ -139,6 +144,8 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
private final Progress progress = new Progress();
private SearchResult search;
+ private EditNoteDialogListener editNoteDialogListener;
+
private final GeoDirHandler locationUpdater = new GeoDirHandler() {
@Override
public void updateGeoData(final IGeoData geo) {
@@ -187,18 +194,11 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
};
protected ImagesList imagesList;
- public CacheDetailActivity() {
- // identifier for manual
- super("c:geolocation-cache-details");
- }
-
@Override
public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
+ super.onCreate(savedInstanceState, R.layout.cacheview);
- // initialize the main view and set a default title
- setTheme();
- setContentView(R.layout.cacheview);
+ // set title in code, as the activity needs a hard coded title due to the intent filters
setTitle(res.getString(R.string.cache));
String geocode = null;
@@ -541,7 +541,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
NavigationAppFactory.addMenuItems(subMenu, cache);
menu.add(0, MENU_CALENDAR, 0, res.getString(R.string.cache_menu_event)).setIcon(R.drawable.ic_menu_agenda); // add event to calendar
- LoggingUI.addMenuItems(menu, cache);
+ LoggingUI.addMenuItems(this, menu, cache);
menu.add(0, MENU_CACHES_AROUND, 0, res.getString(R.string.cache_menu_around)).setIcon(R.drawable.ic_menu_rotate); // caches around
menu.add(0, MENU_BROWSER, 0, res.getString(R.string.cache_menu_browser)).setIcon(R.drawable.ic_menu_globe); // browser
menu.add(0, MENU_SHARE, 0, res.getString(R.string.cache_menu_share)).setIcon(R.drawable.ic_menu_share); // share cache
@@ -557,6 +557,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
menu.findItem(MENU_CACHES_AROUND).setVisible(null != cache.getCoords() && cache.supportsCachesAround());
menu.findItem(MENU_BROWSER).setVisible(cache.canOpenInBrowser());
}
+ LoggingUI.onPrepareOptionsMenu(menu, cache);
return super.onPrepareOptionsMenu(menu);
}
@@ -797,7 +798,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
/**
* Wrapper for the referenced method in the xml-layout.
*/
- public void startDefaultNavigation(@SuppressWarnings("unused") View view) {
+ public void goDefaultNavigation(@SuppressWarnings("unused") View view) {
startDefaultNavigation();
}
@@ -901,7 +902,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
return;
}
imagesList = new ImagesList(this, cache.getGeocode());
- imagesList.loadImages(imageView, cache.getImages(), ImageType.AllImages, false);
+ imagesList.loadImages(imageView, cache.getImages(), false);
}
public static void startActivity(final Context context, final String geocode) {
@@ -1165,7 +1166,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
// favorite count
if (cache.getFavoritePoints() > 0) {
- details.add(R.string.cache_favourite, cache.getFavoritePoints() + "×");
+ details.add(R.string.cache_favorite, cache.getFavoritePoints() + "×");
}
// own rating
@@ -1204,23 +1205,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
// cache coordinates
if (cache.getCoords() != null) {
TextView valueView = details.add(R.string.cache_coordinates, cache.getCoords().toString());
- valueView.setOnClickListener(new View.OnClickListener() {
- private int position = 0;
- private GeopointFormatter.Format[] availableFormats = new GeopointFormatter.Format[] {
- GeopointFormatter.Format.LAT_LON_DECMINUTE,
- GeopointFormatter.Format.LAT_LON_DECSECOND,
- GeopointFormatter.Format.LAT_LON_DECDEGREE
- };
-
- // rotate coordinate formats on click
- @Override
- public void onClick(View view) {
- position = (position + 1) % availableFormats.length;
-
- final TextView valueView = (TextView) view.findViewById(R.id.value);
- valueView.setText(cache.getCoords().format(availableFormats[position]));
- }
- });
+ valueView.setOnClickListener(new CoordinatesFormatSwitcher(cache.getCoords()));
registerForContextMenu(valueView);
}
@@ -1260,7 +1245,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
TextView licenseView = ((TextView) view.findViewById(R.id.license));
licenseView.setText(Html.fromHtml(license), BufferType.SPANNABLE);
licenseView.setClickable(true);
- licenseView.setMovementMethod(LinkMovementMethod.getInstance());
+ licenseView.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance());
} else {
view.findViewById(R.id.license_box).setVisibility(View.GONE);
}
@@ -1356,6 +1341,11 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
return;
}
+ if (!Network.isNetworkConnected(getApplicationContext())) {
+ showToast(getString(R.string.err_server));
+ return;
+ }
+
final RefreshCacheHandler refreshCacheHandler = new RefreshCacheHandler();
progress.show(CacheDetailActivity.this, res.getString(R.string.cache_dialog_refresh_title), res.getString(R.string.cache_dialog_refresh_message), true, refreshCacheHandler.cancelMessage());
@@ -1500,7 +1490,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
}
- /** Thread to add this cache to the favourite list of the user */
+ /** Thread to add this cache to the favorite list of the user */
private class FavoriteAddThread extends Thread {
private final Handler handler;
@@ -1514,7 +1504,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
}
- /** Thread to remove this cache to the favourite list of the user */
+ /** Thread to remove this cache to the favorite list of the user */
private class FavoriteRemoveThread extends Thread {
private final Handler handler;
@@ -1541,25 +1531,25 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
/**
- * Listener for "add to favourites" button
+ * Listener for "add to favorites" button
*/
private class FavoriteAddClickListener extends AbstractWatchlistClickListener {
@Override
public void onClick(View arg0) {
- doExecute(R.string.cache_dialog_favourite_add_title,
- R.string.cache_dialog_favourite_add_message,
+ doExecute(R.string.cache_dialog_favorite_add_title,
+ R.string.cache_dialog_favorite_add_message,
new FavoriteAddThread(new FavoriteUpdateHandler()));
}
}
/**
- * Listener for "remove from favourites" button
+ * Listener for "remove from favorites" button
*/
private class FavoriteRemoveClickListener extends AbstractWatchlistClickListener {
@Override
public void onClick(View arg0) {
- doExecute(R.string.cache_dialog_favourite_remove_title,
- R.string.cache_dialog_favourite_remove_message,
+ doExecute(R.string.cache_dialog_favorite_remove_title,
+ R.string.cache_dialog_favorite_remove_message,
new FavoriteRemoveThread(new FavoriteUpdateHandler()));
}
}
@@ -1752,7 +1742,9 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
- private class DescriptionViewCreator extends AbstractCachingPageViewCreator<ScrollView> {
+ protected class DescriptionViewCreator extends AbstractCachingPageViewCreator<ScrollView> {
+
+ @InjectView(R.id.personalnote) protected TextView personalNoteView;
@Override
public ScrollView getDispatchedView() {
@@ -1762,11 +1754,11 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
view = (ScrollView) getLayoutInflater().inflate(R.layout.cacheview_description, null);
+ Views.inject(this, view);
// cache short description
if (StringUtils.isNotBlank(cache.getShortDescription())) {
- new LoadDescriptionTask().execute(cache.getShortDescription(), view.findViewById(R.id.shortdesc), null);
- registerForContextMenu(view.findViewById(R.id.shortdesc));
+ new LoadDescriptionTask(cache.getShortDescription(), view.findViewById(R.id.shortdesc), null, null).execute();
}
// long description
@@ -1786,31 +1778,20 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
}
// cache personal note
- final TextView personalNoteView = (TextView) view.findViewById(R.id.personalnote);
- setPersonalNote(personalNoteView);
- personalNoteView.setMovementMethod(LinkMovementMethod.getInstance());
+ setPersonalNote();
+ personalNoteView.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance());
registerForContextMenu(personalNoteView);
final Button personalNoteEdit = (Button) view.findViewById(R.id.edit_personalnote);
- if (cache.isOffline()) {
- personalNoteEdit.setVisibility(View.VISIBLE);
- personalNoteEdit.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- EditorDialog editor = new EditorDialog(CacheDetailActivity.this, personalNoteView.getText());
- editor.setOnEditorUpdate(new EditorDialog.EditorUpdate() {
- @Override
- public void update(CharSequence editorText) {
- cache.setPersonalNote(editorText.toString());
- setPersonalNote(personalNoteView);
- cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
- }
- });
- editor.show();
+ personalNoteEdit.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (cache.isOffline()) {
+ editPersonalNote();
+ } else {
+ warnPersonalNoteNeedsStoring();
}
- });
- } else {
- personalNoteEdit.setVisibility(View.INVISIBLE);
- }
+ }
+ });
// cache hint and spoiler images
final View hintBoxView = view.findViewById(R.id.hint_box);
@@ -1863,13 +1844,28 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
return view;
}
- private void setPersonalNote(final TextView personalNoteView) {
+ private void editPersonalNote() {
+ if (cache.isOffline()) {
+ editNoteDialogListener = new EditNoteDialogListener() {
+ @Override
+ public void onFinishEditNoteDialog(final String note) {
+ cache.setPersonalNote(note);
+ setPersonalNote();
+ cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
+ }
+ };
+ final FragmentManager fm = getSupportFragmentManager();
+ final EditNoteDialog dialog = EditNoteDialog.newInstance(cache.getPersonalNote());
+ dialog.show(fm, "fragment_edit_note");
+ }
+ }
+
+ private void setPersonalNote() {
final String personalNote = cache.getPersonalNote();
personalNoteView.setText(personalNote, TextView.BufferType.SPANNABLE);
if (StringUtils.isNotBlank(personalNote)) {
personalNoteView.setVisibility(View.VISIBLE);
- }
- else {
+ } else {
personalNoteView.setVisibility(View.GONE);
}
}
@@ -1880,12 +1876,43 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
showDesc.setOnClickListener(null);
view.findViewById(R.id.loading).setVisibility(View.VISIBLE);
- new LoadDescriptionTask().execute(cache.getDescription(), view.findViewById(R.id.longdesc), view.findViewById(R.id.loading));
- registerForContextMenu(view.findViewById(R.id.longdesc));
+ new LoadDescriptionTask(cache.getDescription(), view.findViewById(R.id.longdesc), view.findViewById(R.id.loading), view.findViewById(R.id.shortdesc)).execute();
+ }
+
+ private void warnPersonalNoteNeedsStoring() {
+ final AlertDialog.Builder builder = new AlertDialog.Builder(CacheDetailActivity.this);
+ builder.setTitle(R.string.cache_personal_note_unstored);
+ builder.setMessage(R.string.cache_personal_note_store);
+ builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ // do nothing
+ }
+ });
+
+ builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ dialog.dismiss();
+ cache.store(null);
+ editPersonalNote();
+ }
+
+ });
+ final AlertDialog dialog = builder.create();
+ dialog.setOwnerActivity(CacheDetailActivity.this);
+ dialog.show();
}
}
+ @Override
+ public void onFinishEditNoteDialog(final String note) {
+ editNoteDialogListener.onFinishEditNoteDialog(note);
+ }
+
private static class HtmlImageCounter implements Html.ImageGetter {
private int imageCount = 0;
@@ -1912,28 +1939,33 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
* </ol>
*/
private class LoadDescriptionTask extends AsyncTask<Object, Void, Void> {
- private View loadingIndicatorView;
- private TextView descriptionView;
- private String descriptionString;
+ private final View loadingIndicatorView;
+ private final TextView descriptionView;
+ private final String descriptionString;
private Spanned description;
+ private final View shortDescView;
+ public LoadDescriptionTask(final String description, final View descriptionView, final View loadingIndicatorView, final View shortDescView) {
+ this.descriptionString = description;
+ this.descriptionView = (TextView) descriptionView;
+ this.loadingIndicatorView = loadingIndicatorView;
+ this.shortDescView = shortDescView;
+ }
@Override
protected Void doInBackground(Object... params) {
try {
- descriptionString = ((String) params[0]);
- descriptionView = (TextView) params[1];
- loadingIndicatorView = (View) params[2];
-
// Fast preview: parse only HTML without loading any images
HtmlImageCounter imageCounter = new HtmlImageCounter();
final UnknownTagsHandler unknownTagsHandler = new UnknownTagsHandler();
description = Html.fromHtml(descriptionString, imageCounter, unknownTagsHandler);
publishProgress();
+
+ boolean needsRefresh = false;
if (imageCounter.getImageCount() > 0) {
// Complete view: parse again with loading images - if necessary ! If there are any images causing problems the user can see at least the preview
description = Html.fromHtml(descriptionString, new HtmlImage(cache.getGeocode(), true, cache.getListId(), false), unknownTagsHandler);
- publishProgress();
+ needsRefresh = true;
}
// If description has an HTML construct which may be problematic to render, add a note at the end of the long description.
@@ -1945,6 +1977,10 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
final Spanned tableNote = Html.fromHtml(res.getString(R.string.cache_description_table_note, "<a href=\"" + cache.getUrl() + "\">" + connector.getName() + "</a>"));
((Editable) description).append("\n\n").append(tableNote);
((Editable) description).setSpan(new StyleSpan(Typeface.ITALIC), startPos, description.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ needsRefresh = true;
+ }
+
+ if (needsRefresh) {
publishProgress();
}
} catch (Exception e) {
@@ -1953,25 +1989,40 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
return null;
}
- /*
- * (non-Javadoc)
- *
- * @see android.os.AsyncTask#onProgressUpdate(Progress[])
- */
@Override
protected void onProgressUpdate(Void... values) {
- if (description != null) {
- if (StringUtils.isNotBlank(descriptionString)) {
- descriptionView.setText(description, TextView.BufferType.SPANNABLE);
- descriptionView.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance());
- fixBlackTextColor(descriptionView, descriptionString);
- }
-
- descriptionView.setVisibility(View.VISIBLE);
- } else {
+ if (description == null) {
showToast(res.getString(R.string.err_load_descr_failed));
+ return;
+ }
+ if (StringUtils.isNotBlank(descriptionString)) {
+ descriptionView.setText(description, TextView.BufferType.SPANNABLE);
+ descriptionView.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance());
+ fixBlackTextColor(descriptionView, descriptionString);
+ descriptionView.setVisibility(View.VISIBLE);
+ registerForContextMenu(descriptionView);
+
+ hideDuplicatedShortDescription();
}
+ }
+ /**
+ * Hide the short description, if it is contained somewhere at the start of the long description.
+ */
+ private void hideDuplicatedShortDescription() {
+ if (shortDescView != null) {
+ final String shortDescription = cache.getShortDescription();
+ if (StringUtils.isNotBlank(shortDescription)) {
+ int index = descriptionString.indexOf(shortDescription);
+ if (index >= 0 && index < 200) {
+ shortDescView.setVisibility(View.GONE);
+ }
+ }
+ }
+ }
+
+ @Override
+ protected void onPostExecute(Void result) {
if (null != loadingIndicatorView) {
loadingIndicatorView.setVisibility(View.GONE);
}
@@ -2094,15 +2145,15 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
// Fast preview: parse only HTML without loading any images
HtmlImageCounter imageCounter = new HtmlImageCounter();
final UnknownTagsHandler unknownTagsHandler = new UnknownTagsHandler();
- holder.text.setText(Html.fromHtml(logText, imageCounter, unknownTagsHandler));
+ holder.text.setText(Html.fromHtml(logText, imageCounter, unknownTagsHandler), TextView.BufferType.SPANNABLE);
if (imageCounter.getImageCount() > 0) {
// Complete view: parse again with loading images - if necessary ! If there are any images causing problems the user can see at least the preview
LogImageLoader loader = new LogImageLoader(holder);
- loader.execute(new String[] { logText });
+ loader.execute(logText);
}
}
else {
- holder.text.setText(logText);
+ holder.text.setText(logText, TextView.BufferType.SPANNABLE);
}
// images
@@ -2132,7 +2183,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
if (null == convertView) {
// if convertView != null then this listeners are already set
holder.author.setOnClickListener(userActionsClickListener);
- holder.text.setMovementMethod(LinkMovementMethod.getInstance());
+ holder.text.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance());
holder.text.setOnClickListener(decryptTextClickListener);
registerForContextMenu(holder.text);
}
@@ -2190,10 +2241,24 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
statusMarker = (ImageView) base.findViewById(R.id.log_mark);
}
+ /**
+ * Read the position of the cursor pointed to by this holder.
+ * <br/>
+ * This must be called by the UI thread.
+ *
+ * @return the cursor position
+ */
public int getPosition() {
return position;
}
+ /**
+ * Set the position of the cursor pointed to by this holder.
+ * <br/>
+ * This must be called by the UI thread.
+ *
+ * @param position the cursor position
+ */
public void setPosition(final int position) {
this.position = position;
}
@@ -2224,6 +2289,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc
// coordinates
if (null != wpt.getCoords()) {
final TextView coordinatesView = (TextView) waypointView.findViewById(R.id.coordinates);
+ coordinatesView.setOnClickListener(new CoordinatesFormatSwitcher(wpt.getCoords()));
coordinatesView.setText(wpt.getCoords().toString());
coordinatesView.setVisibility(View.VISIBLE);
}