From fc2d396d039fb844dcbfa9c1aff5ea9eff495e82 Mon Sep 17 00:00:00 2001 From: Stefanos Togkoulidis Date: Fri, 3 Nov 2017 12:34:48 +0200 Subject: [PATCH 01/11] Context instead of Activity in SiteSettingsInterface This way, SiteSettingsInterface can be used by Services as well. --- .../android/ui/prefs/DotComSiteSettings.java | 3 +- .../android/ui/prefs/DotOrgSiteSettings.java | 3 +- .../ui/prefs/SiteSettingsInterface.java | 91 ++++++++++--------- .../wordpress/android/util/WPPrefUtils.java | 7 +- 4 files changed, 58 insertions(+), 46 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/prefs/DotComSiteSettings.java b/WordPress/src/main/java/org/wordpress/android/ui/prefs/DotComSiteSettings.java index 7498ecfd0562..9c7ba8b82b8d 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/prefs/DotComSiteSettings.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/prefs/DotComSiteSettings.java @@ -1,6 +1,7 @@ package org.wordpress.android.ui.prefs; import android.app.Activity; +import android.content.Context; import android.support.annotation.NonNull; import android.text.TextUtils; @@ -91,7 +92,7 @@ class DotComSiteSettings extends SiteSettingsInterface { private Exception mSaveError = null; /** Only instantiated by {@link SiteSettingsInterface}. */ - DotComSiteSettings(Activity host, SiteModel site, SiteSettingsListener listener) { + DotComSiteSettings(Context host, SiteModel site, SiteSettingsListener listener) { super(host, site, listener); } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/prefs/DotOrgSiteSettings.java b/WordPress/src/main/java/org/wordpress/android/ui/prefs/DotOrgSiteSettings.java index 907c39eb6e16..a6450a865de7 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/prefs/DotOrgSiteSettings.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/prefs/DotOrgSiteSettings.java @@ -1,6 +1,7 @@ package org.wordpress.android.ui.prefs; import android.app.Activity; +import android.content.Context; import org.wordpress.android.datasets.SiteSettingsTable; import org.wordpress.android.fluxc.model.SiteModel; @@ -9,7 +10,7 @@ class DotOrgSiteSettings extends SiteSettingsInterface { /** * Only instantiated by {@link SiteSettingsInterface}. */ - DotOrgSiteSettings(Activity host, SiteModel site, SiteSettingsListener listener) { + DotOrgSiteSettings(Context host, SiteModel site, SiteSettingsListener listener) { super(host, site, listener); } 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 index 0d0978a85200..08f2b769de2a 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/prefs/SiteSettingsInterface.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/prefs/SiteSettingsInterface.java @@ -4,6 +4,7 @@ import android.content.Context; import android.content.SharedPreferences; import android.database.Cursor; +import android.os.Handler; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.text.Html; @@ -66,7 +67,7 @@ * 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, SiteModel, SiteSettingsListener)} method. + * {@link SiteSettingsInterface#getInterface(Context, SiteModel, SiteSettingsListener)} method. */ public abstract class SiteSettingsInterface { @@ -125,7 +126,7 @@ public abstract class SiteSettingsInterface { * Instantiates the appropriate (self-hosted or .com) SiteSettingsInterface. */ @Nullable - public static SiteSettingsInterface getInterface(Activity host, SiteModel site, SiteSettingsListener listener) { + public static SiteSettingsInterface getInterface(Context host, SiteModel site, SiteSettingsListener listener) { if (host == null || site == null) return null; if (SiteUtils.isAccessedViaWPComRest(site)) { @@ -193,7 +194,7 @@ public interface SiteSettingsListener { */ protected abstract void fetchRemoteData(); - protected final Activity mActivity; + protected final Context mContext; protected final SiteModel mSite; protected final SiteSettingsListener mListener; protected final SiteSettingsModel mSettings; @@ -205,10 +206,10 @@ public interface SiteSettingsListener { @Inject SiteStore mSiteStore; @Inject Dispatcher mDispatcher; - protected SiteSettingsInterface(Activity host, SiteModel site, SiteSettingsListener listener) { + protected SiteSettingsInterface(Context host, SiteModel site, SiteSettingsListener listener) { ((WordPress) host.getApplicationContext()).component().inject(this); mDispatcher.register(this); - mActivity = host; + mContext = host; mSite = site; mListener = listener; mSettings = new SiteSettingsModel(); @@ -226,9 +227,9 @@ protected void finalize() throws Throwable { public void saveSettings() { SiteSettingsTable.saveSettings(mSettings); - siteSettingsPreferences(mActivity).edit().putString(LANGUAGE_PREF_KEY, mSettings.language).apply(); - siteSettingsPreferences(mActivity).edit().putInt(DEF_CATEGORY_PREF_KEY, mSettings.defaultCategory).apply(); - siteSettingsPreferences(mActivity).edit().putString(DEF_FORMAT_PREF_KEY, mSettings.defaultPostFormat).apply(); + siteSettingsPreferences(mContext).edit().putString(LANGUAGE_PREF_KEY, mSettings.language).apply(); + siteSettingsPreferences(mContext).edit().putInt(DEF_CATEGORY_PREF_KEY, mSettings.defaultCategory).apply(); + siteSettingsPreferences(mContext).edit().putString(DEF_FORMAT_PREF_KEY, mSettings.defaultPostFormat).apply(); } public @NonNull String getTitle() { @@ -248,14 +249,14 @@ public int getPrivacy() { } public @NonNull String getPrivacyDescription() { - if (mActivity != null) { + if (mContext != null) { switch (getPrivacy()) { case -1: - return mActivity.getString(R.string.site_settings_privacy_private_summary); + return mContext.getString(R.string.site_settings_privacy_private_summary); case 0: - return mActivity.getString(R.string.site_settings_privacy_hidden_summary); + return mContext.getString(R.string.site_settings_privacy_hidden_summary); case 1: - return mActivity.getString(R.string.site_settings_privacy_public_summary); + return mContext.getString(R.string.site_settings_privacy_public_summary); } } return ""; @@ -275,8 +276,8 @@ public int getPrivacy() { public @NonNull Map getFormats() { mSettings.postFormats = new HashMap<>(); - String[] postFormatDisplayNames = mActivity.getResources().getStringArray(R.array.post_format_display_names); - String[] postFormatKeys = mActivity.getResources().getStringArray(R.array.post_format_keys); + String[] postFormatDisplayNames = mContext.getResources().getStringArray(R.array.post_format_display_names); + String[] postFormatKeys = mContext.getResources().getStringArray(R.array.post_format_keys); // Add standard post format (only for .com) mSettings.postFormats.put(STANDARD_POST_FORMAT_KEY, STANDARD_POST_FORMAT); // Add default post formats @@ -350,8 +351,8 @@ public boolean getShowRelatedPostImages() { } public @NonNull String getRelatedPostsDescription() { - if (mActivity == null) return ""; - String desc = mActivity.getString(getShowRelatedPosts() ? R.string.on : R.string.off); + if (mContext == null) return ""; + String desc = mContext.getString(getShowRelatedPosts() ? R.string.on : R.string.off); return StringUtils.capitalize(desc); } @@ -388,11 +389,11 @@ public int getCloseAfterPeriodForDescription() { } public @NonNull String getCloseAfterDescriptionForPeriod(int period) { - if (mActivity == null) return ""; + if (mContext == null) return ""; - if (!getShouldCloseAfter()) return mActivity.getString(R.string.never); + if (!getShouldCloseAfter()) return mContext.getString(R.string.never); - return StringUtils.getQuantityString(mActivity, R.string.never, R.string.days_quantity_one, + return StringUtils.getQuantityString(mContext, R.string.never, R.string.days_quantity_one, R.string.days_quantity_other, period); } @@ -401,16 +402,16 @@ public int getCommentSorting() { } public @NonNull String getSortingDescription() { - if (mActivity == null) return ""; + if (mContext == null) return ""; int order = getCommentSorting(); switch (order) { case SiteSettingsInterface.ASCENDING_SORT: - return mActivity.getString(R.string.oldest_first); + return mContext.getString(R.string.oldest_first); case SiteSettingsInterface.DESCENDING_SORT: - return mActivity.getString(R.string.newest_first); + return mContext.getString(R.string.newest_first); default: - return mActivity.getString(R.string.unknown); + return mContext.getString(R.string.unknown); } } @@ -431,10 +432,10 @@ public int getThreadingLevelsForDescription() { } public @NonNull String getThreadingDescriptionForLevel(int level) { - if (mActivity == null) return ""; + if (mContext == null) return ""; - if (level <= 1) return mActivity.getString(R.string.none); - return String.format(mActivity.getString(R.string.site_settings_threading_summary), level); + if (level <= 1) return mContext.getString(R.string.none); + return String.format(mContext.getString(R.string.site_settings_threading_summary), level); } public boolean getShouldPageComments() { @@ -450,14 +451,14 @@ public int getPagingCountForDescription() { } public @NonNull String getPagingDescription() { - if (mActivity == null) return ""; + if (mContext == null) return ""; if (!getShouldPageComments()) { - return mActivity.getString(R.string.disabled); + return mContext.getString(R.string.disabled); } int count = getPagingCountForDescription(); - return StringUtils.getQuantityString(mActivity, R.string.none, R.string.site_settings_paging_summary_one, + return StringUtils.getQuantityString(mContext, R.string.none, R.string.site_settings_paging_summary_one, R.string.site_settings_paging_summary_other, count); } @@ -548,9 +549,9 @@ public boolean getAllowCommentLikes() { } public @NonNull String getKeysDescription(int count) { - if (mActivity == null) return ""; + if (mContext == null) return ""; - return StringUtils.getQuantityString(mActivity, R.string.site_settings_list_editor_no_items_text, + return StringUtils.getQuantityString(mContext, 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); } @@ -928,9 +929,9 @@ private void loadCachedSettings() { * Notifies listener that credentials have been validated or are incorrect. */ private void notifyCredentialsVerifiedOnUiThread(final Exception error) { - if (mActivity == null || mListener == null) return; + if (mContext == null || mListener == null) return; - mActivity.runOnUiThread(new Runnable() { + new Handler().post(new Runnable() { @Override public void run() { mListener.onCredentialsValidated(error); @@ -939,11 +940,13 @@ public void run() { } protected void notifyFetchErrorOnUiThread(final Exception error) { - if (mActivity == null || mActivity.isFinishing() || mListener == null) { + if (mContext == null + || (mContext instanceof Activity && ((Activity) mContext).isFinishing()) + || mListener == null) { return; } - mActivity.runOnUiThread(new Runnable() { + new Handler().post(new Runnable() { @Override public void run() { mListener.onFetchError(error); @@ -952,11 +955,13 @@ public void run() { } protected void notifySaveErrorOnUiThread(final Exception error) { - if (mActivity == null || mActivity.isFinishing() || mListener == null) { + if (mContext == null + || (mContext instanceof Activity && ((Activity) mContext).isFinishing()) + || mListener == null) { return; } - mActivity.runOnUiThread(new Runnable() { + new Handler().post(new Runnable() { @Override public void run() { mListener.onSaveError(error); @@ -968,9 +973,13 @@ public void run() { * Notifies listener that settings have been updated with the latest remote data. */ protected void notifyUpdatedOnUiThread() { - if (mActivity == null || mActivity.isFinishing() || mListener == null) return; + if (mContext == null + || (mContext instanceof Activity && ((Activity) mContext).isFinishing()) + || mListener == null) { + return; + } - mActivity.runOnUiThread(new Runnable() { + new Handler().post(new Runnable() { @Override public void run() { mListener.onSettingsUpdated(); @@ -982,9 +991,9 @@ public void run() { * Notifies listener that settings have been saved or an error occurred while saving. */ protected void notifySavedOnUiThread() { - if (mActivity == null || mListener == null) return; + if (mContext == null || mListener == null) return; - mActivity.runOnUiThread(new Runnable() { + new Handler().post(new Runnable() { @Override public void run() { mListener.onSettingsSaved(); diff --git a/WordPress/src/main/java/org/wordpress/android/util/WPPrefUtils.java b/WordPress/src/main/java/org/wordpress/android/util/WPPrefUtils.java index 955bf7b2b9ec..1f83a9c8028d 100644 --- a/WordPress/src/main/java/org/wordpress/android/util/WPPrefUtils.java +++ b/WordPress/src/main/java/org/wordpress/android/util/WPPrefUtils.java @@ -1,6 +1,7 @@ package org.wordpress.android.util; import android.app.Activity; +import android.content.Context; import android.preference.Preference; import android.preference.PreferenceCategory; import android.preference.PreferenceFragment; @@ -202,9 +203,9 @@ public static Locale languageLocale(String languageCode) { /** * Creates a map from language codes to WordPress language IDs. */ - public static Map generateLanguageMap(Activity activity) { - String[] languageIds = activity.getResources().getStringArray(R.array.lang_ids); - String[] languageCodes = activity.getResources().getStringArray(R.array.language_codes); + public static Map generateLanguageMap(Context context) { + String[] languageIds = context.getResources().getStringArray(R.array.lang_ids); + String[] languageCodes = context.getResources().getStringArray(R.array.language_codes); Map languageMap = new HashMap<>(); for (int i = 0; i < languageIds.length && i < languageCodes.length; ++i) { From 86ffba93e0d26d5d08095a5ad5f3cbd4576ffb3b Mon Sep 17 00:00:00 2001 From: Stefanos Togkoulidis Date: Tue, 24 Oct 2017 16:43:44 +0300 Subject: [PATCH 02/11] Introduce a Service for new-site creation The fragment attaches, detaches and spawns the new-site creation Service, updating its UI to reflect the process's stage. --- WordPress/src/main/AndroidManifest.xml | 6 +- .../java/org/wordpress/android/WordPress.java | 20 ++ .../android/modules/AppComponent.java | 2 + .../android/ui/ActivityLauncher.java | 1 - .../android/ui/accounts/NewBlogActivity.java | 33 +- .../accounts/signup/SiteCreatingFragment.java | 114 ++++++ .../accounts/signup/SiteCreationService.java | 336 ++++++++++++++++++ .../src/main/res/layout/new_blog_activity.xml | 13 +- .../main/res/layout/site_creating_screen.xml | 31 ++ WordPress/src/main/res/values/strings.xml | 7 + .../android/util/AutoForeground.java | 200 +++++++++++ .../wordpress/android/util/WeakHandler.java | 33 ++ 12 files changed, 760 insertions(+), 36 deletions(-) create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/accounts/signup/SiteCreatingFragment.java create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/accounts/signup/SiteCreationService.java create mode 100644 WordPress/src/main/res/layout/site_creating_screen.xml create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForeground.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/WeakHandler.java diff --git a/WordPress/src/main/AndroidManifest.xml b/WordPress/src/main/AndroidManifest.xml index 4b5f8090eede..7ac23b64f1ee 100644 --- a/WordPress/src/main/AndroidManifest.xml +++ b/WordPress/src/main/AndroidManifest.xml @@ -135,7 +135,7 @@ + { + + private static final String ARG_SITE_TITLE = "ARG_SITE_TITLE"; + private static final String ARG_SITE_TAGLINE = "ARG_SITE_TAGLINE"; + private static final String ARG_SITE_SLUG = "ARG_SITE_SLUG"; + private static final String ARG_SITE_THEME = "ARG_SITE_THEME"; + + public enum SiteCreationPhase { + IDLE, + NEW_SITE, + FETCHING_NEW_SITE, + SET_TAGLINE, + SET_THEME, + SUCCESS, + FAILURE + } + + @Inject Dispatcher mDispatcher; + @Inject AccountStore mAccountStore; + @Inject SiteStore mSiteStore; + + private SiteCreationPhase mSiteCreationPhase = SiteCreationPhase.IDLE; + private AutoForeground mAutoForeground = new AutoForeground<>(this); + + private String mSiteTagline; + private String mSiteTheme; + private long mNewSiteRemoteId; + + public static void createSite( + Context context, + String siteTitle, + String siteTagline, + String siteSlug, + String siteTheme) { + Intent intent = new Intent(context, SiteCreationService.class); + intent.putExtra(ARG_SITE_TITLE, siteTitle); + intent.putExtra(ARG_SITE_TAGLINE, siteTagline); + intent.putExtra(ARG_SITE_SLUG, siteSlug); + intent.putExtra(ARG_SITE_THEME, siteTheme); + context.startService(intent); + } + + @Override + public SiteCreationPhase getCurrentState() { + return mSiteCreationPhase; + } + + @Override + public boolean isInProgress(SiteCreationPhase siteCreationPhase) { + return siteCreationPhase != SiteCreationPhase.IDLE + && siteCreationPhase != SiteCreationPhase.SUCCESS + && siteCreationPhase != SiteCreationPhase.FAILURE; + } + + @Override + public boolean isError(SiteCreationPhase siteCreationPhase) { + return siteCreationPhase == SiteCreationPhase.FAILURE; + } + + @Override + public Notification getNotification(SiteCreationPhase siteCreationPhase) { + switch (siteCreationPhase) { + case NEW_SITE: + return getProgressNotification(25, "Site creation in: " + siteCreationPhase.name()); + case FETCHING_NEW_SITE: + return getProgressNotification(50, "Site creation in: " + siteCreationPhase.name()); + case SET_TAGLINE: + return getProgressNotification(75, "Site creation in: " + siteCreationPhase.name()); + case SET_THEME: + return getProgressNotification(100, "Site creation in: " + siteCreationPhase.name()); + case SUCCESS: + return getSuccessNotification("Site created!"); + case FAILURE: + return getFailureNotification("Site creation failed :("); + } + + return null; + } + + private void notifyState(SiteCreationPhase siteCreationPhase) { + mSiteCreationPhase = siteCreationPhase; + mAutoForeground.notifyState(siteCreationPhase); + + if (siteCreationPhase == SiteCreationPhase.FAILURE || siteCreationPhase == SiteCreationPhase.SUCCESS) { + stopSelf(); + } + } + + @Override + public void onCreate() { + super.onCreate(); + ((WordPress) getApplication()).component().inject(this); + + AppLog.i(T.MAIN, "SiteCreationService > Created"); + mDispatcher.register(this); + + // TODO: Recover any site creations that were interrupted by the service being stopped? + } + + @Override + public void onDestroy() { + mDispatcher.unregister(this); + AppLog.i(T.MAIN, "SiteCreationService > Destroyed"); + super.onDestroy(); + } + + @Nullable + @Override + public IBinder onBind(Intent intent) { + return mAutoForeground.getBinder(); + } + + private Intent getPendingIntent() { + Intent intent = new Intent(this, NewBlogActivity.class); +// intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); +// intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + return intent; + } + + private Notification getProgressNotification(int progress, String content) { + return new NotificationCompat.Builder(this) + .setContentTitle(content) + .setSmallIcon(R.mipmap.app_icon) + .setLargeIcon(BitmapFactory.decodeResource(getApplicationContext().getResources(), + R.mipmap.app_icon)) + .setAutoCancel(true) + .setContentIntent(PendingIntent.getActivity(SiteCreationService.this, + AutoForeground.NOTIFICATION_ID_PROGRESS, + getPendingIntent(), + PendingIntent.FLAG_ONE_SHOT)) + .setProgress(100, progress, false) + .build(); + } + + private Notification getSuccessNotification(String content) { + return new NotificationCompat.Builder(this) + .setContentTitle(content) + .setSmallIcon(R.mipmap.app_icon) + .setLargeIcon(BitmapFactory.decodeResource(getApplicationContext().getResources(), + R.mipmap.app_icon)) + .setAutoCancel(true) + .setContentIntent(PendingIntent.getActivity(SiteCreationService.this, + AutoForeground.NOTIFICATION_ID_SUCCESS, + getPendingIntent(), + PendingIntent.FLAG_ONE_SHOT)) + .build(); + } + + private Notification getFailureNotification(String content) { + return new NotificationCompat.Builder(this) + .setContentTitle(content) + .setSmallIcon(R.mipmap.app_icon) + .setLargeIcon(BitmapFactory.decodeResource(getApplicationContext().getResources(), + R.mipmap.app_icon)) + .setAutoCancel(true) + .setContentIntent(PendingIntent.getActivity(SiteCreationService.this, + AutoForeground.NOTIFICATION_ID_FAILURE, + getPendingIntent(), + PendingIntent.FLAG_ONE_SHOT)) + .build(); + } + + @Override + public int onStartCommand(@Nullable Intent intent, int flags, int startId) { + if (intent == null) { + return START_NOT_STICKY; + } + + notifyState(SiteCreationPhase.NEW_SITE); + + final String siteTitle = intent.getStringExtra(ARG_SITE_TITLE); + final String siteSlug = intent.getStringExtra(ARG_SITE_SLUG); + mSiteTagline = intent.getStringExtra(ARG_SITE_TAGLINE); + mSiteTheme = intent.getStringExtra(ARG_SITE_THEME); + + final String language = LanguageUtils.getPatchedCurrentDeviceLanguage(this); + + SiteStore.NewSitePayload newSitePayload =new SiteStore.NewSitePayload( + siteSlug, + siteTitle, + language, + SiteStore.SiteVisibility.PUBLIC, + false); + mDispatcher.dispatch(SiteActionBuilder.newCreateNewSiteAction(newSitePayload)); + AppLog.i(T.NUX, "User tries to create a new site, title: " + siteTitle + ", SiteName: " + siteSlug); + + return START_REDELIVER_INTENT; + } + + private void activateTheme(final SiteModel site, final String themeId) { + WordPress.getRestClientUtils().setTheme(site.getSiteId(), themeId, new RestRequest.Listener() { + @Override + public void onResponse(JSONObject response) { + ThemeTable.setCurrentTheme(WordPress.wpDB.getDatabase(), String.valueOf(site.getSiteId()), themeId); + + notifyState(SiteCreationPhase.SUCCESS); + } + }, new RestRequest.ErrorListener() { + @Override + public void onErrorResponse(VolleyError error) { + notifyState(SiteCreationPhase.FAILURE); +// ToastUtils.showToast(ThemeBrowserActivity.this, R.string.theme_activation_error, +// ToastUtils.Duration.SHORT); + } + }); + } + + // OnChanged events + + @SuppressWarnings("unused") + @Subscribe(threadMode = ThreadMode.MAIN) + public void onNewSiteCreated(SiteStore.OnNewSiteCreated event) { + AppLog.i(T.NUX, event.toString()); + if (event.isError()) { + notifyState(SiteCreationPhase.FAILURE); +// showError(event.error.type, event.error.message); + return; + } + + AnalyticsTracker.track(AnalyticsTracker.Stat.CREATED_SITE); + + notifyState(SiteCreationPhase.FETCHING_NEW_SITE); + + mNewSiteRemoteId = event.newSiteRemoteId; + + // We can't get all the site informations from the new site endpoint, so we have to fetch the site list. + mDispatcher.dispatch(SiteActionBuilder.newFetchSitesAction()); + } + + @SuppressWarnings("unused") + @Subscribe(threadMode = ThreadMode.MAIN) + public void onSiteChanged(SiteStore.OnSiteChanged event) { + AppLog.i(T.NUX, event.toString()); + if (event.isError()) { + // Site has been created but there was a error while fetching the sites. Can happen if we get + // a response including a broken Jetpack site. We can continue and check if the newly created + // site has been fetched. + AppLog.e(T.NUX, event.error.type.toString()); + } + + final SiteModel site = mSiteStore.getSiteBySiteId(mNewSiteRemoteId); + + if (mSiteCreationPhase == SiteCreationPhase.FETCHING_NEW_SITE) { + Intent intent = new Intent(); + if (site == null) { + notifyState(SiteCreationPhase.FAILURE); + // ToastUtils.showToast(getActivity(), R.string.error_fetch_site_after_creation, ToastUtils.Duration.LONG); + return; + } + + notifyState(SiteCreationPhase.SET_TAGLINE); + + SiteSettingsInterface siteSettings = SiteSettingsInterface.getInterface(this, site, + new SiteSettingsInterface.SiteSettingsListener() { + @Override + public void onSaveError(Exception error) { + notifyState(SiteCreationPhase.FAILURE); + } + + @Override + public void onFetchError(Exception error) { + notifyState(SiteCreationPhase.FAILURE); + } + + @Override + public void onSettingsUpdated() { + // we'll just handle onSettingsSaved() + } + + @Override + public void onSettingsSaved() { + notifyState(SiteCreationPhase.SET_THEME); + SiteModel site = mSiteStore.getSiteBySiteId(mNewSiteRemoteId); + activateTheme(site, mSiteTheme); + } + + @Override + public void onCredentialsValidated(Exception error) { + if (error != null) { + notifyState(SiteCreationPhase.FAILURE); + } + } + }); + + if (siteSettings == null) { + notifyState(SiteCreationPhase.FAILURE); + return; + } + + siteSettings.init(false); + siteSettings.setTagline(mSiteTagline); + siteSettings.saveSettings(); + } else if (mSiteCreationPhase == SiteCreationPhase.SET_TAGLINE) { + notifyState(SiteCreationPhase.SET_THEME); + activateTheme(site, mSiteTheme); + } + } +} diff --git a/WordPress/src/main/res/layout/new_blog_activity.xml b/WordPress/src/main/res/layout/new_blog_activity.xml index 8bdf62edb83e..58e55488f85d 100644 --- a/WordPress/src/main/res/layout/new_blog_activity.xml +++ b/WordPress/src/main/res/layout/new_blog_activity.xml @@ -2,13 +2,12 @@ android:id="@+id/main_view" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="@color/nux_background" - android:orientation="vertical"> + android:orientation="vertical" + android:baselineAligned="true"> - + android:layout_height="match_parent"/> - \ No newline at end of file + diff --git a/WordPress/src/main/res/layout/site_creating_screen.xml b/WordPress/src/main/res/layout/site_creating_screen.xml new file mode 100644 index 000000000000..84185c5161af --- /dev/null +++ b/WordPress/src/main/res/layout/site_creating_screen.xml @@ -0,0 +1,31 @@ + + + + + + + + + diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml index 2b1b30aea8cd..eeb6390d954f 100644 --- a/WordPress/src/main/res/values/strings.xml +++ b/WordPress/src/main/res/values/strings.xml @@ -18,6 +18,13 @@ Logging out from your account will remove all of @%s’s WordPress.com data from this device, including local drafts and local changes. This account has two step authentication enabled. Visit your security settings on WordPress.com and generate an application-specific password. + Preparing your site… + Fetching site info… + Setting the tagline… + Setting the theme… + Sorry, failed to properly create your site :( + Success! + Select categories Separate tags with commas diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForeground.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForeground.java new file mode 100644 index 000000000000..d3c361b76797 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForeground.java @@ -0,0 +1,200 @@ +package org.wordpress.android.util; + +import android.app.Notification; +import android.app.Service; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.IBinder; +import android.os.Message; +import android.os.Messenger; +import android.os.RemoteException; +import android.support.annotation.CallSuper; +import android.support.v4.app.NotificationManagerCompat; + +import java.util.ArrayList; + +public class AutoForeground implements WeakHandler.MessageListener { + + public static final int NOTIFICATION_ID_PROGRESS = 1; + public static final int NOTIFICATION_ID_SUCCESS = 2; + public static final int NOTIFICATION_ID_FAILURE = 3; + + public static final int MSG_REGISTER_CLIENT = 1; + public static final int MSG_UNREGISTER_CLIENT = 2; + + public static final int MSG_CURRENT_STATE = 4; + + public static class ServiceClient { + private ServiceConnection mServiceConnection; + private final Messenger mClient; + private Messenger mService; + + public ServiceClient(Context context, Class> clazz, + WeakHandler.MessageListener clientListener) { + mClient = new Messenger(new WeakHandler(clientListener)); + connect(context, clazz); + } + + private void connect(Context context, Class> clazz) { + mServiceConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName componentName, IBinder iBinder) { + mService = new Messenger(iBinder); + registerClient(); + } + + @Override + public void onServiceDisconnected(ComponentName componentName) { + // nothing here + } + }; + + context.bindService(new Intent(context, clazz), mServiceConnection, Context.BIND_AUTO_CREATE); + } + + public void disconnect(Context context) { + unregisterClient(); + + context.unbindService(mServiceConnection); + } + + private void registerClient() { + Message msg = Message.obtain(null, AutoForeground.MSG_REGISTER_CLIENT); + msg.replyTo = mClient; + try { + mService.send(msg); + requestCurrentState(); + } catch (RemoteException e) { + // In this case the service has crashed before we could even + // do anything with it; we can count on soon being + // disconnected (and then reconnected if it can be restarted) + // so there is no need to do anything special here. + e.printStackTrace(); + } + } + + private void unregisterClient() { + Message msg = Message.obtain(null, AutoForeground.MSG_UNREGISTER_CLIENT); + msg.replyTo = mClient; + try { + mService.send(msg); + } catch (RemoteException e) { + // In this case the service has crashed before we could even + // do anything with it; we can count on soon being + // disconnected (and then reconnected if it can be restarted) + // so there is no need to do anything special here. + e.printStackTrace(); + } + } + + public void requestCurrentState() { + Message msg = Message.obtain(null, AutoForeground.MSG_CURRENT_STATE); + msg.replyTo = mClient; + try { + mService.send(msg); + } catch (RemoteException e) { + e.printStackTrace(); + } + } + } + + public interface AutoForegroundListener { + State getCurrentState(); + Notification getNotification(State state); + boolean isInProgress(State state); + boolean isError(State state); + } + + private final AutoForegroundListener mAutoForegroundListener; + private final Service mService; + + private ArrayList mConnectedClients = new ArrayList<>(); + + private final Messenger mMessenger = new Messenger(new WeakHandler(this)); + + public AutoForeground(T service) { + mAutoForegroundListener = service; + mService = service; + } + + @Override + @CallSuper + public boolean handleMessage(Message msg) { + switch (msg.what) { + case MSG_REGISTER_CLIENT: + mConnectedClients.add(msg.replyTo); + background(); + break; + case MSG_UNREGISTER_CLIENT: + mConnectedClients.remove(msg.replyTo); + if (mConnectedClients.size() == 0) { + promoteForeground(); + } + break; + case MSG_CURRENT_STATE: + notifyState(mAutoForegroundListener.getCurrentState()); + break; + default: + return false; + } + + return true; + } + + private boolean notifyConnectedClients(State state) { + int validClients = 0; + + for (int i = mConnectedClients.size() - 1; i >= 0; i--) { + try { + mConnectedClients.get(i).send(Message.obtain(null, MSG_CURRENT_STATE, state)); + validClients++; + } catch (RemoteException e) { + // The client is dead. Remove it from the list; + // we are going through the list from back to front + // so this is safe to do inside the loop. + mConnectedClients.remove(i); + } + } + + return validClients > 0; + } + + public IBinder getBinder() { + return mMessenger.getBinder(); + } + + private void promoteForeground() { + State state = mAutoForegroundListener.getCurrentState(); + if (mAutoForegroundListener.isInProgress(state)) { + mService.startForeground(NOTIFICATION_ID_PROGRESS, mAutoForegroundListener.getNotification(state)); + } + } + + private void background() { + mService.stopForeground(true); + } + + @CallSuper + public void notifyState(State state) { + boolean hasValidClients = false; + if (mConnectedClients.size() > 0) { + hasValidClients = notifyConnectedClients(state); + } + + if (!hasValidClients) { + if (mAutoForegroundListener.isInProgress(state)) { + NotificationManagerCompat.from(mService).notify(NOTIFICATION_ID_PROGRESS, + mAutoForegroundListener.getNotification(state)); + } else { + background(); + NotificationManagerCompat.from(mService).cancel(NOTIFICATION_ID_PROGRESS); + + NotificationManagerCompat.from(mService).notify( + mAutoForegroundListener.isError(state) ? NOTIFICATION_ID_FAILURE : NOTIFICATION_ID_SUCCESS, + mAutoForegroundListener.getNotification(state)); + } + } + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/WeakHandler.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/WeakHandler.java new file mode 100644 index 000000000000..5883b0ab2da5 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/WeakHandler.java @@ -0,0 +1,33 @@ +package org.wordpress.android.util; + +import android.os.Handler; +import android.os.Message; + +import java.lang.ref.WeakReference; + +/** + * Class to wrap a Handler with a WeakReference so we don't leak a context + */ +public class WeakHandler extends Handler { + public interface MessageListener { + boolean handleMessage(Message msg); + } + + private final WeakReference mWeakMessageListener; + + public WeakHandler(MessageListener messageListener) { + mWeakMessageListener = new WeakReference<>(messageListener); + } + + @Override + public void handleMessage(Message msg) { + final MessageListener messageListener = mWeakMessageListener.get(); + if (messageListener == null) { + return; + } + + if (!messageListener.handleMessage(msg)) { + super.handleMessage(msg); + } + } +} From c97620d811f30fe84dc45ffbbddcdf42a9d72932 Mon Sep 17 00:00:00 2001 From: Stefanos Togkoulidis Date: Mon, 6 Nov 2017 09:18:19 +0200 Subject: [PATCH 03/11] Small optimization by using the builder pattern --- .../wordpress/android/ui/prefs/SiteSettingsInterface.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 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 index 08f2b769de2a..4bb72154c07f 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/prefs/SiteSettingsInterface.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/prefs/SiteSettingsInterface.java @@ -227,9 +227,11 @@ protected void finalize() throws Throwable { public void saveSettings() { SiteSettingsTable.saveSettings(mSettings); - siteSettingsPreferences(mContext).edit().putString(LANGUAGE_PREF_KEY, mSettings.language).apply(); - siteSettingsPreferences(mContext).edit().putInt(DEF_CATEGORY_PREF_KEY, mSettings.defaultCategory).apply(); - siteSettingsPreferences(mContext).edit().putString(DEF_FORMAT_PREF_KEY, mSettings.defaultPostFormat).apply(); + siteSettingsPreferences(mContext).edit() + .putString(LANGUAGE_PREF_KEY, mSettings.language) + .putInt(DEF_CATEGORY_PREF_KEY, mSettings.defaultCategory) + .putString(DEF_FORMAT_PREF_KEY, mSettings.defaultPostFormat) + .apply(); } public @NonNull String getTitle() { From 0247fd674513ef2d08a4efd5dc669fe0d87f407a Mon Sep 17 00:00:00 2001 From: Stefanos Togkoulidis Date: Mon, 6 Nov 2017 09:26:09 +0200 Subject: [PATCH 04/11] Let the Listener check Activity finish if needed --- .../android/ui/prefs/SiteSettingsInterface.java | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 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 index 4bb72154c07f..9813ec1ef03b 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/prefs/SiteSettingsInterface.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/prefs/SiteSettingsInterface.java @@ -942,9 +942,7 @@ public void run() { } protected void notifyFetchErrorOnUiThread(final Exception error) { - if (mContext == null - || (mContext instanceof Activity && ((Activity) mContext).isFinishing()) - || mListener == null) { + if (mListener == null) { return; } @@ -957,9 +955,7 @@ public void run() { } protected void notifySaveErrorOnUiThread(final Exception error) { - if (mContext == null - || (mContext instanceof Activity && ((Activity) mContext).isFinishing()) - || mListener == null) { + if (mListener == null) { return; } @@ -975,9 +971,7 @@ public void run() { * Notifies listener that settings have been updated with the latest remote data. */ protected void notifyUpdatedOnUiThread() { - if (mContext == null - || (mContext instanceof Activity && ((Activity) mContext).isFinishing()) - || mListener == null) { + if (mListener == null) { return; } @@ -993,7 +987,9 @@ public void run() { * Notifies listener that settings have been saved or an error occurred while saving. */ protected void notifySavedOnUiThread() { - if (mContext == null || mListener == null) return; + if (mListener == null) { + return; + } new Handler().post(new Runnable() { @Override From 6f6c4b11ca0129c66b5b941357f695a6ef8e60fa Mon Sep 17 00:00:00 2001 From: Stefanos Togkoulidis Date: Fri, 10 Nov 2017 14:49:02 +0200 Subject: [PATCH 05/11] Use EventBus for messaging Note: EventBus doesn't offer a way to listen to registrations/unregistrations so, need to doing it manually via onBind()/onUnbind()/onRebind(). That means that the client needs to bind to the Service *and* to register to EventBus. The ServiceEventConnection class is introduced as a helper to that end. --- .../accounts/signup/SiteCreatingFragment.java | 99 ++++---- .../accounts/signup/SiteCreationService.java | 84 +++---- libs/utils/WordPressUtils/build.gradle | 1 + .../android/util/AutoForeground.java | 211 +++++------------- .../android/util/ServiceEventConnection.java | 36 +++ 5 files changed, 185 insertions(+), 246 deletions(-) create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ServiceEventConnection.java diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/signup/SiteCreatingFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/accounts/signup/SiteCreatingFragment.java index fa71db730af6..03b14ba44e60 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/accounts/signup/SiteCreatingFragment.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/signup/SiteCreatingFragment.java @@ -1,7 +1,6 @@ package org.wordpress.android.ui.accounts.signup; import android.os.Bundle; -import android.os.Message; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v7.app.ActionBar; @@ -12,19 +11,20 @@ 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.analytics.AnalyticsTracker; +import org.wordpress.android.ui.accounts.signup.SiteCreationService.OnSiteCreationStateUpdated; import org.wordpress.android.util.AppLog; import org.wordpress.android.util.AppLog.T; -import org.wordpress.android.util.AutoForeground; -import org.wordpress.android.util.AutoForeground.ServiceClient; -import org.wordpress.android.util.WeakHandler.MessageListener; +import org.wordpress.android.util.ServiceEventConnection; -public class SiteCreatingFragment extends Fragment implements MessageListener { +public class SiteCreatingFragment extends Fragment { public static final String TAG = "site_creating_fragment_tag"; - private ServiceClient mServiceClient; + private ServiceEventConnection mServiceEventConnection; private TextView mLabel; @@ -56,59 +56,54 @@ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { } @Override - public void onPause() { - super.onPause(); + public void onResume() { + super.onResume(); - mServiceClient.disconnect(getContext()); + // connect to the Service. We'll receive updates via EventBus. + mServiceEventConnection = new ServiceEventConnection(getContext(), SiteCreationService.class, this); } @Override - public void onResume() { - super.onResume(); + public void onPause() { + super.onPause(); - mServiceClient = new ServiceClient(getContext(), SiteCreationService.class, this); + // disconnect from the Service + mServiceEventConnection.disconnect(getContext(), this); } - @Override - public boolean handleMessage(Message msg) { - switch (msg.what) { - case AutoForeground.MSG_CURRENT_STATE: - SiteCreationService.SiteCreationPhase state = (SiteCreationService.SiteCreationPhase) msg.obj; - AppLog.i(T.NUX, "Received state: " + state.name()); - - switch (state) { - case IDLE: - SiteCreationService.createSite(getActivity(), - WordPress.getBuildConfigString(getActivity(), "DEBUG_DOTCOM_NEW_SITE_TITLE"), - WordPress.getBuildConfigString(getActivity(), "DEBUG_DOTCOM_NEW_SITE_TAGLINE"), - WordPress.getBuildConfigString(getActivity(), "DEBUG_DOTCOM_NEW_SITE_SLUG"), - WordPress.getBuildConfigString(getActivity(), "DEBUG_DOTCOM_NEW_SITE_THEME")); - - mLabel.setText(R.string.site_creating_label); - break; - case NEW_SITE: - // nothing special to do here, just waiting for the site creation result... - break; - case FETCHING_NEW_SITE: - mLabel.setText(R.string.site_creating_fetching_info); - break; - case SET_TAGLINE: - mLabel.setText(R.string.site_creating_set_tagline); - break; - case SET_THEME: - mLabel.setText(R.string.site_creating_set_theme); - break; - case FAILURE: - mLabel.setText(R.string.site_creating_failed); - break; - case SUCCESS: - mLabel.setText(R.string.site_creating_success); - break; - } - - return true; + @SuppressWarnings("unused") + @Subscribe(threadMode = ThreadMode.MAIN) + public void onSiteCreationPhaseUpdated(OnSiteCreationStateUpdated event) { + AppLog.i(T.NUX, "Received state: " + event.state.name()); + + switch (event.state) { + case IDLE: + SiteCreationService.createSite(getActivity(), + WordPress.getBuildConfigString(getActivity(), "DEBUG_DOTCOM_NEW_SITE_TITLE"), + WordPress.getBuildConfigString(getActivity(), "DEBUG_DOTCOM_NEW_SITE_TAGLINE"), + WordPress.getBuildConfigString(getActivity(), "DEBUG_DOTCOM_NEW_SITE_SLUG"), + WordPress.getBuildConfigString(getActivity(), "DEBUG_DOTCOM_NEW_SITE_THEME")); + + mLabel.setText(R.string.site_creating_label); + break; + case NEW_SITE: + // nothing special to do here, just waiting for the site creation result... + break; + case FETCHING_NEW_SITE: + mLabel.setText(R.string.site_creating_fetching_info); + break; + case SET_TAGLINE: + mLabel.setText(R.string.site_creating_set_tagline); + break; + case SET_THEME: + mLabel.setText(R.string.site_creating_set_theme); + break; + case FAILURE: + mLabel.setText(R.string.site_creating_failed); + break; + case SUCCESS: + mLabel.setText(R.string.site_creating_success); + break; } - - return false; } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/signup/SiteCreationService.java b/WordPress/src/main/java/org/wordpress/android/ui/accounts/signup/SiteCreationService.java index 52382974c737..2ce569f1ef89 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/accounts/signup/SiteCreationService.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/signup/SiteCreationService.java @@ -2,11 +2,9 @@ import android.app.Notification; import android.app.PendingIntent; -import android.app.Service; import android.content.Context; import android.content.Intent; import android.graphics.BitmapFactory; -import android.os.IBinder; import android.support.annotation.Nullable; import android.support.v4.app.NotificationCompat; @@ -26,17 +24,16 @@ import org.wordpress.android.fluxc.store.AccountStore; import org.wordpress.android.fluxc.store.SiteStore; import org.wordpress.android.ui.accounts.NewBlogActivity; -import org.wordpress.android.ui.accounts.signup.SiteCreationService.SiteCreationPhase; +import org.wordpress.android.ui.accounts.signup.SiteCreationService.OnSiteCreationStateUpdated; import org.wordpress.android.ui.prefs.SiteSettingsInterface; import org.wordpress.android.util.AppLog; import org.wordpress.android.util.AppLog.T; import org.wordpress.android.util.AutoForeground; -import org.wordpress.android.util.AutoForeground.AutoForegroundListener; import org.wordpress.android.util.LanguageUtils; import javax.inject.Inject; -public class SiteCreationService extends Service implements AutoForegroundListener { +public class SiteCreationService extends AutoForeground { private static final String ARG_SITE_TITLE = "ARG_SITE_TITLE"; private static final String ARG_SITE_TAGLINE = "ARG_SITE_TAGLINE"; @@ -53,12 +50,19 @@ public enum SiteCreationPhase { FAILURE } + public static class OnSiteCreationStateUpdated { + public final SiteCreationPhase state; + + public OnSiteCreationStateUpdated(SiteCreationPhase state) { + this.state = state; + } + } + @Inject Dispatcher mDispatcher; @Inject AccountStore mAccountStore; @Inject SiteStore mSiteStore; private SiteCreationPhase mSiteCreationPhase = SiteCreationPhase.IDLE; - private AutoForeground mAutoForeground = new AutoForeground<>(this); private String mSiteTagline; private String mSiteTheme; @@ -78,34 +82,38 @@ public static void createSite( context.startService(intent); } + public SiteCreationService() { + super(OnSiteCreationStateUpdated.class); + } + @Override - public SiteCreationPhase getCurrentState() { - return mSiteCreationPhase; + protected OnSiteCreationStateUpdated getCurrentStateEvent() { + return new OnSiteCreationStateUpdated(mSiteCreationPhase); } @Override - public boolean isInProgress(SiteCreationPhase siteCreationPhase) { - return siteCreationPhase != SiteCreationPhase.IDLE - && siteCreationPhase != SiteCreationPhase.SUCCESS - && siteCreationPhase != SiteCreationPhase.FAILURE; + public boolean isInProgress() { + return mSiteCreationPhase != SiteCreationPhase.IDLE + && mSiteCreationPhase != SiteCreationPhase.SUCCESS + && mSiteCreationPhase != SiteCreationPhase.FAILURE; } @Override - public boolean isError(SiteCreationPhase siteCreationPhase) { - return siteCreationPhase == SiteCreationPhase.FAILURE; + public boolean isError() { + return mSiteCreationPhase == SiteCreationPhase.FAILURE; } @Override - public Notification getNotification(SiteCreationPhase siteCreationPhase) { - switch (siteCreationPhase) { + public Notification getNotification() { + switch (mSiteCreationPhase) { case NEW_SITE: - return getProgressNotification(25, "Site creation in: " + siteCreationPhase.name()); + return getProgressNotification(25, "Site creation in: " + mSiteCreationPhase.name()); case FETCHING_NEW_SITE: - return getProgressNotification(50, "Site creation in: " + siteCreationPhase.name()); + return getProgressNotification(50, "Site creation in: " + mSiteCreationPhase.name()); case SET_TAGLINE: - return getProgressNotification(75, "Site creation in: " + siteCreationPhase.name()); + return getProgressNotification(75, "Site creation in: " + mSiteCreationPhase.name()); case SET_THEME: - return getProgressNotification(100, "Site creation in: " + siteCreationPhase.name()); + return getProgressNotification(100, "Site creation in: " + mSiteCreationPhase.name()); case SUCCESS: return getSuccessNotification("Site created!"); case FAILURE: @@ -115,9 +123,9 @@ public Notification getNotification(SiteCreationPhase siteCreationPhase) { return null; } - private void notifyState(SiteCreationPhase siteCreationPhase) { + private void setState(SiteCreationPhase siteCreationPhase) { mSiteCreationPhase = siteCreationPhase; - mAutoForeground.notifyState(siteCreationPhase); + notifyState(); if (siteCreationPhase == SiteCreationPhase.FAILURE || siteCreationPhase == SiteCreationPhase.SUCCESS) { stopSelf(); @@ -142,12 +150,6 @@ public void onDestroy() { super.onDestroy(); } - @Nullable - @Override - public IBinder onBind(Intent intent) { - return mAutoForeground.getBinder(); - } - private Intent getPendingIntent() { Intent intent = new Intent(this, NewBlogActivity.class); // intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); @@ -204,7 +206,7 @@ public int onStartCommand(@Nullable Intent intent, int flags, int startId) { return START_NOT_STICKY; } - notifyState(SiteCreationPhase.NEW_SITE); + setState(SiteCreationPhase.NEW_SITE); final String siteTitle = intent.getStringExtra(ARG_SITE_TITLE); final String siteSlug = intent.getStringExtra(ARG_SITE_SLUG); @@ -231,12 +233,12 @@ private void activateTheme(final SiteModel site, final String themeId) { public void onResponse(JSONObject response) { ThemeTable.setCurrentTheme(WordPress.wpDB.getDatabase(), String.valueOf(site.getSiteId()), themeId); - notifyState(SiteCreationPhase.SUCCESS); + setState(SiteCreationPhase.SUCCESS); } }, new RestRequest.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { - notifyState(SiteCreationPhase.FAILURE); + setState(SiteCreationPhase.FAILURE); // ToastUtils.showToast(ThemeBrowserActivity.this, R.string.theme_activation_error, // ToastUtils.Duration.SHORT); } @@ -250,14 +252,14 @@ public void onErrorResponse(VolleyError error) { public void onNewSiteCreated(SiteStore.OnNewSiteCreated event) { AppLog.i(T.NUX, event.toString()); if (event.isError()) { - notifyState(SiteCreationPhase.FAILURE); + setState(SiteCreationPhase.FAILURE); // showError(event.error.type, event.error.message); return; } AnalyticsTracker.track(AnalyticsTracker.Stat.CREATED_SITE); - notifyState(SiteCreationPhase.FETCHING_NEW_SITE); + setState(SiteCreationPhase.FETCHING_NEW_SITE); mNewSiteRemoteId = event.newSiteRemoteId; @@ -281,23 +283,23 @@ public void onSiteChanged(SiteStore.OnSiteChanged event) { if (mSiteCreationPhase == SiteCreationPhase.FETCHING_NEW_SITE) { Intent intent = new Intent(); if (site == null) { - notifyState(SiteCreationPhase.FAILURE); + setState(SiteCreationPhase.FAILURE); // ToastUtils.showToast(getActivity(), R.string.error_fetch_site_after_creation, ToastUtils.Duration.LONG); return; } - notifyState(SiteCreationPhase.SET_TAGLINE); + setState(SiteCreationPhase.SET_TAGLINE); SiteSettingsInterface siteSettings = SiteSettingsInterface.getInterface(this, site, new SiteSettingsInterface.SiteSettingsListener() { @Override public void onSaveError(Exception error) { - notifyState(SiteCreationPhase.FAILURE); + setState(SiteCreationPhase.FAILURE); } @Override public void onFetchError(Exception error) { - notifyState(SiteCreationPhase.FAILURE); + setState(SiteCreationPhase.FAILURE); } @Override @@ -307,7 +309,7 @@ public void onSettingsUpdated() { @Override public void onSettingsSaved() { - notifyState(SiteCreationPhase.SET_THEME); + setState(SiteCreationPhase.SET_THEME); SiteModel site = mSiteStore.getSiteBySiteId(mNewSiteRemoteId); activateTheme(site, mSiteTheme); } @@ -315,13 +317,13 @@ public void onSettingsSaved() { @Override public void onCredentialsValidated(Exception error) { if (error != null) { - notifyState(SiteCreationPhase.FAILURE); + setState(SiteCreationPhase.FAILURE); } } }); if (siteSettings == null) { - notifyState(SiteCreationPhase.FAILURE); + setState(SiteCreationPhase.FAILURE); return; } @@ -329,7 +331,7 @@ public void onCredentialsValidated(Exception error) { siteSettings.setTagline(mSiteTagline); siteSettings.saveSettings(); } else if (mSiteCreationPhase == SiteCreationPhase.SET_TAGLINE) { - notifyState(SiteCreationPhase.SET_THEME); + setState(SiteCreationPhase.SET_THEME); activateTheme(site, mSiteTheme); } } diff --git a/libs/utils/WordPressUtils/build.gradle b/libs/utils/WordPressUtils/build.gradle index 2906a1f36df8..ca6ac552c1ea 100644 --- a/libs/utils/WordPressUtils/build.gradle +++ b/libs/utils/WordPressUtils/build.gradle @@ -21,6 +21,7 @@ dependencies { compile 'com.android.support:support-v13:25.3.1' compile 'com.android.support:design:25.3.1' compile 'com.android.support:recyclerview-v7:25.3.1' + compile 'org.greenrobot:eventbus:3.0.0' } android { diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForeground.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForeground.java index d3c361b76797..40f8561c8f30 100644 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForeground.java +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForeground.java @@ -2,199 +2,104 @@ import android.app.Notification; import android.app.Service; -import android.content.ComponentName; -import android.content.Context; import android.content.Intent; -import android.content.ServiceConnection; +import android.os.Binder; import android.os.IBinder; -import android.os.Message; -import android.os.Messenger; -import android.os.RemoteException; import android.support.annotation.CallSuper; +import android.support.annotation.Nullable; import android.support.v4.app.NotificationManagerCompat; -import java.util.ArrayList; +import org.greenrobot.eventbus.EventBus; -public class AutoForeground implements WeakHandler.MessageListener { +public abstract class AutoForeground extends Service { public static final int NOTIFICATION_ID_PROGRESS = 1; public static final int NOTIFICATION_ID_SUCCESS = 2; public static final int NOTIFICATION_ID_FAILURE = 3; - public static final int MSG_REGISTER_CLIENT = 1; - public static final int MSG_UNREGISTER_CLIENT = 2; + private class LocalBinder extends Binder {} - public static final int MSG_CURRENT_STATE = 4; + private final IBinder mBinder = new LocalBinder(); - public static class ServiceClient { - private ServiceConnection mServiceConnection; - private final Messenger mClient; - private Messenger mService; + private final Class mEventClass; - public ServiceClient(Context context, Class> clazz, - WeakHandler.MessageListener clientListener) { - mClient = new Messenger(new WeakHandler(clientListener)); - connect(context, clazz); - } - - private void connect(Context context, Class> clazz) { - mServiceConnection = new ServiceConnection() { - @Override - public void onServiceConnected(ComponentName componentName, IBinder iBinder) { - mService = new Messenger(iBinder); - registerClient(); - } - - @Override - public void onServiceDisconnected(ComponentName componentName) { - // nothing here - } - }; - - context.bindService(new Intent(context, clazz), mServiceConnection, Context.BIND_AUTO_CREATE); - } - - public void disconnect(Context context) { - unregisterClient(); - - context.unbindService(mServiceConnection); - } - - private void registerClient() { - Message msg = Message.obtain(null, AutoForeground.MSG_REGISTER_CLIENT); - msg.replyTo = mClient; - try { - mService.send(msg); - requestCurrentState(); - } catch (RemoteException e) { - // In this case the service has crashed before we could even - // do anything with it; we can count on soon being - // disconnected (and then reconnected if it can be restarted) - // so there is no need to do anything special here. - e.printStackTrace(); - } - } - - private void unregisterClient() { - Message msg = Message.obtain(null, AutoForeground.MSG_UNREGISTER_CLIENT); - msg.replyTo = mClient; - try { - mService.send(msg); - } catch (RemoteException e) { - // In this case the service has crashed before we could even - // do anything with it; we can count on soon being - // disconnected (and then reconnected if it can be restarted) - // so there is no need to do anything special here. - e.printStackTrace(); - } - } + protected abstract EventClass getCurrentStateEvent(); + protected abstract Notification getNotification(); + protected abstract boolean isInProgress(); + protected abstract boolean isError(); - public void requestCurrentState() { - Message msg = Message.obtain(null, AutoForeground.MSG_CURRENT_STATE); - msg.replyTo = mClient; - try { - mService.send(msg); - } catch (RemoteException e) { - e.printStackTrace(); - } - } + protected AutoForeground(Class eventClass) { + mEventClass = eventClass; } - public interface AutoForegroundListener { - State getCurrentState(); - Notification getNotification(State state); - boolean isInProgress(State state); - boolean isError(State state); - } - - private final AutoForegroundListener mAutoForegroundListener; - private final Service mService; + @Nullable + @CallSuper + @Override + public IBinder onBind(Intent intent) { + notifyState(); - private ArrayList mConnectedClients = new ArrayList<>(); + return mBinder; + } - private final Messenger mMessenger = new Messenger(new WeakHandler(this)); + @CallSuper + @Override + public void onRebind(Intent intent) { + super.onRebind(intent); - public AutoForeground(T service) { - mAutoForegroundListener = service; - mService = service; + notifyState(); } - @Override @CallSuper - public boolean handleMessage(Message msg) { - switch (msg.what) { - case MSG_REGISTER_CLIENT: - mConnectedClients.add(msg.replyTo); - background(); - break; - case MSG_UNREGISTER_CLIENT: - mConnectedClients.remove(msg.replyTo); - if (mConnectedClients.size() == 0) { - promoteForeground(); - } - break; - case MSG_CURRENT_STATE: - notifyState(mAutoForegroundListener.getCurrentState()); - break; - default: - return false; - } + @Override + public boolean onUnbind(Intent intent) { + promoteForeground(); - return true; + return true; // call onRebind() if new clients connect } - private boolean notifyConnectedClients(State state) { - int validClients = 0; - - for (int i = mConnectedClients.size() - 1; i >= 0; i--) { - try { - mConnectedClients.get(i).send(Message.obtain(null, MSG_CURRENT_STATE, state)); - validClients++; - } catch (RemoteException e) { - // The client is dead. Remove it from the list; - // we are going through the list from back to front - // so this is safe to do inside the loop. - mConnectedClients.remove(i); - } - } - - return validClients > 0; + private EventBus getEventBus() { + return EventBus.getDefault(); } - public IBinder getBinder() { - return mMessenger.getBinder(); + private boolean hasConnectedClients() { + return getEventBus().hasSubscriberForEvent(mEventClass); } private void promoteForeground() { - State state = mAutoForegroundListener.getCurrentState(); - if (mAutoForegroundListener.isInProgress(state)) { - mService.startForeground(NOTIFICATION_ID_PROGRESS, mAutoForegroundListener.getNotification(state)); + if (isInProgress()) { + startForeground(NOTIFICATION_ID_PROGRESS, getNotification()); } } private void background() { - mService.stopForeground(true); + stopForeground(true); } @CallSuper - public void notifyState(State state) { - boolean hasValidClients = false; - if (mConnectedClients.size() > 0) { - hasValidClients = notifyConnectedClients(state); + protected void notifyState() { + if (hasConnectedClients()) { + // just send a message to the connected clients + getEventBus().post(getCurrentStateEvent()); + return; } - if (!hasValidClients) { - if (mAutoForegroundListener.isInProgress(state)) { - NotificationManagerCompat.from(mService).notify(NOTIFICATION_ID_PROGRESS, - mAutoForegroundListener.getNotification(state)); - } else { - background(); - NotificationManagerCompat.from(mService).cancel(NOTIFICATION_ID_PROGRESS); - - NotificationManagerCompat.from(mService).notify( - mAutoForegroundListener.isError(state) ? NOTIFICATION_ID_FAILURE : NOTIFICATION_ID_SUCCESS, - mAutoForegroundListener.getNotification(state)); - } + // ok, no connected clients so, update will be redirected to a notification + + if (isInProgress()) { + // operation still is progress so, update the notification + NotificationManagerCompat.from(this).notify(NOTIFICATION_ID_PROGRESS, getNotification()); + return; } + + // operation has ended so, demote the Service to a background one + background(); + + // dismiss the sticky notification + NotificationManagerCompat.from(this).cancel(NOTIFICATION_ID_PROGRESS); + + // put out a simple success/failure notification + NotificationManagerCompat.from(this).notify( + isError() ? NOTIFICATION_ID_FAILURE : NOTIFICATION_ID_SUCCESS, + getNotification()); } } diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ServiceEventConnection.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ServiceEventConnection.java new file mode 100644 index 000000000000..1bb4bf52fed3 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ServiceEventConnection.java @@ -0,0 +1,36 @@ +package org.wordpress.android.util; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.IBinder; + +import org.greenrobot.eventbus.EventBus; + +public class ServiceEventConnection { + private final ServiceConnection mServiceConnection; + + public ServiceEventConnection(Context context, Class clazz, Object client) { + EventBus.getDefault().register(client); + + mServiceConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName componentName, IBinder iBinder) { + // nothing here + } + + @Override + public void onServiceDisconnected(ComponentName componentName) { + // nothing here + } + }; + + context.bindService(new Intent(context, clazz), mServiceConnection, Context.BIND_AUTO_CREATE); + } + + public void disconnect(Context context, Object client) { + context.unbindService(mServiceConnection); + EventBus.getDefault().unregister(client); + } +} From 17b66840a59fbb6785925cf758ad53b0b1da59ec Mon Sep 17 00:00:00 2001 From: Stefanos Togkoulidis Date: Fri, 10 Nov 2017 14:53:13 +0200 Subject: [PATCH 06/11] Remove unneeded class --- .../wordpress/android/util/WeakHandler.java | 33 ------------------- 1 file changed, 33 deletions(-) delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/WeakHandler.java diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/WeakHandler.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/WeakHandler.java deleted file mode 100644 index 5883b0ab2da5..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/WeakHandler.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.wordpress.android.util; - -import android.os.Handler; -import android.os.Message; - -import java.lang.ref.WeakReference; - -/** - * Class to wrap a Handler with a WeakReference so we don't leak a context - */ -public class WeakHandler extends Handler { - public interface MessageListener { - boolean handleMessage(Message msg); - } - - private final WeakReference mWeakMessageListener; - - public WeakHandler(MessageListener messageListener) { - mWeakMessageListener = new WeakReference<>(messageListener); - } - - @Override - public void handleMessage(Message msg) { - final MessageListener messageListener = mWeakMessageListener.get(); - if (messageListener == null) { - return; - } - - if (!messageListener.handleMessage(msg)) { - super.handleMessage(msg); - } - } -} From 10be1e01edeb6c73f8d4bb2bb9bee55e108156fb Mon Sep 17 00:00:00 2001 From: Stefanos Togkoulidis Date: Fri, 10 Nov 2017 15:25:20 +0200 Subject: [PATCH 07/11] Stay in background if EventBus clients active --- .../main/java/org/wordpress/android/util/AutoForeground.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForeground.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForeground.java index 40f8561c8f30..52fb4aa0a7b1 100644 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForeground.java +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForeground.java @@ -52,7 +52,9 @@ public void onRebind(Intent intent) { @CallSuper @Override public boolean onUnbind(Intent intent) { - promoteForeground(); + if (!hasConnectedClients()) { + promoteForeground(); + } return true; // call onRebind() if new clients connect } From 0d9ac9f22bc923de9145ca8353e6198414f3559e Mon Sep 17 00:00:00 2001 From: Stefanos Togkoulidis Date: Fri, 10 Nov 2017 15:37:59 +0200 Subject: [PATCH 08/11] Move to background when rebound --- .../src/main/java/org/wordpress/android/util/AutoForeground.java | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForeground.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForeground.java index 52fb4aa0a7b1..95a6a46928e2 100644 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForeground.java +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForeground.java @@ -46,6 +46,7 @@ public IBinder onBind(Intent intent) { public void onRebind(Intent intent) { super.onRebind(intent); + background(); notifyState(); } From 194b57678f09e6df92f8e560ec3e53a532f46940 Mon Sep 17 00:00:00 2001 From: Stefanos Togkoulidis Date: Fri, 10 Nov 2017 16:20:39 +0200 Subject: [PATCH 09/11] Move inside AutoForeground for better correlation --- .../accounts/signup/SiteCreatingFragment.java | 2 +- .../android/util/AutoForeground.java | 30 ++++++++++++++++ .../android/util/ServiceEventConnection.java | 36 ------------------- 3 files changed, 31 insertions(+), 37 deletions(-) delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ServiceEventConnection.java diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/signup/SiteCreatingFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/accounts/signup/SiteCreatingFragment.java index 03b14ba44e60..036ef9e8f5c3 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/accounts/signup/SiteCreatingFragment.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/signup/SiteCreatingFragment.java @@ -19,7 +19,7 @@ import org.wordpress.android.ui.accounts.signup.SiteCreationService.OnSiteCreationStateUpdated; import org.wordpress.android.util.AppLog; import org.wordpress.android.util.AppLog.T; -import org.wordpress.android.util.ServiceEventConnection; +import org.wordpress.android.util.AutoForeground.ServiceEventConnection; public class SiteCreatingFragment extends Fragment { public static final String TAG = "site_creating_fragment_tag"; diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForeground.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForeground.java index 95a6a46928e2..da3172c84db2 100644 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForeground.java +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForeground.java @@ -2,7 +2,10 @@ import android.app.Notification; import android.app.Service; +import android.content.ComponentName; +import android.content.Context; import android.content.Intent; +import android.content.ServiceConnection; import android.os.Binder; import android.os.IBinder; import android.support.annotation.CallSuper; @@ -17,6 +20,33 @@ public abstract class AutoForeground extends Service { public static final int NOTIFICATION_ID_SUCCESS = 2; public static final int NOTIFICATION_ID_FAILURE = 3; + public static class ServiceEventConnection { + private final ServiceConnection mServiceConnection; + + public ServiceEventConnection(Context context, Class clazz, Object client) { + EventBus.getDefault().register(client); + + mServiceConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName componentName, IBinder iBinder) { + // nothing here + } + + @Override + public void onServiceDisconnected(ComponentName componentName) { + // nothing here + } + }; + + context.bindService(new Intent(context, clazz), mServiceConnection, Context.BIND_AUTO_CREATE); + } + + public void disconnect(Context context, Object client) { + context.unbindService(mServiceConnection); + EventBus.getDefault().unregister(client); + } + } + private class LocalBinder extends Binder {} private final IBinder mBinder = new LocalBinder(); diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ServiceEventConnection.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ServiceEventConnection.java deleted file mode 100644 index 1bb4bf52fed3..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ServiceEventConnection.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.wordpress.android.util; - -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.os.IBinder; - -import org.greenrobot.eventbus.EventBus; - -public class ServiceEventConnection { - private final ServiceConnection mServiceConnection; - - public ServiceEventConnection(Context context, Class clazz, Object client) { - EventBus.getDefault().register(client); - - mServiceConnection = new ServiceConnection() { - @Override - public void onServiceConnected(ComponentName componentName, IBinder iBinder) { - // nothing here - } - - @Override - public void onServiceDisconnected(ComponentName componentName) { - // nothing here - } - }; - - context.bindService(new Intent(context, clazz), mServiceConnection, Context.BIND_AUTO_CREATE); - } - - public void disconnect(Context context, Object client) { - context.unbindService(mServiceConnection); - EventBus.getDefault().unregister(client); - } -} From 311a2cdda76edbf1a7d22216a7cd3b3a5d91400e Mon Sep 17 00:00:00 2001 From: Stefanos Togkoulidis Date: Fri, 10 Nov 2017 16:23:27 +0200 Subject: [PATCH 10/11] Remove uneeded comments --- .../android/ui/accounts/signup/SiteCreationService.java | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/signup/SiteCreationService.java b/WordPress/src/main/java/org/wordpress/android/ui/accounts/signup/SiteCreationService.java index 2ce569f1ef89..39177f82f7de 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/accounts/signup/SiteCreationService.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/signup/SiteCreationService.java @@ -151,10 +151,7 @@ public void onDestroy() { } private Intent getPendingIntent() { - Intent intent = new Intent(this, NewBlogActivity.class); -// intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); -// intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - return intent; + return new Intent(this, NewBlogActivity.class); } private Notification getProgressNotification(int progress, String content) { @@ -239,8 +236,6 @@ public void onResponse(JSONObject response) { @Override public void onErrorResponse(VolleyError error) { setState(SiteCreationPhase.FAILURE); -// ToastUtils.showToast(ThemeBrowserActivity.this, R.string.theme_activation_error, -// ToastUtils.Duration.SHORT); } }); } @@ -253,7 +248,6 @@ public void onNewSiteCreated(SiteStore.OnNewSiteCreated event) { AppLog.i(T.NUX, event.toString()); if (event.isError()) { setState(SiteCreationPhase.FAILURE); -// showError(event.error.type, event.error.message); return; } @@ -284,7 +278,6 @@ public void onSiteChanged(SiteStore.OnSiteChanged event) { Intent intent = new Intent(); if (site == null) { setState(SiteCreationPhase.FAILURE); - // ToastUtils.showToast(getActivity(), R.string.error_fetch_site_after_creation, ToastUtils.Duration.LONG); return; } From 17e763787da8b785d1a2d716231354cd560f98c3 Mon Sep 17 00:00:00 2001 From: Stefanos Togkoulidis Date: Fri, 10 Nov 2017 17:06:38 +0200 Subject: [PATCH 11/11] Statusbar icon fix to have it being opaque --- .../android/ui/accounts/signup/SiteCreationService.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/signup/SiteCreationService.java b/WordPress/src/main/java/org/wordpress/android/ui/accounts/signup/SiteCreationService.java index 39177f82f7de..61045fd76155 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/accounts/signup/SiteCreationService.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/signup/SiteCreationService.java @@ -157,7 +157,8 @@ private Intent getPendingIntent() { private Notification getProgressNotification(int progress, String content) { return new NotificationCompat.Builder(this) .setContentTitle(content) - .setSmallIcon(R.mipmap.app_icon) + .setSmallIcon(R.drawable.ic_my_sites_24dp) + .setColor(getResources().getColor(R.color.blue_wordpress)) .setLargeIcon(BitmapFactory.decodeResource(getApplicationContext().getResources(), R.mipmap.app_icon)) .setAutoCancel(true) @@ -172,7 +173,8 @@ private Notification getProgressNotification(int progress, String content) { private Notification getSuccessNotification(String content) { return new NotificationCompat.Builder(this) .setContentTitle(content) - .setSmallIcon(R.mipmap.app_icon) + .setSmallIcon(R.drawable.ic_my_sites_24dp) + .setColor(getResources().getColor(R.color.blue_wordpress)) .setLargeIcon(BitmapFactory.decodeResource(getApplicationContext().getResources(), R.mipmap.app_icon)) .setAutoCancel(true) @@ -186,7 +188,8 @@ private Notification getSuccessNotification(String content) { private Notification getFailureNotification(String content) { return new NotificationCompat.Builder(this) .setContentTitle(content) - .setSmallIcon(R.mipmap.app_icon) + .setSmallIcon(R.drawable.ic_my_sites_24dp) + .setColor(getResources().getColor(R.color.blue_wordpress)) .setLargeIcon(BitmapFactory.decodeResource(getApplicationContext().getResources(), R.mipmap.app_icon)) .setAutoCancel(true)