package cgeo.geocaching.log;
import android.R.string;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
import butterknife.BindView;
import butterknife.ButterKnife;
import cgeo.geocaching.ImageSelectActivity;
import cgeo.geocaching.Intents;
import cgeo.geocaching.R;
import cgeo.geocaching.TrackableActivity;
import cgeo.geocaching.command.AbstractCommand;
import cgeo.geocaching.connector.ConnectorFactory;
import cgeo.geocaching.connector.ILoggingManager;
import cgeo.geocaching.connector.ImageResult;
import cgeo.geocaching.connector.LogResult;
import cgeo.geocaching.connector.trackable.TrackableConnector;
import cgeo.geocaching.connector.trackable.TrackableLoggingManager;
import cgeo.geocaching.enumerations.LoadFlags;
import cgeo.geocaching.enumerations.StatusCode;
import cgeo.geocaching.gcvote.GCVote;
import cgeo.geocaching.gcvote.GCVoteRatingBarUtil;
import cgeo.geocaching.gcvote.GCVoteRatingBarUtil.OnRatingChangeListener;
import cgeo.geocaching.log.LogTemplateProvider.LogContext;
import cgeo.geocaching.models.Geocache;
import cgeo.geocaching.models.Image;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.storage.DataStore;
import cgeo.geocaching.twitter.Twitter;
import cgeo.geocaching.ui.AbstractViewHolder;
import cgeo.geocaching.ui.dialog.DateDialog;
import cgeo.geocaching.ui.dialog.Dialogs;
import cgeo.geocaching.utils.AndroidRxUtils;
import cgeo.geocaching.utils.AsyncTaskWithProgressText;
import cgeo.geocaching.utils.CalendarUtils;
import cgeo.geocaching.utils.Formatter;
import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.ViewUtils;
import io.reactivex.Observable;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
public class LogCacheActivity extends AbstractLoggingActivity implements DateDialog.DateDialogParent {
private static final String SAVED_STATE_RATING = "cgeo.geocaching.saved_state_rating";
private static final String SAVED_STATE_TYPE = "cgeo.geocaching.saved_state_type";
private static final String SAVED_STATE_DATE = "cgeo.geocaching.saved_state_date";
private static final String SAVED_STATE_IMAGE = "cgeo.geocaching.saved_state_image";
private static final String SAVED_STATE_FAVPOINTS = "cgeo.geocaching.saved_state_favpoints";
private static final int SELECT_IMAGE = 101;
private Geocache cache = null;
private String geocode = null;
private String text = null;
private List<LogType> possibleLogTypes = new ArrayList<>();
private final Set<TrackableLog> trackables = new HashSet<>();
@BindView(R.id.tweet)
protected CheckBox tweetCheck;
@BindView(R.id.log_password_box)
protected LinearLayout logPasswordBox;
@BindView(R.id.favorite_check)
protected CheckBox favCheck;
@BindView(R.id.log) protected EditText logEditText;
private ILoggingManager loggingManager;
// Data to be saved while reconfiguring
private float rating;
private LogType typeSelected;
private Calendar date;
private Image image;
private boolean sendButtonEnabled;
private int premFavPoints;
/**
* Hook called at the beginning of onCreateLoader().
*/
public void onLoadStarted() {
showProgress(true);
}
/**
* Hook called at the beginning of onLoadFinished().
*/
public void onLoadFinished() {
if (loggingManager.hasLoaderError()) {
showErrorLoadingData();
return;
}
trackables.addAll(loggingManager.getTrackables());
possibleLogTypes = loggingManager.getPossibleLogTypes();
premFavPoints = loggingManager.getPremFavoritePoints();
if (possibleLogTypes.isEmpty()) {
showErrorLoadingData();
return;
}
verifySelectedLogType();
initializeRatingBar();
enablePostButton(true);
initializeTrackablesAction();
updateTrackablesList();
initializeFavoriteCheck();
showProgress(false);
}
/**
* Checks that the currently selected log type is still available as a possible log type. If it is not available,
* the selected log type will be set to the first possible type.
*/
private void verifySelectedLogType() {
if (!possibleLogTypes.contains(typeSelected)) {
typeSelected = possibleLogTypes.get(0);
setType(typeSelected);
showToast(res.getString(R.string.info_log_type_changed));
}
}
private void showErrorLoadingData() {
showToast(res.getString(R.string.err_log_load_data));
showProgress(false);
}
private void initializeTrackablesAction() {
if (Settings.isTrackableAutoVisit()) {
for (final TrackableLog trackable : trackables) {
trackable.action = LogTypeTrackable.VISITED;
}
}
}
private final class TrackableLogAdapter extends ArrayAdapter<TrackableLog> {
private TrackableLogAdapter(final Context context, final int resource, final TrackableLog[] objects) {
super(context, resource, objects);
}
@Override
public View getView(final int position, final View convertView, final ViewGroup parent) {
View rowView = convertView;
if (rowView == null) {
rowView = getLayoutInflater().inflate(R.layout.logcache_trackable_item, parent, false);
}
ViewHolder holder = (ViewHolder) rowView.getTag();
if (holder == null) {
holder = new ViewHolder(rowView);
}
final TrackableLog trackable = getItem(position);
fillViewHolder(holder, trackable);
return rowView;
}
private void fillViewHolder(final ViewHolder holder, final TrackableLog trackable) {
holder.brandView.setImageResource(trackable.brand.getIconResource());
holder.codeView.setText(trackable.trackCode);
holder.nameView.setText(trackable.name);
holder.actionButton.setText(trackable.action.getLabel() + " ▼");
holder.actionButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View view) {
selectTrackableAction(trackable);
}
});
holder.infoView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View view) {
final Intent trackablesIntent = new Intent(LogCacheActivity.this, TrackableActivity.class);
final String tbCode = StringUtils.isNotEmpty(trackable.geocode) ? trackable.geocode : trackable.trackCode;
trackablesIntent.putExtra(Intents.EXTRA_GEOCODE, tbCode);
trackablesIntent.putExtra(Intents.EXTRA_BRAND, trackable.brand.getId());
trackablesIntent.putExtra(Intents.EXTRA_TRACKING_CODE, trackable.trackCode);
startActivity(trackablesIntent);
}
});
}
}
protected static class ViewHolder extends AbstractViewHolder {
@BindView(R.id.trackable_image_brand) protected ImageView brandView;
@BindView(R.id.trackcode) protected TextView codeView;
@BindView(R.id.name) protected TextView nameView;
@BindView(R.id.action) protected TextView actionButton;
@BindView(R.id.info) protected View infoView;
public ViewHolder(final View rowView) {
super(rowView);
}
}
private void updateTrackablesList() {
final TrackableLog[] trackablesArray = getSortedTrackables().toArray(new TrackableLog[trackables.size()]);
final ListView inventoryList = ButterKnife.findById(this, R.id.inventory);
inventoryList.setAdapter(new TrackableLogAdapter(this, R.layout.logcache_trackable_item, trackablesArray));
ViewUtils.setListViewHeightBasedOnItems(inventoryList);
ButterKnife.findById(this, R.id.inventory_box).setVisibility(trackables.isEmpty() ? View.GONE : View.VISIBLE);
final LinearLayout inventoryChangeAllView = ButterKnife.findById(this, R.id.inventory_changeall);
inventoryChangeAllView.setVisibility(trackables.size() > 1 ? View.VISIBLE : View.GONE);
final Button changeButton = ButterKnife.findById(inventoryChangeAllView, R.id.changebutton);
changeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View view) {
selectAllTrackablesAction();
}
});
}
private ArrayList<TrackableLog> getSortedTrackables() {
final TrackableComparator comparator = Settings.getTrackableComparator();
final ArrayList<TrackableLog> sortedTrackables = new ArrayList<>(trackables);
Collections.sort(sortedTrackables, comparator.getComparator());
return sortedTrackables;
}
private void enablePostButton(final boolean enabled) {
sendButtonEnabled = enabled;
}
@Override
public void onCreate(final Bundle savedInstanceState) {
onCreate(savedInstanceState, R.layout.logcache_activity);
// Get parameters from intent and basic cache information from database
final Bundle extras = getIntent().getExtras();
if (extras != null) {
geocode = extras.getString(Intents.EXTRA_GEOCODE);
if (StringUtils.isBlank(geocode)) {
final String cacheid = extras.getString(Intents.EXTRA_ID);
if (StringUtils.isNotBlank(cacheid)) {
geocode = DataStore.getGeocodeForGuid(cacheid);
}
}
}
cache = DataStore.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB);
invalidateOptionsMenuCompatible();
possibleLogTypes = cache.getPossibleLogTypes();
setCacheTitleBar(cache);
initializeRatingBar();
// initialize with default values
setDefaultValues();
// Restore previous state
if (savedInstanceState != null) {
rating = savedInstanceState.getFloat(SAVED_STATE_RATING);
typeSelected = LogType.getById(savedInstanceState.getInt(SAVED_STATE_TYPE));
date.setTimeInMillis(savedInstanceState.getLong(SAVED_STATE_DATE));
image = savedInstanceState.getParcelable(SAVED_STATE_IMAGE);
premFavPoints = savedInstanceState.getInt(SAVED_STATE_FAVPOINTS);
} else {
// If log had been previously saved, load it now, otherwise initialize signature as needed
loadLogFromDatabase();
}
if (image == null) {
image = Image.NONE;
}
enablePostButton(false);
verifySelectedLogType();
final Button typeButton = ButterKnife.findById(this, R.id.type);
typeButton.setText(typeSelected.getL10n());
typeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View view) {
selectLogType();
}
});
final Button dateButton = ButterKnife.findById(this, R.id.date);
setDate(date);
dateButton.setOnClickListener(new DateListener());
if (StringUtils.isBlank(currentLogText()) && StringUtils.isNotBlank(text)) {
setLogText();
}
tweetCheck.setChecked(true);
updateTweetBox(typeSelected);
updateLogPasswordBox(typeSelected);
loggingManager = cache.getLoggingManager(this);
loggingManager.init();
// Load Generic Trackables
AndroidRxUtils.bindActivity(this,
// Obtain the actives connectors
Observable.fromIterable(ConnectorFactory.getLoggableGenericTrackablesConnectors())
.flatMap(new Function<TrackableConnector, Observable<TrackableLog>>() {
@Override
public Observable<TrackableLog> apply(final TrackableConnector trackableConnector) {
return Observable.defer(new Callable<Observable<TrackableLog>>() {
@Override
public Observable<TrackableLog> call() {
return trackableConnector.trackableLogInventory();
}
}).subscribeOn(AndroidRxUtils.networkScheduler);
}
}).toList()
).subscribe(new Consumer<List<TrackableLog>>() {
@Override
public void accept(final List<TrackableLog> trackableLogs) {
// Store trackables
trackables.addAll(trackableLogs);
// Update the UI
initializeTrackablesAction();
updateTrackablesList();
}
});
requestKeyboardForLogging();
}
private void setLogText() {
logEditText.setText(text);
Dialogs.moveCursorToEnd(logEditText);
}
private void loadLogFromDatabase() {
final LogEntry log = DataStore.loadLogOffline(geocode);
if (log != null) {
typeSelected = log.getType();
date.setTime(new Date(log.date));
text = log.log;
} else if (StringUtils.isNotBlank(Settings.getSignature()) && Settings.isAutoInsertSignature() && StringUtils.isBlank(currentLogText())) {
insertIntoLog(LogTemplateProvider.applyTemplates(Settings.getSignature(), new LogContext(cache, null)), false);
}
}
private void initializeRatingBar() {
if (GCVote.isVotingPossible(cache)) {
GCVoteRatingBarUtil.initializeRatingBar(cache, getWindow().getDecorView().getRootView(), new OnRatingChangeListener() {
@Override
public void onRatingChanged(final float stars) {
rating = stars;
}
});
}
}
private void initializeFavoriteCheck() {
if (ConnectorFactory.getConnector(cache).supportsAddToFavorite(cache, typeSelected)) {
if (premFavPoints > 0) {
favCheck.setVisibility(View.VISIBLE);
favCheck.setText(getString(R.string.fav_points_remaining, premFavPoints));
}
} else {
favCheck.setVisibility(View.GONE);
}
}
private void setDefaultValues() {
date = Calendar.getInstance();
rating = GCVote.NO_RATING;
typeSelected = cache.getDefaultLogType();
// it this is an attended event log, use the event date by default instead of the current date
if (cache.isEventCache() && CalendarUtils.isPastEvent(cache) && typeSelected == LogType.ATTENDED) {
date.setTime(cache.getHiddenDate());
}
text = null;
image = Image.NONE;
}
private void clearLog() {
new ClearLogCommand(this).execute();
}
@Override
public void finish() {
saveLog(false);
super.finish();
}
@Override
public void onStop() {
saveLog(false);
super.onStop();
}
@Override
protected void onSaveInstanceState(final Bundle outState) {
super.onSaveInstanceState(outState);
outState.putDouble(SAVED_STATE_RATING, rating);
outState.putInt(SAVED_STATE_TYPE, typeSelected.id);
outState.putLong(SAVED_STATE_DATE, date.getTimeInMillis());
outState.putParcelable(SAVED_STATE_IMAGE, image);
outState.putInt(SAVED_STATE_FAVPOINTS, premFavPoints);
}
@Override
public void setDate(final Calendar dateIn) {
date = dateIn;
final Button dateButton = ButterKnife.findById(this, R.id.date);
dateButton.setText(Formatter.formatShortDateVerbally(date.getTime().getTime()));
}
public void setType(final LogType type) {
final Button typeButton = ButterKnife.findById(this, R.id.type);
typeSelected = type;
typeButton.setText(typeSelected.getL10n());
updateTweetBox(type);
updateLogPasswordBox(type);
initializeFavoriteCheck();
}
private void updateTweetBox(final LogType type) {
if (type == LogType.FOUND_IT && Settings.isUseTwitter() && Settings.isTwitterLoginValid()) {
tweetCheck.setVisibility(View.VISIBLE);
} else {
tweetCheck.setVisibility(View.GONE);
}
}
private void updateLogPasswordBox(final LogType type) {
if (type == LogType.FOUND_IT && cache.isLogPasswordRequired()) {
logPasswordBox.setVisibility(View.VISIBLE);
} else {
logPasswordBox.setVisibility(View.GONE);
}
}
private final class ClearLogCommand extends AbstractCommand {
private String oldText;
private LogType oldType;
private Calendar oldDate;
ClearLogCommand(final Activity context) {
super(context);
}
@Override
protected void doCommand() {
oldText = currentLogText();
oldType = typeSelected;
oldDate = date;
cache.clearOfflineLog();
}
@Override
protected void undoCommand() {
cache.logOffline(getContext(), oldText, oldDate, oldType);
}
@Override
protected String getResultMessage() {
return getContext().getString(R.string.info_log_cleared);
}
@Override
protected void onFinished() {
setDefaultValues();
setType(typeSelected);
setDate(date);
logEditText.setText(StringUtils.EMPTY);
final EditText logPasswordView = ButterKnife.findById(LogCacheActivity.this, R.id.log_password);
logPasswordView.setText(StringUtils.EMPTY);
}
@Override
protected void onFinishedUndo() {
text = oldText;
typeSelected = oldType;
date = oldDate;
setType(typeSelected);
setDate(date);
setLogText();
}
}
private class DateListener implements View.OnClickListener {
@Override
public void onClick(final View arg0) {
final DateDialog dateDialog = DateDialog.getInstance(date);
dateDialog.setCancelable(true);
dateDialog.show(getSupportFragmentManager(), "date_dialog");
}
}
private class Poster extends AsyncTaskWithProgressText<String, StatusCode> {
Poster(final Activity activity, final String progressMessage) {
super(activity, res.getString(image.isEmpty() ?
R.string.log_posting_log :
R.string.log_saving_and_uploading), progressMessage);
}
@Override
protected StatusCode doInBackgroundInternal(final String[] logTexts) {
final String log = logTexts[0];
final String logPwd = logTexts.length > 1 ? logTexts[1] : null;
try {
final LogResult logResult = loggingManager.postLog(typeSelected, date, log, logPwd, new ArrayList<>(trackables));
ImageResult imageResult = null;
if (logResult.getPostLogResult() == StatusCode.NO_ERROR) {
// update geocache in DB
if (typeSelected.isFoundLog()) {
cache.setFound(true);
cache.setVisitedDate(date.getTimeInMillis());
}
DataStore.saveChangedCache(cache);
final LogEntry.Builder logBuilder = new LogEntry.Builder()
.setDate(date.getTimeInMillis())
.setLogType(typeSelected)
.setLog(log)
.setFriend(true);
// Posting image
if (!image.isEmpty()) {
publishProgress(res.getString(R.string.log_posting_image));
imageResult = loggingManager.postLogImage(logResult.getLogId(), image);
final String uploadedImageUrl = imageResult.getImageUri();
if (StringUtils.isNotEmpty(uploadedImageUrl)) {
logBuilder.addLogImage(image.buildUpon()
.setUrl(uploadedImageUrl)
.build());
}
}
// update logs in DB
final List<LogEntry> newLogs = new ArrayList<>(cache.getLogs());
final LogEntry logNow = logBuilder.build();
newLogs.add(0, logNow);
DataStore.saveLogs(cache.getGeocode(), newLogs);
// update offline log in DB
cache.clearOfflineLog();
if (typeSelected == LogType.FOUND_IT && tweetCheck.isChecked() && tweetCheck.getVisibility() == View.VISIBLE) {
publishProgress(res.getString(R.string.log_posting_twitter));
Twitter.postTweetCache(geocode, logNow);
}
if (GCVote.isValidRating(rating) && GCVote.isVotingPossible(cache)) {
publishProgress(res.getString(R.string.log_posting_gcvote));
if (GCVote.setRating(cache, rating)) {
cache.setMyVote(rating);
DataStore.saveChangedCache(cache);
} else {
showToast(res.getString(R.string.err_gcvote_send_rating));
}
}
// Posting Generic Trackables
for (final TrackableConnector connector: ConnectorFactory.getLoggableGenericTrackablesConnectors()) {
final TrackableLoggingManager manager = connector.getTrackableLoggingManager((AbstractLoggingActivity) activity);
if (manager != null) {
// Filter trackables logs by action and brand
final Set<TrackableLog> trackablesMoved = new HashSet<>();
for (final TrackableLog trackableLog : trackables) {
if (trackableLog.action != LogTypeTrackable.DO_NOTHING && trackableLog.brand == connector.getBrand()) {
trackablesMoved.add(trackableLog);
}
}
// Posting trackables logs
int trackableLogcounter = 1;
for (final TrackableLog trackableLog : trackablesMoved) {
publishProgress(res.getString(R.string.log_posting_generic_trackable, trackableLog.brand.getLabel(), trackableLogcounter, trackablesMoved.size()));
manager.postLog(cache, trackableLog, date, log);
trackableLogcounter++;
}
}
}
}
// Todo error handling should be better than that
if (imageResult != null && imageResult.getPostResult() != StatusCode.NO_ERROR && imageResult.getPostResult() != StatusCode.LOG_SAVED) {
return imageResult.getPostResult();
}
return logResult.getPostLogResult();
} catch (final RuntimeException e) {
Log.e("LogCacheActivity.Poster.doInBackgroundInternal", e);
}
return StatusCode.LOG_POST_ERROR;
}
@Override
protected void onPostExecuteInternal(final StatusCode status) {
if (status == StatusCode.NO_ERROR) {
showToast(res.getString(R.string.info_log_posted));
// No need to save the log when quitting if it has been posted.
text = currentLogText();
finish();
} else if (status == StatusCode.LOG_SAVED) {
showToast(res.getString(R.string.info_log_saved));
finish();
} else {
Dialogs.confirmPositiveNegativeNeutral(activity, R.string.info_log_post_failed,
res.getString(R.string.info_log_post_failed_reason, status.getErrorString(res)),
R.string.info_log_post_retry, // Positive Button
string.cancel, // Negative Button
R.string.info_log_post_save, // Neutral Button
// Positive button: Retry
new OnClickListener() {
@Override
public void onClick(final DialogInterface dialog, final int which) {
sendLogInternal();
}
},
// Negative button: dismiss popup
null,
// Neutral Button: SaveLog
new OnClickListener() {
@Override
public void onClick(final DialogInterface dialogInterface, final int i) {
saveLog(true);
finish();
}
});
}
}
}
private void saveLog(final boolean force) {
final String log = currentLogText();
// Do not erase the saved log if the user has removed all the characters
// without using "Clear". This may be a manipulation mistake, and erasing
// again will be easy using "Clear" while retyping the text may not be.
if (force || (StringUtils.isNotEmpty(log) && !StringUtils.equals(log, text) && !StringUtils.equals(log, Settings.getSignature()))) {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(final Void... params) {
cache.logOffline(LogCacheActivity.this, log, date, typeSelected);
Settings.setLastCacheLog(log);
return null;
}
}.execute();
}
text = log;
}
private String currentLogText() {
return logEditText.getText().toString();
}
private String currentLogPassword() {
return ButterKnife.<EditText>findById(this, R.id.log_password).getText().toString();
}
@Override
protected LogContext getLogContext() {
return new LogContext(cache, null);
}
private void selectAllTrackablesAction() {
final Builder alert = new AlertDialog.Builder(this);
alert.setTitle(res.getString(R.string.log_tb_changeall) + " (" + trackables.size() + ')');
final List<LogTypeTrackable> tbLogTypeValues = LogTypeTrackable.getLogTypeTrackableForLogCache();
final String[] tbLogTypes = getTBLogTypes(tbLogTypeValues);
alert.setItems(tbLogTypes, new OnClickListener() {
@Override
public void onClick(final DialogInterface dialog, final int position) {
final LogTypeTrackable logType = tbLogTypeValues.get(position);
for (final TrackableLog tb : trackables) {
tb.action = logType;
Log.d("Trackable " + tb.trackCode + " (" + tb.name + ") has new action: #" + logType);
}
updateTrackablesList();
dialog.dismiss();
}
});
alert.create().show();
}
private static String[] getTBLogTypes(final List<LogTypeTrackable> tbLogTypeValues) {
final String[] tbLogTypes = new String[tbLogTypeValues.size()];
for (int i = 0; i < tbLogTypes.length; i++) {
tbLogTypes[i] = tbLogTypeValues.get(i).getLabel();
}
return tbLogTypes;
}
private void selectLogType() {
// use a local copy of the possible types, as that one might be modified in the background by the loader
final List<LogType> possible = new ArrayList<>(possibleLogTypes);
final Builder alert = new AlertDialog.Builder(this);
final String[] choices = new String[possible.size()];
for (int i = 0; i < choices.length; i++) {
choices[i] = possible.get(i).getL10n();
}
alert.setSingleChoiceItems(choices, possible.indexOf(typeSelected), new OnClickListener() {
@Override
public void onClick(final DialogInterface dialog, final int position) {
setType(possible.get(position));
dialog.dismiss();
}
});
alert.create().show();
}
private void selectTrackableAction(final TrackableLog trackable) {
final Builder alert = new AlertDialog.Builder(this);
alert.setTitle(trackable.name);
final List<LogTypeTrackable> tbLogTypeValues = LogTypeTrackable.getLogTypeTrackableForLogCache();
final String[] tbLogTypes = getTBLogTypes(tbLogTypeValues);
alert.setSingleChoiceItems(tbLogTypes, tbLogTypeValues.indexOf(trackable.action), new OnClickListener() {
@Override
public void onClick(final DialogInterface dialog, final int position) {
final LogTypeTrackable logType = tbLogTypeValues.get(position);
trackable.action = logType;
Log.d("Trackable " + trackable.trackCode + " (" + trackable.name + ") has new action: #" + logType);
updateTrackablesList();
dialog.dismiss();
}
});
alert.create().show();
}
private void selectImage() {
final Intent selectImageIntent = new Intent(this, ImageSelectActivity.class);
selectImageIntent.putExtra(Intents.EXTRA_IMAGE, image);
selectImageIntent.putExtra(Intents.EXTRA_GEOCODE, cache.getGeocode());
startActivityForResult(selectImageIntent, SELECT_IMAGE);
}
@Override
protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
if (requestCode == SELECT_IMAGE) {
if (resultCode == RESULT_OK) {
image = data.getParcelableExtra(Intents.EXTRA_IMAGE);
} else if (resultCode != RESULT_CANCELED) {
// Image capture failed, advise user
showToast(getString(R.string.err_select_logimage_failed));
}
}
}
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_send:
sendLogAndConfirm();
return true;
case R.id.menu_image:
selectImage();
return true;
case R.id.save:
saveLog(true);
finish();
return true;
case R.id.clear:
clearLog();
return true;
case R.id.menu_sort_trackables_name:
// item.setChecked(true);
sortTrackables(TrackableComparator.TRACKABLE_COMPARATOR_NAME);
return true;
case R.id.menu_sort_trackables_code:
// item.setChecked(true);
sortTrackables(TrackableComparator.TRACKABLE_COMPARATOR_TRACKCODE);
return true;
default:
break;
}
return super.onOptionsItemSelected(item);
}
private void sendLogAndConfirm() {
if (!sendButtonEnabled) {
Dialogs.message(this, R.string.log_post_not_possible);
return;
}
if (CalendarUtils.isFuture(date)) {
Dialogs.message(this, R.string.log_date_future_not_allowed);
return;
}
if (typeSelected.mustConfirmLog()) {
Dialogs.confirm(this, R.string.confirm_log_title, res.getString(R.string.confirm_log_message, typeSelected.getL10n()), new OnClickListener() {
@Override
public void onClick(final DialogInterface dialog, final int which) {
sendLogInternal();
}
});
} else {
sendLogInternal();
}
}
private void sendLogInternal() {
new Poster(this, res.getString(R.string.log_saving)).execute(currentLogText(), currentLogPassword());
Settings.setLastCacheLog(currentLogText());
}
@Override
public boolean onCreateOptionsMenu(final Menu menu) {
super.onCreateOptionsMenu(menu);
menu.findItem(R.id.menu_image).setVisible(cache.supportsLogImages());
menu.findItem(R.id.save).setVisible(true);
menu.findItem(R.id.clear).setVisible(true);
menu.findItem(R.id.menu_sort_trackables_by).setVisible(true);
switch (Settings.getTrackableComparator()) {
case TRACKABLE_COMPARATOR_NAME:
menu.findItem(R.id.menu_sort_trackables_name).setChecked(true);
break;
case TRACKABLE_COMPARATOR_TRACKCODE:
menu.findItem(R.id.menu_sort_trackables_code).setChecked(true);
break;
default:
menu.findItem(R.id.menu_sort_trackables_name).setChecked(true);
}
return true;
}
public static Intent getLogCacheIntent(final Activity context, final String cacheId, final String geocode) {
final Intent logVisitIntent = new Intent(context, LogCacheActivity.class);
logVisitIntent.putExtra(Intents.EXTRA_ID, cacheId);
logVisitIntent.putExtra(Intents.EXTRA_GEOCODE, geocode);
return logVisitIntent;
}
@Override
protected String getLastLog() {
return Settings.getLastCacheLog();
}
private void sortTrackables(final TrackableComparator comparator) {
Settings.setTrackableComparator(comparator);
updateTrackablesList();
invalidateOptionsMenuCompatible();
}
}