package org.wordpress.android.ui.posts;
import android.app.Activity;
import android.app.DatePickerDialog;
import android.app.Fragment;
import android.app.TimePickerDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.location.Address;
import android.location.Location;
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.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.TimePicker;
import android.widget.Toast;
import com.android.volley.toolbox.NetworkImageView;
import org.apache.commons.lang3.StringUtils;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.wordpress.android.R;
import org.wordpress.android.WordPress;
import org.wordpress.android.fluxc.Dispatcher;
import org.wordpress.android.fluxc.generated.SiteActionBuilder;
import org.wordpress.android.fluxc.generated.TaxonomyActionBuilder;
import org.wordpress.android.fluxc.model.MediaModel;
import org.wordpress.android.fluxc.model.PostFormatModel;
import org.wordpress.android.fluxc.model.PostModel;
import org.wordpress.android.fluxc.model.SiteModel;
import org.wordpress.android.fluxc.model.TermModel;
import org.wordpress.android.fluxc.model.post.PostLocation;
import org.wordpress.android.fluxc.model.post.PostStatus;
import org.wordpress.android.fluxc.store.MediaStore;
import org.wordpress.android.fluxc.store.SiteStore;
import org.wordpress.android.fluxc.store.TaxonomyStore;
import org.wordpress.android.fluxc.store.TaxonomyStore.OnTaxonomyChanged;
import org.wordpress.android.fluxc.tools.FluxCImageLoader;
import org.wordpress.android.ui.ActivityLauncher;
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.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.DateTimeUtils;
import org.wordpress.android.util.DisplayUtils;
import org.wordpress.android.util.EditTextUtils;
import org.wordpress.android.util.GeocoderUtils;
import org.wordpress.android.util.ListUtils;
import org.wordpress.android.util.PermissionUtils;
import org.wordpress.android.util.ToastUtils;
import org.wordpress.android.util.helpers.LocationHelper;
import org.wordpress.android.widgets.SuggestionAutoCompleteText;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import javax.inject.Inject;
public class EditPostSettingsFragment extends Fragment
implements View.OnClickListener, TextView.OnEditorActionListener {
private static final String KEY_POST = "KEY_POST";
private static final String POST_FORMAT_STANDARD_KEY = "standard";
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 PostModel mPost;
private SiteModel mSite;
private Spinner mStatusSpinner, mPostFormatSpinner;
private EditText mPasswordEditText, mExcerptEditText;
private TextView mPubDateText;
private ViewGroup mSectionCategories;
private NetworkImageView mFeaturedImageView;
private Button mFeaturedImageButton;
private SuggestionAutoCompleteText mTagsEditText;
private SuggestionServiceConnectionManager mSuggestionServiceConnectionManager;
private long mFeaturedImageId;
private List<TermModel> mCategories;
private PostLocation mPostLocation;
private LocationHelper mLocationHelper;
private int mYear, mMonth, mDay, mHour, mMinute;
private String mCustomPubDate = "";
private boolean mIsCustomPubDate;
private ArrayList<String> mPostFormatKeys;
private ArrayList<String> mPostFormatNames;
private enum LocationStatus {NONE, FOUND, NOT_FOUND, SEARCHING}
@Inject SiteStore mSiteStore;
@Inject MediaStore mMediaStore;
@Inject TaxonomyStore mTaxonomyStore;
@Inject Dispatcher mDispatcher;
@Inject FluxCImageLoader mImageLoader;
public static EditPostSettingsFragment newInstance(SiteModel site, PostModel post) {
EditPostSettingsFragment fragment = new EditPostSettingsFragment();
Bundle bundle = new Bundle();
bundle.putSerializable(WordPress.SITE, site);
bundle.putSerializable(KEY_POST, post);
fragment.setArguments(bundle);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((WordPress) getActivity().getApplicationContext()).component().inject(this);
mDispatcher.register(this);
if (getActivity() != null) {
PreferenceManager.setDefaultValues(getActivity(), R.xml.account_settings, false);
}
updateSiteOrFinishActivity(savedInstanceState);
}
private void updateSiteOrFinishActivity(Bundle savedInstanceState) {
if (savedInstanceState == null) {
if (getArguments() != null) {
mSite = (SiteModel) getArguments().getSerializable(WordPress.SITE);
mPost = (PostModel) getArguments().getSerializable(KEY_POST);
} else {
mSite = (SiteModel) getActivity().getIntent().getSerializableExtra(WordPress.SITE);
mPost = (PostModel) getActivity().getIntent().getSerializableExtra(KEY_POST);
}
} else {
mSite = (SiteModel) savedInstanceState.getSerializable(WordPress.SITE);
mPost = (PostModel) savedInstanceState.getSerializable(KEY_POST);
}
if (mSite == null) {
ToastUtils.showToast(getActivity(), R.string.blog_not_found, ToastUtils.Duration.SHORT);
getActivity().finish();
}
// Update post formats and categories, in case anything changed.
mDispatcher.dispatch(SiteActionBuilder.newFetchPostFormatsAction(mSite));
if (!mPost.isPage()) {
mDispatcher.dispatch(TaxonomyActionBuilder.newFetchCategoriesAction(mSite));
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putSerializable(WordPress.SITE, mSite);
outState.putSerializable(KEY_POST, mPost);
}
@Override
public void onDestroy() {
if (mSuggestionServiceConnectionManager != null) {
mSuggestionServiceConnectionManager.unbindFromService();
}
mDispatcher.unregister(this);
super.onDestroy();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.edit_post_settings_fragment, container, false);
if (rootView == 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);
mExcerptEditText = (EditText) rootView.findViewById(R.id.postExcerpt);
mPasswordEditText = (EditText) rootView.findViewById(R.id.post_password);
mPubDateText = (TextView) rootView.findViewById(R.id.pubDate);
mPubDateText.setOnClickListener(this);
mStatusSpinner = (Spinner) rootView.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) rootView.findViewById(R.id.sectionCategories));
TextView featuredImageLabel = (TextView) rootView.findViewById(R.id.featuredImageLabel);
mFeaturedImageView = (NetworkImageView) rootView.findViewById(R.id.featuredImage);
mFeaturedImageButton = (Button) rootView.findViewById(R.id.addFeaturedImage);
if (AppPrefs.isVisualEditorEnabled() || AppPrefs.isAztecEditorEnabled()) {
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 {
featuredImageLabel.setVisibility(View.GONE);
mFeaturedImageView.setVisibility(View.GONE);
mFeaturedImageButton.setVisibility(View.GONE);
}
if (mPost.isPage()) { // remove post specific views
mExcerptEditText.setVisibility(View.GONE);
rootView.findViewById(R.id.sectionTags).setVisibility(View.GONE);
rootView.findViewById(R.id.sectionCategories).setVisibility(View.GONE);
rootView.findViewById(R.id.postFormatLabel).setVisibility(View.GONE);
rootView.findViewById(R.id.postFormat).setVisibility(View.GONE);
} else {
// Default values
mPostFormatKeys = new ArrayList<>(Arrays.asList(getResources().getStringArray(R.array.post_format_keys)));
mPostFormatNames = new ArrayList<>(
Arrays.asList(getResources().getStringArray(R.array.post_format_display_names)));
// If we have specific values for this site, use them
List<PostFormatModel> postFormatModels = mSiteStore.getPostFormats(mSite);
for (PostFormatModel postFormatModel : postFormatModels) {
if (!mPostFormatKeys.contains(postFormatModel.getSlug())) {
mPostFormatKeys.add(postFormatModel.getSlug());
mPostFormatNames.add(postFormatModel.getDisplayName());
}
}
// Set up the Post Format spinner
mPostFormatSpinner = (Spinner) rootView.findViewById(R.id.postFormat);
ArrayAdapter<String> pfAdapter = new ArrayAdapter<>(getActivity(), R.layout.simple_spinner_item,
mPostFormatNames);
pfAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mPostFormatSpinner.setAdapter(pfAdapter);
String activePostFormat = POST_FORMAT_STANDARD_KEY;
if (!TextUtils.isEmpty(mPost.getPostFormat())) {
activePostFormat = mPost.getPostFormat();
}
for (int i = 0; i < mPostFormatKeys.size(); i++) {
if (mPostFormatKeys.get(i).equals(activePostFormat))
mPostFormatSpinner.setSelection(i);
}
mPostFormatSpinner.setOnTouchListener(
new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
return false;
}
}
);
mTagsEditText = (SuggestionAutoCompleteText) rootView.findViewById(R.id.tags);
if (mTagsEditText != null) {
mTagsEditText.setTokenizer(new SuggestionAutoCompleteText.CommaTokenizer());
setupSuggestionServiceAndAdapter();
}
}
initSettingsFields();
populateSelectedCategories();
initLocation(rootView);
return rootView;
}
@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;
long remoteBlogId = mSite.getSiteId();
mSuggestionServiceConnectionManager = new SuggestionServiceConnectionManager(getActivity(), remoteBlogId);
TagSuggestionAdapter tagSuggestionAdapter = SuggestionUtils.setupTagSuggestions(mSite, getActivity(),
mSuggestionServiceConnectionManager);
if (tagSuggestionAdapter != null) {
mTagsEditText.setAdapter(tagSuggestionAdapter);
}
}
private void initSettingsFields() {
mExcerptEditText.setText(mPost.getExcerpt());
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;
}
}
);
String pubDate = mPost.getDateCreated();
if (StringUtils.isNotEmpty(pubDate)) {
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(),
DateTimeUtils.timestampFromIso8601Millis(pubDate), flags);
mPubDateText.setText(formattedDate);
} catch (RuntimeException e) {
AppLog.e(T.POSTS, e);
}
}
if (!TextUtils.isEmpty(mPost.getPassword())) {
mPasswordEditText.setText(mPost.getPassword());
}
updateStatusSpinner();
}
public void updateStatusSpinner() {
switch (PostStatus.fromPost(mPost)) {
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;
}
String tags = TextUtils.join(",", mPost.getTagNameList());
if (!tags.equals("") && mTagsEditText != null) {
mTagsEditText.setText(tags);
}
if (AppPrefs.isVisualEditorEnabled() || AppPrefs.isAztecEditorEnabled()) {
updateFeaturedImage(mPost.getFeaturedImageId());
}
}
public long getFeaturedImageId() {
return mFeaturedImageId;
}
public void updateFeaturedImage(long id) {
if (mFeaturedImageId != id) {
mFeaturedImageId = id;
if (mFeaturedImageId > 0) {
MediaModel media = mMediaStore.getSiteMediaWithId(mSite, mFeaturedImageId);
if (media == null) {
return;
}
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);
WordPressMediaUtils.loadNetworkImage(media.getThumbnailUrl() + "?w=" + imageWidth, mFeaturedImageView,
mImageLoader);
} else {
mFeaturedImageView.setVisibility(View.GONE);
mFeaturedImageButton.setVisibility(View.VISIBLE);
}
}
}
private void launchMediaGalleryActivity() {
Intent intent = new Intent(getActivity(), MediaGalleryPickerActivity.class);
intent.putExtra(WordPress.SITE, mSite);
intent.putExtra(MediaGalleryPickerActivity.PARAM_SELECT_ONE_ITEM, true);
startActivityForResult(intent, MediaGalleryPickerActivity.REQUEST_CODE);
}
private PostStatus getPostStatusForSpinnerPosition(int position) {
switch (position) {
case 0:
return PostStatus.PUBLISHED;
case 1:
return PostStatus.DRAFT;
case 2:
return PostStatus.PENDING;
case 3:
return PostStatus.PRIVATE;
default:
return 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")) {
@SuppressWarnings("unchecked")
List<TermModel> categoryList = (List<TermModel>) extras.getSerializable("selectedCategories");
mCategories = categoryList;
populateSelectedCategories();
}
break;
case MediaGalleryPickerActivity.REQUEST_CODE:
if (resultCode == Activity.RESULT_OK) {
ArrayList<Long> ids = ListUtils.
fromLongArray(data.getLongArrayExtra(MediaGalleryPickerActivity.RESULT_IDS));
if (ids == null || ids.size() == 0) {
return;
}
updateFeaturedImage(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) {
Intent categoriesIntent = new Intent(getActivity(), SelectCategoriesActivity.class);
categoriesIntent.putExtra(WordPress.SITE, mSite);
// Make sure the PostModel is up to date with current category selections
updatePostSettings(mPost);
categoriesIntent.putExtra(SelectCategoriesActivity.KEY_POST, mPost);
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 DatePickerDialog datePickerDialog = new DatePickerDialog(getActivity(), null, mYear, mMonth, mDay);
datePickerDialog.setTitle(R.string.select_date);
datePickerDialog.setButton(DialogInterface.BUTTON_POSITIVE, getResources().getText(android.R.string.ok),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
mYear = datePickerDialog.getDatePicker().getYear();
mMonth = datePickerDialog.getDatePicker().getMonth();
mDay = datePickerDialog.getDatePicker().getDayOfMonth();
showPostTimeSelectionDialog();
}
});
datePickerDialog.setButton(DialogInterface.BUTTON_NEUTRAL, getResources().getText(R.string.immediately),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
mIsCustomPubDate = true;
mPubDateText.setText(R.string.immediately);
updatePostSettingsAndSaveButton();
}
});
datePickerDialog.setButton(DialogInterface.BUTTON_NEGATIVE, getResources().getText(android.R.string.cancel),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
}
});
datePickerDialog.show();
}
private void showPostTimeSelectionDialog() {
final TimePickerDialog timePickerDialog = new TimePickerDialog(getActivity(),
new TimePickerDialog.OnTimeSetListener() {
@Override
public void onTimeSet(TimePicker timePicker, int selectedHour, int selectedMinute) {
mHour = selectedHour;
mMinute = selectedMinute;
Date javaDate = new Date(mYear - 1900, mMonth, mDay, mHour, mMinute);
long javaTimestamp = javaDate.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(), javaTimestamp, flags);
mCustomPubDate = DateTimeUtils.iso8601FromDate(javaDate);
mPubDateText.setText(formattedDate);
mIsCustomPubDate = true;
updatePostSettingsAndSaveButton();
} catch (RuntimeException e) {
AppLog.e(T.POSTS, e);
}
}
}, mHour, mMinute, DateFormat.is24HourFormat(getActivity()));
timePickerDialog.setTitle(R.string.select_time);
timePickerDialog.show();
}
/**
* Updates given post object with current status of settings fields
*/
public void updatePostSettings(PostModel post) {
if (!isAdded() || post == null) {
return;
}
String password = EditTextUtils.getText(mPasswordEditText);
String excerpt = EditTextUtils.getText(mExcerptEditText);
boolean publishImmediately = EditTextUtils.getText(mPubDateText).equals(getText(R.string.immediately));
String publicationDateIso8601 = "";
if (mIsCustomPubDate && publishImmediately && !post.isLocalDraft()) {
publicationDateIso8601 = DateTimeUtils.iso8601FromDate(new Date());
} else if (!publishImmediately) {
if (mIsCustomPubDate) {
publicationDateIso8601 = mCustomPubDate;
} else if (StringUtils.isNotEmpty(post.getDateCreated())) {
publicationDateIso8601 = post.getDateCreated();
}
}
post.setDateCreated(publicationDateIso8601);
String tags = "", postFormat = "";
if (!post.isPage()) {
tags = EditTextUtils.getText(mTagsEditText);
// since mTagsEditText is a `textMultiLine` field, we should replace "\n" with space
tags = tags.replace("\n", " ");
// post format
if (mPostFormatKeys != null && mPostFormatSpinner != null &&
mPostFormatSpinner.getSelectedItemPosition() < mPostFormatKeys.size()) {
postFormat = mPostFormatKeys.get(mPostFormatSpinner.getSelectedItemPosition());
}
}
String status;
if (mStatusSpinner != null) {
status = getPostStatusForSpinnerPosition(mStatusSpinner.getSelectedItemPosition()).toString();
} else {
status = post.getStatus();
}
if (post.supportsLocation()) {
if (mPostLocation == null) {
post.clearLocation();
} else {
post.setLocation(mPostLocation);
}
}
if (mCategories != null) {
List<Long> categoryIds = new ArrayList<>();
for (TermModel category : mCategories) {
categoryIds.add(category.getRemoteTermId());
}
post.setCategoryIdList(categoryIds);
}
if (AppPrefs.isVisualEditorEnabled() || AppPrefs.isAztecEditorEnabled()) {
post.setFeaturedImageId(mFeaturedImageId);
}
post.setExcerpt(excerpt);
post.setTagNameList(Arrays.asList(TextUtils.split(tags, ",")));
post.setStatus(status);
post.setPassword(password);
post.setPostFormat(postFormat);
}
/*
* Saves settings to post object and updates save button text in the ActionBar
*/
private void updatePostSettingsAndSaveButton() {
if (isAdded()) {
updatePostSettings(mPost);
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);
// 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 {
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.clearLocation();
updateLocationText("");
setLocationStatus(LocationStatus.NONE);
}
private void viewLocation() {
if (mPostLocation != null && mPostLocation.isValid()) {
String locationString = "geo:" + mPostLocation.getLatitude() + "," + mPostLocation.getLongitude();
ActivityLauncher.openUrlExternal(getActivity(), locationString);
} 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_location_found_black_translucent_40_32dp;
break;
case NOT_FOUND:
drawableId = R.drawable.ic_location_off_black_translucent_40_32dp;
break;
case SEARCHING:
drawableId = R.drawable.ic_location_searching_black_40_32dp;
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).getName().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<>();
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 (TermModel category : mCategories) {
AppCompatButton buttonCategory = (AppCompatButton) layoutInflater.inflate(R.layout.category_button,
null);
if (category != null && category.getName() != null && buttonCategory != null) {
buttonCategory.setText(Html.fromHtml(category.getName()));
buttonCategory.setTag(CATEGORY_PREFIX_TAG + category.getName());
buttonCategory.setOnClickListener(this);
mSectionCategories.addView(buttonCategory);
}
}
}
// Add select category button once the category list has been initialized
Button selectCategory = (Button) layoutInflater.inflate(R.layout.category_select_button, null);
if (selectCategory != null && mCategories != null) {
selectCategory.setOnClickListener(this);
mSectionCategories.addView(selectCategory);
}
}
@SuppressWarnings("unused")
@Subscribe(threadMode = ThreadMode.MAIN)
public void onTaxonomyChanged(OnTaxonomyChanged event) {
switch (event.causeOfChange) {
case FETCH_CATEGORIES:
mCategories = mTaxonomyStore.getCategoriesForPost(mPost, mSite);
populateSelectedCategories();
break;
}
}
}