blob: 13fc10c5b69e2dfb9a75b820762a0bc7d2278bbf [file] [log] [blame]
package org.wordpress.android.ui.prefs;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.Handler;
import android.preference.EditTextPreference;
import android.preference.Preference;
import android.preference.PreferenceFragment;
import android.preference.PreferenceScreen;
import android.support.annotation.NonNull;
import android.support.design.widget.Snackbar;
import android.support.v7.widget.LinearLayoutManager;
import android.text.TextUtils;
import android.util.Pair;
import android.util.SparseBooleanArray;
import android.view.ActionMode;
import android.view.ContextThemeWrapper;
import android.view.HapticFeedbackConstants;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager.LayoutParams;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.NumberPicker.Formatter;
import android.widget.TextView;
import com.android.volley.VolleyError;
import com.wordpress.rest.RestRequest;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.wordpress.android.R;
import org.wordpress.android.WordPress;
import org.wordpress.android.analytics.AnalyticsTracker;
import org.wordpress.android.models.AccountHelper;
import org.wordpress.android.models.Blog;
import org.wordpress.android.ui.WPWebViewActivity;
import org.wordpress.android.ui.stats.StatsWidgetProvider;
import org.wordpress.android.ui.stats.datasets.StatsTable;
import org.wordpress.android.util.AnalyticsUtils;
import org.wordpress.android.util.AppLog;
import org.wordpress.android.util.CoreEvents;
import org.wordpress.android.util.HelpshiftHelper;
import org.wordpress.android.util.NetworkUtils;
import org.wordpress.android.util.StringUtils;
import org.wordpress.android.util.ToastUtils;
import org.wordpress.android.util.UrlUtils;
import org.wordpress.android.util.WPActivityUtils;
import org.wordpress.android.util.WPPrefUtils;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import de.greenrobot.event.EventBus;
/**
* Allows interfacing with WordPress site settings. Works with WP.com and WP.org v4.5+ (pending).
*
* Settings are synced automatically when local changes are made.
*/
public class SiteSettingsFragment extends PreferenceFragment
implements Preference.OnPreferenceChangeListener,
Preference.OnPreferenceClickListener,
AdapterView.OnItemLongClickListener,
ViewGroup.OnHierarchyChangeListener,
Dialog.OnDismissListener,
SiteSettingsInterface.SiteSettingsListener {
/**
* Use this argument to pass the {@link Integer} local blog ID to this fragment.
*/
public static final String ARG_LOCAL_BLOG_ID = "local_blog_id";
/**
* When the user removes a site (by selecting Delete Site) the parent {@link Activity} result
* is set to this value and {@link Activity#finish()} is invoked.
*/
public static final int RESULT_BLOG_REMOVED = Activity.RESULT_FIRST_USER;
/**
* Provides the regex to identify domain HTTP(S) protocol and/or 'www' sub-domain.
*
* Used to format user-facing {@link String}'s in certain preferences.
*/
public static final String ADDRESS_FORMAT_REGEX = "^(https?://(w{3})?|www\\.)";
/**
* url that points to wordpress.com purchases
*/
public static final String WORDPRESS_PURCHASES_URL = "https://wordpress.com/purchases";
/**
* Used to move the Uncategorized category to the beginning of the category list.
*/
private static final int UNCATEGORIZED_CATEGORY_ID = 1;
/**
* Request code used when creating the {@link RelatedPostsDialog}.
*/
private static final int RELATED_POSTS_REQUEST_CODE = 1;
private static final int THREADING_REQUEST_CODE = 2;
private static final int PAGING_REQUEST_CODE = 3;
private static final int CLOSE_AFTER_REQUEST_CODE = 4;
private static final int MULTIPLE_LINKS_REQUEST_CODE = 5;
private static final int DELETE_SITE_REQUEST_CODE = 6;
private static final String DELETE_SITE_TAG = "delete-site";
private static final String PURCHASE_ORIGINAL_RESPONSE_KEY = "originalResponse";
private static final String PURCHASE_ACTIVE_KEY = "active";
private static final String ANALYTICS_ERROR_PROPERTY_KEY = "error";
private static final long FETCH_DELAY = 1000;
// Reference to blog obtained from passed ID (ARG_LOCAL_BLOG_ID)
private Blog mBlog;
// Can interface with WP.com or WP.org
private SiteSettingsInterface mSiteSettings;
// Reference to the list of items being edited in the current list editor
private List<String> mEditingList;
// Used to ensure that settings are only fetched once throughout the lifecycle of the fragment
private boolean mShouldFetch;
// General settings
private EditTextPreference mTitlePref;
private EditTextPreference mTaglinePref;
private EditTextPreference mAddressPref;
private DetailListPreference mPrivacyPref;
private DetailListPreference mLanguagePref;
// Account settings (NOTE: only for WP.org)
private EditTextPreference mUsernamePref;
private EditTextPreference mPasswordPref;
// Writing settings
private WPSwitchPreference mLocationPref;
private DetailListPreference mCategoryPref;
private DetailListPreference mFormatPref;
private Preference mRelatedPostsPref;
// Discussion settings preview
private WPSwitchPreference mAllowCommentsPref;
private WPSwitchPreference mSendPingbacksPref;
private WPSwitchPreference mReceivePingbacksPref;
// Discussion settings -> Defaults for New Posts
private WPSwitchPreference mAllowCommentsNested;
private WPSwitchPreference mSendPingbacksNested;
private WPSwitchPreference mReceivePingbacksNested;
private PreferenceScreen mMorePreference;
// Discussion settings -> Comments
private WPSwitchPreference mIdentityRequiredPreference;
private WPSwitchPreference mUserAccountRequiredPref;
private Preference mCloseAfterPref;
private DetailListPreference mSortByPref;
private Preference mThreadingPref;
private Preference mPagingPref;
private DetailListPreference mWhitelistPref;
private Preference mMultipleLinksPref;
private Preference mModerationHoldPref;
private Preference mBlacklistPref;
// This Device settings
private DetailListPreference mImageWidthPref;
private WPSwitchPreference mUploadAndLinkPref;
// Advanced settings
private Preference mStartOverPref;
private Preference mExportSitePref;
private Preference mDeleteSitePref;
private boolean mEditingEnabled = true;
// Reference to the state of the fragment
private boolean mIsFragmentPaused = false;
// Hold for Moderation and Blacklist settings
private Dialog mDialog;
private ActionMode mActionMode;
private MultiSelectRecyclerViewAdapter mAdapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Activity activity = getActivity();
// make sure we have local site data and a network connection, otherwise finish activity
mBlog = WordPress.getBlog(getArguments().getInt(ARG_LOCAL_BLOG_ID, -1));
if (mBlog == null || !NetworkUtils.checkConnection(activity)) {
getActivity().finish();
return;
}
// track successful settings screen access
AnalyticsUtils.trackWithCurrentBlogDetails(
AnalyticsTracker.Stat.SITE_SETTINGS_ACCESSED);
// setup state to fetch remote settings
mShouldFetch = true;
// initialize the appropriate settings interface (WP.com or WP.org)
mSiteSettings = SiteSettingsInterface.getInterface(activity, mBlog, this);
setRetainInstance(true);
addPreferencesFromResource(R.xml.site_settings);
// toggle which preferences are shown and set references
initPreferences();
}
@Override
public void onPause() {
super.onPause();
WordPress.wpDB.saveBlog(mBlog);
mIsFragmentPaused = true;
}
@Override
public void onResume() {
super.onResume();
// Fragment#onResume() is called after FragmentActivity#onPostResume().
// The latter is the most secure way of keeping track of the activity's state, and avoid calls to commitAllowingStateLoss.
mIsFragmentPaused = false;
// always load cached settings
mSiteSettings.init(false);
if (mShouldFetch) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
// initialize settings with locally cached values, fetch remote on first pass
mSiteSettings.init(true);
}
}, FETCH_DELAY);
// stop future calls from fetching remote settings
mShouldFetch = false;
}
}
@Override
public void onDestroyView() {
removeMoreScreenToolbar();
super.onDestroyView();
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (data != null) {
switch (requestCode) {
case RELATED_POSTS_REQUEST_CODE:
// data is null if user cancelled editing Related Posts settings
mSiteSettings.setShowRelatedPosts(data.getBooleanExtra(
RelatedPostsDialog.SHOW_RELATED_POSTS_KEY, false));
mSiteSettings.setShowRelatedPostHeader(data.getBooleanExtra(
RelatedPostsDialog.SHOW_HEADER_KEY, false));
mSiteSettings.setShowRelatedPostImages(data.getBooleanExtra(
RelatedPostsDialog.SHOW_IMAGES_KEY, false));
onPreferenceChange(mRelatedPostsPref, mSiteSettings.getRelatedPostsDescription());
break;
case THREADING_REQUEST_CODE:
int levels = data.getIntExtra(NumberPickerDialog.CUR_VALUE_KEY, -1);
mSiteSettings.setShouldThreadComments(levels > 1 && data.getBooleanExtra
(NumberPickerDialog.SWITCH_ENABLED_KEY, false));
onPreferenceChange(mThreadingPref, levels);
break;
case PAGING_REQUEST_CODE:
mSiteSettings.setShouldPageComments(data.getBooleanExtra
(NumberPickerDialog.SWITCH_ENABLED_KEY, false));
onPreferenceChange(mPagingPref, data.getIntExtra(
NumberPickerDialog.CUR_VALUE_KEY, -1));
break;
case CLOSE_AFTER_REQUEST_CODE:
mSiteSettings.setShouldCloseAfter(data.getBooleanExtra
(NumberPickerDialog.SWITCH_ENABLED_KEY, false));
onPreferenceChange(mCloseAfterPref, data.getIntExtra(
NumberPickerDialog.CUR_VALUE_KEY, -1));
break;
case MULTIPLE_LINKS_REQUEST_CODE:
int numLinks = data.getIntExtra(NumberPickerDialog.CUR_VALUE_KEY, -1);
if (numLinks < 0 || numLinks == mSiteSettings.getMultipleLinks()) return;
onPreferenceChange(mMultipleLinksPref, numLinks);
break;
}
} else {
switch (requestCode) {
case DELETE_SITE_REQUEST_CODE:
deleteSite();
break;
}
}
super.onActivityResult(requestCode, resultCode, data);
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState) {
// use a wrapper to apply the Calypso theme
Context themer = new ContextThemeWrapper(getActivity(), R.style.Calypso_SiteSettingsTheme);
LayoutInflater localInflater = inflater.cloneInContext(themer);
View view = super.onCreateView(localInflater, container, savedInstanceState);
if (view != null) {
setupPreferenceList((ListView) view.findViewById(android.R.id.list), getResources());
}
return view;
}
@Override
public void onSaveInstanceState(Bundle outState) {
removeMoreScreenToolbar();
super.onSaveInstanceState(outState);
setupMorePreferenceScreen();
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState != null) setupMorePreferenceScreen();
}
@Override
public void onChildViewAdded(View parent, View child) {
if (child.getId() == android.R.id.title && child instanceof TextView) {
// style preference category title views
TextView title = (TextView) child;
WPPrefUtils.layoutAsBody2(title);
} else {
// style preference title views
TextView title = (TextView) child.findViewById(android.R.id.title);
if (title != null) WPPrefUtils.layoutAsSubhead(title);
}
}
@Override
public void onChildViewRemoved(View parent, View child) {
// NOP
}
@Override
public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) {
super.onPreferenceTreeClick(screen, preference);
// More preference selected, style the Discussion screen
if (preference == mMorePreference) {
// track user accessing the full Discussion settings screen
AnalyticsUtils.trackWithCurrentBlogDetails(
AnalyticsTracker.Stat.SITE_SETTINGS_ACCESSED_MORE_SETTINGS);
return setupMorePreferenceScreen();
} else if (preference == findPreference(getString(R.string.pref_key_site_start_over_screen))) {
Dialog dialog = ((PreferenceScreen) preference).getDialog();
if (dialog == null) return false;
AnalyticsUtils.trackWithCurrentBlogDetails(
AnalyticsTracker.Stat.SITE_SETTINGS_START_OVER_ACCESSED);
setupPreferenceList((ListView) dialog.findViewById(android.R.id.list), getResources());
String title = getString(R.string.start_over);
WPActivityUtils.addToolbarToDialog(this, dialog, title);
}
return false;
}
@Override
public boolean onPreferenceClick(Preference preference) {
if (preference == mRelatedPostsPref) {
showRelatedPostsDialog();
} else if (preference == mMultipleLinksPref) {
showMultipleLinksDialog();
} else if (preference == mModerationHoldPref) {
mEditingList = mSiteSettings.getModerationKeys();
showListEditorDialog(R.string.site_settings_moderation_hold_title,
R.string.site_settings_hold_for_moderation_description);
} else if (preference == mBlacklistPref) {
mEditingList = mSiteSettings.getBlacklistKeys();
showListEditorDialog(R.string.site_settings_blacklist_title,
R.string.site_settings_blacklist_description);
} else if (preference == mStartOverPref) {
AnalyticsUtils.trackWithCurrentBlogDetails(
AnalyticsTracker.Stat.SITE_SETTINGS_START_OVER_CONTACT_SUPPORT_CLICKED);
HelpshiftHelper.getInstance().showConversation(getActivity(), HelpshiftHelper.Tag.ORIGIN_START_OVER);
} else if (preference == mCloseAfterPref) {
showCloseAfterDialog();
} else if (preference == mPagingPref) {
showPagingDialog();
} else if (preference == mThreadingPref) {
showThreadingDialog();
} else if (preference == mCategoryPref || preference == mFormatPref) {
return !shouldShowListPreference((DetailListPreference) preference);
} else if (preference == mExportSitePref) {
showExportContentDialog();
} else if (preference == mDeleteSitePref) {
AnalyticsUtils.trackWithCurrentBlogDetails(
AnalyticsTracker.Stat.SITE_SETTINGS_DELETE_SITE_ACCESSED);
requestPurchasesForDeletionCheck();
} else {
return false;
}
return true;
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (newValue == null || !mEditingEnabled) return false;
if (preference == mTitlePref) {
mSiteSettings.setTitle(newValue.toString());
changeEditTextPreferenceValue(mTitlePref, mSiteSettings.getTitle());
} else if (preference == mTaglinePref) {
mSiteSettings.setTagline(newValue.toString());
changeEditTextPreferenceValue(mTaglinePref, mSiteSettings.getTagline());
} else if (preference == mAddressPref) {
mSiteSettings.setAddress(newValue.toString());
changeEditTextPreferenceValue(mAddressPref, mSiteSettings.getAddress());
} else if (preference == mLanguagePref) {
if (!mSiteSettings.setLanguageCode(newValue.toString())) {
AppLog.w(AppLog.T.SETTINGS, "Unknown language code " + newValue.toString() + " selected in Site Settings.");
ToastUtils.showToast(getActivity(), R.string.site_settings_unknown_language_code_error);
}
changeLanguageValue(mSiteSettings.getLanguageCode());
} else if (preference == mPrivacyPref) {
mSiteSettings.setPrivacy(Integer.parseInt(newValue.toString()));
setDetailListPreferenceValue(mPrivacyPref,
String.valueOf(mSiteSettings.getPrivacy()),
mSiteSettings.getPrivacyDescription());
} else if (preference == mAllowCommentsPref || preference == mAllowCommentsNested) {
setAllowComments((Boolean) newValue);
} else if (preference == mSendPingbacksPref || preference == mSendPingbacksNested) {
setSendPingbacks((Boolean) newValue);
} else if (preference == mReceivePingbacksPref || preference == mReceivePingbacksNested) {
setReceivePingbacks((Boolean) newValue);
} else if (preference == mCloseAfterPref) {
mSiteSettings.setCloseAfter(Integer.parseInt(newValue.toString()));
mCloseAfterPref.setSummary(mSiteSettings.getCloseAfterDescription());
} else if (preference == mSortByPref) {
mSiteSettings.setCommentSorting(Integer.parseInt(newValue.toString()));
setDetailListPreferenceValue(mSortByPref,
newValue.toString(),
mSiteSettings.getSortingDescription());
} else if (preference == mThreadingPref) {
mSiteSettings.setThreadingLevels(Integer.parseInt(newValue.toString()));
mThreadingPref.setSummary(mSiteSettings.getThreadingDescription());
} else if (preference == mPagingPref) {
mSiteSettings.setPagingCount(Integer.parseInt(newValue.toString()));
mPagingPref.setSummary(mSiteSettings.getPagingDescription());
} else if (preference == mIdentityRequiredPreference) {
mSiteSettings.setIdentityRequired((Boolean) newValue);
} else if (preference == mUserAccountRequiredPref) {
mSiteSettings.setUserAccountRequired((Boolean) newValue);
} else if (preference == mWhitelistPref) {
updateWhitelistSettings(Integer.parseInt(newValue.toString()));
} else if (preference == mMultipleLinksPref) {
mSiteSettings.setMultipleLinks(Integer.parseInt(newValue.toString()));
String s = StringUtils.getQuantityString(getActivity(), R.string.site_settings_multiple_links_summary_zero,
R.string.site_settings_multiple_links_summary_one,
R.string.site_settings_multiple_links_summary_other, mSiteSettings.getMultipleLinks());
mMultipleLinksPref.setSummary(s);
} else if (preference == mUsernamePref) {
mSiteSettings.setUsername(newValue.toString());
changeEditTextPreferenceValue(mUsernamePref, mSiteSettings.getUsername());
} else if (preference == mPasswordPref) {
mSiteSettings.setPassword(newValue.toString());
changeEditTextPreferenceValue(mPasswordPref, mSiteSettings.getPassword());
} else if (preference == mLocationPref) {
mSiteSettings.setLocation((Boolean) newValue);
} else if (preference == mCategoryPref) {
mSiteSettings.setDefaultCategory(Integer.parseInt(newValue.toString()));
setDetailListPreferenceValue(mCategoryPref,
newValue.toString(),
mSiteSettings.getDefaultCategoryForDisplay());
} else if (preference == mFormatPref) {
mSiteSettings.setDefaultFormat(newValue.toString());
setDetailListPreferenceValue(mFormatPref,
newValue.toString(),
mSiteSettings.getDefaultPostFormatDisplay());
} else if (preference == mImageWidthPref) {
mBlog.setMaxImageWidth(newValue.toString());
setDetailListPreferenceValue(mImageWidthPref,
mBlog.getMaxImageWidth(),
mBlog.getMaxImageWidth());
} else if (preference == mUploadAndLinkPref) {
mBlog.setFullSizeImage(Boolean.valueOf(newValue.toString()));
} else if (preference == mRelatedPostsPref) {
mRelatedPostsPref.setSummary(newValue.toString());
} else if (preference == mModerationHoldPref) {
mModerationHoldPref.setSummary(mSiteSettings.getModerationHoldDescription());
} else if (preference == mBlacklistPref) {
mBlacklistPref.setSummary(mSiteSettings.getBlacklistDescription());
} else {
return false;
}
mSiteSettings.saveSettings();
return true;
}
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
ListView listView = (ListView) parent;
ListAdapter listAdapter = listView.getAdapter();
Object obj = listAdapter.getItem(position);
if (obj != null) {
if (obj instanceof View.OnLongClickListener) {
View.OnLongClickListener longListener = (View.OnLongClickListener) obj;
return longListener.onLongClick(view);
} else if (obj instanceof PreferenceHint) {
PreferenceHint hintObj = (PreferenceHint) obj;
if (hintObj.hasHint()) {
HashMap<String, Object> properties = new HashMap<>();
properties.put("hint_shown", hintObj.getHint());
AnalyticsUtils.trackWithCurrentBlogDetails(
AnalyticsTracker.Stat.SITE_SETTINGS_HINT_TOAST_SHOWN, properties);
ToastUtils.showToast(getActivity(), hintObj.getHint(), ToastUtils.Duration.SHORT);
}
return true;
}
}
return false;
}
@Override
public void onDismiss(DialogInterface dialog) {
if (mEditingList == mSiteSettings.getModerationKeys()) {
onPreferenceChange(mModerationHoldPref, mEditingList.size());
} else if (mEditingList == mSiteSettings.getBlacklistKeys()) {
onPreferenceChange(mBlacklistPref, mEditingList.size());
}
mEditingList = null;
}
@Override
public void onSettingsUpdated(Exception error) {
if (error != null) {
ToastUtils.showToast(getActivity(), R.string.error_fetch_remote_site_settings);
getActivity().finish();
return;
}
if (isAdded()) setPreferencesFromSiteSettings();
}
@Override
public void onSettingsSaved(Exception error) {
if (error != null) {
ToastUtils.showToast(WordPress.getContext(), R.string.error_post_remote_site_settings);
return;
}
mBlog.setBlogName(mSiteSettings.getTitle());
WordPress.wpDB.saveBlog(mBlog);
// update the global current Blog so WordPress.getCurrentBlog() callers will get the updated object
WordPress.setCurrentBlog(mBlog.getLocalTableBlogId());
EventBus.getDefault().post(new CoreEvents.BlogListChanged());
}
@Override
public void onCredentialsValidated(Exception error) {
if (error != null) {
ToastUtils.showToast(WordPress.getContext(), R.string.username_or_password_incorrect);
}
}
private void setupPreferenceList(ListView prefList, Resources res) {
if (prefList == null || res == null) return;
// customize list dividers
//noinspection deprecation
prefList.setDivider(res.getDrawable(R.drawable.preferences_divider));
prefList.setDividerHeight(res.getDimensionPixelSize(R.dimen.site_settings_divider_height));
// handle long clicks on preferences to display hints
prefList.setOnItemLongClickListener(this);
// required to customize (Calypso) preference views
prefList.setOnHierarchyChangeListener(this);
// remove footer divider bar
prefList.setFooterDividersEnabled(false);
//noinspection deprecation
prefList.setOverscrollFooter(res.getDrawable(R.color.transparent));
}
/**
* Helper method to retrieve {@link Preference} references and initialize any data.
*/
private void initPreferences() {
mTitlePref = (EditTextPreference) getChangePref(R.string.pref_key_site_title);
mTaglinePref = (EditTextPreference) getChangePref(R.string.pref_key_site_tagline);
mAddressPref = (EditTextPreference) getChangePref(R.string.pref_key_site_address);
mPrivacyPref = (DetailListPreference) getChangePref(R.string.pref_key_site_visibility);
mLanguagePref = (DetailListPreference) getChangePref(R.string.pref_key_site_language);
mUsernamePref = (EditTextPreference) getChangePref(R.string.pref_key_site_username);
mPasswordPref = (EditTextPreference) getChangePref(R.string.pref_key_site_password);
mLocationPref = (WPSwitchPreference) getChangePref(R.string.pref_key_site_location);
mCategoryPref = (DetailListPreference) getChangePref(R.string.pref_key_site_category);
mFormatPref = (DetailListPreference) getChangePref(R.string.pref_key_site_format);
mAllowCommentsPref = (WPSwitchPreference) getChangePref(R.string.pref_key_site_allow_comments);
mAllowCommentsNested = (WPSwitchPreference) getChangePref(R.string.pref_key_site_allow_comments_nested);
mSendPingbacksPref = (WPSwitchPreference) getChangePref(R.string.pref_key_site_send_pingbacks);
mSendPingbacksNested = (WPSwitchPreference) getChangePref(R.string.pref_key_site_send_pingbacks_nested);
mReceivePingbacksPref = (WPSwitchPreference) getChangePref(R.string.pref_key_site_receive_pingbacks);
mReceivePingbacksNested = (WPSwitchPreference) getChangePref(R.string.pref_key_site_receive_pingbacks_nested);
mIdentityRequiredPreference = (WPSwitchPreference) getChangePref(R.string.pref_key_site_identity_required);
mUserAccountRequiredPref = (WPSwitchPreference) getChangePref(R.string.pref_key_site_user_account_required);
mSortByPref = (DetailListPreference) getChangePref(R.string.pref_key_site_sort_by);
mWhitelistPref = (DetailListPreference) getChangePref(R.string.pref_key_site_whitelist);
mMorePreference = (PreferenceScreen) getClickPref(R.string.pref_key_site_more_discussion);
mRelatedPostsPref = getClickPref(R.string.pref_key_site_related_posts);
mCloseAfterPref = getClickPref(R.string.pref_key_site_close_after);
mPagingPref = getClickPref(R.string.pref_key_site_paging);
mThreadingPref = getClickPref(R.string.pref_key_site_threading);
mMultipleLinksPref = getClickPref(R.string.pref_key_site_multiple_links);
mModerationHoldPref = getClickPref(R.string.pref_key_site_moderation_hold);
mBlacklistPref = getClickPref(R.string.pref_key_site_blacklist);
mImageWidthPref = (DetailListPreference) getChangePref(R.string.pref_key_site_image_width);
mUploadAndLinkPref = (WPSwitchPreference) getChangePref(R.string.pref_key_site_upload_and_link_image);
mStartOverPref = getClickPref(R.string.pref_key_site_start_over);
mExportSitePref = getClickPref(R.string.pref_key_site_export_site);
mDeleteSitePref = getClickPref(R.string.pref_key_site_delete_site);
sortLanguages();
// .com sites hide the Account category, self-hosted sites hide the Related Posts preference
if (mBlog.isDotcomFlag()) {
removeSelfHostedOnlyPreferences();
} else {
removeDotComOnlyPreferences();
}
// hide all options except for Delete site and Enable Location if user is not admin
if (!mBlog.isAdmin()) hideAdminRequiredPreferences();
}
public void setEditingEnabled(boolean enabled) {
// excludes mAddressPref, mMorePreference
final Preference[] editablePreference = {
mTitlePref , mTaglinePref, mPrivacyPref, mLanguagePref, mUsernamePref,
mPasswordPref, mLocationPref, mCategoryPref, mFormatPref, mAllowCommentsPref,
mAllowCommentsNested, mSendPingbacksPref, mSendPingbacksNested, mReceivePingbacksPref,
mReceivePingbacksNested, mIdentityRequiredPreference, mUserAccountRequiredPref,
mSortByPref, mWhitelistPref, mRelatedPostsPref, mCloseAfterPref, mPagingPref,
mThreadingPref, mMultipleLinksPref, mModerationHoldPref, mBlacklistPref,
mImageWidthPref, mUploadAndLinkPref, mDeleteSitePref
};
for(Preference preference : editablePreference) {
if(preference!=null) preference.setEnabled(enabled);
}
mEditingEnabled = enabled;
}
private void showRelatedPostsDialog() {
DialogFragment relatedPosts = new RelatedPostsDialog();
Bundle args = new Bundle();
args.putBoolean(RelatedPostsDialog.SHOW_RELATED_POSTS_KEY, mSiteSettings.getShowRelatedPosts());
args.putBoolean(RelatedPostsDialog.SHOW_HEADER_KEY, mSiteSettings.getShowRelatedPostHeader());
args.putBoolean(RelatedPostsDialog.SHOW_IMAGES_KEY, mSiteSettings.getShowRelatedPostImages());
relatedPosts.setArguments(args);
relatedPosts.setTargetFragment(this, RELATED_POSTS_REQUEST_CODE);
relatedPosts.show(getFragmentManager(), "related-posts");
}
private void showNumberPickerDialog(Bundle args, int requestCode, String tag) {
showNumberPickerDialog(args, requestCode, tag, null);
}
private void showNumberPickerDialog(Bundle args, int requestCode, String tag, Formatter format) {
NumberPickerDialog dialog = new NumberPickerDialog();
dialog.setNumberFormat(format);
dialog.setArguments(args);
dialog.setTargetFragment(this, requestCode);
dialog.show(getFragmentManager(), tag);
}
private void showPagingDialog() {
Bundle args = new Bundle();
args.putBoolean(NumberPickerDialog.SHOW_SWITCH_KEY, true);
args.putBoolean(NumberPickerDialog.SWITCH_ENABLED_KEY, mSiteSettings.getShouldPageComments());
args.putString(NumberPickerDialog.SWITCH_TITLE_KEY, getString(R.string.site_settings_paging_title));
args.putString(NumberPickerDialog.SWITCH_DESC_KEY, getString(R.string.site_settings_paging_dialog_description));
args.putString(NumberPickerDialog.TITLE_KEY, getString(R.string.site_settings_paging_title));
args.putString(NumberPickerDialog.HEADER_TEXT_KEY, getString(R.string.site_settings_paging_dialog_header));
args.putInt(NumberPickerDialog.MIN_VALUE_KEY, 1);
args.putInt(NumberPickerDialog.MAX_VALUE_KEY, getResources().getInteger(R.integer.paging_limit));
args.putInt(NumberPickerDialog.CUR_VALUE_KEY, mSiteSettings.getPagingCount());
showNumberPickerDialog(args, PAGING_REQUEST_CODE, "paging-dialog");
}
private void showThreadingDialog() {
Bundle args = new Bundle();
args.putBoolean(NumberPickerDialog.SHOW_SWITCH_KEY, true);
args.putBoolean(NumberPickerDialog.SWITCH_ENABLED_KEY, mSiteSettings.getShouldThreadComments());
args.putString(NumberPickerDialog.SWITCH_TITLE_KEY, getString(R.string.site_settings_threading_title));
args.putString(NumberPickerDialog.SWITCH_DESC_KEY, getString(R.string.site_settings_threading_dialog_description));
args.putString(NumberPickerDialog.TITLE_KEY, getString(R.string.site_settings_threading_title));
args.putString(NumberPickerDialog.HEADER_TEXT_KEY, getString(R.string.site_settings_threading_dialog_header));
args.putInt(NumberPickerDialog.MIN_VALUE_KEY, 2);
args.putInt(NumberPickerDialog.MAX_VALUE_KEY, getResources().getInteger(R.integer.threading_limit));
args.putInt(NumberPickerDialog.CUR_VALUE_KEY, mSiteSettings.getThreadingLevels());
showNumberPickerDialog(args, THREADING_REQUEST_CODE, "threading-dialog", new Formatter() {
@Override
public String format(int value) {
return mSiteSettings.getThreadingDescriptionForLevel(value);
}
});
}
private void showExportContentDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.export_your_content);
String email = AccountHelper.getDefaultAccount().getEmail();
builder.setMessage(getString(R.string.export_your_content_message, email));
builder.setPositiveButton(R.string.site_settings_export_content_title, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
AnalyticsUtils.trackWithCurrentBlogDetails(
AnalyticsTracker.Stat.SITE_SETTINGS_EXPORT_SITE_REQUESTED);
exportSite();
}
});
builder.setNegativeButton(R.string.cancel, null);
builder.show();
AnalyticsUtils.trackWithCurrentBlogDetails(
AnalyticsTracker.Stat.SITE_SETTINGS_EXPORT_SITE_ACCESSED);
}
private void dismissProgressDialog(ProgressDialog progressDialog) {
if (progressDialog != null && progressDialog.isShowing()) {
try {
progressDialog.dismiss();
} catch (IllegalArgumentException e) {
// dialog doesn't exist
}
}
}
private void requestPurchasesForDeletionCheck() {
final Blog currentBlog = WordPress.getCurrentBlog();
final ProgressDialog progressDialog = ProgressDialog.show(getActivity(), "", getString(R.string.checking_purchases), true, false);
AnalyticsUtils.trackWithCurrentBlogDetails(
AnalyticsTracker.Stat.SITE_SETTINGS_DELETE_SITE_PURCHASES_REQUESTED);
WordPress.getRestClientUtils().getSitePurchases(currentBlog.getDotComBlogId(), new RestRequest.Listener() {
@Override
public void onResponse(JSONObject response) {
dismissProgressDialog(progressDialog);
if (isAdded()) {
showPurchasesOrDeleteSiteDialog(response, currentBlog);
}
}
}, new RestRequest.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
dismissProgressDialog(progressDialog);
if (isAdded()) {
ToastUtils.showToast(getActivity(), getString(R.string.purchases_request_error));
AppLog.e(AppLog.T.API, "Error occurred while requesting purchases for deletion check: " + error.toString());
}
}
});
}
private void showPurchasesOrDeleteSiteDialog(JSONObject response, final Blog currentBlog) {
try {
JSONArray purchases = response.getJSONArray(PURCHASE_ORIGINAL_RESPONSE_KEY);
if (hasActivePurchases(purchases)) {
showPurchasesDialog(currentBlog);
} else {
showDeleteSiteDialog();
}
} catch (JSONException e) {
AppLog.e(AppLog.T.API, "Error occurred while trying to delete site: " + e.toString());
}
}
private void showPurchasesDialog(final Blog currentBlog) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.premium_upgrades_title);
builder.setMessage(R.string.premium_upgrades_message);
builder.setPositiveButton(R.string.show_purchases, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
AnalyticsUtils.trackWithCurrentBlogDetails(
AnalyticsTracker.Stat.SITE_SETTINGS_DELETE_SITE_PURCHASES_SHOW_CLICKED);
WPWebViewActivity.openUrlByUsingWPCOMCredentials(getActivity(), WORDPRESS_PURCHASES_URL, AccountHelper.getCurrentUsernameForBlog(currentBlog));
}
});
builder.setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
builder.show();
AnalyticsUtils.trackWithCurrentBlogDetails(
AnalyticsTracker.Stat.SITE_SETTINGS_DELETE_SITE_PURCHASES_SHOWN);
}
private boolean hasActivePurchases(JSONArray purchases) throws JSONException {
for (int i = 0; i < purchases.length(); i++) {
JSONObject purchase = purchases.getJSONObject(i);
int active = purchase.getInt(PURCHASE_ACTIVE_KEY);
if (active == 1) {
return true;
}
}
return false;
}
private void showDeleteSiteDialog() {
if (mIsFragmentPaused) return; // Do not show the DeleteSiteDialogFragment if the fragment was paused.
// DialogFragment internally uses commit(), and not commitAllowingStateLoss, crashing the app in case like that.
Bundle args = new Bundle();
args.putString(DeleteSiteDialogFragment.SITE_DOMAIN_KEY, UrlUtils.getHost(mBlog.getHomeURL()));
DeleteSiteDialogFragment deleteSiteDialogFragment = new DeleteSiteDialogFragment();
deleteSiteDialogFragment.setArguments(args);
deleteSiteDialogFragment.setTargetFragment(this, DELETE_SITE_REQUEST_CODE);
deleteSiteDialogFragment.show(getFragmentManager(), DELETE_SITE_TAG);
}
private void showCloseAfterDialog() {
Bundle args = new Bundle();
args.putBoolean(NumberPickerDialog.SHOW_SWITCH_KEY, true);
args.putBoolean(NumberPickerDialog.SWITCH_ENABLED_KEY, mSiteSettings.getShouldCloseAfter());
args.putString(NumberPickerDialog.SWITCH_TITLE_KEY, getString(R.string.site_settings_close_after_dialog_switch_text));
args.putString(NumberPickerDialog.SWITCH_DESC_KEY, getString(R.string.site_settings_close_after_dialog_description));
args.putString(NumberPickerDialog.TITLE_KEY, getString(R.string.site_settings_close_after_dialog_title));
args.putString(NumberPickerDialog.HEADER_TEXT_KEY, getString(R.string.site_settings_close_after_dialog_header));
args.putInt(NumberPickerDialog.MIN_VALUE_KEY, 1);
args.putInt(NumberPickerDialog.MAX_VALUE_KEY, getResources().getInteger(R.integer.close_after_limit));
args.putInt(NumberPickerDialog.CUR_VALUE_KEY, mSiteSettings.getCloseAfter());
showNumberPickerDialog(args, CLOSE_AFTER_REQUEST_CODE, "close-after-dialog");
}
private void showMultipleLinksDialog() {
Bundle args = new Bundle();
args.putBoolean(NumberPickerDialog.SHOW_SWITCH_KEY, false);
args.putString(NumberPickerDialog.TITLE_KEY, getString(R.string.site_settings_multiple_links_title));
args.putInt(NumberPickerDialog.MIN_VALUE_KEY, 0);
args.putInt(NumberPickerDialog.MAX_VALUE_KEY, getResources().getInteger(R.integer.max_links_limit));
args.putInt(NumberPickerDialog.CUR_VALUE_KEY, mSiteSettings.getMultipleLinks());
showNumberPickerDialog(args, MULTIPLE_LINKS_REQUEST_CODE, "multiple-links-dialog");
}
private void setPreferencesFromSiteSettings() {
mLocationPref.setChecked(mSiteSettings.getLocation());
changeEditTextPreferenceValue(mTitlePref, mSiteSettings.getTitle());
changeEditTextPreferenceValue(mTaglinePref, mSiteSettings.getTagline());
changeEditTextPreferenceValue(mAddressPref, mSiteSettings.getAddress());
changeEditTextPreferenceValue(mUsernamePref, mSiteSettings.getUsername());
changeEditTextPreferenceValue(mPasswordPref, mSiteSettings.getPassword());
changeLanguageValue(mSiteSettings.getLanguageCode());
setDetailListPreferenceValue(mPrivacyPref,
String.valueOf(mSiteSettings.getPrivacy()),
mSiteSettings.getPrivacyDescription());
setDetailListPreferenceValue(mImageWidthPref,
mBlog.getMaxImageWidth(),
mBlog.getMaxImageWidth());
setCategories();
setPostFormats();
setAllowComments(mSiteSettings.getAllowComments());
setSendPingbacks(mSiteSettings.getSendPingbacks());
setReceivePingbacks(mSiteSettings.getReceivePingbacks());
setDetailListPreferenceValue(mSortByPref,
String.valueOf(mSiteSettings.getCommentSorting()),
mSiteSettings.getSortingDescription());
int approval = mSiteSettings.getManualApproval() ?
mSiteSettings.getUseCommentWhitelist() ? 0
: -1 : 1;
setDetailListPreferenceValue(mWhitelistPref, String.valueOf(approval), getWhitelistSummary(approval));
String s = StringUtils.getQuantityString(getActivity(), R.string.site_settings_multiple_links_summary_zero,
R.string.site_settings_multiple_links_summary_one,
R.string.site_settings_multiple_links_summary_other, mSiteSettings.getMultipleLinks());
mMultipleLinksPref.setSummary(s);
mUploadAndLinkPref.setChecked(mBlog.isFullSizeImage());
mIdentityRequiredPreference.setChecked(mSiteSettings.getIdentityRequired());
mUserAccountRequiredPref.setChecked(mSiteSettings.getUserAccountRequired());
mThreadingPref.setSummary(mSiteSettings.getThreadingDescription());
mCloseAfterPref.setSummary(mSiteSettings.getCloseAfterDescriptionForPeriod());
mPagingPref.setSummary(mSiteSettings.getPagingDescription());
mRelatedPostsPref.setSummary(mSiteSettings.getRelatedPostsDescription());
mModerationHoldPref.setSummary(mSiteSettings.getModerationHoldDescription());
mBlacklistPref.setSummary(mSiteSettings.getBlacklistDescription());
}
private void setCategories() {
// Ignore if there are no changes
if (mSiteSettings.isSameCategoryList(mCategoryPref.getEntryValues())) {
mCategoryPref.setValue(String.valueOf(mSiteSettings.getDefaultCategory()));
mCategoryPref.setSummary(mSiteSettings.getDefaultCategoryForDisplay());
return;
}
Map<Integer, String> categories = mSiteSettings.getCategoryNames();
CharSequence[] entries = new CharSequence[categories.size()];
CharSequence[] values = new CharSequence[categories.size()];
int i = 0;
for (Integer key : categories.keySet()) {
entries[i] = categories.get(key);
values[i] = String.valueOf(key);
if (key == UNCATEGORIZED_CATEGORY_ID) {
CharSequence temp = entries[0];
entries[0] = entries[i];
entries[i] = temp;
temp = values[0];
values[0] = values[i];
values[i] = temp;
}
++i;
}
mCategoryPref.setEntries(entries);
mCategoryPref.setEntryValues(values);
mCategoryPref.setValue(String.valueOf(mSiteSettings.getDefaultCategory()));
mCategoryPref.setSummary(mSiteSettings.getDefaultCategoryForDisplay());
}
private void setPostFormats() {
// Ignore if there are no changes
if (mSiteSettings.isSameFormatList(mFormatPref.getEntryValues())) {
mFormatPref.setValue(String.valueOf(mSiteSettings.getDefaultPostFormat()));
mFormatPref.setSummary(mSiteSettings.getDefaultPostFormatDisplay());
return;
}
// clone the post formats map
final Map<String, String> postFormats = new HashMap<>(mSiteSettings.getFormats());
// transform the keys and values into arrays and set the ListPreference's data
mFormatPref.setEntries(postFormats.values().toArray(new String[0]));
mFormatPref.setEntryValues(postFormats.keySet().toArray(new String[0]));
mFormatPref.setValue(String.valueOf(mSiteSettings.getDefaultPostFormat()));
mFormatPref.setSummary(mSiteSettings.getDefaultPostFormatDisplay());
}
private void setAllowComments(boolean newValue) {
mSiteSettings.setAllowComments(newValue);
mAllowCommentsPref.setChecked(newValue);
mAllowCommentsNested.setChecked(newValue);
}
private void setSendPingbacks(boolean newValue) {
mSiteSettings.setSendPingbacks(newValue);
mSendPingbacksPref.setChecked(newValue);
mSendPingbacksNested.setChecked(newValue);
}
private void setReceivePingbacks(boolean newValue) {
mSiteSettings.setReceivePingbacks(newValue);
mReceivePingbacksPref.setChecked(newValue);
mReceivePingbacksNested.setChecked(newValue);
}
private void setDetailListPreferenceValue(DetailListPreference pref, String value, String summary) {
pref.setValue(value);
pref.setSummary(summary);
pref.refreshAdapter();
}
/**
* Helper method to perform validation and set multiple properties on an EditTextPreference.
* If newValue is equal to the current preference text no action will be taken.
*/
private void changeEditTextPreferenceValue(EditTextPreference pref, String newValue) {
if (newValue == null || pref == null || pref.getEditText().isInEditMode()) return;
if (!newValue.equals(pref.getSummary())) {
String formattedValue = StringUtils.unescapeHTML(newValue.replaceFirst(ADDRESS_FORMAT_REGEX, ""));
pref.setText(formattedValue);
pref.setSummary(formattedValue);
}
}
/**
* Detail strings for the dialog are generated in the selected language.
*
* @param newValue
* languageCode
*/
private void changeLanguageValue(String newValue) {
if (mLanguagePref == null || newValue == null) return;
if (TextUtils.isEmpty(mLanguagePref.getSummary()) ||
!newValue.equals(mLanguagePref.getValue())) {
mLanguagePref.setValue(newValue);
String summary = WPPrefUtils.getLanguageString(newValue, WPPrefUtils.languageLocale(newValue));
mLanguagePref.setSummary(summary);
mLanguagePref.refreshAdapter();
}
}
private void sortLanguages() {
if (mLanguagePref == null) return;
Pair<String[], String[]> pair = WPPrefUtils.createSortedLanguageDisplayStrings(mLanguagePref.getEntryValues(), WPPrefUtils.languageLocale(null));
if (pair != null) {
String[] sortedEntries = pair.first;
String[] sortedValues = pair.second;
mLanguagePref.setEntries(sortedEntries);
mLanguagePref.setEntryValues(sortedValues);
mLanguagePref.setDetails(WPPrefUtils.createLanguageDetailDisplayStrings(sortedValues));
}
}
private String getWhitelistSummary(int value) {
if (isAdded()) {
switch (value) {
case -1:
return getString(R.string.site_settings_whitelist_none_summary);
case 0:
return getString(R.string.site_settings_whitelist_known_summary);
case 1:
return getString(R.string.site_settings_whitelist_all_summary);
}
}
return "";
}
private void updateWhitelistSettings(int val) {
mSiteSettings.setManualApproval(val == -1);
mSiteSettings.setUseCommentWhitelist(val == 0);
setDetailListPreferenceValue(mWhitelistPref,
String.valueOf(val),
getWhitelistSummary(val));
}
private void showListEditorDialog(int titleRes, int headerRes) {
mDialog = new Dialog(getActivity(), R.style.Calypso_SiteSettingsTheme);
mDialog.setOnDismissListener(this);
mDialog.setContentView(getListEditorView(getString(headerRes)));
mDialog.show();
WPActivityUtils.addToolbarToDialog(this, mDialog, getString(titleRes));
}
private View getListEditorView(String headerText) {
Context themer = new ContextThemeWrapper(getActivity(), R.style.Calypso_SiteSettingsTheme);
View view = View.inflate(themer, R.layout.list_editor, null);
((TextView) view.findViewById(R.id.list_editor_header_text)).setText(headerText);
mAdapter = null;
final EmptyViewRecyclerView list = (EmptyViewRecyclerView) view.findViewById(android.R.id.list);
list.setLayoutManager(
new SmoothScrollLinearLayoutManager(
getActivity(),
LinearLayoutManager.VERTICAL,
false,
getResources().getInteger(android.R.integer.config_mediumAnimTime)
)
);
list.setAdapter(getAdapter());
list.setEmptyView(view.findViewById(R.id.empty_view));
list.addOnItemTouchListener(
new RecyclerViewItemClickListener(
getActivity(),
list,
new RecyclerViewItemClickListener.OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
if (mActionMode != null) {
getAdapter().toggleItemSelected(position);
mActionMode.invalidate();
if (getAdapter().getItemsSelected().size() <= 0) {
mActionMode.finish();
}
}
}
@Override
public void onLongItemClick(View view, int position) {
if (mActionMode == null) {
if (view.isHapticFeedbackEnabled()) {
view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
}
mDialog.getWindow().getDecorView().startActionMode(new ActionModeCallback());
getAdapter().setItemSelected(position);
mActionMode.invalidate();
}
}
}
)
);
view.findViewById(R.id.fab_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AlertDialog.Builder builder =
new AlertDialog.Builder(getActivity(), R.style.Calypso_AlertDialog);
final EditText input = new EditText(getActivity());
WPPrefUtils.layoutAsInput(input);
input.setWidth(getResources().getDimensionPixelSize(R.dimen.list_editor_input_max_width));
input.setHint(R.string.site_settings_list_editor_input_hint);
builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String entry = input.getText().toString();
if (!TextUtils.isEmpty(entry) && !mEditingList.contains(entry)) {
mEditingList.add(entry);
getAdapter().notifyItemInserted(getAdapter().getItemCount() - 1);
list.post(
new Runnable() {
@Override
public void run() {
list.smoothScrollToPosition(getAdapter().getItemCount() - 1);
}
}
);
mSiteSettings.saveSettings();
AnalyticsUtils.trackWithCurrentBlogDetails(
AnalyticsTracker.Stat.SITE_SETTINGS_ADDED_LIST_ITEM);
}
}
});
builder.setNegativeButton(R.string.cancel, null);
final AlertDialog alertDialog = builder.create();
int spacing = getResources().getDimensionPixelSize(R.dimen.dlp_padding_start);
alertDialog.setView(input, spacing, spacing, spacing, 0);
alertDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
alertDialog.getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_VISIBLE);
alertDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
alertDialog.getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_HIDDEN);
}
});
alertDialog.show();
Button positive = alertDialog.getButton(DialogInterface.BUTTON_POSITIVE);
Button negative = alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE);
if (positive != null) WPPrefUtils.layoutAsFlatButton(positive);
if (negative != null) WPPrefUtils.layoutAsFlatButton(negative);
}
});
return view;
}
private void removeBlog() {
if (WordPress.wpDB.deleteBlog(getActivity(), mBlog.getLocalTableBlogId())) {
StatsTable.deleteStatsForBlog(getActivity(), mBlog.getLocalTableBlogId()); // Remove stats data
AnalyticsUtils.refreshMetadata();
ToastUtils.showToast(getActivity(), R.string.blog_removed_successfully);
WordPress.wpDB.deleteLastBlogId();
WordPress.currentBlog = null;
getActivity().setResult(RESULT_BLOG_REMOVED);
// If the last blog is removed and the user is not signed in wpcom, broadcast a UserSignedOut event
if (!AccountHelper.isSignedIn()) {
EventBus.getDefault().post(new CoreEvents.UserSignedOutCompletely());
}
// Checks for stats widgets that were synched with a blog that could be gone now.
StatsWidgetProvider.updateWidgetsOnLogout(getActivity());
getActivity().finish();
} else {
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(getActivity());
dialogBuilder.setTitle(getResources().getText(R.string.error));
dialogBuilder.setMessage(getResources().getText(R.string.could_not_remove_account));
dialogBuilder.setPositiveButton(R.string.ok, null);
dialogBuilder.setCancelable(true);
dialogBuilder.create().show();
}
}
private boolean shouldShowListPreference(DetailListPreference preference) {
return preference != null && preference.getEntries() != null && preference.getEntries().length > 0;
}
private boolean setupMorePreferenceScreen() {
if (mMorePreference == null || !isAdded()) return false;
String title = getString(R.string.site_settings_discussion_title);
Dialog dialog = mMorePreference.getDialog();
if (dialog != null) {
setupPreferenceList((ListView) dialog.findViewById(android.R.id.list), getResources());
WPActivityUtils.addToolbarToDialog(this, dialog, title);
return true;
}
return false;
}
private void removeMoreScreenToolbar() {
if (mMorePreference == null || !isAdded()) return;
Dialog moreDialog = mMorePreference.getDialog();
WPActivityUtils.removeToolbarFromDialog(this, moreDialog);
}
private void hideAdminRequiredPreferences() {
WPPrefUtils.removePreference(this, R.string.pref_key_site_screen, R.string.pref_key_site_general);
WPPrefUtils.removePreference(this, R.string.pref_key_site_screen, R.string.pref_key_site_account);
WPPrefUtils.removePreference(this, R.string.pref_key_site_screen, R.string.pref_key_site_discussion);
WPPrefUtils.removePreference(this, R.string.pref_key_site_writing, R.string.pref_key_site_category);
WPPrefUtils.removePreference(this, R.string.pref_key_site_writing, R.string.pref_key_site_format);
WPPrefUtils.removePreference(this, R.string.pref_key_site_writing, R.string.pref_key_site_related_posts);
}
private void removeDotComOnlyPreferences() {
WPPrefUtils.removePreference(this, R.string.pref_key_site_general, R.string.pref_key_site_language);
WPPrefUtils.removePreference(this, R.string.pref_key_site_writing, R.string.pref_key_site_related_posts);
}
private void removeSelfHostedOnlyPreferences() {
WPPrefUtils.removePreference(this, R.string.pref_key_site_screen, R.string.pref_key_site_account);
WPPrefUtils.removePreference(this, R.string.pref_key_site_screen, R.string.pref_key_site_delete_site_screen);
}
private Preference getChangePref(int id) {
return WPPrefUtils.getPrefAndSetChangeListener(this, id, this);
}
private Preference getClickPref(int id) {
return WPPrefUtils.getPrefAndSetClickListener(this, id, this);
}
private void handleDeleteSiteError() {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.error_deleting_site);
builder.setMessage(R.string.error_deleting_site_summary);
builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
builder.setPositiveButton(R.string.contact_support, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
HelpshiftHelper.getInstance().showConversation(getActivity(), HelpshiftHelper.Tag.ORIGIN_DELETE_SITE);
}
});
builder.show();
}
private void exportSite() {
final Blog currentBlog = WordPress.getCurrentBlog();
if (currentBlog.isDotcomFlag()) {
final ProgressDialog progressDialog = ProgressDialog.show(getActivity(), "", getActivity().getString(R.string.exporting_content_progress), true, true);
WordPress.getRestClientUtils().exportContentAll(currentBlog.getDotComBlogId(), new RestRequest.Listener() {
@Override
public void onResponse(JSONObject response) {
if (isAdded()) {
AnalyticsUtils.trackWithCurrentBlogDetails(
AnalyticsTracker.Stat.SITE_SETTINGS_EXPORT_SITE_RESPONSE_OK);
dismissProgressDialog(progressDialog);
Snackbar.make(getView(), R.string.export_email_sent, Snackbar.LENGTH_LONG).show();
}
}
}, new RestRequest.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
if (isAdded()) {
HashMap<String, Object> errorProperty = new HashMap<>();
errorProperty.put(ANALYTICS_ERROR_PROPERTY_KEY, error.getMessage());
AnalyticsUtils.trackWithCurrentBlogDetails(
AnalyticsTracker.Stat.SITE_SETTINGS_EXPORT_SITE_RESPONSE_ERROR, errorProperty);
dismissProgressDialog(progressDialog);
}
}
});
}
}
private void deleteSite() {
final Blog currentBlog = WordPress.getCurrentBlog();
if (currentBlog.isDotcomFlag()) {
final ProgressDialog progressDialog = ProgressDialog.show(getActivity(), "", getString(R.string.delete_site_progress), true, false);
AnalyticsUtils.trackWithCurrentBlogDetails(
AnalyticsTracker.Stat.SITE_SETTINGS_DELETE_SITE_REQUESTED);
WordPress.getRestClientUtils().deleteSite(currentBlog.getDotComBlogId(), new RestRequest.Listener() {
@Override
public void onResponse(JSONObject response) {
AnalyticsUtils.trackWithCurrentBlogDetails(
AnalyticsTracker.Stat.SITE_SETTINGS_DELETE_SITE_RESPONSE_OK);
progressDialog.dismiss();
removeBlog();
}
}, new RestRequest.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
HashMap<String, Object> errorProperty = new HashMap<>();
errorProperty.put(ANALYTICS_ERROR_PROPERTY_KEY, error.getMessage());
AnalyticsUtils.trackWithCurrentBlogDetails(
AnalyticsTracker.Stat.SITE_SETTINGS_DELETE_SITE_RESPONSE_ERROR, errorProperty);
dismissProgressDialog(progressDialog);
handleDeleteSiteError();
}
});
}
}
private MultiSelectRecyclerViewAdapter getAdapter() {
if (mAdapter == null) {
mAdapter = new MultiSelectRecyclerViewAdapter(getActivity(), mEditingList);
}
return mAdapter;
}
private final class ActionModeCallback implements ActionMode.Callback {
@Override
public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
switch (menuItem.getItemId()) {
case R.id.menu_delete:
SparseBooleanArray checkedItems = getAdapter().getItemsSelected();
HashMap<String, Object> properties = new HashMap<>();
properties.put("num_items_deleted", checkedItems.size());
AnalyticsUtils.trackWithCurrentBlogDetails(AnalyticsTracker.Stat.SITE_SETTINGS_DELETED_LIST_ITEMS, properties);
for (int i = checkedItems.size() - 1; i >= 0; i--) {
final int index = checkedItems.keyAt(i);
if (checkedItems.get(index)) {
mEditingList.remove(index);
}
}
mSiteSettings.saveSettings();
mActionMode.finish();
return true;
case R.id.menu_select_all:
for (int i = 0; i < getAdapter().getItemCount(); i++) {
getAdapter().setItemSelected(i);
}
mActionMode.invalidate();
return true;
default:
return false;
}
}
@Override
public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
WPActivityUtils.setStatusBarColor(mDialog.getWindow(), R.color.action_mode_status_bar_tint);
mActionMode = actionMode;
MenuInflater inflater = actionMode.getMenuInflater();
inflater.inflate(R.menu.list_editor, menu);
return true;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
WPActivityUtils.setStatusBarColor(mDialog.getWindow(), R.color.status_bar_tint);
getAdapter().removeItemsSelected();
mActionMode = null;
}
@Override
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
actionMode.setTitle(getString(
R.string.site_settings_list_editor_action_mode_title,
getAdapter().getItemsSelected().size())
);
return true;
}
}
}