blob: cdcde6efc3124c5157b1ac86d1a91401358eea5e [file] [log] [blame]
package org.wordpress.android.ui.posts;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Fragment;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.location.Address;
import android.location.Location;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v7.widget.AppCompatButton;
import android.text.Editable;
import android.text.Html;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.text.format.DateFormat;
import android.text.format.DateUtils;
import android.view.ContextMenu;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewStub;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.inputmethod.EditorInfo;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.TimePicker;
import android.widget.Toast;
import com.android.volley.toolbox.NetworkImageView;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import org.apache.commons.lang.StringEscapeUtils;
import org.json.JSONArray;
import org.wordpress.android.R;
import org.wordpress.android.WordPress;
import org.wordpress.android.models.Post;
import org.wordpress.android.models.PostLocation;
import org.wordpress.android.models.PostStatus;
import org.wordpress.android.ui.RequestCodes;
import org.wordpress.android.ui.media.MediaGalleryPickerActivity;
import org.wordpress.android.ui.media.WordPressMediaUtils;
import org.wordpress.android.ui.prefs.AppPrefs;
import org.wordpress.android.ui.prefs.SiteSettingsInterface;
import org.wordpress.android.ui.suggestion.adapters.TagSuggestionAdapter;
import org.wordpress.android.ui.suggestion.util.SuggestionServiceConnectionManager;
import org.wordpress.android.ui.suggestion.util.SuggestionUtils;
import org.wordpress.android.util.AppLog;
import org.wordpress.android.util.AppLog.T;
import org.wordpress.android.util.DisplayUtils;
import org.wordpress.android.util.EditTextUtils;
import org.wordpress.android.util.GeocoderUtils;
import org.wordpress.android.util.JSONUtils;
import org.wordpress.android.util.PermissionUtils;
import org.wordpress.android.util.StringUtils;
import org.wordpress.android.util.ToastUtils;
import org.wordpress.android.util.helpers.LocationHelper;
import org.wordpress.android.widgets.SuggestionAutoCompleteText;
import org.xmlrpc.android.ApiHelper;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
public class EditPostSettingsFragment extends Fragment
implements View.OnClickListener, TextView.OnEditorActionListener {
private static final int ACTIVITY_REQUEST_CODE_SELECT_CATEGORIES = 5;
private static final String CATEGORY_PREFIX_TAG = "category-";
private static final int SELECT_LIBRARY_MENU_POSITION = 100;
private static final int CLEAR_FEATURED_IMAGE_MENU_POSITION = 101;
private Post mPost;
private Spinner mStatusSpinner, mPostFormatSpinner;
private EditText mPasswordEditText, mExcerptEditText;
private TextView mPubDateText;
private ViewGroup mSectionCategories;
private ViewGroup mRootView;
private TextView mFeaturedImageLabel;
private NetworkImageView mFeaturedImageView;
private Button mFeaturedImageButton;
private SuggestionAutoCompleteText mTagsEditText;
private SuggestionServiceConnectionManager mSuggestionServiceConnectionManager;
private long mFeaturedImageId;
private ArrayList<String> mCategories;
private PostLocation mPostLocation;
private LocationHelper mLocationHelper;
private int mYear, mMonth, mDay, mHour, mMinute;
private long mCustomPubDate = 0;
private boolean mIsCustomPubDate;
private String[] mPostFormats;
private String[] mPostFormatTitles;
private enum LocationStatus {NONE, FOUND, NOT_FOUND, SEARCHING}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getActivity() != null) {
PreferenceManager.setDefaultValues(getActivity(), R.xml.account_settings, false);
}
}
@Override
public void onDestroy() {
if (mSuggestionServiceConnectionManager != null) {
mSuggestionServiceConnectionManager.unbindFromService();
}
super.onDestroy();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mPost = ((EditPostActivity) getActivity()).getPost();
mRootView = (ViewGroup) inflater.inflate(R.layout.edit_post_settings_fragment, container, false);
if (mRootView == null || mPost == null) {
return null;
}
Calendar c = Calendar.getInstance();
mYear = c.get(Calendar.YEAR);
mMonth = c.get(Calendar.MONTH);
mDay = c.get(Calendar.DAY_OF_MONTH);
mHour = c.get(Calendar.HOUR_OF_DAY);
mMinute = c.get(Calendar.MINUTE);
mCategories = new ArrayList<String>();
mExcerptEditText = (EditText) mRootView.findViewById(R.id.postExcerpt);
mPasswordEditText = (EditText) mRootView.findViewById(R.id.post_password);
mPubDateText = (TextView) mRootView.findViewById(R.id.pubDate);
mPubDateText.setOnClickListener(this);
mStatusSpinner = (Spinner) mRootView.findViewById(R.id.status);
mStatusSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
updatePostSettingsAndSaveButton();
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
mSectionCategories = ((ViewGroup) mRootView.findViewById(R.id.sectionCategories));
mFeaturedImageLabel = (TextView) mRootView.findViewById(R.id.featuredImageLabel);
mFeaturedImageView = (NetworkImageView) mRootView.findViewById(R.id.featuredImage);
mFeaturedImageButton = (Button) mRootView.findViewById(R.id.addFeaturedImage);
if (AppPrefs.isVisualEditorEnabled()) {
registerForContextMenu(mFeaturedImageView);
mFeaturedImageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
view.showContextMenu();
}
});
mFeaturedImageButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
launchMediaGalleryActivity();
}
});
} else {
mFeaturedImageLabel.setVisibility(View.GONE);
mFeaturedImageView.setVisibility(View.GONE);
mFeaturedImageButton.setVisibility(View.GONE);
}
if (mPost.isPage()) { // remove post specific views
mExcerptEditText.setVisibility(View.GONE);
mRootView.findViewById(R.id.sectionTags).setVisibility(View.GONE);
mRootView.findViewById(R.id.sectionCategories).setVisibility(View.GONE);
mRootView.findViewById(R.id.postFormatLabel).setVisibility(View.GONE);
mRootView.findViewById(R.id.postFormat).setVisibility(View.GONE);
} else {
mPostFormatTitles = getResources().getStringArray(R.array.post_formats_array);
mPostFormats =
new String[]{"aside", "audio", "chat", "gallery", "image", "link", "quote", "standard", "status",
"video"};
if (WordPress.getCurrentBlog().getPostFormats().equals("")) {
new ApiHelper.GetPostFormatsTask().execute(WordPress.getCurrentBlog());
} else {
try {
Gson gson = new Gson();
Type type = new TypeToken<Map<String, String>>() {}.getType();
Map<String, String> jsonPostFormats = gson.fromJson(WordPress.getCurrentBlog().getPostFormats(),
type);
mPostFormats = new String[jsonPostFormats.size()];
mPostFormatTitles = new String[jsonPostFormats.size()];
int i = 0;
for (Map.Entry<String, String> entry : jsonPostFormats.entrySet()) {
String key = entry.getKey();
String val = entry.getValue();
mPostFormats[i] = key;
mPostFormatTitles[i] = StringEscapeUtils.unescapeHtml(val);
i++;
}
} catch (RuntimeException e) {
AppLog.e(T.POSTS, e);
}
}
mPostFormatSpinner = (Spinner) mRootView.findViewById(R.id.postFormat);
ArrayAdapter<String> pfAdapter = new ArrayAdapter<>(getActivity(), R.layout.simple_spinner_item,
mPostFormatTitles);
pfAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mPostFormatSpinner.setAdapter(pfAdapter);
String activePostFormat = "standard";
if (!TextUtils.isEmpty(mPost.getPostFormat())) {
activePostFormat = mPost.getPostFormat();
}
for (int i = 0; i < mPostFormats.length; i++) {
if (mPostFormats[i].equals(activePostFormat))
mPostFormatSpinner.setSelection(i);
}
mPostFormatSpinner.setOnTouchListener(
new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
return false;
}
}
);
mTagsEditText = (SuggestionAutoCompleteText) mRootView.findViewById(R.id.tags);
if (mTagsEditText != null) {
mTagsEditText.setTokenizer(new SuggestionAutoCompleteText.CommaTokenizer());
setupSuggestionServiceAndAdapter();
}
}
initSettingsFields();
populateSelectedCategories();
initLocation(mRootView);
return mRootView;
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
menu.add(0, SELECT_LIBRARY_MENU_POSITION, 0, getResources().getText(R.string.select_from_media_library));
menu.add(0, CLEAR_FEATURED_IMAGE_MENU_POSITION, 0, "Remove featured image");
}
@Override
public boolean onContextItemSelected(MenuItem item) {
switch (item.getItemId()) {
case SELECT_LIBRARY_MENU_POSITION:
launchMediaGalleryActivity();
return true;
case CLEAR_FEATURED_IMAGE_MENU_POSITION:
mFeaturedImageId = -1;
mFeaturedImageView.setVisibility(View.GONE);
mFeaturedImageButton.setVisibility(View.VISIBLE);
return true;
default:
return false;
}
}
private void setupSuggestionServiceAndAdapter() {
if (!isAdded()) return;
int remoteBlogId = -1;
String blogID = WordPress.getCurrentRemoteBlogId();
remoteBlogId = StringUtils.stringToInt(blogID, -1);
mSuggestionServiceConnectionManager = new SuggestionServiceConnectionManager(getActivity(), remoteBlogId);
TagSuggestionAdapter tagSuggestionAdapter = SuggestionUtils.setupTagSuggestions(remoteBlogId, getActivity(), mSuggestionServiceConnectionManager);
if (tagSuggestionAdapter != null) {
mTagsEditText.setAdapter(tagSuggestionAdapter);
}
}
private void initSettingsFields() {
mExcerptEditText.setText(mPost.getPostExcerpt());
String[] items = new String[]{ getResources().getString(R.string.publish_post),
getResources().getString(R.string.draft),
getResources().getString(R.string.pending_review),
getResources().getString(R.string.post_private) };
ArrayAdapter<String> adapter = new ArrayAdapter<>(getActivity(), android.R.layout.simple_spinner_item, items);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mStatusSpinner.setAdapter(adapter);
mStatusSpinner.setOnTouchListener(
new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
return false;
}
}
);
long pubDate = mPost.getDate_created_gmt();
if (pubDate != 0) {
try {
int flags = 0;
flags |= android.text.format.DateUtils.FORMAT_SHOW_DATE;
flags |= android.text.format.DateUtils.FORMAT_ABBREV_MONTH;
flags |= android.text.format.DateUtils.FORMAT_SHOW_YEAR;
flags |= android.text.format.DateUtils.FORMAT_SHOW_TIME;
String formattedDate = DateUtils.formatDateTime(getActivity(), pubDate,
flags);
mPubDateText.setText(formattedDate);
} catch (RuntimeException e) {
AppLog.e(T.POSTS, e);
}
}
if (!TextUtils.isEmpty(mPost.getPassword())) {
mPasswordEditText.setText(mPost.getPassword());
}
switch (mPost.getStatusEnum()) {
case PUBLISHED:
case SCHEDULED:
case UNKNOWN:
mStatusSpinner.setSelection(0, true);
break;
case DRAFT:
mStatusSpinner.setSelection(1, true);
break;
case PENDING:
mStatusSpinner.setSelection(2, true);
break;
case PRIVATE:
mStatusSpinner.setSelection(3, true);
break;
}
if (!mPost.isPage()) {
if (mPost.getJSONCategories() != null) {
mCategories = JSONUtils.fromJSONArrayToStringList(mPost.getJSONCategories());
}
}
String tags = mPost.getKeywords();
if (!tags.equals("")) {
mTagsEditText.setText(tags);
}
if (AppPrefs.isVisualEditorEnabled()) {
updateFeaturedImage(mPost.getFeaturedImageId());
}
}
public long getFeaturedImageId() {
return mFeaturedImageId;
}
public void updateFeaturedImage(long id) {
if (mFeaturedImageId != id) {
mFeaturedImageId = id;
if (mFeaturedImageId > 0) {
int blogId = WordPress.getCurrentBlog().getLocalTableBlogId();
Cursor cursor = WordPress.wpDB.getMediaFile(String.valueOf(blogId), String.valueOf(mFeaturedImageId));
if (cursor != null && cursor.moveToFirst()) {
mFeaturedImageView.setVisibility(View.VISIBLE);
mFeaturedImageButton.setVisibility(View.GONE);
// Get max width for photon thumbnail
int maxWidth = getResources().getDisplayMetrics().widthPixels;
int padding = DisplayUtils.dpToPx(getActivity(), 16);
int imageWidth = (maxWidth - padding);
String thumbUrl = WordPressMediaUtils.getNetworkThumbnailUrl(cursor, imageWidth);
WordPressMediaUtils.loadNetworkImage(thumbUrl, mFeaturedImageView);
}
if (cursor != null) {
cursor.close();
}
} else {
mFeaturedImageView.setVisibility(View.GONE);
mFeaturedImageButton.setVisibility(View.VISIBLE);
}
}
}
private void launchMediaGalleryActivity() {
Intent intent = new Intent(getActivity(), MediaGalleryPickerActivity.class);
intent.putExtra(MediaGalleryPickerActivity.PARAM_SELECT_ONE_ITEM, true);
startActivityForResult(intent, MediaGalleryPickerActivity.REQUEST_CODE);
}
private String getPostStatusForSpinnerPosition(int position) {
switch (position) {
case 0:
return PostStatus.toString(PostStatus.PUBLISHED);
case 1:
return PostStatus.toString(PostStatus.DRAFT);
case 2:
return PostStatus.toString(PostStatus.PENDING);
case 3:
return PostStatus.toString(PostStatus.PRIVATE);
default:
return PostStatus.toString(PostStatus.UNKNOWN);
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (data != null || ((requestCode == RequestCodes.TAKE_PHOTO ||
requestCode == RequestCodes.TAKE_VIDEO))) {
Bundle extras;
switch (requestCode) {
case ACTIVITY_REQUEST_CODE_SELECT_CATEGORIES:
extras = data.getExtras();
if (extras != null && extras.containsKey("selectedCategories")) {
mCategories = (ArrayList<String>) extras.getSerializable("selectedCategories");
populateSelectedCategories();
}
break;
case MediaGalleryPickerActivity.REQUEST_CODE:
if (resultCode == Activity.RESULT_OK) {
ArrayList<String> ids = data.getStringArrayListExtra(MediaGalleryPickerActivity.RESULT_IDS);
if (ids == null || ids.size() == 0) {
return;
}
updateFeaturedImage(Long.parseLong(ids.get(0)));
}
}
}
}
@Override
public void onClick(View v) {
int id = v.getId();
if (id == R.id.pubDate) {
showPostDateSelectionDialog();
} else if (id == R.id.selectCategories) {
Bundle bundle = new Bundle();
bundle.putInt("id", WordPress.getCurrentBlog().getLocalTableBlogId());
if (mCategories != null && mCategories.size() > 0) {
bundle.putSerializable("categories", new HashSet<String>(mCategories));
}
Intent categoriesIntent = new Intent(getActivity(), SelectCategoriesActivity.class);
categoriesIntent.putExtras(bundle);
startActivityForResult(categoriesIntent, ACTIVITY_REQUEST_CODE_SELECT_CATEGORIES);
} else if (id == R.id.categoryButton) {
onCategoryButtonClick(v);
} else if (id == R.id.locationText) {
viewLocation();
} else if (id == R.id.updateLocation) {
showLocationSearch();
} else if (id == R.id.removeLocation) {
removeLocation();
showLocationAdd();
} else if (id == R.id.addLocation) {
// Init Location settings when we switch to the fragment, that could trigger the opening of
// a dialog asking the user to enable the Geolocation permission (starting Android 6.+).
if (checkForLocationPermission()) {
showLocationSearch();
}
} else if (id == R.id.searchLocation) {
if (checkForLocationPermission()) {
searchLocation();
}
}
}
@Override
public boolean onEditorAction(TextView view, int actionId, KeyEvent event) {
boolean handled = false;
int id = view.getId();
if (id == R.id.searchLocationText && actionId == EditorInfo.IME_ACTION_SEARCH && checkForLocationPermission()) {
searchLocation();
handled = true;
}
return handled;
}
private void showPostDateSelectionDialog() {
final DatePicker datePicker = new DatePicker(getActivity());
datePicker.init(mYear, mMonth, mDay, null);
datePicker.setCalendarViewShown(false);
new AlertDialog.Builder(getActivity())
.setTitle(R.string.select_date)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
mYear = datePicker.getYear();
mMonth = datePicker.getMonth();
mDay = datePicker.getDayOfMonth();
showPostTimeSelectionDialog();
}
})
.setNeutralButton(getResources().getText(R.string.immediately),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface,
int i) {
mIsCustomPubDate = true;
mPubDateText.setText(R.string.immediately);
updatePostSettingsAndSaveButton();
}
})
.setNegativeButton(android.R.string.cancel,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
}
}
).setView(datePicker).show();
}
private void showPostTimeSelectionDialog() {
final TimePicker timePicker = new TimePicker(getActivity());
timePicker.setIs24HourView(DateFormat.is24HourFormat(getActivity()));
timePicker.setCurrentHour(mHour);
timePicker.setCurrentMinute(mMinute);
new AlertDialog.Builder(getActivity())
.setTitle(R.string.select_time)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
mHour = timePicker.getCurrentHour();
mMinute = timePicker.getCurrentMinute();
Date d = new Date(mYear - 1900, mMonth, mDay, mHour, mMinute);
long timestamp = d.getTime();
try {
int flags = 0;
flags |= DateUtils.FORMAT_SHOW_DATE;
flags |= DateUtils.FORMAT_ABBREV_MONTH;
flags |= DateUtils.FORMAT_SHOW_YEAR;
flags |= DateUtils.FORMAT_SHOW_TIME;
String formattedDate = DateUtils.formatDateTime(getActivity(), timestamp, flags);
mCustomPubDate = timestamp;
mPubDateText.setText(formattedDate);
mIsCustomPubDate = true;
updatePostSettingsAndSaveButton();
} catch (RuntimeException e) {
AppLog.e(T.POSTS, e);
}
}
})
.setNegativeButton(android.R.string.cancel,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
}
}).setView(timePicker).show();
}
/**
* Updates post object with content of this fragment
*/
public void updatePostSettings() {
if (!isAdded() || mPost == null) {
return;
}
String password = EditTextUtils.getText(mPasswordEditText);
String pubDate = EditTextUtils.getText(mPubDateText);
String excerpt = EditTextUtils.getText(mExcerptEditText);
long pubDateTimestamp = 0;
if (mIsCustomPubDate && pubDate.equals(getText(R.string.immediately)) && !mPost.isLocalDraft()) {
Date d = new Date();
pubDateTimestamp = d.getTime();
} else if (!pubDate.equals(getText(R.string.immediately))) {
if (mIsCustomPubDate)
pubDateTimestamp = mCustomPubDate;
else if (mPost.getDate_created_gmt() > 0)
pubDateTimestamp = mPost.getDate_created_gmt();
} else if (pubDate.equals(getText(R.string.immediately)) && mPost.isLocalDraft()) {
mPost.setDate_created_gmt(0);
mPost.setDateCreated(0);
}
String tags = "", postFormat = "";
if (!mPost.isPage()) {
tags = EditTextUtils.getText(mTagsEditText);
// post format
if (mPostFormats != null && mPostFormatSpinner != null &&
mPostFormatSpinner.getSelectedItemPosition() < mPostFormats.length) {
postFormat = mPostFormats[mPostFormatSpinner.getSelectedItemPosition()];
}
}
String status;
if (mStatusSpinner != null) {
status = getPostStatusForSpinnerPosition(mStatusSpinner.getSelectedItemPosition());
} else {
status = mPost.getPostStatus();
}
// We want to flag this post as having changed statuses from draft to published so that we
// properly track stats we care about for when users first publish posts.
if (!mPost.isLocalDraft() && mPost.getPostStatus().equals(PostStatus.toString(PostStatus.DRAFT))
&& status.equals(PostStatus.toString(PostStatus.PUBLISHED))) {
mPost.setChangedFromDraftToPublished(true);
}
if (mPost.supportsLocation()) {
mPost.setLocation(mPostLocation);
}
if (mCategories != null) {
mPost.setJSONCategories(new JSONArray(mCategories));
}
if (AppPrefs.isVisualEditorEnabled()) {
mPost.setFeaturedImageId(mFeaturedImageId);
}
mPost.setPostExcerpt(excerpt);
mPost.setDate_created_gmt(pubDateTimestamp);
mPost.setKeywords(tags);
mPost.setPostStatus(status);
mPost.setPassword(password);
mPost.setPostFormat(postFormat);
}
/*
* Saves settings to post object and updates save button text in the ActionBar
*/
private void updatePostSettingsAndSaveButton() {
if (isAdded()) {
updatePostSettings();
getActivity().invalidateOptionsMenu();
}
}
/**
* Location methods
*/
/*
* retrieves and displays the friendly address for a lat/long location
*/
private class GetAddressTask extends AsyncTask<Double, Void, Address> {
double latitude;
double longitude;
@Override
protected void onPreExecute() {
setLocationStatus(LocationStatus.SEARCHING);
showLocationView();
}
@Override
protected Address doInBackground(Double... args) {
// args will be the latitude, longitude to look up
latitude = args[0];
longitude = args[1];
return GeocoderUtils.getAddressFromCoords(getActivity(), latitude, longitude);
}
protected void onPostExecute(Address address) {
setLocationStatus(LocationStatus.FOUND);
if (address == null) {
// show lat/long when Geocoder fails (ugly, but better than not showing anything
// or showing an error since the location has been assigned to the post already)
updateLocationText(Double.toString(latitude) + ", " + Double.toString(longitude));
} else {
String locationName = GeocoderUtils.getLocationNameFromAddress(address);
updateLocationText(locationName);
}
}
}
private class GetCoordsTask extends AsyncTask<String, Void, Address> {
@Override
protected void onPreExecute() {
setLocationStatus(LocationStatus.SEARCHING);
showLocationView();
}
@Override
protected Address doInBackground(String... args) {
String locationName = args[0];
return GeocoderUtils.getAddressFromLocationName(getActivity(), locationName);
}
@Override
protected void onPostExecute(Address address) {
setLocationStatus(LocationStatus.FOUND);
showLocationView();
if (address != null) {
double[] coordinates = GeocoderUtils.getCoordsFromAddress(address);
setLocation(coordinates[0], coordinates[1]);
String locationName = GeocoderUtils.getLocationNameFromAddress(address);
updateLocationText(locationName);
} else {
showLocationNotAvailableError();
showLocationSearch();
}
}
}
private LocationHelper.LocationResult locationResult = new LocationHelper.LocationResult() {
@Override
public void gotLocation(final Location location) {
if (getActivity() == null)
return;
// note that location will be null when requesting location fails
getActivity().runOnUiThread(new Runnable() {
public void run() {
setLocation(location);
}
});
}
};
private View mLocationAddSection;
private View mLocationSearchSection;
private View mLocationViewSection;
private TextView mLocationText;
private EditText mLocationEditText;
private Button mButtonSearchLocation;
private TextWatcher mLocationEditTextWatcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) { }
@Override
public void afterTextChanged(Editable s) {
String buttonText;
if (s.length() > 0) {
buttonText = getResources().getString(R.string.search_location);
} else {
buttonText = getResources().getString(R.string.search_current_location);
}
mButtonSearchLocation.setText(buttonText);
}
};
/*
* called when activity is created to initialize the location provider, show views related
* to location if enabled for this blog, and retrieve the current location if necessary
*/
private void initLocation(ViewGroup rootView) {
if (!mPost.supportsLocation()) return;
// show the location views if a provider was found and this is a post on a blog that has location enabled
View locationRootView = ((ViewStub) rootView.findViewById(R.id.stub_post_location_settings)).inflate();
TextView locationLabel = ((TextView) locationRootView.findViewById(R.id.locationLabel));
locationLabel.setText(getResources().getString(R.string.location).toUpperCase());
mLocationText = (TextView) locationRootView.findViewById(R.id.locationText);
mLocationText.setOnClickListener(this);
mLocationAddSection = locationRootView.findViewById(R.id.sectionLocationAdd);
mLocationSearchSection = locationRootView.findViewById(R.id.sectionLocationSearch);
mLocationViewSection = locationRootView.findViewById(R.id.sectionLocationView);
Button addLocation = (Button) locationRootView.findViewById(R.id.addLocation);
addLocation.setOnClickListener(this);
mButtonSearchLocation = (Button) locationRootView.findViewById(R.id.searchLocation);
mButtonSearchLocation.setOnClickListener(this);
mLocationEditText = (EditText) locationRootView.findViewById(R.id.searchLocationText);
mLocationEditText.setOnEditorActionListener(this);
mLocationEditText.addTextChangedListener(mLocationEditTextWatcher);
Button updateLocation = (Button) locationRootView.findViewById(R.id.updateLocation);
Button removeLocation = (Button) locationRootView.findViewById(R.id.removeLocation);
updateLocation.setOnClickListener(this);
removeLocation.setOnClickListener(this);
// this is where we ask for location permission when EditPostActivity is oppened
if (SiteSettingsInterface.getGeotagging(getActivity()) && !checkForLocationPermission()) return;
// if this post has location attached to it, look up the location address
if (mPost.hasLocation()) {
showLocationView();
PostLocation location = mPost.getLocation();
setLocation(location.getLatitude(), location.getLongitude());
} else {
// Search for current location to geotag post if preferences allow
EditPostActivity activity = (EditPostActivity) getActivity();
if (SiteSettingsInterface.getGeotagging(activity) && activity.isNewPost()) {
searchLocation();
} else {
showLocationAdd();
}
}
}
private boolean checkForLocationPermission() {
return isAdded() && PermissionUtils.checkLocationPermissions(getActivity(),
EditPostActivity.LOCATION_PERMISSION_REQUEST_CODE);
}
public void showLocationSearch() {
mLocationAddSection.setVisibility(View.GONE);
mLocationSearchSection.setVisibility(View.VISIBLE);
mLocationViewSection.setVisibility(View.GONE);
EditTextUtils.showSoftInput(mLocationEditText);
}
private void showLocationAdd() {
mLocationAddSection.setVisibility(View.VISIBLE);
mLocationSearchSection.setVisibility(View.GONE);
mLocationViewSection.setVisibility(View.GONE);
}
private void showLocationView() {
mLocationAddSection.setVisibility(View.GONE);
mLocationSearchSection.setVisibility(View.GONE);
mLocationViewSection.setVisibility(View.VISIBLE);
}
public void searchLocation() {
if(!isAdded() || mLocationEditText == null) return;
EditTextUtils.hideSoftInput(mLocationEditText);
String location = EditTextUtils.getText(mLocationEditText);
removeLocation();
if (location.isEmpty()) {
fetchCurrentLocation();
} else {
new GetCoordsTask().execute(location);
}
}
/*
* get the current location
*/
private void fetchCurrentLocation() {
if (!isAdded()) {
return;
}
if (mLocationHelper == null) {
mLocationHelper = new LocationHelper();
}
boolean canGetLocation = mLocationHelper.getLocation(getActivity(), locationResult);
if (canGetLocation) {
setLocationStatus(LocationStatus.SEARCHING);
showLocationView();
} else {
setLocation(null);
showLocationNotAvailableError();
showLocationAdd();
}
}
/*
* called when location is retrieved/updated for this post - looks up the address to
* display for the lat/long
*/
private void setLocation(Location location) {
if (location != null) {
setLocation(location.getLatitude(), location.getLongitude());
} else {
updateLocationText(getString(R.string.location_not_found));
setLocationStatus(LocationStatus.NOT_FOUND);
}
}
private void setLocation(double latitude, double longitude) {
mPostLocation = new PostLocation(latitude, longitude);
new GetAddressTask().execute(mPostLocation.getLatitude(), mPostLocation.getLongitude());
}
private void removeLocation() {
mPostLocation = null;
mPost.unsetLocation();
updateLocationText("");
setLocationStatus(LocationStatus.NONE);
}
private void viewLocation() {
if (mPostLocation != null && mPostLocation.isValid()) {
String uri = "geo:" + mPostLocation.getLatitude() + "," + mPostLocation.getLongitude();
startActivity(new Intent(android.content.Intent.ACTION_VIEW, Uri.parse(uri)));
} else {
showLocationNotAvailableError();
showLocationAdd();
}
}
private void showLocationNotAvailableError() {
if (!isAdded()) {
return;
}
Toast.makeText(getActivity(), getResources().getText(R.string.location_not_found), Toast.LENGTH_SHORT).show();
}
private void updateLocationText(String locationName) {
mLocationText.setText(locationName);
}
/*
* changes the left drawable on the location text to match the passed status
*/
private void setLocationStatus(LocationStatus status) {
if (!isAdded()) {
return;
}
// animate location text when searching
if (status == LocationStatus.SEARCHING) {
updateLocationText(getString(R.string.loading));
Animation aniBlink = AnimationUtils.loadAnimation(getActivity(), R.anim.blink);
if (aniBlink != null) {
mLocationText.startAnimation(aniBlink);
}
} else {
mLocationText.clearAnimation();
}
final int drawableId;
switch (status) {
case FOUND:
drawableId = R.drawable.ic_action_location_found;
break;
case NOT_FOUND:
drawableId = R.drawable.ic_action_location_off;
break;
case SEARCHING:
drawableId = R.drawable.ic_action_location_searching;
break;
case NONE:
drawableId = 0;
break;
default:
return;
}
mLocationText.setCompoundDrawablesWithIntrinsicBounds(drawableId, 0, 0, 0);
}
/**
* Categories
*/
private void onCategoryButtonClick(View v) {
if (mCategories == null) {
ToastUtils.showToast(getActivity(), R.string.error_generic);
return;
}
// Get category name by removing prefix from the tag
boolean listChanged = false;
String categoryName = (String) v.getTag();
categoryName = categoryName.replaceFirst(CATEGORY_PREFIX_TAG, "");
// Remove clicked category from list
for (int i = 0; i < mCategories.size(); i++) {
if (mCategories.get(i).equals(categoryName)) {
mCategories.remove(i);
listChanged = true;
break;
}
}
// Recreate category views
if (listChanged) {
populateSelectedCategories();
}
}
private void populateSelectedCategories() {
// Remove previous category buttons if any + select category button
List<View> viewsToRemove = new ArrayList<View>();
for (int i = 0; i < mSectionCategories.getChildCount(); i++) {
View v = mSectionCategories.getChildAt(i);
if (v == null)
return;
Object tag = v.getTag();
if (tag != null && tag.getClass() == String.class &&
(((String) tag).startsWith(CATEGORY_PREFIX_TAG) || tag.equals("select-category"))) {
viewsToRemove.add(v);
}
}
for (View viewToRemove : viewsToRemove) {
mSectionCategories.removeView(viewToRemove);
}
viewsToRemove.clear();
// New category buttons
LayoutInflater layoutInflater = getActivity().getLayoutInflater();
if (mCategories != null) {
for (String categoryName : mCategories) {
AppCompatButton buttonCategory = (AppCompatButton) layoutInflater.inflate(R.layout.category_button, null);
if (categoryName != null && buttonCategory != null) {
buttonCategory.setText(Html.fromHtml(categoryName));
buttonCategory.setTag(CATEGORY_PREFIX_TAG + categoryName);
buttonCategory.setOnClickListener(this);
mSectionCategories.addView(buttonCategory);
}
}
}
// Add select category button
Button selectCategory = (Button) layoutInflater.inflate(R.layout.category_select_button, null);
if (selectCategory != null) {
selectCategory.setOnClickListener(this);
mSectionCategories.addView(selectCategory);
}
}
}