From f26cddc875e2235234b738a4aa2182ae682a61e3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Feb 2024 08:26:43 +0000 Subject: [PATCH 01/25] Bump androidx.navigation.safeargs.kotlin from 2.5.3 to 2.7.7 Bumps androidx.navigation.safeargs.kotlin from 2.5.3 to 2.7.7. --- updated-dependencies: - dependency-name: androidx.navigation.safeargs.kotlin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- settings.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle b/settings.gradle index 0dd34fb91ca1..b6b8018a0b2a 100644 --- a/settings.gradle +++ b/settings.gradle @@ -2,7 +2,7 @@ pluginManagement { gradle.ext.kotlinVersion = '1.9.10' gradle.ext.agpVersion = '8.1.0' gradle.ext.googleServicesVersion = '4.3.15' - gradle.ext.navigationVersion = '2.5.3' + gradle.ext.navigationVersion = '2.7.7' gradle.ext.sentryVersion = '3.14.0' gradle.ext.daggerVersion = "2.46.1" gradle.ext.detektVersion = '1.23.0' From 393c1ec990e1d5ecd0918009c84fecb281449618 Mon Sep 17 00:00:00 2001 From: Thomas Horta Date: Tue, 6 Feb 2024 17:46:30 -0300 Subject: [PATCH 02/25] Clean up some formatting/old TODO --- .../android/ui/reader/ReaderPostListFragment.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListFragment.java index 2da410a95ab6..3bf9dc3c615d 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListFragment.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListFragment.java @@ -1724,9 +1724,6 @@ private void setEmptyTitleDescriptionAndButton(boolean requestFailed) { // Ensure the default image is reset for empty views before applying logic mActionableEmptyView.image.setImageResource(R.drawable.illustration_reader_empty); - // TODO thomashortadev - // try to quickly hack some way of making the button black - if (shouldShowEmptyViewForSelfHostedCta()) { setEmptyTitleAndDescriptionForSelfHostedCta(); return; @@ -1940,7 +1937,9 @@ private void showBookmarksSavedLocallyDialog(ShowBookmarkedSavedOnlyLocallyDialo .setCancelable(false) .create(); mBookmarksSavedLocallyDialog.show(); - } /* + } + + /* * called by post adapter when data has been loaded */ private final ReaderInterfaces.DataLoadedListener mDataLoadedListener = new ReaderInterfaces.DataLoadedListener() { From 5b573f64c3b7698ccd434833c64fde9253d07ba2 Mon Sep 17 00:00:00 2001 From: Thomas Horta Date: Wed, 7 Feb 2024 00:33:12 -0300 Subject: [PATCH 03/25] Fix tag list check logic to avoid saving same data to DB IMPORTANT: this breaks ReaderPostListFragment/ViewModel fetch logic because it was relying on this bug causing FollowedTagsChanged to be triggered in the EventBus all the time. With this fix the Subscriptions feed is completely broken (and the other feeds that use this Fragments are likely to be broken as well, which are all the other except Discover). --- .../java/org/wordpress/android/datasets/ReaderTagTable.java | 4 ++++ .../java/org/wordpress/android/models/ReaderTagList.java | 2 ++ .../ui/reader/services/update/ReaderUpdateLogic.java | 6 ++---- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/datasets/ReaderTagTable.java b/WordPress/src/main/java/org/wordpress/android/datasets/ReaderTagTable.java index 977f7eaf0f2e..7c7530756b12 100644 --- a/WordPress/src/main/java/org/wordpress/android/datasets/ReaderTagTable.java +++ b/WordPress/src/main/java/org/wordpress/android/datasets/ReaderTagTable.java @@ -232,6 +232,10 @@ public static ReaderTagList getBookmarkTags() { return getTagsOfType(ReaderTagType.BOOKMARKED); } + public static ReaderTagList getDiscoverPostCardsTags() { + return getTagsOfType(ReaderTagType.DISCOVER_POST_CARDS); + } + private static ReaderTagList getTagsOfType(ReaderTagType tagType) { String[] args = {Integer.toString(tagType.toInt())}; Cursor c = ReaderDatabase.getReadableDb() diff --git a/WordPress/src/main/java/org/wordpress/android/models/ReaderTagList.java b/WordPress/src/main/java/org/wordpress/android/models/ReaderTagList.java index 6a9633c44441..12da31783833 100644 --- a/WordPress/src/main/java/org/wordpress/android/models/ReaderTagList.java +++ b/WordPress/src/main/java/org/wordpress/android/models/ReaderTagList.java @@ -44,6 +44,8 @@ public boolean isSameList(ReaderTagList otherList) { return false; } else if (!otherTag.getTagTitle().equals(this.get(i).getTagTitle())) { return false; + } else if (!otherTag.getTagDisplayName().equals(this.get(i).getTagDisplayName())) { + return false; } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/services/update/ReaderUpdateLogic.java b/WordPress/src/main/java/org/wordpress/android/ui/reader/services/update/ReaderUpdateLogic.java index cde09194380f..1da857ba5a16 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/services/update/ReaderUpdateLogic.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/services/update/ReaderUpdateLogic.java @@ -176,11 +176,9 @@ public void run() { localTopics.addAll(ReaderTagTable.getFollowedTags()); localTopics.addAll(ReaderTagTable.getBookmarkTags()); localTopics.addAll(ReaderTagTable.getCustomListTags()); + localTopics.addAll(ReaderTagTable.getDiscoverPostCardsTags()); - if ( - !localTopics.isSameList(serverTopics) - || displayNameUpdateWasNeeded - ) { + if (!localTopics.isSameList(serverTopics)) { AppLog.d(AppLog.T.READER, "reader service > followed topics changed " + "updatedDisplayNames [" + displayNameUpdateWasNeeded + "]"); From f69531c98d270c322ca083aa6ce929b2cd81301b Mon Sep 17 00:00:00 2001 From: Thomas Horta Date: Wed, 7 Feb 2024 00:37:22 -0300 Subject: [PATCH 04/25] Fix empty view being hidden when coming back to Subscriptions The empty view is being reused for showing several messages, including the fetch message. Because of that, that are pieces of code that rely on previous code showing the "empty view" and just alter its content, without calling "show" again. If we hide the empty view when the list is actually empty, we get to a scenario of a blank screen when coming back to this feed from some other screens. Example: with 0 blog subscriptions, in the Subscriptions feed, going to the tag suggestions and back cause the Subscriptions feed to be blank. --- .../org/wordpress/android/ui/reader/ReaderPostListFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListFragment.java index 3bf9dc3c615d..fdee851a6f05 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListFragment.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListFragment.java @@ -2332,7 +2332,7 @@ public void run() { mActionableEmptyView.button.setVisibility(View.GONE); mActionableEmptyView.subtitle.setVisibility(View.GONE); showEmptyView(); - } else { + } else if (!isPostAdapterEmpty()) { hideEmptyView(); } }); From 4a8ba198caeda3974ce0db642b0e91c16455031b Mon Sep 17 00:00:00 2001 From: Thomas Horta Date: Fri, 9 Feb 2024 19:05:46 -0300 Subject: [PATCH 05/25] WIP trying again to fix initial fetching... Tag Interests has an infinite loading because a use case expects the event that is not triggered anymore (I think). --- .../ui/reader/ReaderPostListFragment.java | 21 ++++++++++++++++++- .../services/update/ReaderUpdateLogic.java | 1 + .../ui/reader/viewmodels/ReaderViewModel.kt | 3 ++- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListFragment.java index fdee851a6f05..69116fd5f7b3 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListFragment.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListFragment.java @@ -1945,9 +1945,13 @@ private void showBookmarksSavedLocallyDialog(ShowBookmarkedSavedOnlyLocallyDialo private final ReaderInterfaces.DataLoadedListener mDataLoadedListener = new ReaderInterfaces.DataLoadedListener() { @Override public void onDataLoaded(boolean isEmpty) { - if (!isAdded() || !mHasUpdatedPosts) { + if (!isAdded()) return; + + if (!mHasUpdatedPosts) { + fetchInitialData(); return; } + if (isEmpty) { if (getPostListType() != ReaderPostListType.SEARCH_RESULTS || getSearchTabsPosition() == TAB_SITES && getSiteSearchAdapter().isEmpty() @@ -1972,6 +1976,21 @@ public void onDataLoaded(boolean isEmpty) { } }; + private void fetchInitialData() { + if (getPostListType() == ReaderPostListType.TAG_FOLLOWED) { + reloadTags(); + + // update the current tag if the list fragment is empty - this will happen if + // the tag table was previously empty (ie: first run) + if (isPostAdapterEmpty()) { + updateCurrentTag(); + } + } + + if (mReaderViewModel != null) mReaderViewModel.loadTabs(); + if (mSubFilterViewModel != null) mSubFilterViewModel.loadSubFilters(); + } + private boolean isBookmarksList() { return getPostListType() == ReaderPostListType.TAG_FOLLOWED && (mCurrentTag != null && mCurrentTag.isBookmarked()); diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/services/update/ReaderUpdateLogic.java b/WordPress/src/main/java/org/wordpress/android/ui/reader/services/update/ReaderUpdateLogic.java index 1da857ba5a16..b935807df17f 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/services/update/ReaderUpdateLogic.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/services/update/ReaderUpdateLogic.java @@ -193,6 +193,7 @@ public void run() { ReaderTagTable.replaceTags(serverTopics); } // broadcast the fact that there are changes + // TODO thomashortadev this was being sent EVERY time EventBus.getDefault().post(new ReaderEvents.FollowedTagsChanged(true)); } AppPrefs.setReaderTagsUpdatedTimestamp(new Date().getTime()); diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/viewmodels/ReaderViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/viewmodels/ReaderViewModel.kt index a6e26e3f648a..c745626738a2 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/viewmodels/ReaderViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/viewmodels/ReaderViewModel.kt @@ -135,7 +135,8 @@ class ReaderViewModel @Inject constructor( // _showJetpackPoweredBottomSheet.value = Event(true) } - private fun loadTabs(savedInstanceState: Bundle? = null) { + @JvmOverloads + fun loadTabs(savedInstanceState: Bundle? = null) { launch { val tagList = loadReaderTabsUseCase.loadTabs() if (tagList.isNotEmpty() && readerTagsList != tagList) { From 7f069f6082c0a1eadeebc4627d0213a3e8643efd Mon Sep 17 00:00:00 2001 From: Thomas Horta Date: Mon, 19 Feb 2024 19:30:01 -0300 Subject: [PATCH 06/25] Rename FollowedTagsChanged to FollowedTagsFetched Upon investigation I realized that most places using this event were actually using it as a callback for the end of the fetch task rather than something that is ONLY emitted when the tags CHANGE, which was what the name implied. That only worked because of the bug mentioned in commit 3017bab that did not properly compare the local and server tags and considered all fetches as requiring a local database write, which in turn triggered the event. The constant triggering of that FollowedTagsChanged event was also the cause of bugs #20009 and #20010 since part of the code that runs there was actually only supposed to run some times. To fix that I renamed it to FollowedTagsFetched to better represent what it does and figured out which parts of the code inside `ReaderPostListFragment` event listener were supposed to run and in which scenario. I also added a `didChange` field in the `FollowedTagsFetched` event for completeness but that part might not be needed in the future, since the only code using that is legacy code related to the old subfilter which should be removed in the future. --- .../android/ui/reader/ReaderEvents.java | 15 +++++- .../ui/reader/ReaderPostListFragment.java | 46 +++++++++---------- .../android/ui/reader/ReaderSubsActivity.java | 3 +- .../ui/reader/actions/ReaderTagActions.java | 12 ++--- .../repository/ReaderDiscoverDataProvider.kt | 4 +- .../usecases/tags/FetchFollowedTagsUseCase.kt | 4 +- .../tags/FollowInterestTagsUseCase.kt | 4 +- .../services/update/ReaderUpdateLogic.java | 6 ++- .../ui/reader/subfilter/SubFilterViewModel.kt | 2 +- .../ui/reader/viewmodels/ReaderViewModel.kt | 2 +- .../FetchFollowedTagsUseCaseTest.kt | 14 +++--- .../ReaderDiscoverDataProviderTest.kt | 8 +++- .../reader/viewmodels/ReaderViewModelTest.kt | 2 +- 13 files changed, 69 insertions(+), 53 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderEvents.java b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderEvents.java index e107db26f932..de72a22e2b40 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderEvents.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderEvents.java @@ -26,16 +26,27 @@ private ReaderEvents() { throw new AssertionError(); } - public static class FollowedTagsChanged { + public static class FollowedTagsFetched { private final boolean mDidSucceed; + private final boolean mDidChange; - public FollowedTagsChanged(boolean didSucceed) { + public FollowedTagsFetched(boolean didSucceed) { mDidSucceed = didSucceed; + mDidChange = true; + } + + public FollowedTagsFetched(boolean didSucceed, boolean didChange) { + mDidSucceed = didSucceed; + mDidChange = didChange; } public boolean didSucceed() { return mDidSucceed; } + + public boolean didChange() { + return mDidChange; + } } public static class TagAdded { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListFragment.java index 69116fd5f7b3..a721385892dc 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListFragment.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListFragment.java @@ -84,6 +84,7 @@ import org.wordpress.android.ui.mysite.jetpackbadge.JetpackPoweredBottomSheetFragment; import org.wordpress.android.ui.pages.SnackbarMessageHolder; import org.wordpress.android.ui.prefs.AppPrefs; +import org.wordpress.android.ui.reader.ReaderEvents.FollowedTagsFetched; import org.wordpress.android.ui.reader.ReaderEvents.TagAdded; import org.wordpress.android.ui.reader.ReaderTypes.ReaderPostListType; import org.wordpress.android.ui.reader.actions.ReaderActions; @@ -934,14 +935,16 @@ private void resetPostAdapter(ReaderPostListType postListType) { @SuppressWarnings("unused") @Subscribe(threadMode = ThreadMode.MAIN) - public void onEventMainThread(ReaderEvents.FollowedTagsChanged event) { + public void onEventMainThread(FollowedTagsFetched event) { if (getPostListType() == ReaderPostListType.TAG_FOLLOWED) { - // reload the tag filter since tags have changed - reloadTags(); + if (event.didChange()) { + // reload the tag filter since tags have changed or we just opened the fragment + reloadTags(); + } // update the current tag if the list fragment is empty - this will happen if // the tag table was previously empty (ie: first run) - if (isPostAdapterEmpty()) { + if (isPostAdapterEmpty() && (ReaderBlogTable.hasFollowedBlogs() || !mHasUpdatedPosts)) { updateCurrentTag(); } } @@ -1945,12 +1948,7 @@ private void showBookmarksSavedLocallyDialog(ShowBookmarkedSavedOnlyLocallyDialo private final ReaderInterfaces.DataLoadedListener mDataLoadedListener = new ReaderInterfaces.DataLoadedListener() { @Override public void onDataLoaded(boolean isEmpty) { - if (!isAdded()) return; - - if (!mHasUpdatedPosts) { - fetchInitialData(); - return; - } + if (!isAdded() || !mHasUpdatedPosts) return; if (isEmpty) { if (getPostListType() != ReaderPostListType.SEARCH_RESULTS @@ -1976,20 +1974,20 @@ public void onDataLoaded(boolean isEmpty) { } }; - private void fetchInitialData() { - if (getPostListType() == ReaderPostListType.TAG_FOLLOWED) { - reloadTags(); - - // update the current tag if the list fragment is empty - this will happen if - // the tag table was previously empty (ie: first run) - if (isPostAdapterEmpty()) { - updateCurrentTag(); - } - } - - if (mReaderViewModel != null) mReaderViewModel.loadTabs(); - if (mSubFilterViewModel != null) mSubFilterViewModel.loadSubFilters(); - } +// private void fetchInitialData() { +// if (getPostListType() == ReaderPostListType.TAG_FOLLOWED) { +// reloadTags(); +// +// // update the current tag if the list fragment is empty - this will happen if +// // the tag table was previously empty (ie: first run) +// if (isPostAdapterEmpty()) { +// updateCurrentTag(); +// } +// } +// +// if (mReaderViewModel != null) mReaderViewModel.loadTabs(); +// if (mSubFilterViewModel != null) mSubFilterViewModel.loadSubFilters(); +// } private boolean isBookmarksList() { return getPostListType() == ReaderPostListType.TAG_FOLLOWED diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderSubsActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderSubsActivity.java index 955a08936ce5..3e8914829792 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderSubsActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderSubsActivity.java @@ -41,6 +41,7 @@ import org.wordpress.android.ui.LocaleAwareActivity; import org.wordpress.android.ui.RequestCodes; import org.wordpress.android.ui.prefs.AppPrefs; +import org.wordpress.android.ui.reader.ReaderEvents.FollowedTagsFetched; import org.wordpress.android.ui.reader.actions.ReaderActions; import org.wordpress.android.ui.reader.actions.ReaderBlogActions; import org.wordpress.android.ui.reader.actions.ReaderTagActions; @@ -203,7 +204,7 @@ protected void onResume() { @SuppressWarnings("unused") @Subscribe(threadMode = ThreadMode.MAIN) - public void onEventMainThread(ReaderEvents.FollowedTagsChanged event) { + public void onEventMainThread(FollowedTagsFetched event) { AppLog.d(AppLog.T.READER, "reader subs > followed tags changed"); getPageAdapter().refreshFollowedTagFragment(); } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/actions/ReaderTagActions.java b/WordPress/src/main/java/org/wordpress/android/ui/reader/actions/ReaderTagActions.java index 9577553148fa..8e9ec0895f73 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/actions/ReaderTagActions.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/actions/ReaderTagActions.java @@ -13,7 +13,7 @@ import org.wordpress.android.models.ReaderTagList; import org.wordpress.android.models.ReaderTagType; import org.wordpress.android.ui.reader.ReaderConstants; -import org.wordpress.android.ui.reader.ReaderEvents; +import org.wordpress.android.ui.reader.ReaderEvents.FollowedTagsFetched; import org.wordpress.android.ui.reader.actions.ReaderActions.ActionListener; import org.wordpress.android.ui.reader.utils.ReaderUtils; import org.wordpress.android.util.AppLog; @@ -51,7 +51,7 @@ public static boolean deleteTag(final ReaderTag tag, private static boolean deleteTagsLocallyOnly(ActionListener actionListener, ReaderTag tag) { ReaderTagTable.deleteTag(tag); ReaderActions.callActionListener(actionListener, true); - EventBus.getDefault().post(new ReaderEvents.FollowedTagsChanged(true)); + EventBus.getDefault().post(new FollowedTagsFetched(true)); return true; } @@ -130,7 +130,7 @@ public static boolean addTags(@NonNull final List tags, private static boolean saveTagsLocallyOnly(ActionListener actionListener, ReaderTagList newTags) { ReaderTagTable.addOrUpdateTags(newTags); ReaderActions.callActionListener(actionListener, true); - EventBus.getDefault().post(new ReaderEvents.FollowedTagsChanged(true)); + EventBus.getDefault().post(new FollowedTagsFetched(true)); return true; } @@ -147,7 +147,7 @@ private static boolean saveTagsLocallyAndRemotely(ActionListener actionListener, if (actionListener != null) { ReaderActions.callActionListener(actionListener, true); } - EventBus.getDefault().post(new ReaderEvents.FollowedTagsChanged(true)); + EventBus.getDefault().post(new FollowedTagsFetched(true)); }; RestRequest.ErrorListener errorListener = volleyError -> { @@ -159,7 +159,7 @@ private static boolean saveTagsLocallyAndRemotely(ActionListener actionListener, if (actionListener != null) { ReaderActions.callActionListener(actionListener, true); } - EventBus.getDefault().post(new ReaderEvents.FollowedTagsChanged(true)); + EventBus.getDefault().post(new FollowedTagsFetched(true)); return; } @@ -171,7 +171,7 @@ private static boolean saveTagsLocallyAndRemotely(ActionListener actionListener, if (actionListener != null) { ReaderActions.callActionListener(actionListener, false); } - EventBus.getDefault().post(new ReaderEvents.FollowedTagsChanged(false)); + EventBus.getDefault().post(new FollowedTagsFetched(false)); }; ReaderTagTable.addOrUpdateTags(newTags); diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/repository/ReaderDiscoverDataProvider.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/repository/ReaderDiscoverDataProvider.kt index a1a20185e26d..27b8cb35b031 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/repository/ReaderDiscoverDataProvider.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/repository/ReaderDiscoverDataProvider.kt @@ -14,7 +14,7 @@ import org.wordpress.android.models.discover.ReaderDiscoverCards import org.wordpress.android.modules.IO_THREAD import org.wordpress.android.modules.UI_THREAD import org.wordpress.android.ui.reader.ReaderEvents.FetchDiscoverCardsEnded -import org.wordpress.android.ui.reader.ReaderEvents.FollowedTagsChanged +import org.wordpress.android.ui.reader.ReaderEvents.FollowedTagsFetched import org.wordpress.android.ui.reader.actions.ReaderActions.UpdateResult.CHANGED import org.wordpress.android.ui.reader.actions.ReaderActions.UpdateResult.FAILED import org.wordpress.android.ui.reader.actions.ReaderActions.UpdateResult.HAS_NEW @@ -211,7 +211,7 @@ class ReaderDiscoverDataProvider @Inject constructor( @Suppress("unused", "UNUSED_PARAMETER") @Subscribe(threadMode = BACKGROUND) - fun onFollowedTagsChanged(event: FollowedTagsChanged) { + fun onFollowedTagsFetched(event: FollowedTagsFetched) { launch { refreshCards() } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/repository/usecases/tags/FetchFollowedTagsUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/repository/usecases/tags/FetchFollowedTagsUseCase.kt index 3afd6a0d2cf2..1d109666337d 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/repository/usecases/tags/FetchFollowedTagsUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/repository/usecases/tags/FetchFollowedTagsUseCase.kt @@ -2,7 +2,7 @@ package org.wordpress.android.ui.reader.repository.usecases.tags import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode -import org.wordpress.android.ui.reader.ReaderEvents.FollowedTagsChanged +import org.wordpress.android.ui.reader.ReaderEvents.FollowedTagsFetched import org.wordpress.android.ui.reader.repository.ReaderRepositoryCommunication import org.wordpress.android.ui.reader.repository.ReaderRepositoryCommunication.Error.NetworkUnavailable import org.wordpress.android.ui.reader.repository.ReaderRepositoryCommunication.Error.RemoteRequestFailure @@ -48,7 +48,7 @@ class FetchFollowedTagsUseCase @Inject constructor( @Suppress("unused") @Subscribe(threadMode = ThreadMode.BACKGROUND) - fun onFollowedTagsChanged(event: FollowedTagsChanged) { + fun onFollowedTagsFetched(event: FollowedTagsFetched) { val result = if (event.didSucceed()) { Success } else { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/repository/usecases/tags/FollowInterestTagsUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/repository/usecases/tags/FollowInterestTagsUseCase.kt index 3002e258d450..8e171e262261 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/repository/usecases/tags/FollowInterestTagsUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/repository/usecases/tags/FollowInterestTagsUseCase.kt @@ -4,7 +4,7 @@ import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode import org.wordpress.android.fluxc.store.AccountStore import org.wordpress.android.models.ReaderTag -import org.wordpress.android.ui.reader.ReaderEvents.FollowedTagsChanged +import org.wordpress.android.ui.reader.ReaderEvents.FollowedTagsFetched import org.wordpress.android.ui.reader.actions.ReaderTagActions import org.wordpress.android.ui.reader.repository.ReaderRepositoryCommunication import org.wordpress.android.ui.reader.repository.ReaderRepositoryCommunication.Error.NetworkUnavailable @@ -43,7 +43,7 @@ class FollowInterestTagsUseCase @Inject constructor( @Suppress("unused") @Subscribe(threadMode = ThreadMode.BACKGROUND) - fun onFollowedTagsChanged(event: FollowedTagsChanged) { + fun onFollowedTagsFetched(event: FollowedTagsFetched) { val result = if (event.didSucceed()) { Success } else { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/services/update/ReaderUpdateLogic.java b/WordPress/src/main/java/org/wordpress/android/ui/reader/services/update/ReaderUpdateLogic.java index b935807df17f..bafd6275709e 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/services/update/ReaderUpdateLogic.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/services/update/ReaderUpdateLogic.java @@ -24,6 +24,7 @@ import org.wordpress.android.ui.prefs.AppPrefs; import org.wordpress.android.ui.reader.ReaderConstants; import org.wordpress.android.ui.reader.ReaderEvents; +import org.wordpress.android.ui.reader.ReaderEvents.FollowedTagsFetched; import org.wordpress.android.ui.reader.ReaderEvents.InterestTagsFetchEnded; import org.wordpress.android.ui.reader.services.ServiceCompletionListener; import org.wordpress.android.util.AppLog; @@ -178,6 +179,7 @@ public void run() { localTopics.addAll(ReaderTagTable.getCustomListTags()); localTopics.addAll(ReaderTagTable.getDiscoverPostCardsTags()); + boolean didChangeFollowedTags = false; if (!localTopics.isSameList(serverTopics)) { AppLog.d(AppLog.T.READER, "reader service > followed topics changed " + "updatedDisplayNames [" + displayNameUpdateWasNeeded + "]"); @@ -193,9 +195,9 @@ public void run() { ReaderTagTable.replaceTags(serverTopics); } // broadcast the fact that there are changes - // TODO thomashortadev this was being sent EVERY time - EventBus.getDefault().post(new ReaderEvents.FollowedTagsChanged(true)); + didChangeFollowedTags = true; } + EventBus.getDefault().post(new FollowedTagsFetched(true, didChangeFollowedTags)); AppPrefs.setReaderTagsUpdatedTimestamp(new Date().getTime()); taskCompleted(UpdateTask.TAGS); diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/subfilter/SubFilterViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/subfilter/SubFilterViewModel.kt index e331ecaeb231..a9dd37639a36 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/subfilter/SubFilterViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/subfilter/SubFilterViewModel.kt @@ -393,7 +393,7 @@ class SubFilterViewModel @Inject constructor( @Suppress("unused", "UNUSED_PARAMETER") @Subscribe(threadMode = ThreadMode.MAIN) - fun onEventMainThread(event: ReaderEvents.FollowedTagsChanged) { + fun onEventMainThread(event: ReaderEvents.FollowedTagsFetched) { AppLog.d(T.READER, "Subfilter bottom sheet > followed tags changed") loadSubFilters() } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/viewmodels/ReaderViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/viewmodels/ReaderViewModel.kt index c745626738a2..0e13b2f17e0b 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/viewmodels/ReaderViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/viewmodels/ReaderViewModel.kt @@ -216,7 +216,7 @@ class ReaderViewModel @Inject constructor( @Suppress("unused", "UNUSED_PARAMETER") @Subscribe(threadMode = MAIN) - fun onTagsUpdated(event: ReaderEvents.FollowedTagsChanged) { + fun onTagsUpdated(event: ReaderEvents.FollowedTagsFetched) { loadTabs() } diff --git a/WordPress/src/test/java/org/wordpress/android/ui/reader/repository/FetchFollowedTagsUseCaseTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/reader/repository/FetchFollowedTagsUseCaseTest.kt index a581bc43584f..5c0c086000e0 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/reader/repository/FetchFollowedTagsUseCaseTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/reader/repository/FetchFollowedTagsUseCaseTest.kt @@ -9,7 +9,7 @@ import org.mockito.Mock import org.mockito.junit.MockitoJUnitRunner import org.mockito.kotlin.whenever import org.wordpress.android.BaseUnitTest -import org.wordpress.android.ui.reader.ReaderEvents.FollowedTagsChanged +import org.wordpress.android.ui.reader.ReaderEvents.FollowedTagsFetched import org.wordpress.android.ui.reader.repository.ReaderRepositoryCommunication.Error.NetworkUnavailable import org.wordpress.android.ui.reader.repository.ReaderRepositoryCommunication.Error.RemoteRequestFailure import org.wordpress.android.ui.reader.repository.ReaderRepositoryCommunication.Success @@ -61,12 +61,12 @@ class FetchFollowedTagsUseCaseTest : BaseUnitTest() { } @Test - fun `Success returned when FollowedTagsChanged event is posted with true`() = test { + fun `Success returned when FollowedTagsFetched event is posted with success`() = test { // Given whenever(networkUtilsWrapper.isNetworkAvailable()).thenReturn(true) - val event = FollowedTagsChanged(true) + val event = FollowedTagsFetched(true) whenever(readerUpdateServiceStarterWrapper.startService(contextProvider.getContext(), EnumSet.of(TAGS))) - .then { useCase.onFollowedTagsChanged(event) } + .then { useCase.onFollowedTagsFetched(event) } // When val result = useCase.fetch() @@ -76,12 +76,12 @@ class FetchFollowedTagsUseCaseTest : BaseUnitTest() { } @Test - fun `RemoteRequestFailure returned when FollowedTagsChanged event is posted with false`() = test { + fun `RemoteRequestFailure returned when FollowedTagsFetched event is posted with failure`() = test { // Given whenever(networkUtilsWrapper.isNetworkAvailable()).thenReturn(true) - val event = FollowedTagsChanged(false) + val event = FollowedTagsFetched(false) whenever(readerUpdateServiceStarterWrapper.startService(contextProvider.getContext(), EnumSet.of(TAGS))) - .then { useCase.onFollowedTagsChanged(event) } + .then { useCase.onFollowedTagsFetched(event) } // When val result = useCase.fetch() diff --git a/WordPress/src/test/java/org/wordpress/android/ui/reader/repository/ReaderDiscoverDataProviderTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/reader/repository/ReaderDiscoverDataProviderTest.kt index 18f0d5704887..3a87558edee4 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/reader/repository/ReaderDiscoverDataProviderTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/reader/repository/ReaderDiscoverDataProviderTest.kt @@ -16,7 +16,7 @@ import org.wordpress.android.models.ReaderPost import org.wordpress.android.models.discover.ReaderDiscoverCard.ReaderPostCard import org.wordpress.android.models.discover.ReaderDiscoverCards import org.wordpress.android.ui.reader.ReaderEvents.FetchDiscoverCardsEnded -import org.wordpress.android.ui.reader.ReaderEvents.FollowedTagsChanged +import org.wordpress.android.ui.reader.ReaderEvents.FollowedTagsFetched import org.wordpress.android.ui.reader.actions.ReaderActions.UpdateResult.FAILED import org.wordpress.android.ui.reader.actions.ReaderActions.UpdateResult.HAS_NEW import org.wordpress.android.ui.reader.actions.ReaderActions.UpdateResult.UNCHANGED @@ -249,7 +249,11 @@ class ReaderDiscoverDataProviderTest : BaseUnitTest() { @Test fun `when followed tags change the discover feed gets refreshed`() = test { // Act - dataProvider.onFollowedTagsChanged(FollowedTagsChanged(true)) + dataProvider.onFollowedTagsFetched( + FollowedTagsFetched( + true + ) + ) // Assert verify(fetchDiscoverCardsUseCase).fetch(REQUEST_FIRST_PAGE) } diff --git a/WordPress/src/test/java/org/wordpress/android/ui/reader/viewmodels/ReaderViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/reader/viewmodels/ReaderViewModelTest.kt index 29780c984015..2f437f24465c 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/reader/viewmodels/ReaderViewModelTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/reader/viewmodels/ReaderViewModelTest.kt @@ -177,7 +177,7 @@ class ReaderViewModelTest : BaseUnitTest() { } @Test - fun `Tags are reloaded when FollowedTagsChanged event is received`() = testWithNonEmptyTags { + fun `Tags are reloaded when FollowedTagsFetched event is received`() = testWithNonEmptyTags { // Arrange var state: ReaderUiState? = null viewModel.uiState.observeForever { From cfd0d99f90d0a80e6a552525855364b5d1d6229b Mon Sep 17 00:00:00 2001 From: Thomas Horta Date: Tue, 20 Feb 2024 14:47:41 -0300 Subject: [PATCH 07/25] Remove unused code --- .../ui/reader/ReaderPostListFragment.java | 20 +++---------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListFragment.java index a721385892dc..287204bb16d1 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListFragment.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListFragment.java @@ -1948,8 +1948,9 @@ private void showBookmarksSavedLocallyDialog(ShowBookmarkedSavedOnlyLocallyDialo private final ReaderInterfaces.DataLoadedListener mDataLoadedListener = new ReaderInterfaces.DataLoadedListener() { @Override public void onDataLoaded(boolean isEmpty) { - if (!isAdded() || !mHasUpdatedPosts) return; - + if (!isAdded() || !mHasUpdatedPosts) { + return; + } if (isEmpty) { if (getPostListType() != ReaderPostListType.SEARCH_RESULTS || getSearchTabsPosition() == TAB_SITES && getSiteSearchAdapter().isEmpty() @@ -1974,21 +1975,6 @@ public void onDataLoaded(boolean isEmpty) { } }; -// private void fetchInitialData() { -// if (getPostListType() == ReaderPostListType.TAG_FOLLOWED) { -// reloadTags(); -// -// // update the current tag if the list fragment is empty - this will happen if -// // the tag table was previously empty (ie: first run) -// if (isPostAdapterEmpty()) { -// updateCurrentTag(); -// } -// } -// -// if (mReaderViewModel != null) mReaderViewModel.loadTabs(); -// if (mSubFilterViewModel != null) mSubFilterViewModel.loadSubFilters(); -// } - private boolean isBookmarksList() { return getPostListType() == ReaderPostListType.TAG_FOLLOWED && (mCurrentTag != null && mCurrentTag.isBookmarked()); From 09cc0b5c9fd944ceec4ffe75051fde734a67dd34 Mon Sep 17 00:00:00 2001 From: Gerardo Date: Wed, 21 Feb 2024 12:37:08 +0100 Subject: [PATCH 08/25] EditPostActivity - Update showVideoDurationLimitWarning to display message in Snackbar instead of a Toast, since there's a limitation of two lines max starting in Android 12 --- .../org/wordpress/android/ui/posts/EditPostActivity.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index 1604569719e9..80f000355921 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -3932,7 +3932,12 @@ public void onMediaModelsCreatedFromOptimizedUris(@NonNull Map Date: Wed, 21 Feb 2024 18:01:28 +0100 Subject: [PATCH 09/25] tests: add unit test for feature annotation processing --- libs/processors/build.gradle | 1 + .../processor/RemoteConfigProcessorTest.kt | 49 +++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 libs/processors/src/test/kotlin/org/wordpress/android/processor/RemoteConfigProcessorTest.kt diff --git a/libs/processors/build.gradle b/libs/processors/build.gradle index 8e338bd2ea76..a98f3bd76530 100644 --- a/libs/processors/build.gradle +++ b/libs/processors/build.gradle @@ -14,6 +14,7 @@ dependencies { kapt "com.google.auto.service:auto-service:$googleAutoServiceVersion" implementation "com.squareup:kotlinpoet:$squareupKotlinPoetVersion" + testImplementation "com.github.tschuchortdev:kotlin-compile-testing:1.5.0" testImplementation "junit:junit:$junitVersion" testImplementation "org.assertj:assertj-core:$assertjVersion" } diff --git a/libs/processors/src/test/kotlin/org/wordpress/android/processor/RemoteConfigProcessorTest.kt b/libs/processors/src/test/kotlin/org/wordpress/android/processor/RemoteConfigProcessorTest.kt new file mode 100644 index 000000000000..8ffb5ea40ff8 --- /dev/null +++ b/libs/processors/src/test/kotlin/org/wordpress/android/processor/RemoteConfigProcessorTest.kt @@ -0,0 +1,49 @@ +package org.wordpress.android.processor + +import com.tschuchort.compiletesting.KotlinCompilation +import com.tschuchort.compiletesting.SourceFile +import org.assertj.core.api.Assertions.assertThat +import org.junit.Test + +class RemoteConfigProcessorTest { + + @Test + fun `given a class with features annotation, when compiling, generate expected configuration check`() { + // given + val featureA = SourceFile.kotlin( + "Feature.kt", """ + import org.wordpress.android.annotation.Feature + import org.wordpress.android.util.config.AppConfig + + @Feature("remoteField", false) + class A(appConfig: AppConfig, val remoteField: String ="foo") + """ + ) + + // when + val result = compile(listOf(featureA)) + + // then + assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.OK) + assertThat(result.classLoader.loadClass("org.wordpress.android.util.config.RemoteFeatureConfigCheck")) + .hasDeclaredMethods("checkRemoteFields") + } + + private fun compile(src: List) = KotlinCompilation().apply { + sources = src + fakeAppConfig + annotationProcessors = listOf(RemoteConfigProcessor()) + inheritClassPath = true + messageOutputStream = System.out + }.compile() + + // Fake AppConfig is needed, as it's a class that is expected to be present in the classpath. Originally, this class + // is placed in `WordPress` module. + private val fakeAppConfig = SourceFile.kotlin( + "AppConfig.kt", """ + package org.wordpress.android.util.config + + class AppConfig + """ + ) + +} From 3876f2b549b4fe9fc5ac33dd66b4417457d31c1d Mon Sep 17 00:00:00 2001 From: Wojtek Zieba Date: Wed, 21 Feb 2024 16:15:39 +0100 Subject: [PATCH 10/25] tests: add a test for remote field annotation (defaults generator) --- libs/processors/build.gradle | 1 + .../processor/RemoteConfigProcessorTest.kt | 51 ++++++++++++++++--- 2 files changed, 44 insertions(+), 8 deletions(-) diff --git a/libs/processors/build.gradle b/libs/processors/build.gradle index a98f3bd76530..77eb4965cfe2 100644 --- a/libs/processors/build.gradle +++ b/libs/processors/build.gradle @@ -17,4 +17,5 @@ dependencies { testImplementation "com.github.tschuchortdev:kotlin-compile-testing:1.5.0" testImplementation "junit:junit:$junitVersion" testImplementation "org.assertj:assertj-core:$assertjVersion" + testImplementation "org.jetbrains.kotlin:kotlin-reflect:$gradle.ext.kotlinVersion" } diff --git a/libs/processors/src/test/kotlin/org/wordpress/android/processor/RemoteConfigProcessorTest.kt b/libs/processors/src/test/kotlin/org/wordpress/android/processor/RemoteConfigProcessorTest.kt index 8ffb5ea40ff8..c60e078a1d1c 100644 --- a/libs/processors/src/test/kotlin/org/wordpress/android/processor/RemoteConfigProcessorTest.kt +++ b/libs/processors/src/test/kotlin/org/wordpress/android/processor/RemoteConfigProcessorTest.kt @@ -3,30 +3,55 @@ package org.wordpress.android.processor import com.tschuchort.compiletesting.KotlinCompilation import com.tschuchort.compiletesting.SourceFile import org.assertj.core.api.Assertions.assertThat +import org.jetbrains.kotlin.utils.addToStdlib.cast import org.junit.Test class RemoteConfigProcessorTest { @Test fun `given a class with features annotation, when compiling, generate expected configuration check`() { + // when + val result = compile(listOf(featureA)) + + // then + assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.OK) + assertThat(result.classLoader.loadClass("org.wordpress.android.util.config.RemoteFeatureConfigCheck")) + .hasDeclaredMethods("checkRemoteFields") + } + + @Test + fun `given a class with remote field annotation, when compiling, generate expected config defaults class`() { // given - val featureA = SourceFile.kotlin( - "Feature.kt", """ - import org.wordpress.android.annotation.Feature + val remoteFieldA = SourceFile.kotlin( + "RemoteField.kt", """ + import org.wordpress.android.annotation.RemoteFieldDefaultGenerater import org.wordpress.android.util.config.AppConfig - @Feature("remoteField", false) - class A(appConfig: AppConfig, val remoteField: String ="foo") + @RemoteFieldDefaultGenerater(remoteField = "remoteField", defaultValue = "default") + class RemoteFieldA """ ) // when - val result = compile(listOf(featureA)) + val result = compile( + listOf( + remoteFieldA, + featureA, /* adding a feature, as without it, annotation processor won't start */ + ) + ) // then assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.OK) - assertThat(result.classLoader.loadClass("org.wordpress.android.util.config.RemoteFeatureConfigCheck")) - .hasDeclaredMethods("checkRemoteFields") + val remoteFieldConfigDefaultsClass = + result.classLoader.loadClass("org.wordpress.android.util.config.RemoteFieldConfigDefaults") + val remoteFieldConfigDefaultsObject = remoteFieldConfigDefaultsClass.kotlin.objectInstance + + assertThat( + remoteFieldConfigDefaultsClass.getDeclaredField("remoteFieldConfigDefaults") + .apply { isAccessible = true } + .get(remoteFieldConfigDefaultsObject) + .cast>() + ).containsEntry("remoteField", "default") } private fun compile(src: List) = KotlinCompilation().apply { @@ -46,4 +71,14 @@ class RemoteConfigProcessorTest { """ ) + private val featureA = SourceFile.kotlin( + "Feature.kt", """ + import org.wordpress.android.annotation.Feature + import org.wordpress.android.util.config.AppConfig + + @Feature("remoteField", false) + class FeatureA(appConfig: AppConfig, val remoteField: String ="foo") + """ + ) + } From 71a71d68f528ae66a9992eba9260f42244b42e9a Mon Sep 17 00:00:00 2001 From: Wojtek Zieba Date: Wed, 21 Feb 2024 16:24:50 +0100 Subject: [PATCH 11/25] tests: add a test for features and experiments (defaults generator) --- .../processor/RemoteConfigProcessorTest.kt | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/libs/processors/src/test/kotlin/org/wordpress/android/processor/RemoteConfigProcessorTest.kt b/libs/processors/src/test/kotlin/org/wordpress/android/processor/RemoteConfigProcessorTest.kt index c60e078a1d1c..f99c2e3aacc6 100644 --- a/libs/processors/src/test/kotlin/org/wordpress/android/processor/RemoteConfigProcessorTest.kt +++ b/libs/processors/src/test/kotlin/org/wordpress/android/processor/RemoteConfigProcessorTest.kt @@ -54,6 +54,41 @@ class RemoteConfigProcessorTest { ).containsEntry("remoteField", "default") } + @Test + fun `given class with feature and class with experiment annotation, when compiling, generate expected config defaults class`() { + // given + val experiment = SourceFile.kotlin( + "Experiment.kt", """ + import org.wordpress.android.annotation.Experiment + import org.wordpress.android.util.config.AppConfig + + @Experiment("experimentFeature", "defaultVariant") + class Experiment + """ + ) + + // when + val result = compile(listOf(featureA, experiment)) + + // then + assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.OK) + val remoteFieldConfigDefaultsClass = + result.classLoader.loadClass("org.wordpress.android.util.config.RemoteFeatureConfigDefaults") + val remoteFieldConfigDefaultsObject = remoteFieldConfigDefaultsClass.kotlin.objectInstance + + assertThat( + remoteFieldConfigDefaultsClass.getDeclaredField("remoteFeatureConfigDefaults") + .apply { isAccessible = true } + .get(remoteFieldConfigDefaultsObject) + .cast>() + ).containsExactlyInAnyOrderEntriesOf( + mapOf( + "experimentFeature" to "defaultVariant", + "remoteField" to "false" + ) + ) + } + private fun compile(src: List) = KotlinCompilation().apply { sources = src + fakeAppConfig annotationProcessors = listOf(RemoteConfigProcessor()) From 8586e0fc3f7403a20db959d7722215e919cdc656 Mon Sep 17 00:00:00 2001 From: Wojtek Zieba Date: Wed, 21 Feb 2024 17:55:52 +0100 Subject: [PATCH 12/25] tests: add a test for features in development generation --- .../processor/RemoteConfigProcessorTest.kt | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/libs/processors/src/test/kotlin/org/wordpress/android/processor/RemoteConfigProcessorTest.kt b/libs/processors/src/test/kotlin/org/wordpress/android/processor/RemoteConfigProcessorTest.kt index f99c2e3aacc6..b6ab50d085fe 100644 --- a/libs/processors/src/test/kotlin/org/wordpress/android/processor/RemoteConfigProcessorTest.kt +++ b/libs/processors/src/test/kotlin/org/wordpress/android/processor/RemoteConfigProcessorTest.kt @@ -89,6 +89,40 @@ class RemoteConfigProcessorTest { ) } + @Test + fun `given class with feature in development annotation, when compiling, generate expected list of classes`() { + // given + val experiment = SourceFile.kotlin( + "Experiment.kt", """ + import org.wordpress.android.annotation.FeatureInDevelopment + import org.wordpress.android.util.config.AppConfig + + @FeatureInDevelopment + class DevFeature + """ + ) + + // when + val result = compile( + listOf( + experiment, + featureA, /* adding a feature, as without it, annotation processor won't start */ + ) + ) + + // then + + val featuresInDevelopmentClass = + result.classLoader.loadClass("org.wordpress.android.util.config.FeaturesInDevelopment") + val featuresInDevelopmentObject = featuresInDevelopmentClass.kotlin.objectInstance + assertThat( + featuresInDevelopmentClass.getDeclaredField("featuresInDevelopment") + .apply { isAccessible = true } + .get(featuresInDevelopmentObject) + .cast>() + ).containsOnly("DevFeature") + } + private fun compile(src: List) = KotlinCompilation().apply { sources = src + fakeAppConfig annotationProcessors = listOf(RemoteConfigProcessor()) From 305cf90e412d0e5c886ea5def6d2e9d0610e95bf Mon Sep 17 00:00:00 2001 From: Wojtek Zieba Date: Wed, 21 Feb 2024 18:26:47 +0100 Subject: [PATCH 13/25] style: fix checkstyle --- .../wordpress/android/processor/RemoteConfigProcessorTest.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libs/processors/src/test/kotlin/org/wordpress/android/processor/RemoteConfigProcessorTest.kt b/libs/processors/src/test/kotlin/org/wordpress/android/processor/RemoteConfigProcessorTest.kt index b6ab50d085fe..b4ee3385c125 100644 --- a/libs/processors/src/test/kotlin/org/wordpress/android/processor/RemoteConfigProcessorTest.kt +++ b/libs/processors/src/test/kotlin/org/wordpress/android/processor/RemoteConfigProcessorTest.kt @@ -7,7 +7,6 @@ import org.jetbrains.kotlin.utils.addToStdlib.cast import org.junit.Test class RemoteConfigProcessorTest { - @Test fun `given a class with features annotation, when compiling, generate expected configuration check`() { // when @@ -55,7 +54,7 @@ class RemoteConfigProcessorTest { } @Test - fun `given class with feature and class with experiment annotation, when compiling, generate expected config defaults class`() { + fun `given class with feature and experiment annotation, when compiling, generate config defaults class`() { // given val experiment = SourceFile.kotlin( "Experiment.kt", """ @@ -149,5 +148,4 @@ class RemoteConfigProcessorTest { class FeatureA(appConfig: AppConfig, val remoteField: String ="foo") """ ) - } From dbfcb6e235db0447e9e57d9e95f0f1e4d4d9ea5a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 Feb 2024 18:39:05 +0000 Subject: [PATCH 14/25] Bump se.bjurr.violations.violation-comments-to-github-gradle-plugin Bumps se.bjurr.violations.violation-comments-to-github-gradle-plugin from 1.67 to 1.70.0. --- updated-dependencies: - dependency-name: se.bjurr.violations.violation-comments-to-github-gradle-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- settings.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle b/settings.gradle index a092afee5eb6..c2109be8a27c 100644 --- a/settings.gradle +++ b/settings.gradle @@ -6,7 +6,7 @@ pluginManagement { gradle.ext.sentryVersion = '3.14.0' gradle.ext.daggerVersion = "2.50" gradle.ext.detektVersion = '1.23.0' - gradle.ext.violationCommentsVersion = '1.67' + gradle.ext.violationCommentsVersion = '1.70.0' gradle.ext.measureBuildsVersion = '2.0.3' gradle.ext.koverVersion = '0.7.5' From c702921923985833cb695944e014795b4357a7d6 Mon Sep 17 00:00:00 2001 From: Thomas Horta Date: Wed, 21 Feb 2024 15:39:06 -0300 Subject: [PATCH 15/25] Remove displayNameUpdatedWasNeeded variable (PR comments) --- .../services/update/ReaderUpdateLogic.java | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/services/update/ReaderUpdateLogic.java b/WordPress/src/main/java/org/wordpress/android/ui/reader/services/update/ReaderUpdateLogic.java index bafd6275709e..e743d7f52bfa 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/services/update/ReaderUpdateLogic.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/services/update/ReaderUpdateLogic.java @@ -123,24 +123,21 @@ public void onErrorResponse(VolleyError volleyError) { .get("read/menu", params, null, listener, errorListener); } - private boolean displayNameUpdateWasNeeded(ReaderTagList serverTopics) { - boolean updateDone = false; - + /** + * Update the display names of the default tags (such as Subscribed and Discover) in the serverTopics list. + * + * @param serverTopics The list of default tags. + */ + private void updateDisplayNamesIfNeeded(@NonNull ReaderTagList serverTopics) { for (ReaderTag tag : serverTopics) { - String tagNameBefore = tag.getTagDisplayName(); if (tag.isFollowedSites()) { tag.setTagDisplayName(mContext.getString(R.string.reader_subscribed_display_name)); - if (!tagNameBefore.equals(tag.getTagDisplayName())) updateDone = true; } else if (tag.isDiscover()) { tag.setTagDisplayName(mContext.getString(R.string.reader_discover_display_name)); - if (!tagNameBefore.equals(tag.getTagDisplayName())) updateDone = true; } else if (tag.isPostsILike()) { tag.setTagDisplayName(mContext.getString(R.string.reader_my_likes_display_name)); - if (!tagNameBefore.equals(tag.getTagDisplayName())) updateDone = true; } } - - return updateDone; } private void handleUpdateTagsResponse(final JSONObject jsonObject) { @@ -152,7 +149,7 @@ public void run() { ReaderTagList serverTopics = new ReaderTagList(); serverTopics.addAll(parseTags(jsonObject, "default", ReaderTagType.DEFAULT)); - boolean displayNameUpdateWasNeeded = displayNameUpdateWasNeeded(serverTopics); + updateDisplayNamesIfNeeded(serverTopics); serverTopics.addAll(parseTags(jsonObject, "subscribed", ReaderTagType.FOLLOWED)); @@ -181,8 +178,7 @@ public void run() { boolean didChangeFollowedTags = false; if (!localTopics.isSameList(serverTopics)) { - AppLog.d(AppLog.T.READER, "reader service > followed topics changed " - + "updatedDisplayNames [" + displayNameUpdateWasNeeded + "]"); + AppLog.d(AppLog.T.READER, "reader service > followed topics changed"); if (!mAccountStore.hasAccessToken()) { // Do not delete locally saved tags for logged out user From a8b6c32571bf6572b7dfbf6170e6ec55c550ffda Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Wed, 21 Feb 2024 14:28:07 -0500 Subject: [PATCH 16/25] Update release notes for 24.3 --- WordPress/jetpack_metadata/release_notes.txt | 5 ++--- WordPress/metadata/release_notes.txt | 3 +-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/WordPress/jetpack_metadata/release_notes.txt b/WordPress/jetpack_metadata/release_notes.txt index be8790a36766..17d689ccd4c5 100644 --- a/WordPress/jetpack_metadata/release_notes.txt +++ b/WordPress/jetpack_metadata/release_notes.txt @@ -1,3 +1,2 @@ -* [**] Added support to use third-party passkey providers and other devices passkeys as a WordPress.com login option [https://github.com/wordpress-mobile/WordPress-Android/pull/20174] -* [*] [Jetpack-only] Fix the visibility issue with the menu button on the stats [https://github.com/wordpress-mobile/WordPress-Android/pull/20175] - +Log in to your site with Google credentials, physical devices, and third-party passkeys. Don’t worry, the site’s still locked down tighter than the Colonel’s secret recipe. +We hid the menu icon on Stats screens so it’s only visible from the Insights tab. Ninja mode: activated. diff --git a/WordPress/metadata/release_notes.txt b/WordPress/metadata/release_notes.txt index d16d3ea03efd..89c2c07ee6ac 100644 --- a/WordPress/metadata/release_notes.txt +++ b/WordPress/metadata/release_notes.txt @@ -1,2 +1 @@ -* [**] Added support to use third-party passkey providers and other devices passkeys as a WordPress.com login option [https://github.com/wordpress-mobile/WordPress-Android/pull/20174] - +You can log in to your WordPress website using Google credentials, physical devices, and other third-party passkeys. Don’t worry, your site is still locked down tighter than the Colonel’s secret recipe. From a5195264e407f247e74bbba9d6a054fa911349f5 Mon Sep 17 00:00:00 2001 From: Automattic Release Bot Date: Wed, 21 Feb 2024 19:30:36 +0000 Subject: [PATCH 17/25] Update WordPress `PlayStoreStrings.po` for version 24.3 --- WordPress/metadata/PlayStoreStrings.po | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/WordPress/metadata/PlayStoreStrings.po b/WordPress/metadata/PlayStoreStrings.po index c7dffa2f5f85..9e2282892dec 100644 --- a/WordPress/metadata/PlayStoreStrings.po +++ b/WordPress/metadata/PlayStoreStrings.po @@ -10,6 +10,12 @@ msgstr "" "X-Generator: VsCode\n" "Project-Id-Version: Release Notes & Play Store Descriptions\n" +msgctxt "release_note_243" +msgid "" +"24.3:\n" +"You can log in to your WordPress website using Google credentials, physical devices, and other third-party passkeys. Don’t worry, your site is still locked down tighter than the Colonel’s secret recipe.\n" +msgstr "" + msgctxt "release_note_242" msgid "" "24.2:\n" @@ -18,15 +24,6 @@ msgid "" "The editor won’t crash anymore when you’re working on large posts. That’s right, we’ve saved your drafts and your sanity.\n" msgstr "" -msgctxt "release_note_241" -msgid "" -"24.1:\n" -"- Get notified when you’re working offline.\n" -"- Image block uploads pause when you lose internet and resume when you reconnect.\n" -"- Select a custom gradient in the editor and see a color indicator.\n" -"- “Forward” and “back” arrows are correct for right-to-left readers.\n" -msgstr "" - #. translators: Release notes for this version to be displayed in the Play Store. Limit to 500 characters including spaces and commas! #. translators: Shorter Release notes for this version to be displayed in the Play Store. Limit to 500 characters including spaces and commas! msgctxt "sample_post_content" From 51fd8fada9390c738cf00490cfa1cc533e1cb06d Mon Sep 17 00:00:00 2001 From: Automattic Release Bot Date: Wed, 21 Feb 2024 19:30:36 +0000 Subject: [PATCH 18/25] Update Jetpack `PlayStoreStrings.po` for version 24.3 --- WordPress/jetpack_metadata/PlayStoreStrings.po | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/WordPress/jetpack_metadata/PlayStoreStrings.po b/WordPress/jetpack_metadata/PlayStoreStrings.po index 486ae0460084..46c0d8b9741a 100644 --- a/WordPress/jetpack_metadata/PlayStoreStrings.po +++ b/WordPress/jetpack_metadata/PlayStoreStrings.po @@ -10,6 +10,13 @@ msgstr "" "X-Generator: VsCode\n" "Project-Id-Version: Jetpack - Apps - Android - Release Notes\n" +msgctxt "release_note_243" +msgid "" +"24.3:\n" +"Log in to your site with Google credentials, physical devices, and third-party passkeys. Don’t worry, the site’s still locked down tighter than the Colonel’s secret recipe.\n" +"We hid the menu icon on Stats screens so it’s only visible from the Insights tab. Ninja mode: activated.\n" +msgstr "" + msgctxt "release_note_242" msgid "" "24.2:\n" @@ -19,17 +26,6 @@ msgid "" "- We added new Site Monitoring menu items like metrics, PHP logs, and web server logs.\n" msgstr "" -msgctxt "release_note_241" -msgid "" -"24.1:\n" -"- Get notified when you’re working offline.\n" -"- Image block uploads pause/resume with internet connection.\n" -"- See custom gradient selections in the editor.\n" -"- Fixed forward/back arrows for right-to-left readers.\n" -"- Daily Prompt tags work properly.\n" -"- Tap Site Domain cards to manage domains.\n" -msgstr "" - #. translators: Release notes for this version to be displayed in the Play Store. Limit to 500 characters including spaces and commas! #. translators: Title to be displayed in the Play Store. Limit to 30 characters including spaces and commas! msgctxt "play_store_app_title" From 8c2c169093cc5cec65aa57e26c90817fb3a440f2 Mon Sep 17 00:00:00 2001 From: Ravi Date: Thu, 22 Feb 2024 13:15:15 +1100 Subject: [PATCH 19/25] Update InsightsManagementMapper.kt Remove Today Stats from Insights when TrafficTab is enabled --- .../insights/management/InsightsManagementMapper.kt | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/InsightsManagementMapper.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/InsightsManagementMapper.kt index 2ce68123cd8d..1c619ebec6f9 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/InsightsManagementMapper.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/InsightsManagementMapper.kt @@ -33,6 +33,7 @@ import org.wordpress.android.ui.stats.refresh.lists.sections.insights.management import org.wordpress.android.ui.stats.refresh.lists.sections.insights.management.InsightsManagementViewModel.InsightListItem.InsightModel.Status.ADDED import org.wordpress.android.ui.stats.refresh.lists.sections.insights.management.InsightsManagementViewModel.InsightListItem.InsightModel.Status.REMOVED import org.wordpress.android.ui.utils.ListItemInteraction +import org.wordpress.android.util.config.StatsTrafficTabFeatureConfig import javax.inject.Inject import javax.inject.Named @@ -47,17 +48,23 @@ private val ACTIVITY_INSIGHTS = mutableListOf( private val GENERAL_INSIGHTS = mutableListOf( ALL_TIME_STATS, MOST_POPULAR_DAY_AND_HOUR, - ANNUAL_SITE_STATS, - TODAY_STATS + ANNUAL_SITE_STATS ) class InsightsManagementMapper @Inject constructor( - @Named(BG_THREAD) private val bgDispatcher: CoroutineDispatcher + @Named(BG_THREAD) private val bgDispatcher: CoroutineDispatcher, + private val trafficTabFeatureConfig: StatsTrafficTabFeatureConfig ) { suspend fun buildUIModel(addedTypes: Set, onClick: (InsightType) -> Unit) = withContext(bgDispatcher) { val insightListItems = mutableListOf() insightListItems += Header(R.string.stats_insights_management_general) + if (BuildConfig.IS_JETPACK_APP && + !trafficTabFeatureConfig.isEnabled() && + !GENERAL_INSIGHTS.contains(TODAY_STATS) + ) { + GENERAL_INSIGHTS.add(TODAY_STATS) + } if (BuildConfig.IS_JETPACK_APP && !GENERAL_INSIGHTS.contains(VIEWS_AND_VISITORS)) { GENERAL_INSIGHTS.add(0, VIEWS_AND_VISITORS) } From cb86656ea0f02942c585083e9470f5ce34121375 Mon Sep 17 00:00:00 2001 From: Ravi Date: Thu, 22 Feb 2024 13:16:26 +1100 Subject: [PATCH 20/25] Update StatsModule.kt Add Today Stats only when Traffic Tab is not enabled --- .../wordpress/android/ui/stats/refresh/StatsModule.kt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/StatsModule.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/StatsModule.kt index 08881ec68a44..407b7ab2b6fe 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/StatsModule.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/StatsModule.kt @@ -126,7 +126,8 @@ class StatsModule { managementNewsCardUseCase: ManagementNewsCardUseCase, actionCardGrowUseCase: ActionCardGrowUseCase, actionCardReminderUseCase: ActionCardReminderUseCase, - actionCardScheduleUseCase: ActionCardScheduleUseCase + actionCardScheduleUseCase: ActionCardScheduleUseCase, + trafficTabFeatureConfig: StatsTrafficTabFeatureConfig ): List<@JvmSuppressWildcards BaseStatsUseCase<*, *>> { val useCases = mutableListOf>() if (BuildConfig.IS_JETPACK_APP) { @@ -140,11 +141,15 @@ class StatsModule { } else { useCases.add(followerTotalsUseCase) } + + if (!trafficTabFeatureConfig.isEnabled()) { + useCases.add(todayStatsUseCase) + } + useCases.addAll( listOf( allTimeStatsUseCase, latestPostSummaryUseCase, - todayStatsUseCase, followersUseCaseFactory.build(BLOCK), commentsUseCase, mostPopularInsightsUseCase, From 88734d0e158b904cfd842c5f5f46d69751e62292 Mon Sep 17 00:00:00 2001 From: Ravi Date: Thu, 22 Feb 2024 15:57:35 +1100 Subject: [PATCH 21/25] Update InsightsManagementMapperTest.kt --- .../InsightsManagementMapperTest.kt | 62 ++++++++++--------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/InsightsManagementMapperTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/InsightsManagementMapperTest.kt index b1b0a69db246..14e5bf6c057d 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/InsightsManagementMapperTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/InsightsManagementMapperTest.kt @@ -4,6 +4,7 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi import org.assertj.core.api.Assertions.assertThat import org.junit.Before import org.junit.Test +import org.mockito.Mock import org.wordpress.android.BaseUnitTest import org.wordpress.android.R import org.wordpress.android.fluxc.store.StatsStore.InsightType @@ -16,22 +17,26 @@ import org.wordpress.android.fluxc.store.StatsStore.InsightType.MOST_POPULAR_DAY import org.wordpress.android.fluxc.store.StatsStore.InsightType.POSTING_ACTIVITY import org.wordpress.android.fluxc.store.StatsStore.InsightType.PUBLICIZE import org.wordpress.android.fluxc.store.StatsStore.InsightType.TAGS_AND_CATEGORIES -import org.wordpress.android.fluxc.store.StatsStore.InsightType.TODAY_STATS import org.wordpress.android.ui.stats.refresh.lists.sections.insights.management.InsightsManagementViewModel.InsightListItem import org.wordpress.android.ui.stats.refresh.lists.sections.insights.management.InsightsManagementViewModel.InsightListItem.Header import org.wordpress.android.ui.stats.refresh.lists.sections.insights.management.InsightsManagementViewModel.InsightListItem.InsightModel import org.wordpress.android.ui.stats.refresh.lists.sections.insights.management.InsightsManagementViewModel.InsightListItem.InsightModel.Status +import org.wordpress.android.util.config.StatsTrafficTabFeatureConfig @ExperimentalCoroutinesApi class InsightsManagementMapperTest : BaseUnitTest() { + @Mock + private lateinit var trafficTabFeatureConfig: StatsTrafficTabFeatureConfig + private lateinit var insightsManagementMapper: InsightsManagementMapper - private val insightTypeCount = 10 // POSTS_AND_PAGES_INSIGHTS.size + ACTIVITY_INSIGHTS.size + GENERAL_INSIGHTS.size + private var insightTypeCount = 9 // POSTS_AND_PAGES_INSIGHTS.size + ACTIVITY_INSIGHTS.size + GENERAL_INSIGHTS.size private val sectionsCount = 3 @Before fun setUp() { insightsManagementMapper = InsightsManagementMapper( - testDispatcher() + testDispatcher(), + trafficTabFeatureConfig ) } @@ -49,15 +54,14 @@ class InsightsManagementMapperTest : BaseUnitTest() { assertInsight(result[1], ALL_TIME_STATS, true) assertInsight(result[2], MOST_POPULAR_DAY_AND_HOUR, true) assertInsight(result[3], ANNUAL_SITE_STATS, true) - assertInsight(result[4], TODAY_STATS, true) - assertHeader(result[5], R.string.stats_insights_management_posts_and_pages) - assertInsight(result[6], LATEST_POST_SUMMARY, true) - assertInsight(result[7], POSTING_ACTIVITY, true) - assertInsight(result[8], TAGS_AND_CATEGORIES, true) - assertHeader(result[9], R.string.stats_insights_management_activity) - assertInsight(result[10], FOLLOWERS, true) - assertInsight(result[11], FOLLOWER_TOTALS, true) - assertInsight(result[12], PUBLICIZE, true) + assertHeader(result[4], R.string.stats_insights_management_posts_and_pages) + assertInsight(result[5], LATEST_POST_SUMMARY, true) + assertInsight(result[6], POSTING_ACTIVITY, true) + assertInsight(result[7], TAGS_AND_CATEGORIES, true) + assertHeader(result[8], R.string.stats_insights_management_activity) + assertInsight(result[9], FOLLOWERS, true) + assertInsight(result[10], FOLLOWER_TOTALS, true) + assertInsight(result[11], PUBLICIZE, true) } @Test @@ -74,15 +78,14 @@ class InsightsManagementMapperTest : BaseUnitTest() { assertInsight(result[1], ALL_TIME_STATS, true) assertInsight(result[2], MOST_POPULAR_DAY_AND_HOUR, false) assertInsight(result[3], ANNUAL_SITE_STATS, false) - assertInsight(result[4], TODAY_STATS, false) - assertHeader(result[5], R.string.stats_insights_management_posts_and_pages) - assertInsight(result[6], LATEST_POST_SUMMARY, false) - assertInsight(result[7], POSTING_ACTIVITY, false) - assertInsight(result[8], TAGS_AND_CATEGORIES, false) - assertHeader(result[9], R.string.stats_insights_management_activity) - assertInsight(result[10], FOLLOWERS, false) - assertInsight(result[11], FOLLOWER_TOTALS, false) - assertInsight(result[12], PUBLICIZE, true) + assertHeader(result[4], R.string.stats_insights_management_posts_and_pages) + assertInsight(result[5], LATEST_POST_SUMMARY, false) + assertInsight(result[6], POSTING_ACTIVITY, false) + assertInsight(result[7], TAGS_AND_CATEGORIES, false) + assertHeader(result[8], R.string.stats_insights_management_activity) + assertInsight(result[9], FOLLOWERS, false) + assertInsight(result[10], FOLLOWER_TOTALS, false) + assertInsight(result[11], PUBLICIZE, true) } @Test @@ -96,15 +99,14 @@ class InsightsManagementMapperTest : BaseUnitTest() { assertInsight(result[1], ALL_TIME_STATS, false) assertInsight(result[2], MOST_POPULAR_DAY_AND_HOUR, false) assertInsight(result[3], ANNUAL_SITE_STATS, false) - assertInsight(result[4], TODAY_STATS, false) - assertHeader(result[5], R.string.stats_insights_management_posts_and_pages) - assertInsight(result[6], LATEST_POST_SUMMARY, false) - assertInsight(result[7], POSTING_ACTIVITY, false) - assertInsight(result[8], TAGS_AND_CATEGORIES, false) - assertHeader(result[9], R.string.stats_insights_management_activity) - assertInsight(result[10], FOLLOWERS, false) - assertInsight(result[11], FOLLOWER_TOTALS, false) - assertInsight(result[12], PUBLICIZE, false) + assertHeader(result[4], R.string.stats_insights_management_posts_and_pages) + assertInsight(result[5], LATEST_POST_SUMMARY, false) + assertInsight(result[6], POSTING_ACTIVITY, false) + assertInsight(result[7], TAGS_AND_CATEGORIES, false) + assertHeader(result[8], R.string.stats_insights_management_activity) + assertInsight(result[9], FOLLOWERS, false) + assertInsight(result[10], FOLLOWER_TOTALS, false) + assertInsight(result[11], PUBLICIZE, false) } private fun assertHeader(item: InsightListItem, text: Int) { From 66e3191ed64a61d19bdc6423135d28ada7daf19d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 22 Feb 2024 08:57:07 +0000 Subject: [PATCH 22/25] Bump mockitoVersion from 5.3.1 to 5.10.0 Bumps `mockitoVersion` from 5.3.1 to 5.10.0. Updates `org.mockito:mockito-core` from 5.3.1 to 5.10.0 - [Release notes](https://github.com/mockito/mockito/releases) - [Commits](https://github.com/mockito/mockito/compare/v5.3.1...v5.10.0) Updates `org.mockito:mockito-android` from 5.3.1 to 5.10.0 - [Release notes](https://github.com/mockito/mockito/releases) - [Commits](https://github.com/mockito/mockito/compare/v5.3.1...v5.10.0) --- updated-dependencies: - dependency-name: org.mockito:mockito-core dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.mockito:mockito-android dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index eba5484f157b..743b387e0d37 100644 --- a/build.gradle +++ b/build.gradle @@ -97,7 +97,7 @@ ext { // test assertjVersion = '3.23.1' junitVersion = '4.13.2' - mockitoVersion = '5.3.1' + mockitoVersion = '5.10.0' mockitoKotlinVersion = '4.1.0' // android test From a51652d9fb778ebba594a8faeeffcc15f243120d Mon Sep 17 00:00:00 2001 From: Ravi Date: Fri, 23 Feb 2024 08:11:56 +1100 Subject: [PATCH 23/25] Update InsightsManagementMapper.kt Remove IS_JETPACK_APP check since Stats only on Jetpack app now --- .../insights/management/InsightsManagementMapper.kt | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/InsightsManagementMapper.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/InsightsManagementMapper.kt index 1c619ebec6f9..d0f9ecfe1c45 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/InsightsManagementMapper.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/InsightsManagementMapper.kt @@ -2,7 +2,6 @@ package org.wordpress.android.ui.stats.refresh.lists.sections.insights.managemen import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.withContext -import org.wordpress.android.BuildConfig import org.wordpress.android.R import org.wordpress.android.fluxc.store.StatsStore.InsightType import org.wordpress.android.fluxc.store.StatsStore.InsightType.ACTION_GROW @@ -59,13 +58,10 @@ class InsightsManagementMapper @Inject constructor( withContext(bgDispatcher) { val insightListItems = mutableListOf() insightListItems += Header(R.string.stats_insights_management_general) - if (BuildConfig.IS_JETPACK_APP && - !trafficTabFeatureConfig.isEnabled() && - !GENERAL_INSIGHTS.contains(TODAY_STATS) - ) { + if (!trafficTabFeatureConfig.isEnabled() && !GENERAL_INSIGHTS.contains(TODAY_STATS)) { GENERAL_INSIGHTS.add(TODAY_STATS) } - if (BuildConfig.IS_JETPACK_APP && !GENERAL_INSIGHTS.contains(VIEWS_AND_VISITORS)) { + if (!GENERAL_INSIGHTS.contains(VIEWS_AND_VISITORS)) { GENERAL_INSIGHTS.add(0, VIEWS_AND_VISITORS) } insightListItems += GENERAL_INSIGHTS.map { type -> @@ -77,7 +73,7 @@ class InsightsManagementMapper @Inject constructor( } insightListItems += Header(R.string.stats_insights_management_activity) - if (BuildConfig.IS_JETPACK_APP && ACTIVITY_INSIGHTS.contains(FOLLOWER_TOTALS)) { + if (ACTIVITY_INSIGHTS.contains(FOLLOWER_TOTALS)) { // Replace FOLLOWER_TOTALS with Stats revamp v2 total insights val followerTotalsIndex = ACTIVITY_INSIGHTS.indexOf(FOLLOWER_TOTALS) ACTIVITY_INSIGHTS.remove(FOLLOWER_TOTALS) From 0d23445a026f225aec15dc4f131f82fc83be47d9 Mon Sep 17 00:00:00 2001 From: Ravi Date: Fri, 23 Feb 2024 09:59:25 +1100 Subject: [PATCH 24/25] Update InsightsManagementMapperTest.kt --- .../InsightsManagementMapperTest.kt | 90 ++++++++++--------- 1 file changed, 47 insertions(+), 43 deletions(-) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/InsightsManagementMapperTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/InsightsManagementMapperTest.kt index 14e5bf6c057d..e28a7479031d 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/InsightsManagementMapperTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/InsightsManagementMapperTest.kt @@ -8,15 +8,7 @@ import org.mockito.Mock import org.wordpress.android.BaseUnitTest import org.wordpress.android.R import org.wordpress.android.fluxc.store.StatsStore.InsightType -import org.wordpress.android.fluxc.store.StatsStore.InsightType.ALL_TIME_STATS -import org.wordpress.android.fluxc.store.StatsStore.InsightType.ANNUAL_SITE_STATS -import org.wordpress.android.fluxc.store.StatsStore.InsightType.FOLLOWERS -import org.wordpress.android.fluxc.store.StatsStore.InsightType.FOLLOWER_TOTALS -import org.wordpress.android.fluxc.store.StatsStore.InsightType.LATEST_POST_SUMMARY -import org.wordpress.android.fluxc.store.StatsStore.InsightType.MOST_POPULAR_DAY_AND_HOUR -import org.wordpress.android.fluxc.store.StatsStore.InsightType.POSTING_ACTIVITY -import org.wordpress.android.fluxc.store.StatsStore.InsightType.PUBLICIZE -import org.wordpress.android.fluxc.store.StatsStore.InsightType.TAGS_AND_CATEGORIES +import org.wordpress.android.fluxc.store.StatsStore.InsightType.* import org.wordpress.android.ui.stats.refresh.lists.sections.insights.management.InsightsManagementViewModel.InsightListItem import org.wordpress.android.ui.stats.refresh.lists.sections.insights.management.InsightsManagementViewModel.InsightListItem.Header import org.wordpress.android.ui.stats.refresh.lists.sections.insights.management.InsightsManagementViewModel.InsightListItem.InsightModel @@ -29,7 +21,7 @@ class InsightsManagementMapperTest : BaseUnitTest() { private lateinit var trafficTabFeatureConfig: StatsTrafficTabFeatureConfig private lateinit var insightsManagementMapper: InsightsManagementMapper - private var insightTypeCount = 9 // POSTS_AND_PAGES_INSIGHTS.size + ACTIVITY_INSIGHTS.size + GENERAL_INSIGHTS.size + private var insightTypeCount = 13 // POSTS_AND_PAGES_INSIGHTS.size + ACTIVITY_INSIGHTS.size + GENERAL_INSIGHTS.size private val sectionsCount = 3 @Before @@ -51,17 +43,21 @@ class InsightsManagementMapperTest : BaseUnitTest() { // Then assertThat(result).hasSize(insightTypeCount + sectionsCount) assertHeader(result[0], R.string.stats_insights_management_general) - assertInsight(result[1], ALL_TIME_STATS, true) - assertInsight(result[2], MOST_POPULAR_DAY_AND_HOUR, true) - assertInsight(result[3], ANNUAL_SITE_STATS, true) - assertHeader(result[4], R.string.stats_insights_management_posts_and_pages) - assertInsight(result[5], LATEST_POST_SUMMARY, true) - assertInsight(result[6], POSTING_ACTIVITY, true) - assertInsight(result[7], TAGS_AND_CATEGORIES, true) - assertHeader(result[8], R.string.stats_insights_management_activity) - assertInsight(result[9], FOLLOWERS, true) - assertInsight(result[10], FOLLOWER_TOTALS, true) - assertInsight(result[11], PUBLICIZE, true) + assertInsight(result[1], VIEWS_AND_VISITORS, true) + assertInsight(result[2], ALL_TIME_STATS, true) + assertInsight(result[3], MOST_POPULAR_DAY_AND_HOUR, true) + assertInsight(result[4], ANNUAL_SITE_STATS, true) + assertInsight(result[5], TODAY_STATS, true) + assertHeader(result[6], R.string.stats_insights_management_posts_and_pages) + assertInsight(result[7], LATEST_POST_SUMMARY, true) + assertInsight(result[8], POSTING_ACTIVITY, true) + assertInsight(result[9], TAGS_AND_CATEGORIES, true) + assertHeader(result[10], R.string.stats_insights_management_activity) + assertInsight(result[11], FOLLOWERS, true) + assertInsight(result[12], TOTAL_LIKES, true) + assertInsight(result[13], TOTAL_COMMENTS, true) + assertInsight(result[14], TOTAL_FOLLOWERS, true) + assertInsight(result[15], PUBLICIZE, true) } @Test @@ -75,17 +71,21 @@ class InsightsManagementMapperTest : BaseUnitTest() { // Then assertThat(result).hasSize(insightTypeCount + sectionsCount) assertHeader(result[0], R.string.stats_insights_management_general) - assertInsight(result[1], ALL_TIME_STATS, true) - assertInsight(result[2], MOST_POPULAR_DAY_AND_HOUR, false) - assertInsight(result[3], ANNUAL_SITE_STATS, false) - assertHeader(result[4], R.string.stats_insights_management_posts_and_pages) - assertInsight(result[5], LATEST_POST_SUMMARY, false) - assertInsight(result[6], POSTING_ACTIVITY, false) - assertInsight(result[7], TAGS_AND_CATEGORIES, false) - assertHeader(result[8], R.string.stats_insights_management_activity) - assertInsight(result[9], FOLLOWERS, false) - assertInsight(result[10], FOLLOWER_TOTALS, false) - assertInsight(result[11], PUBLICIZE, true) + assertInsight(result[1], VIEWS_AND_VISITORS, false) + assertInsight(result[2], ALL_TIME_STATS, true) + assertInsight(result[3], MOST_POPULAR_DAY_AND_HOUR, false) + assertInsight(result[4], ANNUAL_SITE_STATS, false) + assertInsight(result[5], TODAY_STATS, false) + assertHeader(result[6], R.string.stats_insights_management_posts_and_pages) + assertInsight(result[7], LATEST_POST_SUMMARY, false) + assertInsight(result[8], POSTING_ACTIVITY, false) + assertInsight(result[9], TAGS_AND_CATEGORIES, false) + assertHeader(result[10], R.string.stats_insights_management_activity) + assertInsight(result[11], FOLLOWERS, false) + assertInsight(result[12], TOTAL_LIKES, false) + assertInsight(result[13], TOTAL_COMMENTS, false) + assertInsight(result[14], TOTAL_FOLLOWERS, false) + assertInsight(result[15], PUBLICIZE, true) } @Test @@ -96,17 +96,21 @@ class InsightsManagementMapperTest : BaseUnitTest() { // Then assertThat(result).hasSize(insightTypeCount + sectionsCount) assertHeader(result[0], R.string.stats_insights_management_general) - assertInsight(result[1], ALL_TIME_STATS, false) - assertInsight(result[2], MOST_POPULAR_DAY_AND_HOUR, false) - assertInsight(result[3], ANNUAL_SITE_STATS, false) - assertHeader(result[4], R.string.stats_insights_management_posts_and_pages) - assertInsight(result[5], LATEST_POST_SUMMARY, false) - assertInsight(result[6], POSTING_ACTIVITY, false) - assertInsight(result[7], TAGS_AND_CATEGORIES, false) - assertHeader(result[8], R.string.stats_insights_management_activity) - assertInsight(result[9], FOLLOWERS, false) - assertInsight(result[10], FOLLOWER_TOTALS, false) - assertInsight(result[11], PUBLICIZE, false) + assertInsight(result[1], VIEWS_AND_VISITORS, false) + assertInsight(result[2], ALL_TIME_STATS, false) + assertInsight(result[3], MOST_POPULAR_DAY_AND_HOUR, false) + assertInsight(result[4], ANNUAL_SITE_STATS, false) + assertInsight(result[5], TODAY_STATS, false) + assertHeader(result[6], R.string.stats_insights_management_posts_and_pages) + assertInsight(result[7], LATEST_POST_SUMMARY, false) + assertInsight(result[8], POSTING_ACTIVITY, false) + assertInsight(result[9], TAGS_AND_CATEGORIES, false) + assertHeader(result[10], R.string.stats_insights_management_activity) + assertInsight(result[11], FOLLOWERS, false) + assertInsight(result[12], TOTAL_LIKES, false) + assertInsight(result[13], TOTAL_COMMENTS, false) + assertInsight(result[14], TOTAL_FOLLOWERS, false) + assertInsight(result[15], PUBLICIZE, false) } private fun assertHeader(item: InsightListItem, text: Int) { From cc8d3ca45ec9bf20168cd9f6a18f33cf7819af6b Mon Sep 17 00:00:00 2001 From: Ravi Date: Fri, 23 Feb 2024 10:12:43 +1100 Subject: [PATCH 25/25] Update InsightsManagementMapperTest.kt fix detekt warning about imports --- .../management/InsightsManagementMapperTest.kt | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/InsightsManagementMapperTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/InsightsManagementMapperTest.kt index e28a7479031d..2e9df36f6232 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/InsightsManagementMapperTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/management/InsightsManagementMapperTest.kt @@ -8,7 +8,19 @@ import org.mockito.Mock import org.wordpress.android.BaseUnitTest import org.wordpress.android.R import org.wordpress.android.fluxc.store.StatsStore.InsightType -import org.wordpress.android.fluxc.store.StatsStore.InsightType.* +import org.wordpress.android.fluxc.store.StatsStore.InsightType.ALL_TIME_STATS +import org.wordpress.android.fluxc.store.StatsStore.InsightType.ANNUAL_SITE_STATS +import org.wordpress.android.fluxc.store.StatsStore.InsightType.FOLLOWERS +import org.wordpress.android.fluxc.store.StatsStore.InsightType.LATEST_POST_SUMMARY +import org.wordpress.android.fluxc.store.StatsStore.InsightType.MOST_POPULAR_DAY_AND_HOUR +import org.wordpress.android.fluxc.store.StatsStore.InsightType.POSTING_ACTIVITY +import org.wordpress.android.fluxc.store.StatsStore.InsightType.PUBLICIZE +import org.wordpress.android.fluxc.store.StatsStore.InsightType.TAGS_AND_CATEGORIES +import org.wordpress.android.fluxc.store.StatsStore.InsightType.TODAY_STATS +import org.wordpress.android.fluxc.store.StatsStore.InsightType.TOTAL_COMMENTS +import org.wordpress.android.fluxc.store.StatsStore.InsightType.TOTAL_FOLLOWERS +import org.wordpress.android.fluxc.store.StatsStore.InsightType.TOTAL_LIKES +import org.wordpress.android.fluxc.store.StatsStore.InsightType.VIEWS_AND_VISITORS import org.wordpress.android.ui.stats.refresh.lists.sections.insights.management.InsightsManagementViewModel.InsightListItem import org.wordpress.android.ui.stats.refresh.lists.sections.insights.management.InsightsManagementViewModel.InsightListItem.Header import org.wordpress.android.ui.stats.refresh.lists.sections.insights.management.InsightsManagementViewModel.InsightListItem.InsightModel