diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/ReaderPostCardActionsHandler.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/ReaderPostCardActionsHandler.kt index 2c2143fa55ea..67c786274ee7 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/ReaderPostCardActionsHandler.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/discover/ReaderPostCardActionsHandler.kt @@ -22,6 +22,7 @@ import org.wordpress.android.models.ReaderPost import org.wordpress.android.modules.BG_THREAD import org.wordpress.android.ui.pages.SnackbarMessageHolder import org.wordpress.android.ui.prefs.AppPrefsWrapper +import org.wordpress.android.ui.reader.ReaderEvents import org.wordpress.android.ui.reader.comments.ThreadedCommentsActionSource import org.wordpress.android.ui.reader.discover.ReaderCardUiState.ReaderRecommendedBlogsCardUiState.ReaderRecommendedBlogUiState import org.wordpress.android.ui.reader.discover.ReaderNavigationEvents.SharePost @@ -79,6 +80,7 @@ import org.wordpress.android.ui.utils.UiString.UiStringRes import org.wordpress.android.ui.utils.UiString.UiStringText import org.wordpress.android.util.AppLog import org.wordpress.android.util.AppLog.T +import org.wordpress.android.util.EventBusWrapper import org.wordpress.android.viewmodel.Event import org.wordpress.android.viewmodel.ResourceProvider import org.wordpress.android.widgets.AppReviewsManagerWrapper @@ -104,6 +106,7 @@ class ReaderPostCardActionsHandler @Inject constructor( private val seenStatusToggleUseCase: ReaderSeenStatusToggleUseCase, private val readerBlogTableWrapper: ReaderBlogTableWrapper, private val accountStore: AccountStore, + private val eventBusWrapper: EventBusWrapper, @Named(BG_THREAD) private val bgDispatcher: CoroutineDispatcher ) { private lateinit var coroutineScope: CoroutineScope @@ -438,6 +441,7 @@ class ReaderPostCardActionsHandler @Inject constructor( when (it) { is BlockSiteState.SiteBlockedInLocalDb -> { _refreshPosts.postValue(Event(Unit)) + notifyFollowedBlogsChanged() updateBlockedStateFunction?.let { func -> func(true) } _snackbarEvents.postValue( Event( @@ -449,6 +453,7 @@ class ReaderPostCardActionsHandler @Inject constructor( val blogId = it.blockedBlogData.blogId undoBlockBlogUseCase.undoBlockBlog(it.blockedBlogData, source) _refreshPosts.postValue(Event(Unit)) + notifyFollowedBlogsChanged() _scrollToSiteId.emit(blogId) _snackbarEvents.postValue( Event( @@ -472,6 +477,7 @@ class ReaderPostCardActionsHandler @Inject constructor( } BlockSiteState.Failed.RequestFailed -> { _refreshPosts.postValue(Event(Unit)) + notifyFollowedBlogsChanged() _snackbarEvents.postValue( Event(SnackbarMessageHolder(UiStringRes(R.string.reader_toast_err_unable_to_block_blog))) ) @@ -481,6 +487,17 @@ class ReaderPostCardActionsHandler @Inject constructor( } } + private fun notifyFollowedBlogsChanged() { + eventBusWrapper.post( + ReaderEvents.FollowedBlogsFetched( + getFollowedBlogsCount(), + true + ) + ) + } + + private fun getFollowedBlogsCount(): Int = readerBlogTableWrapper.getFollowedBlogs().size + private suspend fun handleBlockUserClicked( authorId: Long, feedId: Long, diff --git a/WordPress/src/test/java/org/wordpress/android/ui/reader/discover/ReaderPostCardActionsHandlerTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/reader/discover/ReaderPostCardActionsHandlerTest.kt index 258cfa978d7a..81a48c80b8cc 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/reader/discover/ReaderPostCardActionsHandlerTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/reader/discover/ReaderPostCardActionsHandlerTest.kt @@ -13,6 +13,7 @@ import org.mockito.junit.MockitoJUnitRunner import org.mockito.kotlin.any import org.mockito.kotlin.anyOrNull import org.mockito.kotlin.anyVararg +import org.mockito.kotlin.argumentCaptor import org.mockito.kotlin.eq import org.mockito.kotlin.mock import org.mockito.kotlin.times @@ -26,6 +27,7 @@ import org.wordpress.android.fluxc.store.AccountStore.AddOrDeleteSubscriptionPay import org.wordpress.android.models.ReaderPost import org.wordpress.android.ui.pages.SnackbarMessageHolder import org.wordpress.android.ui.prefs.AppPrefsWrapper +import org.wordpress.android.ui.reader.ReaderEvents.FollowedBlogsFetched import org.wordpress.android.ui.reader.discover.ReaderNavigationEvents.OpenEditorForReblog import org.wordpress.android.ui.reader.discover.ReaderNavigationEvents.SharePost import org.wordpress.android.ui.reader.discover.ReaderNavigationEvents.ShowBlogPreview @@ -79,6 +81,7 @@ import org.wordpress.android.ui.reader.usecases.ReaderSiteFollowUseCase.FollowSi import org.wordpress.android.ui.reader.usecases.ReaderSiteNotificationsUseCase import org.wordpress.android.ui.reader.usecases.ReaderSiteNotificationsUseCase.SiteNotificationState import org.wordpress.android.ui.utils.HtmlMessageUtils +import org.wordpress.android.util.EventBusWrapper import org.wordpress.android.viewmodel.ResourceProvider private const val SOURCE = "source" @@ -134,6 +137,9 @@ class ReaderPostCardActionsHandlerTest : BaseUnitTest() { @Mock private lateinit var accountStore: AccountStore + @Mock + private lateinit var eventBusWrapper: EventBusWrapper + @Mock private lateinit var resourceProvider: ResourceProvider @@ -161,6 +167,7 @@ class ReaderPostCardActionsHandlerTest : BaseUnitTest() { seenStatusToggleUseCase, readerBlogTableWrapper, accountStore, + eventBusWrapper, testDispatcher() ) actionHandler.initScope(testScope()) @@ -740,6 +747,52 @@ class ReaderPostCardActionsHandlerTest : BaseUnitTest() { assertThat(observedValues.refreshPosts.size).isEqualTo(1) } + @Test + fun `FollowedBlogsFetched event is posted with new count when site blocked in local db`() = test { + // Arrange + whenever(blockBlogUseCase.blockBlog(any(), any())) + .thenReturn(flowOf(SiteBlockedInLocalDb(mock()))) + whenever(readerBlogTableWrapper.getFollowedBlogs()) + .thenReturn(listOf(mock(), mock())) + // Act + actionHandler.onAction( + mock(), + BLOCK_SITE, + false, + SOURCE + ) + + // Assert + val captor = argumentCaptor() + verify(eventBusWrapper).post(captor.capture()) + val event = captor.firstValue as FollowedBlogsFetched + assertThat(event.getTotalSubscriptions()).isEqualTo(2) + assertThat(event.didChange()).isTrue() + } + + @Test + fun `FollowedBlogsFetched event is posted when user clicks on undo action in snackbar`() = test { + // Arrange + whenever(blockBlogUseCase.blockBlog(any(), any())) + .thenReturn(flowOf(SiteBlockedInLocalDb(mock()))) + whenever(readerBlogTableWrapper.getFollowedBlogs()).thenReturn(emptyList()) + val observedValues = startObserving(backgroundScope) + actionHandler.onAction( + mock(), + BLOCK_SITE, + false, + SOURCE + ) + // Act + observedValues.snackbarMsgs[0].buttonAction.invoke() + // Assert + val captor = argumentCaptor() + verify(eventBusWrapper, times(2)).post(captor.capture()) + val events = captor.allValues.map { it as FollowedBlogsFetched } + assertThat(events) + .allMatch { it.didChange() && it.getTotalSubscriptions() == 0 } + } + @Test fun `Snackbar shown when site blocked in local db`() = test { // Arrange @@ -794,6 +847,28 @@ class ReaderPostCardActionsHandlerTest : BaseUnitTest() { assertThat(observedValues.refreshPosts.size).isEqualTo(1) } + @Test + fun `FollowedBlogsFetched event is posted when request to block site fails with request failed error`() = test { + // Arrange + whenever(blockBlogUseCase.blockBlog(any(), any())) + .thenReturn(flowOf(Failed.RequestFailed)) + whenever(readerBlogTableWrapper.getFollowedBlogs()).thenReturn(emptyList()) + // Act + actionHandler.onAction( + mock(), + BLOCK_SITE, + false, + SOURCE + ) + + // Assert + val captor = argumentCaptor() + verify(eventBusWrapper).post(captor.capture()) + val event = captor.firstValue as FollowedBlogsFetched + assertThat(event.getTotalSubscriptions()).isZero() + assertThat(event.didChange()).isTrue() + } + @Test fun `Snackbar shown when request to block site failes with request failed error`() = test { // Arrange