diff options
Diffstat (limited to 'WordPress/src/main/java/org/wordpress/android/ui/prefs/SiteSettingsInterface.java')
-rw-r--r-- | WordPress/src/main/java/org/wordpress/android/ui/prefs/SiteSettingsInterface.java | 871 |
1 files changed, 871 insertions, 0 deletions
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/prefs/SiteSettingsInterface.java b/WordPress/src/main/java/org/wordpress/android/ui/prefs/SiteSettingsInterface.java new file mode 100644 index 000000000..0dc980e2d --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/prefs/SiteSettingsInterface.java @@ -0,0 +1,871 @@ +package org.wordpress.android.ui.prefs; + +import android.app.Activity; +import android.content.Context; +import android.content.SharedPreferences; +import android.database.Cursor; +import android.support.annotation.NonNull; +import android.text.Html; +import android.text.TextUtils; + +import org.wordpress.android.R; +import org.wordpress.android.datasets.SiteSettingsTable; +import org.wordpress.android.models.Blog; +import org.wordpress.android.models.CategoryModel; +import org.wordpress.android.models.SiteSettingsModel; +import org.wordpress.android.util.LanguageUtils; +import org.wordpress.android.util.StringUtils; +import org.wordpress.android.util.WPPrefUtils; +import org.xmlrpc.android.ApiHelper.Method; +import org.xmlrpc.android.ApiHelper.Param; +import org.xmlrpc.android.XMLRPCCallback; +import org.xmlrpc.android.XMLRPCClientInterface; +import org.xmlrpc.android.XMLRPCFactory; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Interface for WordPress (.com and .org) Site Settings. The {@link SiteSettingsModel} class is + * used to store the following settings: + * + * - Title + * - Tagline + * - Address + * - Privacy + * - Language + * - Username (.org only) + * - Password (.org only) + * - Location (local device setting, not saved remotely) + * - Default Category + * - Default Format + * - Related Posts + * - Allow Comments + * - Send Pingbacks + * - Receive Pingbacks + * - Identity Required + * - User Account Required + * - Close Comments After + * - Comment Sort Order + * - Comment Threading + * - Comment Paging + * - Comment User Whitelist + * - Comment Link Limit + * - Comment Moderation Hold Filter + * - Comment Blacklist Filter + * + * This class is marked abstract. This is due to the fact that .org (self-hosted) and .com sites + * expose different API's to query and edit their respective settings (even though the options + * offered by each is roughly the same). To get an instance of this interface class use the + * {@link SiteSettingsInterface#getInterface(Activity, Blog, SiteSettingsListener)} method. It will + * determine which interface ({@link SelfHostedSiteSettings} or {@link DotComSiteSettings}) is + * appropriate for the given blog. + */ + +public abstract class SiteSettingsInterface { + + /** + * Name of the {@link SharedPreferences} that is used to store local settings. + */ + public static final String SITE_SETTINGS_PREFS = "site-settings-prefs"; + + /** + * Key used to access the language preference stored in {@link SharedPreferences}. + */ + public static final String LANGUAGE_PREF_KEY = "site-settings-language-pref"; + + /** + * Key used to access the location preference stored in {@link SharedPreferences}. + */ + public static final String LOCATION_PREF_KEY = "site-settings-location-pref"; + + /** + * Key used to access the default category preference stored in {@link SharedPreferences}. + */ + public static final String DEF_CATEGORY_PREF_KEY = "site-settings-category-pref"; + + /** + * Key used to access the default post format preference stored in {@link SharedPreferences}. + */ + public static final String DEF_FORMAT_PREF_KEY = "site-settings-format-pref"; + + /** + * Identifies an Ascending (oldest to newest) sort order. + */ + public static final int ASCENDING_SORT = 0; + + /** + * Identifies an Descending (newest to oldest) sort order. + */ + public static final int DESCENDING_SORT = 1; + + /** + * Used to prefix keys in an analytics property list. + */ + protected static final String SAVED_ITEM_PREFIX = "item_saved_"; + + /** + * Key for the Standard post format. Used as default if post format is not set/known. + */ + private static final String STANDARD_POST_FORMAT_KEY = "standard"; + + /** + * Standard post format value. Used as default display value if post format is unknown. + */ + private static final String STANDARD_POST_FORMAT = "Standard"; + + /** + * Instantiates the appropriate (self-hosted or .com) SiteSettingsInterface. + */ + public static SiteSettingsInterface getInterface(Activity host, Blog blog, SiteSettingsListener listener) { + if (host == null || blog == null) return null; + + if (blog.isDotcomFlag()) { + return new DotComSiteSettings(host, blog, listener); + } else { + return new SelfHostedSiteSettings(host, blog, listener); + } + } + + /** + * Returns an instance of the {@link this#SITE_SETTINGS_PREFS} {@link SharedPreferences}. + */ + public static SharedPreferences siteSettingsPreferences(Context context) { + return context.getSharedPreferences(SITE_SETTINGS_PREFS, Context.MODE_PRIVATE); + } + + /** + * Gets the geo-tagging value stored in {@link SharedPreferences}, false by default. + */ + public static boolean getGeotagging(Context context) { + return siteSettingsPreferences(context).getBoolean(LOCATION_PREF_KEY, false); + } + + /** + * Gets the default category value stored in {@link SharedPreferences}, 0 by default. + */ + public static String getDefaultCategory(Context context) { + int id = siteSettingsPreferences(context).getInt(DEF_CATEGORY_PREF_KEY, 0); + + if (id != 0) { + CategoryModel category = new CategoryModel(); + Cursor cursor = SiteSettingsTable.getCategory(id); + if (cursor != null && cursor.moveToFirst()) { + category.deserializeFromDatabase(cursor); + return category.name; + } + } + + return ""; + } + + /** + * Gets the default post format value stored in {@link SharedPreferences}, "" by default. + */ + public static String getDefaultFormat(Context context) { + return siteSettingsPreferences(context).getString(DEF_FORMAT_PREF_KEY, ""); + } + + /** + * Thrown when provided credentials are not valid. + */ + public class AuthenticationError extends Exception { } + + /** + * Interface callbacks for settings events. + */ + public interface SiteSettingsListener { + /** + * Called when settings have been updated with remote changes. + * + * @param error + * null if successful + */ + void onSettingsUpdated(Exception error); + + /** + * Called when attempt to update remote settings is finished. + * + * @param error + * null if successful + */ + void onSettingsSaved(Exception error); + + /** + * Called when a request to validate current credentials has completed. + * + * @param error + * null if successful + */ + void onCredentialsValidated(Exception error); + } + + /** + * {@link SiteSettingsInterface} implementations should use this method to start a background + * task to load settings data from a remote source. + */ + protected abstract void fetchRemoteData(); + + protected final Activity mActivity; + protected final Blog mBlog; + protected final SiteSettingsListener mListener; + protected final SiteSettingsModel mSettings; + protected final SiteSettingsModel mRemoteSettings; + + private final Map<String, String> mLanguageCodes; + + protected SiteSettingsInterface(Activity host, Blog blog, SiteSettingsListener listener) { + mActivity = host; + mBlog = blog; + mListener = listener; + mSettings = new SiteSettingsModel(); + mRemoteSettings = new SiteSettingsModel(); + mLanguageCodes = WPPrefUtils.generateLanguageMap(host); + } + + public void saveSettings() { + SiteSettingsTable.saveSettings(mSettings); + siteSettingsPreferences(mActivity).edit().putString(LANGUAGE_PREF_KEY, mSettings.language).apply(); + siteSettingsPreferences(mActivity).edit().putBoolean(LOCATION_PREF_KEY, mSettings.location).apply(); + siteSettingsPreferences(mActivity).edit().putInt(DEF_CATEGORY_PREF_KEY, mSettings.defaultCategory).apply(); + siteSettingsPreferences(mActivity).edit().putString(DEF_FORMAT_PREF_KEY, mSettings.defaultPostFormat).apply(); + } + + public @NonNull String getTitle() { + return mSettings.title == null ? "" : mSettings.title; + } + + public @NonNull String getTagline() { + return mSettings.tagline == null ? "" : mSettings.tagline; + } + + public @NonNull String getAddress() { + return mSettings.address == null ? "" : mSettings.address; + } + + public int getPrivacy() { + return mSettings.privacy; + } + + public @NonNull String getPrivacyDescription() { + if (mActivity != null) { + switch (getPrivacy()) { + case -1: + return mActivity.getString(R.string.site_settings_privacy_private_summary); + case 0: + return mActivity.getString(R.string.site_settings_privacy_hidden_summary); + case 1: + return mActivity.getString(R.string.site_settings_privacy_public_summary); + } + } + return ""; + } + + public @NonNull String getLanguageCode() { + return mSettings.language == null ? "" : mSettings.language; + } + + public @NonNull String getUsername() { + return mSettings.username == null ? "" : mSettings.username; + } + + public @NonNull String getPassword() { + return mSettings.password == null ? "" : mSettings.password; + } + + public boolean getLocation() { + return mSettings.location; + } + + public @NonNull Map<String, String> getFormats() { + if (mSettings.postFormats == null) mSettings.postFormats = new HashMap<>(); + return mSettings.postFormats; + } + + public @NonNull CategoryModel[] getCategories() { + if (mSettings.categories == null) mSettings.categories = new CategoryModel[0]; + return mSettings.categories; + } + + public @NonNull Map<Integer, String> getCategoryNames() { + Map<Integer, String> categoryNames = new HashMap<>(); + if (mSettings.categories != null && mSettings.categories.length > 0) { + for (CategoryModel model : mSettings.categories) { + categoryNames.put(model.id, Html.fromHtml(model.name).toString()); + } + } + + return categoryNames; + } + + public int getDefaultCategory() { + return mSettings.defaultCategory; + } + + public @NonNull String getDefaultCategoryForDisplay() { + for (CategoryModel model : getCategories()) { + if (model != null && model.id == getDefaultCategory()) { + return Html.fromHtml(model.name).toString(); + } + } + + return ""; + } + + public @NonNull String getDefaultPostFormat() { + if (TextUtils.isEmpty(mSettings.defaultPostFormat) || !getFormats().containsKey(mSettings.defaultPostFormat)) { + mSettings.defaultPostFormat = STANDARD_POST_FORMAT_KEY; + } + return mSettings.defaultPostFormat; + } + + public @NonNull String getDefaultPostFormatDisplay() { + String defaultFormat = getFormats().get(getDefaultPostFormat()); + if (TextUtils.isEmpty(defaultFormat)) defaultFormat = STANDARD_POST_FORMAT; + return defaultFormat; + } + + public boolean getShowRelatedPosts() { + return mSettings.showRelatedPosts; + } + + public boolean getShowRelatedPostHeader() { + return mSettings.showRelatedPostHeader; + } + + public boolean getShowRelatedPostImages() { + return mSettings.showRelatedPostImages; + } + + public @NonNull String getRelatedPostsDescription() { + if (mActivity == null) return ""; + String desc = mActivity.getString(getShowRelatedPosts() ? R.string.on : R.string.off); + return StringUtils.capitalize(desc); + } + + public boolean getAllowComments() { + return mSettings.allowComments; + } + + public boolean getSendPingbacks() { + return mSettings.sendPingbacks; + } + + public boolean getReceivePingbacks() { + return mSettings.receivePingbacks; + } + + public boolean getShouldCloseAfter() { + return mSettings.shouldCloseAfter; + } + + public int getCloseAfter() { + return mSettings.closeCommentAfter; + } + + public @NonNull String getCloseAfterDescriptionForPeriod() { + return getCloseAfterDescriptionForPeriod(getCloseAfter()); + } + + public int getCloseAfterPeriodForDescription() { + return !getShouldCloseAfter() ? 0 : getCloseAfter(); + } + + public @NonNull String getCloseAfterDescription() { + return getCloseAfterDescriptionForPeriod(getCloseAfterPeriodForDescription()); + } + + public @NonNull String getCloseAfterDescriptionForPeriod(int period) { + if (mActivity == null) return ""; + + if (!getShouldCloseAfter()) return mActivity.getString(R.string.never); + + return StringUtils.getQuantityString(mActivity, R.string.never, R.string.days_quantity_one, + R.string.days_quantity_other, period); + } + + public int getCommentSorting() { + return mSettings.sortCommentsBy; + } + + public @NonNull String getSortingDescription() { + if (mActivity == null) return ""; + + int order = getCommentSorting(); + switch (order) { + case SiteSettingsInterface.ASCENDING_SORT: + return mActivity.getString(R.string.oldest_first); + case SiteSettingsInterface.DESCENDING_SORT: + return mActivity.getString(R.string.newest_first); + default: + return mActivity.getString(R.string.unknown); + } + } + + public boolean getShouldThreadComments() { + return mSettings.shouldThreadComments; + } + + public int getThreadingLevels() { + return mSettings.threadingLevels; + } + + public int getThreadingLevelsForDescription() { + return !getShouldThreadComments() ? 1 : getThreadingLevels(); + } + + public @NonNull String getThreadingDescription() { + return getThreadingDescriptionForLevel(getThreadingLevelsForDescription()); + } + + public @NonNull String getThreadingDescriptionForLevel(int level) { + if (mActivity == null) return ""; + + if (level <= 1) return mActivity.getString(R.string.none); + return String.format(mActivity.getString(R.string.site_settings_threading_summary), level); + } + + public boolean getShouldPageComments() { + return mSettings.shouldPageComments; + } + + public int getPagingCount() { + return mSettings.commentsPerPage; + } + + public int getPagingCountForDescription() { + return !getShouldPageComments() ? 0 : getPagingCount(); + } + + public @NonNull String getPagingDescription() { + if (mActivity == null) return ""; + + if (!getShouldPageComments()) { + return mActivity.getString(R.string.disabled); + } + + int count = getPagingCountForDescription(); + return StringUtils.getQuantityString(mActivity, R.string.none, R.string.site_settings_paging_summary_one, + R.string.site_settings_paging_summary_other, count); + } + + public boolean getManualApproval() { + return mSettings.commentApprovalRequired; + } + + public boolean getIdentityRequired() { + return mSettings.commentsRequireIdentity; + } + + public boolean getUserAccountRequired() { + return mSettings.commentsRequireUserAccount; + } + + public boolean getUseCommentWhitelist() { + return mSettings.commentAutoApprovalKnownUsers; + } + + public int getMultipleLinks() { + return mSettings.maxLinks; + } + + public @NonNull List<String> getModerationKeys() { + if (mSettings.holdForModeration == null) mSettings.holdForModeration = new ArrayList<>(); + return mSettings.holdForModeration; + } + + public @NonNull String getModerationHoldDescription() { + return getKeysDescription(getModerationKeys().size()); + } + + public @NonNull List<String> getBlacklistKeys() { + if (mSettings.blacklist == null) mSettings.blacklist = new ArrayList<>(); + return mSettings.blacklist; + } + + public @NonNull String getBlacklistDescription() { + return getKeysDescription(getBlacklistKeys().size()); + } + + public @NonNull String getKeysDescription(int count) { + if (mActivity == null) return ""; + + return StringUtils.getQuantityString(mActivity, R.string.site_settings_list_editor_no_items_text, + R.string.site_settings_list_editor_summary_one, + R.string.site_settings_list_editor_summary_other, count); + + } + + public void setTitle(String title) { + mSettings.title = title; + } + + public void setTagline(String tagline) { + mSettings.tagline = tagline; + } + + public void setAddress(String address) { + mSettings.address = address; + } + + public void setPrivacy(int privacy) { + mSettings.privacy = privacy; + } + + public boolean setLanguageCode(String languageCode) { + if (!mLanguageCodes.containsKey(languageCode) || + TextUtils.isEmpty(mLanguageCodes.get(languageCode))) return false; + mSettings.language = languageCode; + mSettings.languageId = Integer.valueOf(mLanguageCodes.get(languageCode)); + return true; + } + + public void setLanguageId(int languageId) { + // want to prevent O(n) language code lookup if there is no change + if (mSettings.languageId != languageId) { + mSettings.languageId = languageId; + mSettings.language = languageIdToLanguageCode(Integer.toString(languageId)); + } + } + + public void setUsername(String username) { + mSettings.username = username; + } + + public void setPassword(String password) { + mSettings.password = password; + } + + public void setLocation(boolean location) { + mSettings.location = location; + } + + public void setAllowComments(boolean allowComments) { + mSettings.allowComments = allowComments; + } + + public void setSendPingbacks(boolean sendPingbacks) { + mSettings.sendPingbacks = sendPingbacks; + } + + public void setReceivePingbacks(boolean receivePingbacks) { + mSettings.receivePingbacks = receivePingbacks; + } + + public void setShouldCloseAfter(boolean shouldCloseAfter) { + mSettings.shouldCloseAfter = shouldCloseAfter; + } + + public void setCloseAfter(int period) { + mSettings.closeCommentAfter = period; + } + + public void setCommentSorting(int method) { + mSettings.sortCommentsBy = method; + } + + public void setShouldThreadComments(boolean shouldThread) { + mSettings.shouldThreadComments = shouldThread; + } + + public void setThreadingLevels(int levels) { + mSettings.threadingLevels = levels; + } + + public void setShouldPageComments(boolean shouldPage) { + mSettings.shouldPageComments= shouldPage; + } + + public void setPagingCount(int count) { + mSettings.commentsPerPage = count; + } + + public void setManualApproval(boolean required) { + mSettings.commentApprovalRequired = required; + } + + public void setIdentityRequired(boolean required) { + mSettings.commentsRequireIdentity = required; + } + + public void setUserAccountRequired(boolean required) { + mSettings.commentsRequireUserAccount = required; + } + + public void setUseCommentWhitelist(boolean useWhitelist) { + mSettings.commentAutoApprovalKnownUsers = useWhitelist; + } + + public void setMultipleLinks(int count) { + mSettings.maxLinks = count; + } + + public void setModerationKeys(List<String> keys) { + mSettings.holdForModeration = keys; + } + + public void setBlacklistKeys(List<String> keys) { + mSettings.blacklist = keys; + } + + public void setDefaultCategory(int category) { + mSettings.defaultCategory = category; + } + + /** + * Sets the default post format. + * + * @param format + * if null or empty default format is set to {@link SiteSettingsInterface#STANDARD_POST_FORMAT_KEY} + */ + public void setDefaultFormat(String format) { + if (TextUtils.isEmpty(format)) { + mSettings.defaultPostFormat = STANDARD_POST_FORMAT_KEY; + } else { + mSettings.defaultPostFormat = format.toLowerCase(); + } + } + + public void setShowRelatedPosts(boolean relatedPosts) { + mSettings.showRelatedPosts = relatedPosts; + } + + public void setShowRelatedPostHeader(boolean showHeader) { + mSettings.showRelatedPostHeader = showHeader; + } + + public void setShowRelatedPostImages(boolean showImages) { + mSettings.showRelatedPostImages = showImages; + } + + /** + * Determines if the current Moderation Hold list contains a given value. + */ + public boolean moderationHoldListContains(String value) { + return getModerationKeys().contains(value); + } + + /** + * Determines if the current Blacklist list contains a given value. + */ + public boolean blacklistListContains(String value) { + return getBlacklistKeys().contains(value); + } + + /** + * Checks if the provided list of post format IDs is the same (order dependent) as the current + * list of Post Formats in the local settings object. + * + * @param ids + * an array of post format IDs + * @return + * true unless the provided IDs are different from the current IDs or in a different order + */ + public boolean isSameFormatList(CharSequence[] ids) { + if (ids == null) return mSettings.postFormats == null; + if (mSettings.postFormats == null || ids.length != mSettings.postFormats.size()) return false; + + String[] keys = mSettings.postFormats.keySet().toArray(new String[mSettings.postFormats.size()]); + for (int i = 0; i < ids.length; ++i) { + if (!keys[i].equals(ids[i])) return false; + } + + return true; + } + + /** + * Checks if the provided list of category IDs is the same (order dependent) as the current + * list of Categories in the local settings object. + * + * @param ids + * an array of integers stored as Strings (for convenience) + * @return + * true unless the provided IDs are different from the current IDs or in a different order + */ + public boolean isSameCategoryList(CharSequence[] ids) { + if (ids == null) return mSettings.categories == null; + if (mSettings.categories == null || ids.length != mSettings.categories.length) return false; + + for (int i = 0; i < ids.length; ++i) { + if (Integer.valueOf(ids[i].toString()) != mSettings.categories[i].id) return false; + } + + return true; + } + + /** + * Needed so that subclasses can be created before initializing. The final member variables + * are null until object has been created so XML-RPC callbacks will not run. + * + * @return + * returns itself for the convenience of + * {@link SiteSettingsInterface#getInterface(Activity, Blog, SiteSettingsListener)} + */ + public SiteSettingsInterface init(boolean fetchRemote) { + loadCachedSettings(); + + if (fetchRemote) { + fetchRemoteData(); + fetchPostFormats(); + } + + return this; + } + + /** + * If there is a change in verification status the listener is notified. + */ + protected void credentialsVerified(boolean valid) { + Exception e = valid ? null : new AuthenticationError(); + if (mSettings.hasVerifiedCredentials != valid) notifyCredentialsVerifiedOnUiThread(e); + mRemoteSettings.hasVerifiedCredentials = mSettings.hasVerifiedCredentials = valid; + } + + /** + * Helper method to create an XML-RPC interface for the current blog. + */ + protected XMLRPCClientInterface instantiateInterface() { + if (mBlog == null) return null; + return XMLRPCFactory.instantiate(mBlog.getUri(), mBlog.getHttpuser(), mBlog.getHttppassword()); + } + + /** + * Language IDs, used only by WordPress, are integer values that map to a language code. + * https://github.com/Automattic/calypso-pre-oss/blob/72c2029b0805a73b749a2b64dd1d8655cae528d0/config/production.json#L86-L227 + * + * Language codes are unique two-letter identifiers defined by ISO 639-1. Region dialects can + * be defined by appending a -** where ** is the region code (en-GB -> English, Great Britain). + * https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes + */ + protected String languageIdToLanguageCode(String id) { + if (id != null) { + for (String key : mLanguageCodes.keySet()) { + if (id.equals(mLanguageCodes.get(key))) { + return key; + } + } + } + + return ""; + } + + /** + * Need to defer loading the cached settings to a thread so it completes after initialization. + */ + private void loadCachedSettings() { + Cursor localSettings = SiteSettingsTable.getSettings(mBlog.getRemoteBlogId()); + + if (localSettings != null) { + Map<Integer, CategoryModel> cachedModels = SiteSettingsTable.getAllCategories(); + mSettings.deserializeOptionsDatabaseCursor(localSettings, cachedModels); + mSettings.language = languageIdToLanguageCode(Integer.toString(mSettings.languageId)); + if (mSettings.language == null) { + setLanguageCode(LanguageUtils.getPatchedCurrentDeviceLanguage(null)); + } + mRemoteSettings.language = mSettings.language; + mRemoteSettings.languageId = mSettings.languageId; + mRemoteSettings.location = mSettings.location; + localSettings.close(); + notifyUpdatedOnUiThread(null); + } else { + mSettings.isInLocalTable = false; + setAddress(mBlog.getHomeURL()); + setUsername(mBlog.getUsername()); + setPassword(mBlog.getPassword()); + setTitle(mBlog.getBlogName()); + } + } + + /** + * Gets available post formats via XML-RPC. Since both self-hosted and .com sites retrieve the + * format list via XML-RPC there is no need to implement this in the sub-classes. + */ + private void fetchPostFormats() { + XMLRPCClientInterface client = instantiateInterface(); + if (client == null) return; + + Map<String, String> args = new HashMap<>(); + args.put(Param.SHOW_SUPPORTED_POST_FORMATS, "true"); + Object[] params = { mBlog.getRemoteBlogId(), mBlog.getUsername(), + mBlog.getPassword(), args}; + client.callAsync(new XMLRPCCallback() { + @Override + public void onSuccess(long id, Object result) { + credentialsVerified(true); + + if (result != null && result instanceof HashMap) { + Map<?, ?> resultMap = (HashMap<?, ?>) result; + Map allFormats; + Object[] supportedFormats; + if (resultMap.containsKey("supported")) { + allFormats = (Map) resultMap.get("all"); + supportedFormats = (Object[]) resultMap.get("supported"); + } else { + allFormats = resultMap; + supportedFormats = allFormats.keySet().toArray(); + } + + mRemoteSettings.postFormats = new HashMap<>(); + mRemoteSettings.postFormats.put("standard", "Standard"); + for (Object supportedFormat : supportedFormats) { + if (allFormats.containsKey(supportedFormat)) { + mRemoteSettings.postFormats.put(supportedFormat.toString(), allFormats.get(supportedFormat).toString()); + } + } + mSettings.postFormats = new HashMap<>(mRemoteSettings.postFormats); + SiteSettingsTable.saveSettings(mSettings); + + notifyUpdatedOnUiThread(null); + } + } + + @Override + public void onFailure(long id, Exception error) { + } + }, Method.GET_POST_FORMATS, params); + } + + /** + * Notifies listener that credentials have been validated or are incorrect. + */ + private void notifyCredentialsVerifiedOnUiThread(final Exception error) { + if (mActivity == null || mListener == null) return; + + mActivity.runOnUiThread(new Runnable() { + @Override + public void run() { + mListener.onCredentialsValidated(error); + } + }); + } + + /** + * Notifies listener that settings have been updated with the latest remote data. + */ + protected void notifyUpdatedOnUiThread(final Exception error) { + if (mActivity == null || mActivity.isFinishing() || mListener == null) return; + + mActivity.runOnUiThread(new Runnable() { + @Override + public void run() { + mListener.onSettingsUpdated(error); + } + }); + } + + /** + * Notifies listener that settings have been saved or an error occurred while saving. + */ + protected void notifySavedOnUiThread(final Exception error) { + if (mActivity == null || mListener == null) return; + + mActivity.runOnUiThread(new Runnable() { + @Override + public void run() { + mListener.onSettingsSaved(error); + } + }); + } +} |