package org.wordpress.android.ui.prefs; import android.os.AsyncTask; import android.os.Bundle; import android.preference.Preference; import android.preference.PreferenceFragment; import android.support.design.widget.CoordinatorLayout; import android.support.design.widget.Snackbar; import android.support.v4.content.ContextCompat; import android.text.InputType; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; 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.AccountActionBuilder; import org.wordpress.android.fluxc.model.AccountModel; import org.wordpress.android.fluxc.model.SiteModel; import org.wordpress.android.fluxc.store.AccountStore; import org.wordpress.android.fluxc.store.AccountStore.OnAccountChanged; import org.wordpress.android.fluxc.store.AccountStore.PushAccountSettingsPayload; import org.wordpress.android.fluxc.store.SiteStore; import org.wordpress.android.util.NetworkUtils; import org.wordpress.android.util.SiteUtils; import org.wordpress.android.util.StringUtils; import org.wordpress.android.util.ToastUtils; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import javax.inject.Inject; @SuppressWarnings("deprecation") public class AccountSettingsFragment extends PreferenceFragment implements Preference.OnPreferenceChangeListener { private Preference mUsernamePreference; private EditTextPreferenceWithValidation mEmailPreference; private DetailListPreference mPrimarySitePreference; private EditTextPreferenceWithValidation mWebAddressPreference; private Snackbar mEmailSnackbar; @Inject Dispatcher mDispatcher; @Inject AccountStore mAccountStore; @Inject SiteStore mSiteStore; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ((WordPress) getActivity().getApplication()).component().inject(this); setRetainInstance(true); addPreferencesFromResource(R.xml.account_settings); mUsernamePreference = findPreference(getString(R.string.pref_key_username)); mEmailPreference = (EditTextPreferenceWithValidation) findPreference(getString(R.string.pref_key_email)); mPrimarySitePreference = (DetailListPreference) findPreference(getString(R.string.pref_key_primary_site)); mWebAddressPreference = (EditTextPreferenceWithValidation) findPreference(getString(R.string.pref_key_web_address)); mEmailPreference.getEditText().setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS); mEmailPreference.setValidationType(EditTextPreferenceWithValidation.ValidationType.EMAIL); mWebAddressPreference.getEditText().setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_URI); mWebAddressPreference.setValidationType(EditTextPreferenceWithValidation.ValidationType.URL); mWebAddressPreference.setDialogMessage(R.string.web_address_dialog_hint); mEmailPreference.setOnPreferenceChangeListener(this); mPrimarySitePreference.setOnPreferenceChangeListener(this); mWebAddressPreference.setOnPreferenceChangeListener(this); // load site list asynchronously new LoadSitesTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View coordinatorView = inflater.inflate(R.layout.preference_coordinator, container, false); CoordinatorLayout coordinator = (CoordinatorLayout) coordinatorView.findViewById(R.id.coordinator); View preferenceView = super.onCreateView(inflater, coordinator, savedInstanceState); coordinator.addView(preferenceView); return coordinatorView; } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); refreshAccountDetails(); } @Override public void onResume() { super.onResume(); if (NetworkUtils.isNetworkAvailable(getActivity())) { mDispatcher.dispatch(AccountActionBuilder.newFetchSettingsAction()); } } @Override public void onStart() { super.onStart(); mDispatcher.register(this); } @Override public void onStop() { mDispatcher.unregister(this); super.onStop(); } @Override public boolean onPreferenceChange(Preference preference, Object newValue) { if (newValue == null) return false; if (preference == mEmailPreference) { updateEmail(newValue.toString()); showPendingEmailChangeSnackbar(newValue.toString()); mEmailPreference.setEnabled(false); return false; } else if (preference == mPrimarySitePreference) { changePrimaryBlogPreference(Long.parseLong(newValue.toString())); updatePrimaryBlog(newValue.toString()); return false; } else if (preference == mWebAddressPreference) { mWebAddressPreference.setSummary(newValue.toString()); updateWebAddress(newValue.toString()); return false; } return true; } public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: getActivity().finish(); } return super.onOptionsItemSelected(item); } private void refreshAccountDetails() { AccountModel account = mAccountStore.getAccount(); mUsernamePreference.setSummary(account.getUserName()); mEmailPreference.setSummary(account.getEmail()); mWebAddressPreference.setSummary(account.getWebAddress()); changePrimaryBlogPreference(account.getPrimarySiteId()); checkIfEmailChangeIsPending(); } private void checkIfEmailChangeIsPending() { AccountModel account = mAccountStore.getAccount(); if (account.getPendingEmailChange()) { showPendingEmailChangeSnackbar(account.getNewEmail()); } else if (mEmailSnackbar != null && mEmailSnackbar.isShown()){ mEmailSnackbar.dismiss(); } mEmailPreference.setEnabled(!account.getPendingEmailChange()); } private void showPendingEmailChangeSnackbar(String newEmail) { if (getView() != null) { if (mEmailSnackbar == null || !mEmailSnackbar.isShown()) { View.OnClickListener clickListener = new View.OnClickListener() { @Override public void onClick(View v) { cancelPendingEmailChange(); } }; mEmailSnackbar = Snackbar .make(getView(), "", Snackbar.LENGTH_INDEFINITE).setAction(getString(R.string.button_revert), clickListener); mEmailSnackbar.getView().setBackgroundColor(ContextCompat.getColor(getActivity(), R.color.grey_dark)); mEmailSnackbar.setActionTextColor(ContextCompat.getColor(getActivity(), R.color.blue_medium)); TextView textView = (TextView) mEmailSnackbar.getView().findViewById(android.support.design.R.id.snackbar_text); textView.setMaxLines(4); } // instead of creating a new snackbar, update the current one to avoid the jumping animation mEmailSnackbar.setText(getString(R.string.pending_email_change_snackbar, newEmail)); if (!mEmailSnackbar.isShown()) { mEmailSnackbar.show(); } } } private void changePrimaryBlogPreference(long siteRemoteId) { mPrimarySitePreference.setValue(String.valueOf(siteRemoteId)); SiteModel site = mSiteStore.getSiteBySiteId(siteRemoteId); if (site != null) { mPrimarySitePreference.setSummary(StringUtils.unescapeHTML(SiteUtils.getSiteNameOrHomeURL(site))); mPrimarySitePreference.refreshAdapter(); } } private void cancelPendingEmailChange() { PushAccountSettingsPayload payload = new PushAccountSettingsPayload(); payload.params = new HashMap<>(); payload.params.put("user_email_change_pending", "false"); mDispatcher.dispatch(AccountActionBuilder.newPushSettingsAction(payload)); if (mEmailSnackbar != null && mEmailSnackbar.isShown()) { mEmailSnackbar.dismiss(); } } private void updateEmail(String newEmail) { PushAccountSettingsPayload payload = new PushAccountSettingsPayload(); payload.params = new HashMap<>(); payload.params.put("user_email", newEmail); mDispatcher.dispatch(AccountActionBuilder.newPushSettingsAction(payload)); } private void updatePrimaryBlog(String blogId) { PushAccountSettingsPayload payload = new PushAccountSettingsPayload(); payload.params = new HashMap<>(); payload.params.put("primary_site_ID", blogId); mDispatcher.dispatch(AccountActionBuilder.newPushSettingsAction(payload)); } public void updateWebAddress(String newWebAddress) { PushAccountSettingsPayload payload = new PushAccountSettingsPayload(); payload.params = new HashMap<>(); payload.params.put("user_URL", newWebAddress); mDispatcher.dispatch(AccountActionBuilder.newPushSettingsAction(payload)); } @SuppressWarnings("unused") @Subscribe(threadMode = ThreadMode.MAIN) public void onAccountChanged(OnAccountChanged event) { if (!isAdded()) return; if (event.isError()) { switch (event.error.type) { case SETTINGS_FETCH_ERROR: ToastUtils.showToast(getActivity(), R.string.error_fetch_account_settings, ToastUtils.Duration.LONG); break; case SETTINGS_POST_ERROR: ToastUtils.showToast(getActivity(), R.string.error_post_account_settings, ToastUtils.Duration.LONG); // we optimistically show the email change snackbar, if that request fails, we should remove the snackbar checkIfEmailChangeIsPending(); break; } } else { refreshAccountDetails(); } } public static String[] getSiteNamesFromSites(List<SiteModel> sites) { List<String> blogNames = new ArrayList<>(); for (SiteModel site : sites) { blogNames.add(SiteUtils.getSiteNameOrHomeURL(site)); } return blogNames.toArray(new String[blogNames.size()]); } public static String[] getHomeURLOrHostNamesFromSites(List<SiteModel> sites) { List<String> urls = new ArrayList<>(); for (SiteModel site : sites) { urls.add(SiteUtils.getHomeURLOrHostName(site)); } return urls.toArray(new String[urls.size()]); } public static String[] getSiteIdsFromSites(List<SiteModel> sites) { List<String> ids = new ArrayList<>(); for (SiteModel site : sites) { ids.add(String.valueOf(site.getSiteId())); } return ids.toArray(new String[ids.size()]); } /* * AsyncTask which loads sites from database for primary site preference */ private class LoadSitesTask extends AsyncTask<Void, Void, Void> { @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected void onCancelled() { super.onCancelled(); } @Override protected Void doInBackground(Void... params) { List<SiteModel> sites = mSiteStore.getSitesAccessedViaWPComRest(); mPrimarySitePreference.setEntries(getSiteNamesFromSites(sites)); mPrimarySitePreference.setEntryValues(getSiteIdsFromSites(sites)); mPrimarySitePreference.setDetails(getHomeURLOrHostNamesFromSites(sites)); return null; } @Override protected void onPostExecute(Void results) { super.onPostExecute(results); mPrimarySitePreference.refreshAdapter(); } } }