Repository: wordpress-mobile/WordPress-Android (language: kotlin)

Issue:
[Reader] Empty screen shown in tags feed when there's no internet connection
When tags feed is first loaded and the user has no internet connection, we're showing an empty screen. We should probably show an error like we do in the other feeds (in case we don't have the tags). We should compare it with iOS.


Discussion hints:
Thanks for reporting! 👍 <!-- generated_by_dangermattic -->


Pull request: [Tags Feed] Implement no connection state
Fixes #20815 

- Implement `NoConnection` state for showing an error message when the Feed is opened without an internet connection
- Initialize the UI State to `Loading` when there is an internet connection
- Avoid refreshing the tags when there's no internet connection (pull-to-refresh and coming back from tag details)
- Fix snackbar positioning
- Extract Error Message UI logic for reuse in `NoConnection` and `PostList.Error` states

<img src="https://github.com/wordpress-mobile/WordPress-Android/assets/5091503/55594993-672f-4e60-ace3-b16eeb8d7d25" width="300" />

-----

## To Test:

1. Open Jetpack
2. Make sure `reader_tags_feed` FeatureConfig is ON (`Debug Settings` -> `Remote Features`
3. Turn ON airplane mode
4. Go to Reader
5. Go to `Your Tags` feed
6. **Verify** a connection error is shown
7. Tap "Retry"
8. **Verify** the screen starts loading and goes back to the connection error
9. Turn OFF airplane mode and wait for internet connection to come back
10. Tap "Retry"
11. **Verify** the tags feed is loaded
12. Pull to refresh
13. **Verify** the tags feed is refreshed
14. Turn ON airplane mode
15. Pull to refresh
16. **Verify** the feed is not refreshed and a Snackback with a connection error message is shown

-----

## Regression Notes

1. Potential unintended areas of impact

    - Refreshing/fetching issues

18. What I did to test those areas of impact (or what existing automated tests I relied on)

    - Manual testing and unit testing

19. What automated tests I added (or what prevented me from doing so)

    - Added tests covering no internet connection scenarios

-----

## PR Submission Checklist:

- [x] I have completed the Regression Notes.
- [x] I have considered adding accessibility improvements for my changes.
- [x] I have considered if this change warrants user-facing release notes and have added them to `RELEASE-NOTES.txt` if necessary.

-----

## Testing Checklist (strike-out the not-applying and unnecessary ones):

- [ ] WordPress.com sites and self-hosted Jetpack sites.
- [x] Portrait and landscape orientations.
- [x] Light and dark modes.
- [ ] Fonts: Larger, smaller and bold text.
- [ ] High contrast.
- [ ] Talkback.
- [ ] Languages with large words or with letters/accents not frequently used in English.
- [ ] Right-to-left languages. (Even if translation isn’t complete, formatting should still respect the right-to-left layout)
- [ ] Large and small screen sizes. (Tablet and smaller phones)
- [ ] Multi-tasking: Split screen and Pop-up view. (Android 10 or higher)


Test command: ./gradlew :WordPress:testWordpressVanillaDebugUnitTest --tests "org.wordpress.android.ui.reader.viewmodels.ReaderTagsFeedViewModelTest"

Fix patch:
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/bloggingprompts/promptslist/compose/BloggingPromptsListScreen.kt b/WordPress/src/main/java/org/wordpress/android/ui/bloggingprompts/promptslist/compose/BloggingPromptsListScreen.kt
index e499fad2f4b2..a809a3bdc48c 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/bloggingprompts/promptslist/compose/BloggingPromptsListScreen.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/bloggingprompts/promptslist/compose/BloggingPromptsListScreen.kt
@@ -112,8 +112,8 @@ private fun FetchErrorContent() {
 @Composable
 private fun NetworkErrorContent() {
     EmptyContent(
-        title = stringResource(R.string.blogging_prompts_list_error_network_title),
-        subtitle = stringResource(R.string.blogging_prompts_list_error_network_subtitle),
+        title = stringResource(R.string.no_connection_error_title),
+        subtitle = stringResource(R.string.no_connection_error_description),
         image = R.drawable.img_illustration_cloud_off_152dp,
         modifier = Modifier.fillMaxSize(),
     )
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderTagsFeedFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderTagsFeedFragment.kt
index b96d71fef96b..531c9742fc38 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderTagsFeedFragment.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderTagsFeedFragment.kt
@@ -101,6 +101,7 @@ class ReaderTagsFeedFragment : ViewPagerFragment(R.layout.reader_tag_feed_fragme
         observeErrorMessageEvents()
         observeSnackbarEvents()
         observeOpenMoreMenuEvents()
+        viewModel.onViewCreated()
     }
 
     override fun onDestroy() {
@@ -282,8 +283,8 @@ class ReaderTagsFeedFragment : ViewPagerFragment(R.layout.reader_tag_feed_fragme
 
     private fun observeErrorMessageEvents() {
         viewModel.errorMessageEvents.observeEvent(viewLifecycleOwner) { stringRes ->
-            activity?.findViewById<View?>(android.R.id.content)?.let { view ->
-                WPSnackbar.make(view, getString(stringRes), Snackbar.LENGTH_LONG).show()
+            if (isAdded) {
+                WPSnackbar.make(binding.root, getString(stringRes), Snackbar.LENGTH_LONG).show()
             }
         }
     }
@@ -291,20 +292,18 @@ class ReaderTagsFeedFragment : ViewPagerFragment(R.layout.reader_tag_feed_fragme
     private fun observeSnackbarEvents() {
         viewModel.snackbarEvents.observeEvent(viewLifecycleOwner) { snackbarMessageHolder ->
             if (isAdded) {
-                activity?.findViewById<View>(R.id.coordinator)?.let { coordinator ->
-                    with(snackbarMessageHolder) {
-                        val snackbar = WPSnackbar.make(
-                            coordinator,
-                            uiHelpers.getTextOfUiString(requireContext(), message),
-                            Snackbar.LENGTH_LONG
-                        )
-                        if (buttonTitle != null) {
-                            snackbar.setAction(uiHelpers.getTextOfUiString(requireContext(), buttonTitle)) {
-                                buttonAction.invoke()
-                            }
+                with(snackbarMessageHolder) {
+                    val snackbar = WPSnackbar.make(
+                        binding.root,
+                        uiHelpers.getTextOfUiString(requireContext(), message),
+                        Snackbar.LENGTH_LONG
+                    )
+                    if (buttonTitle != null) {
+                        snackbar.setAction(uiHelpers.getTextOfUiString(requireContext(), buttonTitle)) {
+                            buttonAction.invoke()
                         }
-                        snackbar.show()
                     }
+                    snackbar.show()
                 }
             }
         }
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/viewmodels/tagsfeed/ReaderTagsFeedViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/viewmodels/tagsfeed/ReaderTagsFeedViewModel.kt
index 30a21829e1bf..2a0344f7ef56 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/reader/viewmodels/tagsfeed/ReaderTagsFeedViewModel.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/viewmodels/tagsfeed/ReaderTagsFeedViewModel.kt
@@ -6,6 +6,7 @@ import androidx.lifecycle.MediatorLiveData
 import androidx.lifecycle.viewModelScope
 import dagger.hilt.android.lifecycle.HiltViewModel
 import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.delay
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.update
@@ -32,6 +33,7 @@ import org.wordpress.android.ui.reader.repository.usecases.PostLikeUseCase
 import org.wordpress.android.ui.reader.tracker.ReaderTracker
 import org.wordpress.android.ui.reader.views.compose.tagsfeed.TagsFeedPostItem
 import org.wordpress.android.util.DisplayUtilsWrapper
+import org.wordpress.android.util.NetworkUtilsWrapper
 import org.wordpress.android.viewmodel.Event
 import org.wordpress.android.viewmodel.ScopedViewModel
 import org.wordpress.android.viewmodel.SingleLiveEvent
@@ -50,6 +52,7 @@ class ReaderTagsFeedViewModel @Inject constructor(
     private val readerPostUiStateBuilder: ReaderPostUiStateBuilder,
     private val displayUtilsWrapper: DisplayUtilsWrapper,
     private val readerTracker: ReaderTracker,
+    private val networkUtilsWrapper: NetworkUtilsWrapper,
 ) : ScopedViewModel(bgDispatcher) {
     private val _uiStateFlow: MutableStateFlow<UiState> = MutableStateFlow(UiState.Initial)
     val uiStateFlow: StateFlow<UiState> = _uiStateFlow
@@ -75,6 +78,16 @@ class ReaderTagsFeedViewModel @Inject constructor(
 
     private var hasInitialized = false
 
+    fun onViewCreated() {
+        if (!hasInitialized) {
+            hasInitialized = true
+            readerPostCardActionsHandler.initScope(viewModelScope)
+            initNavigationEvents()
+            initSnackbarEvents()
+            initUiState()
+        }
+    }
+
     /**
      * Fetch multiple tag posts in parallel. Each tag load causes a new state to be emitted, so multiple emissions of
      * [uiStateFlow] are expected when calling this method for each tag, since each can go through the following
@@ -93,13 +106,6 @@ class ReaderTagsFeedViewModel @Inject constructor(
             return
         }
 
-        if (!hasInitialized) {
-            hasInitialized = true
-            readerPostCardActionsHandler.initScope(viewModelScope)
-            initNavigationEvents()
-            initSnackbarEvents()
-        }
-
         // Add tags to the list with the posts loading UI
         _uiStateFlow.update {
             readerTagsFeedUiStateMapper.mapInitialPostsUiState(
@@ -125,6 +131,27 @@ class ReaderTagsFeedViewModel @Inject constructor(
         }
     }
 
+    private fun initUiState() {
+        _uiStateFlow.value = if (networkUtilsWrapper.isNetworkAvailable()) {
+            UiState.Loading
+        } else {
+            UiState.NoConnection(::onNoConnectionRetryClick)
+        }
+    }
+
+    private fun onNoConnectionRetryClick() {
+        _uiStateFlow.value = UiState.Loading
+        if (networkUtilsWrapper.isNetworkAvailable()) {
+            _actionEvents.value = ActionEvent.RefreshTags
+        } else {
+            // delay a bit before returning to NoConnection for a better feedback to the user
+            launch {
+                delay(NO_CONNECTION_DELAY)
+                _uiStateFlow.value = UiState.NoConnection(::onNoConnectionRetryClick)
+            }
+        }
+    }
+
     /**
      * Fetch posts for a single tag. This method will emit a new state to [uiStateFlow] for different [UiState]s:
      * [UiState.Initial], [UiState.Loaded], [UiState.Loading], [UiState.Empty], but only for the tag being fetched.
@@ -210,6 +237,11 @@ class ReaderTagsFeedViewModel @Inject constructor(
 
     @VisibleForTesting
     fun onRefresh() {
+        if (!networkUtilsWrapper.isNetworkAvailable()) {
+            _errorMessageEvents.postValue(Event(R.string.no_network_message))
+            return
+        }
+
         _uiStateFlow.update {
             (it as? UiState.Loaded)?.copy(isRefreshing = true) ?: it
         }
@@ -217,6 +249,8 @@ class ReaderTagsFeedViewModel @Inject constructor(
     }
 
     fun onBackFromTagDetails() {
+        if (!networkUtilsWrapper.isNetworkAvailable()) return
+
         _actionEvents.value = ActionEvent.RefreshTags
     }
 
@@ -501,6 +535,8 @@ class ReaderTagsFeedViewModel @Inject constructor(
         data object Loading : UiState()
 
         data class Empty(val onOpenTagsListClick: () -> Unit) : UiState()
+
+        data class NoConnection(val onRetryClick: () -> Unit) : UiState()
     }
 
     data class TagFeedItem(
@@ -542,4 +578,8 @@ class ReaderTagsFeedViewModel @Inject constructor(
         val readerCardUiState: ReaderCardUiState.ReaderPostNewUiState,
         val readerPostCardActions: List<ReaderPostCardAction>,
     )
+
+    companion object {
+        private const val NO_CONNECTION_DELAY = 500L
+    }
 }
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/views/compose/tagsfeed/ReaderTagsFeed.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/views/compose/tagsfeed/ReaderTagsFeed.kt
index ef85b60a357c..789bf55173d7 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/reader/views/compose/tagsfeed/ReaderTagsFeed.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/views/compose/tagsfeed/ReaderTagsFeed.kt
@@ -21,6 +21,7 @@ import androidx.compose.foundation.layout.widthIn
 import androidx.compose.foundation.lazy.LazyColumn
 import androidx.compose.foundation.lazy.LazyRow
 import androidx.compose.foundation.lazy.items
+import androidx.compose.foundation.shape.CircleShape
 import androidx.compose.foundation.shape.RoundedCornerShape
 import androidx.compose.material.Button
 import androidx.compose.material.ButtonDefaults
@@ -78,6 +79,7 @@ fun ReaderTagsFeed(uiState: UiState) {
             is UiState.Loading -> Loading()
             is UiState.Loaded -> Loaded(uiState)
             is UiState.Empty -> Empty(uiState)
+            is UiState.NoConnection -> NoConnection(uiState)
             is UiState.Initial -> {
                 // no-op
             }
@@ -134,7 +136,7 @@ private fun Loaded(uiState: UiState.Loaded) {
                 when (postList) {
                     is PostList.Initial, is PostList.Loading -> PostListLoading()
                     is PostList.Loaded -> PostListLoaded(postList, tagChip, backgroundColor)
-                    is PostList.Error -> PostListError(backgroundColor, tagChip, postList)
+                    is PostList.Error -> PostListError(postList, tagChip, backgroundColor)
                 }
                 Spacer(modifier = Modifier.height(Margin.ExtraExtraMediumLarge.value))
             }
@@ -266,6 +268,28 @@ private fun Empty(uiState: UiState.Empty) {
     }
 }
 
+@Composable
+fun NoConnection(uiState: UiState.NoConnection) {
+    val backgroundColor = if (isSystemInDarkTheme()) {
+        AppColor.White.copy(alpha = 0.12F)
+    } else {
+        AppColor.Black.copy(alpha = 0.08F)
+    }
+
+    Box(modifier = Modifier.fillMaxSize()) {
+        ErrorMessage(
+            modifier = Modifier
+                .align(Alignment.Center)
+                .fillMaxWidth(),
+            backgroundColor = backgroundColor,
+            titleText = stringResource(R.string.no_connection_error_title),
+            descriptionText = stringResource(R.string.no_connection_error_description),
+            actionText = stringResource(R.string.reader_tags_feed_error_retry),
+            onActionClick = uiState.onRetryClick,
+        )
+    }
+}
+
 @Composable
 private fun PostListLoading() {
     val loadingLabel = stringResource(id = R.string.loading)
@@ -369,47 +393,65 @@ private fun PostListLoaded(
 
 @Composable
 private fun PostListError(
-    backgroundColor: Color,
-    tagChip: TagChip,
     postList: PostList.Error,
+    tagChip: TagChip,
+    backgroundColor: Color,
 ) {
-    Column(
+    val tagName = tagChip.tag.tagDisplayName
+    val errorMessage = when (postList.type) {
+        is ErrorType.Default -> stringResource(R.string.reader_tags_feed_loading_error_description)
+        is ErrorType.NoContent -> stringResource(R.string.reader_tags_feed_no_content_error_description, tagName)
+    }
+
+    ErrorMessage(
         modifier = Modifier
             .heightIn(min = ReaderTagsFeedComposeUtils.PostItemHeight)
-            .fillMaxWidth()
+            .fillMaxWidth(),
+        backgroundColor = backgroundColor,
+        titleText = stringResource(id = R.string.reader_tags_feed_error_title, tagName),
+        descriptionText = errorMessage,
+        actionText = stringResource(R.string.reader_tags_feed_error_retry),
+        onActionClick = { postList.onRetryClick(tagChip.tag) }
+    )
+}
+
+@Composable
+private fun ErrorMessage(
+    backgroundColor: Color,
+    titleText: String,
+    descriptionText: String,
+    actionText: String,
+    modifier: Modifier = Modifier,
+    onActionClick: () -> Unit,
+) {
+    Column(
+        modifier = modifier
             .semantics(mergeDescendants = true) {}
             .padding(start = 60.dp, end = 60.dp),
         horizontalAlignment = Alignment.CenterHorizontally,
         verticalArrangement = Arrangement.Center,
     ) {
-        Spacer(modifier = Modifier.height(Margin.Medium.value))
         Icon(
             modifier = Modifier
-                .drawBehind {
-                    drawCircle(
-                        color = backgroundColor,
-                        radius = this.size.maxDimension
-                    )
-                },
+                .background(
+                    color = backgroundColor,
+                    shape = CircleShape
+                )
+                .padding(Margin.Medium.value),
             painter = painterResource(R.drawable.ic_wifi_off_24px),
             tint = MaterialTheme.colors.onSurface,
             contentDescription = null
         )
         Spacer(modifier = Modifier.height(Margin.ExtraMediumLarge.value))
-        val tagName = tagChip.tag.tagDisplayName
         Text(
-            text = stringResource(id = R.string.reader_tags_feed_error_title, tagName),
+            text = titleText,
             style = androidx.compose.material3.MaterialTheme.typography.labelLarge,
             color = MaterialTheme.colors.onSurface,
             textAlign = TextAlign.Center,
         )
         Spacer(modifier = Modifier.height(Margin.Small.value))
-        val errorMessage = when (postList.type) {
-            is ErrorType.Default -> stringResource(R.string.reader_tags_feed_loading_error_description)
-            is ErrorType.NoContent -> stringResource(R.string.reader_tags_feed_no_content_error_description, tagName)
-        }
         Text(
-            text = errorMessage,
+            text = descriptionText,
             style = androidx.compose.material3.MaterialTheme.typography.bodySmall,
             color = if (isSystemInDarkTheme()) {
                 AppColor.White.copy(alpha = 0.4F)
@@ -420,7 +462,7 @@ private fun PostListError(
         )
         Spacer(modifier = Modifier.height(Margin.Large.value))
         Button(
-            onClick = { postList.onRetryClick(tagChip.tag) },
+            onClick = onActionClick,
             modifier = Modifier
                 .height(36.dp)
                 .widthIn(min = 114.dp),
@@ -440,7 +482,7 @@ private fun PostListError(
                 style = androidx.compose.material3.MaterialTheme.typography.labelLarge,
                 fontWeight = FontWeight.Medium,
                 color = MaterialTheme.colors.surface,
-                text = stringResource(R.string.reader_tags_feed_error_retry),
+                text = actionText,
             )
         }
     }
diff --git a/WordPress/src/main/res/values-ar/strings.xml b/WordPress/src/main/res/values-ar/strings.xml
index 8a48702ee148..4afff1755719 100644
--- a/WordPress/src/main/res/values-ar/strings.xml
+++ b/WordPress/src/main/res/values-ar/strings.xml
@@ -534,14 +534,14 @@ Language: ar
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_notifications">ستنتقل ميزة التنبيهات إلى Jetpack</string>
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_reader">ستنتقل ميزة القارئ إلى تطبيق Jetpack</string>
     <string name="wp_jetpack_feature_removal_overlay_switch_to_new_jetpack_app">التبديل إلى تطبيق Jetpack الجديد</string>
-    <string name="blogging_prompts_list_error_network_title">يتعذر تحميل هذا المحتوى حاليًا.</string>
+    <string name="no_connection_error_title">يتعذر تحميل هذا المحتوى حاليًا.</string>
     <string name="blogging_prompts_list_error_fetch_subtitle">حدث خطأ في أثناء تحميل المطالبات.</string>
     <string name="blogging_prompts_list_error_fetch_title">عذرًا</string>
     <string name="blogging_prompts_list_no_prompts">لا توجد مطالبات بعد</string>
     <string name="blogging_prompts_list_number_of_answers_other">%d من الإجابات</string>
     <string name="blogging_prompts_list_number_of_answers_one">إجابة واحدة</string>
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_stats">ستنتقل ميزة الإحصاءات لديك إلى تطبيق Jetpack</string>
-    <string name="blogging_prompts_list_error_network_subtitle">تحقق من اتصالك بالشبكة وحاول مرة أخرى.</string>
+    <string name="no_connection_error_description">تحقق من اتصالك بالشبكة وحاول مرة أخرى.</string>
     <string name="blogging_prompts_list_number_of_answers_zero">0 من الإجابات</string>
     <string name="blogging_prompts_list_answered_prompt">✓ تم الرد</string>
     <string name="blogging_prompts_list_title">المطالبات</string>
diff --git a/WordPress/src/main/res/values-cs/strings.xml b/WordPress/src/main/res/values-cs/strings.xml
index a7e128c3e6cb..d8b4b56bf66b 100644
--- a/WordPress/src/main/res/values-cs/strings.xml
+++ b/WordPress/src/main/res/values-cs/strings.xml
@@ -148,8 +148,8 @@ Language: cs_CZ
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_reader">Čtečka se přesouvá do aplikace Jetpack</string>
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_stats">Vaše statistiky se přesouvají do aplikace Jetpack</string>
     <string name="wp_jetpack_feature_removal_overlay_switch_to_new_jetpack_app">Přepněte na novou aplikaci Jetpack</string>
-    <string name="blogging_prompts_list_error_network_subtitle">Zkontrolujte připojení k síti a zkuste to znovu.</string>
-    <string name="blogging_prompts_list_error_network_title">Momentálně tento obsah nelze načíst</string>
+    <string name="no_connection_error_description">Zkontrolujte připojení k síti a zkuste to znovu.</string>
+    <string name="no_connection_error_title">Momentálně tento obsah nelze načíst</string>
     <string name="blogging_prompts_list_error_fetch_subtitle">Došlo k chybě při načítání to se mi líbí</string>
     <string name="blogging_prompts_list_error_fetch_title">Jejda</string>
     <string name="blogging_prompts_list_no_prompts">Zatím žádné výzvy</string>
diff --git a/WordPress/src/main/res/values-de/strings.xml b/WordPress/src/main/res/values-de/strings.xml
index 995411887988..5f2d7106d702 100644
--- a/WordPress/src/main/res/values-de/strings.xml
+++ b/WordPress/src/main/res/values-de/strings.xml
@@ -549,8 +549,8 @@ Language: de
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_reader">Der Reader wird in die Jetpack-App verschoben</string>
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_stats">Deine Statistiken werden in die Jetpack-App verschoben</string>
     <string name="wp_jetpack_feature_removal_overlay_switch_to_new_jetpack_app">Zur neuen Jetpack-App wechseln</string>
-    <string name="blogging_prompts_list_error_network_subtitle">Prüfe deine Netzwerkverbindung und versuche es erneut.</string>
-    <string name="blogging_prompts_list_error_network_title">Dieser Inhalt kann gerade nicht geladen werden</string>
+    <string name="no_connection_error_description">Prüfe deine Netzwerkverbindung und versuche es erneut.</string>
+    <string name="no_connection_error_title">Dieser Inhalt kann gerade nicht geladen werden</string>
     <string name="blogging_prompts_list_error_fetch_subtitle">Beim Laden der Schreibanregungen ist ein Fehler aufgetreten.</string>
     <string name="blogging_prompts_list_error_fetch_title">Ups</string>
     <string name="blogging_prompts_list_no_prompts">Noch keine Schreibanregungen</string>
diff --git a/WordPress/src/main/res/values-en-rCA/strings.xml b/WordPress/src/main/res/values-en-rCA/strings.xml
index bf42b4a96689..44e41f34c9d7 100644
--- a/WordPress/src/main/res/values-en-rCA/strings.xml
+++ b/WordPress/src/main/res/values-en-rCA/strings.xml
@@ -491,8 +491,8 @@ Language: en_CA
     <string name="jetpack_feature_card_content_phase_three">Stats, Reader, Notifications and other features will soon move to the Jetpack mobile app.</string>
     <string name="blogging_prompts_list_error_fetch_subtitle">There was an error loading prompts.</string>
     <string name="blogging_prompts_list_error_fetch_title">Oops</string>
-    <string name="blogging_prompts_list_error_network_subtitle">Check your network connection and try again.</string>
-    <string name="blogging_prompts_list_error_network_title">Unable to load this content right now</string>
+    <string name="no_connection_error_description">Check your network connection and try again.</string>
+    <string name="no_connection_error_title">Unable to load this content right now</string>
     <string name="blogging_prompts_list_no_prompts">No prompts yet</string>
     <string name="blogging_prompts_list_number_of_answers_one">1 answer</string>
     <string name="blogging_prompts_list_number_of_answers_other">%d answers</string>
diff --git a/WordPress/src/main/res/values-en-rGB/strings.xml b/WordPress/src/main/res/values-en-rGB/strings.xml
index 7f5704278c21..1e5b512815c1 100644
--- a/WordPress/src/main/res/values-en-rGB/strings.xml
+++ b/WordPress/src/main/res/values-en-rGB/strings.xml
@@ -549,8 +549,8 @@ Language: en_GB
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_reader">Reader is moving to the Jetpack app</string>
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_stats">Your stats are moving to the Jetpack app</string>
     <string name="wp_jetpack_feature_removal_overlay_switch_to_new_jetpack_app">Switch to the new Jetpack app</string>
-    <string name="blogging_prompts_list_error_network_subtitle">Check your network connection and try again.</string>
-    <string name="blogging_prompts_list_error_network_title">Unable to load this content right now</string>
+    <string name="no_connection_error_description">Check your network connection and try again.</string>
+    <string name="no_connection_error_title">Unable to load this content right now</string>
     <string name="blogging_prompts_list_error_fetch_subtitle">There was an error loading prompts.</string>
     <string name="blogging_prompts_list_error_fetch_title">Oops</string>
     <string name="blogging_prompts_list_no_prompts">No prompts yet</string>
diff --git a/WordPress/src/main/res/values-es-rCO/strings.xml b/WordPress/src/main/res/values-es-rCO/strings.xml
index a09dd4e8652c..eac1fde19f77 100644
--- a/WordPress/src/main/res/values-es-rCO/strings.xml
+++ b/WordPress/src/main/res/values-es-rCO/strings.xml
@@ -549,8 +549,8 @@ Language: es_CO
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_reader">El lector se está trasladando a la aplicación de Jetpack</string>
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_stats">La estadísticas se están trasladado a la aplicación de Jetpack</string>
     <string name="wp_jetpack_feature_removal_overlay_switch_to_new_jetpack_app">Cambiar a la nueva aplicación de Jetpack</string>
-    <string name="blogging_prompts_list_error_network_subtitle">Comprueba tu conexión a la red e inténtalo de nuevo.</string>
-    <string name="blogging_prompts_list_error_network_title">En este momento no se ha podido cargar este contenido</string>
+    <string name="no_connection_error_description">Comprueba tu conexión a la red e inténtalo de nuevo.</string>
+    <string name="no_connection_error_title">En este momento no se ha podido cargar este contenido</string>
     <string name="blogging_prompts_list_error_fetch_subtitle">Se ha producido un error al cargar las indicaciones.</string>
     <string name="blogging_prompts_list_error_fetch_title">¡Vaya!</string>
     <string name="blogging_prompts_list_no_prompts">Todavía no hay sugerencias</string>
diff --git a/WordPress/src/main/res/values-es/strings.xml b/WordPress/src/main/res/values-es/strings.xml
index d44702d9f362..3041cd1330c5 100644
--- a/WordPress/src/main/res/values-es/strings.xml
+++ b/WordPress/src/main/res/values-es/strings.xml
@@ -549,8 +549,8 @@ Language: es
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_reader">El lector se está trasladando a la aplicación de Jetpack</string>
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_stats">La estadísticas se están trasladado a la aplicación de Jetpack</string>
     <string name="wp_jetpack_feature_removal_overlay_switch_to_new_jetpack_app">Cambiar a la nueva aplicación de Jetpack</string>
-    <string name="blogging_prompts_list_error_network_subtitle">Comprueba tu conexión a la red e inténtalo de nuevo.</string>
-    <string name="blogging_prompts_list_error_network_title">En este momento no se ha podido cargar este contenido</string>
+    <string name="no_connection_error_description">Comprueba tu conexión a la red e inténtalo de nuevo.</string>
+    <string name="no_connection_error_title">En este momento no se ha podido cargar este contenido</string>
     <string name="blogging_prompts_list_error_fetch_subtitle">Se ha producido un error al cargar las indicaciones.</string>
     <string name="blogging_prompts_list_error_fetch_title">¡Vaya!</string>
     <string name="blogging_prompts_list_no_prompts">Todavía no hay sugerencias</string>
diff --git a/WordPress/src/main/res/values-fr-rCA/strings.xml b/WordPress/src/main/res/values-fr-rCA/strings.xml
index bb762e3bd384..99007a63887d 100644
--- a/WordPress/src/main/res/values-fr-rCA/strings.xml
+++ b/WordPress/src/main/res/values-fr-rCA/strings.xml
@@ -542,8 +542,8 @@ Language: fr
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_reader">Le lecteur va être déplacé dans l’application Jetpack</string>
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_stats">Les statistiques vont être déplacées dans l’application Jetpack</string>
     <string name="wp_jetpack_feature_removal_overlay_switch_to_new_jetpack_app">Passer à la nouvelle application Jetpack</string>
-    <string name="blogging_prompts_list_error_network_subtitle">Vérifiez votre connexion réseau et réessayez.</string>
-    <string name="blogging_prompts_list_error_network_title">Impossible de charger ce contenu pour le moment</string>
+    <string name="no_connection_error_description">Vérifiez votre connexion réseau et réessayez.</string>
+    <string name="no_connection_error_title">Impossible de charger ce contenu pour le moment</string>
     <string name="blogging_prompts_list_error_fetch_subtitle">Un problème est survenu lors du chargement des incitations.</string>
     <string name="blogging_prompts_list_error_fetch_title">Oups</string>
     <string name="blogging_prompts_list_no_prompts">Pas encore d’incitation</string>
diff --git a/WordPress/src/main/res/values-fr/strings.xml b/WordPress/src/main/res/values-fr/strings.xml
index bb762e3bd384..99007a63887d 100644
--- a/WordPress/src/main/res/values-fr/strings.xml
+++ b/WordPress/src/main/res/values-fr/strings.xml
@@ -542,8 +542,8 @@ Language: fr
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_reader">Le lecteur va être déplacé dans l’application Jetpack</string>
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_stats">Les statistiques vont être déplacées dans l’application Jetpack</string>
     <string name="wp_jetpack_feature_removal_overlay_switch_to_new_jetpack_app">Passer à la nouvelle application Jetpack</string>
-    <string name="blogging_prompts_list_error_network_subtitle">Vérifiez votre connexion réseau et réessayez.</string>
-    <string name="blogging_prompts_list_error_network_title">Impossible de charger ce contenu pour le moment</string>
+    <string name="no_connection_error_description">Vérifiez votre connexion réseau et réessayez.</string>
+    <string name="no_connection_error_title">Impossible de charger ce contenu pour le moment</string>
     <string name="blogging_prompts_list_error_fetch_subtitle">Un problème est survenu lors du chargement des incitations.</string>
     <string name="blogging_prompts_list_error_fetch_title">Oups</string>
     <string name="blogging_prompts_list_no_prompts">Pas encore d’incitation</string>
diff --git a/WordPress/src/main/res/values-gl/strings.xml b/WordPress/src/main/res/values-gl/strings.xml
index b4d23cc2778e..5006494cabc3 100644
--- a/WordPress/src/main/res/values-gl/strings.xml
+++ b/WordPress/src/main/res/values-gl/strings.xml
@@ -556,9 +556,9 @@ Language: gl_ES
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_notifications">Os avisos estanse trasladando á aplicación de Jetpack</string>
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_reader">O lector estase trasladando á aplicación de Jetpack</string>
     <string name="blogging_prompts_list_error_fetch_subtitle">Produciuse un erro ao cargar as indicacións.</string>
-    <string name="blogging_prompts_list_error_network_title">Neste momento non se puido cargar este contido</string>
+    <string name="no_connection_error_title">Neste momento non se puido cargar este contido</string>
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_stats">A estatísticas estanse trasladado á aplicación de Jetpack</string>
-    <string name="blogging_prompts_list_error_network_subtitle">Comproba a túa conexión á rede e inténtao de novo.</string>
+    <string name="no_connection_error_description">Comproba a túa conexión á rede e inténtao de novo.</string>
     <string name="blogging_prompts_list_title">Peticións</string>
     <string name="blogging_prompts_list_answered_prompt">✓ Respondido</string>
     <string name="close_desc">pechar</string>
diff --git a/WordPress/src/main/res/values-he/strings.xml b/WordPress/src/main/res/values-he/strings.xml
index 212e233c0619..9a13d85610f7 100644
--- a/WordPress/src/main/res/values-he/strings.xml
+++ b/WordPress/src/main/res/values-he/strings.xml
@@ -542,8 +542,8 @@ Language: he_IL
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_reader">הכלי Reader עובר לאפליקציה של Jetpack</string>
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_stats">הנתונים הסטטיסטיים שלך עוברים לאפליקציה של Jetpack</string>
     <string name="wp_jetpack_feature_removal_overlay_switch_to_new_jetpack_app">לעבור לאפליקציה החדשה של Jetpack</string>
-    <string name="blogging_prompts_list_error_network_subtitle">יש לבדוק את החיבור לרשת ולנסות שוב.</string>
-    <string name="blogging_prompts_list_error_network_title">אין אפשרות לטעון את התוכן כרגע</string>
+    <string name="no_connection_error_description">יש לבדוק את החיבור לרשת ולנסות שוב.</string>
+    <string name="no_connection_error_title">אין אפשרות לטעון את התוכן כרגע</string>
     <string name="blogging_prompts_list_error_fetch_subtitle">אירעה שגיאה בטעינת ההצעות.</string>
     <string name="blogging_prompts_list_error_fetch_title">אופס</string>
     <string name="blogging_prompts_list_no_prompts">עדיין אין הצעות</string>
diff --git a/WordPress/src/main/res/values-id/strings.xml b/WordPress/src/main/res/values-id/strings.xml
index d5fff60fe9fe..8233297376fd 100644
--- a/WordPress/src/main/res/values-id/strings.xml
+++ b/WordPress/src/main/res/values-id/strings.xml
@@ -548,8 +548,8 @@ Language: id
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_reader">Reader akan berpindah ke aplikasi Jetpack</string>
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_stats">Statistik Anda akan berpindah ke aplikasi Jetpack</string>
     <string name="wp_jetpack_feature_removal_overlay_switch_to_new_jetpack_app">Beralih ke aplikasi Jetpack baru</string>
-    <string name="blogging_prompts_list_error_network_subtitle">Periksa koneksi internet Anda dan coba lagi.</string>
-    <string name="blogging_prompts_list_error_network_title">Tidak dapat memuat konten ini sekarang</string>
+    <string name="no_connection_error_description">Periksa koneksi internet Anda dan coba lagi.</string>
+    <string name="no_connection_error_title">Tidak dapat memuat konten ini sekarang</string>
     <string name="blogging_prompts_list_error_fetch_subtitle">Terjadi eror saat memuat prompt.</string>
     <string name="blogging_prompts_list_error_fetch_title">Waduh</string>
     <string name="blogging_prompts_list_no_prompts">Belum ada prompt</string>
diff --git a/WordPress/src/main/res/values-it/strings.xml b/WordPress/src/main/res/values-it/strings.xml
index 86385c8715c0..b1c509251ad5 100644
--- a/WordPress/src/main/res/values-it/strings.xml
+++ b/WordPress/src/main/res/values-it/strings.xml
@@ -543,8 +543,8 @@ Language: it
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_reader">Le notifiche si stanno spostando sull\'app Jetpack</string>
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_stats">Le tue statistiche si stanno spostando sull\'app Jetpack</string>
     <string name="wp_jetpack_feature_removal_overlay_switch_to_new_jetpack_app">Passa alla nuova app Jetpack</string>
-    <string name="blogging_prompts_list_error_network_subtitle">Controlla la connessione di rete e riprova.</string>
-    <string name="blogging_prompts_list_error_network_title">Impossibile caricare questo contenuto al momento</string>
+    <string name="no_connection_error_description">Controlla la connessione di rete e riprova.</string>
+    <string name="no_connection_error_title">Impossibile caricare questo contenuto al momento</string>
     <string name="blogging_prompts_list_error_fetch_subtitle">Si è verificato un errore durante il caricamento delle richieste.</string>
     <string name="blogging_prompts_list_error_fetch_title">Ops</string>
     <string name="blogging_prompts_list_no_prompts">Ancora nessuna richiesta</string>
diff --git a/WordPress/src/main/res/values-ja/strings.xml b/WordPress/src/main/res/values-ja/strings.xml
index e0d1f587b197..443a856f6581 100644
--- a/WordPress/src/main/res/values-ja/strings.xml
+++ b/WordPress/src/main/res/values-ja/strings.xml
@@ -538,8 +538,8 @@ Language: ja_JP
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_reader">Reader は Jetpack アプリに移動しています</string>
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_stats">統計は Jetpack アプリに移動しています</string>
     <string name="wp_jetpack_feature_removal_overlay_switch_to_new_jetpack_app">新しい Jetpack アプリに切り替える</string>
-    <string name="blogging_prompts_list_error_network_subtitle">ネットワーク接続を確認して、もう一度お試しください。</string>
-    <string name="blogging_prompts_list_error_network_title">現在このページを読み込めません</string>
+    <string name="no_connection_error_description">ネットワーク接続を確認して、もう一度お試しください。</string>
+    <string name="no_connection_error_title">現在このページを読み込めません</string>
     <string name="blogging_prompts_list_error_fetch_subtitle">プロンプトの読み込みでエラーが発生しました。</string>
     <string name="blogging_prompts_list_error_fetch_title">エラーです</string>
     <string name="blogging_prompts_list_no_prompts">プロンプトはまだありません</string>
diff --git a/WordPress/src/main/res/values-ko/strings.xml b/WordPress/src/main/res/values-ko/strings.xml
index 14fe72e23c0d..fa1858c54c0e 100644
--- a/WordPress/src/main/res/values-ko/strings.xml
+++ b/WordPress/src/main/res/values-ko/strings.xml
@@ -542,8 +542,8 @@ Language: ko_KR
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_reader">젯팩 앱으로 리더 이동 중</string>
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_stats">젯팩 앱으로 통계 이동 중</string>
     <string name="wp_jetpack_feature_removal_overlay_switch_to_new_jetpack_app">새 젯팩 앱으로 전환</string>
-    <string name="blogging_prompts_list_error_network_subtitle">네트워크 연결을 확인하고 다시 시도하세요.</string>
-    <string name="blogging_prompts_list_error_network_title">지금 이 콘텐츠를 로드할 수 없습니다.</string>
+    <string name="no_connection_error_description">네트워크 연결을 확인하고 다시 시도하세요.</string>
+    <string name="no_connection_error_title">지금 이 콘텐츠를 로드할 수 없습니다.</string>
     <string name="blogging_prompts_list_error_fetch_subtitle">프롬프트 로드 중 오류가 발생했습니다.</string>
     <string name="blogging_prompts_list_error_fetch_title">죄송합니다.</string>
     <string name="blogging_prompts_list_no_prompts">아직 프롬프트 없음</string>
diff --git a/WordPress/src/main/res/values-lv/strings.xml b/WordPress/src/main/res/values-lv/strings.xml
index 600711a3a7a2..20cccf2ded05 100644
--- a/WordPress/src/main/res/values-lv/strings.xml
+++ b/WordPress/src/main/res/values-lv/strings.xml
@@ -280,8 +280,8 @@ Language: lv
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_reader">Lasītājs pāriet uz Jetpack lietotni</string>
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_stats">Jūsu statistika tiek pārvietota uz Jetpack lietotni</string>
     <string name="wp_jetpack_feature_removal_overlay_switch_to_new_jetpack_app">Pārslēdzieties uz jauno Jetpack lietotni</string>
-    <string name="blogging_prompts_list_error_network_subtitle">Pārbaudiet tīkla savienojumu un mēģiniet vēlreiz.</string>
-    <string name="blogging_prompts_list_error_network_title">Pašlaik nevar ielādēt šo saturu</string>
+    <string name="no_connection_error_description">Pārbaudiet tīkla savienojumu un mēģiniet vēlreiz.</string>
+    <string name="no_connection_error_title">Pašlaik nevar ielādēt šo saturu</string>
     <string name="blogging_prompts_list_error_fetch_subtitle">Ielādējot uzvednes, radās kļūda.</string>
     <string name="blogging_prompts_list_error_fetch_title">Hmm…</string>
     <string name="blogging_prompts_list_no_prompts">Vēl nav uzvedņu</string>
diff --git a/WordPress/src/main/res/values-nl/strings.xml b/WordPress/src/main/res/values-nl/strings.xml
index 3f3e5c65075f..b13e6af15c54 100644
--- a/WordPress/src/main/res/values-nl/strings.xml
+++ b/WordPress/src/main/res/values-nl/strings.xml
@@ -549,8 +549,8 @@ Language: nl
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_reader">Reader zal naar de Jetpack-app worden verplaatst</string>
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_stats">Je statistieken zullen naar de Jetpack-app worden verplaatst</string>
     <string name="wp_jetpack_feature_removal_overlay_switch_to_new_jetpack_app">Schakel over naar de nieuwe Jetpack-app</string>
-    <string name="blogging_prompts_list_error_network_subtitle">Controleer je netwerkverbinding en probeer het nogmaals.</string>
-    <string name="blogging_prompts_list_error_network_title">Deze inhoud kan momenteel niet geladen worden</string>
+    <string name="no_connection_error_description">Controleer je netwerkverbinding en probeer het nogmaals.</string>
+    <string name="no_connection_error_title">Deze inhoud kan momenteel niet geladen worden</string>
     <string name="blogging_prompts_list_error_fetch_subtitle">Er is een fout opgetreden bij het laden van opdrachten.</string>
     <string name="blogging_prompts_list_error_fetch_title">Oeps</string>
     <string name="blogging_prompts_list_no_prompts">Er zijn nog geen opdrachten</string>
diff --git a/WordPress/src/main/res/values-pt-rBR/strings.xml b/WordPress/src/main/res/values-pt-rBR/strings.xml
index e4a4322da026..d276a53dab52 100644
--- a/WordPress/src/main/res/values-pt-rBR/strings.xml
+++ b/WordPress/src/main/res/values-pt-rBR/strings.xml
@@ -312,8 +312,8 @@ Language: pt_BR
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_reader">O Leitor está migrando para o aplicativo Jetpack</string>
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_stats">Suas estatísticas estão migrando para o aplicativo Jetpack</string>
     <string name="wp_jetpack_feature_removal_overlay_switch_to_new_jetpack_app">Mudar para o novo aplicativo do Jetpack</string>
-    <string name="blogging_prompts_list_error_network_subtitle">Verifique sua conexão de rede e tente novamente.</string>
-    <string name="blogging_prompts_list_error_network_title">Não foi possível carregar esse conteúdo no momento</string>
+    <string name="no_connection_error_description">Verifique sua conexão de rede e tente novamente.</string>
+    <string name="no_connection_error_title">Não foi possível carregar esse conteúdo no momento</string>
     <string name="blogging_prompts_list_error_fetch_subtitle">Ocorreu um erro ao carregar as sugestões.</string>
     <string name="blogging_prompts_list_error_fetch_title">Opa</string>
     <string name="blogging_prompts_list_no_prompts">Nenhuma sugestão ainda</string>
diff --git a/WordPress/src/main/res/values-ro/strings.xml b/WordPress/src/main/res/values-ro/strings.xml
index 36b4adb1ff35..b53e1f914ff9 100644
--- a/WordPress/src/main/res/values-ro/strings.xml
+++ b/WordPress/src/main/res/values-ro/strings.xml
@@ -549,8 +549,8 @@ Language: ro
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_reader">Cititorul a fost mutat în aplicația Jetpack</string>
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_stats">Statisticile se mută în aplicația Jetpack</string>
     <string name="wp_jetpack_feature_removal_overlay_switch_to_new_jetpack_app">Comută la noua aplicație Jetpack</string>
-    <string name="blogging_prompts_list_error_network_subtitle">Verifică conexiunea rețelei și încearcă din nou.</string>
-    <string name="blogging_prompts_list_error_network_title">Nu pot să încarc acest conținut chiar acum</string>
+    <string name="no_connection_error_description">Verifică conexiunea rețelei și încearcă din nou.</string>
+    <string name="no_connection_error_title">Nu pot să încarc acest conținut chiar acum</string>
     <string name="blogging_prompts_list_error_fetch_subtitle">A fost o eroare la încărcarea îndemnurilor.</string>
     <string name="blogging_prompts_list_error_fetch_title">Hopa</string>
     <string name="blogging_prompts_list_no_prompts">Niciun îndemn încă</string>
diff --git a/WordPress/src/main/res/values-ru/strings.xml b/WordPress/src/main/res/values-ru/strings.xml
index c93edc6bb2d2..fb236e7a2f07 100644
--- a/WordPress/src/main/res/values-ru/strings.xml
+++ b/WordPress/src/main/res/values-ru/strings.xml
@@ -547,8 +547,8 @@ Language: ru
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_reader">Чтиво переезжает в приложение Jetpack</string>
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_stats">Статистика переезжает в приложение Jetpack</string>
     <string name="wp_jetpack_feature_removal_overlay_switch_to_new_jetpack_app">Перейти в новое приложение Jetpack</string>
-    <string name="blogging_prompts_list_error_network_subtitle">Проверьте ваше подключение к сети и попробуйте снова.</string>
-    <string name="blogging_prompts_list_error_network_title">Сейчас невозможно загрузить это содержимое</string>
+    <string name="no_connection_error_description">Проверьте ваше подключение к сети и попробуйте снова.</string>
+    <string name="no_connection_error_title">Сейчас невозможно загрузить это содержимое</string>
     <string name="blogging_prompts_list_error_fetch_subtitle">При загрузке подсказок возникла ошибка.</string>
     <string name="blogging_prompts_list_error_fetch_title">Ой!</string>
     <string name="blogging_prompts_list_no_prompts">Пока нет подсказок</string>
diff --git a/WordPress/src/main/res/values-sq/strings.xml b/WordPress/src/main/res/values-sq/strings.xml
index 11a3d337c205..18f2adb9e44c 100644
--- a/WordPress/src/main/res/values-sq/strings.xml
+++ b/WordPress/src/main/res/values-sq/strings.xml
@@ -520,8 +520,8 @@ Language: sq_AL
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_reader">Lexuesi po kalohet te aplikacioni Jetpack</string>
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_stats">Statistikat tuaja po kalojnë te aplikacioni Jetpack</string>
     <string name="wp_jetpack_feature_removal_overlay_switch_to_new_jetpack_app">Kaloni në aplikacionin e ri Jetpack</string>
-    <string name="blogging_prompts_list_error_network_subtitle">Kontrolloni lidhjen tuaj në rrjet dhe riprovoni.</string>
-    <string name="blogging_prompts_list_error_network_title">S’arrihet të ngarkohet kjo lëndë këtë çast</string>
+    <string name="no_connection_error_description">Kontrolloni lidhjen tuaj në rrjet dhe riprovoni.</string>
+    <string name="no_connection_error_title">S’arrihet të ngarkohet kjo lëndë këtë çast</string>
     <string name="blogging_prompts_list_error_fetch_subtitle">Pati një gabim në ngarkim cytjesh.</string>
     <string name="blogging_prompts_list_error_fetch_title">Hëm</string>
     <string name="blogging_prompts_list_no_prompts">Ende pa cytje</string>
diff --git a/WordPress/src/main/res/values-sv/strings.xml b/WordPress/src/main/res/values-sv/strings.xml
index df5eade59e7d..a0fb595b94c8 100644
--- a/WordPress/src/main/res/values-sv/strings.xml
+++ b/WordPress/src/main/res/values-sv/strings.xml
@@ -549,8 +549,8 @@ Language: sv_SE
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_reader">Läsaren flyttar till Jetpack-appen</string>
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_stats">Din statistik flyttas till Jetpack-appen</string>
     <string name="wp_jetpack_feature_removal_overlay_switch_to_new_jetpack_app">Byt till den nya Jetpack-appen</string>
-    <string name="blogging_prompts_list_error_network_subtitle">Kontrollera din nätverksanslutning och försök igen.</string>
-    <string name="blogging_prompts_list_error_network_title">Det går inte att ladda detta innehåll just nu</string>
+    <string name="no_connection_error_description">Kontrollera din nätverksanslutning och försök igen.</string>
+    <string name="no_connection_error_title">Det går inte att ladda detta innehåll just nu</string>
     <string name="blogging_prompts_list_error_fetch_subtitle">Det var ett problem att ladda in förslag.</string>
     <string name="blogging_prompts_list_error_fetch_title">Hoppsan</string>
     <string name="blogging_prompts_list_no_prompts">Inga förslag än</string>
diff --git a/WordPress/src/main/res/values-tr/strings.xml b/WordPress/src/main/res/values-tr/strings.xml
index 6bdc41bf6bd1..4eefcfe02e32 100644
--- a/WordPress/src/main/res/values-tr/strings.xml
+++ b/WordPress/src/main/res/values-tr/strings.xml
@@ -546,8 +546,8 @@ Language: tr
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_reader">Okuyucu, Jetpack uygulamasına taşınıyor</string>
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_stats">İstatistikleriniz Jetpack uygulamasına taşınıyor</string>
     <string name="wp_jetpack_feature_removal_overlay_switch_to_new_jetpack_app">Yeni Jetpack uygulamasına geçiş yapın</string>
-    <string name="blogging_prompts_list_error_network_subtitle">Ağ bağlantınızı denetleyip yeniden deneyin.</string>
-    <string name="blogging_prompts_list_error_network_title">Bu içerik şu an yüklenemiyor</string>
+    <string name="no_connection_error_description">Ağ bağlantınızı denetleyip yeniden deneyin.</string>
+    <string name="no_connection_error_title">Bu içerik şu an yüklenemiyor</string>
     <string name="blogging_prompts_list_error_fetch_subtitle">İstemler yüklenirken bir sorun çıktı.</string>
     <string name="blogging_prompts_list_error_fetch_title">Eyvah</string>
     <string name="blogging_prompts_list_no_prompts">Henüz bir istem yok</string>
diff --git a/WordPress/src/main/res/values-zh-rCN/strings.xml b/WordPress/src/main/res/values-zh-rCN/strings.xml
index 3844b72060a9..9cefd4408257 100644
--- a/WordPress/src/main/res/values-zh-rCN/strings.xml
+++ b/WordPress/src/main/res/values-zh-rCN/strings.xml
@@ -540,8 +540,8 @@ Language: zh_CN
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_reader">阅读器即将移至 Jetpack 应用</string>
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_stats">统计信息即将移至 Jetpack 应用</string>
     <string name="wp_jetpack_feature_removal_overlay_switch_to_new_jetpack_app">切换到新版 Jetpack 应用</string>
-    <string name="blogging_prompts_list_error_network_subtitle">请检查您的网络连接，然后重试。</string>
-    <string name="blogging_prompts_list_error_network_title">现在无法加载此内容</string>
+    <string name="no_connection_error_description">请检查您的网络连接，然后重试。</string>
+    <string name="no_connection_error_title">现在无法加载此内容</string>
     <string name="blogging_prompts_list_error_fetch_subtitle">加载提示时出错。</string>
     <string name="blogging_prompts_list_error_fetch_title">糟糕</string>
     <string name="blogging_prompts_list_no_prompts">尚无提示</string>
diff --git a/WordPress/src/main/res/values-zh-rHK/strings.xml b/WordPress/src/main/res/values-zh-rHK/strings.xml
index 7106eb840445..f6cce6eb1afa 100644
--- a/WordPress/src/main/res/values-zh-rHK/strings.xml
+++ b/WordPress/src/main/res/values-zh-rHK/strings.xml
@@ -542,8 +542,8 @@ Language: zh_TW
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_reader">「閱讀器」將轉移至 Jetpack 應用程式</string>
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_stats">你的統計資料將轉移至 Jetpack 應用程式</string>
     <string name="wp_jetpack_feature_removal_overlay_switch_to_new_jetpack_app">切換至全新 Jetpack 應用程式</string>
-    <string name="blogging_prompts_list_error_network_subtitle">請檢查你的網路連線並再試一次。</string>
-    <string name="blogging_prompts_list_error_network_title">目前無法載入此內容</string>
+    <string name="no_connection_error_description">請檢查你的網路連線並再試一次。</string>
+    <string name="no_connection_error_title">目前無法載入此內容</string>
     <string name="blogging_prompts_list_error_fetch_subtitle">載入提示時發生錯誤。</string>
     <string name="blogging_prompts_list_error_fetch_title">糟糕</string>
     <string name="blogging_prompts_list_no_prompts">尚無提示</string>
diff --git a/WordPress/src/main/res/values-zh-rTW/strings.xml b/WordPress/src/main/res/values-zh-rTW/strings.xml
index 7106eb840445..f6cce6eb1afa 100644
--- a/WordPress/src/main/res/values-zh-rTW/strings.xml
+++ b/WordPress/src/main/res/values-zh-rTW/strings.xml
@@ -542,8 +542,8 @@ Language: zh_TW
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_reader">「閱讀器」將轉移至 Jetpack 應用程式</string>
     <string name="wp_jetpack_feature_removal_overlay_phase_two_and_three_title_stats">你的統計資料將轉移至 Jetpack 應用程式</string>
     <string name="wp_jetpack_feature_removal_overlay_switch_to_new_jetpack_app">切換至全新 Jetpack 應用程式</string>
-    <string name="blogging_prompts_list_error_network_subtitle">請檢查你的網路連線並再試一次。</string>
-    <string name="blogging_prompts_list_error_network_title">目前無法載入此內容</string>
+    <string name="no_connection_error_description">請檢查你的網路連線並再試一次。</string>
+    <string name="no_connection_error_title">目前無法載入此內容</string>
     <string name="blogging_prompts_list_error_fetch_subtitle">載入提示時發生錯誤。</string>
     <string name="blogging_prompts_list_error_fetch_title">糟糕</string>
     <string name="blogging_prompts_list_no_prompts">尚無提示</string>
diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml
index e9ec2d338432..f7486889e865 100644
--- a/WordPress/src/main/res/values/strings.xml
+++ b/WordPress/src/main/res/values/strings.xml
@@ -122,6 +122,9 @@
 
     <string name="experimental_badge">&lt;Experimental&gt;</string>
 
+    <string name="no_connection_error_title">Unable to load this content right now</string>
+    <string name="no_connection_error_description">Check your network connection and try again.</string>
+
     <!-- CAB -->
     <string name="cab_selected">%d selected</string>
 
@@ -4310,8 +4313,6 @@ translators: %s: Select control option value e.g: "Auto, 25%". -->
     <string name="blogging_prompts_list_no_prompts">No prompts yet</string>
     <string name="blogging_prompts_list_error_fetch_title">Oops</string>
     <string name="blogging_prompts_list_error_fetch_subtitle">There was an error loading prompts.</string>
-    <string name="blogging_prompts_list_error_network_title">Unable to load this content right now</string>
-    <string name="blogging_prompts_list_error_network_subtitle">Check your network connection and try again.</string>
 
     <!-- Editor module -->
     <string name="post_content" tools:ignore="UnusedResources" a8c-src-lib="module:editor">Content</string>


Test patch:
diff --git a/WordPress/src/test/java/org/wordpress/android/ui/reader/viewmodels/ReaderTagsFeedViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/reader/viewmodels/ReaderTagsFeedViewModelTest.kt
index 06368089184f..83baaa4a6c28 100644
--- a/WordPress/src/test/java/org/wordpress/android/ui/reader/viewmodels/ReaderTagsFeedViewModelTest.kt
+++ b/WordPress/src/test/java/org/wordpress/android/ui/reader/viewmodels/ReaderTagsFeedViewModelTest.kt
@@ -15,10 +15,12 @@ import org.mockito.Mock
 import org.mockito.Mockito
 import org.mockito.kotlin.any
 import org.mockito.kotlin.doSuspendableAnswer
+import org.mockito.kotlin.times
 import org.mockito.kotlin.verify
 import org.mockito.kotlin.verifyNoInteractions
 import org.mockito.kotlin.whenever
 import org.wordpress.android.BaseUnitTest
+import org.wordpress.android.R
 import org.wordpress.android.analytics.AnalyticsTracker
 import org.wordpress.android.datasets.wrappers.ReaderPostTableWrapper
 import org.wordpress.android.getOrAwaitValue
@@ -41,9 +43,11 @@ import org.wordpress.android.ui.reader.viewmodels.tagsfeed.ReaderTagsFeedViewMod
 import org.wordpress.android.ui.reader.viewmodels.tagsfeed.ReaderTagsFeedViewModel.ActionEvent
 import org.wordpress.android.ui.reader.views.compose.tagsfeed.TagsFeedPostItem
 import org.wordpress.android.util.DisplayUtilsWrapper
+import org.wordpress.android.util.NetworkUtilsWrapper
 import org.wordpress.android.viewmodel.Event
 import kotlin.test.assertIs
 
+@Suppress("LargeClass")
 @OptIn(ExperimentalCoroutinesApi::class)
 class ReaderTagsFeedViewModelTest : BaseUnitTest() {
     @Mock
@@ -79,12 +83,16 @@ class ReaderTagsFeedViewModelTest : BaseUnitTest() {
     @Mock
     lateinit var snackbarEvents: MediatorLiveData<Event<SnackbarMessageHolder>>
 
+    @Mock
+    lateinit var networkUtilsWrapper: NetworkUtilsWrapper
+
     private lateinit var viewModel: ReaderTagsFeedViewModel
 
     private val collectedUiStates: MutableList<ReaderTagsFeedViewModel.UiState> = mutableListOf()
 
     private val actionEvents = mutableListOf<ActionEvent>()
     private val readerNavigationEvents = mutableListOf<Event<ReaderNavigationEvents>>()
+    private val errorMessageEvents = mutableListOf<Event<Int>>()
 
     val tag = ReaderTag(
         "tag",
@@ -107,6 +115,7 @@ class ReaderTagsFeedViewModelTest : BaseUnitTest() {
             readerPostUiStateBuilder = readerPostUiStateBuilder,
             displayUtilsWrapper = displayUtilsWrapper,
             readerTracker = readerTracker,
+            networkUtilsWrapper = networkUtilsWrapper,
         )
         whenever(readerPostCardActionsHandler.navigationEvents)
             .thenReturn(navigationEvents)
@@ -114,6 +123,7 @@ class ReaderTagsFeedViewModelTest : BaseUnitTest() {
             .thenReturn(snackbarEvents)
         observeActionEvents()
         observeNavigationEvents()
+        observeErrorMessageEvents()
     }
 
     @Test
@@ -386,6 +396,7 @@ class ReaderTagsFeedViewModelTest : BaseUnitTest() {
         val posts2 = ReaderPostList().apply {
             add(ReaderPost())
         }
+        whenever(networkUtilsWrapper.isNetworkAvailable()).thenReturn(true)
         whenever(readerPostRepository.fetchNewerPostsForTag(tag1)).doSuspendableAnswer {
             delay(100)
             posts1
@@ -448,6 +459,7 @@ class ReaderTagsFeedViewModelTest : BaseUnitTest() {
         val posts2 = ReaderPostList().apply {
             add(ReaderPost())
         }
+        whenever(networkUtilsWrapper.isNetworkAvailable()).thenReturn(true)
         whenever(readerPostRepository.fetchNewerPostsForTag(tag1)).doSuspendableAnswer {
             delay(100)
             posts1
@@ -487,6 +499,7 @@ class ReaderTagsFeedViewModelTest : BaseUnitTest() {
         val posts2 = ReaderPostList().apply {
             add(ReaderPost())
         }
+        whenever(networkUtilsWrapper.isNetworkAvailable()).thenReturn(true)
         whenever(readerPostRepository.fetchNewerPostsForTag(tag1)).doSuspendableAnswer {
             delay(100)
             posts1
@@ -514,6 +527,46 @@ class ReaderTagsFeedViewModelTest : BaseUnitTest() {
         assertThat(action).isEqualTo(ActionEvent.RefreshTags)
     }
 
+    @Suppress("LongMethod")
+    @Test
+    fun `given tags fetched and no connection, when refreshing, then show error message`() = testCollectingUiStates {
+        // Given
+        val tag1 = ReaderTestUtils.createTag("tag1")
+        val tag2 = ReaderTestUtils.createTag("tag2")
+        val posts1 = ReaderPostList().apply {
+            add(ReaderPost())
+        }
+        val posts2 = ReaderPostList().apply {
+            add(ReaderPost())
+        }
+        whenever(networkUtilsWrapper.isNetworkAvailable()).thenReturn(false)
+        whenever(readerPostRepository.fetchNewerPostsForTag(tag1)).doSuspendableAnswer {
+            delay(100)
+            posts1
+        }
+        whenever(readerPostRepository.fetchNewerPostsForTag(tag2)).doSuspendableAnswer {
+            delay(200)
+            posts2
+        }
+        mockMapInitialTagFeedItems()
+        mockMapLoadingTagFeedItems()
+        mockMapLoadedTagFeedItems()
+
+        // When
+        viewModel.onTagsChanged(listOf(tag1, tag2))
+        advanceUntilIdle()
+        viewModel.onItemEnteredView(getInitialTagFeedItem(tag1))
+        advanceUntilIdle()
+        viewModel.onItemEnteredView(getInitialTagFeedItem(tag2))
+        advanceUntilIdle()
+
+        // Then
+        viewModel.onRefresh()
+
+        val messageRes = errorMessageEvents.last().peekContent()
+        assertThat(messageRes).isEqualTo(R.string.no_network_message)
+    }
+
     @Test
     fun `Should update UI immediately when like button is tapped`() = testCollectingUiStates {
         // Given
@@ -603,6 +656,8 @@ class ReaderTagsFeedViewModelTest : BaseUnitTest() {
 
     @Test
     fun `Should emit RefreshTags when onBackFromTagDetails is called`() {
+        whenever(networkUtilsWrapper.isNetworkAvailable()).thenReturn(true)
+
         // When
         viewModel.onBackFromTagDetails()
 
@@ -610,6 +665,17 @@ class ReaderTagsFeedViewModelTest : BaseUnitTest() {
         assertIs<ActionEvent.RefreshTags>(actionEvents.first())
     }
 
+    @Test
+    fun `Should not emit RefreshTags when onBackFromTagDetails is called with no connection`() {
+        whenever(networkUtilsWrapper.isNetworkAvailable()).thenReturn(false)
+
+        // When
+        viewModel.onBackFromTagDetails()
+
+        // Then
+        actionEvents.isEmpty()
+    }
+
     @Test
     fun `Should track READER_POST_CARD_TAPPED when onPostCardClick is called`() = testCollectingUiStates {
         // Given
@@ -699,6 +765,80 @@ class ReaderTagsFeedViewModelTest : BaseUnitTest() {
         )
     }
 
+    @Test
+    fun `when calling onViewCreated multiple times, then initialize handler once`() = test {
+        // When
+        viewModel.onViewCreated()
+        viewModel.onViewCreated()
+
+        // Then
+        verify(readerPostCardActionsHandler, times(1)).initScope(any())
+    }
+
+    @Test
+    fun `given connection on, when onViewCreated, then init UI state with Loading`() = testCollectingUiStates {
+        // Given
+        whenever(networkUtilsWrapper.isNetworkAvailable()).thenReturn(true)
+
+        // When
+        viewModel.onViewCreated()
+
+        // Then
+        assertThat(collectedUiStates.last()).isEqualTo(ReaderTagsFeedViewModel.UiState.Loading)
+    }
+
+    @Test
+    fun `given connection off, when onViewCreated, then init UI state with NoConnection`() = testCollectingUiStates {
+        // Given
+        whenever(networkUtilsWrapper.isNetworkAvailable()).thenReturn(false)
+
+        // When
+        viewModel.onViewCreated()
+
+        // Then
+        assertThat(collectedUiStates.last()).isInstanceOf(ReaderTagsFeedViewModel.UiState.NoConnection::class.java)
+    }
+
+    @Test
+    fun `given NoConnectionState and connection off, when onRetryClick, then UI state is NoConnection`() =
+        testCollectingUiStates {
+            // Given
+            whenever(networkUtilsWrapper.isNetworkAvailable()).thenReturn(false)
+            viewModel.onViewCreated()
+            val noConnectionState = collectedUiStates.last() as ReaderTagsFeedViewModel.UiState.NoConnection
+
+            // When
+            noConnectionState.onRetryClick()
+            advanceUntilIdle()
+
+            // Then
+            val lastStates = collectedUiStates.takeLast(2)
+            assertThat(lastStates[0]).isEqualTo(ReaderTagsFeedViewModel.UiState.Loading)
+            assertThat(lastStates[1]).isInstanceOf(ReaderTagsFeedViewModel.UiState.NoConnection::class.java)
+        }
+
+    @Test
+    fun `given NoConnectionState and connection on, when onRetryClick, then refresh is requested`() =
+        testCollectingUiStates {
+            // Given
+            whenever(networkUtilsWrapper.isNetworkAvailable())
+                .thenReturn(false)
+                .thenReturn(true)
+            viewModel.onViewCreated()
+            val noConnectionState = collectedUiStates.last() as ReaderTagsFeedViewModel.UiState.NoConnection
+
+            // When
+            noConnectionState.onRetryClick()
+            advanceUntilIdle()
+
+            // Then
+            val lastState = collectedUiStates.last()
+            assertThat(lastState).isEqualTo(ReaderTagsFeedViewModel.UiState.Loading)
+            viewModel.actionEvents.getOrAwaitValue().let {
+                assertThat(it).isEqualTo(ActionEvent.RefreshTags)
+            }
+        }
+
     private fun mockMapInitialTagFeedItems() {
         whenever(readerTagsFeedUiStateMapper.mapInitialPostsUiState(any(), any(), any(), any(), any(), any()))
             .thenAnswer {
@@ -773,4 +913,10 @@ class ReaderTagsFeedViewModelTest : BaseUnitTest() {
             it?.let { readerNavigationEvents.add(it) }
         }
     }
+
+    private fun observeErrorMessageEvents() {
+        viewModel.errorMessageEvents.observeForever {
+            it?.let { errorMessageEvents.add(it) }
+        }
+    }
 }