As part of my previous work on #17215 and #17960 I keep stumbling on the fact that on WPAndroid, instead of using the AndroidX Preference library for anything settings related, it is still using the legacy and long deprecated Android Preference library.
⚠️ As per the Settings documentations, starting with Android 10 (API 29), the legacy android.preference library, referred to as the platform android.preference library, is deprecated. For consistent behavior across all devices it is recommended to use the androidx.preference library.
Also, in addition to the above, the WPAndroid preference configuration and usage just that bit more complicated. The complication comes from the fact that WPAndroid used both android.preference and androidx.preference (see #17215).
androidx.preference is used only for PreferenceManager related work, while
android.preference is used for everything else.
The above makes that bit more complicated to update the AndroidX Preference library to newer versions, and that is, because as one would need to know all the above before deciding towards the updating strategy.
For example, while working on #17960 I was tempted to also try and migrated at least one screen from android.preference and into androidx.preference. I tried with the seemingly simple AccountSettingsFragment.kt class, which is related to the very simple Account Settings screen, but without success, not at all. After a while, I realized that everything is interconnected in such a degree that it is impossible to complete this migration without affecting any other screen (more on that below).
Technical Details
While trying to migrate AccountSettingsFragment.kt class to androidx.preference, during my work on #17960 I ended up mapping down every usage of android.preference and anything that is depending on it, via extending those classes, or using those via composition.
Below is a summary of that, you can expand and see the details per class, as well as how to test each class:
1. AccountSettingsFragment.kt
Res: account_settings.xml
Extends from: PreferenceFragmentLifeCycleOwner.kt
Uses:
EditTextPreferenceWithValidation.java, which extends from SummaryEditTextPreference.java
DetailListPreference.java
To test:
- Go to
Me screen.
- Click on the
Account Settings button.
- Verify that the
Account Settings screen is displayed.
- Click on each of the settings within the
Account Settings screen and verify that every setting works as expected.
2. AppSettingsFragment.java
Res: app_settings.xml
Uses:
WPActivityUtils.java, which uses add/removeToolbarFromDialog(...)
WPSwitchPreference.java, which uses SummaryEditTextPreference.java
DetailListPreference.java
LearnMorePreference.java
WPPreference.java, which uses DetailListPreference.java`
WPPrefUtils.java
To test:
- Go to
Me screen.
- Click on the
App Settings button.
- Verify that the
App Settings screen is displayed.
- Click on each of the settings within the
App Settings screen and verify that every setting works as expected, including the inner settings like the Privacy Settings and Debug Settings screens.
3. SiteSettingsFragment.java
Res: site_settings.xml
Uses:
WPActivityUtils.java, which uses add/removeToolbarFromDialog(...)
WPSwitchPreference.java, which uses SummaryEditTextPreference.java
EditTextPreferenceWithValidation.java, which extends from SummaryEditTextPreference.java
SummaryEditTextPreference.java
DetailListPreference.java
LearnMorePreference.java
WPPreference.java, which uses DetailListPreference.java`
WPStartOverPreference.java, which extends from WPPreference.java
WPPrefUtils.java
To test:
- While on the
My Site/MENU tab.
- Click on the
Site Settings button.
- Verify that the
Site Settings screen is displayed.
- Click on each of the settings within the
Site Settings screen and verify that every setting works as expected.
4. JetpackSecuritySettingsFragment.java
Res: jetpack_settings.xml
Uses:
WPSwitchPreference.java, which uses SummaryEditTextPreference.java
LearnMorePreference.java
WPPrefUtils.java
To test:
- Prerequisite: You must have a Jetpack connected site, which displays this setting.
- While on the
My Site/MENU tab.
- Click on the
Jetpack Settings button.
- Verify that the
Security setting screen is displayed.
- Click on each of the settings within the
Security settings screen and verify that every setting works as expected.
5. NotificationSettingsFragment.java
Res: notifications_settings.xml
Uses:
NotificationsSettingsDialogPreference.java
WPActivityUtils.java, which uses add/removeToolbarFromDialog(...)
WPSwitchPreference.java, which uses SummaryEditTextPreference.java
To test:
- While on the
Notifications tab.
- Click on the
Gear setting button (top-right).
- Verify that the
Notification Settings screen is displayed.
- Click on each of the settings within the
Notification Settings settings screen and verify that every setting works as expected.
Also, consider the below usages of android.preference in non-setting screen related part of WPAndroid's codebase:
1. EditPostActivity.java
Uses:
EditTextPreferenceWithValidation.java, which extends from SummaryEditTextPreference.java
To test:
- Go to
Post screen.
- Edit a new post, which uses
PreferenceManager to setDefaultValues(...) for Account Settings, add a few of the main blocks and verify that everything is workings as expected.
2. MySitesPage.java (UI Test)
To test:
- Run the
StatsTests UI test suite, which uses the MySitesPage.java class, and verify that all tests pass.
From the above you will notice the below:
- There are 5 settings screens overall:
Account Settings, which corresponds to AccountSettingsFragment.kt and account_settings.xml
App Settings, which corresponds to AppSettingsFragment.java and app_settings.xml
Site Settings, which corresponds to SiteSettingsFragment.java and site_settings.xml
Jetpack Security Settings, which corresponds to JetpackSecuritySettingsFragment.java and jetpack_settings.xml
Notifications Settings, which corresponds to NotificationsSettingsFragment.java and notifications_settings.xml
- There are 8 custom preference classes:
WPPreference.java, which uses DetailListPreference.java`
WPStartOverPreference.java, which extends from WPPreference.java and only used by SiteSettingsFragment.java
WPSwitchPreference, which uses SummaryEditTextPreference.java
SummaryEditTextPreference
EditTextPreferenceWithValidation, which extends from SummaryEditTextPreference
DetailListPreference
LearnMorePreference
NotificationsSettingsDialogPreference, which is only used by NotificationSettingsFragment.java
- There are 3 extra classes related to preferences, utils or otherwise:
WPPrefUtils, which uses add/removeToolbarFromDialog(...)
WPActivityUtils
PreferenceFragmentLifeCycleOwner, which is extended only by AccountSettingsFragment.kt
Recommendation & Suggested Strategy
From the technical details above you will notice how interconnected everything is.
As such, my recommendation is instead of migrating all 5 settings screens, and thus, forcing us to do that change in one go, most probably even in one PR (as I am not seeing another alternative), we could create a project which will rewrite each of those screens instead. This will make this change more manageable, enable the creation of multiple PRs, each tested in isolation, and which, will target trunk directly, that is, without the need for a parent intermediate feature branch.
Per the above, my suggested strategy would be:
- To create 5 individual PRs, per the 5 settings screens above.
- For each PR, create a completely new screen with
androidx.preference, along with creating any custom preference class that this screen might required to become fully operational.
In more detail, I would have followed the below PR chain strategy:
- First, start with a new
Account Settings screen, along with creating 3 new custom preference classes (SummaryEditTextPreference.kt, EditTextPreferenceWithValidation.kt and DetailListPreference.kt).
- Then, continue with a new
Jetpack Security Settings screen, along with creating 2 new custom preference classes (WPSwitchPreference.kt and LearnMorePreference.kt).
- Then, continue with a new
Notifications Settings screen, along with creating 1 new custom preference class (NotificationsSettingsDialogPreference.kt).
- Then, continue with a new
App Settings screen, along with creating 1 new custom preference class (WPPreference.kt).
- Then, end with a new
Site Settings screen, along with creating 1 new custom preference class (WPStartOverPreference).
- Finally, if not already done by all the above, remove any remaining usage of
android.preference from anywhere else (ie. PreferenceFragmentLifeCycleOwner, WPPrefUtils, WPActivityUtils, EditPostActivity, MySitesPage, etc)
Let's discuss, let me know your thoughts on all the above! 🙇
As part of my previous work on #17215 and #17960 I keep stumbling on the fact that on WPAndroid, instead of using the AndroidX Preference library for anything settings related, it is still using the legacy and long deprecated Android Preference library.
API 29), the legacyandroid.preferencelibrary, referred to as the platformandroid.preferencelibrary, is deprecated. For consistent behavior across all devices it is recommended to use theandroidx.preferencelibrary.Also, in addition to the above, the WPAndroid preference configuration and usage just that bit more complicated. The complication comes from the fact that WPAndroid used both
android.preferenceandandroidx.preference(see #17215).androidx.preferenceis used only forPreferenceManagerrelated work, whileandroid.preferenceis used for everything else.The above makes that bit more complicated to update the AndroidX Preference library to newer versions, and that is, because as one would need to know all the above before deciding towards the updating strategy.
For example, while working on #17960 I was tempted to also try and migrated at least one screen from
android.preferenceand intoandroidx.preference. I tried with the seemingly simpleAccountSettingsFragment.ktclass, which is related to the very simpleAccount Settingsscreen, but without success, not at all. After a while, I realized that everything is interconnected in such a degree that it is impossible to complete this migration without affecting any other screen (more on that below).Technical Details
While trying to migrate
AccountSettingsFragment.ktclass toandroidx.preference, during my work on #17960 I ended up mapping down every usage ofandroid.preferenceand anything that is depending on it, via extending those classes, or using those via composition.Below is a summary of that, you can expand and see the details per class, as well as how to test each class:
1. AccountSettingsFragment.kt
Res:
account_settings.xmlExtends from:
PreferenceFragmentLifeCycleOwner.ktUses:
EditTextPreferenceWithValidation.java, which extends fromSummaryEditTextPreference.javaDetailListPreference.javaTo test:
Mescreen.Account Settingsbutton.Account Settingsscreen is displayed.Account Settingsscreen and verify that every setting works as expected.2. AppSettingsFragment.java
Res:
app_settings.xmlUses:
WPActivityUtils.java, which usesadd/removeToolbarFromDialog(...)WPSwitchPreference.java, which usesSummaryEditTextPreference.javaDetailListPreference.javaLearnMorePreference.javaWPPreference.java, which usesDetailListPreference.java`WPPrefUtils.javaTo test:
Mescreen.App Settingsbutton.App Settingsscreen is displayed.App Settingsscreen and verify that every setting works as expected, including the inner settings like thePrivacy SettingsandDebug Settingsscreens.3. SiteSettingsFragment.java
Res:
site_settings.xmlUses:
WPActivityUtils.java, which usesadd/removeToolbarFromDialog(...)WPSwitchPreference.java, which usesSummaryEditTextPreference.javaEditTextPreferenceWithValidation.java, which extends fromSummaryEditTextPreference.javaSummaryEditTextPreference.javaDetailListPreference.javaLearnMorePreference.javaWPPreference.java, which usesDetailListPreference.java`WPStartOverPreference.java, which extends from WPPreference.javaWPPrefUtils.javaTo test:
My Site/MENUtab.Site Settingsbutton.Site Settingsscreen is displayed.Site Settingsscreen and verify that every setting works as expected.4. JetpackSecuritySettingsFragment.java
Res:
jetpack_settings.xmlUses:
WPSwitchPreference.java, which usesSummaryEditTextPreference.javaLearnMorePreference.javaWPPrefUtils.javaTo test:
My Site/MENUtab.Jetpack Settingsbutton.Securitysetting screen is displayed.Securitysettings screen and verify that every setting works as expected.5. NotificationSettingsFragment.java
Res:
notifications_settings.xmlUses:
NotificationsSettingsDialogPreference.javaWPActivityUtils.java, which usesadd/removeToolbarFromDialog(...)WPSwitchPreference.java, which usesSummaryEditTextPreference.javaTo test:
Notificationstab.Gearsetting button (top-right).Notification Settingsscreen is displayed.Notification Settingssettings screen and verify that every setting works as expected.Also, consider the below usages of
android.preferencein non-setting screen related part of WPAndroid's codebase:1. EditPostActivity.java
Uses:
EditTextPreferenceWithValidation.java, which extends fromSummaryEditTextPreference.javaTo test:
Postscreen.PreferenceManagertosetDefaultValues(...)forAccount Settings, add a few of the main blocks and verify that everything is workings as expected.2. MySitesPage.java (UI Test)
To test:
StatsTestsUI test suite, which uses theMySitesPage.javaclass, and verify that all tests pass.From the above you will notice the below:
Account Settings, which corresponds toAccountSettingsFragment.ktandaccount_settings.xmlApp Settings, which corresponds toAppSettingsFragment.javaandapp_settings.xmlSite Settings, which corresponds toSiteSettingsFragment.javaandsite_settings.xmlJetpack Security Settings, which corresponds toJetpackSecuritySettingsFragment.javaandjetpack_settings.xmlNotifications Settings, which corresponds toNotificationsSettingsFragment.javaandnotifications_settings.xmlWPPreference.java, which usesDetailListPreference.java`WPStartOverPreference.java, which extends from WPPreference.javaand only used bySiteSettingsFragment.javaWPSwitchPreference, which usesSummaryEditTextPreference.javaSummaryEditTextPreferenceEditTextPreferenceWithValidation, which extends fromSummaryEditTextPreferenceDetailListPreferenceLearnMorePreferenceNotificationsSettingsDialogPreference, which is only used byNotificationSettingsFragment.javaWPPrefUtils, which usesadd/removeToolbarFromDialog(...)WPActivityUtilsPreferenceFragmentLifeCycleOwner, which is extended only byAccountSettingsFragment.ktRecommendation & Suggested Strategy
From the technical details above you will notice how interconnected everything is.
As such, my recommendation is instead of migrating all 5 settings screens, and thus, forcing us to do that change in one go, most probably even in one PR (as I am not seeing another alternative), we could create a project which will rewrite each of those screens instead. This will make this change more manageable, enable the creation of multiple PRs, each tested in isolation, and which, will target
trunkdirectly, that is, without the need for a parent intermediate feature branch.Per the above, my suggested strategy would be:
androidx.preference, along with creating any custom preference class that this screen might required to become fully operational.In more detail, I would have followed the below PR chain strategy:
Account Settingsscreen, along with creating 3 new custom preference classes (SummaryEditTextPreference.kt,EditTextPreferenceWithValidation.ktandDetailListPreference.kt).Jetpack Security Settingsscreen, along with creating 2 new custom preference classes (WPSwitchPreference.ktandLearnMorePreference.kt).Notifications Settingsscreen, along with creating 1 new custom preference class (NotificationsSettingsDialogPreference.kt).App Settingsscreen, along with creating 1 new custom preference class (WPPreference.kt).Site Settingsscreen, along with creating 1 new custom preference class (WPStartOverPreference).android.preferencefrom anywhere else (ie.PreferenceFragmentLifeCycleOwner,WPPrefUtils,WPActivityUtils,EditPostActivity,MySitesPage, etc)Let's discuss, let me know your thoughts on all the above! 🙇