From 28b75381f4786cee9ae0d3395da93ff8b83c7b59 Mon Sep 17 00:00:00 2001 From: Thomas Horta Date: Tue, 2 Apr 2024 11:51:07 -0300 Subject: [PATCH 01/22] Add accessibility to feedback request paragraph --- .../readingpreferences/ReadingPreferencesScreen.kt | 11 +++++++++++ WordPress/src/main/res/values/strings.xml | 2 ++ 2 files changed, 13 insertions(+) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/views/compose/readingpreferences/ReadingPreferencesScreen.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/views/compose/readingpreferences/ReadingPreferencesScreen.kt index d503a9be824e..4fb7a92b216b 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/views/compose/readingpreferences/ReadingPreferencesScreen.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/views/compose/readingpreferences/ReadingPreferencesScreen.kt @@ -33,6 +33,8 @@ import androidx.compose.ui.hapticfeedback.HapticFeedbackType import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalHapticFeedback import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.onClick +import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.buildAnnotatedString @@ -261,6 +263,7 @@ private fun ReadingPreferencesPreviewFeedback( ) } + val buttonLabel = stringResource(R.string.reader_preferences_screen_preview_text_feedback_label) ClickableText( text = annotatedString, style = textStyle, @@ -273,6 +276,14 @@ private fun ReadingPreferencesPreviewFeedback( } } }, + modifier = Modifier.semantics { + onClick( + label = buttonLabel, + ) { + onSendFeedbackClick() + true + } + }, ) } diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml index a98f8033b020..eebd6aef2355 100644 --- a/WordPress/src/main/res/values/strings.xml +++ b/WordPress/src/main/res/values/strings.xml @@ -1705,6 +1705,8 @@ This is a new feature still in development. To help us improve it %s. send your feedback + + send your feedback Default Soft From 7e32acfadbe781d22b1636130279c47f866731f0 Mon Sep 17 00:00:00 2001 From: Thomas Horta Date: Tue, 2 Apr 2024 11:54:33 -0300 Subject: [PATCH 02/22] Match tags accessibility with Reader Details experience --- .../readingpreferences/ReadingPreferencesPreviewTag.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/views/compose/readingpreferences/ReadingPreferencesPreviewTag.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/views/compose/readingpreferences/ReadingPreferencesPreviewTag.kt index 177e2c517c0f..2727d38e5a6a 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/views/compose/readingpreferences/ReadingPreferencesPreviewTag.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/views/compose/readingpreferences/ReadingPreferencesPreviewTag.kt @@ -14,6 +14,9 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.dimensionResource +import androidx.compose.ui.semantics.Role +import androidx.compose.ui.semantics.role +import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.font.FontFamily import androidx.core.content.res.ResourcesCompat import org.wordpress.android.R @@ -42,6 +45,9 @@ fun ReadingPreferencesPreviewTag( Box( modifier = Modifier + .semantics(mergeDescendants = true) { + role = Role.Button + } .heightIn(min = minHeight) .border( width = strokeWidth, From c355742599157366508dbf212f6ebde8e91c0a0b Mon Sep 17 00:00:00 2001 From: Thomas Horta Date: Tue, 2 Apr 2024 13:27:31 -0300 Subject: [PATCH 03/22] Improve Scheme and Font buttons accessibility Properly set selection state and which preference each button represents --- .../ReadingPreferencesButtons.kt | 19 +++++++++++++++++-- WordPress/src/main/res/values/strings.xml | 7 +++++-- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/views/compose/readingpreferences/ReadingPreferencesButtons.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/views/compose/readingpreferences/ReadingPreferencesButtons.kt index 8296a6dee1ca..4a6df2e5330e 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/views/compose/readingpreferences/ReadingPreferencesButtons.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/views/compose/readingpreferences/ReadingPreferencesButtons.kt @@ -28,6 +28,12 @@ import androidx.compose.ui.draw.rotate import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.Role +import androidx.compose.ui.semantics.clearAndSetSemantics +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.role +import androidx.compose.ui.semantics.selected +import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.PlatformTextStyle import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontWeight @@ -65,10 +71,16 @@ private fun ReadingPreferenceButton( onClick: () -> Unit, modifier: Modifier = Modifier, verticalSpacing: Dp = buttonSpacing, + buttonTypeContentDescription: String? = null, preview: @Composable () -> Unit, ) { Column( modifier = modifier + .semantics { + role = Role.Button + if (isSelected) selected = true + buttonTypeContentDescription?.let { contentDescription = it } + } .width(buttonWidth) .background( color = MaterialTheme.colors.surface, @@ -113,6 +125,7 @@ fun ReadingPreferencesThemeButton( ReadingPreferenceButton( label = stringResource(theme.displayNameRes), isSelected = isSelected, + buttonTypeContentDescription = stringResource(R.string.reader_preferences_screen_theme_label), onClick = onClick, ) { Column( @@ -148,10 +161,11 @@ fun ReadingPreferencesFontFamilyButton( label = stringResource(fontFamily.displayNameRes), isSelected = isSelected, verticalSpacing = 0.dp, + buttonTypeContentDescription = stringResource(R.string.reader_preferences_screen_font_family_label), onClick = onClick, ) { Text( - text = stringResource(R.string.reader_preferences_font_family_preview), + text = stringResource(R.string.reader_preferences_screen_font_family_preview), style = TextStyle( fontFamily = fontFamily.toComposeFontFamily(), fontSize = fontFamilyButtonPreviewSize, @@ -159,7 +173,8 @@ fun ReadingPreferencesFontFamilyButton( platformStyle = PlatformTextStyle( includeFontPadding = false ) - ) + ), + modifier = Modifier.clearAndSetSemantics { }, ) } } diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml index eebd6aef2355..73abcc5b3a54 100644 --- a/WordPress/src/main/res/values/strings.xml +++ b/WordPress/src/main/res/values/strings.xml @@ -1708,6 +1708,7 @@ send your feedback + Color Scheme Default Soft Sepia @@ -1716,12 +1717,14 @@ h4x0r Candy + Font + Aa Serif Sans Mono - Aa - A + Font Size + A Post saved online From 9a1bd491e6357926652bf7b92ca562784303bb30 Mon Sep 17 00:00:00 2001 From: Thomas Horta Date: Tue, 2 Apr 2024 14:13:38 -0300 Subject: [PATCH 04/22] Fix accessibility for Font Size slider --- .../reader/models/ReaderReadingPreferences.kt | 30 +++++++++++++++---- .../ReadingPreferencesFontSizeSlider.kt | 21 +++++++++++-- WordPress/src/main/res/values/strings.xml | 5 ++++ 3 files changed, 47 insertions(+), 9 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/models/ReaderReadingPreferences.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/models/ReaderReadingPreferences.kt index a6ccab110565..cbd0817e70b2 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/models/ReaderReadingPreferences.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/models/ReaderReadingPreferences.kt @@ -168,14 +168,32 @@ data class ReaderReadingPreferences @JvmOverloads constructor( ), } - enum class FontSize(val value: Int) { - EXTRA_SMALL(10), - SMALL(12), + enum class FontSize( + @StringRes val displayNameRes: Int, + val value: Int, + ) { + EXTRA_SMALL( + displayNameRes = R.string.reader_preferences_font_size_extra_small, + value = 10, + ), + SMALL( + displayNameRes = R.string.reader_preferences_font_size_small, + value = 12, + ), @FallbackValue - NORMAL(16), - LARGE(20), - EXTRA_LARGE(24); + NORMAL( + displayNameRes = R.string.reader_preferences_font_size_normal, + value = 16, + ), + LARGE( + displayNameRes = R.string.reader_preferences_font_size_large, + value = 20, + ), + EXTRA_LARGE( + displayNameRes = R.string.reader_preferences_font_size_extra_large, + value = 24, + ); val multiplier: Float get() = value / DEFAULT.value.toFloat() diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/views/compose/readingpreferences/ReadingPreferencesFontSizeSlider.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/views/compose/readingpreferences/ReadingPreferencesFontSizeSlider.kt index c399bcb48424..9aa88d65ba72 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/views/compose/readingpreferences/ReadingPreferencesFontSizeSlider.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/views/compose/readingpreferences/ReadingPreferencesFontSizeSlider.kt @@ -26,6 +26,10 @@ import androidx.compose.ui.graphics.compositeOver import androidx.compose.ui.layout.Layout import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.clearAndSetSemantics +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.semantics.stateDescription import androidx.compose.ui.text.PlatformTextStyle import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontFamily @@ -79,8 +83,17 @@ fun ReadingPreferencesFontSizeSlider( val sliderColors = SliderDefaults.colors( thumbColor = MaterialTheme.colors.onSurface, ) + + val contentDescriptionLabel = stringResource(R.string.reader_preferences_screen_font_size_label) + val selectedFontSizeLabel = stringResource(selectedFontSize.displayNameRes) + Slider( - modifier = Modifier.fillMaxWidth(), + modifier = Modifier + .fillMaxWidth() + .semantics { + contentDescription = contentDescriptionLabel + stateDescription = selectedFontSizeLabel + }, value = selectedIndex.toFloat(), onValueChange = { val newIndex = it.toInt() @@ -116,13 +129,15 @@ private fun FontSizePreviewLabels( ) { val sliderPaddingX = with(LocalDensity.current) { totalThumbSize.toPx() / 2 } Layout( - modifier = Modifier.fillMaxWidth(), + modifier = Modifier + .fillMaxWidth() + .clearAndSetSemantics { }, content = { ReaderReadingPreferences.FontSize.values().forEach { fontSize -> val isSelected = fontSize == selectedFontSize Text( - text = stringResource(R.string.reader_preferences_font_size_preview), + text = stringResource(R.string.reader_preferences_screen_font_size_preview), style = TextStyle( fontFamily = previewFontFamily, fontSize = fontSize.value.sp, diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml index 73abcc5b3a54..87e22ade337c 100644 --- a/WordPress/src/main/res/values/strings.xml +++ b/WordPress/src/main/res/values/strings.xml @@ -1724,6 +1724,11 @@ Mono Font Size + Extra small + Small + Normal + Large + Extra large A From 4b1237a4157adcc14083bb3134ca6d3facafb6e7 Mon Sep 17 00:00:00 2001 From: Irfan Omur Date: Wed, 3 Apr 2024 22:01:51 +0300 Subject: [PATCH 05/22] Fix UnknownFormatConversionException on Account Settings screen --- .../android/ui/prefs/accountsettings/AccountSettingsFragment.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/prefs/accountsettings/AccountSettingsFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/prefs/accountsettings/AccountSettingsFragment.kt index 9be1151e9117..46c9efbf6984 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/prefs/accountsettings/AccountSettingsFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/prefs/accountsettings/AccountSettingsFragment.kt @@ -264,7 +264,7 @@ class AccountSettingsFragment : PreferenceFragmentLifeCycleOwner(), primarySiteSettingsUiState?.let { state -> primarySitePreference.apply { value = (state.primarySite?.siteId ?: "").toString() - summary = state.primarySite?.siteName + summary = state.primarySite?.siteName?.replace("%", "%%") entries = state.siteNames entryValues = state.siteIds canShowDialog = state.canShowChoosePrimarySiteDialog From 450d44f6f276f5a6da7f07f976611f40b7d14ab8 Mon Sep 17 00:00:00 2001 From: Irfan Omur Date: Wed, 3 Apr 2024 22:25:23 +0300 Subject: [PATCH 06/22] Fix UnknownFormatConversionException on Site Settings screen --- .../org/wordpress/android/ui/prefs/SiteSettingsFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/prefs/SiteSettingsFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/prefs/SiteSettingsFragment.java index b85410d6e0ec..d86e2eca768b 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/prefs/SiteSettingsFragment.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/prefs/SiteSettingsFragment.java @@ -1652,7 +1652,7 @@ private void setCategories() { mCategoryPref.setEntries(entries); mCategoryPref.setEntryValues(values); mCategoryPref.setValue(String.valueOf(mSiteSettings.getDefaultCategory())); - mCategoryPref.setSummary(mSiteSettings.getDefaultCategoryForDisplay()); + mCategoryPref.setSummary(mSiteSettings.getDefaultCategoryForDisplay().replace("%", "%%")); } private void setPostFormats() { From 73ca0bcf50a5382d17232782dd3641175051587d Mon Sep 17 00:00:00 2001 From: Irfan Omur Date: Thu, 4 Apr 2024 15:33:40 +0300 Subject: [PATCH 07/22] Fix UnknownFormatConversionException on setting default category --- .../org/wordpress/android/ui/prefs/SiteSettingsFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/prefs/SiteSettingsFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/prefs/SiteSettingsFragment.java index d86e2eca768b..4469e5763261 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/prefs/SiteSettingsFragment.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/prefs/SiteSettingsFragment.java @@ -807,7 +807,7 @@ public boolean onPreferenceChange(Preference preference, Object newValue) { mSiteSettings.setDefaultCategory(Integer.parseInt(newValue.toString())); setDetailListPreferenceValue(mCategoryPref, newValue.toString(), - mSiteSettings.getDefaultCategoryForDisplay()); + mSiteSettings.getDefaultCategoryForDisplay().replace("%", "%%")); } else if (preference == mFormatPref) { mSiteSettings.setDefaultFormat(newValue.toString()); setDetailListPreferenceValue(mFormatPref, From 23b7043251aa6d97042481cccc1c02979b5e5d54 Mon Sep 17 00:00:00 2001 From: Thomas Horta Date: Thu, 4 Apr 2024 15:10:12 -0300 Subject: [PATCH 08/22] Create ReaderReadingPreferencesTracker --- .../reader/models/ReaderReadingPreferences.kt | 16 ++- .../ReaderReadingPreferencesTracker.kt | 114 ++++++++++++++++++ .../android/analytics/AnalyticsTracker.java | 5 + 3 files changed, 131 insertions(+), 4 deletions(-) create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/reader/tracker/ReaderReadingPreferencesTracker.kt diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/models/ReaderReadingPreferences.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/models/ReaderReadingPreferences.kt index cbd0817e70b2..619cff57a15e 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/models/ReaderReadingPreferences.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/models/ReaderReadingPreferences.kt @@ -14,8 +14,8 @@ import java.util.Locale import com.google.android.material.R as MaterialR data class ReaderReadingPreferences @JvmOverloads constructor( - val theme: Theme = Theme.SYSTEM, - val fontFamily: FontFamily = FontFamily.SANS, + val theme: Theme = Theme.DEFAULT, + val fontFamily: FontFamily = FontFamily.DEFAULT, val fontSize: FontSize = FontSize.DEFAULT, ) { enum class Theme( @@ -74,7 +74,11 @@ data class ReaderReadingPreferences @JvmOverloads constructor( backgroundColorRes = R.color.reader_theme_candy_background, baseTextColorRes = R.color.reader_theme_candy_text, linkColorRes = R.color.reader_theme_candy_text, - ), + ); + + companion object { + val DEFAULT = SYSTEM + } } @Suppress("MagicNumber") @@ -165,7 +169,11 @@ data class ReaderReadingPreferences @JvmOverloads constructor( MONO( displayNameRes = R.string.reader_preferences_font_family_mono, value = "monospace", - ), + ); + + companion object { + val DEFAULT = SANS + } } enum class FontSize( diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/tracker/ReaderReadingPreferencesTracker.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/tracker/ReaderReadingPreferencesTracker.kt new file mode 100644 index 000000000000..e05e955b06d4 --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/tracker/ReaderReadingPreferencesTracker.kt @@ -0,0 +1,114 @@ +package org.wordpress.android.ui.reader.tracker + +import org.wordpress.android.analytics.AnalyticsTracker +import org.wordpress.android.ui.reader.models.ReaderReadingPreferences +import org.wordpress.android.util.analytics.AnalyticsTrackerWrapper +import javax.inject.Inject + +class ReaderReadingPreferencesTracker @Inject constructor( + private val analyticsTrackerWrapper: AnalyticsTrackerWrapper, +) { + fun trackScreenOpened(source: Source) { + val props = mapOf(Source.KEY to source.value) + + analyticsTrackerWrapper.track(AnalyticsTracker.Stat.READER_READING_PREFERENCES_OPENED, props) + } + + fun trackScreenClosed() { + analyticsTrackerWrapper.track(AnalyticsTracker.Stat.READER_READING_PREFERENCES_CLOSED) + } + + fun trackFeedbackTapped() { + analyticsTrackerWrapper.track(AnalyticsTracker.Stat.READER_READING_PREFERENCES_FEEDBACK_TAPPED) + } + + fun trackItemTapped(theme: ReaderReadingPreferences.Theme) { + val props = mapOf( + PROP_TYPE_KEY to PROP_TYPE_THEME, + PROP_VALUE_KEY to propValueFor(theme) + ) + + analyticsTrackerWrapper.track(AnalyticsTracker.Stat.READER_READING_PREFERENCES_ITEM_TAPPED, props) + } + + fun trackItemTapped(fontFamily: ReaderReadingPreferences.FontFamily) { + val props = mapOf( + PROP_TYPE_KEY to PROP_TYPE_FONT_FAMILY, + PROP_VALUE_KEY to propValueFor(fontFamily) + ) + + analyticsTrackerWrapper.track(AnalyticsTracker.Stat.READER_READING_PREFERENCES_ITEM_TAPPED, props) + } + + fun trackItemTapped(fontSize: ReaderReadingPreferences.FontSize) { + val props = mapOf( + PROP_TYPE_KEY to PROP_TYPE_FONT_SIZE, + PROP_VALUE_KEY to propValueFor(fontSize) + ) + + analyticsTrackerWrapper.track(AnalyticsTracker.Stat.READER_READING_PREFERENCES_ITEM_TAPPED, props) + } + + fun trackSaved(preferences: ReaderReadingPreferences, hasChanged: Boolean) { + val props = mapOf( + PROP_IS_DEFAULT_KEY to preferences.isDefault(), + PROP_HAS_CHANGED_KEY to hasChanged, + PROP_TYPE_THEME to propValueFor(preferences.theme), + PROP_TYPE_FONT_FAMILY to propValueFor(preferences.fontFamily), + PROP_TYPE_FONT_SIZE to propValueFor(preferences.fontSize), + ) + + analyticsTrackerWrapper.track(AnalyticsTracker.Stat.READER_READING_PREFERENCES_SAVED, props) + } + + private fun ReaderReadingPreferences.isDefault(): Boolean { + return theme == ReaderReadingPreferences.Theme.DEFAULT && + fontFamily == ReaderReadingPreferences.FontFamily.DEFAULT && + fontSize == ReaderReadingPreferences.FontSize.DEFAULT + } + + enum class Source(val value: String) { + POST_DETAILS_TOP_BAR("post_details_top_bar"), + POST_DETAILS_MORE_MENU("post_details_more_menu"); + + companion object { + const val KEY = "source" + } + } + + companion object { + private const val PROP_IS_DEFAULT_KEY = "is_default" + private const val PROP_HAS_CHANGED_KEY = "has_changed" + + private const val PROP_TYPE_KEY = "type" + const val PROP_TYPE_THEME = "color_scheme" + const val PROP_TYPE_FONT_FAMILY = "font" + const val PROP_TYPE_FONT_SIZE = "font_size" + + private const val PROP_VALUE_KEY = "value" + + private fun propValueFor(theme: ReaderReadingPreferences.Theme) = when(theme) { + ReaderReadingPreferences.Theme.SYSTEM -> "default" + ReaderReadingPreferences.Theme.SOFT -> "soft" + ReaderReadingPreferences.Theme.SEPIA -> "sepia" + ReaderReadingPreferences.Theme.EVENING -> "evening" + ReaderReadingPreferences.Theme.OLED -> "oled" + ReaderReadingPreferences.Theme.H4X0R -> "h4x0r" + ReaderReadingPreferences.Theme.CANDY -> "candy" + } + + private fun propValueFor(fontFamily: ReaderReadingPreferences.FontFamily) = when(fontFamily) { + ReaderReadingPreferences.FontFamily.SANS -> "sans" + ReaderReadingPreferences.FontFamily.SERIF -> "serif" + ReaderReadingPreferences.FontFamily.MONO -> "mono" + } + + private fun propValueFor(fontSize: ReaderReadingPreferences.FontSize) = when(fontSize) { + ReaderReadingPreferences.FontSize.EXTRA_SMALL -> "extra_small" + ReaderReadingPreferences.FontSize.SMALL -> "small" + ReaderReadingPreferences.FontSize.NORMAL -> "default" + ReaderReadingPreferences.FontSize.LARGE -> "large" + ReaderReadingPreferences.FontSize.EXTRA_LARGE -> "extra_large" + } + } +} diff --git a/libs/analytics/src/main/java/org/wordpress/android/analytics/AnalyticsTracker.java b/libs/analytics/src/main/java/org/wordpress/android/analytics/AnalyticsTracker.java index 07e73a61286e..18b1d3e6e045 100644 --- a/libs/analytics/src/main/java/org/wordpress/android/analytics/AnalyticsTracker.java +++ b/libs/analytics/src/main/java/org/wordpress/android/analytics/AnalyticsTracker.java @@ -83,6 +83,11 @@ public enum Stat { READER_SAVED_POST_OPENED_FROM_OTHER_POST_LIST("reader_saved_post_opened"), READER_SITE_SHARED, READER_FOLLOWING_FETCHED, + READER_READING_PREFERENCES_OPENED, + READER_READING_PREFERENCES_CLOSED, + READER_READING_PREFERENCES_FEEDBACK_TAPPED, + READER_READING_PREFERENCES_ITEM_TAPPED, + READER_READING_PREFERENCES_SAVED, STATS_ACCESSED, STATS_ACCESS_ERROR, STATS_PERIOD_ACCESSED, From b74f21b35f34e7d1d7e1dae365e073ea5fbced82 Mon Sep 17 00:00:00 2001 From: Thomas Horta Date: Thu, 4 Apr 2024 15:18:10 -0300 Subject: [PATCH 09/22] Add unit tests for ReadingPreferencesTracker --- .../ReaderReadingPreferencesTrackerTest.kt | 188 ++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 WordPress/src/test/java/org/wordpress/android/ui/reader/tracker/ReaderReadingPreferencesTrackerTest.kt diff --git a/WordPress/src/test/java/org/wordpress/android/ui/reader/tracker/ReaderReadingPreferencesTrackerTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/reader/tracker/ReaderReadingPreferencesTrackerTest.kt new file mode 100644 index 000000000000..b3c2648a3762 --- /dev/null +++ b/WordPress/src/test/java/org/wordpress/android/ui/reader/tracker/ReaderReadingPreferencesTrackerTest.kt @@ -0,0 +1,188 @@ +package org.wordpress.android.ui.reader.tracker + +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.junit.MockitoJUnitRunner +import org.mockito.kotlin.verify +import org.wordpress.android.analytics.AnalyticsTracker.Stat +import org.wordpress.android.ui.reader.models.ReaderReadingPreferences +import org.wordpress.android.ui.reader.tracker.ReaderReadingPreferencesTracker.Source +import org.wordpress.android.util.analytics.AnalyticsTrackerWrapper + +@RunWith(MockitoJUnitRunner::class) +class ReaderReadingPreferencesTrackerTest { + @Mock + lateinit var analyticsTrackerWrapper: AnalyticsTrackerWrapper + + private lateinit var tracker: ReaderReadingPreferencesTracker + + @Before + fun setUp() { + tracker = ReaderReadingPreferencesTracker(analyticsTrackerWrapper) + } + + @Test + fun `when trackScreenOpened is called, then track event`() { + Source.values().forEach { source -> + tracker.trackScreenOpened(source) + + val expectedSource = when (source) { + Source.POST_DETAILS_TOP_BAR -> "post_details_top_bar" + Source.POST_DETAILS_MORE_MENU -> "post_details_more_menu" + } + + verify(analyticsTrackerWrapper).track( + Stat.READER_READING_PREFERENCES_OPENED, + mapOf("source" to expectedSource) + ) + } + } + + @Test + fun `when trackScreenClosed is called, then track event`() { + tracker.trackScreenClosed() + + verify(analyticsTrackerWrapper).track(Stat.READER_READING_PREFERENCES_CLOSED) + } + + @Test + fun `when trackFeedbackTapped is called, then track event`() { + tracker.trackFeedbackTapped() + + verify(analyticsTrackerWrapper).track(Stat.READER_READING_PREFERENCES_FEEDBACK_TAPPED) + } + + @Test + fun `when trackItemTapped is called with theme, then track event`() { + ReaderReadingPreferences.Theme.values().forEach { theme -> + tracker.trackItemTapped(theme) + + verify(analyticsTrackerWrapper).track( + Stat.READER_READING_PREFERENCES_ITEM_TAPPED, + mapOf( + "type" to "color_scheme", + "value" to propValueFor(theme) + ) + ) + } + } + + @Test + fun `when trackItemTapped is called with font family, then track event`() { + ReaderReadingPreferences.FontFamily.values().forEach { fontFamily -> + tracker.trackItemTapped(fontFamily) + + verify(analyticsTrackerWrapper).track( + Stat.READER_READING_PREFERENCES_ITEM_TAPPED, + mapOf( + "type" to "font", + "value" to propValueFor(fontFamily) + ) + ) + } + } + + @Test + fun `when trackItemTapped is called with font size, then track event`() { + ReaderReadingPreferences.FontSize.values().forEach { fontSize -> + tracker.trackItemTapped(fontSize) + + verify(analyticsTrackerWrapper).track( + Stat.READER_READING_PREFERENCES_ITEM_TAPPED, + mapOf( + "type" to "font_size", + "value" to propValueFor(fontSize) + ) + ) + } + } + + @Test + fun `given default preferences, when trackSaved is called, then track event`() { + val preferences = ReaderReadingPreferences() + val hasChanged = true + + tracker.trackSaved(preferences, hasChanged) + + verify(analyticsTrackerWrapper).track( + Stat.READER_READING_PREFERENCES_SAVED, + mapOf( + "is_default" to true, + "has_changed" to hasChanged, + "color_scheme" to propValueFor(preferences.theme), + "font" to propValueFor(preferences.fontFamily), + "font_size" to propValueFor(preferences.fontSize) + ) + ) + } + + @Test + fun `given custom preferences, when trackSaved is called, then track event`() { + val preferences = ReaderReadingPreferences( + theme = ReaderReadingPreferences.Theme.SOFT, + fontFamily = ReaderReadingPreferences.FontFamily.SERIF, + fontSize = ReaderReadingPreferences.FontSize.LARGE + ) + val hasChanged = true + + tracker.trackSaved(preferences, hasChanged) + + verify(analyticsTrackerWrapper).track( + Stat.READER_READING_PREFERENCES_SAVED, + mapOf( + "is_default" to false, + "has_changed" to hasChanged, + "color_scheme" to propValueFor(preferences.theme), + "font" to propValueFor(preferences.fontFamily), + "font_size" to propValueFor(preferences.fontSize) + ) + ) + } + + @Test + fun `given no changes, when trackSaved is called, then track event`() { + val preferences = ReaderReadingPreferences() + val hasChanged = false + + tracker.trackSaved(preferences, hasChanged) + + verify(analyticsTrackerWrapper).track( + Stat.READER_READING_PREFERENCES_SAVED, + mapOf( + "is_default" to true, + "has_changed" to hasChanged, + "color_scheme" to propValueFor(preferences.theme), + "font" to propValueFor(preferences.fontFamily), + "font_size" to propValueFor(preferences.fontSize) + ) + ) + } + + // region helper methods (note: they match the implementation but they are duplicated here for reliable testing) + private fun propValueFor(theme: ReaderReadingPreferences.Theme) = when(theme) { + ReaderReadingPreferences.Theme.SYSTEM -> "default" + ReaderReadingPreferences.Theme.SOFT -> "soft" + ReaderReadingPreferences.Theme.SEPIA -> "sepia" + ReaderReadingPreferences.Theme.EVENING -> "evening" + ReaderReadingPreferences.Theme.OLED -> "oled" + ReaderReadingPreferences.Theme.H4X0R -> "h4x0r" + ReaderReadingPreferences.Theme.CANDY -> "candy" + } + + private fun propValueFor(fontFamily: ReaderReadingPreferences.FontFamily) = when(fontFamily) { + ReaderReadingPreferences.FontFamily.SANS -> "sans" + ReaderReadingPreferences.FontFamily.SERIF -> "serif" + ReaderReadingPreferences.FontFamily.MONO -> "mono" + } + + private fun propValueFor(fontSize: ReaderReadingPreferences.FontSize) = when(fontSize) { + ReaderReadingPreferences.FontSize.EXTRA_SMALL -> "extra_small" + ReaderReadingPreferences.FontSize.SMALL -> "small" + ReaderReadingPreferences.FontSize.NORMAL -> "default" + ReaderReadingPreferences.FontSize.LARGE -> "large" + ReaderReadingPreferences.FontSize.EXTRA_LARGE -> "extra_large" + } + // endregion +} From 9b0cdf4aa859bb32ed1e290172b24a486b50955c Mon Sep 17 00:00:00 2001 From: Thomas Horta Date: Thu, 4 Apr 2024 16:18:32 -0300 Subject: [PATCH 10/22] Track analytics events for Reading Preferences --- .../ui/reader/ReaderPostDetailFragment.kt | 11 +++++-- .../ReaderReadingPreferencesDialogFragment.kt | 31 +++++++++++++++-- .../discover/ReaderPostCardActionsHandler.kt | 1 - .../ReaderReadingPreferencesTracker.kt | 10 +++--- .../ReaderReadingPreferencesViewModel.kt | 30 ++++++++++++----- .../ReaderReadingPreferencesTrackerTest.kt | 33 +++---------------- .../ReaderReadingPreferencesViewModelTest.kt | 13 +++++--- 7 files changed, 77 insertions(+), 52 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostDetailFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostDetailFragment.kt index 5d0e2422014b..914eac36c195 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostDetailFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostDetailFragment.kt @@ -110,6 +110,7 @@ import org.wordpress.android.ui.reader.discover.ReaderPostCardAction.PrimaryActi import org.wordpress.android.ui.reader.discover.ReaderPostCardActionType import org.wordpress.android.ui.reader.models.ReaderBlogIdPostId import org.wordpress.android.ui.reader.models.ReaderReadingPreferences +import org.wordpress.android.ui.reader.tracker.ReaderReadingPreferencesTracker import org.wordpress.android.ui.reader.tracker.ReaderTracker import org.wordpress.android.ui.reader.tracker.ReaderTracker.Companion.SOURCE_POST_DETAIL_TOOLBAR import org.wordpress.android.ui.reader.usecases.ReaderGetReadingPreferencesSyncUseCase @@ -950,7 +951,10 @@ class ReaderPostDetailFragment : ViewPagerFragment(), } ReaderNavigationEvents.ShowReadingPreferences -> - ReaderReadingPreferencesDialogFragment.show(childFragmentManager) + ReaderReadingPreferencesDialogFragment.show( + childFragmentManager, + ReaderReadingPreferencesTracker.Source.POST_DETAIL_MORE_MENU, + ) is ReaderNavigationEvents.ShowPostDetail, is ReaderNavigationEvents.ShowVideoViewer, @@ -1128,7 +1132,10 @@ class ReaderPostDetailFragment : ViewPagerFragment(), true } R.id.menu_reading_preferences -> { - ReaderReadingPreferencesDialogFragment.show(childFragmentManager) + ReaderReadingPreferencesDialogFragment.show( + childFragmentManager, + ReaderReadingPreferencesTracker.Source.POST_DETAIL_TOOLBAR, + ) true } else -> false diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderReadingPreferencesDialogFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderReadingPreferencesDialogFragment.kt index 30d0879fcf2c..6e75a63af686 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderReadingPreferencesDialogFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderReadingPreferencesDialogFragment.kt @@ -1,6 +1,7 @@ package org.wordpress.android.ui.reader import android.app.Dialog +import android.content.DialogInterface import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -22,11 +23,13 @@ import org.wordpress.android.R import org.wordpress.android.ui.WPWebViewActivity import org.wordpress.android.ui.compose.theme.AppTheme import org.wordpress.android.ui.reader.models.ReaderReadingPreferences +import org.wordpress.android.ui.reader.tracker.ReaderReadingPreferencesTracker import org.wordpress.android.ui.reader.viewmodels.ReaderPostDetailViewModel import org.wordpress.android.ui.reader.viewmodels.ReaderReadingPreferencesViewModel import org.wordpress.android.ui.reader.viewmodels.ReaderReadingPreferencesViewModel.ActionEvent import org.wordpress.android.ui.reader.views.compose.readingpreferences.ReadingPreferencesScreen import org.wordpress.android.util.extensions.fillScreen +import org.wordpress.android.util.extensions.getSerializableCompat import org.wordpress.android.util.extensions.setWindowStatusBarColor @AndroidEntryPoint @@ -40,6 +43,13 @@ class ReaderReadingPreferencesDialogFragment : BottomSheetDialogFragment() { return R.style.ReaderReadingPreferencesDialogFragment } + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + arguments?.getSerializableCompat(ARG_SOURCE)?.let { + viewModel.onScreenOpened(it) + } + } + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -78,6 +88,11 @@ class ReaderReadingPreferencesDialogFragment : BottomSheetDialogFragment() { } } + override fun onDismiss(dialog: DialogInterface) { + super.onDismiss(dialog) + viewModel.onScreenClosed() + } + private fun observeActionEvents() { viewModel.actionEvents.onEach { when (it) { @@ -106,13 +121,23 @@ class ReaderReadingPreferencesDialogFragment : BottomSheetDialogFragment() { } companion object { - const val TAG = "READER_READING_PREFERENCES_FRAGMENT" + private const val TAG = "READER_READING_PREFERENCES_FRAGMENT" + private const val ARG_SOURCE = "source" @JvmStatic - fun newInstance(): ReaderReadingPreferencesDialogFragment = ReaderReadingPreferencesDialogFragment() + fun newInstance( + source: ReaderReadingPreferencesTracker.Source, + ): ReaderReadingPreferencesDialogFragment = ReaderReadingPreferencesDialogFragment().apply { + arguments = Bundle().apply { + putSerializable(ARG_SOURCE, source) + } + } @JvmStatic - fun show(fm: FragmentManager): ReaderReadingPreferencesDialogFragment = newInstance().also { + fun show( + fm: FragmentManager, + source: ReaderReadingPreferencesTracker.Source, + ): ReaderReadingPreferencesDialogFragment = newInstance(source).also { it.show(fm, TAG) } } 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 e07eb0813797..213ddc2fd3ac 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 @@ -397,7 +397,6 @@ class ReaderPostCardActionsHandler @Inject constructor( } private fun handleReadingPreferencesClicked() { - // TODO add analytics readerTracker.track(AnalyticsTracker.Stat.READER_READING_PREFERENCES_OPENED) _navigationEvents.postValue(Event(ShowReadingPreferences)) } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/tracker/ReaderReadingPreferencesTracker.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/tracker/ReaderReadingPreferencesTracker.kt index e05e955b06d4..a14a7a9b2fc8 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/tracker/ReaderReadingPreferencesTracker.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/tracker/ReaderReadingPreferencesTracker.kt @@ -49,10 +49,9 @@ class ReaderReadingPreferencesTracker @Inject constructor( analyticsTrackerWrapper.track(AnalyticsTracker.Stat.READER_READING_PREFERENCES_ITEM_TAPPED, props) } - fun trackSaved(preferences: ReaderReadingPreferences, hasChanged: Boolean) { + fun trackSaved(preferences: ReaderReadingPreferences) { val props = mapOf( PROP_IS_DEFAULT_KEY to preferences.isDefault(), - PROP_HAS_CHANGED_KEY to hasChanged, PROP_TYPE_THEME to propValueFor(preferences.theme), PROP_TYPE_FONT_FAMILY to propValueFor(preferences.fontFamily), PROP_TYPE_FONT_SIZE to propValueFor(preferences.fontSize), @@ -68,8 +67,8 @@ class ReaderReadingPreferencesTracker @Inject constructor( } enum class Source(val value: String) { - POST_DETAILS_TOP_BAR("post_details_top_bar"), - POST_DETAILS_MORE_MENU("post_details_more_menu"); + POST_DETAIL_TOOLBAR("post_detail_toolbar"), + POST_DETAIL_MORE_MENU("post_detail_more_menu"); companion object { const val KEY = "source" @@ -78,7 +77,6 @@ class ReaderReadingPreferencesTracker @Inject constructor( companion object { private const val PROP_IS_DEFAULT_KEY = "is_default" - private const val PROP_HAS_CHANGED_KEY = "has_changed" private const val PROP_TYPE_KEY = "type" const val PROP_TYPE_THEME = "color_scheme" @@ -106,7 +104,7 @@ class ReaderReadingPreferencesTracker @Inject constructor( private fun propValueFor(fontSize: ReaderReadingPreferences.FontSize) = when(fontSize) { ReaderReadingPreferences.FontSize.EXTRA_SMALL -> "extra_small" ReaderReadingPreferences.FontSize.SMALL -> "small" - ReaderReadingPreferences.FontSize.NORMAL -> "default" + ReaderReadingPreferences.FontSize.NORMAL -> "normal" ReaderReadingPreferences.FontSize.LARGE -> "large" ReaderReadingPreferences.FontSize.EXTRA_LARGE -> "extra_large" } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/viewmodels/ReaderReadingPreferencesViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/viewmodels/ReaderReadingPreferencesViewModel.kt index 27e20e5b18a6..c4e16cafa5d5 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/viewmodels/ReaderReadingPreferencesViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/viewmodels/ReaderReadingPreferencesViewModel.kt @@ -9,6 +9,7 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update import org.wordpress.android.modules.BG_THREAD import org.wordpress.android.ui.reader.models.ReaderReadingPreferences +import org.wordpress.android.ui.reader.tracker.ReaderReadingPreferencesTracker import org.wordpress.android.ui.reader.usecases.ReaderGetReadingPreferencesSyncUseCase import org.wordpress.android.ui.reader.usecases.ReaderSaveReadingPreferencesUseCase import org.wordpress.android.util.config.ReaderReadingPreferencesFeedbackFeatureConfig @@ -20,7 +21,8 @@ import javax.inject.Named class ReaderReadingPreferencesViewModel @Inject constructor( getReadingPreferences: ReaderGetReadingPreferencesSyncUseCase, private val saveReadingPreferences: ReaderSaveReadingPreferencesUseCase, - private val readerReadingPreferencesFeedbackFeatureConfig: ReaderReadingPreferencesFeedbackFeatureConfig, + private val readingPreferencesFeedbackFeatureConfig: ReaderReadingPreferencesFeedbackFeatureConfig, + private val readingPreferencesTracker: ReaderReadingPreferencesTracker, @Named(BG_THREAD) private val bgDispatcher: CoroutineDispatcher, ) : ScopedViewModel(bgDispatcher) { private val originalReadingPreferences = getReadingPreferences() @@ -35,37 +37,49 @@ class ReaderReadingPreferencesViewModel @Inject constructor( fun init() { launch { - _isFeedbackEnabled.emit(readerReadingPreferencesFeedbackFeatureConfig.isEnabled()) + _isFeedbackEnabled.emit(readingPreferencesFeedbackFeatureConfig.isEnabled()) _actionEvents.emit(ActionEvent.UpdateStatusBarColor(originalReadingPreferences.theme)) } } + fun onScreenOpened(source: ReaderReadingPreferencesTracker.Source) { + readingPreferencesTracker.trackScreenOpened(source) + } + + fun onScreenClosed() { + readingPreferencesTracker.trackScreenClosed() + } + fun onThemeClick(theme: ReaderReadingPreferences.Theme) { _currentReadingPreferences.update { it.copy(theme = theme) } + readingPreferencesTracker.trackItemTapped(theme) } fun onFontFamilyClick(fontFamily: ReaderReadingPreferences.FontFamily) { _currentReadingPreferences.update { it.copy(fontFamily = fontFamily) } + readingPreferencesTracker.trackItemTapped(fontFamily) } fun onFontSizeClick(fontSize: ReaderReadingPreferences.FontSize) { _currentReadingPreferences.update { it.copy(fontSize = fontSize) } + readingPreferencesTracker.trackItemTapped(fontSize) } fun saveReadingPreferencesAndClose() { launch { - if (currentReadingPreferences.value != originalReadingPreferences) { - saveReadingPreferences(currentReadingPreferences.value) - val isDirty = currentReadingPreferences.value != originalReadingPreferences - _actionEvents.emit(ActionEvent.Close(isDirty = isDirty)) - } else { - _actionEvents.emit(ActionEvent.Close(isDirty = false)) + val currentPreferences = currentReadingPreferences.value + val isDirty = currentPreferences != originalReadingPreferences + if (isDirty) { + saveReadingPreferences(currentPreferences) + readingPreferencesTracker.trackSaved(currentPreferences) } + _actionEvents.emit(ActionEvent.Close(isDirty)) } } fun onSendFeedbackClick() { launch { + readingPreferencesTracker.trackFeedbackTapped() _actionEvents.emit(ActionEvent.OpenWebView(FEEDBACK_URL)) } } diff --git a/WordPress/src/test/java/org/wordpress/android/ui/reader/tracker/ReaderReadingPreferencesTrackerTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/reader/tracker/ReaderReadingPreferencesTrackerTest.kt index b3c2648a3762..46292f092bb2 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/reader/tracker/ReaderReadingPreferencesTrackerTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/reader/tracker/ReaderReadingPreferencesTrackerTest.kt @@ -29,8 +29,8 @@ class ReaderReadingPreferencesTrackerTest { tracker.trackScreenOpened(source) val expectedSource = when (source) { - Source.POST_DETAILS_TOP_BAR -> "post_details_top_bar" - Source.POST_DETAILS_MORE_MENU -> "post_details_more_menu" + Source.POST_DETAIL_TOOLBAR -> "post_detail_toolbar" + Source.POST_DETAIL_MORE_MENU -> "post_detail_more_menu" } verify(analyticsTrackerWrapper).track( @@ -102,15 +102,13 @@ class ReaderReadingPreferencesTrackerTest { @Test fun `given default preferences, when trackSaved is called, then track event`() { val preferences = ReaderReadingPreferences() - val hasChanged = true - tracker.trackSaved(preferences, hasChanged) + tracker.trackSaved(preferences) verify(analyticsTrackerWrapper).track( Stat.READER_READING_PREFERENCES_SAVED, mapOf( "is_default" to true, - "has_changed" to hasChanged, "color_scheme" to propValueFor(preferences.theme), "font" to propValueFor(preferences.fontFamily), "font_size" to propValueFor(preferences.fontSize) @@ -125,34 +123,13 @@ class ReaderReadingPreferencesTrackerTest { fontFamily = ReaderReadingPreferences.FontFamily.SERIF, fontSize = ReaderReadingPreferences.FontSize.LARGE ) - val hasChanged = true - tracker.trackSaved(preferences, hasChanged) + tracker.trackSaved(preferences) verify(analyticsTrackerWrapper).track( Stat.READER_READING_PREFERENCES_SAVED, mapOf( "is_default" to false, - "has_changed" to hasChanged, - "color_scheme" to propValueFor(preferences.theme), - "font" to propValueFor(preferences.fontFamily), - "font_size" to propValueFor(preferences.fontSize) - ) - ) - } - - @Test - fun `given no changes, when trackSaved is called, then track event`() { - val preferences = ReaderReadingPreferences() - val hasChanged = false - - tracker.trackSaved(preferences, hasChanged) - - verify(analyticsTrackerWrapper).track( - Stat.READER_READING_PREFERENCES_SAVED, - mapOf( - "is_default" to true, - "has_changed" to hasChanged, "color_scheme" to propValueFor(preferences.theme), "font" to propValueFor(preferences.fontFamily), "font_size" to propValueFor(preferences.fontSize) @@ -180,7 +157,7 @@ class ReaderReadingPreferencesTrackerTest { private fun propValueFor(fontSize: ReaderReadingPreferences.FontSize) = when(fontSize) { ReaderReadingPreferences.FontSize.EXTRA_SMALL -> "extra_small" ReaderReadingPreferences.FontSize.SMALL -> "small" - ReaderReadingPreferences.FontSize.NORMAL -> "default" + ReaderReadingPreferences.FontSize.NORMAL -> "normal" ReaderReadingPreferences.FontSize.LARGE -> "large" ReaderReadingPreferences.FontSize.EXTRA_LARGE -> "extra_large" } diff --git a/WordPress/src/test/java/org/wordpress/android/ui/reader/viewmodels/ReaderReadingPreferencesViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/reader/viewmodels/ReaderReadingPreferencesViewModelTest.kt index 128c8aa42a90..ac5343768947 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/reader/viewmodels/ReaderReadingPreferencesViewModelTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/reader/viewmodels/ReaderReadingPreferencesViewModelTest.kt @@ -16,6 +16,7 @@ import org.mockito.kotlin.verify import org.mockito.kotlin.whenever import org.wordpress.android.BaseUnitTest import org.wordpress.android.ui.reader.models.ReaderReadingPreferences +import org.wordpress.android.ui.reader.tracker.ReaderReadingPreferencesTracker import org.wordpress.android.ui.reader.usecases.ReaderGetReadingPreferencesSyncUseCase import org.wordpress.android.ui.reader.usecases.ReaderSaveReadingPreferencesUseCase import org.wordpress.android.ui.reader.viewmodels.ReaderReadingPreferencesViewModel.ActionEvent @@ -30,7 +31,10 @@ class ReaderReadingPreferencesViewModelTest : BaseUnitTest() { lateinit var saveReadingPreferences: ReaderSaveReadingPreferencesUseCase @Mock - lateinit var readerReadingPreferencesFeedbackFeatureConfig: ReaderReadingPreferencesFeedbackFeatureConfig + lateinit var readingPreferencesFeedbackFeatureConfig: ReaderReadingPreferencesFeedbackFeatureConfig + + @Mock + lateinit var readingPreferencesTracker: ReaderReadingPreferencesTracker private val viewModelDispatcher = UnconfinedTestDispatcher(testDispatcher().scheduler) private lateinit var viewModel: ReaderReadingPreferencesViewModel @@ -44,7 +48,8 @@ class ReaderReadingPreferencesViewModelTest : BaseUnitTest() { viewModel = ReaderReadingPreferencesViewModel( getReadingPreferences, saveReadingPreferences, - readerReadingPreferencesFeedbackFeatureConfig, + readingPreferencesFeedbackFeatureConfig, + readingPreferencesTracker, viewModelDispatcher, ) @@ -172,7 +177,7 @@ class ReaderReadingPreferencesViewModelTest : BaseUnitTest() { @Test fun `when readerReadingPreferencesFeedbackFeatureConfig is true then isFeedbackEnabled emits true`() = test { // Given - whenever(readerReadingPreferencesFeedbackFeatureConfig.isEnabled()).thenReturn(true) + whenever(readingPreferencesFeedbackFeatureConfig.isEnabled()).thenReturn(true) // When viewModel.init() @@ -185,7 +190,7 @@ class ReaderReadingPreferencesViewModelTest : BaseUnitTest() { @Test fun `when readerReadingPreferencesFeedbackFeatureConfig is false then isFeedbackEnabled emits false`() = test { // Given - whenever(readerReadingPreferencesFeedbackFeatureConfig.isEnabled()).thenReturn(false) + whenever(readingPreferencesFeedbackFeatureConfig.isEnabled()).thenReturn(false) // When viewModel.init() From 628383695300e74afc292fbd3dc87f8ea2ed7d36 Mon Sep 17 00:00:00 2001 From: Thomas Horta Date: Thu, 4 Apr 2024 16:22:44 -0300 Subject: [PATCH 11/22] Add unit tests for Reading Preferences tracking --- .../ReaderPostCardActionsHandlerTest.kt | 18 +++++ .../ReaderReadingPreferencesViewModelTest.kt | 76 +++++++++++++++++++ 2 files changed, 94 insertions(+) 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 873442e99762..aa9580135f85 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 @@ -32,6 +32,7 @@ import org.wordpress.android.ui.reader.discover.ReaderNavigationEvents.ShowBookm import org.wordpress.android.ui.reader.discover.ReaderNavigationEvents.ShowNoSitesToReblog import org.wordpress.android.ui.reader.discover.ReaderNavigationEvents.ShowPostDetail import org.wordpress.android.ui.reader.discover.ReaderNavigationEvents.ShowReaderComments +import org.wordpress.android.ui.reader.discover.ReaderNavigationEvents.ShowReadingPreferences import org.wordpress.android.ui.reader.discover.ReaderNavigationEvents.ShowReportPost import org.wordpress.android.ui.reader.discover.ReaderNavigationEvents.ShowReportUser import org.wordpress.android.ui.reader.discover.ReaderNavigationEvents.ShowSitePickerForResult @@ -42,6 +43,7 @@ import org.wordpress.android.ui.reader.discover.ReaderPostCardActionType.BOOKMAR import org.wordpress.android.ui.reader.discover.ReaderPostCardActionType.COMMENTS import org.wordpress.android.ui.reader.discover.ReaderPostCardActionType.FOLLOW import org.wordpress.android.ui.reader.discover.ReaderPostCardActionType.LIKE +import org.wordpress.android.ui.reader.discover.ReaderPostCardActionType.READING_PREFERENCES import org.wordpress.android.ui.reader.discover.ReaderPostCardActionType.REBLOG import org.wordpress.android.ui.reader.discover.ReaderPostCardActionType.SHARE import org.wordpress.android.ui.reader.discover.ReaderPostCardActionType.SITE_NOTIFICATIONS @@ -1214,6 +1216,22 @@ class ReaderPostCardActionsHandlerTest : BaseUnitTest() { /** COMMENTS ACTION end **/ + /** READING PREFERENCES ACTION begin **/ + @Test + fun `Reading preferences screen shown when the user clicks on reading preferences button`() = test { + // Arrange + val observedValues = startObserving() + // Act + actionHandler.onAction( + mock(), + READING_PREFERENCES, + false, + SOURCE + ) + // Assert + assertThat(observedValues.navigation[0]).isInstanceOf(ShowReadingPreferences::class.java) + } + @Test fun `Clicking on a post opens post detail`() = test { // Arrange diff --git a/WordPress/src/test/java/org/wordpress/android/ui/reader/viewmodels/ReaderReadingPreferencesViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/reader/viewmodels/ReaderReadingPreferencesViewModelTest.kt index ac5343768947..e37042061b1d 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/reader/viewmodels/ReaderReadingPreferencesViewModelTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/reader/viewmodels/ReaderReadingPreferencesViewModelTest.kt @@ -200,6 +200,82 @@ class ReaderReadingPreferencesViewModelTest : BaseUnitTest() { assertThat(isFeedbackEnabled).isFalse() } + // analytics tests + @Test + fun `when onScreenOpened is called then it should track the screen opened event`() = test { + ReaderReadingPreferencesTracker.Source.values().forEach { source -> + // When + viewModel.onScreenOpened(source) + + // Then + verify(readingPreferencesTracker).trackScreenOpened(source) + } + } + + @Test + fun `when onScreenClosed is called then it should track the screen closed event`() = test { + // When + viewModel.onScreenClosed() + + // Then + verify(readingPreferencesTracker).trackScreenClosed() + } + + @Test + fun `when onSendFeedbackClick is called then it should track the feedback tapped event`() = test { + // When + viewModel.onSendFeedbackClick() + + // Then + verify(readingPreferencesTracker).trackFeedbackTapped() + } + + @Test + fun `when onThemeClick is called then it should track the theme tapped event`() = test { + ReaderReadingPreferences.Theme.values().forEach { theme -> + // When + viewModel.onThemeClick(theme) + + // Then + verify(readingPreferencesTracker).trackItemTapped(theme) + } + } + + @Test + fun `when onFontFamilyClick is called then it should track the font family tapped event`() = test { + ReaderReadingPreferences.FontFamily.values().forEach { fontFamily -> + // When + viewModel.onFontFamilyClick(fontFamily) + + // Then + verify(readingPreferencesTracker).trackItemTapped(fontFamily) + } + } + + @Test + fun `when onFontSizeClick is called then it should track the font size tapped event`() = test { + ReaderReadingPreferences.FontSize.values().forEach { fontSize -> + // When + viewModel.onFontSizeClick(fontSize) + + // Then + verify(readingPreferencesTracker).trackItemTapped(fontSize) + } + } + + @Test + fun `when saveReadingPreferencesAndClose is called then it should track the saved event`() = test { + // Given + val newTheme = ReaderReadingPreferences.Theme.SOFT + viewModel.onThemeClick(newTheme) + + // When + viewModel.saveReadingPreferencesAndClose() + + // Then + verify(readingPreferencesTracker).trackSaved(argThat { theme == newTheme }) + } + companion object { private val DEFAULT_READING_PREFERENCES = ReaderReadingPreferences() private const val EXPECTED_FEEDBACK_URL = "https://automattic.survey.fm/reader-customization-survey" From 6f6bce630c6803f668acb891576f2b63d944093c Mon Sep 17 00:00:00 2001 From: Thomas Horta Date: Thu, 4 Apr 2024 16:43:26 -0300 Subject: [PATCH 12/22] Cache reading preferences in repository for better multiple-call performance --- .../ReaderReadingPreferencesRepository.kt | 24 +++++++++++++------ .../ReaderReadingPreferencesRepositoryTest.kt | 21 +++++++++++++++- 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/repository/ReaderReadingPreferencesRepository.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/repository/ReaderReadingPreferencesRepository.kt index c27831585c0f..a86c550f7bef 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/repository/ReaderReadingPreferencesRepository.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/repository/ReaderReadingPreferencesRepository.kt @@ -10,7 +10,9 @@ import org.wordpress.android.util.EnumWithFallbackValueTypeAdapterFactory import org.wordpress.android.util.config.ReaderReadingPreferencesFeatureConfig import javax.inject.Inject import javax.inject.Named +import javax.inject.Singleton +@Singleton class ReaderReadingPreferencesRepository @Inject constructor( private val appPrefsWrapper: AppPrefsWrapper, private val readingPreferencesFeatureConfig: ReaderReadingPreferencesFeatureConfig, @@ -20,23 +22,31 @@ class ReaderReadingPreferencesRepository @Inject constructor( .registerTypeAdapterFactory(EnumWithFallbackValueTypeAdapterFactory()) .create() + // the preferences never change during the app lifecycle, so we can cache them safely for better performance + private var readingPreferences: ReaderReadingPreferences? = null + suspend fun getReadingPreferences(): ReaderReadingPreferences = withContext(ioDispatcher) { getReadingPreferencesSync() } fun getReadingPreferencesSync(): ReaderReadingPreferences { - val savedPreferences = if (readingPreferencesFeatureConfig.isEnabled()) { - appPrefsWrapper.readerReadingPreferencesJson - } else { - null + if (!readingPreferencesFeatureConfig.isEnabled()) { + return ReaderReadingPreferences() } - return savedPreferences?.let { - gson.fromJson(it, ReaderReadingPreferences::class.java) - } ?: ReaderReadingPreferences() + return readingPreferences ?: loadReadingPreferences().also { + readingPreferences = it + } } suspend fun saveReadingPreferences(preferences: ReaderReadingPreferences): Unit = withContext(ioDispatcher) { appPrefsWrapper.readerReadingPreferencesJson = gson.toJson(preferences) + readingPreferences = preferences + } + + private fun loadReadingPreferences(): ReaderReadingPreferences { + return appPrefsWrapper.readerReadingPreferencesJson?.let { + gson.fromJson(it, ReaderReadingPreferences::class.java) + } ?: ReaderReadingPreferences() } } diff --git a/WordPress/src/test/java/org/wordpress/android/ui/reader/repository/ReaderReadingPreferencesRepositoryTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/reader/repository/ReaderReadingPreferencesRepositoryTest.kt index 6b578d82f153..c366636f0181 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/reader/repository/ReaderReadingPreferencesRepositoryTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/reader/repository/ReaderReadingPreferencesRepositoryTest.kt @@ -5,8 +5,10 @@ import org.assertj.core.api.Assertions.assertThat import org.junit.Before import org.junit.Test import org.mockito.Mock +import org.mockito.kotlin.clearInvocations import org.mockito.kotlin.spy import org.mockito.kotlin.verify +import org.mockito.kotlin.verifyNoInteractions import org.mockito.kotlin.whenever import org.wordpress.android.BaseUnitTest import org.wordpress.android.ui.prefs.AppPrefsWrapper @@ -48,7 +50,7 @@ class ReaderReadingPreferencesRepositoryTest : BaseUnitTest() { } @Test - fun `getReadingPreferencesSync should return saved preferences if feature is enabled`() { + fun `getReadingPreferencesSync should return saved preferences the first time it's called`() { // Given whenever(readingPreferencesFeatureConfig.isEnabled()).thenReturn(true) whenever(appPrefsWrapper.readerReadingPreferencesJson).thenReturn(READER_PREFERENCES_JSON) @@ -57,6 +59,23 @@ class ReaderReadingPreferencesRepositoryTest : BaseUnitTest() { val result = repository.getReadingPreferencesSync() // Then + verify(appPrefsWrapper).readerReadingPreferencesJson + assertThat(result).isEqualTo(READER_PREFERENCES) + } + + @Test + fun `getReadingPreferencesSync should return cached preferences the second time it's called`() { + // Given + whenever(readingPreferencesFeatureConfig.isEnabled()).thenReturn(true) + whenever(appPrefsWrapper.readerReadingPreferencesJson).thenReturn(READER_PREFERENCES_JSON) + + // When + repository.getReadingPreferencesSync() + clearInvocations(appPrefsWrapper) + val result = repository.getReadingPreferencesSync() + + // Then + verifyNoInteractions(appPrefsWrapper) assertThat(result).isEqualTo(READER_PREFERENCES) } From 5ee56aa27dda68e9c848f970eef53305f0100e64 Mon Sep 17 00:00:00 2001 From: Thomas Horta Date: Thu, 4 Apr 2024 17:07:37 -0300 Subject: [PATCH 13/22] Add reading preferences properties to reader_article_opened --- .../ui/reader/ReaderPostPagerActivity.java | 5 ++++- .../ReaderReadingPreferencesTracker.kt | 22 ++++++++++++++----- .../ui/reader/tracker/ReaderTracker.kt | 17 +++++++++++++- 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostPagerActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostPagerActivity.java index 9f7f2de1c01c..4b617af9d089 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostPagerActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostPagerActivity.java @@ -64,6 +64,7 @@ import org.wordpress.android.ui.reader.services.post.ReaderPostServiceStarter; import org.wordpress.android.ui.reader.tracker.ReaderTracker; import org.wordpress.android.ui.reader.tracker.ReaderTrackerType; +import org.wordpress.android.ui.reader.usecases.ReaderGetReadingPreferencesSyncUseCase; import org.wordpress.android.ui.reader.utils.ReaderPostSeenStatusWrapper; import org.wordpress.android.ui.sitecreation.misc.SiteCreationSource; import org.wordpress.android.ui.uploads.UploadActionUseCase; @@ -176,6 +177,7 @@ public enum DirectOperation { private JetpackFeatureFullScreenOverlayViewModel mJetpackFullScreenViewModel; @Inject AccountStore mAccountStore; @Inject JetpackFeatureRemovalPhaseHelper mJetpackFeatureRemovalPhaseHelper; + @Inject ReaderGetReadingPreferencesSyncUseCase mGetReadingPreferencesSyncUseCase; @Override public void onCreate(@Nullable Bundle savedInstanceState) { @@ -766,7 +768,8 @@ private void trackPost(long blogId, long postId) { // analytics tracking mReaderTracker.trackPost( AnalyticsTracker.Stat.READER_ARTICLE_OPENED, - mReaderPostTableWrapper.getBlogPost(blogId, postId, true) + mReaderPostTableWrapper.getBlogPost(blogId, postId, true), + mGetReadingPreferencesSyncUseCase.invoke() ); } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/tracker/ReaderReadingPreferencesTracker.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/tracker/ReaderReadingPreferencesTracker.kt index a14a7a9b2fc8..6dba0899bdee 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/tracker/ReaderReadingPreferencesTracker.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/tracker/ReaderReadingPreferencesTracker.kt @@ -50,14 +50,24 @@ class ReaderReadingPreferencesTracker @Inject constructor( } fun trackSaved(preferences: ReaderReadingPreferences) { - val props = mapOf( - PROP_IS_DEFAULT_KEY to preferences.isDefault(), - PROP_TYPE_THEME to propValueFor(preferences.theme), - PROP_TYPE_FONT_FAMILY to propValueFor(preferences.fontFamily), - PROP_TYPE_FONT_SIZE to propValueFor(preferences.fontSize), + analyticsTrackerWrapper.track( + AnalyticsTracker.Stat.READER_READING_PREFERENCES_SAVED, + getPropertiesForPreferences(preferences) ) + } - analyticsTrackerWrapper.track(AnalyticsTracker.Stat.READER_READING_PREFERENCES_SAVED, props) + fun getPropertiesForPreferences( + preferences: ReaderReadingPreferences, + prefix: String? = null, + ): MutableMap { + fun String.withPrefix() = prefix?.let { "${it}_$this" } ?: this + + return mutableMapOf( + PROP_IS_DEFAULT_KEY.withPrefix() to preferences.isDefault(), + PROP_TYPE_THEME.withPrefix() to propValueFor(preferences.theme), + PROP_TYPE_FONT_FAMILY.withPrefix() to propValueFor(preferences.fontFamily), + PROP_TYPE_FONT_SIZE.withPrefix() to propValueFor(preferences.fontSize), + ) } private fun ReaderReadingPreferences.isDefault(): Boolean { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/tracker/ReaderTracker.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/tracker/ReaderTracker.kt index 2266d20b391f..1788e4148ef2 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/tracker/ReaderTracker.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/tracker/ReaderTracker.kt @@ -8,6 +8,7 @@ import org.wordpress.android.models.ReaderPost import org.wordpress.android.models.ReaderTag import org.wordpress.android.ui.prefs.AppPrefsWrapper import org.wordpress.android.ui.reader.ReaderTypes.ReaderPostListType +import org.wordpress.android.ui.reader.models.ReaderReadingPreferences import org.wordpress.android.ui.reader.utils.DateProvider import org.wordpress.android.util.AppLog import org.wordpress.android.util.DateTimeUtils @@ -23,7 +24,8 @@ class ReaderTracker @Inject constructor( private val dateProvider: DateProvider, private val appPrefsWrapper: AppPrefsWrapper, private val analyticsTrackerWrapper: AnalyticsTrackerWrapper, - private val analyticsUtilsWrapper: AnalyticsUtilsWrapper + private val analyticsUtilsWrapper: AnalyticsUtilsWrapper, + private val readingPreferencesTracker: ReaderReadingPreferencesTracker, ) { // TODO: evaluate to use something like Dispatchers.Main.Immediate in the fun(s) // to sync the access to trackers; so to remove the @MainThread and make the @@ -295,6 +297,18 @@ class ReaderTracker @Inject constructor( trackPost(stat, post, mutableMapOf()) } + fun trackPost( + stat: AnalyticsTracker.Stat, + post: ReaderPost?, + readingPreferences: ReaderReadingPreferences, + ) { + trackPost( + stat, + post, + readingPreferencesTracker.getPropertiesForPreferences(readingPreferences, READING_PREFERENCES_KEYS_PREFIX) + ) + } + fun trackPost( stat: AnalyticsTracker.Stat, post: ReaderPost?, @@ -439,6 +453,7 @@ class ReaderTracker @Inject constructor( private const val QUANTITY_KEY = "quantity" private const val INTERCEPTED_URI_KEY = "intercepted_uri" private const val QUERY_KEY = "query" + private const val READING_PREFERENCES_KEYS_PREFIX = "reading_preferences" private const val SOURCE_KEY = "source" const val SOURCE_FOLLOWING = "following" From 97a55b9a2b8e3947f2d577ebb7bc2eaf281eedb0 Mon Sep 17 00:00:00 2001 From: Thomas Horta Date: Thu, 4 Apr 2024 17:25:44 -0300 Subject: [PATCH 14/22] Add more reading preferences track related unit tests --- .../android/ui/reader/ReaderTrackerTest.kt | 28 ++++++++++- .../ReaderReadingPreferencesTrackerTest.kt | 47 +++++++++++++++++-- 2 files changed, 71 insertions(+), 4 deletions(-) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/reader/ReaderTrackerTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/reader/ReaderTrackerTest.kt index e6eddc8466df..c45df778107b 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/reader/ReaderTrackerTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/reader/ReaderTrackerTest.kt @@ -6,12 +6,17 @@ import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.junit.MockitoJUnitRunner +import org.mockito.kotlin.any +import org.mockito.kotlin.eq import org.mockito.kotlin.verify import org.mockito.kotlin.whenever import org.wordpress.android.analytics.AnalyticsTracker +import org.wordpress.android.models.ReaderPost import org.wordpress.android.models.ReaderTag import org.wordpress.android.models.ReaderTagType import org.wordpress.android.ui.prefs.AppPrefsWrapper +import org.wordpress.android.ui.reader.models.ReaderReadingPreferences +import org.wordpress.android.ui.reader.tracker.ReaderReadingPreferencesTracker import org.wordpress.android.ui.reader.tracker.ReaderTracker import org.wordpress.android.ui.reader.tracker.ReaderTrackerType import org.wordpress.android.ui.reader.utils.DateProvider @@ -34,6 +39,9 @@ class ReaderTrackerTest { @Mock lateinit var analyticsUtilsWrapper: AnalyticsUtilsWrapper + @Mock + lateinit var readingPreferencesTracker: ReaderReadingPreferencesTracker + private lateinit var tracker: ReaderTracker @Before @@ -42,7 +50,8 @@ class ReaderTrackerTest { dateProvider, appPrefsWrapper, analyticsTrackerWrapper, - analyticsUtilsWrapper + analyticsUtilsWrapper, + readingPreferencesTracker, ) } @@ -316,6 +325,23 @@ class ReaderTrackerTest { ) } + @Test + fun `Should track post with reading preferences returned from ReadingPreferencesTracker`() { + val post = ReaderPost() + val readingPreferences = ReaderReadingPreferences() + val properties = mutableMapOf("key" to "value") + whenever(readingPreferencesTracker.getPropertiesForPreferences(eq(readingPreferences), any())) + .thenReturn(properties) + + tracker.trackPost(AnalyticsTracker.Stat.READER_ARTICLE_OPENED, post, readingPreferences) + + verify(analyticsUtilsWrapper).trackWithReaderPostDetails( + AnalyticsTracker.Stat.READER_ARTICLE_OPENED, + post, + properties + ) + } + private fun addToDate(date: Date, seconds: Int): Date { val calendar = Calendar.getInstance() calendar.time = date diff --git a/WordPress/src/test/java/org/wordpress/android/ui/reader/tracker/ReaderReadingPreferencesTrackerTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/reader/tracker/ReaderReadingPreferencesTrackerTest.kt index 46292f092bb2..9a7593a8a5ed 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/reader/tracker/ReaderReadingPreferencesTrackerTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/reader/tracker/ReaderReadingPreferencesTrackerTest.kt @@ -1,5 +1,6 @@ package org.wordpress.android.ui.reader.tracker +import org.assertj.core.api.Assertions.assertThat import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -137,8 +138,48 @@ class ReaderReadingPreferencesTrackerTest { ) } + @Test + fun `given all possible combinations, when getPropertiesForPreferences is called, return expected properties`() { + val defaultPreferences = ReaderReadingPreferences() + + ReaderReadingPreferences.Theme.values().forEach { theme -> + ReaderReadingPreferences.FontFamily.values().forEach { fontFamily -> + ReaderReadingPreferences.FontSize.values().forEach { fontSize -> + val preferences = ReaderReadingPreferences(theme, fontFamily, fontSize) + val expectedProperties = mapOf( + "is_default" to (preferences == defaultPreferences), + "color_scheme" to propValueFor(theme), + "font" to propValueFor(fontFamily), + "font_size" to propValueFor(fontSize) + ) + + val result = tracker.getPropertiesForPreferences(preferences) + + assertThat(result).isEqualTo(expectedProperties) + } + } + } + } + + @Test + fun `given a prefix, when getPropertiesForPreferences is called, return expected properties with prefix`() { + val prefix = "my_prefix" + + val preferences = ReaderReadingPreferences() + val expectedProperties = mapOf( + "my_prefix_is_default" to true, + "my_prefix_color_scheme" to propValueFor(preferences.theme), + "my_prefix_font" to propValueFor(preferences.fontFamily), + "my_prefix_font_size" to propValueFor(preferences.fontSize) + ) + + val result = tracker.getPropertiesForPreferences(preferences, prefix) + + assertThat(result).isEqualTo(expectedProperties) + } + // region helper methods (note: they match the implementation but they are duplicated here for reliable testing) - private fun propValueFor(theme: ReaderReadingPreferences.Theme) = when(theme) { + private fun propValueFor(theme: ReaderReadingPreferences.Theme) = when (theme) { ReaderReadingPreferences.Theme.SYSTEM -> "default" ReaderReadingPreferences.Theme.SOFT -> "soft" ReaderReadingPreferences.Theme.SEPIA -> "sepia" @@ -148,13 +189,13 @@ class ReaderReadingPreferencesTrackerTest { ReaderReadingPreferences.Theme.CANDY -> "candy" } - private fun propValueFor(fontFamily: ReaderReadingPreferences.FontFamily) = when(fontFamily) { + private fun propValueFor(fontFamily: ReaderReadingPreferences.FontFamily) = when (fontFamily) { ReaderReadingPreferences.FontFamily.SANS -> "sans" ReaderReadingPreferences.FontFamily.SERIF -> "serif" ReaderReadingPreferences.FontFamily.MONO -> "mono" } - private fun propValueFor(fontSize: ReaderReadingPreferences.FontSize) = when(fontSize) { + private fun propValueFor(fontSize: ReaderReadingPreferences.FontSize) = when (fontSize) { ReaderReadingPreferences.FontSize.EXTRA_SMALL -> "extra_small" ReaderReadingPreferences.FontSize.SMALL -> "small" ReaderReadingPreferences.FontSize.NORMAL -> "normal" From f255597362ff520d7eaade51586f0b9e576104aa Mon Sep 17 00:00:00 2001 From: Thomas Horta Date: Thu, 4 Apr 2024 11:49:20 -0300 Subject: [PATCH 15/22] Add experimental badge --- .../ReadingPreferencesScreen.kt | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/views/compose/readingpreferences/ReadingPreferencesScreen.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/views/compose/readingpreferences/ReadingPreferencesScreen.kt index 4fb7a92b216b..bcb56b3ed328 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/views/compose/readingpreferences/ReadingPreferencesScreen.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/views/compose/readingpreferences/ReadingPreferencesScreen.kt @@ -4,6 +4,7 @@ import androidx.compose.animation.animateColorAsState import androidx.compose.foundation.background import androidx.compose.foundation.horizontalScroll import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.FlowRow @@ -15,6 +16,7 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.text.ClickableText import androidx.compose.foundation.verticalScroll import androidx.compose.material.MaterialTheme @@ -98,6 +100,26 @@ fun ReadingPreferencesScreen( onNavigationIconClick = onCloseClick, backgroundColor = backgroundColor, contentColor = baseTextColor, + actions = { + Box( + modifier = Modifier + .background(baseTextColor, shape = CircleShape) + .padding( + vertical = Margin.Medium.value, + horizontal = Margin.Large.value, + ), + contentAlignment = Alignment.Center, + ) { + Text( + text = "Experimental", + style = TextStyle( + color = backgroundColor, + fontSize = 14.sp, + fontWeight = FontWeight.Medium, + ), + ) + } + } ) // Preview section From 9e5f733eebe1dc2626db05a461d2d15c998ad986 Mon Sep 17 00:00:00 2001 From: Thomas Horta Date: Fri, 5 Apr 2024 16:45:30 -0300 Subject: [PATCH 16/22] Text-only experimental badge in Reading Preferences screen --- .../ReadingPreferencesScreen.kt | 40 +++++++++---------- WordPress/src/main/res/values/strings.xml | 2 + 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/views/compose/readingpreferences/ReadingPreferencesScreen.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/views/compose/readingpreferences/ReadingPreferencesScreen.kt index bcb56b3ed328..a820c248400d 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/views/compose/readingpreferences/ReadingPreferencesScreen.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/views/compose/readingpreferences/ReadingPreferencesScreen.kt @@ -4,7 +4,6 @@ import androidx.compose.animation.animateColorAsState import androidx.compose.foundation.background import androidx.compose.foundation.horizontalScroll import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.FlowRow @@ -16,7 +15,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.text.ClickableText import androidx.compose.foundation.verticalScroll import androidx.compose.material.MaterialTheme @@ -101,24 +99,10 @@ fun ReadingPreferencesScreen( backgroundColor = backgroundColor, contentColor = baseTextColor, actions = { - Box( - modifier = Modifier - .background(baseTextColor, shape = CircleShape) - .padding( - vertical = Margin.Medium.value, - horizontal = Margin.Large.value, - ), - contentAlignment = Alignment.Center, - ) { - Text( - text = "Experimental", - style = TextStyle( - color = backgroundColor, - fontSize = 14.sp, - fontWeight = FontWeight.Medium, - ), - ) - } + ExperimentalBadge( + contentColor = textColor, + modifier = Modifier.padding(end = Margin.Large.value), + ) } ) @@ -254,6 +238,22 @@ fun ReadingPreferencesScreen( } } +@Composable +private fun ExperimentalBadge( + contentColor: Color, + modifier: Modifier = Modifier, +) { + Text( + text = stringResource(R.string.experimental_badge), + modifier = modifier, + style = TextStyle( + color = contentColor.copy(alpha = 0.6f), + fontWeight = FontWeight.Medium, + fontFamily = FontFamily.Monospace, + ), + ) +} + @Composable private fun ReadingPreferencesPreviewFeedback( onSendFeedbackClick: () -> Unit, diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml index 634a93666360..c3201b709286 100644 --- a/WordPress/src/main/res/values/strings.xml +++ b/WordPress/src/main/res/values/strings.xml @@ -120,6 +120,8 @@ Me Everyone + [Experimental] + %d selected From c24c155365bf3591e8a22db2cb5c6c301d43c596 Mon Sep 17 00:00:00 2001 From: Thomas Horta Date: Mon, 1 Apr 2024 16:24:57 -0300 Subject: [PATCH 17/22] Make Reading Preferences Feature Config remote --- .../config/ReaderReadingPreferencesFeatureConfig.kt | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/util/config/ReaderReadingPreferencesFeatureConfig.kt b/WordPress/src/main/java/org/wordpress/android/util/config/ReaderReadingPreferencesFeatureConfig.kt index bdc4d6bceed4..477a2bc0aa80 100644 --- a/WordPress/src/main/java/org/wordpress/android/util/config/ReaderReadingPreferencesFeatureConfig.kt +++ b/WordPress/src/main/java/org/wordpress/android/util/config/ReaderReadingPreferencesFeatureConfig.kt @@ -1,12 +1,18 @@ package org.wordpress.android.util.config import org.wordpress.android.BuildConfig -import org.wordpress.android.annotation.FeatureInDevelopment +import org.wordpress.android.annotation.Feature import javax.inject.Inject -@FeatureInDevelopment +private const val READING_PREFERENCES_REMOTE_FIELD = "reading_preferences" + +@Feature(READING_PREFERENCES_REMOTE_FIELD, true) class ReaderReadingPreferencesFeatureConfig -@Inject constructor(appConfig: AppConfig) : FeatureConfig(appConfig, BuildConfig.READER_READING_PREFERENCES) { +@Inject constructor(appConfig: AppConfig) : FeatureConfig( + appConfig, + BuildConfig.READER_READING_PREFERENCES, + READING_PREFERENCES_REMOTE_FIELD, +) { override fun isEnabled(): Boolean { return super.isEnabled() && BuildConfig.IS_JETPACK_APP } From b034305afe3469e435b66c8f6de5a175e0cadc55 Mon Sep 17 00:00:00 2001 From: Thomas Horta Date: Fri, 5 Apr 2024 16:58:17 -0300 Subject: [PATCH 18/22] Add release notes for Reading Preferences --- RELEASE-NOTES.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index cca5a3431484..f89ff46e7eb5 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -9,6 +9,7 @@ * [**] Block editor: Highlight text fixes [https://github.com/WordPress/gutenberg/pull/57650] * [*] Block editor: Fixes an Aztec editor crash occurring on some occasions when the keyboard suggestions are used [https://github.com/wordpress-mobile/WordPress-Android/pull/20518] * [*] [Jetpack-only] Change "∞" symbol with "100%" on stats [https://github.com/wordpress-mobile/WordPress-Android/pull/20564] +* [**] [Jetpack-only] Reader: introduce "reading preferences", an experimental feature that allows users to customize their Reader post content screen with the color, font, and size that they like the most. [https://github.com/wordpress-mobile/WordPress-Android/pull/20567] 24.5 ----- From d74a6f5b6d0e79d5e74346377540c2b5d9a98ed6 Mon Sep 17 00:00:00 2001 From: Thomas Horta Date: Fri, 5 Apr 2024 17:41:38 -0300 Subject: [PATCH 19/22] Change font family of badge according to selection --- .../compose/readingpreferences/ReadingPreferencesScreen.kt | 4 +++- WordPress/src/main/res/values/strings.xml | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/views/compose/readingpreferences/ReadingPreferencesScreen.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/views/compose/readingpreferences/ReadingPreferencesScreen.kt index a820c248400d..f7ae9bbac88b 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/views/compose/readingpreferences/ReadingPreferencesScreen.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/views/compose/readingpreferences/ReadingPreferencesScreen.kt @@ -101,6 +101,7 @@ fun ReadingPreferencesScreen( actions = { ExperimentalBadge( contentColor = textColor, + fontFamily = fontFamily, modifier = Modifier.padding(end = Margin.Large.value), ) } @@ -241,6 +242,7 @@ fun ReadingPreferencesScreen( @Composable private fun ExperimentalBadge( contentColor: Color, + fontFamily: FontFamily, modifier: Modifier = Modifier, ) { Text( @@ -249,7 +251,7 @@ private fun ExperimentalBadge( style = TextStyle( color = contentColor.copy(alpha = 0.6f), fontWeight = FontWeight.Medium, - fontFamily = FontFamily.Monospace, + fontFamily = fontFamily, ), ) } diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml index c3201b709286..41803994841e 100644 --- a/WordPress/src/main/res/values/strings.xml +++ b/WordPress/src/main/res/values/strings.xml @@ -120,7 +120,7 @@ Me Everyone - [Experimental] + <Experimental> %d selected From c05ca1892fe356fbf1b7909da36af3b0e5f5a541 Mon Sep 17 00:00:00 2001 From: Automattic Release Bot Date: Mon, 8 Apr 2024 14:55:23 +0000 Subject: [PATCH 20/22] Freeze strings for translation --- fastlane/resources/values/strings.xml | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/fastlane/resources/values/strings.xml b/fastlane/resources/values/strings.xml index e93b2cd4f041..41803994841e 100644 --- a/fastlane/resources/values/strings.xml +++ b/fastlane/resources/values/strings.xml @@ -120,6 +120,8 @@ Me Everyone + <Experimental> + %d selected @@ -1705,7 +1707,10 @@ This is a new feature still in development. To help us improve it %s. send your feedback + + send your feedback + Color Scheme Default Soft Sepia @@ -1714,12 +1719,19 @@ h4x0r Candy + Font + Aa Serif Sans Mono - Aa - A + Font Size + Extra small + Small + Normal + Large + Extra large + A Post saved online From f2460d28747b75a3cd80c7736217edd7075751c8 Mon Sep 17 00:00:00 2001 From: Automattic Release Bot Date: Mon, 8 Apr 2024 14:57:43 +0000 Subject: [PATCH 21/22] Update translations --- WordPress/src/main/res/values-ar/strings.xml | 2 +- WordPress/src/main/res/values-az/strings.xml | 2 +- WordPress/src/main/res/values-bg/strings.xml | 2 +- WordPress/src/main/res/values-cs/strings.xml | 2 +- WordPress/src/main/res/values-cy/strings.xml | 2 +- WordPress/src/main/res/values-da/strings.xml | 2 +- WordPress/src/main/res/values-de/strings.xml | 27 +++++++++++++-- WordPress/src/main/res/values-el/strings.xml | 2 +- .../src/main/res/values-en-rCA/strings.xml | 2 +- .../src/main/res/values-en-rGB/strings.xml | 27 +++++++++++++-- .../src/main/res/values-es-rCL/strings.xml | 2 +- .../src/main/res/values-es-rCO/strings.xml | 27 +++++++++++++-- .../src/main/res/values-es-rMX/strings.xml | 2 +- .../src/main/res/values-es-rVE/strings.xml | 2 +- WordPress/src/main/res/values-es/strings.xml | 27 +++++++++++++-- WordPress/src/main/res/values-eu/strings.xml | 2 +- .../src/main/res/values-fr-rCA/strings.xml | 2 +- WordPress/src/main/res/values-fr/strings.xml | 2 +- WordPress/src/main/res/values-gd/strings.xml | 2 +- WordPress/src/main/res/values-gl/strings.xml | 2 +- WordPress/src/main/res/values-he/strings.xml | 2 +- WordPress/src/main/res/values-hi/strings.xml | 2 +- WordPress/src/main/res/values-hr/strings.xml | 2 +- WordPress/src/main/res/values-hu/strings.xml | 2 +- WordPress/src/main/res/values-id/strings.xml | 18 ++++++++-- WordPress/src/main/res/values-is/strings.xml | 2 +- WordPress/src/main/res/values-it/strings.xml | 2 +- WordPress/src/main/res/values-ja/strings.xml | 2 +- WordPress/src/main/res/values-kmr/strings.xml | 2 +- WordPress/src/main/res/values-ko/strings.xml | 2 +- WordPress/src/main/res/values-lv/strings.xml | 2 +- WordPress/src/main/res/values-mk/strings.xml | 2 +- WordPress/src/main/res/values-ms/strings.xml | 2 +- WordPress/src/main/res/values-nb/strings.xml | 2 +- WordPress/src/main/res/values-nl/strings.xml | 27 +++++++++++++-- WordPress/src/main/res/values-pl/strings.xml | 34 +++++++++++++++++-- .../src/main/res/values-pt-rBR/strings.xml | 2 +- WordPress/src/main/res/values-ro/strings.xml | 29 ++++++++++++++-- WordPress/src/main/res/values-ru/strings.xml | 31 +++++++++++------ WordPress/src/main/res/values-sk/strings.xml | 2 +- WordPress/src/main/res/values-sq/strings.xml | 26 ++++++++++++-- WordPress/src/main/res/values-sr/strings.xml | 2 +- WordPress/src/main/res/values-sv/strings.xml | 27 +++++++++++++-- WordPress/src/main/res/values-th/strings.xml | 2 +- WordPress/src/main/res/values-tr/strings.xml | 2 +- WordPress/src/main/res/values-uz/strings.xml | 2 +- WordPress/src/main/res/values-vi/strings.xml | 2 +- .../src/main/res/values-zh-rCN/strings.xml | 2 +- .../src/main/res/values-zh-rHK/strings.xml | 6 ++-- .../src/main/res/values-zh-rTW/strings.xml | 6 ++-- 50 files changed, 312 insertions(+), 74 deletions(-) diff --git a/WordPress/src/main/res/values-ar/strings.xml b/WordPress/src/main/res/values-ar/strings.xml index 7943e4e822e8..8bddc81f1539 100644 --- a/WordPress/src/main/res/values-ar/strings.xml +++ b/WordPress/src/main/res/values-ar/strings.xml @@ -2,7 +2,7 @@ diff --git a/WordPress/src/main/res/values-az/strings.xml b/WordPress/src/main/res/values-az/strings.xml index aac0dfa1a441..d6eef534fd0e 100644 --- a/WordPress/src/main/res/values-az/strings.xml +++ b/WordPress/src/main/res/values-az/strings.xml @@ -2,7 +2,7 @@ diff --git a/WordPress/src/main/res/values-bg/strings.xml b/WordPress/src/main/res/values-bg/strings.xml index edddde82924a..3665a6a4a0a1 100644 --- a/WordPress/src/main/res/values-bg/strings.xml +++ b/WordPress/src/main/res/values-bg/strings.xml @@ -2,7 +2,7 @@ diff --git a/WordPress/src/main/res/values-cs/strings.xml b/WordPress/src/main/res/values-cs/strings.xml index 90d7010f22cf..583dc2768bba 100644 --- a/WordPress/src/main/res/values-cs/strings.xml +++ b/WordPress/src/main/res/values-cs/strings.xml @@ -2,7 +2,7 @@ diff --git a/WordPress/src/main/res/values-cy/strings.xml b/WordPress/src/main/res/values-cy/strings.xml index 10ec1f5a17c0..9c9491dd254f 100644 --- a/WordPress/src/main/res/values-cy/strings.xml +++ b/WordPress/src/main/res/values-cy/strings.xml @@ -2,7 +2,7 @@ diff --git a/WordPress/src/main/res/values-da/strings.xml b/WordPress/src/main/res/values-da/strings.xml index ed621e118cc2..5db1c8830978 100644 --- a/WordPress/src/main/res/values-da/strings.xml +++ b/WordPress/src/main/res/values-da/strings.xml @@ -2,7 +2,7 @@ diff --git a/WordPress/src/main/res/values-de/strings.xml b/WordPress/src/main/res/values-de/strings.xml index 2d3dd16021fd..8f51ea84d9f3 100644 --- a/WordPress/src/main/res/values-de/strings.xml +++ b/WordPress/src/main/res/values-de/strings.xml @@ -1,11 +1,29 @@ + Ausgewählte Farbe löschen + Keine abonnierten Schlagwörter + Du folgst diesem Schlagwort bereits + Lesepräferenzen + Abonnierte Schlagwörter + Candy + h4x0r + OLED + Abendstimmung + Sepia + Soft + Standard + sende dein Feedback + Dies ist eine neue Funktion, die noch in der Entwicklung ist. Um uns zu helfen, sie zu verbessern %s. + Wähle deine Farben, Schriften und Größen. Hier kannst du eine Vorschau deiner Auswahl sehen und Beiträge mit deinen Stilen lesen, sobald du fertig bist. + Lesepräferenzen + Einem Schlagwort folgen + Lesen Du kannst den Text deines Beitrags kopieren, falls dein Inhalt betroffen ist. Kopiere die Fehlerdetails zur Fehlerbehebung und teile sie dem Support mit. Im Editor ist ein unerwarteter Fehler aufgetreten Hier tippen, um den Beitragstext zu kopieren @@ -76,9 +94,11 @@ Language: de Abonnements Entdecken Suche + Schlagwörter abonnieren Blogs, die du abonnieren kannst Vorgeschlagene Schlagwörter Suche nach einem Blog + Abonniere ein Schlagwort und du siehst hier die besten Beiträge dazu. Keine Schlagwörter Abonniere Blogs in Entdecken und die neuesten Beiträge werden hier angezeigt. Oder suche nach einem Blog, den du bereits magst. Keine Blog-Abonnements @@ -1467,6 +1487,7 @@ Language: de Layouts sind offline nicht verfügbar Mit Store-Anmeldedaten fortfahren Verbundene E-Mail-Adresse suchen + Folge mehreren Schlagwörtern, um deine Suche zu erweitern Keine aktuellen Beiträge Willkommen! Scannen @@ -1517,6 +1538,7 @@ Language: de Wähle aus der WordPress-Mediathek Zurück Erste Schritte + Folge Schlagwörtern, um neue Blogs zu entdecken Von Dieser Referrer kann nicht als Spam markiert werden Spam-Markierung aufheben @@ -3524,6 +3546,7 @@ Language: de Konnte diese Aktion nicht ausführen Zeitplan Aktualisieren + Gib eine URL oder ein Schlagwort ein, dem du folgen möchtest Wenn du dich üblicherweise ohne Probleme mit dieser Website verbinden kannst, könnte dieser Fehler bedeute, dass sich jemand als diese Website ausgibt und du daher nicht weitermachen solltest. Möchtest du dem Zertifikat trotzdem vertrauen? Ungültiges SSL Zertifikat Hilfe diff --git a/WordPress/src/main/res/values-el/strings.xml b/WordPress/src/main/res/values-el/strings.xml index 1d9690bda491..0d1f639b9429 100644 --- a/WordPress/src/main/res/values-el/strings.xml +++ b/WordPress/src/main/res/values-el/strings.xml @@ -2,7 +2,7 @@ diff --git a/WordPress/src/main/res/values-en-rCA/strings.xml b/WordPress/src/main/res/values-en-rCA/strings.xml index 25beb8ffcb8c..40494cb5072e 100644 --- a/WordPress/src/main/res/values-en-rCA/strings.xml +++ b/WordPress/src/main/res/values-en-rCA/strings.xml @@ -2,7 +2,7 @@ diff --git a/WordPress/src/main/res/values-en-rGB/strings.xml b/WordPress/src/main/res/values-en-rGB/strings.xml index 17c3b33db689..13b7fca0eec5 100644 --- a/WordPress/src/main/res/values-en-rGB/strings.xml +++ b/WordPress/src/main/res/values-en-rGB/strings.xml @@ -1,11 +1,29 @@ + Clear selected colour + No followed tags + You\'re already following this tag + Reading Preferences + Followed tags + Candy + h4x0r + OLED + Evening + Sepia + Soft + Default + send your feedback + This is a new feature still in development. To help us improve it %s. + Choose your colours, fonts, and sizes. Preview your selection here, and read posts with your styles once you’re done. + Reading Preferences + Follow a tag + Read You can copy your post text in case your content is impacted. Copy error details to debug and share with support. The editor has encountered an unexpected error Tap here to copy post text @@ -76,9 +94,11 @@ Language: en_GB Subscriptions Discover Search + Follow tags Blogs to which to subscribe Suggested tags Search for a blog + Follow a tag and you’ll be able to see the best posts from it here. No tags Subscribe to blogs in Discover and you’ll see their latest posts here. Or search for a blog that you like already. No blog subscriptions @@ -1467,6 +1487,7 @@ Language: en_GB Layouts not available while offline Continue with store credentials Find your connected email + Try following more tags to broaden the search No recent posts Welcome! Scan @@ -1517,6 +1538,7 @@ Language: en_GB Choose from WordPress Media Library Back Get Started + Follow tags to discover new blogs By This referrer can\'t be marked as spam Unmark as Spam @@ -3524,6 +3546,7 @@ Language: en_GB Unable to perform this action Schedule Update + Enter a URL or tag to follow If you usually connect to this site without problems, this error could mean that someone is trying to impersonate the site, and you shouldn\'t continue. Would you like to trust the certificate anyway? Invalid SSL certificate Help diff --git a/WordPress/src/main/res/values-es-rCL/strings.xml b/WordPress/src/main/res/values-es-rCL/strings.xml index ac9b1ecad95c..ceca6ab0657f 100644 --- a/WordPress/src/main/res/values-es-rCL/strings.xml +++ b/WordPress/src/main/res/values-es-rCL/strings.xml @@ -2,7 +2,7 @@ diff --git a/WordPress/src/main/res/values-es-rCO/strings.xml b/WordPress/src/main/res/values-es-rCO/strings.xml index 8f81748573ed..1e86812df6bf 100644 --- a/WordPress/src/main/res/values-es-rCO/strings.xml +++ b/WordPress/src/main/res/values-es-rCO/strings.xml @@ -1,11 +1,29 @@ + Vaciar el color seleccionado + No sigues etiquetas + Ya estás siguiendo esta etiqueta + Preferencias de lectura + Etiquetas seguidas + Caramelo + h4x0r + OLED + Noche + Sepia + Suave + Por defecto + envía tus comentarios + Esta es una nueva característica aún en desarrollo. Para ayudarnos a mejorarla %s. + Elige tus colores, fuentes y tamaños. Previsualiza aquí tu selección y lee entradas con tus estilos cuando hayas terminado. + Preferencias de lectura + Sigue una etiqueta + Leer Puedes copiar el texto de tu publicación en caso de que tu contenido se vea afectado. Copia los detalles del error para depurar y compartir con el soporte. El editor ha encontrado un error inesperado. Toca aquí para copiar el texto de la publicación @@ -76,9 +94,11 @@ Language: es_CO Suscripciones Descubrir Buscar + Seguir etiquetas Blogs a los que suscribirse Etiquetas recomendadas Buscar un blog + Sigue una etiqueta y podrás ve las mejores publicaciones asociadas a ella. Sin etiquetas Suscríbete a blogs en Descubrir y verás sus últimas publicaciones aquí. O busca un blog que ya te guste. No hay suscripciones al blog @@ -1467,6 +1487,7 @@ Language: es_CO Los diseños no están disponibles sin conexión Continuar con las credenciales de la tienda Encuentra tu correo electrónico conectado + Prueba a seguir más etiquetas para ampliar la búsqueda No hay entradas recientes ¡Bienvenido! Explorar @@ -1517,6 +1538,7 @@ Language: es_CO Elige desde la biblioteca de medios de WordPress Volver Primeros pasos + Sigue etiquetas para descubrir nuevos blogs por Este referido no puede ser marcado como spam Desmarcar como spam @@ -3524,6 +3546,7 @@ Language: es_CO No es posible realizar esta acción Programar Actualizar + Introduce una URL o etiqueta para seguir SI normalmente se conecta sin problemas a este sitio sin problemas, este error puede significar que alguien están intentando suplantar el sitio, por lo que no deberías continuar. ¿Quieres, de todas formas, confiar en el certificado? Certificado SSL no válido Ayuda diff --git a/WordPress/src/main/res/values-es-rMX/strings.xml b/WordPress/src/main/res/values-es-rMX/strings.xml index 08a445e241d8..c0304eb87147 100644 --- a/WordPress/src/main/res/values-es-rMX/strings.xml +++ b/WordPress/src/main/res/values-es-rMX/strings.xml @@ -2,7 +2,7 @@ diff --git a/WordPress/src/main/res/values-es-rVE/strings.xml b/WordPress/src/main/res/values-es-rVE/strings.xml index d121d96f0374..6404685f0e95 100644 --- a/WordPress/src/main/res/values-es-rVE/strings.xml +++ b/WordPress/src/main/res/values-es-rVE/strings.xml @@ -2,7 +2,7 @@ diff --git a/WordPress/src/main/res/values-es/strings.xml b/WordPress/src/main/res/values-es/strings.xml index 1279e2c2e9f0..a09b43b0fdbc 100644 --- a/WordPress/src/main/res/values-es/strings.xml +++ b/WordPress/src/main/res/values-es/strings.xml @@ -1,11 +1,29 @@ + Vaciar el color seleccionado + No sigues etiquetas + Ya estás siguiendo esta etiqueta + Preferencias de lectura + Etiquetas seguidas + Caramelo + h4x0r + OLED + Noche + Sepia + Suave + Por defecto + envía tus comentarios + Esta es una nueva característica aún en desarrollo. Para ayudarnos a mejorarla %s. + Elige tus colores, fuentes y tamaños. Previsualiza aquí tu selección y lee entradas con tus estilos cuando hayas terminado. + Preferencias de lectura + Sigue una etiqueta + Leer Puedes copiar el texto de tu entrada en caso de que tu contenido se vea afectado. Copia los detalles del error para depurarlo y compartirlo con el servicio de asistencia. El editor ha encontrado un error inesperado. Pulsa aquí para copiar el texto de la entrada. @@ -76,9 +94,11 @@ Language: es Suscripciones Descubrir Buscar + Seguir etiquetas Blogs a los que suscribirse Etiquetas recomendadas Buscar un blog + Sigue una etiqueta y podrás ve las mejores publicaciones asociadas a ella. Sin etiquetas Suscríbete a blogs en Descubrir y verás sus últimas publicaciones aquí. O busca un blog que ya te guste. No hay suscripciones al blog @@ -1467,6 +1487,7 @@ Language: es Los diseños no están disponibles sin conexión Continuar con las credenciales de la tienda Encuentra tu correo electrónico conectado + Prueba a seguir más etiquetas para ampliar la búsqueda No hay entradas recientes ¡Bienvenido! Explorar @@ -1517,6 +1538,7 @@ Language: es Elige desde la biblioteca de medios de WordPress Volver Primeros pasos + Sigue etiquetas para descubrir nuevos blogs por Este referido no puede ser marcado como spam Desmarcar como spam @@ -3524,6 +3546,7 @@ Language: es No es posible realizar esta acción Programar Actualizar + Introduce una URL o etiqueta para seguir SI normalmente se conecta sin problemas a este sitio sin problemas, este error puede significar que alguien están intentando suplantar el sitio, por lo que no deberías continuar. ¿Quieres, de todas formas, confiar en el certificado? Certificado SSL no válido Ayuda diff --git a/WordPress/src/main/res/values-eu/strings.xml b/WordPress/src/main/res/values-eu/strings.xml index bc88876f9de4..f40f76ace1e0 100644 --- a/WordPress/src/main/res/values-eu/strings.xml +++ b/WordPress/src/main/res/values-eu/strings.xml @@ -2,7 +2,7 @@ diff --git a/WordPress/src/main/res/values-fr-rCA/strings.xml b/WordPress/src/main/res/values-fr-rCA/strings.xml index 3192632d9e15..6134b40d2124 100644 --- a/WordPress/src/main/res/values-fr-rCA/strings.xml +++ b/WordPress/src/main/res/values-fr-rCA/strings.xml @@ -2,7 +2,7 @@ diff --git a/WordPress/src/main/res/values-fr/strings.xml b/WordPress/src/main/res/values-fr/strings.xml index 3192632d9e15..6134b40d2124 100644 --- a/WordPress/src/main/res/values-fr/strings.xml +++ b/WordPress/src/main/res/values-fr/strings.xml @@ -2,7 +2,7 @@ diff --git a/WordPress/src/main/res/values-gd/strings.xml b/WordPress/src/main/res/values-gd/strings.xml index cd487017291a..022517648097 100644 --- a/WordPress/src/main/res/values-gd/strings.xml +++ b/WordPress/src/main/res/values-gd/strings.xml @@ -2,7 +2,7 @@ diff --git a/WordPress/src/main/res/values-gl/strings.xml b/WordPress/src/main/res/values-gl/strings.xml index e10bb9b1eb96..b9e145010515 100644 --- a/WordPress/src/main/res/values-gl/strings.xml +++ b/WordPress/src/main/res/values-gl/strings.xml @@ -2,7 +2,7 @@ diff --git a/WordPress/src/main/res/values-he/strings.xml b/WordPress/src/main/res/values-he/strings.xml index cc6aaf9b022d..0677935861ec 100644 --- a/WordPress/src/main/res/values-he/strings.xml +++ b/WordPress/src/main/res/values-he/strings.xml @@ -2,7 +2,7 @@ diff --git a/WordPress/src/main/res/values-hi/strings.xml b/WordPress/src/main/res/values-hi/strings.xml index 6d43e40c17f5..04fbc6cbd28d 100644 --- a/WordPress/src/main/res/values-hi/strings.xml +++ b/WordPress/src/main/res/values-hi/strings.xml @@ -2,7 +2,7 @@ diff --git a/WordPress/src/main/res/values-hr/strings.xml b/WordPress/src/main/res/values-hr/strings.xml index cf5ca954dbcc..74405ace25c2 100644 --- a/WordPress/src/main/res/values-hr/strings.xml +++ b/WordPress/src/main/res/values-hr/strings.xml @@ -2,7 +2,7 @@ diff --git a/WordPress/src/main/res/values-hu/strings.xml b/WordPress/src/main/res/values-hu/strings.xml index 0bcb43921b00..9f52d53587dc 100644 --- a/WordPress/src/main/res/values-hu/strings.xml +++ b/WordPress/src/main/res/values-hu/strings.xml @@ -2,7 +2,7 @@ diff --git a/WordPress/src/main/res/values-id/strings.xml b/WordPress/src/main/res/values-id/strings.xml index 0a0494a74ce2..913e5b3bd789 100644 --- a/WordPress/src/main/res/values-id/strings.xml +++ b/WordPress/src/main/res/values-id/strings.xml @@ -1,8 +1,8 @@ @@ -31,12 +31,15 @@ Language: id Tidak dapat memuat media untuk dibagikan. Harap periksa perizinan aplikasi\n atau gunakan pustaka media aplikasi. Saat ini kami tidak dapat membuka pemantauan situs. Coba lagi nanti Log Server web + Log PHP + Metrik Pemantauan Situs Gunakan <b>Temukan</b> untuk menemukan situs dan tag. Coba pilih <b>Langganan</b> untuk melihat konten langganan dan mengelola langganan Anda. Buka langganan Blog langganan Anda belum mengeposkan apa pun akhir-akhir ini Langganan blog di Temukan atau cari blog yang sudah Anda sukai. Tidak ada blog rekomendasi + Belum ada pos dengan tag ini Tidak dapat memblokir blog ini Pos dari blog ini tidak akan ditampilkan lagi Tidak dapat berhenti berlangganan blog @@ -44,6 +47,7 @@ Language: id Tidak dapat berlangganan blog ini Anda sudah berlangganan blog ini Tidak dapat menampilkan blog ini + Pilih minat Anda 1 pelanggan %s pelanggan %,d Pelanggan @@ -51,10 +55,12 @@ Language: id Cari blog langganan Telah berlangganan Berlangganan + Blokir blog ini Sunting tag dan blog Telah berlangganan blog Ikuti tag Kelola Tag & Blog + Tag Blog Pembaca Telah berlangganan %d Tag @@ -99,6 +105,7 @@ Language: id Domain WordPress.com gratis Domain lain untuk %s Domain utama + %s Bloganuary telah hadir! Ayo mulai! Nyalakan prompt blogging @@ -110,6 +117,7 @@ Language: id Ikuti tantangan menulis sebulan penuh dari kami Bloganuary Selama bulan Januari, prompt blogging akan datang dari Bloganuary — tantangan kami untuk komunitas guna membentuk kebiasaan blogging di tahun yang baru. + Bloganuary segera hadir! Karenanya, kami menyarankan Anda untuk mengedit blok melalui browser web. Karenanya, kami menyarankan Anda untuk mengedit blok melalui editor web. Atau, Anda dapat meratakan konten dengan membatalkan pengelompokan blok. @@ -199,6 +207,8 @@ Language: id Konsep pos terbaru Anda. Buat konsep pos Kunjungan, Pengunjung, dan suka + Kartu bisa saja menampilkan konten berbeda, tergantung pada apa yang terjadi di situs Anda + Tambahkan atau sembunyikan Kartu Sesuaikan tab beranda Ketuk untuk mempersonalisasikan tab beranda Anda Personalisasikan tab beranda Anda @@ -3013,6 +3023,10 @@ Language: id Pos disimpan secara online Kualitas gambar. Semakin tinggi nilainya, semakin bagus kualitas gambarnya. Memungkinkan pengubahan ukuran dan kompresi gambar + Maksimum + Tinggi + Sedang + Rendah Diunggah Unggahan Gagal Dihapus diff --git a/WordPress/src/main/res/values-is/strings.xml b/WordPress/src/main/res/values-is/strings.xml index 831347859a2b..9ca2fcd87f01 100644 --- a/WordPress/src/main/res/values-is/strings.xml +++ b/WordPress/src/main/res/values-is/strings.xml @@ -2,7 +2,7 @@ diff --git a/WordPress/src/main/res/values-it/strings.xml b/WordPress/src/main/res/values-it/strings.xml index dbd44092f2fa..1f4531e8c20d 100644 --- a/WordPress/src/main/res/values-it/strings.xml +++ b/WordPress/src/main/res/values-it/strings.xml @@ -2,7 +2,7 @@ diff --git a/WordPress/src/main/res/values-ja/strings.xml b/WordPress/src/main/res/values-ja/strings.xml index ea965c832753..21c54d64e3d6 100644 --- a/WordPress/src/main/res/values-ja/strings.xml +++ b/WordPress/src/main/res/values-ja/strings.xml @@ -2,7 +2,7 @@ diff --git a/WordPress/src/main/res/values-kmr/strings.xml b/WordPress/src/main/res/values-kmr/strings.xml index b443498b72c8..b2e523940ba1 100644 --- a/WordPress/src/main/res/values-kmr/strings.xml +++ b/WordPress/src/main/res/values-kmr/strings.xml @@ -2,7 +2,7 @@ diff --git a/WordPress/src/main/res/values-ko/strings.xml b/WordPress/src/main/res/values-ko/strings.xml index 10bc25a0492a..4a25dc74ed4b 100644 --- a/WordPress/src/main/res/values-ko/strings.xml +++ b/WordPress/src/main/res/values-ko/strings.xml @@ -2,7 +2,7 @@ diff --git a/WordPress/src/main/res/values-lv/strings.xml b/WordPress/src/main/res/values-lv/strings.xml index 94255f9d2087..6c6ceb120f8d 100644 --- a/WordPress/src/main/res/values-lv/strings.xml +++ b/WordPress/src/main/res/values-lv/strings.xml @@ -2,7 +2,7 @@ diff --git a/WordPress/src/main/res/values-mk/strings.xml b/WordPress/src/main/res/values-mk/strings.xml index ae09c0085e15..e89b8b5621b8 100644 --- a/WordPress/src/main/res/values-mk/strings.xml +++ b/WordPress/src/main/res/values-mk/strings.xml @@ -2,7 +2,7 @@ diff --git a/WordPress/src/main/res/values-ms/strings.xml b/WordPress/src/main/res/values-ms/strings.xml index 884c9938f9ff..b1ef64f09274 100644 --- a/WordPress/src/main/res/values-ms/strings.xml +++ b/WordPress/src/main/res/values-ms/strings.xml @@ -2,7 +2,7 @@ diff --git a/WordPress/src/main/res/values-nb/strings.xml b/WordPress/src/main/res/values-nb/strings.xml index ce0159416b6f..374cb7ebb211 100644 --- a/WordPress/src/main/res/values-nb/strings.xml +++ b/WordPress/src/main/res/values-nb/strings.xml @@ -2,7 +2,7 @@ diff --git a/WordPress/src/main/res/values-nl/strings.xml b/WordPress/src/main/res/values-nl/strings.xml index 6c79949e82aa..2d338079a140 100644 --- a/WordPress/src/main/res/values-nl/strings.xml +++ b/WordPress/src/main/res/values-nl/strings.xml @@ -1,11 +1,29 @@ + Wis geselecteerde kleur + Geen gevolgde tags + Je volgt deze tag al + Leesvoorkeuren + Gevolgde tags + Candy + h4x0r + OLED + Avond + Sepia + Zacht + Standaard + verzend je feedback + Dit is een nieuwe functie die nog in ontwikkeling is. Om ons te helpen het te verbeteren %s. + Kies je kleuren, lettertypen en groottes. Bekijk hier een voorbeeld van je selectie en lees berichten met je stijlen zodra je klaar bent. + Leesvoorkeuren + Volg een tag + Lees Je kan je berichttekst kopiëren als de fout betrekking heeft op je content. Kopieer de foutdetails om te debuggen en te delen met de ondersteuning. De editor is op een onverwacht probleem gestuit Tik hier om de berichttekst te kopiëren @@ -76,9 +94,11 @@ Language: nl Abonnementen Ontdek Zoeken + Volg tags Blogs om je op te abonneren Voorgestelde tags Een blog zoeken + Volg een tag en je zult de beste berichten ervan hier kunnen zien. Geen tags Abonneer je op blogs in Ontdek en je ziet hun nieuwste berichten hier. Of zoek een blog die je al leuk vindt. Geen blog-abonnementen @@ -1467,6 +1487,7 @@ Language: nl Lay-outs zijn niet beschikbaar indien offline Ga verder met winkel-referenties Vind je verbonden e-mail + Probeer meer tags te volgen om de zoekopdracht te verbreden Geen recente berichten Welkom! Scan @@ -1517,6 +1538,7 @@ Language: nl Kies uit WordPress mediabibliotheek Terug Aan de slag + Volg tags om nieuwe blogs te ontdekken Door Deze verwijzer kan niet gemarkeerd worden als spam Markering als spam ongedaan maken @@ -3524,6 +3546,7 @@ Language: nl Deze actie kan niet uitgevoerd worden Inplannen Update + Voer een URL of tag in om te volgen Als je normaal gesproken zonder problemen verbinding maakt met deze site kan deze fout betekenen dat iemand zich probeert voor te doen als deze site. Ga niet verder als dat zo is. Wil je het certificaat toch vertrouwen? Ongeldig SSL-certificaat Help diff --git a/WordPress/src/main/res/values-pl/strings.xml b/WordPress/src/main/res/values-pl/strings.xml index 1c5020b8af28..5de986237b61 100644 --- a/WordPress/src/main/res/values-pl/strings.xml +++ b/WordPress/src/main/res/values-pl/strings.xml @@ -1,11 +1,34 @@ + Ruch + Rozmiar liter, %1$s + Plik nie jest obsługiwany jako plik mediów. + Nie można odtworzyć pliku mediów. Spróbuj ponownie później + Wyszukaj domenę + Nigdy nie wygasa + Pozostałe domeny dla %s + %s + Uaktualnij do planu + Uzyskaj bezpłatną roczną rejestrację domeny lub transfer z dowolnym płatnym planem rocznym. + Twoja darmowa subdomena na WordPress.com + Domena główna + Transferuj domenę + Błąd + %s / rocznie + Edytowano + Zakładki + Kup domenę + Wybierz plan + Zapisz + Zapisano + Może polubisz + Coś poszło nie tak. Proszę spróbować później. ZAMKNIJ Wstaw blok filmu Wstaw blok obrazka @@ -59,6 +82,7 @@ Language: pl Konto użytkownika nie może zostać natychmiast zamknięte, ponieważ ma aktywne zakupy. Skontaktuj się z naszym zespołem pomocy technicznej, aby dokończyć jego usuwanie. Brak uprawnień do zamknięcia konta. Potwierdź zamknięcie konta… + Nie możesz automatycznie zamknąć konta! Aby potwierdzić, wprowadź ponownie swoją nazwę użytkownika przed zamknięciem konta. Zamknij konto Dowiedz się więcej @@ -670,6 +694,7 @@ Language: pl Opcjonalne: wprowadź własną wiadomość, która zostanie wysłana wraz z zaproszeniem. Podpis pliku audio. %s Podpis pliku audio. Pusty + Dodaj plik audio Dowiedz się więcej o rolach Znaleziono Naprawiono @@ -1055,6 +1080,7 @@ Language: pl Notka dotycząca prywatności dla użytkowników Kaliforni Status i widoczność Aktualizuj teraz + %1$s · Otwórz menu działań na blokach Przenieś na górę Wstaw wzmiankę @@ -1168,6 +1194,7 @@ Language: pl Strona zapisana online Dokonałeś w ostatnim czasie zmian na tej stronie, ale nie zostały zapisane. Wybierz którą wersję wczytać:\n Wybierz blog dla skrótu QuickPress + Wiadomość ostrzeżenia Pokaż treść wpisu Odnośnik do Pokaż tylko zajawkę @@ -1306,6 +1333,7 @@ Language: pl Dodaj opis Dodaj tekst alternatywny Wystąpił nieznany błąd. Proszę spróbować ponownie. + Dodaj film Stuknij przycisk Dodaj do Zapisanych Wpisów aby zapisać wpis na swojej liście. \"Lista ma %1$d elementów.\" Powiadomienia @@ -2400,6 +2428,8 @@ Language: pl Jakość obrazków. Wyższa wartość oznacza lepszą jakość. Uaktywnij aby zmienić rozmiar i skompresować obrazki Wysłano + Maksymalnie + Średnio Usunięto Usuwanie Przesyłanie diff --git a/WordPress/src/main/res/values-pt-rBR/strings.xml b/WordPress/src/main/res/values-pt-rBR/strings.xml index f60567dc1312..1bb932d3a525 100644 --- a/WordPress/src/main/res/values-pt-rBR/strings.xml +++ b/WordPress/src/main/res/values-pt-rBR/strings.xml @@ -2,7 +2,7 @@ diff --git a/WordPress/src/main/res/values-ro/strings.xml b/WordPress/src/main/res/values-ro/strings.xml index b5878fec688d..dccbaf351497 100644 --- a/WordPress/src/main/res/values-ro/strings.xml +++ b/WordPress/src/main/res/values-ro/strings.xml @@ -1,11 +1,29 @@ + Șterge culoarea selectată + Nicio etichetă urmărită + Deja urmărești această etichetă + Preferințe pentru citire + Etichete urmărite + Candy + h4x0r + OLED + Seara + Sepia + Delicat + Implicită + trimite impresiile + Aceasta este o funcționalitate nouă, încă în dezvoltare. Pentru a ne ajuta să o îmbunătățim %s. + Alegi culorile, fonturile și dimensiunile. După ce ai terminat, previzualizezi aici ce ai selectat și citești articolele în stilul tău. + Preferințe pentru citire + Urmărește o etichetă + Citește Dacă conținutul tău este afectat, poți să copiezi textul articolului. Copiază detaliile despre erori pentru a depana și partaja cu suportul. Editorul a găsit o eroare neașteptată Atinge aici pentru a copia textul articolului @@ -76,9 +94,11 @@ Language: ro Abonamente Descoperă Caută + Urmărește etichetele Bloguri la care să te abonezi Etichete sugerate Caută un blog + Urmărește o etichetă și vei putea să vezi aici cele mai bune articole cu această etichetă. Nicio etichetă Abonează-te la bloguri în Descoperă și vei vedea aici ultimele articole publicate pe ele. Sau caută un blog care ți-a plăcut. Niciun abonament la bloguri @@ -1467,6 +1487,7 @@ Language: ro Aranjamentele nu sunt disponibile când ești offline Continuă cu datele de conectare la magazin Găsește emailul conectat + Încearcă să urmărești mai multe etichete pentru a extinde căutarea Niciun articol recent Bine ai venit! Scanează @@ -1517,6 +1538,7 @@ Language: ro Alege din biblioteca Media din WordPress Înapoi Începe + Urmărește etichetele ca să descoperi bloguri noi De Acest referent nu poate fi marcat ca spam Anulează marcarea ca spam @@ -3524,6 +3546,7 @@ Language: ro Nu pot face acestă acțiune Programează Actualizează + Introdu un URL sau o etichetă pentru urmărire Dacă în mod uzual te conectezi fără probleme la acest site, această eroare poate să însemne că cineva încearcă să se substituie site-ului și n-ar trebui să mai continui. Preferi să te încrezi în certificat oricum? Certificat SSL invalid Ajutor @@ -3683,7 +3706,7 @@ Language: ro Numele scurtăturii nu poate fi gol Private Titlu - Separă etichetele cu virgulă + Separă etichetele cu virgule Categorii Cardul SD e necesar Media diff --git a/WordPress/src/main/res/values-ru/strings.xml b/WordPress/src/main/res/values-ru/strings.xml index 386a68357642..51caad063f8d 100644 --- a/WordPress/src/main/res/values-ru/strings.xml +++ b/WordPress/src/main/res/values-ru/strings.xml @@ -1,11 +1,17 @@ + Очистить выбранный цвет + Нет подписок на метки + Вы уже подписаны на эту метку + OLED + Подписаться на метку + Читать Вы можете копировать текст своей записи на случай, если ваш контент окажется повреждён. Скопируйте данные об ошибке, чтобы сообщить их инженерам поддержки и устранить неполадку. Произошла непредвиденная ошибка редактора. Нажмите здесь, чтобы скопировать текст записи @@ -56,16 +62,16 @@ Language: ru Подписка оформлена Подписаться Заблокировать этот блог - Редактировать теги и блоги + Редактировать метки и блоги Подписки на блоги - Подписаться на теги + Подписаться на метки Управление тегами и блогами Метка Блог в разделе «Чтиво» Подписка оформлена - Теги: %d - 1 тег - Теги: 0 + Метки: %d + 1 метка + Нет меток Блоги: %d 1 блог Блоги: 0 @@ -76,15 +82,17 @@ Language: ru Подписки Раздел «Поиск» Поиск + Подписаться на метки Блоги, на которые можно подписаться - Рекомендуемые теги + Рекомендуемые метки Искать блог - Нет тегов + Подпишитесь на метку, и лучшие записи с ней станут отображаться здесь. + Нет меток Подписывайтесь на блоги в разделе «Поиск», и последние записи из них будут отображаться здесь. Или найдите блог, который вам уже понравился. Нет подписок на блоги Подписаться на блог Просмотреть последние записи из блогов, на которые вы подписаны - Фильтровать по тегу + Фильтр по метке Фильтровать по блогу По году По месяцу @@ -1467,6 +1475,7 @@ Language: ru Макеты недоступны при отсутствии подключения к сети Продолжить с учетными данными магазина Узнать адрес привязанной эл. почты + Для расширения поиска попробуйте подписаться на больше меток Нет свежих записей Добро пожаловать! Сканировать @@ -1517,6 +1526,7 @@ Language: ru Выберите из медиатеки WordPress Назад Начните + Подписывайтесь на метки для того, чтобы найти новые блоги От автора Этот реферер не может быть отмечен как спам Убрать отметку спам @@ -3524,6 +3534,7 @@ Language: ru Не удалось совершить это действие Запланировать Обновить + Введите URL или метку для подписки Если вы обычно заходите на этот сайт без проблем, эта ошибка может означать, что кто-то пытается подделать сайт и вам не стоит сюда заходить. Хотите ли вы доверять ssl сертификату? Недействительный сертификат SSL Помощь diff --git a/WordPress/src/main/res/values-sk/strings.xml b/WordPress/src/main/res/values-sk/strings.xml index a7fe94d9487b..628363ebd203 100644 --- a/WordPress/src/main/res/values-sk/strings.xml +++ b/WordPress/src/main/res/values-sk/strings.xml @@ -2,7 +2,7 @@ diff --git a/WordPress/src/main/res/values-sq/strings.xml b/WordPress/src/main/res/values-sq/strings.xml index 622fe4955017..37beaeb489d8 100644 --- a/WordPress/src/main/res/values-sq/strings.xml +++ b/WordPress/src/main/res/values-sq/strings.xml @@ -1,11 +1,28 @@ + Hiqe ngjyrën e përzgjedhur + Pa etiketa të ndjekura + E ndiqni tashmë këtë etiketë. + Parapëlqime Leximi + Etiketa të ndjekura + h4x0r + OLED + Mbrëmje + Sepia + Butë + Parazgjedhje + jepni përshtypjet tuaja + Kjo është veçori e re ende në zhvillim. Që të na ndihmoni ta përmirësojmë, %s. + Zgjidhni ngjyra, shkronja dhe madhësi tuajat. Bëni këtu paraparje të përzgjedhjes tuaj dhe lexoni postime me stilet tuaja, pasi të keni mbaruar. + Parapëlqime Leximi + Ndiqni një etiketë + Lexoni Mund ta kopjoni tekstin e postimit tuaj, në rast se preket lënda juaj. Kopjoni hollësi gabimi, për diagnostikim dhe për t’ia dhënë asistencës. Përpunuesi hasi një gabim të papritur Prekeni këtu, që të kopjohet tekstin e postimit @@ -76,9 +93,11 @@ Language: sq_AL Pajtime Zbuloni Kërko + Ndiqni etiketa Blogje ku të pajtoheni Etiketa të sugjeruara Kërkoni për një blog + Ndiqni një etiketë dhe do të jeni në gjendje të shihni këtu postimet më të mira. Pa etiketa Pajtohuni në blogje te Zbuloni dhe do të shihni këtu postimet e tyre më të reja. Ose kërkoni për një blog që ju pëlqen tashmë. S’ka pajtime në blog @@ -1459,6 +1478,7 @@ Language: sq_AL S’mund të kihen skema, teksa jeni jashtë linje Vazhdo me kredenciale shitoreje Gjeni email-in tuaj të lidhur + Provoni të ndiqni më tepër etiketa që të zgjerohet kërkimi Pa postime së fundi Mirë se vini! Skanoje @@ -1509,6 +1529,7 @@ Language: sq_AL Zgjidhni prej Mediatekës WordPress Mbrapsht Fillojani + Ndiqni etiketa, që të zbuloni blogje të rinj Nga Këtij referuesi s’mund t’i vihet shenjë si i padëshiruar Hiqja Shenjën Si i Padëshiruar @@ -3516,6 +3537,7 @@ Language: sq_AL I pazoti të kryejë këtë veprim Planifikoje Përditësoje + Jepni një URL, ose etiketë, që të ndiqet Nëse zakonisht lidheni te ky sajt pa probleme, ky gabim mund të thotë që dikush po provon të hiqet si ky sajt, dhe s’duhet të vazhdoni. Doni të besohet dëshmia, sido qoftë? Dëshmi SSL e pavlefshme Ndihmë diff --git a/WordPress/src/main/res/values-sr/strings.xml b/WordPress/src/main/res/values-sr/strings.xml index cd7b094b2709..7f582d924152 100644 --- a/WordPress/src/main/res/values-sr/strings.xml +++ b/WordPress/src/main/res/values-sr/strings.xml @@ -2,7 +2,7 @@ diff --git a/WordPress/src/main/res/values-sv/strings.xml b/WordPress/src/main/res/values-sv/strings.xml index 22ccdca63ebb..99146494e6f4 100644 --- a/WordPress/src/main/res/values-sv/strings.xml +++ b/WordPress/src/main/res/values-sv/strings.xml @@ -1,11 +1,29 @@ + Rensa vald färg + Inga följda etiketter + Du följer redan denna etikett + Läspreferenser + Följda taggar + Godis + h4x0r + OLED + Kväll + Sepia + Mjuk + Standard + skicka din feedback + Detta är en ny funktion som fortfarande är under utveckling. För att hjälpa oss att förbättra det %s. + Välj dina färger, typsnitt och storlekar. Förhandsgranska ditt val här och läs inlägg med dina stilar när du är klar. + Läspreferenser + Följ en etikett + Läst Du kan kopiera din inläggstext om ditt innehåll påverkas. Kopiera felinformation så att du kan felsöka och dela med dig till supporten. Redigeraren har stött på ett oväntat fel Klicka här för att kopiera inläggstext @@ -76,9 +94,11 @@ Language: sv_SE Prenumerationer Upptäck Sök + Prenumerera på etiketter Bloggar att prenumerera på Föreslagna etiketter Sök efter en blogg + Prenumerera på en etikett så kommer du att se dess bästa inlägg här. Inga etiketter Prenumerera på bloggar i Upptäck så kommer du att se deras senaste inlägg här. Eller så kan du söka efter en blogg som du redan gillar. Inga bloggprenumerationer @@ -1467,6 +1487,7 @@ Language: sv_SE Layouter är inte tillgängliga när du saknar internetförbindelse Fortsätt med butiksautentiseringsuppgifter Hitta din anslutna e-postadress + Försök att följa fler etiketter för att söka bredare Inga nya inlägg Välkommen! Skanna @@ -1517,6 +1538,7 @@ Language: sv_SE Välj ur mediabiblioteket i WordPress Tillbaka Kom igång + Följ etiketter för att upptäcka nya bloggar Av Denna hänvisande webbplats går inte att avmarkera som skräp Ta bort markering som skräppost @@ -3524,6 +3546,7 @@ Language: sv_SE Kunde inte genomföra denna åtgärd Tidinställ Uppdatera + Ange en URL eller etikett du vill följa Om du vanligtvis kan nå denna webbplats utan problem kan felet betyda att någon försöker efterlikna webbplatsen och du borde inte fortsätta. Vill du lita på certifikatet ändå? Ogiltigt SSL-ceritfikat Hjälp diff --git a/WordPress/src/main/res/values-th/strings.xml b/WordPress/src/main/res/values-th/strings.xml index a557dcea13e5..40f346cab922 100644 --- a/WordPress/src/main/res/values-th/strings.xml +++ b/WordPress/src/main/res/values-th/strings.xml @@ -2,7 +2,7 @@ diff --git a/WordPress/src/main/res/values-tr/strings.xml b/WordPress/src/main/res/values-tr/strings.xml index eb1e9e2e4e5c..73b2613fa954 100644 --- a/WordPress/src/main/res/values-tr/strings.xml +++ b/WordPress/src/main/res/values-tr/strings.xml @@ -2,7 +2,7 @@ diff --git a/WordPress/src/main/res/values-uz/strings.xml b/WordPress/src/main/res/values-uz/strings.xml index a605e9d8fbd9..e432e4ff17fc 100644 --- a/WordPress/src/main/res/values-uz/strings.xml +++ b/WordPress/src/main/res/values-uz/strings.xml @@ -2,7 +2,7 @@ diff --git a/WordPress/src/main/res/values-vi/strings.xml b/WordPress/src/main/res/values-vi/strings.xml index b5e17f932eca..f2c3021c1300 100644 --- a/WordPress/src/main/res/values-vi/strings.xml +++ b/WordPress/src/main/res/values-vi/strings.xml @@ -2,7 +2,7 @@ diff --git a/WordPress/src/main/res/values-zh-rCN/strings.xml b/WordPress/src/main/res/values-zh-rCN/strings.xml index dec49980adbc..9b53490b293f 100644 --- a/WordPress/src/main/res/values-zh-rCN/strings.xml +++ b/WordPress/src/main/res/values-zh-rCN/strings.xml @@ -2,7 +2,7 @@ diff --git a/WordPress/src/main/res/values-zh-rHK/strings.xml b/WordPress/src/main/res/values-zh-rHK/strings.xml index ef46e496fb53..b6c6b8603870 100644 --- a/WordPress/src/main/res/values-zh-rHK/strings.xml +++ b/WordPress/src/main/res/values-zh-rHK/strings.xml @@ -1,8 +1,8 @@ @@ -1648,7 +1648,7 @@ Language: zh_TW 根據《加州消費者隱私保護法》(以下稱「CCPA」) 規定,我們必須提供加州使用者一些額外資訊,說明我們收集和分享的個人資訊種類、從哪裡取得這些資訊,以及這些資訊的使用方式及用途。 加州使用者的隱私權聲明 狀態及可見度 - 馬上更新 + 立即更新 %1$s · 開啟區塊操作選單 移至頂端 diff --git a/WordPress/src/main/res/values-zh-rTW/strings.xml b/WordPress/src/main/res/values-zh-rTW/strings.xml index ef46e496fb53..b6c6b8603870 100644 --- a/WordPress/src/main/res/values-zh-rTW/strings.xml +++ b/WordPress/src/main/res/values-zh-rTW/strings.xml @@ -1,8 +1,8 @@ @@ -1648,7 +1648,7 @@ Language: zh_TW 根據《加州消費者隱私保護法》(以下稱「CCPA」) 規定,我們必須提供加州使用者一些額外資訊,說明我們收集和分享的個人資訊種類、從哪裡取得這些資訊,以及這些資訊的使用方式及用途。 加州使用者的隱私權聲明 狀態及可見度 - 馬上更新 + 立即更新 %1$s · 開啟區塊操作選單 移至頂端 From 469cd3a6c6d8ce0cdd1e4635b2594684313fa0cc Mon Sep 17 00:00:00 2001 From: Automattic Release Bot Date: Mon, 8 Apr 2024 14:57:53 +0000 Subject: [PATCH 22/22] Bump version number --- version.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.properties b/version.properties index a79cd5cc3d18..c370818e50bf 100644 --- a/version.properties +++ b/version.properties @@ -1,2 +1,2 @@ -versionName=24.6-rc-1 -versionCode=1420 \ No newline at end of file +versionName=24.6-rc-2 +versionCode=1421 \ No newline at end of file