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 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(); 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>() {}.getType(); Map jsonPostFormats = gson.fromJson(WordPress.getCurrentBlog().getPostFormats(), type); mPostFormats = new String[jsonPostFormats.size()]; mPostFormatTitles = new String[jsonPostFormats.size()]; int i = 0; for (Map.Entry 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 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 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) extras.getSerializable("selectedCategories"); populateSelectedCategories(); } break; case MediaGalleryPickerActivity.REQUEST_CODE: if (resultCode == Activity.RESULT_OK) { ArrayList 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(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 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 { @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 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 (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); } } }