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

Issue:
[Bloganuary] Implement the Bloganuary attribution UI in Prompts card
We are internally talking about returning the value `bloganuary` in the `attribution` field of the API response as we do for Day One (which returns `dayone`).

Internal ref: pe7F0s-1iI-p2#comment-1738

We should implement/reuse that `attribution` logic to show the "From Bloganuary" attribution UI in the card.


![Image](https://github.com/wordpress-mobile/WordPress-Android/assets/5091503/d4125038-21af-45d8-925a-71526616e849)




Discussion hints:
nan

Pull request: [Bloganuary] Show prompts bloganuary attribution UI
Fixes #19592 

When the prompts for today contains `bloganuary` in the `attribution` field we should show the proper icon and text in the attribution UI (the same we use for Day One).

**Note:** This still does not implement the updated UI, just reuses the attribution logic for the card.

![image](https://github.com/wordpress-mobile/WordPress-Android/assets/5091503/87103df0-9053-45f1-9ed9-dd808c970461)

## To test
The testing setup is the same as the one explained here: https://github.com/wordpress-mobile/WordPress-Android/pull/19590 (Charles Setup and mocked json response)

### Test Steps
1. Download, install, and log in the Jetpack version from this PR
3. **Disable** the `Map Local` setting in Charles (so we hit the actual endpoint)
4. Refresh the app dashboard
5. **Verify** the prompt card either shows no attribution UI or the `Day One` attribution (if today's prompt is a Day One prompt)
6. **Enable** the `Map Local` setting in Charles (so we hit our mocked json response)
7. Refresh the app dashboard
8. **Verify** the prompt card shows the attribution UI for `Bloganuary`

## Regression Notes
1. Potential unintended areas of impact
Incorrect attribution UI being shown.

2. What I did to test those areas of impact (or what existing automated tests I relied on)
Manual and Unit testing.

3. What automated tests I added (or what prevented me from doing so)
Test for the possible attribution types and proper mapping.

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.

UI Changes testing checklist:

- [x] Portrait and landscape orientations.
- [x] Light and dark modes.
- [x] Fonts: Larger, smaller and bold text.
- [x] 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.mysite.cards.dashboard.bloggingprompts.BloggingPromptCardBuilderTest"

Fix patch:
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/main/CompactBloggingPromptCardViewHolder.kt b/WordPress/src/main/java/org/wordpress/android/ui/main/CompactBloggingPromptCardViewHolder.kt
index bf5cedf0e23e..b6793405407a 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/main/CompactBloggingPromptCardViewHolder.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/main/CompactBloggingPromptCardViewHolder.kt
@@ -1,10 +1,9 @@
 package org.wordpress.android.ui.main
 
 import android.view.ViewGroup
-import org.wordpress.android.R
 import org.wordpress.android.databinding.BloggingPromptCardCompactBinding
 import org.wordpress.android.ui.main.MainActionListItem.AnswerBloggingPromptAction
-import org.wordpress.android.ui.mysite.cards.dashboard.bloggingprompts.BloggingPromptAttribution.DAY_ONE
+import org.wordpress.android.ui.mysite.cards.dashboard.bloggingprompts.BloggingPromptAttribution
 import org.wordpress.android.ui.utils.UiHelpers
 import org.wordpress.android.util.HtmlCompatWrapper
 import org.wordpress.android.util.extensions.viewBinding
@@ -21,11 +20,8 @@ class CompactBloggingPromptCardViewHolder(
             uiHelpers.getTextOfUiString(promptContent.context, action.promptTitle).toString()
         )
         uiHelpers.setTextOrHide(promptContent, cardPrompt)
-        uiHelpers.updateVisibility(attributionContainer, action.attribution == DAY_ONE)
 
-        attributionContent.text = htmlCompatWrapper.fromHtml(
-            attributionContent.context.getString(R.string.my_site_blogging_prompt_card_attribution_dayone)
-        )
+        setupAttributionContainer(action.attribution)
 
         answerButton.setOnClickListener {
             action.onClickAction?.invoke(action.promptId)
@@ -36,4 +32,25 @@ class CompactBloggingPromptCardViewHolder(
         uiHelpers.updateVisibility(answeredButton, action.isAnswered)
         uiHelpers.updateVisibility(answerButton, !action.isAnswered)
     }
+
+    private fun BloggingPromptCardCompactBinding.setupAttributionContainer(
+        attribution: BloggingPromptAttribution
+    ) {
+        uiHelpers.updateVisibility(attributionContainer, attribution != BloggingPromptAttribution.NO_ATTRIBUTION)
+
+        val context = attributionContainer.context
+
+        attribution.contentRes
+            .takeIf { it != -1 }
+            ?.let { context.getString(it) }
+            ?.let { content ->
+                attributionContent.text = htmlCompatWrapper.fromHtml(content)
+            }
+
+        attribution.iconRes
+            .takeIf { it != -1 }
+            ?.let { iconRes ->
+                attributionIcon.setImageResource(iconRes)
+            }
+    }
 }
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dashboard/bloggingprompts/BloggingPromptAttribution.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dashboard/bloggingprompts/BloggingPromptAttribution.kt
index a543dcc24c06..453c3bca8c5e 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dashboard/bloggingprompts/BloggingPromptAttribution.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dashboard/bloggingprompts/BloggingPromptAttribution.kt
@@ -1,13 +1,27 @@
 package org.wordpress.android.ui.mysite.cards.dashboard.bloggingprompts
 
-enum class BloggingPromptAttribution {
-    NO_ATTRIBUTION,
-    DAY_ONE;
+import androidx.annotation.DrawableRes
+import androidx.annotation.StringRes
+import org.wordpress.android.R
+
+enum class BloggingPromptAttribution(
+    @StringRes val contentRes: Int,
+    @DrawableRes val iconRes: Int,
+) {
+    NO_ATTRIBUTION(-1, -1),
+    DAY_ONE(
+        R.string.my_site_blogging_prompt_card_attribution_dayone,
+        R.drawable.ic_dayone_24dp,
+    ),
+    BLOGANUARY(
+        R.string.my_site_blogging_prompt_card_attribution_bloganuary,
+        R.drawable.ic_bloganuary_24dp,
+    );
 
     companion object {
         fun fromString(value: String): BloggingPromptAttribution = when (value) {
             "dayone" -> DAY_ONE
-
+            "bloganuary" -> BLOGANUARY
             else -> NO_ATTRIBUTION
         }
     }
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dashboard/bloggingprompts/BloggingPromptCardViewHolder.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dashboard/bloggingprompts/BloggingPromptCardViewHolder.kt
index 2d648547333a..43850b31799a 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dashboard/bloggingprompts/BloggingPromptCardViewHolder.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dashboard/bloggingprompts/BloggingPromptCardViewHolder.kt
@@ -9,7 +9,7 @@ import org.wordpress.android.databinding.MySiteBloggingPromptCardBinding
 import org.wordpress.android.ui.avatars.TrainOfAvatarsItem
 import org.wordpress.android.ui.mysite.MySiteCardAndItem.Card.BloggingPromptCard.BloggingPromptCardWithData
 import org.wordpress.android.ui.mysite.MySiteCardAndItemViewHolder
-import org.wordpress.android.ui.mysite.cards.dashboard.bloggingprompts.BloggingPromptAttribution.DAY_ONE
+import org.wordpress.android.ui.mysite.cards.dashboard.bloggingprompts.BloggingPromptAttribution.NO_ATTRIBUTION
 import org.wordpress.android.ui.utils.UiHelpers
 import org.wordpress.android.util.HtmlCompatWrapper
 import org.wordpress.android.util.extensions.getColorStateListFromAttributeOrRes
@@ -31,11 +31,7 @@ class BloggingPromptCardViewHolder(
         uiHelpers.setTextOrHide(promptContent, cardPrompt)
         uiHelpers.updateVisibility(answerButton, !card.isAnswered)
 
-        uiHelpers.updateVisibility(attributionContainer, card.attribution == DAY_ONE)
-
-        attributionContent.text = htmlCompatWrapper.fromHtml(
-            attributionContent.context.getString(R.string.my_site_blogging_prompt_card_attribution_dayone)
-        )
+        setupAttributionContainer(card.attribution)
 
         bloggingPromptCardMenu.setOnClickListener {
             bloggingPromptsCardAnalyticsTracker.trackMySiteCardMenuClicked()
@@ -59,6 +55,27 @@ class BloggingPromptCardViewHolder(
         setupAnsweredUsersContainer(card)
     }
 
+    private fun MySiteBloggingPromptCardBinding.setupAttributionContainer(
+        attribution: BloggingPromptAttribution
+    ) {
+        uiHelpers.updateVisibility(attributionContainer, attribution != NO_ATTRIBUTION)
+
+        val context = attributionContainer.context
+
+        attribution.contentRes
+            .takeIf { it != -1 }
+            ?.let { context.getString(it) }
+            ?.let { content ->
+                attributionContent.text = htmlCompatWrapper.fromHtml(content)
+            }
+
+        attribution.iconRes
+            .takeIf { it != -1 }
+            ?.let { iconRes ->
+                attributionIcon.setImageResource(iconRes)
+            }
+    }
+
     @Suppress("NestedBlockDepth")
     private fun setupAnsweredUsersContainer(
         card: BloggingPromptCardWithData,
diff --git a/WordPress/src/main/res/drawable-night/ic_bloganuary_24dp.xml b/WordPress/src/main/res/drawable-night/ic_bloganuary_24dp.xml
new file mode 100644
index 000000000000..d9d06fe107e0
--- /dev/null
+++ b/WordPress/src/main/res/drawable-night/ic_bloganuary_24dp.xml
@@ -0,0 +1,11 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:width="22.285715dp"
+    android:height="24dp"
+    android:viewportHeight="14"
+    android:viewportWidth="13">
+    <path
+        android:fillColor="#FFFFFF"
+        android:pathData="M9.713,0.91H3.287C1.613,0.91 0.249,2.319 0.249,4.049V9.951C0.249,11.684 1.613,13.09 3.287,13.09H9.713C11.39,13.09 12.751,11.681 12.751,9.951V4.049C12.751,2.316 11.387,0.91 9.713,0.91ZM6.5,6.745C6.218,6.745 5.99,6.509 5.99,6.218C5.99,5.927 6.218,5.691 6.5,5.691C6.782,5.691 7.01,5.927 7.01,6.218C7.01,6.509 6.782,6.745 6.5,6.745ZM6.813,7.339C7.285,7.197 7.636,6.751 7.636,6.218C7.636,5.571 7.126,5.044 6.5,5.044C5.874,5.044 5.364,5.571 5.364,6.218C5.364,6.751 5.715,7.197 6.187,7.339V9.744C5.633,8.678 4.889,7.918 3.953,7.482V4.427C3.953,4.243 4.097,4.094 4.276,4.094H8.721C8.9,4.094 9.044,4.243 9.044,4.427V7.504C8.08,8.07 7.335,8.833 6.813,9.78V7.339ZM12.125,9.951C12.125,11.325 11.043,12.444 9.713,12.444H6.813V11.448C7.235,9.896 8.139,8.729 9.503,7.979L9.669,7.889V4.427C9.669,3.887 9.244,3.448 8.721,3.448H4.279C3.756,3.448 3.331,3.887 3.331,4.427V7.915L3.528,7.996C4.776,8.503 5.671,9.667 6.187,11.451V12.444H3.287C1.957,12.444 0.875,11.325 0.875,9.951V4.049C0.875,2.675 1.957,1.557 3.287,1.557H9.713C11.043,1.557 12.125,2.675 12.125,4.049V9.951Z"
+        tools:ignore="VectorPath" />
+</vector>
diff --git a/WordPress/src/main/res/drawable/ic_bloganuary_24dp.xml b/WordPress/src/main/res/drawable/ic_bloganuary_24dp.xml
new file mode 100644
index 000000000000..ac7773959434
--- /dev/null
+++ b/WordPress/src/main/res/drawable/ic_bloganuary_24dp.xml
@@ -0,0 +1,11 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:width="22.285715dp"
+    android:height="24dp"
+    android:viewportHeight="14"
+    android:viewportWidth="13">
+    <path
+        android:fillColor="#000000"
+        android:pathData="M9.713,0.91H3.287C1.613,0.91 0.249,2.319 0.249,4.049V9.951C0.249,11.684 1.613,13.09 3.287,13.09H9.713C11.39,13.09 12.751,11.681 12.751,9.951V4.049C12.751,2.316 11.387,0.91 9.713,0.91ZM6.5,6.745C6.218,6.745 5.99,6.509 5.99,6.218C5.99,5.927 6.218,5.691 6.5,5.691C6.782,5.691 7.01,5.927 7.01,6.218C7.01,6.509 6.782,6.745 6.5,6.745ZM6.813,7.339C7.285,7.197 7.636,6.751 7.636,6.218C7.636,5.571 7.126,5.044 6.5,5.044C5.874,5.044 5.364,5.571 5.364,6.218C5.364,6.751 5.715,7.197 6.187,7.339V9.744C5.633,8.678 4.889,7.918 3.953,7.482V4.427C3.953,4.243 4.097,4.094 4.276,4.094H8.721C8.9,4.094 9.044,4.243 9.044,4.427V7.504C8.08,8.07 7.335,8.833 6.813,9.78V7.339ZM12.125,9.951C12.125,11.325 11.043,12.444 9.713,12.444H6.813V11.448C7.235,9.896 8.139,8.729 9.503,7.979L9.669,7.889V4.427C9.669,3.887 9.244,3.448 8.721,3.448H4.279C3.756,3.448 3.331,3.887 3.331,4.427V7.915L3.528,7.996C4.776,8.503 5.671,9.667 6.187,11.451V12.444H3.287C1.957,12.444 0.875,11.325 0.875,9.951V4.049C0.875,2.675 1.957,1.557 3.287,1.557H9.713C11.043,1.557 12.125,2.675 12.125,4.049V9.951Z"
+        tools:ignore="VectorPath" />
+</vector>
diff --git a/WordPress/src/main/res/layout/blogging_prompt_card_compact.xml b/WordPress/src/main/res/layout/blogging_prompt_card_compact.xml
index 2d90535788a2..b9d9295cb8fd 100644
--- a/WordPress/src/main/res/layout/blogging_prompt_card_compact.xml
+++ b/WordPress/src/main/res/layout/blogging_prompt_card_compact.xml
@@ -76,10 +76,11 @@
             tools:visibility="visible">
 
             <ImageView
+                android:id="@+id/attribution_icon"
                 android:layout_width="wrap_content"
                 android:layout_height="16dp"
                 android:importantForAccessibility="no"
-                android:src="@drawable/ic_dayone_24dp" />
+                tools:src="@drawable/ic_dayone_24dp" />
 
             <TextView
                 android:id="@+id/attribution_content"
diff --git a/WordPress/src/main/res/layout/my_site_blogging_prompt_card.xml b/WordPress/src/main/res/layout/my_site_blogging_prompt_card.xml
index 9af805b37681..aac5f191f805 100644
--- a/WordPress/src/main/res/layout/my_site_blogging_prompt_card.xml
+++ b/WordPress/src/main/res/layout/my_site_blogging_prompt_card.xml
@@ -63,10 +63,11 @@
             tools:visibility="visible">
 
             <ImageView
+                android:id="@+id/attribution_icon"
                 android:layout_width="wrap_content"
                 android:layout_height="16dp"
                 android:importantForAccessibility="no"
-                android:src="@drawable/ic_dayone_24dp" />
+                tools:src="@drawable/ic_dayone_24dp" />
 
             <TextView
                 android:id="@+id/attribution_content"
diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml
index 90146cab631f..edbed58bbb67 100644
--- a/WordPress/src/main/res/values/strings.xml
+++ b/WordPress/src/main/res/values/strings.xml
@@ -2399,6 +2399,7 @@
     <string name="my_site_blogging_prompt_card_menu_skip">Skip for today</string>
     <string name="my_site_blogging_prompt_card_menu_remove">Turn off prompts</string>
     <string name="my_site_blogging_prompt_card_attribution_dayone">From &lt;b&gt;DayOne&lt;/b&gt;</string>
+    <string name="my_site_blogging_prompt_card_attribution_bloganuary">From &lt;b&gt;Bloganuary&lt;/b&gt;</string>
     <string name="my_site_blogging_prompt_card_menu_learn_more">Learn more</string>
     <string name="my_site_blogging_prompt_card_skipped_snackbar">Skipped today\'s blogging prompt</string>
     <string name="my_site_blogging_prompt_card_removed_snackbar_title">Blogging Prompts hidden</string>


Test patch:
diff --git a/WordPress/src/test/java/org/wordpress/android/ui/mysite/cards/dashboard/bloggingprompts/BloggingPromptCardBuilderTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/mysite/cards/dashboard/bloggingprompts/BloggingPromptCardBuilderTest.kt
index a7c5381131f2..d109707fe366 100644
--- a/WordPress/src/test/java/org/wordpress/android/ui/mysite/cards/dashboard/bloggingprompts/BloggingPromptCardBuilderTest.kt
+++ b/WordPress/src/test/java/org/wordpress/android/ui/mysite/cards/dashboard/bloggingprompts/BloggingPromptCardBuilderTest.kt
@@ -43,35 +43,22 @@ private val RESPONDENTS = listOf(
 class BloggingPromptCardBuilderTest : BaseUnitTest() {
     private lateinit var builder: BloggingPromptCardBuilder
 
-    @Suppress("MaxLineLength")
-    private val bloggingPrompt = BloggingPromptModel(
-        id = 123,
-        text = PROMPT_TITLE,
-        date = Date(),
-        isAnswered = false,
-        attribution = "dayone",
-        respondentsCount = 5,
-        respondentsAvatarUrls = RESPONDENTS,
-        answeredLink = "https://wordpress.com/tag/dailyprompt-123"
-    )
-
     @Before
     fun setUp() {
         builder = BloggingPromptCardBuilder()
     }
 
     @Test
-    fun `given blogging prompt, when card is built, then return card`() {
-        val statCard = buildBloggingPromptCardBuilderParams(bloggingPrompt)
-
-        assertThat(statCard).isNotNull()
-    }
-
-    @Test
-    fun `given blogging prompt, when card is built without showing view answers action, then return matching card`() {
-        val statCard = buildBloggingPromptCardBuilderParams(bloggingPrompt)
-
-        assertThat(statCard).isEqualTo(bloggingPromptCard())
+    fun `given blogging prompt, when card is built then return matching card`() {
+        // lets test all possible attribution types to verify proper mapping
+        mapOf(
+            "dayone" to BloggingPromptAttribution.DAY_ONE,
+            "bloganuary" to BloggingPromptAttribution.BLOGANUARY,
+            "" to BloggingPromptAttribution.NO_ATTRIBUTION
+        ).forEach { (attributionString, attribution) ->
+            val promptCard = buildBloggingPromptCardBuilderParams(bloggingPromptModel(attributionString))
+            assertThat(promptCard).isEqualTo(bloggingPromptCard(attribution))
+        }
     }
 
     @Test
@@ -102,7 +89,21 @@ class BloggingPromptCardBuilderTest : BaseUnitTest() {
     private val onViewAnswersClick: (tagUrl: String) -> Unit = { }
     private val onRemoveClick: () -> Unit = { }
 
+    private fun bloggingPromptModel(
+        attribution: String
+    ) = BloggingPromptModel(
+        id = 123,
+        text = PROMPT_TITLE,
+        date = Date(),
+        isAnswered = false,
+        attribution = attribution,
+        respondentsCount = 5,
+        respondentsAvatarUrls = RESPONDENTS,
+        answeredLink = "https://wordpress.com/tag/dailyprompt-123"
+    )
+
     private fun bloggingPromptCard(
+        attribution: BloggingPromptAttribution
     ) = BloggingPromptCardWithData(
         prompt = UiStringText(PROMPT_TITLE),
         respondents = RESPONDENTS_IN_CARD_VIEW_ANSWERS,
@@ -110,7 +111,7 @@ class BloggingPromptCardBuilderTest : BaseUnitTest() {
         false,
         promptId = 123,
         tagUrl = "https://wordpress.com/tag/dailyprompt-123",
-        attribution = BloggingPromptAttribution.DAY_ONE,
+        attribution = attribution,
         onShareClick = onShareClick,
         onAnswerClick = onAnswerClick,
         onSkipClick = onSkipClick,