From e4e0dae27158619d641cda624cf107b53d32a556 Mon Sep 17 00:00:00 2001 From: Jasjeet Singh <98077881+07jasjeet@users.noreply.github.com> Date: Tue, 2 Jan 2024 20:54:00 +0530 Subject: [PATCH 01/14] Update NotificationsSettingsFragment.java 1) Only updated feasible getFragmentManager() occurence --- .../ui/prefs/notifications/NotificationsSettingsFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsFragment.java index 47c9aaba611a..d95132c384ad 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsFragment.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsFragment.java @@ -736,7 +736,7 @@ private void configureFollowedBlogsSettings(@Nullable PreferenceCategory blogsCa mPreviousEmailComments); dialog.setArguments(args); dialog.setTargetFragment(NotificationsSettingsFragment.this, NOTIFICATION_SETTINGS); - dialog.show(getFragmentManager(), NotificationSettingsFollowedDialog.TAG); + dialog.show(getChildFragmentManager(), NotificationSettingsFollowedDialog.TAG); return true; }); } else { From 357ce6be8741dda6beba2381678ab8efe7d9b2a1 Mon Sep 17 00:00:00 2001 From: Jasjeet Singh <98077881+07jasjeet@users.noreply.github.com> Date: Tue, 2 Jan 2024 20:55:44 +0530 Subject: [PATCH 02/14] Updated NotificationSettingsFragment with kt extenstion For java to kotlin conversion --- ...ionsSettingsFragment.java => NotificationsSettingsFragment.kt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/{NotificationsSettingsFragment.java => NotificationsSettingsFragment.kt} (100%) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsFragment.kt similarity index 100% rename from WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsFragment.java rename to WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsFragment.kt From d2acb7876921875c77a32dfb437269a70a5e410c Mon Sep 17 00:00:00 2001 From: Jasjeet Singh <98077881+07jasjeet@users.noreply.github.com> Date: Tue, 2 Jan 2024 21:09:17 +0530 Subject: [PATCH 03/14] AS Auto-convert results --- .../NotificationsSettingsFragment.kt | 1650 +++++++++-------- 1 file changed, 851 insertions(+), 799 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsFragment.kt index d95132c384ad..526e5216e9e5 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsFragment.kt @@ -1,1038 +1,1090 @@ -package org.wordpress.android.ui.prefs.notifications; - -import android.Manifest; -import android.app.Activity; -import android.app.Dialog; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.graphics.PorterDuff.Mode; -import android.os.Build; -import android.os.Bundle; -import android.preference.Preference; -import android.preference.PreferenceCategory; -import android.preference.PreferenceFragment; -import android.preference.PreferenceScreen; -import android.text.TextUtils; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; -import android.widget.ListView; - -import androidx.annotation.DrawableRes; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.StringRes; -import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.widget.SearchView; -import androidx.core.view.ViewCompat; -import androidx.lifecycle.ViewModelProvider; -import androidx.preference.PreferenceManager; - -import com.android.volley.VolleyError; -import com.wordpress.rest.RestRequest; - -import org.greenrobot.eventbus.EventBus; -import org.greenrobot.eventbus.Subscribe; -import org.greenrobot.eventbus.ThreadMode; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; -import org.wordpress.android.R; -import org.wordpress.android.WordPress; -import org.wordpress.android.analytics.AnalyticsTracker; -import org.wordpress.android.analytics.AnalyticsTracker.Stat; -import org.wordpress.android.databinding.JetpackBadgeFooterBinding; -import org.wordpress.android.datasets.ReaderBlogTable; -import org.wordpress.android.fluxc.Dispatcher; -import org.wordpress.android.fluxc.generated.AccountActionBuilder; -import org.wordpress.android.fluxc.model.SiteModel; -import org.wordpress.android.fluxc.store.AccountStore; -import org.wordpress.android.fluxc.store.AccountStore.AddOrDeleteSubscriptionPayload; -import org.wordpress.android.fluxc.store.AccountStore.AddOrDeleteSubscriptionPayload.SubscriptionAction; -import org.wordpress.android.fluxc.store.AccountStore.OnSubscriptionUpdated; -import org.wordpress.android.fluxc.store.AccountStore.OnSubscriptionsChanged; -import org.wordpress.android.fluxc.store.AccountStore.SubscriptionType; -import org.wordpress.android.fluxc.store.AccountStore.UpdateSubscriptionPayload; -import org.wordpress.android.fluxc.store.AccountStore.UpdateSubscriptionPayload.SubscriptionFrequency; -import org.wordpress.android.fluxc.store.SiteStore; -import org.wordpress.android.models.JetpackPoweredScreen; -import org.wordpress.android.models.NotificationsSettings; -import org.wordpress.android.models.NotificationsSettings.Channel; -import org.wordpress.android.models.NotificationsSettings.Type; -import org.wordpress.android.ui.WPLaunchActivity; -import org.wordpress.android.ui.bloggingreminders.BloggingReminderUtils; -import org.wordpress.android.ui.bloggingreminders.BloggingRemindersViewModel; -import org.wordpress.android.ui.mysite.jetpackbadge.JetpackPoweredBottomSheetFragment; -import org.wordpress.android.ui.notifications.NotificationEvents; -import org.wordpress.android.ui.notifications.utils.NotificationsUtils; -import org.wordpress.android.ui.prefs.notifications.FollowedBlogsProvider.PreferenceModel; -import org.wordpress.android.ui.prefs.notifications.FollowedBlogsProvider.PreferenceModel.ClickHandler; -import org.wordpress.android.ui.prefs.notifications.NotificationsSettingsDialogPreference.BloggingRemindersProvider; -import org.wordpress.android.ui.utils.UiHelpers; -import org.wordpress.android.ui.utils.UiString; -import org.wordpress.android.util.AppLog; -import org.wordpress.android.util.AppLog.T; -import org.wordpress.android.util.BuildConfigWrapper; -import org.wordpress.android.util.JetpackBrandingUtils; -import org.wordpress.android.util.SiteUtils; -import org.wordpress.android.util.ToastUtils; -import org.wordpress.android.util.ToastUtils.Duration; -import org.wordpress.android.util.WPActivityUtils; -import org.wordpress.android.util.WPPermissionUtils; -import org.wordpress.android.util.extensions.ContextExtensionsKt; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; - -import javax.inject.Inject; - -import static org.wordpress.android.fluxc.generated.AccountActionBuilder.newUpdateSubscriptionEmailCommentAction; -import static org.wordpress.android.fluxc.generated.AccountActionBuilder.newUpdateSubscriptionEmailPostAction; -import static org.wordpress.android.fluxc.generated.AccountActionBuilder.newUpdateSubscriptionEmailPostFrequencyAction; -import static org.wordpress.android.fluxc.generated.AccountActionBuilder.newUpdateSubscriptionNotificationPostAction; -import static org.wordpress.android.ui.RequestCodes.NOTIFICATION_SETTINGS; -import static org.wordpress.android.util.WPPermissionUtils.NOTIFICATIONS_PERMISSION_REQUEST_CODE; - -public class NotificationsSettingsFragment extends PreferenceFragment - implements SharedPreferences.OnSharedPreferenceChangeListener { - private static final String KEY_SEARCH_QUERY = "search_query"; - private static final int SITE_SEARCH_VISIBILITY_COUNT = 15; - // The number of notification types we support (e.g. timeline, email, mobile) - private static final int TYPE_COUNT = 3; - private static final int NO_MAXIMUM = -1; - private static final int MAX_SITES_TO_SHOW_ON_FIRST_SCREEN = 3; - - private NotificationsSettings mNotificationsSettings; - private SearchView mSearchView; - private MenuItem mSearchMenuItem; - private boolean mSearchMenuItemCollapsed = true; - - private String mDeviceId; - private String mNotificationUpdatedSite; - private String mPreviousEmailPostsFrequency; - private String mRestoredQuery; - private UpdateSubscriptionPayload mUpdateSubscriptionFrequencyPayload; - private boolean mNotificationsEnabled; - private boolean mPreviousEmailComments; - private boolean mPreviousEmailPosts; - private boolean mPreviousNotifyPosts; - private boolean mUpdateEmailPostsFirst; - private int mSiteCount; - private int mSubscriptionCount; - - private final List mTypePreferenceCategories = new ArrayList<>(); - private PreferenceCategory mBlogsCategory; - @Nullable private PreferenceCategory mFollowedBlogsCategory; - - @Inject AccountStore mAccountStore; - @Inject SiteStore mSiteStore; - @Inject Dispatcher mDispatcher; - @Inject FollowedBlogsProvider mFollowedBlogsProvider; - @Inject BuildConfigWrapper mBuildConfigWrapper; - @Inject ViewModelProvider.Factory mViewModelFactory; - @Inject JetpackBrandingUtils mJetpackBrandingUtils; - @Inject UiHelpers mUiHelpers; - - private BloggingRemindersViewModel mBloggingRemindersViewModel; - private final Map mBloggingRemindersSummariesBySiteId = new HashMap<>(); - - private static final String BLOGGING_REMINDERS_BOTTOM_SHEET_TAG = "blogging-reminders-dialog-tag"; - - @Override - public void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - ((WordPress) getActivity().getApplication()).component().inject(this); - - addPreferencesFromResource(R.xml.notifications_settings); - setHasOptionsMenu(true); - removeSightAndSoundsForAPI26(); - removeFollowedBlogsPreferenceForIfDisabled(); +package org.wordpress.android.ui.prefs.notifications + +import android.Manifest +import android.content.Context +import android.content.Intent +import android.content.SharedPreferences +import android.content.SharedPreferences.OnSharedPreferenceChangeListener +import android.graphics.PorterDuff +import android.os.Build +import android.os.Bundle +import android.preference.Preference +import android.preference.PreferenceCategory +import android.preference.PreferenceFragment +import android.preference.PreferenceScreen +import android.text.TextUtils +import android.view.LayoutInflater +import android.view.Menu +import android.view.MenuInflater +import android.view.MenuItem +import android.view.View +import android.widget.ListView +import androidx.annotation.DrawableRes +import androidx.annotation.StringRes +import androidx.appcompat.app.AppCompatActivity +import androidx.appcompat.widget.SearchView +import androidx.core.view.ViewCompat +import androidx.lifecycle.Observer +import androidx.lifecycle.ViewModelProvider +import androidx.preference.PreferenceManager +import com.wordpress.rest.RestRequest +import org.greenrobot.eventbus.EventBus +import org.greenrobot.eventbus.Subscribe +import org.greenrobot.eventbus.ThreadMode +import org.json.JSONArray +import org.json.JSONException +import org.json.JSONObject +import org.wordpress.android.R +import org.wordpress.android.WordPress +import org.wordpress.android.WordPress.Companion.getRestClientUtilsV1_1 +import org.wordpress.android.analytics.AnalyticsTracker +import org.wordpress.android.analytics.AnalyticsTracker.Stat +import org.wordpress.android.databinding.JetpackBadgeFooterBinding +import org.wordpress.android.datasets.ReaderBlogTable +import org.wordpress.android.fluxc.Dispatcher +import org.wordpress.android.fluxc.generated.AccountActionBuilder +import org.wordpress.android.fluxc.model.SiteModel +import org.wordpress.android.fluxc.store.AccountStore +import org.wordpress.android.fluxc.store.AccountStore.AddOrDeleteSubscriptionPayload +import org.wordpress.android.fluxc.store.AccountStore.AddOrDeleteSubscriptionPayload.SubscriptionAction +import org.wordpress.android.fluxc.store.AccountStore.OnSubscriptionUpdated +import org.wordpress.android.fluxc.store.AccountStore.OnSubscriptionsChanged +import org.wordpress.android.fluxc.store.AccountStore.SubscriptionType +import org.wordpress.android.fluxc.store.AccountStore.UpdateSubscriptionPayload +import org.wordpress.android.fluxc.store.AccountStore.UpdateSubscriptionPayload.SubscriptionFrequency +import org.wordpress.android.fluxc.store.SiteStore +import org.wordpress.android.models.JetpackPoweredScreen +import org.wordpress.android.models.NotificationsSettings +import org.wordpress.android.ui.RequestCodes +import org.wordpress.android.ui.WPLaunchActivity +import org.wordpress.android.ui.bloggingreminders.BloggingReminderUtils.observeBottomSheet +import org.wordpress.android.ui.bloggingreminders.BloggingRemindersViewModel +import org.wordpress.android.ui.mysite.jetpackbadge.JetpackPoweredBottomSheetFragment +import org.wordpress.android.ui.notifications.NotificationEvents.NotificationsSettingsStatusChanged +import org.wordpress.android.ui.notifications.utils.NotificationsUtils +import org.wordpress.android.ui.prefs.notifications.FollowedBlogsProvider.PreferenceModel +import org.wordpress.android.ui.prefs.notifications.NotificationsSettingsDialogPreference.BloggingRemindersProvider +import org.wordpress.android.ui.prefs.notifications.NotificationsSettingsDialogPreference.OnNotificationsSettingsChangedListener +import org.wordpress.android.ui.utils.UiHelpers +import org.wordpress.android.ui.utils.UiString +import org.wordpress.android.util.AppLog +import org.wordpress.android.util.BuildConfigWrapper +import org.wordpress.android.util.JetpackBrandingUtils +import org.wordpress.android.util.SiteUtils +import org.wordpress.android.util.ToastUtils +import org.wordpress.android.util.WPActivityUtils +import org.wordpress.android.util.WPPermissionUtils +import org.wordpress.android.util.extensions.getColorStateListFromAttribute +import java.util.Collections +import javax.inject.Inject + +class NotificationsSettingsFragment : PreferenceFragment(), OnSharedPreferenceChangeListener { + private var mNotificationsSettings: NotificationsSettings? = null + private var mSearchView: SearchView? = null + private var mSearchMenuItem: MenuItem? = null + private var mSearchMenuItemCollapsed = true + private var mDeviceId: String? = null + private var mNotificationUpdatedSite: String? = null + private var mPreviousEmailPostsFrequency: String? = null + private var mRestoredQuery: String? = null + private var mUpdateSubscriptionFrequencyPayload: UpdateSubscriptionPayload? = null + private var mNotificationsEnabled = false + private var mPreviousEmailComments = false + private var mPreviousEmailPosts = false + private var mPreviousNotifyPosts = false + private var mUpdateEmailPostsFirst = false + private var mSiteCount = 0 + private var mSubscriptionCount = 0 + private val mTypePreferenceCategories: MutableList = ArrayList() + private var mBlogsCategory: PreferenceCategory? = null + private var mFollowedBlogsCategory: PreferenceCategory? = null + + @JvmField + @Inject + var mAccountStore: AccountStore? = null + + @JvmField + @Inject + var mSiteStore: SiteStore? = null + + @JvmField + @Inject + var mDispatcher: Dispatcher? = null + + @JvmField + @Inject + var mFollowedBlogsProvider: FollowedBlogsProvider? = null + + @JvmField + @Inject + var mBuildConfigWrapper: BuildConfigWrapper? = null + + @JvmField + @Inject + var mViewModelFactory: Factory? = null + + @JvmField + @Inject + var mJetpackBrandingUtils: JetpackBrandingUtils? = null + + @JvmField + @Inject + var mUiHelpers: UiHelpers? = null + private var mBloggingRemindersViewModel: BloggingRemindersViewModel? = null + private val mBloggingRemindersSummariesBySiteId: MutableMap = HashMap() + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + (activity.application as WordPress).component().inject(this) + addPreferencesFromResource(R.xml.notifications_settings) + setHasOptionsMenu(true) + removeSightAndSoundsForAPI26() + removeFollowedBlogsPreferenceForIfDisabled() // Bump Analytics if (savedInstanceState == null) { - AnalyticsTracker.track(AnalyticsTracker.Stat.NOTIFICATION_SETTINGS_LIST_OPENED); + AnalyticsTracker.track(Stat.NOTIFICATION_SETTINGS_LIST_OPENED) } } - private void removeSightAndSoundsForAPI26() { + private fun removeSightAndSoundsForAPI26() { // on API26 we removed the Sight & Sounds category altogether, as it can always be // overriden by the user in the Device settings, and the settings here // wouldn't either reflect nor have any effect anyway. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - PreferenceScreen preferenceScreen = - (PreferenceScreen) findPreference(getActivity().getString(R.string.wp_pref_notifications_root)); - - PreferenceCategory categorySightsAndSounds = (PreferenceCategory) preferenceScreen - .findPreference(getActivity().getString(R.string.pref_notification_sights_sounds)); - preferenceScreen.removePreference(categorySightsAndSounds); + val preferenceScreen = + findPreference(activity.getString(R.string.wp_pref_notifications_root)) as PreferenceScreen + val categorySightsAndSounds = preferenceScreen + .findPreference(activity.getString(R.string.pref_notification_sights_sounds)) as PreferenceCategory + preferenceScreen.removePreference(categorySightsAndSounds) } } - private void removeFollowedBlogsPreferenceForIfDisabled() { - if (!mBuildConfigWrapper.isFollowedSitesSettingsEnabled()) { - PreferenceScreen preferenceScreen = - (PreferenceScreen) findPreference(getActivity().getString(R.string.wp_pref_notifications_root)); - - PreferenceCategory categoryFollowedBlogs = (PreferenceCategory) preferenceScreen - .findPreference(getActivity().getString(R.string.pref_notification_blogs_followed)); - preferenceScreen.removePreference(categoryFollowedBlogs); + private fun removeFollowedBlogsPreferenceForIfDisabled() { + if (!mBuildConfigWrapper!!.isFollowedSitesSettingsEnabled) { + val preferenceScreen = + findPreference(activity.getString(R.string.wp_pref_notifications_root)) as PreferenceScreen + val categoryFollowedBlogs = preferenceScreen + .findPreference(activity.getString(R.string.pref_notification_blogs_followed)) as PreferenceCategory + preferenceScreen.removePreference(categoryFollowedBlogs) } } - @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - - boolean isLoggedIn = mAccountStore.hasAccessToken(); + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) + val isLoggedIn = mAccountStore!!.hasAccessToken() if (!isLoggedIn) { // Not logged in users can start Notification Settings from App info > Notifications menu. // If there isn't a logged in user, just show the entry screen. - Intent intent = new Intent(getContext(), WPLaunchActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); - startActivity(intent); - getActivity().finish(); - return; + val intent = Intent(context, WPLaunchActivity::class.java) + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK) + startActivity(intent) + activity.finish() + return } - - SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(getActivity()); - mDeviceId = settings.getString(NotificationsUtils.WPCOM_PUSH_DEVICE_SERVER_ID, ""); - + val settings = PreferenceManager.getDefaultSharedPreferences(activity) + mDeviceId = settings.getString(NotificationsUtils.WPCOM_PUSH_DEVICE_SERVER_ID, "") if (hasNotificationsSettings()) { - loadNotificationsAndUpdateUI(true); + loadNotificationsAndUpdateUI(true) } - - if (savedInstanceState != null && savedInstanceState.containsKey(KEY_SEARCH_QUERY)) { - mRestoredQuery = savedInstanceState.getString(KEY_SEARCH_QUERY); + if (savedInstanceState != null && savedInstanceState.containsKey( + NotificationsSettingsFragment.Companion.KEY_SEARCH_QUERY + ) + ) { + mRestoredQuery = + savedInstanceState.getString(NotificationsSettingsFragment.Companion.KEY_SEARCH_QUERY) } } - @Override - public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - final ListView lv = (ListView) view.findViewById(android.R.id.list); + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + val lv = view.findViewById(android.R.id.list) as ListView if (lv != null) { - ViewCompat.setNestedScrollingEnabled(lv, true); - addJetpackBadgeAsFooterIfEnabled(lv); + ViewCompat.setNestedScrollingEnabled(lv, true) + addJetpackBadgeAsFooterIfEnabled(lv) } - initBloggingReminders(); + initBloggingReminders() } - @Override public void onViewStateRestored(Bundle savedInstanceState) { - super.onViewStateRestored(savedInstanceState); - PreferenceScreen otherBlogsScreen = (PreferenceScreen) findPreference( - getString(R.string.pref_notification_other_blogs)); - addToolbarToDialog(otherBlogsScreen); + override fun onViewStateRestored(savedInstanceState: Bundle) { + super.onViewStateRestored(savedInstanceState) + val otherBlogsScreen = findPreference( + getString(R.string.pref_notification_other_blogs) + ) as PreferenceScreen + addToolbarToDialog(otherBlogsScreen) } - private void addJetpackBadgeAsFooterIfEnabled(ListView listView) { - if (mJetpackBrandingUtils.shouldShowJetpackBranding()) { - final JetpackPoweredScreen screen = JetpackPoweredScreen.WithDynamicText.NOTIFICATIONS_SETTINGS; - final Context context = getContext(); - final LayoutInflater inflater = LayoutInflater.from(context); - final JetpackBadgeFooterBinding binding = JetpackBadgeFooterBinding.inflate(inflater); - binding.footerJetpackBadge.jetpackPoweredBadge.setText( - mUiHelpers.getTextOfUiString( - context, - mJetpackBrandingUtils.getBrandingTextForScreen(screen) + private fun addJetpackBadgeAsFooterIfEnabled(listView: ListView) { + if (mJetpackBrandingUtils!!.shouldShowJetpackBranding()) { + val screen: JetpackPoweredScreen = + JetpackPoweredScreen.WithDynamicText.NOTIFICATIONS_SETTINGS + val context = context + val inflater = LayoutInflater.from(context) + val binding = JetpackBadgeFooterBinding.inflate(inflater) + binding.footerJetpackBadge.jetpackPoweredBadge.text = mUiHelpers!!.getTextOfUiString( + context, + mJetpackBrandingUtils!!.getBrandingTextForScreen(screen) + ) + if (mJetpackBrandingUtils!!.shouldShowJetpackPoweredBottomSheet()) { + binding.footerJetpackBadge.jetpackPoweredBadge.setOnClickListener { v: View? -> + mJetpackBrandingUtils!!.trackBadgeTapped(screen) + JetpackPoweredBottomSheetFragment().show( + (activity as AppCompatActivity).supportFragmentManager, + JetpackPoweredBottomSheetFragment.TAG ) - ); - if (mJetpackBrandingUtils.shouldShowJetpackPoweredBottomSheet()) { - binding.footerJetpackBadge.jetpackPoweredBadge.setOnClickListener(v -> { - mJetpackBrandingUtils.trackBadgeTapped(screen); - new JetpackPoweredBottomSheetFragment().show( - ((AppCompatActivity) getActivity()).getSupportFragmentManager(), - JetpackPoweredBottomSheetFragment.TAG); - }); + } } - listView.addFooterView(binding.getRoot(), null, false); + listView.addFooterView(binding.root, null, false) } } - @Override - public void onStart() { - super.onStart(); - mDispatcher.register(this); - getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(this); + override fun onStart() { + super.onStart() + mDispatcher!!.register(this) + preferenceManager.sharedPreferences.registerOnSharedPreferenceChangeListener(this) } - @Override - public void onResume() { - super.onResume(); - - mNotificationsEnabled = NotificationsUtils.isNotificationsEnabled(getActivity()); - refreshSettings(); + override fun onResume() { + super.onResume() + mNotificationsEnabled = NotificationsUtils.isNotificationsEnabled(activity) + refreshSettings() } - @Override - public void onStop() { - super.onStop(); - mDispatcher.unregister(this); - getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this); + override fun onStop() { + super.onStop() + mDispatcher!!.unregister(this) + preferenceManager.sharedPreferences.unregisterOnSharedPreferenceChangeListener(this) } - @Override - public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { - inflater.inflate(R.menu.notifications_settings, menu); - - mSearchMenuItem = menu.findItem(R.id.menu_notifications_settings_search); - mSearchView = (SearchView) mSearchMenuItem.getActionView(); - mSearchView.setQueryHint(getString(R.string.search_sites)); - mBlogsCategory = (PreferenceCategory) findPreference( - getString(R.string.pref_notification_blogs)); - mFollowedBlogsCategory = (PreferenceCategory) findPreference( - getString(R.string.pref_notification_blogs_followed)); - - mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { - @Override - public boolean onQueryTextSubmit(String query) { - configureBlogsSettings(mBlogsCategory, true); - configureFollowedBlogsSettings(mFollowedBlogsCategory, true); - return true; + override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { + inflater.inflate(R.menu.notifications_settings, menu) + mSearchMenuItem = menu.findItem(R.id.menu_notifications_settings_search) + mSearchView = mSearchMenuItem.getActionView() as SearchView? + mSearchView!!.queryHint = getString(R.string.search_sites) + mBlogsCategory = findPreference( + getString(R.string.pref_notification_blogs) + ) as PreferenceCategory + mFollowedBlogsCategory = findPreference( + getString(R.string.pref_notification_blogs_followed) + ) as PreferenceCategory + mSearchView!!.setOnQueryTextListener(object : SearchView.OnQueryTextListener { + override fun onQueryTextSubmit(query: String): Boolean { + configureBlogsSettings(mBlogsCategory, true) + configureFollowedBlogsSettings(mFollowedBlogsCategory, true) + return true } - @Override - public boolean onQueryTextChange(String newText) { + override fun onQueryTextChange(newText: String): Boolean { // we need to perform this check because when the search menu item is collapsed // a new queryTExtChange event is triggered with an empty value "", and we only // would want to take care of it when the user actively opened/cleared the search term - configureBlogsSettings(mBlogsCategory, !mSearchMenuItemCollapsed); - configureFollowedBlogsSettings(mFollowedBlogsCategory, !mSearchMenuItemCollapsed); - return true; + configureBlogsSettings(mBlogsCategory, !mSearchMenuItemCollapsed) + configureFollowedBlogsSettings(mFollowedBlogsCategory, !mSearchMenuItemCollapsed) + return true } - }); - - mSearchMenuItem.setOnActionExpandListener(new MenuItem.OnActionExpandListener() { - @Override - public boolean onMenuItemActionExpand(@NonNull MenuItem item) { - mSearchMenuItemCollapsed = false; - configureBlogsSettings(mBlogsCategory, true); - configureFollowedBlogsSettings(mFollowedBlogsCategory, true); - return true; + }) + mSearchMenuItem.setOnActionExpandListener(object : MenuItem.OnActionExpandListener { + override fun onMenuItemActionExpand(item: MenuItem): Boolean { + mSearchMenuItemCollapsed = false + configureBlogsSettings(mBlogsCategory, true) + configureFollowedBlogsSettings(mFollowedBlogsCategory, true) + return true } - @Override - public boolean onMenuItemActionCollapse(@NonNull MenuItem item) { - mSearchMenuItemCollapsed = true; - configureBlogsSettings(mBlogsCategory, false); - configureFollowedBlogsSettings(mFollowedBlogsCategory, false); - return true; + override fun onMenuItemActionCollapse(item: MenuItem): Boolean { + mSearchMenuItemCollapsed = true + configureBlogsSettings(mBlogsCategory, false) + configureFollowedBlogsSettings(mFollowedBlogsCategory, false) + return true } - }); - - updateSearchMenuVisibility(); + }) + updateSearchMenuVisibility() // Check for a restored search query (if device was rotated, etc) if (!TextUtils.isEmpty(mRestoredQuery)) { - mSearchMenuItem.expandActionView(); - mSearchView.setQuery(mRestoredQuery, true); + mSearchMenuItem.expandActionView() + mSearchView!!.setQuery(mRestoredQuery, true) } } - @Override - public void onSaveInstanceState(Bundle outState) { - if (mSearchView != null && !TextUtils.isEmpty(mSearchView.getQuery())) { - outState.putString(KEY_SEARCH_QUERY, mSearchView.getQuery().toString()); + override fun onSaveInstanceState(outState: Bundle) { + if (mSearchView != null && !TextUtils.isEmpty(mSearchView!!.query)) { + outState.putString( + NotificationsSettingsFragment.Companion.KEY_SEARCH_QUERY, + mSearchView!!.query.toString() + ) } - - super.onSaveInstanceState(outState); + super.onSaveInstanceState(outState) } - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - - if (data != null && requestCode == NOTIFICATION_SETTINGS) { - boolean notifyPosts = - data.getBooleanExtra(NotificationSettingsFollowedDialog.KEY_NOTIFICATION_POSTS, false); - boolean emailPosts = - data.getBooleanExtra(NotificationSettingsFollowedDialog.KEY_EMAIL_POSTS, false); - String emailPostsFrequency = - data.getStringExtra(NotificationSettingsFollowedDialog.KEY_EMAIL_POSTS_FREQUENCY); - boolean emailComments = - data.getBooleanExtra(NotificationSettingsFollowedDialog.KEY_EMAIL_COMMENTS, false); - + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) { + super.onActivityResult(requestCode, resultCode, data) + if (data != null && requestCode == RequestCodes.NOTIFICATION_SETTINGS) { + val notifyPosts = data.getBooleanExtra( + NotificationSettingsFollowedDialog.KEY_NOTIFICATION_POSTS, + false + ) + val emailPosts = + data.getBooleanExtra(NotificationSettingsFollowedDialog.KEY_EMAIL_POSTS, false) + val emailPostsFrequency = + data.getStringExtra(NotificationSettingsFollowedDialog.KEY_EMAIL_POSTS_FREQUENCY) + val emailComments = + data.getBooleanExtra(NotificationSettingsFollowedDialog.KEY_EMAIL_COMMENTS, false) if (notifyPosts != mPreviousNotifyPosts) { - ReaderBlogTable.setNotificationsEnabledByBlogId(Long.parseLong(mNotificationUpdatedSite), notifyPosts); - AddOrDeleteSubscriptionPayload payload; - - if (notifyPosts) { - AnalyticsTracker.track(Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_ON); - payload = new AddOrDeleteSubscriptionPayload(mNotificationUpdatedSite, SubscriptionAction.NEW); + ReaderBlogTable.setNotificationsEnabledByBlogId( + mNotificationUpdatedSite!!.toLong(), + notifyPosts + ) + val payload: AddOrDeleteSubscriptionPayload + payload = if (notifyPosts) { + AnalyticsTracker.track(Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_ON) + AddOrDeleteSubscriptionPayload( + mNotificationUpdatedSite!!, + SubscriptionAction.NEW + ) } else { - AnalyticsTracker.track(Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_OFF); - payload = new AddOrDeleteSubscriptionPayload(mNotificationUpdatedSite, SubscriptionAction.DELETE); + AnalyticsTracker.track(Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_OFF) + AddOrDeleteSubscriptionPayload( + mNotificationUpdatedSite!!, + SubscriptionAction.DELETE + ) } - - mDispatcher.dispatch(newUpdateSubscriptionNotificationPostAction(payload)); + mDispatcher!!.dispatch( + AccountActionBuilder.newUpdateSubscriptionNotificationPostAction( + payload + ) + ) } - if (emailPosts != mPreviousEmailPosts) { - AddOrDeleteSubscriptionPayload payload; - - if (emailPosts) { - AnalyticsTracker.track(Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_EMAIL_ON); - payload = new AddOrDeleteSubscriptionPayload(mNotificationUpdatedSite, SubscriptionAction.NEW); + val payload: AddOrDeleteSubscriptionPayload + payload = if (emailPosts) { + AnalyticsTracker.track(Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_EMAIL_ON) + AddOrDeleteSubscriptionPayload( + mNotificationUpdatedSite!!, + SubscriptionAction.NEW + ) } else { - AnalyticsTracker.track(Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_EMAIL_OFF); - payload = new AddOrDeleteSubscriptionPayload(mNotificationUpdatedSite, SubscriptionAction.DELETE); + AnalyticsTracker.track(Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_EMAIL_OFF) + AddOrDeleteSubscriptionPayload( + mNotificationUpdatedSite!!, + SubscriptionAction.DELETE + ) } - - mDispatcher.dispatch(newUpdateSubscriptionEmailPostAction(payload)); + mDispatcher!!.dispatch( + AccountActionBuilder.newUpdateSubscriptionEmailPostAction( + payload + ) + ) } - - if (emailPostsFrequency != null && !emailPostsFrequency.equalsIgnoreCase(mPreviousEmailPostsFrequency)) { - SubscriptionFrequency subscriptionFrequency = getSubscriptionFrequencyFromString(emailPostsFrequency); - mUpdateSubscriptionFrequencyPayload = new UpdateSubscriptionPayload(mNotificationUpdatedSite, - subscriptionFrequency); + if (emailPostsFrequency != null && !emailPostsFrequency.equals( + mPreviousEmailPostsFrequency, + ignoreCase = true + ) + ) { + val subscriptionFrequency = getSubscriptionFrequencyFromString(emailPostsFrequency) + mUpdateSubscriptionFrequencyPayload = UpdateSubscriptionPayload( + mNotificationUpdatedSite!!, + subscriptionFrequency + ) /* * The email post frequency update will be overridden by the email post update if the email post * frequency callback returns first. Thus, the updates must be dispatched sequentially when the * email post update is switched from disabled to enabled. - */ - if (emailPosts != mPreviousEmailPosts && emailPosts) { - mUpdateEmailPostsFirst = true; + */if (emailPosts != mPreviousEmailPosts && emailPosts) { + mUpdateEmailPostsFirst = true } else { - mDispatcher.dispatch(newUpdateSubscriptionEmailPostFrequencyAction( - mUpdateSubscriptionFrequencyPayload)); + mDispatcher!!.dispatch( + AccountActionBuilder.newUpdateSubscriptionEmailPostFrequencyAction( + mUpdateSubscriptionFrequencyPayload + ) + ) } } - if (emailComments != mPreviousEmailComments) { - AddOrDeleteSubscriptionPayload payload; - - if (emailComments) { - AnalyticsTracker.track(Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_COMMENTS_ON); - payload = new AddOrDeleteSubscriptionPayload(mNotificationUpdatedSite, SubscriptionAction.NEW); + val payload: AddOrDeleteSubscriptionPayload + payload = if (emailComments) { + AnalyticsTracker.track(Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_COMMENTS_ON) + AddOrDeleteSubscriptionPayload( + mNotificationUpdatedSite!!, + SubscriptionAction.NEW + ) } else { - AnalyticsTracker.track(Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_COMMENTS_OFF); - payload = new AddOrDeleteSubscriptionPayload(mNotificationUpdatedSite, SubscriptionAction.DELETE); + AnalyticsTracker.track(Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_COMMENTS_OFF) + AddOrDeleteSubscriptionPayload( + mNotificationUpdatedSite!!, + SubscriptionAction.DELETE + ) } - - mDispatcher.dispatch(newUpdateSubscriptionEmailCommentAction(payload)); + mDispatcher!!.dispatch( + AccountActionBuilder.newUpdateSubscriptionEmailCommentAction( + payload + ) + ) } } } - @SuppressWarnings("unused") + @Suppress("unused") @Subscribe(threadMode = ThreadMode.MAIN) - public void onSubscriptionsChanged(OnSubscriptionsChanged event) { - if (event.isError()) { - AppLog.e(T.API, "NotificationsSettingsFragment.onSubscriptionsChanged: " + event.error.message); + fun onSubscriptionsChanged(event: OnSubscriptionsChanged) { + if (event.isError) { + AppLog.e( + AppLog.T.API, + "NotificationsSettingsFragment.onSubscriptionsChanged: " + event.error.message + ) } else { - configureFollowedBlogsSettings(mFollowedBlogsCategory, !mSearchMenuItemCollapsed); + configureFollowedBlogsSettings(mFollowedBlogsCategory, !mSearchMenuItemCollapsed) } } - @SuppressWarnings("unused") + @Suppress("unused") @Subscribe(threadMode = ThreadMode.MAIN) - public void onSubscriptionUpdated(OnSubscriptionUpdated event) { - if (event.isError()) { - AppLog.e(T.API, "NotificationsSettingsFragment.onSubscriptionUpdated: " + event.error.message); + fun onSubscriptionUpdated(event: OnSubscriptionUpdated) { + if (event.isError) { + AppLog.e( + AppLog.T.API, + "NotificationsSettingsFragment.onSubscriptionUpdated: " + event.error.message + ) } else if (event.type == SubscriptionType.EMAIL_POST && mUpdateEmailPostsFirst) { - mUpdateEmailPostsFirst = false; - mDispatcher.dispatch(newUpdateSubscriptionEmailPostFrequencyAction(mUpdateSubscriptionFrequencyPayload)); + mUpdateEmailPostsFirst = false + mDispatcher!!.dispatch( + AccountActionBuilder.newUpdateSubscriptionEmailPostFrequencyAction( + mUpdateSubscriptionFrequencyPayload + ) + ) } else { - mDispatcher.dispatch(AccountActionBuilder.newFetchSubscriptionsAction()); + mDispatcher!!.dispatch(AccountActionBuilder.newFetchSubscriptionsAction()) } } - private SubscriptionFrequency getSubscriptionFrequencyFromString(String s) { - if (s.equalsIgnoreCase(SubscriptionFrequency.DAILY.toString())) { - AnalyticsTracker.track(Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_EMAIL_DAILY); - return SubscriptionFrequency.DAILY; - } else if (s.equalsIgnoreCase(SubscriptionFrequency.WEEKLY.toString())) { - AnalyticsTracker.track(Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_EMAIL_WEEKLY); - return SubscriptionFrequency.WEEKLY; + private fun getSubscriptionFrequencyFromString(s: String): SubscriptionFrequency { + return if (s.equals(SubscriptionFrequency.DAILY.toString(), ignoreCase = true)) { + AnalyticsTracker.track(Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_EMAIL_DAILY) + SubscriptionFrequency.DAILY + } else if (s.equals(SubscriptionFrequency.WEEKLY.toString(), ignoreCase = true)) { + AnalyticsTracker.track(Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_EMAIL_WEEKLY) + SubscriptionFrequency.WEEKLY } else { - AnalyticsTracker.track(Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_EMAIL_INSTANTLY); - return SubscriptionFrequency.INSTANTLY; + AnalyticsTracker.track(Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_EMAIL_INSTANTLY) + SubscriptionFrequency.INSTANTLY } } - private void refreshSettings() { + private fun refreshSettings() { if (!hasNotificationsSettings()) { EventBus.getDefault() - .post(new NotificationEvents.NotificationsSettingsStatusChanged(getString(R.string.loading))); + .post(NotificationsSettingsStatusChanged(getString(R.string.loading))) } - if (hasNotificationsSettings()) { - updateUIForNotificationsEnabledState(); + updateUIForNotificationsEnabledState() } - - if (!mAccountStore.hasAccessToken()) { - return; + if (!mAccountStore!!.hasAccessToken()) { + return } - - NotificationsUtils.getPushNotificationSettings(getActivity(), new RestRequest.Listener() { - @Override - public void onResponse(JSONObject response) { - AppLog.d(T.NOTIFS, "Get settings action succeeded"); - if (!isAdded()) { - return; - } - - boolean settingsExisted = hasNotificationsSettings(); - if (!settingsExisted) { - EventBus.getDefault().post(new NotificationEvents.NotificationsSettingsStatusChanged(null)); - } - - SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(getActivity()); - SharedPreferences.Editor editor = settings.edit(); - editor.putString(NotificationsUtils.WPCOM_PUSH_DEVICE_NOTIFICATION_SETTINGS, response.toString()); - editor.apply(); - - loadNotificationsAndUpdateUI(!settingsExisted); - updateUIForNotificationsEnabledState(); + NotificationsUtils.getPushNotificationSettings(activity, RestRequest.Listener { response -> + AppLog.d(AppLog.T.NOTIFS, "Get settings action succeeded") + if (!isAdded) { + return@Listener } - }, new RestRequest.ErrorListener() { - @Override - public void onErrorResponse(VolleyError error) { - if (!isAdded()) { - return; - } - AppLog.e(T.NOTIFS, "Get settings action failed", error); - - if (!hasNotificationsSettings()) { - EventBus.getDefault().post(new NotificationEvents.NotificationsSettingsStatusChanged( - getString(R.string.error_loading_notifications))); - } + val settingsExisted = hasNotificationsSettings() + if (!settingsExisted) { + EventBus.getDefault().post(NotificationsSettingsStatusChanged(null)) + } + val settings = PreferenceManager.getDefaultSharedPreferences(activity) + val editor = settings.edit() + editor.putString( + NotificationsUtils.WPCOM_PUSH_DEVICE_NOTIFICATION_SETTINGS, + response.toString() + ) + editor.apply() + loadNotificationsAndUpdateUI(!settingsExisted) + updateUIForNotificationsEnabledState() + }, RestRequest.ErrorListener { error -> + if (!isAdded) { + return@ErrorListener } - }); + AppLog.e(AppLog.T.NOTIFS, "Get settings action failed", error) + if (!hasNotificationsSettings()) { + EventBus.getDefault().post( + NotificationsSettingsStatusChanged( + getString(R.string.error_loading_notifications) + ) + ) + } + }) } - private void loadNotificationsAndUpdateUI(boolean shouldUpdateUI) { - JSONObject settingsJson; - try { - SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity()); - settingsJson = new JSONObject( - sharedPreferences.getString(NotificationsUtils.WPCOM_PUSH_DEVICE_NOTIFICATION_SETTINGS, "") - ); - } catch (JSONException e) { - AppLog.e(T.NOTIFS, "Could not parse notifications settings JSON"); - return; + private fun loadNotificationsAndUpdateUI(shouldUpdateUI: Boolean) { + val settingsJson: JSONObject + settingsJson = try { + val sharedPreferences = PreferenceManager.getDefaultSharedPreferences( + activity + ) + JSONObject( + sharedPreferences.getString( + NotificationsUtils.WPCOM_PUSH_DEVICE_NOTIFICATION_SETTINGS, + "" + ) + ) + } catch (e: JSONException) { + AppLog.e(AppLog.T.NOTIFS, "Could not parse notifications settings JSON") + return } - if (mNotificationsSettings == null) { - mNotificationsSettings = new NotificationsSettings(settingsJson); + mNotificationsSettings = NotificationsSettings(settingsJson) } else { - mNotificationsSettings.updateJson(settingsJson); + mNotificationsSettings!!.updateJson(settingsJson) } - if (shouldUpdateUI) { if (mBlogsCategory == null) { - mBlogsCategory = (PreferenceCategory) findPreference( - getString(R.string.pref_notification_blogs)); + mBlogsCategory = findPreference( + getString(R.string.pref_notification_blogs) + ) as PreferenceCategory } - if (mFollowedBlogsCategory == null) { - mFollowedBlogsCategory = (PreferenceCategory) findPreference( - getString(R.string.pref_notification_blogs_followed)); + mFollowedBlogsCategory = findPreference( + getString(R.string.pref_notification_blogs_followed) + ) as PreferenceCategory } - - configureBlogsSettings(mBlogsCategory, false); - configureFollowedBlogsSettings(mFollowedBlogsCategory, false); - configureOtherSettings(); - configureWPComSettings(); + configureBlogsSettings(mBlogsCategory, false) + configureFollowedBlogsSettings(mFollowedBlogsCategory, false) + configureOtherSettings() + configureWPComSettings() } } - private boolean hasNotificationsSettings() { - SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity()); - - return sharedPreferences.contains(NotificationsUtils.WPCOM_PUSH_DEVICE_NOTIFICATION_SETTINGS); + private fun hasNotificationsSettings(): Boolean { + val sharedPreferences = PreferenceManager.getDefaultSharedPreferences( + activity + ) + return sharedPreferences.contains(NotificationsUtils.WPCOM_PUSH_DEVICE_NOTIFICATION_SETTINGS) } // Updates the UI for preference screens based on if notifications are enabled or not - private void updateUIForNotificationsEnabledState() { - if (mTypePreferenceCategories.size() == 0) { - return; + private fun updateUIForNotificationsEnabledState() { + if (mTypePreferenceCategories.size == 0) { + return } - - for (final PreferenceCategory category : mTypePreferenceCategories) { - if (mNotificationsEnabled && category.getPreferenceCount() > TYPE_COUNT) { - category.removePreference(category.getPreference(TYPE_COUNT)); - } else if (!mNotificationsEnabled && category.getPreferenceCount() == TYPE_COUNT) { - Preference disabledMessage = new Preference(getActivity()); - category.addPreference(disabledMessage); + for (category in mTypePreferenceCategories) { + if (mNotificationsEnabled && category.preferenceCount > NotificationsSettingsFragment.Companion.TYPE_COUNT) { + category.removePreference(category.getPreference(NotificationsSettingsFragment.Companion.TYPE_COUNT)) + } else if (!mNotificationsEnabled && category.preferenceCount == NotificationsSettingsFragment.Companion.TYPE_COUNT) { + val disabledMessage = Preference(activity) + category.addPreference(disabledMessage) } - - if (category.getPreferenceCount() >= TYPE_COUNT - && category.getPreference(TYPE_COUNT - 1) != null) { - category.getPreference(TYPE_COUNT - 1).setEnabled(mNotificationsEnabled); + if (category.preferenceCount >= NotificationsSettingsFragment.Companion.TYPE_COUNT + && category.getPreference(NotificationsSettingsFragment.Companion.TYPE_COUNT - 1) != null + ) { + category.getPreference(NotificationsSettingsFragment.Companion.TYPE_COUNT - 1).isEnabled = + mNotificationsEnabled } - - if (category.getPreferenceCount() > TYPE_COUNT - && category.getPreference(TYPE_COUNT) != null) { - updateDisabledMessagePreference(category.getPreference(TYPE_COUNT)); + if (category.preferenceCount > NotificationsSettingsFragment.Companion.TYPE_COUNT + && category.getPreference(NotificationsSettingsFragment.Companion.TYPE_COUNT) != null + ) { + updateDisabledMessagePreference(category.getPreference(NotificationsSettingsFragment.Companion.TYPE_COUNT)) } } } - private void updateDisabledMessagePreference(Preference disabledMessagePreference) { - disabledMessagePreference.setSummary(getDisabledMessageResId()); - disabledMessagePreference.setOnPreferenceClickListener(preference -> { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && shouldRequestRuntimePermission()) { - // Request runtime permission. - requestPermissions(new String[]{Manifest.permission.POST_NOTIFICATIONS}, - NOTIFICATIONS_PERMISSION_REQUEST_CODE); - } else { - // Navigate to app settings. - WPPermissionUtils.showNotificationsSettings(getContext()); + private fun updateDisabledMessagePreference(disabledMessagePreference: Preference) { + disabledMessagePreference.setSummary(disabledMessageResId) + disabledMessagePreference.onPreferenceClickListener = + Preference.OnPreferenceClickListener { preference: Preference? -> + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && shouldRequestRuntimePermission()) { + // Request runtime permission. + requestPermissions( + arrayOf(Manifest.permission.POST_NOTIFICATIONS), + WPPermissionUtils.NOTIFICATIONS_PERMISSION_REQUEST_CODE + ) + } else { + // Navigate to app settings. + WPPermissionUtils.showNotificationsSettings(context) + } + true } - return true; - }); } - private boolean shouldRequestRuntimePermission() { - return Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU - && !WPPermissionUtils.isPermissionAlwaysDenied(getActivity(), Manifest.permission.POST_NOTIFICATIONS); + private fun shouldRequestRuntimePermission(): Boolean { + return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU + && !WPPermissionUtils.isPermissionAlwaysDenied( + activity, + Manifest.permission.POST_NOTIFICATIONS + )) } - @StringRes - private int getDisabledMessageResId() { - if (shouldRequestRuntimePermission()) { - return R.string.notifications_disabled_permission_dialog; + @get:StringRes + private val disabledMessageResId: Int + private get() = if (shouldRequestRuntimePermission()) { + R.string.notifications_disabled_permission_dialog } else { - return R.string.notifications_disabled; + R.string.notifications_disabled } - } - @Override - public void onRequestPermissionsResult(int requestCode, - @NonNull String[] permissions, - @NonNull int[] grantResults) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults); - - WPPermissionUtils.setPermissionListAsked(getActivity(), requestCode, permissions, grantResults, false); + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + WPPermissionUtils.setPermissionListAsked( + activity, + requestCode, + permissions, + grantResults, + false + ) } - private void configureBlogsSettings(PreferenceCategory blogsCategory, boolean showAll) { - if (!isAdded()) { - return; + private fun configureBlogsSettings(blogsCategory: PreferenceCategory?, showAll: Boolean) { + if (!isAdded) { + return } - - List sites; - String trimmedQuery = ""; - if (mSearchView != null && !TextUtils.isEmpty(mSearchView.getQuery())) { - trimmedQuery = mSearchView.getQuery().toString().trim(); - sites = mSiteStore.getSitesAccessedViaWPComRestByNameOrUrlMatching(trimmedQuery); + val sites: List + var trimmedQuery = "" + if (mSearchView != null && !TextUtils.isEmpty(mSearchView!!.query)) { + trimmedQuery = mSearchView!!.query.toString().trim { it <= ' ' } + sites = mSiteStore!!.getSitesAccessedViaWPComRestByNameOrUrlMatching(trimmedQuery) } else { - sites = mSiteStore.getSitesAccessedViaWPComRest(); + sites = mSiteStore!!.sitesAccessedViaWPComRest } - mSiteCount = sites.size(); - + mSiteCount = sites.size if (mSiteCount > 0) { - Collections.sort(sites, new Comparator() { - @Override public int compare(SiteModel o1, SiteModel o2) { - return SiteUtils.getSiteNameOrHomeURL(o1).compareToIgnoreCase(SiteUtils.getSiteNameOrHomeURL(o2)); - } - }); + Collections.sort(sites) { o1, o2 -> + SiteUtils.getSiteNameOrHomeURL(o1).compareTo( + SiteUtils.getSiteNameOrHomeURL(o2), ignoreCase = true + ) + } } - - Context context = getActivity(); - - blogsCategory.removeAll(); - - int maxSitesToShow = showAll ? NO_MAXIMUM : MAX_SITES_TO_SHOW_ON_FIRST_SCREEN; - int count = 0; - for (SiteModel site : sites) { + val context: Context? = activity + blogsCategory!!.removeAll() + val maxSitesToShow: Int = + if (showAll) NotificationsSettingsFragment.Companion.NO_MAXIMUM else NotificationsSettingsFragment.Companion.MAX_SITES_TO_SHOW_ON_FIRST_SCREEN + var count = 0 + for (site in sites) { if (context == null) { - return; + return } - - count++; - if (maxSitesToShow != NO_MAXIMUM && count > maxSitesToShow) { - break; + count++ + if (maxSitesToShow != NotificationsSettingsFragment.Companion.NO_MAXIMUM && count > maxSitesToShow) { + break } - - PreferenceScreen prefScreen = getPreferenceManager().createPreferenceScreen(context); - prefScreen.setTitle(SiteUtils.getSiteNameOrHomeURL(site)); - prefScreen.setSummary(SiteUtils.getHomeURLOrHostName(site)); - addPreferencesForPreferenceScreen(prefScreen, Channel.BLOGS, site.getSiteId()); - blogsCategory.addPreference(prefScreen); + val prefScreen = preferenceManager.createPreferenceScreen(context) + prefScreen.title = SiteUtils.getSiteNameOrHomeURL(site) + prefScreen.summary = SiteUtils.getHomeURLOrHostName(site) + addPreferencesForPreferenceScreen( + prefScreen, + NotificationsSettings.Channel.BLOGS, + site.siteId + ) + blogsCategory.addPreference(prefScreen) } // Add a message in a preference if there are no matching search results if (mSiteCount == 0 && !TextUtils.isEmpty(trimmedQuery)) { - Preference searchResultsPref = new Preference(context); - searchResultsPref - .setSummary(String.format(getString(R.string.notifications_no_search_results), trimmedQuery)); - blogsCategory.addPreference(searchResultsPref); + val searchResultsPref = Preference(context) + searchResultsPref.summary = + String.format(getString(R.string.notifications_no_search_results), trimmedQuery) + blogsCategory.addPreference(searchResultsPref) } - if (mSiteCount > maxSitesToShow && !showAll) { // append a "view all" option - appendViewAllSitesOption(context, getString(R.string.pref_notification_blogs), false); + appendViewAllSitesOption(context, getString(R.string.pref_notification_blogs), false) } - - updateSearchMenuVisibility(); + updateSearchMenuVisibility() } - private void configureFollowedBlogsSettings(@Nullable PreferenceCategory blogsCategory, final boolean showAll) { - if (!isAdded() || blogsCategory == null) { - return; + private fun configureFollowedBlogsSettings( + blogsCategory: PreferenceCategory?, + showAll: Boolean + ) { + if (!isAdded || blogsCategory == null) { + return } - - List models; - String query = ""; - - if (mSearchView != null && !TextUtils.isEmpty(mSearchView.getQuery())) { - query = mSearchView.getQuery().toString().trim(); - models = mFollowedBlogsProvider.getAllFollowedBlogs(query); + val models: List + var query = "" + if (mSearchView != null && !TextUtils.isEmpty(mSearchView!!.query)) { + query = mSearchView!!.query.toString().trim { it <= ' ' } + models = mFollowedBlogsProvider!!.getAllFollowedBlogs(query) } else { - models = mFollowedBlogsProvider.getAllFollowedBlogs(null); + models = mFollowedBlogsProvider!!.getAllFollowedBlogs(null) } - - Context context = getActivity(); - blogsCategory.removeAll(); - - int maxSitesToShow = showAll ? NO_MAXIMUM : MAX_SITES_TO_SHOW_ON_FIRST_SCREEN; - mSubscriptionCount = 0; - - if (models.size() > 0) { - Collections.sort(models, (o1, o2) -> o1.getTitle().compareToIgnoreCase(o2.getTitle())); + val context: Context? = activity + blogsCategory.removeAll() + val maxSitesToShow: Int = + if (showAll) NotificationsSettingsFragment.Companion.NO_MAXIMUM else NotificationsSettingsFragment.Companion.MAX_SITES_TO_SHOW_ON_FIRST_SCREEN + mSubscriptionCount = 0 + if (models.size > 0) { + Collections.sort(models) { (title): PreferenceModel, (title1): PreferenceModel -> + title.compareTo( + title1, ignoreCase = true + ) + } } - - for (final PreferenceModel preferenceModel : models) { + for ((title, summary, blogId, clickHandler) in models) { if (context == null) { - return; + return } - - mSubscriptionCount++; - + mSubscriptionCount++ if (!showAll && mSubscriptionCount > maxSitesToShow) { - break; + break } - - PreferenceScreen prefScreen = getPreferenceManager().createPreferenceScreen(context); - prefScreen.setTitle(preferenceModel.getTitle()); - prefScreen.setSummary(preferenceModel.getSummary()); - - ClickHandler clickHandler = preferenceModel.getClickHandler(); + val prefScreen = preferenceManager.createPreferenceScreen(context) + prefScreen.title = title + prefScreen.summary = summary if (clickHandler != null) { - prefScreen.setOnPreferenceClickListener(preference -> { - mNotificationUpdatedSite = preferenceModel.getBlogId(); - mPreviousNotifyPosts = clickHandler.getShouldNotifyPosts(); - mPreviousEmailPosts = clickHandler.getShouldEmailPosts(); - mPreviousEmailPostsFrequency = clickHandler.getEmailPostFrequency(); - mPreviousEmailComments = clickHandler.getShouldEmailComments(); - NotificationSettingsFollowedDialog dialog = new NotificationSettingsFollowedDialog(); - Bundle args = new Bundle(); - args.putBoolean(NotificationSettingsFollowedDialog.ARG_NOTIFICATION_POSTS, - mPreviousNotifyPosts); - args.putBoolean(NotificationSettingsFollowedDialog.ARG_EMAIL_POSTS, - mPreviousEmailPosts); - args.putString(NotificationSettingsFollowedDialog.ARG_EMAIL_POSTS_FREQUENCY, - mPreviousEmailPostsFrequency); - args.putBoolean(NotificationSettingsFollowedDialog.ARG_EMAIL_COMMENTS, - mPreviousEmailComments); - dialog.setArguments(args); - dialog.setTargetFragment(NotificationsSettingsFragment.this, NOTIFICATION_SETTINGS); - dialog.show(getChildFragmentManager(), NotificationSettingsFollowedDialog.TAG); - return true; - }); + prefScreen.onPreferenceClickListener = + Preference.OnPreferenceClickListener { preference: Preference? -> + mNotificationUpdatedSite = blogId + mPreviousNotifyPosts = clickHandler.shouldNotifyPosts + mPreviousEmailPosts = clickHandler.shouldEmailPosts + mPreviousEmailPostsFrequency = clickHandler.emailPostFrequency + mPreviousEmailComments = clickHandler.shouldEmailComments + val dialog = NotificationSettingsFollowedDialog() + val args = Bundle() + args.putBoolean( + NotificationSettingsFollowedDialog.ARG_NOTIFICATION_POSTS, + mPreviousNotifyPosts + ) + args.putBoolean( + NotificationSettingsFollowedDialog.ARG_EMAIL_POSTS, + mPreviousEmailPosts + ) + args.putString( + NotificationSettingsFollowedDialog.ARG_EMAIL_POSTS_FREQUENCY, + mPreviousEmailPostsFrequency + ) + args.putBoolean( + NotificationSettingsFollowedDialog.ARG_EMAIL_COMMENTS, + mPreviousEmailComments + ) + dialog.arguments = args + dialog.setTargetFragment( + this@NotificationsSettingsFragment, + RequestCodes.NOTIFICATION_SETTINGS + ) + dialog.show(childFragmentManager, NotificationSettingsFollowedDialog.TAG) + true + } } else { - prefScreen.setEnabled(false); + prefScreen.isEnabled = false } - - blogsCategory.addPreference(prefScreen); + blogsCategory.addPreference(prefScreen) } // Add message if there are no matching search results. if (mSubscriptionCount == 0 && !TextUtils.isEmpty(query)) { - Preference searchResultsPref = new Preference(context); - searchResultsPref.setSummary(String.format(getString(R.string.notifications_no_search_results), query)); - blogsCategory.addPreference(searchResultsPref); + val searchResultsPref = Preference(context) + searchResultsPref.summary = + String.format(getString(R.string.notifications_no_search_results), query) + blogsCategory.addPreference(searchResultsPref) } // Add view all entry when more sites than maximum to show. if (!showAll && mSubscriptionCount > maxSitesToShow) { - appendViewAllSitesOption(context, getString(R.string.pref_notification_blogs_followed), true); + appendViewAllSitesOption( + context, + getString(R.string.pref_notification_blogs_followed), + true + ) } - - updateSearchMenuVisibility(); + updateSearchMenuVisibility() } - private void appendViewAllSitesOption(Context context, String preference, boolean isFollowed) { - PreferenceCategory blogsCategory = (PreferenceCategory) findPreference(preference); - - PreferenceScreen prefScreen = getPreferenceManager().createPreferenceScreen(context); - prefScreen.setTitle(isFollowed ? R.string.notification_settings_item_your_sites_all_followed_sites - : R.string.notification_settings_item_your_sites_all_your_sites); - addSitesForViewAllSitesScreen(prefScreen, isFollowed); - blogsCategory.addPreference(prefScreen); + private fun appendViewAllSitesOption( + context: Context?, + preference: String, + isFollowed: Boolean + ) { + val blogsCategory = findPreference(preference) as PreferenceCategory + val prefScreen = preferenceManager.createPreferenceScreen(context) + prefScreen.setTitle(if (isFollowed) R.string.notification_settings_item_your_sites_all_followed_sites else R.string.notification_settings_item_your_sites_all_your_sites) + addSitesForViewAllSitesScreen(prefScreen, isFollowed) + blogsCategory.addPreference(prefScreen) } - private void updateSearchMenuVisibility() { + private fun updateSearchMenuVisibility() { // Show the search menu item in the toolbar if we have enough sites if (mSearchMenuItem != null) { - mSearchMenuItem.setVisible(mSiteCount > SITE_SEARCH_VISIBILITY_COUNT - || mSubscriptionCount > SITE_SEARCH_VISIBILITY_COUNT); + mSearchMenuItem!!.isVisible = + (mSiteCount > NotificationsSettingsFragment.Companion.SITE_SEARCH_VISIBILITY_COUNT + || mSubscriptionCount > NotificationsSettingsFragment.Companion.SITE_SEARCH_VISIBILITY_COUNT) } } - private void configureOtherSettings() { - PreferenceScreen otherBlogsScreen = (PreferenceScreen) findPreference( - getString(R.string.pref_notification_other_blogs)); - addPreferencesForPreferenceScreen(otherBlogsScreen, Channel.OTHER, 0); + private fun configureOtherSettings() { + val otherBlogsScreen = findPreference( + getString(R.string.pref_notification_other_blogs) + ) as PreferenceScreen + addPreferencesForPreferenceScreen(otherBlogsScreen, NotificationsSettings.Channel.OTHER, 0) } - private void configureWPComSettings() { - PreferenceCategory otherPreferenceCategory = (PreferenceCategory) findPreference( - getString(R.string.pref_notification_other_category)); - NotificationsSettingsDialogPreference devicePreference = new NotificationsSettingsDialogPreference( - getActivity(), null, Channel.WPCOM, NotificationsSettings.Type.DEVICE, 0, mNotificationsSettings, - mOnSettingsChangedListener - ); - devicePreference.setTitle(R.string.notification_settings_item_other_account_emails); - devicePreference.setDialogTitle(R.string.notification_settings_item_other_account_emails); - devicePreference.setSummary(R.string.notification_settings_item_other_account_emails_summary); - otherPreferenceCategory.addPreference(devicePreference); + private fun configureWPComSettings() { + val otherPreferenceCategory = findPreference( + getString(R.string.pref_notification_other_category) + ) as PreferenceCategory + val devicePreference = NotificationsSettingsDialogPreference( + activity, + null, + NotificationsSettings.Channel.WPCOM, + NotificationsSettings.Type.DEVICE, + 0, + mNotificationsSettings, + mOnSettingsChangedListener + ) + devicePreference.setTitle(R.string.notification_settings_item_other_account_emails) + devicePreference.setDialogTitle(R.string.notification_settings_item_other_account_emails) + devicePreference.setSummary(R.string.notification_settings_item_other_account_emails_summary) + otherPreferenceCategory.addPreference(devicePreference) } - private void addPreferencesForPreferenceScreen(PreferenceScreen preferenceScreen, Channel channel, long blogId) { - Context context = getActivity(); - if (context == null) { - return; - } - - PreferenceCategory rootCategory = new PreferenceCategory(context); - rootCategory.setTitle(R.string.notification_types); - preferenceScreen.addPreference(rootCategory); - - NotificationsSettingsDialogPreference timelinePreference = new NotificationsSettingsDialogPreference( - context, null, channel, NotificationsSettings.Type.TIMELINE, blogId, mNotificationsSettings, - mOnSettingsChangedListener - ); - - setPreferenceIcon(timelinePreference, R.drawable.ic_bell_white_24dp); - timelinePreference.setTitle(R.string.notifications_tab); - timelinePreference.setDialogTitle(R.string.notifications_tab); - timelinePreference.setSummary(R.string.notifications_tab_summary); - rootCategory.addPreference(timelinePreference); - - NotificationsSettingsDialogPreference emailPreference = new NotificationsSettingsDialogPreference( - context, null, channel, NotificationsSettings.Type.EMAIL, blogId, mNotificationsSettings, - mOnSettingsChangedListener - ); - - setPreferenceIcon(emailPreference, R.drawable.ic_mail_white_24dp); - emailPreference.setTitle(R.string.email); - emailPreference.setDialogTitle(R.string.email); - emailPreference.setSummary(R.string.notifications_email_summary); - rootCategory.addPreference(emailPreference); - - SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context); - String deviceID = settings.getString(NotificationsUtils.WPCOM_PUSH_DEVICE_SERVER_ID, null); + private fun addPreferencesForPreferenceScreen( + preferenceScreen: PreferenceScreen, + channel: NotificationsSettings.Channel, + blogId: Long + ) { + val context = activity ?: return + val rootCategory = PreferenceCategory(context) + rootCategory.setTitle(R.string.notification_types) + preferenceScreen.addPreference(rootCategory) + val timelinePreference = NotificationsSettingsDialogPreference( + context, + null, + channel, + NotificationsSettings.Type.TIMELINE, + blogId, + mNotificationsSettings, + mOnSettingsChangedListener + ) + setPreferenceIcon(timelinePreference, R.drawable.ic_bell_white_24dp) + timelinePreference.setTitle(R.string.notifications_tab) + timelinePreference.setDialogTitle(R.string.notifications_tab) + timelinePreference.setSummary(R.string.notifications_tab_summary) + rootCategory.addPreference(timelinePreference) + val emailPreference = NotificationsSettingsDialogPreference( + context, + null, + channel, + NotificationsSettings.Type.EMAIL, + blogId, + mNotificationsSettings, + mOnSettingsChangedListener + ) + setPreferenceIcon(emailPreference, R.drawable.ic_mail_white_24dp) + emailPreference.setTitle(R.string.email) + emailPreference.setDialogTitle(R.string.email) + emailPreference.setSummary(R.string.notifications_email_summary) + rootCategory.addPreference(emailPreference) + val settings = PreferenceManager.getDefaultSharedPreferences(context) + val deviceID = settings.getString(NotificationsUtils.WPCOM_PUSH_DEVICE_SERVER_ID, null) if (!TextUtils.isEmpty(deviceID)) { - NotificationsSettingsDialogPreference devicePreference = new NotificationsSettingsDialogPreference( - context, null, channel, NotificationsSettings.Type.DEVICE, blogId, mNotificationsSettings, - mOnSettingsChangedListener, mBloggingRemindersProvider - ); - setPreferenceIcon(devicePreference, R.drawable.ic_phone_white_24dp); - devicePreference.setTitle(R.string.app_notifications); - devicePreference.setDialogTitle(R.string.app_notifications); - devicePreference.setSummary(R.string.notifications_push_summary); - devicePreference.setEnabled(mNotificationsEnabled); - rootCategory.addPreference(devicePreference); + val devicePreference = NotificationsSettingsDialogPreference( + context, + null, + channel, + NotificationsSettings.Type.DEVICE, + blogId, + mNotificationsSettings, + mOnSettingsChangedListener, + mBloggingRemindersProvider + ) + setPreferenceIcon(devicePreference, R.drawable.ic_phone_white_24dp) + devicePreference.setTitle(R.string.app_notifications) + devicePreference.setDialogTitle(R.string.app_notifications) + devicePreference.setSummary(R.string.notifications_push_summary) + devicePreference.isEnabled = mNotificationsEnabled + rootCategory.addPreference(devicePreference) } - - mTypePreferenceCategories.add(rootCategory); + mTypePreferenceCategories.add(rootCategory) } - private void setPreferenceIcon(NotificationsSettingsDialogPreference preference, @DrawableRes int drawableRes) { - preference.setIcon(drawableRes); - preference.getIcon().setTintMode(Mode.SRC_IN); - preference.getIcon().setTintList(ContextExtensionsKt - .getColorStateListFromAttribute(preference.getContext(), R.attr.wpColorOnSurfaceMedium)); + private fun setPreferenceIcon( + preference: NotificationsSettingsDialogPreference, + @DrawableRes drawableRes: Int + ) { + preference.setIcon(drawableRes) + preference.icon.setTintMode(PorterDuff.Mode.SRC_IN) + preference.icon.setTintList(preference.context.getColorStateListFromAttribute(R.attr.wpColorOnSurfaceMedium)) } - private void addSitesForViewAllSitesScreen(PreferenceScreen preferenceScreen, boolean isFollowed) { - Context context = getActivity(); - if (context == null) { - return; - } - - PreferenceCategory rootCategory = new PreferenceCategory(context); - rootCategory.setTitle(isFollowed ? R.string.notification_settings_category_followed_sites - : R.string.notification_settings_category_your_sites); - preferenceScreen.addPreference(rootCategory); - + private fun addSitesForViewAllSitesScreen( + preferenceScreen: PreferenceScreen, + isFollowed: Boolean + ) { + val context = activity ?: return + val rootCategory = PreferenceCategory(context) + rootCategory.setTitle(if (isFollowed) R.string.notification_settings_category_followed_sites else R.string.notification_settings_category_your_sites) + preferenceScreen.addPreference(rootCategory) if (isFollowed) { - configureFollowedBlogsSettings(rootCategory, true); + configureFollowedBlogsSettings(rootCategory, true) } else { - configureBlogsSettings(rootCategory, true); + configureBlogsSettings(rootCategory, true) } } - private final NotificationsSettingsDialogPreference.OnNotificationsSettingsChangedListener - mOnSettingsChangedListener = - new NotificationsSettingsDialogPreference.OnNotificationsSettingsChangedListener() { - @SuppressWarnings("unchecked") - @Override - public void onSettingsChanged(Channel channel, NotificationsSettings.Type type, long blogId, - JSONObject newValues) { - if (!isAdded()) { - return; - } - - // Construct a new settings JSONObject to send back to WP.com - JSONObject settingsObject = new JSONObject(); - switch (channel) { - case BLOGS: - try { - JSONObject blogObject = new JSONObject(); - blogObject.put(NotificationsSettings.KEY_BLOG_ID, blogId); - - JSONArray blogsArray = new JSONArray(); - if (type == Type.DEVICE) { - newValues.put(NotificationsSettings.KEY_DEVICE_ID, Long.parseLong(mDeviceId)); - JSONArray devicesArray = new JSONArray(); - devicesArray.put(newValues); - blogObject.put(NotificationsSettings.KEY_DEVICES, devicesArray); - blogsArray.put(blogObject); - } else { - blogObject.put(type.toString(), newValues); - blogsArray.put(blogObject); - } - - settingsObject.put(NotificationsSettings.KEY_BLOGS, blogsArray); - } catch (JSONException e) { - AppLog.e(T.NOTIFS, "Could not build notification settings object"); - } - break; - case OTHER: - try { - JSONObject otherObject = new JSONObject(); - if (type == Type.DEVICE) { - newValues.put(NotificationsSettings.KEY_DEVICE_ID, Long.parseLong(mDeviceId)); - JSONArray devicesArray = new JSONArray(); - devicesArray.put(newValues); - otherObject.put(NotificationsSettings.KEY_DEVICES, devicesArray); - } else { - otherObject.put(type.toString(), newValues); - } + private val mOnSettingsChangedListener = + OnNotificationsSettingsChangedListener { channel, type, blogId, newValues -> + if (!isAdded) { + return@OnNotificationsSettingsChangedListener + } - settingsObject.put(NotificationsSettings.KEY_OTHER, otherObject); - } catch (JSONException e) { - AppLog.e(T.NOTIFS, "Could not build notification settings object"); - } - break; - case WPCOM: - try { - settingsObject.put(NotificationsSettings.KEY_WPCOM, newValues); - } catch (JSONException e) { - AppLog.e(T.NOTIFS, "Could not build notification settings object"); - } - break; + // Construct a new settings JSONObject to send back to WP.com + val settingsObject = JSONObject() + when (channel) { + NotificationsSettings.Channel.BLOGS -> try { + val blogObject = JSONObject() + blogObject.put(NotificationsSettings.KEY_BLOG_ID, blogId) + val blogsArray = JSONArray() + if (type == NotificationsSettings.Type.DEVICE) { + newValues.put(NotificationsSettings.KEY_DEVICE_ID, mDeviceId!!.toLong()) + val devicesArray = JSONArray() + devicesArray.put(newValues) + blogObject.put(NotificationsSettings.KEY_DEVICES, devicesArray) + blogsArray.put(blogObject) + } else { + blogObject.put(type.toString(), newValues) + blogsArray.put(blogObject) } + settingsObject.put(NotificationsSettings.KEY_BLOGS, blogsArray) + } catch (e: JSONException) { + AppLog.e(AppLog.T.NOTIFS, "Could not build notification settings object") + } - if (settingsObject.length() > 0) { - WordPress.getRestClientUtilsV1_1() - .post("/me/notifications/settings", settingsObject, null, null, null); + NotificationsSettings.Channel.OTHER -> try { + val otherObject = JSONObject() + if (type == NotificationsSettings.Type.DEVICE) { + newValues.put(NotificationsSettings.KEY_DEVICE_ID, mDeviceId!!.toLong()) + val devicesArray = JSONArray() + devicesArray.put(newValues) + otherObject.put(NotificationsSettings.KEY_DEVICES, devicesArray) + } else { + otherObject.put(type.toString(), newValues) } + settingsObject.put(NotificationsSettings.KEY_OTHER, otherObject) + } catch (e: JSONException) { + AppLog.e(AppLog.T.NOTIFS, "Could not build notification settings object") } - }; - @Override - public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, @NonNull Preference preference) { - super.onPreferenceTreeClick(preferenceScreen, preference); + NotificationsSettings.Channel.WPCOM -> try { + settingsObject.put(NotificationsSettings.KEY_WPCOM, newValues) + } catch (e: JSONException) { + AppLog.e(AppLog.T.NOTIFS, "Could not build notification settings object") + } + } + if (settingsObject.length() > 0) { + getRestClientUtilsV1_1() + .post("/me/notifications/settings", settingsObject, null, null, null) + } + } - if (preference instanceof PreferenceScreen) { - addToolbarToDialog(preference); - AnalyticsTracker.track(AnalyticsTracker.Stat.NOTIFICATION_SETTINGS_STREAMS_OPENED); + override fun onPreferenceTreeClick( + preferenceScreen: PreferenceScreen, + preference: Preference + ): Boolean { + super.onPreferenceTreeClick(preferenceScreen, preference) + if (preference is PreferenceScreen) { + addToolbarToDialog(preference) + AnalyticsTracker.track(Stat.NOTIFICATION_SETTINGS_STREAMS_OPENED) } else { - AnalyticsTracker.track(AnalyticsTracker.Stat.NOTIFICATION_SETTINGS_DETAILS_OPENED); + AnalyticsTracker.track(Stat.NOTIFICATION_SETTINGS_DETAILS_OPENED) } - - return false; + return false } - private void addToolbarToDialog(Preference preference) { - Dialog prefDialog = ((PreferenceScreen) preference).getDialog(); + private fun addToolbarToDialog(preference: Preference) { + val prefDialog = (preference as PreferenceScreen).dialog if (prefDialog != null) { - String title = String.valueOf(preference.getTitle()); - WPActivityUtils.addToolbarToDialog(this, prefDialog, title); + val title = preference.getTitle().toString() + WPActivityUtils.addToolbarToDialog(this, prefDialog, title) } } - @Override - public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { - if (key.equals(getString(R.string.pref_key_notification_pending_drafts))) { - if (getActivity() != null) { - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity()); - boolean shouldNotifyOfPendingDrafts = prefs.getBoolean("wp_pref_notification_pending_drafts", true); + override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String?) { + if (key == getString(R.string.pref_key_notification_pending_drafts)) { + if (activity != null) { + val prefs = PreferenceManager.getDefaultSharedPreferences( + activity + ) + val shouldNotifyOfPendingDrafts = + prefs.getBoolean("wp_pref_notification_pending_drafts", true) if (shouldNotifyOfPendingDrafts) { - AnalyticsTracker.track(AnalyticsTracker.Stat.NOTIFICATION_PENDING_DRAFTS_SETTINGS_ENABLED); + AnalyticsTracker.track(Stat.NOTIFICATION_PENDING_DRAFTS_SETTINGS_ENABLED) } else { - AnalyticsTracker.track(AnalyticsTracker.Stat.NOTIFICATION_PENDING_DRAFTS_SETTINGS_DISABLED); + AnalyticsTracker.track(Stat.NOTIFICATION_PENDING_DRAFTS_SETTINGS_DISABLED) } } - } else if (key.equals(getString(R.string.wp_pref_custom_notification_sound))) { - final String defaultPath = - getString(R.string.notification_settings_item_sights_and_sounds_choose_sound_default); - final String value = sharedPreferences.getString(key, defaultPath); - - if (value.trim().toLowerCase(Locale.ROOT).startsWith("file://")) { + } else if (key == getString(R.string.wp_pref_custom_notification_sound)) { + val defaultPath = + getString(R.string.notification_settings_item_sights_and_sounds_choose_sound_default) + val value = sharedPreferences.getString(key, defaultPath) + if (value!!.trim { it <= ' ' }.lowercase().startsWith("file://")) { // sound path begins with 'file://` which will lead to FileUriExposedException when used. Revert to // default and let the user know. - AppLog.w(T.NOTIFS, "Notification sound starts with unacceptable scheme: " + value); - - Context context = WordPress.getContext(); + AppLog.w( + AppLog.T.NOTIFS, + "Notification sound starts with unacceptable scheme: $value" + ) + val context = WordPress.getContext() if (context != null) { // let the user know we won't be using the selected sound - ToastUtils.showToast(context, R.string.notification_sound_has_invalid_path, Duration.LONG); + ToastUtils.showToast( + context, + R.string.notification_sound_has_invalid_path, + ToastUtils.Duration.LONG + ) } } } } - @Nullable - private AppCompatActivity getAppCompatActivity() { - final Activity activity = getActivity(); - if (activity instanceof AppCompatActivity) { - return (AppCompatActivity) activity; - } - return null; - } - - private final BloggingRemindersProvider mBloggingRemindersProvider = new BloggingRemindersProvider() { - @Override public String getSummary(long blogId) { - UiString uiString = mBloggingRemindersSummariesBySiteId.get(blogId); - return uiString != null ? mUiHelpers.getTextOfUiString(getContext(), uiString).toString() : null; + private val appCompatActivity: AppCompatActivity? + private get() { + val activity = activity + return if (activity is AppCompatActivity) { + activity + } else null } + private val mBloggingRemindersProvider: BloggingRemindersProvider = + object : BloggingRemindersProvider { + override fun getSummary(blogId: Long): String { + val uiString = mBloggingRemindersSummariesBySiteId[blogId] + return if (uiString != null) mUiHelpers!!.getTextOfUiString(context, uiString) + .toString() else null + } - @Override public void onClick(long blogId) { - mBloggingRemindersViewModel.onNotificationSettingsItemClicked(blogId); + override fun onClick(blogId: Long) { + mBloggingRemindersViewModel!!.onNotificationSettingsItemClicked(blogId) + } } - }; - private void initBloggingReminders() { - if (!isAdded()) { - return; + private fun initBloggingReminders() { + if (!isAdded) { + return } - - final AppCompatActivity appCompatActivity = getAppCompatActivity(); + val appCompatActivity = appCompatActivity if (appCompatActivity != null) { - mBloggingRemindersViewModel = new ViewModelProvider(appCompatActivity, mViewModelFactory) - .get(BloggingRemindersViewModel.class); - BloggingReminderUtils.observeBottomSheet( - mBloggingRemindersViewModel.isBottomSheetShowing(), + mBloggingRemindersViewModel = ViewModelProvider(appCompatActivity, mViewModelFactory) + .get(BloggingRemindersViewModel::class.java) + observeBottomSheet( + mBloggingRemindersViewModel!!.isBottomSheetShowing, + appCompatActivity, + NotificationsSettingsFragment.Companion.BLOGGING_REMINDERS_BOTTOM_SHEET_TAG + ) { appCompatActivity.supportFragmentManager } + mBloggingRemindersViewModel!!.notificationsSettingsUiState + .observe( appCompatActivity, - BLOGGING_REMINDERS_BOTTOM_SHEET_TAG, - appCompatActivity::getSupportFragmentManager - ); - - mBloggingRemindersViewModel.getNotificationsSettingsUiState() - .observe(appCompatActivity, mBloggingRemindersSummariesBySiteId::putAll); + Observer> { m: Map? -> + mBloggingRemindersSummariesBySiteId.putAll(m) + }) } } + + companion object { + private const val KEY_SEARCH_QUERY = "search_query" + private const val SITE_SEARCH_VISIBILITY_COUNT = 15 + + // The number of notification types we support (e.g. timeline, email, mobile) + private const val TYPE_COUNT = 3 + private const val NO_MAXIMUM = -1 + private const val MAX_SITES_TO_SHOW_ON_FIRST_SCREEN = 3 + private const val BLOGGING_REMINDERS_BOTTOM_SHEET_TAG = "blogging-reminders-dialog-tag" + } } From 763345569adf6304c4188b6342c2e605ee48bf43 Mon Sep 17 00:00:00 2001 From: Jasjeet Singh <98077881+07jasjeet@users.noreply.github.com> Date: Tue, 2 Jan 2024 21:15:05 +0530 Subject: [PATCH 04/14] Fixed AS auto-convert errors --- .../NotificationsSettingsFragment.kt | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsFragment.kt index 526e5216e9e5..fcf0cb41ab87 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsFragment.kt @@ -24,7 +24,6 @@ import androidx.annotation.StringRes import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.SearchView import androidx.core.view.ViewCompat -import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProvider import androidx.preference.PreferenceManager import com.wordpress.rest.RestRequest @@ -121,7 +120,7 @@ class NotificationsSettingsFragment : PreferenceFragment(), OnSharedPreferenceCh @JvmField @Inject - var mViewModelFactory: Factory? = null + var mViewModelFactory: ViewModelProvider.Factory? = null @JvmField @Inject @@ -258,7 +257,7 @@ class NotificationsSettingsFragment : PreferenceFragment(), OnSharedPreferenceCh override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { inflater.inflate(R.menu.notifications_settings, menu) mSearchMenuItem = menu.findItem(R.id.menu_notifications_settings_search) - mSearchView = mSearchMenuItem.getActionView() as SearchView? + mSearchView = mSearchMenuItem?.getActionView() as SearchView? mSearchView!!.queryHint = getString(R.string.search_sites) mBlogsCategory = findPreference( getString(R.string.pref_notification_blogs) @@ -282,7 +281,7 @@ class NotificationsSettingsFragment : PreferenceFragment(), OnSharedPreferenceCh return true } }) - mSearchMenuItem.setOnActionExpandListener(object : MenuItem.OnActionExpandListener { + mSearchMenuItem?.setOnActionExpandListener(object : MenuItem.OnActionExpandListener { override fun onMenuItemActionExpand(item: MenuItem): Boolean { mSearchMenuItemCollapsed = false configureBlogsSettings(mBlogsCategory, true) @@ -301,7 +300,7 @@ class NotificationsSettingsFragment : PreferenceFragment(), OnSharedPreferenceCh // Check for a restored search query (if device was rotated, etc) if (!TextUtils.isEmpty(mRestoredQuery)) { - mSearchMenuItem.expandActionView() + mSearchMenuItem?.expandActionView() mSearchView!!.setQuery(mRestoredQuery, true) } } @@ -1044,7 +1043,7 @@ class NotificationsSettingsFragment : PreferenceFragment(), OnSharedPreferenceCh } private val mBloggingRemindersProvider: BloggingRemindersProvider = object : BloggingRemindersProvider { - override fun getSummary(blogId: Long): String { + override fun getSummary(blogId: Long): String? { val uiString = mBloggingRemindersSummariesBySiteId[blogId] return if (uiString != null) mUiHelpers!!.getTextOfUiString(context, uiString) .toString() else null @@ -1061,7 +1060,7 @@ class NotificationsSettingsFragment : PreferenceFragment(), OnSharedPreferenceCh } val appCompatActivity = appCompatActivity if (appCompatActivity != null) { - mBloggingRemindersViewModel = ViewModelProvider(appCompatActivity, mViewModelFactory) + mBloggingRemindersViewModel = ViewModelProvider(appCompatActivity, mViewModelFactory!!) .get(BloggingRemindersViewModel::class.java) observeBottomSheet( mBloggingRemindersViewModel!!.isBottomSheetShowing, @@ -1069,11 +1068,9 @@ class NotificationsSettingsFragment : PreferenceFragment(), OnSharedPreferenceCh NotificationsSettingsFragment.Companion.BLOGGING_REMINDERS_BOTTOM_SHEET_TAG ) { appCompatActivity.supportFragmentManager } mBloggingRemindersViewModel!!.notificationsSettingsUiState - .observe( - appCompatActivity, - Observer> { m: Map? -> - mBloggingRemindersSummariesBySiteId.putAll(m) - }) + .observe(appCompatActivity) { map -> + mBloggingRemindersSummariesBySiteId.putAll(map) + } } } From c7cbb31524da9e3c9f07ac7264d3e442af7fde03 Mon Sep 17 00:00:00 2001 From: Jasjeet Singh <98077881+07jasjeet@users.noreply.github.com> Date: Thu, 11 Jan 2024 01:35:29 +0530 Subject: [PATCH 05/14] Migrated NotificationsSettingsDialogPreference Created AndroidX implementation of NotificationsSettingsDialogPreference.java --- .../NotificationsSettingsDialogFragment.kt | 378 ++++++++++++++++++ .../NotificationsSettingsDialogPreferenceX.kt | 18 + 2 files changed, 396 insertions(+) create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsDialogFragment.kt create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsDialogPreferenceX.kt diff --git a/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsDialogFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsDialogFragment.kt new file mode 100644 index 000000000000..6ac16fe64557 --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsDialogFragment.kt @@ -0,0 +1,378 @@ +package org.wordpress.android.ui.prefs.notifications + +import android.annotation.SuppressLint +import android.app.Dialog +import android.content.DialogInterface +import android.os.Bundle +import android.text.TextUtils +import android.view.View +import android.view.ViewGroup +import android.widget.CompoundButton +import android.widget.LinearLayout +import android.widget.ScrollView +import android.widget.TextView +import androidx.appcompat.app.ActionBar +import androidx.appcompat.app.AlertDialog +import androidx.appcompat.widget.SwitchCompat +import androidx.core.content.ContextCompat +import androidx.fragment.app.DialogFragment +import com.google.android.material.dialog.MaterialAlertDialogBuilder +import org.json.JSONException +import org.json.JSONObject +import org.wordpress.android.R +import org.wordpress.android.databinding.NotificationsSettingsSwitchBinding +import org.wordpress.android.models.NotificationsSettings +import org.wordpress.android.ui.prefs.AppPrefs +import org.wordpress.android.util.AppLog +import org.wordpress.android.util.JSONUtils +import org.wordpress.android.util.extensions.getDrawableFromAttribute + +class NotificationsSettingsDialogFragment( + private val channel: NotificationsSettings.Channel, + private val type: NotificationsSettings.Type, + private val blogId: Long = 0, + private val settings: NotificationsSettings, + private val onNotificationsSettingsChangedListener: NotificationsSettingsDialogPreference.OnNotificationsSettingsChangedListener, + private val bloggingRemindersProvider: NotificationsSettingsDialogPreference.BloggingRemindersProvider? = null, + private val title: String +): DialogFragment(), PrefMainSwitchToolbarView.MainSwitchToolbarListener, DialogInterface.OnClickListener { + companion object { + const val TAG = "Notifications_Settings_Dialog_Fragment" + private const val SETTING_VALUE_ACHIEVEMENT = "achievement" + } + + private val mUpdatedJson = JSONObject() + private var mTitleViewWithMainSwitch: ViewGroup? = null + + // view to display when main switch is on + private var mDisabledView: View? = null + + // view to display when main switch is off + private var mOptionsView: LinearLayout? = null + + private var mMainSwitchToolbarView: PrefMainSwitchToolbarView? = null + private val mShouldDisplayMainSwitch: Boolean = settings.shouldDisplayMainSwitch(channel, type) + + private var mSettingsArray = arrayOfNulls(0) + private var mSettingsValues: Array? = arrayOfNulls(0) + + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + val context = requireContext() + + @SuppressLint("InflateParams") + val layout = requireActivity().layoutInflater.inflate( + R.layout.notifications_settings_types_dialog, null) + val outerView = layout.findViewById(R.id.outer_view) + + outerView.layoutParams = LinearLayout.LayoutParams( + LinearLayout.LayoutParams.WRAP_CONTENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ) + val innerView = LinearLayout(context) + innerView.layoutParams = LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.MATCH_PARENT + ) + innerView.orientation = LinearLayout.VERTICAL + if (mShouldDisplayMainSwitch) { + val dividerView = View(context) + val dividerHeight = context.resources.getDimensionPixelSize( + R.dimen.notifications_settings_dialog_divider_height + ) + dividerView.background = context.getDrawableFromAttribute(android.R.attr.listDivider) + dividerView.layoutParams = ViewGroup.LayoutParams(ActionBar.LayoutParams.MATCH_PARENT, dividerHeight) + innerView.addView(dividerView) + } else { + val spacerView = View(context) + val spacerHeight = context.resources.getDimensionPixelSize(R.dimen.margin_medium) + spacerView.layoutParams = ViewGroup.LayoutParams(ActionBar.LayoutParams.MATCH_PARENT, spacerHeight) + innerView.addView(spacerView) + } + mDisabledView = View.inflate(context, R.layout.notifications_tab_disabled_text_layout, null) + mDisabledView?.layoutParams = ViewGroup.LayoutParams( + ActionBar.LayoutParams.MATCH_PARENT, + ActionBar.LayoutParams.WRAP_CONTENT + ) + mOptionsView = LinearLayout(context) + mOptionsView?.layoutParams = LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.MATCH_PARENT + ) + mOptionsView?.orientation = LinearLayout.VERTICAL + innerView.addView(mDisabledView) + innerView.addView(mOptionsView) + outerView.addView(innerView) + configureLayoutForView(mOptionsView!!) + + val builder: AlertDialog.Builder = MaterialAlertDialogBuilder(requireActivity()).apply { + setTitle(title) + setPositiveButton(android.R.string.ok, this@NotificationsSettingsDialogFragment) + setNegativeButton(R.string.cancel, this@NotificationsSettingsDialogFragment) + setView(layout) + } + + if (mShouldDisplayMainSwitch) { + setupTitleViewWithMainSwitch(outerView) + if (mTitleViewWithMainSwitch == null) { + AppLog.e(AppLog.T.NOTIFS, "Main switch enabled but layout not set") + } else { + builder.setCustomTitle(mTitleViewWithMainSwitch) + } + } + + return builder.create() + } + + private fun setupTitleViewWithMainSwitch(view: View) { + when (this.channel) { + NotificationsSettings.Channel.BLOGS -> if (this.type == NotificationsSettings.Type.TIMELINE) { + mTitleViewWithMainSwitch = layoutInflater + .inflate(R.layout.notifications_tab_for_blog_title_layout, view as ViewGroup, false) as ViewGroup + } + + NotificationsSettings.Channel.OTHER, NotificationsSettings.Channel.WPCOM -> {} + } + if (mTitleViewWithMainSwitch != null) { + val titleView = mTitleViewWithMainSwitch!!.findViewById(R.id.title) + titleView.text = title + mMainSwitchToolbarView = mTitleViewWithMainSwitch!!.findViewById(R.id.main_switch) + mMainSwitchToolbarView!!.setMainSwitchToolbarListener(this) + mMainSwitchToolbarView!! + .setBackgroundColor(ContextCompat.getColor(requireContext(), android.R.color.transparent)) + + // Main Switch initial state: + // On: If at least one of the settings options is on + // Off: If all settings options are off + val settingsJson = settings.getSettingsJsonForChannelAndType(channel, type, blogId) + val checkMainSwitch = settings.isAtLeastOneSettingsEnabled( + settingsJson, + mSettingsArray, + mSettingsValues + ) + mMainSwitchToolbarView!!.loadInitialState(checkMainSwitch) + hideDisabledView(mMainSwitchToolbarView!!.isMainChecked) + } + } + + override fun onClick(dialog: DialogInterface?, which: Int) { + if (which == DialogInterface.BUTTON_POSITIVE && mUpdatedJson.length() > 0) { + onNotificationsSettingsChangedListener.onSettingsChanged(this.channel, + this.type, this.blogId, mUpdatedJson) + + // Update the settings json + val keys: Iterator<*> = mUpdatedJson.keys() + while (keys.hasNext()) { + val settingName = keys.next() as String + settings.updateSettingForChannelAndType( + this.channel, this.type, settingName, + mUpdatedJson.optBoolean(settingName), this.blogId + ) + } + } + } + + private fun configureLayoutForView(view: LinearLayout): View { + val settingsJson = settings.getSettingsJsonForChannelAndType(this.channel, + this.type, this.blogId + ) + var summaryArray = arrayOfNulls(0) + when (this.channel) { + NotificationsSettings.Channel.BLOGS -> { + mSettingsArray = requireContext().resources.getStringArray(R.array.notifications_blog_settings) + mSettingsValues = requireContext().resources + .getStringArray(R.array.notifications_blog_settings_values) + } + + NotificationsSettings.Channel.OTHER -> { + mSettingsArray = requireContext().resources.getStringArray(R.array.notifications_other_settings) + mSettingsValues = requireContext().resources.getStringArray(R.array.notifications_other_settings_values) + } + + NotificationsSettings.Channel.WPCOM -> { + mSettingsArray = requireContext().resources.getStringArray(R.array.notifications_wpcom_settings) + mSettingsValues = requireContext().resources.getStringArray(R.array.notifications_wpcom_settings_values) + summaryArray = requireContext().resources.getStringArray(R.array.notifications_wpcom_settings_summaries) + } + } + val shouldShowLocalNotifications = + this.channel == NotificationsSettings.Channel.BLOGS && this.type == NotificationsSettings.Type.DEVICE + if (settingsJson != null && mSettingsArray.size == mSettingsValues!!.size) { + for (i in mSettingsArray.indices) { + val settingName = mSettingsArray[i]!! + val settingValue = mSettingsValues!![i]!! + + // Skip a few settings for 'Email' section + if (this.type == NotificationsSettings.Type.EMAIL && settingValue == SETTING_VALUE_ACHIEVEMENT) { + continue + } + + // Add special summary text for the WPCOM section + var settingSummary: String? = null + if (this.channel == NotificationsSettings.Channel.WPCOM && i < summaryArray.size) { + settingSummary = summaryArray[i] + } + val isSettingChecked = JSONUtils.queryJSON(settingsJson, settingValue, true) + val isSettingLast = !shouldShowLocalNotifications && i == mSettingsArray.size - 1 + view.addView( + setupSwitchSettingView( + settingName, settingValue, settingSummary, isSettingChecked, + isSettingLast, mOnCheckedChangedListener + ) + ) + } + } + if (shouldShowLocalNotifications) { + val isBloggingRemindersEnabled = this.bloggingRemindersProvider != null + addWeeklyRoundupSetting(view, !isBloggingRemindersEnabled) + if (isBloggingRemindersEnabled) { + addBloggingReminderSetting(view) + } + } + return view + } + + private fun addWeeklyRoundupSetting(view: LinearLayout, isLast: Boolean) { + view.addView(setupSwitchSettingView( + requireContext().getString(R.string.weekly_roundup), + null, + null, + AppPrefs.shouldShowWeeklyRoundupNotification(this.blogId), + isLast + ) { compoundButton: CompoundButton?, isChecked: Boolean -> + AppPrefs.setShouldShowWeeklyRoundupNotification( + this.blogId, + isChecked + ) + }) + } + + private fun addBloggingReminderSetting(view: LinearLayout) { + view.addView(setupClickSettingView( + requireContext().getString(R.string.site_settings_blogging_reminders_notification_title), + this.bloggingRemindersProvider?.getSummary(this.blogId), + true + ) { v: View? -> + this.bloggingRemindersProvider?.onClick(this.blogId) + requireDialog().dismiss() + }) + } + + private fun setupSwitchSettingView( + settingName: String, settingValue: String?, + settingSummary: String?, isSettingChecked: Boolean, + isSettingLast: Boolean, + onCheckedChangeListener: CompoundButton.OnCheckedChangeListener + ): View { + return setupSettingView( + settingName, settingValue, settingSummary, isSettingChecked, + isSettingLast, onCheckedChangeListener, null + ) + } + + private fun setupClickSettingView( + settingName: String, settingSummary: String?, isSettingLast: Boolean, + onClickListener: View.OnClickListener + ): View { + return setupSettingView( + settingName, null, settingSummary, false, + isSettingLast, null, onClickListener + ) + } + + private fun setupSettingView( + settingName: String, settingValue: String?, settingSummary: String?, + isSettingChecked: Boolean, isSettingLast: Boolean, + onCheckedChangeListener: CompoundButton.OnCheckedChangeListener?, + onClickListener: View.OnClickListener? + ): View { + NotificationsSettingsSwitchBinding.inflate(layoutInflater).apply { + notificationsSwitchTitle.text = settingName + if (!TextUtils.isEmpty(settingSummary)) { + notificationsSwitchSummary.visibility = View.VISIBLE + notificationsSwitchSummary.text = settingSummary + } + if (onCheckedChangeListener != null) { + notificationsSwitch.isChecked = isSettingChecked + notificationsSwitch.tag = settingValue + notificationsSwitch.setOnCheckedChangeListener(onCheckedChangeListener) + rowContainer.setOnClickListener { v -> notificationsSwitch.toggle() } + } else { + notificationsSwitch.visibility = View.GONE + } + if (onClickListener != null) { + rowContainer.setOnClickListener(onClickListener) + } + if (mShouldDisplayMainSwitch && isSettingLast) { + val divider: View = notificationsListDivider + val mlp = divider.layoutParams as ViewGroup.MarginLayoutParams + mlp.leftMargin = 0 + mlp.rightMargin = 0 + divider.layoutParams = mlp + } + return root + } + } + + private val mOnCheckedChangedListener = + CompoundButton.OnCheckedChangeListener { compoundButton, isChecked -> + try { + mUpdatedJson.put(compoundButton.tag.toString(), isChecked) + + // Switch off main switch if all current settings switches are off + if (mMainSwitchToolbarView != null && !isChecked + && areAllSettingsSwitchesUnchecked() + ) { + mMainSwitchToolbarView!!.setChecked(false) + } + } catch (e: JSONException) { + AppLog.e(AppLog.T.NOTIFS, "Could not add notification setting change to JSONObject") + } + } + + override fun onMainSwitchCheckedChanged(buttonView: CompoundButton?, isChecked: Boolean) { + setSettingsSwitchesChecked(isChecked) + hideDisabledView(isChecked) + } + + /** + * Hide view when Notifications Tab Settings are disabled by toggling the main switch off. + * + * @param isMainChecked TRUE to hide disabled view, FALSE to show disabled view + */ + private fun hideDisabledView(isMainChecked: Boolean) { + mDisabledView!!.visibility = if (isMainChecked) View.GONE else View.VISIBLE + mOptionsView!!.visibility = if (isMainChecked) View.VISIBLE else View.GONE + } + + /** + * Updates Notifications current settings switches state based on the main switch state + * + * @param isMainChecked TRUE to switch on the settings switches. + * FALSE to switch off the settings switches. + */ + private fun setSettingsSwitchesChecked(isMainChecked: Boolean) { + for (settingValue in mSettingsValues!!) { + val toggleSwitch = mOptionsView!!.findViewWithTag(settingValue) + if (toggleSwitch != null) { + toggleSwitch.isChecked = isMainChecked + } + } + } + + // returns true if all current settings switches on the dialog are unchecked + private fun areAllSettingsSwitchesUnchecked(): Boolean { + var settingsSwitchesUnchecked = true + for (settingValue in mSettingsValues!!) { + val toggleSwitch = mOptionsView!!.findViewWithTag(settingValue) + if (toggleSwitch != null) { + val isChecked = toggleSwitch.isChecked + if (isChecked) { + settingsSwitchesUnchecked = false + break + } + } + } + return settingsSwitchesUnchecked + } +} + diff --git a/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsDialogPreferenceX.kt b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsDialogPreferenceX.kt new file mode 100644 index 000000000000..48474d224c09 --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsDialogPreferenceX.kt @@ -0,0 +1,18 @@ +package org.wordpress.android.ui.prefs.notifications + +import android.content.Context +import android.util.AttributeSet +import androidx.annotation.StringRes +import androidx.preference.DialogPreference +import org.wordpress.android.models.NotificationsSettings +class NotificationsSettingsDialogPreferenceX( + context: Context, + attrs: AttributeSet?, + val channel: NotificationsSettings.Channel, + val type: NotificationsSettings.Type, + val blogId: Long, + val settings: NotificationsSettings, + val listener: NotificationsSettingsDialogPreference.OnNotificationsSettingsChangedListener, + val bloggingRemindersProvider: NotificationsSettingsDialogPreference.BloggingRemindersProvider? = null, + @StringRes val dialogTitleRes: Int +) : DialogPreference(context, attrs) From 9372604a8bc040dc63dc6a4e72c3cfa7d0439687 Mon Sep 17 00:00:00 2001 From: Jasjeet Singh <98077881+07jasjeet@users.noreply.github.com> Date: Thu, 11 Jan 2024 01:36:33 +0530 Subject: [PATCH 06/14] Created AndroidX implementation of WPSwitchPreference --- .../android/ui/prefs/WPSwitchPreference.java | 1 + .../android/ui/prefs/WPSwitchPreferenceX.kt | 109 ++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/prefs/WPSwitchPreferenceX.kt diff --git a/WordPress/src/main/java/org/wordpress/android/ui/prefs/WPSwitchPreference.java b/WordPress/src/main/java/org/wordpress/android/ui/prefs/WPSwitchPreference.java index fe43b25964fc..abe77d2cd604 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/prefs/WPSwitchPreference.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/prefs/WPSwitchPreference.java @@ -19,6 +19,7 @@ import org.wordpress.android.R; +/**@see WPSwitchPreferenceX*/ public class WPSwitchPreference extends SwitchPreference implements PreferenceHint { private String mHint; private ColorStateList mTint; diff --git a/WordPress/src/main/java/org/wordpress/android/ui/prefs/WPSwitchPreferenceX.kt b/WordPress/src/main/java/org/wordpress/android/ui/prefs/WPSwitchPreferenceX.kt new file mode 100644 index 000000000000..5a92d6109a01 --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/prefs/WPSwitchPreferenceX.kt @@ -0,0 +1,109 @@ +package org.wordpress.android.ui.prefs + +import android.annotation.SuppressLint +import android.content.Context +import android.content.res.ColorStateList +import android.text.TextUtils +import android.util.AttributeSet +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.Switch +import android.widget.TextView +import androidx.appcompat.content.res.AppCompatResources +import androidx.core.view.ViewCompat +import androidx.preference.PreferenceViewHolder +import androidx.preference.SwitchPreference +import org.wordpress.android.R + +/** AndroidX implementation of [WPSwitchPreference] + * @see WPSwitchPreference*/ +class WPSwitchPreferenceX(context: Context, attrs: AttributeSet?) : + SwitchPreference(context, attrs), PreferenceHint { + private var mHint: String? = null + private var mTint: ColorStateList? = null + private var mThumbTint: ColorStateList? = null + private var mStartOffset = 0 + + init { + val array = context.obtainStyledAttributes(attrs, R.styleable.SummaryEditTextPreference) + for (i in 0 until array.indexCount) { + val index = array.getIndex(i) + if (index == R.styleable.SummaryEditTextPreference_longClickHint) { + mHint = array.getString(index) + } else if (index == R.styleable.SummaryEditTextPreference_iconTint) { + val resourceId = array.getResourceId(index, 0) + if (resourceId != 0) { + mTint = AppCompatResources.getColorStateList(context, resourceId) + } + } else if (index == R.styleable.SummaryEditTextPreference_switchThumbTint) { + mThumbTint = array.getColorStateList(index) + } else if (index == R.styleable.SummaryEditTextPreference_startOffset) { + mStartOffset = array.getDimensionPixelSize(index, 0) + } + } + array.recycle() + } + + @SuppressLint("UseSwitchCompatOrMaterialCode") + override fun onBindViewHolder(holder: PreferenceViewHolder) { + super.onBindViewHolder(holder) + val view = holder.itemView + val icon = view.findViewById(android.R.id.icon) + if (icon != null && mTint != null) { + icon.imageTintList = mTint + } + val titleView = view.findViewById(android.R.id.title) + if (titleView != null) { + val res = context.resources + + // add padding to the start of nested preferences + if (!TextUtils.isEmpty(dependency)) { + val margin = res.getDimensionPixelSize(R.dimen.margin_large) + ViewCompat.setPaddingRelative(titleView, margin + mStartOffset, 0, 0, 0) + } else { + ViewCompat.setPaddingRelative(titleView, mStartOffset, 0, 0, 0) + } + } + + // style custom switch preference + val switchControl = getSwitch(view as ViewGroup) + if (switchControl != null) { + if (mThumbTint != null) { + switchControl.thumbTintList = mThumbTint + } + } + + // Add padding to start of switch. + ViewCompat.setPaddingRelative( + getSwitch(view)!!, + context.resources.getDimensionPixelSize(R.dimen.margin_extra_large), 0, 0, 0 + ) + } + @SuppressLint("UseSwitchCompatOrMaterialCode") + private fun getSwitch(parentView: ViewGroup): Switch? { + for (i in 0 until parentView.childCount) { + val childView = parentView.getChildAt(i) + if (childView is Switch) { + return childView + } else if (childView is ViewGroup) { + val theSwitch = getSwitch(childView) + if (theSwitch != null) { + return theSwitch + } + } + } + return null + } + + override fun hasHint(): Boolean { + return !TextUtils.isEmpty(mHint) + } + + override fun getHint(): String { + return mHint!! + } + + override fun setHint(hint: String) { + mHint = hint + } +} From d9e40e2ebc0d2de28fae8787b1d721b2d49cdba4 Mon Sep 17 00:00:00 2001 From: Jasjeet Singh <98077881+07jasjeet@users.noreply.github.com> Date: Thu, 11 Jan 2024 01:38:35 +0530 Subject: [PATCH 07/14] Updated Notification Settings Preference Layout 1) Ringtone preference is deprecated. 2) WPSwitchPreference replaced with AndroidX implementation. --- WordPress/src/main/res/xml/notifications_settings.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/WordPress/src/main/res/xml/notifications_settings.xml b/WordPress/src/main/res/xml/notifications_settings.xml index caa42ec5917e..22b530c439d3 100644 --- a/WordPress/src/main/res/xml/notifications_settings.xml +++ b/WordPress/src/main/res/xml/notifications_settings.xml @@ -19,7 +19,7 @@ android:key="@string/pref_notification_other_blogs" android:title="@string/notification_settings_item_other_comments_other_blogs" /> - @@ -30,19 +30,19 @@ android:key="@string/pref_notification_sights_sounds" android:title="@string/notification_settings_category_sights_and_sounds"> - - - From 7bd1a5f84944805dcbc1f43ad610c6191b38321c Mon Sep 17 00:00:00 2001 From: Jasjeet Singh <98077881+07jasjeet@users.noreply.github.com> Date: Thu, 11 Jan 2024 01:39:43 +0530 Subject: [PATCH 08/14] Migrated NotificationSettingsFollowedDialog to AndroidX --- .../NotificationSettingsFollowedDialog.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationSettingsFollowedDialog.java b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationSettingsFollowedDialog.java index 40fe0e268902..4ac719671bd8 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationSettingsFollowedDialog.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationSettingsFollowedDialog.java @@ -3,7 +3,6 @@ import android.annotation.SuppressLint; import android.app.Activity; import android.app.Dialog; -import android.app.DialogFragment; import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; @@ -15,6 +14,8 @@ import androidx.appcompat.app.AlertDialog; import androidx.appcompat.widget.SwitchCompat; +import androidx.fragment.app.DialogFragment; +import androidx.fragment.app.Fragment; import com.google.android.material.dialog.MaterialAlertDialogBuilder; @@ -52,7 +53,7 @@ public class NotificationSettingsFollowedDialog extends DialogFragment implement @Override public Dialog onCreateDialog(Bundle savedInstanceState) { - LayoutInflater inflater = getActivity().getLayoutInflater(); + LayoutInflater inflater = requireActivity().getLayoutInflater(); @SuppressLint("InflateParams") View layout = inflater.inflate(R.layout.followed_sites_dialog, null); @@ -88,7 +89,7 @@ public Dialog onCreateDialog(Bundle savedInstanceState) { } } - AlertDialog.Builder builder = new MaterialAlertDialogBuilder(getActivity()); + AlertDialog.Builder builder = new MaterialAlertDialogBuilder(requireActivity()); builder.setTitle(getString(R.string.notification_settings_followed_dialog_title)); builder.setPositiveButton(android.R.string.ok, this); builder.setNegativeButton(R.string.cancel, this); @@ -122,10 +123,7 @@ public void onClick(DialogInterface dialog, int which) { @Override public void onDismiss(DialogInterface dialog) { - // TODO: android.app.Fragment is deprecated since Android P. - // Needs to be replaced with android.support.v4.app.Fragment - // See https://developer.android.com/reference/android/app/Fragment - android.app.Fragment target = getTargetFragment(); + Fragment target = getTargetFragment(); if (target != null) { target.onActivityResult(getTargetRequestCode(), Activity.RESULT_OK, getResultIntent()); From d2d3cb1366651d35ab8e0aba5416f8054bd78937 Mon Sep 17 00:00:00 2001 From: Jasjeet Singh <98077881+07jasjeet@users.noreply.github.com> Date: Thu, 11 Jan 2024 01:51:58 +0530 Subject: [PATCH 09/14] Created NotificationsTypes fragment 1) Why? -> androidx.preference does not support addition of Child Preference Screens programtically no longer. Reference: https://stackoverflow.com/questions/60029806/why-does-the-nested-preferencescreen-not-open-when-using-androidx (Cites documentation as proof of result) 2) Why `ChildNotificationSettingsFragment`? -> To automatically change toolbar's state. 3) Why Change `NotificationsSettingsActivity`? -> The new androidx implementation requires the use of `PreferenceFragmentCompat` and to navigate to child preference screens, we need the parent activity to implement `PreferenceFragmentCompat.OnPreferenceStartFragmentCallback` --- .../ChildNotificationSettingsFragment.kt | 37 +++ .../NotificationsSettingsActivity.kt | 40 ++- .../NotificationsSettingsTypesFragment.kt | 262 ++++++++++++++++++ .../notifications_settings_activity.xml | 5 +- .../notifications_settings_types_dialog.xml | 11 + .../res/xml/notification_settings_types.xml | 4 + 6 files changed, 351 insertions(+), 8 deletions(-) create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/ChildNotificationSettingsFragment.kt create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsTypesFragment.kt create mode 100644 WordPress/src/main/res/layout/notifications_settings_types_dialog.xml create mode 100644 WordPress/src/main/res/xml/notification_settings_types.xml diff --git a/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/ChildNotificationSettingsFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/ChildNotificationSettingsFragment.kt new file mode 100644 index 000000000000..43d6c16be22b --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/ChildNotificationSettingsFragment.kt @@ -0,0 +1,37 @@ +package org.wordpress.android.ui.prefs.notifications + +import android.os.Bundle +import android.view.Gravity +import android.view.View +import androidx.preference.PreferenceFragmentCompat +import androidx.transition.Slide +import androidx.transition.Transition +import androidx.transition.TransitionManager +import com.google.android.material.appbar.AppBarLayout +import org.wordpress.android.R + +/** Child Notification fragments should inherit from this class in order to make navigation consistent.*/ +abstract class ChildNotificationSettingsFragment: PreferenceFragmentCompat() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setMainSwitchVisibility(View.GONE) + } + + override fun onDestroy() { + super.onDestroy() + setMainSwitchVisibility(View.VISIBLE) + } + + private fun setMainSwitchVisibility(visibility: Int) { + with(requireActivity()) { + val mainSwitchToolBarView = findViewById(R.id.main_switch) + val rootView = findViewById(R.id.app_bar_layout) + val transition: Transition = Slide(Gravity.TOP) + transition.duration = 200 + transition.addTarget(R.id.main_switch) + + TransitionManager.beginDelayedTransition(rootView, transition) + mainSwitchToolBarView.visibility = visibility + } + } +} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsActivity.kt index 32a4f5910436..8957701207a4 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsActivity.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsActivity.kt @@ -8,6 +8,9 @@ import android.widget.CompoundButton import android.widget.LinearLayout import android.widget.TextView import androidx.appcompat.widget.Toolbar +import androidx.fragment.app.commit +import androidx.preference.Preference +import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceManager import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.CoroutineScope @@ -29,7 +32,8 @@ import javax.inject.Named import android.R as AndroidR @AndroidEntryPoint -class NotificationsSettingsActivity : LocaleAwareActivity(), MainSwitchToolbarListener { +class NotificationsSettingsActivity : LocaleAwareActivity(), + MainSwitchToolbarListener, PreferenceFragmentCompat.OnPreferenceStartFragmentCallback { @Inject lateinit var updateNotificationSettingsUseCase: UpdateNotificationSettingsUseCase @@ -52,10 +56,9 @@ class NotificationsSettingsActivity : LocaleAwareActivity(), MainSwitchToolbarLi setUpMainSwitch() if (savedInstanceState == null) { - @Suppress("DEPRECATION") - fragmentManager.beginTransaction() - .add(R.id.fragment_container, NotificationsSettingsFragment()) - .commit() + supportFragmentManager.commit { + add(R.id.fragment_container, NotificationsSettingsFragment()) + } } messageContainer = findViewById(R.id.notifications_settings_message_container) @@ -82,6 +85,33 @@ class NotificationsSettingsActivity : LocaleAwareActivity(), MainSwitchToolbarLi return super.onOptionsItemSelected(item) } + @Suppress("DEPRECATION") + override fun onPreferenceStartFragment(caller: PreferenceFragmentCompat, pref: Preference): Boolean { + val args = pref.extras + val fragment = supportFragmentManager.fragmentFactory.instantiate( + classLoader, + pref.fragment!! + ) + + val titleView = findViewById(R.id.toolbar_title) + titleView.text = pref.title + + fragment.arguments = args + fragment.setTargetFragment(caller, 0) + // Replace the existing Fragment with the new Fragment. + supportFragmentManager.commit { + setCustomAnimations( + R.anim.fade_in, + R.anim.fade_out, + R.anim.fade_in, + R.anim.fade_out, + ) + replace(R.id.fragment_container, fragment) + addToBackStack(null) + } + return true + } + @Subscribe(threadMode = MAIN) fun onEventMainThread(event: NotificationsSettingsStatusChanged) { if (TextUtils.isEmpty(event.message)) { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsTypesFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsTypesFragment.kt new file mode 100644 index 000000000000..a1d5073668c0 --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsTypesFragment.kt @@ -0,0 +1,262 @@ +package org.wordpress.android.ui.prefs.notifications + +import android.graphics.PorterDuff +import android.os.Bundle +import android.text.TextUtils +import android.view.View +import androidx.annotation.DrawableRes +import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.ViewModelProvider +import androidx.preference.Preference +import androidx.preference.PreferenceCategory +import androidx.preference.PreferenceManager +import org.json.JSONArray +import org.json.JSONException +import org.json.JSONObject +import org.wordpress.android.R +import org.wordpress.android.WordPress +import org.wordpress.android.models.NotificationsSettings +import org.wordpress.android.ui.RequestCodes +import org.wordpress.android.ui.bloggingreminders.BloggingReminderUtils +import org.wordpress.android.ui.bloggingreminders.BloggingRemindersViewModel +import org.wordpress.android.ui.notifications.utils.NotificationsUtils +import org.wordpress.android.ui.utils.UiHelpers +import org.wordpress.android.ui.utils.UiString +import org.wordpress.android.util.AppLog +import org.wordpress.android.util.extensions.getColorStateListFromAttribute +import javax.inject.Inject + +class NotificationsSettingsTypesFragment: ChildNotificationSettingsFragment() { + companion object { + const val ARG_BLOG_ID = "ARG_BLOG_ID" + const val ARG_NOTIFICATION_CHANNEL = "ARG_NOTIFICATION_CHANNEL" + const val ARG_NOTIFICATIONS_ENABLED = "ARG_NOTIFICATIONS_ENABLED" + + private const val BLOGGING_REMINDERS_BOTTOM_SHEET_TAG = "blogging-reminders-dialog-tag" + } + + @Inject + lateinit var mViewModelFactory: ViewModelProvider.Factory + + @Inject + lateinit var mUiHelpers: UiHelpers + + private var mDeviceId: String? = null + private var mNotificationsSettings: NotificationsSettings? = null + private var mNotificationsEnabled: Boolean = false + private var mBloggingRemindersViewModel: BloggingRemindersViewModel? = null + private val mBloggingRemindersSummariesBySiteId: MutableMap = HashMap() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + (requireActivity().application as WordPress).component().inject(this) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + initBloggingReminders() + } + + override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { + setPreferencesFromResource(R.xml.notification_settings_types, rootKey) + + loadNotificationsSettings() + + val settings = PreferenceManager.getDefaultSharedPreferences(requireActivity()) + mDeviceId = settings.getString(NotificationsUtils.WPCOM_PUSH_DEVICE_SERVER_ID, "") + + val blogId: Long + val channel: NotificationsSettings.Channel + requireArguments().apply { + blogId = getLong(ARG_BLOG_ID) + channel = NotificationsSettings.Channel.toNotificationChannel(getInt(ARG_NOTIFICATION_CHANNEL)) + mNotificationsEnabled = getBoolean(ARG_NOTIFICATIONS_ENABLED) + } + + val context = requireContext() + val category = PreferenceCategory(context) + category.setTitle(R.string.notification_types) + preferenceScreen.addPreference(category) + + val timelinePreference = NotificationsSettingsDialogPreferenceX( + context = context, attrs = null, channel = channel, type = NotificationsSettings.Type.TIMELINE, + blogId = blogId, settings = mNotificationsSettings!!, listener = mOnSettingsChangedListener, + dialogTitleRes = R.string.notifications_tab + ).apply { + setPreferenceIcon(R.drawable.ic_bell_white_24dp) + setTitle(R.string.notifications_tab) + setSummary(R.string.notifications_tab_summary) + key = getString(R.string.notifications_tab) + } + category.addPreference(timelinePreference) + + val emailPreference = NotificationsSettingsDialogPreferenceX( + context = context, attrs = null, channel = channel, type = NotificationsSettings.Type.EMAIL, + blogId = blogId, settings = mNotificationsSettings!!, listener = mOnSettingsChangedListener, + dialogTitleRes = R.string.email + ).apply { + setPreferenceIcon(R.drawable.ic_mail_white_24dp) + setTitle(R.string.email) + setSummary(R.string.notifications_email_summary) + key = getString(R.string.email) + } + category.addPreference(emailPreference) + + if (!TextUtils.isEmpty(mDeviceId)) { + val devicePreference = NotificationsSettingsDialogPreferenceX( + context = context, attrs = null, channel = channel, type = NotificationsSettings.Type.DEVICE, + blogId = blogId, settings = mNotificationsSettings!!, listener = mOnSettingsChangedListener, + bloggingRemindersProvider = mBloggingRemindersProvider, dialogTitleRes = R.string.app_notifications + ).apply { + setPreferenceIcon(R.drawable.ic_phone_white_24dp) + setTitle(R.string.app_notifications) + setSummary(R.string.notifications_push_summary) + key = getString(R.string.app_notifications) + isEnabled = mNotificationsEnabled + } + category.addPreference(devicePreference) + } + } + + @Suppress("DEPRECATION", "Warnings") + override fun onDisplayPreferenceDialog(preference: Preference) { + if (preference is NotificationsSettingsDialogPreferenceX) { + if (parentFragmentManager.findFragmentByTag(NotificationsSettingsDialogFragment.TAG) != null) { + return + } + + with(preference) { + NotificationsSettingsDialogFragment( + channel = channel, + type = type, + blogId = blogId, + settings = settings, + onNotificationsSettingsChangedListener = listener, + bloggingRemindersProvider = bloggingRemindersProvider, + title = context.getString(dialogTitleRes) + ).apply { + setTargetFragment( + this@NotificationsSettingsTypesFragment, + RequestCodes.NOTIFICATION_SETTINGS + ) + }.show( + parentFragmentManager, + NotificationsSettingsDialogFragment.TAG + ) + } + } else { + super.onDisplayPreferenceDialog(preference) + } + } + + private val mOnSettingsChangedListener = + NotificationsSettingsDialogPreference.OnNotificationsSettingsChangedListener { channel, type, blogId, newValues -> + if (!isAdded) { + return@OnNotificationsSettingsChangedListener + } + + // Construct a new settings JSONObject to send back to WP.com + val settingsObject = JSONObject() + when (channel!!) { + NotificationsSettings.Channel.BLOGS -> try { + val blogObject = JSONObject() + blogObject.put(NotificationsSettings.KEY_BLOG_ID, blogId) + val blogsArray = JSONArray() + if (type == NotificationsSettings.Type.DEVICE) { + newValues.put(NotificationsSettings.KEY_DEVICE_ID, mDeviceId!!.toLong()) + val devicesArray = JSONArray() + devicesArray.put(newValues) + blogObject.put(NotificationsSettings.KEY_DEVICES, devicesArray) + blogsArray.put(blogObject) + } else { + blogObject.put(type.toString(), newValues) + blogsArray.put(blogObject) + } + settingsObject.put(NotificationsSettings.KEY_BLOGS, blogsArray) + } catch (e: JSONException) { + AppLog.e(AppLog.T.NOTIFS, "Could not build notification settings object") + } + + NotificationsSettings.Channel.OTHER -> try { + val otherObject = JSONObject() + if (type == NotificationsSettings.Type.DEVICE) { + newValues.put(NotificationsSettings.KEY_DEVICE_ID, mDeviceId!!.toLong()) + val devicesArray = JSONArray() + devicesArray.put(newValues) + otherObject.put(NotificationsSettings.KEY_DEVICES, devicesArray) + } else { + otherObject.put(type.toString(), newValues) + } + settingsObject.put(NotificationsSettings.KEY_OTHER, otherObject) + } catch (e: JSONException) { + AppLog.e(AppLog.T.NOTIFS, "Could not build notification settings object") + } + + NotificationsSettings.Channel.WPCOM -> try { + settingsObject.put(NotificationsSettings.KEY_WPCOM, newValues) + } catch (e: JSONException) { + AppLog.e(AppLog.T.NOTIFS, "Could not build notification settings object") + } + } + if (settingsObject.length() > 0) { + WordPress.getRestClientUtilsV1_1() + .post("/me/notifications/settings", settingsObject, null, null, null) + } + } + + private val mBloggingRemindersProvider: NotificationsSettingsDialogPreference.BloggingRemindersProvider = object : + NotificationsSettingsDialogPreference.BloggingRemindersProvider { + override fun getSummary(blogId: Long): String? { + val uiString = mBloggingRemindersSummariesBySiteId[blogId] + return if (uiString != null) mUiHelpers.getTextOfUiString(requireContext(), uiString).toString() else null + } + + override fun onClick(blogId: Long) { + mBloggingRemindersViewModel!!.onNotificationSettingsItemClicked(blogId) + } + } + + private fun initBloggingReminders() { + if (!isAdded) { + return + } + (activity as AppCompatActivity?)?.let { activity -> + mBloggingRemindersViewModel = ViewModelProvider( + activity, + mViewModelFactory + )[BloggingRemindersViewModel::class.java] + BloggingReminderUtils.observeBottomSheet( + mBloggingRemindersViewModel!!.isBottomSheetShowing, + activity, + BLOGGING_REMINDERS_BOTTOM_SHEET_TAG + ) { activity.supportFragmentManager } + mBloggingRemindersViewModel!!.notificationsSettingsUiState + .observe(activity) { map -> + mBloggingRemindersSummariesBySiteId.putAll(map) + } + } + } + + private fun loadNotificationsSettings() { + val settingsJson: JSONObject = try { + val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireActivity()) + JSONObject( + sharedPreferences.getString(NotificationsUtils.WPCOM_PUSH_DEVICE_NOTIFICATION_SETTINGS, "")!! + ) + } catch (e: JSONException) { + AppLog.e(AppLog.T.NOTIFS, "Could not parse notifications settings JSON") + return + } + if (mNotificationsSettings == null) { + mNotificationsSettings = NotificationsSettings(settingsJson) + } else { + mNotificationsSettings!!.updateJson(settingsJson) + } + } + + private fun NotificationsSettingsDialogPreferenceX.setPreferenceIcon(@DrawableRes drawableRes: Int) { + setIcon(drawableRes) + icon?.setTintMode(PorterDuff.Mode.SRC_IN) + icon?.setTintList(context.getColorStateListFromAttribute(R.attr.wpColorOnSurfaceMedium)) + } +} diff --git a/WordPress/src/main/res/layout/notifications_settings_activity.xml b/WordPress/src/main/res/layout/notifications_settings_activity.xml index 1f7978403be7..d041fdb99886 100644 --- a/WordPress/src/main/res/layout/notifications_settings_activity.xml +++ b/WordPress/src/main/res/layout/notifications_settings_activity.xml @@ -10,6 +10,7 @@ @@ -28,6 +29,7 @@ app:theme="@style/WordPress.ActionBar"> - - + + + + diff --git a/WordPress/src/main/res/xml/notification_settings_types.xml b/WordPress/src/main/res/xml/notification_settings_types.xml new file mode 100644 index 000000000000..7bf2aa65d884 --- /dev/null +++ b/WordPress/src/main/res/xml/notification_settings_types.xml @@ -0,0 +1,4 @@ + + + + From a61466b30d9b11e6dd010a976ac30b4417413d32 Mon Sep 17 00:00:00 2001 From: Jasjeet Singh <98077881+07jasjeet@users.noreply.github.com> Date: Thu, 11 Jan 2024 01:57:50 +0530 Subject: [PATCH 10/14] Child My Sites Fragment Implemented 1) Why? -> androidx.preference does not support addition of Child Preference Screens programtically no longer. Reference: https://stackoverflow.com/questions/60029806/why-does-the-nested-preferencescreen-not-open-when-using-androidx (Cites documentation as proof of result) 2) Why `NotificationsMySitesSettingsFragment` interface? -> So, both `NotifcationsSettingsFragment` and a child preference screen deal with changes in settings for followed blogs/my sites. To separate out common code and give a form of abstraction to the purpose, this interface was implemented. --- .../NotificationsMySitesSettingsFragment.kt | 118 ++++++++++ .../NotificationsSettingsMySitesFragment.kt | 215 ++++++++++++++++++ .../xml/notification_settings_my_sites.xml | 4 + 3 files changed, 337 insertions(+) create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsMySitesSettingsFragment.kt create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsMySitesFragment.kt create mode 100644 WordPress/src/main/res/xml/notification_settings_my_sites.xml diff --git a/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsMySitesSettingsFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsMySitesSettingsFragment.kt new file mode 100644 index 000000000000..80eff22f69fb --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsMySitesSettingsFragment.kt @@ -0,0 +1,118 @@ +package org.wordpress.android.ui.prefs.notifications + +import android.content.Intent +import org.wordpress.android.analytics.AnalyticsTracker +import org.wordpress.android.datasets.ReaderBlogTable +import org.wordpress.android.fluxc.Dispatcher +import org.wordpress.android.fluxc.generated.AccountActionBuilder +import org.wordpress.android.fluxc.store.AccountStore + +/** Any notification preference fragment that deals with **My Sites** or **My Followed Sites** + * should implement this interface.*/ +interface NotificationsMySitesSettingsFragment { + var mNotificationUpdatedSite: String? + var mPreviousEmailComments: Boolean + var mPreviousEmailPosts: Boolean + var mPreviousNotifyPosts: Boolean + var mUpdateEmailPostsFirst: Boolean + var mPreviousEmailPostsFrequency: String? + var mUpdateSubscriptionFrequencyPayload: AccountStore.UpdateSubscriptionPayload? + var mDispatcher: Dispatcher + + fun onMySiteSettingsChanged(data: Intent?) { + if (data == null) + return + + val notifyPosts = data.getBooleanExtra(NotificationSettingsFollowedDialog.KEY_NOTIFICATION_POSTS, false) + val emailPosts = data.getBooleanExtra(NotificationSettingsFollowedDialog.KEY_EMAIL_POSTS, false) + val emailPostsFrequency = data.getStringExtra(NotificationSettingsFollowedDialog.KEY_EMAIL_POSTS_FREQUENCY) + val emailComments = data.getBooleanExtra(NotificationSettingsFollowedDialog.KEY_EMAIL_COMMENTS, false) + if (notifyPosts != mPreviousNotifyPosts) { + ReaderBlogTable.setNotificationsEnabledByBlogId(mNotificationUpdatedSite!!.toLong(), notifyPosts) + val payload: AccountStore.AddOrDeleteSubscriptionPayload = if (notifyPosts) { + AnalyticsTracker.track(AnalyticsTracker.Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_ON) + AccountStore.AddOrDeleteSubscriptionPayload( + mNotificationUpdatedSite!!, + AccountStore.AddOrDeleteSubscriptionPayload.SubscriptionAction.NEW + ) + } else { + AnalyticsTracker.track(AnalyticsTracker.Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_OFF) + AccountStore.AddOrDeleteSubscriptionPayload( + mNotificationUpdatedSite!!, + AccountStore.AddOrDeleteSubscriptionPayload.SubscriptionAction.DELETE + ) + } + mDispatcher.dispatch(AccountActionBuilder.newUpdateSubscriptionNotificationPostAction(payload)) + } + if (emailPosts != mPreviousEmailPosts) { + val payload: AccountStore.AddOrDeleteSubscriptionPayload = if (emailPosts) { + AnalyticsTracker.track(AnalyticsTracker.Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_EMAIL_ON) + AccountStore.AddOrDeleteSubscriptionPayload( + mNotificationUpdatedSite!!, + AccountStore.AddOrDeleteSubscriptionPayload.SubscriptionAction.NEW + ) + } else { + AnalyticsTracker.track(AnalyticsTracker.Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_EMAIL_OFF) + AccountStore.AddOrDeleteSubscriptionPayload( + mNotificationUpdatedSite!!, + AccountStore.AddOrDeleteSubscriptionPayload.SubscriptionAction.DELETE + ) + } + mDispatcher.dispatch(AccountActionBuilder.newUpdateSubscriptionEmailPostAction(payload)) + } + if (emailPostsFrequency != null && !emailPostsFrequency.equals( + mPreviousEmailPostsFrequency, + ignoreCase = true + ) + ) { + val subscriptionFrequency = getSubscriptionFrequencyFromString(emailPostsFrequency) + mUpdateSubscriptionFrequencyPayload = AccountStore.UpdateSubscriptionPayload( + mNotificationUpdatedSite!!, + subscriptionFrequency + ) + /* + * The email post frequency update will be overridden by the email post update if the email post + * frequency callback returns first. Thus, the updates must be dispatched sequentially when the + * email post update is switched from disabled to enabled. + */ + if (emailPosts != mPreviousEmailPosts && emailPosts) { + mUpdateEmailPostsFirst = true + } else { + mDispatcher.dispatch( + AccountActionBuilder.newUpdateSubscriptionEmailPostFrequencyAction( + mUpdateSubscriptionFrequencyPayload + ) + ) + } + } + if (emailComments != mPreviousEmailComments) { + val payload: AccountStore.AddOrDeleteSubscriptionPayload = if (emailComments) { + AnalyticsTracker.track(AnalyticsTracker.Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_COMMENTS_ON) + AccountStore.AddOrDeleteSubscriptionPayload( + mNotificationUpdatedSite!!, + AccountStore.AddOrDeleteSubscriptionPayload.SubscriptionAction.NEW + ) + } else { + AnalyticsTracker.track(AnalyticsTracker.Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_COMMENTS_OFF) + AccountStore.AddOrDeleteSubscriptionPayload( + mNotificationUpdatedSite!!, + AccountStore.AddOrDeleteSubscriptionPayload.SubscriptionAction.DELETE + ) + } + mDispatcher.dispatch(AccountActionBuilder.newUpdateSubscriptionEmailCommentAction(payload)) + } + } + + fun getSubscriptionFrequencyFromString(s: String): AccountStore.UpdateSubscriptionPayload.SubscriptionFrequency { + return if (s.equals(AccountStore.UpdateSubscriptionPayload.SubscriptionFrequency.DAILY.toString(), ignoreCase = true)) { + AnalyticsTracker.track(AnalyticsTracker.Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_EMAIL_DAILY) + AccountStore.UpdateSubscriptionPayload.SubscriptionFrequency.DAILY + } else if (s.equals(AccountStore.UpdateSubscriptionPayload.SubscriptionFrequency.WEEKLY.toString(), ignoreCase = true)) { + AnalyticsTracker.track(AnalyticsTracker.Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_EMAIL_WEEKLY) + AccountStore.UpdateSubscriptionPayload.SubscriptionFrequency.WEEKLY + } else { + AnalyticsTracker.track(AnalyticsTracker.Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_EMAIL_INSTANTLY) + AccountStore.UpdateSubscriptionPayload.SubscriptionFrequency.INSTANTLY + } + } +} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsMySitesFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsMySitesFragment.kt new file mode 100644 index 000000000000..44076bd74efb --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsMySitesFragment.kt @@ -0,0 +1,215 @@ +package org.wordpress.android.ui.prefs.notifications + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import androidx.preference.Preference +import androidx.preference.PreferenceCategory +import org.greenrobot.eventbus.Subscribe +import org.greenrobot.eventbus.ThreadMode +import org.wordpress.android.R +import org.wordpress.android.WordPress +import org.wordpress.android.fluxc.Dispatcher +import org.wordpress.android.fluxc.generated.AccountActionBuilder +import org.wordpress.android.fluxc.model.SiteModel +import org.wordpress.android.fluxc.store.AccountStore +import org.wordpress.android.fluxc.store.SiteStore +import org.wordpress.android.models.NotificationsSettings +import org.wordpress.android.ui.RequestCodes +import org.wordpress.android.util.AppLog +import org.wordpress.android.util.SiteUtils +import javax.inject.Inject + +class NotificationsSettingsMySitesFragment: ChildNotificationSettingsFragment(), NotificationsMySitesSettingsFragment { + companion object { + const val ARG_IS_FOLLOWED = "ARG_IS_FOLLOWED" + } + override var mNotificationUpdatedSite: String? = null + override var mPreviousEmailPostsFrequency: String? = null + override var mUpdateSubscriptionFrequencyPayload: AccountStore.UpdateSubscriptionPayload? = null + override var mPreviousEmailComments: Boolean = false + override var mPreviousEmailPosts: Boolean = false + override var mPreviousNotifyPosts: Boolean = false + override var mUpdateEmailPostsFirst: Boolean = false + + @Inject + override lateinit var mDispatcher: Dispatcher + + @Inject + lateinit var mSiteStore: SiteStore + + @Inject + lateinit var mFollowedBlogsProvider: FollowedBlogsProvider + + private lateinit var rootCategory: PreferenceCategory + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + (requireActivity().application as WordPress).component().inject(this) + + val isFollowed: Boolean + requireArguments().apply { + isFollowed = getBoolean(ARG_IS_FOLLOWED) + } + rootCategory = PreferenceCategory(requireContext()) + rootCategory.setTitle( + if (isFollowed) + R.string.notification_settings_category_followed_sites + else + R.string.notification_settings_category_your_sites + ) + preferenceScreen?.addPreference(rootCategory) + if (isFollowed) { + configureFollowedBlogsSettings(rootCategory) + } else { + configureBlogsSettings(rootCategory) + } + } + + override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { + setPreferencesFromResource(R.xml.notification_settings_my_sites, rootKey) + } + + override fun onStart() { + super.onStart() + mDispatcher.register(this) + } + + override fun onStop() { + super.onStop() + mDispatcher.unregister(this) + } + + @Suppress("unused") + @Subscribe(threadMode = ThreadMode.MAIN) + fun onSubscriptionsChanged(event: AccountStore.OnSubscriptionsChanged) { + if (event.isError) { + AppLog.e(AppLog.T.API, "NotificationsSettingsFragment.onSubscriptionsChanged: " + event.error.message) + } else { + configureFollowedBlogsSettings(rootCategory) + } + } + + @Suppress("unused") + @Subscribe(threadMode = ThreadMode.MAIN) + fun onSubscriptionUpdated(event: AccountStore.OnSubscriptionUpdated) { + if (event.isError) { + AppLog.e(AppLog.T.API, "NotificationsSettingsFragment.onSubscriptionUpdated: " + event.error.message) + } else if (event.type == AccountStore.SubscriptionType.EMAIL_POST && mUpdateEmailPostsFirst) { + mUpdateEmailPostsFirst = false + mDispatcher.dispatch( + AccountActionBuilder.newUpdateSubscriptionEmailPostFrequencyAction( + mUpdateSubscriptionFrequencyPayload + ) + ) + } else { + mDispatcher.dispatch(AccountActionBuilder.newFetchSubscriptionsAction()) + } + } + + @Suppress("DEPRECATION") + private fun configureFollowedBlogsSettings(blogsCategory: PreferenceCategory?) { + if (!isAdded || blogsCategory == null) { + return + } + val models: List = + mFollowedBlogsProvider.getAllFollowedBlogs(null) + .sortedWith { (title): FollowedBlogsProvider.PreferenceModel, + (otherTitle): FollowedBlogsProvider.PreferenceModel -> + title.compareTo( + otherTitle, + ignoreCase = true + ) + } + blogsCategory.removeAll() + + val context: Context? = activity + for ((title, summary, blogId, clickHandler) in models) { + if (context == null) { + return + } + val prefScreen = preferenceManager.createPreferenceScreen(context) + prefScreen.title = title + prefScreen.summary = summary + if (clickHandler != null) { + prefScreen.onPreferenceClickListener = + Preference.OnPreferenceClickListener { + mNotificationUpdatedSite = blogId + mPreviousNotifyPosts = clickHandler.shouldNotifyPosts + mPreviousEmailPosts = clickHandler.shouldEmailPosts + mPreviousEmailPostsFrequency = clickHandler.emailPostFrequency + mPreviousEmailComments = clickHandler.shouldEmailComments + val dialog = NotificationSettingsFollowedDialog() + val args = Bundle().apply { + putBoolean( + NotificationSettingsFollowedDialog.ARG_NOTIFICATION_POSTS, + mPreviousNotifyPosts + ) + putBoolean( + NotificationSettingsFollowedDialog.ARG_EMAIL_POSTS, + mPreviousEmailPosts + ) + putString( + NotificationSettingsFollowedDialog.ARG_EMAIL_POSTS_FREQUENCY, + mPreviousEmailPostsFrequency + ) + putBoolean( + NotificationSettingsFollowedDialog.ARG_EMAIL_COMMENTS, + mPreviousEmailComments + ) + } + dialog.arguments = args + dialog.setTargetFragment( + this@NotificationsSettingsMySitesFragment, + RequestCodes.NOTIFICATION_SETTINGS + ) + dialog.show(parentFragmentManager, NotificationSettingsFollowedDialog.TAG) + true + } + } else { + prefScreen.isEnabled = false + } + blogsCategory.addPreference(prefScreen) + } + } + + private fun configureBlogsSettings(blogsCategory: PreferenceCategory?) { + if (!isAdded || blogsCategory == null) { + return + } + val sites: List = mSiteStore.sitesAccessedViaWPComRest + .sortedWith { o1, o2 -> + SiteUtils.getSiteNameOrHomeURL(o1) + .compareTo(SiteUtils.getSiteNameOrHomeURL(o2), ignoreCase = true) + } + blogsCategory.removeAll() + + val context: Context? = activity + for (site in sites) { + if (context == null) { + return + } + val prefScreen = preferenceManager.createPreferenceScreen(context) + prefScreen.title = SiteUtils.getSiteNameOrHomeURL(site) + prefScreen.summary = SiteUtils.getHomeURLOrHostName(site) + prefScreen.extras.apply { + putLong(NotificationsSettingsTypesFragment.ARG_BLOG_ID, site.siteId) + putInt( + NotificationsSettingsTypesFragment.ARG_NOTIFICATION_CHANNEL, + NotificationsSettings.Channel.BLOGS.ordinal + ) + } + prefScreen.fragment = NotificationsSettingsTypesFragment::class.qualifiedName + blogsCategory.addPreference(prefScreen) + } + } + + @Deprecated("Deprecated in Java") + @Suppress("DEPRECATION") + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + if (requestCode == RequestCodes.NOTIFICATION_SETTINGS) { + this.onMySiteSettingsChanged(data) + } + } +} diff --git a/WordPress/src/main/res/xml/notification_settings_my_sites.xml b/WordPress/src/main/res/xml/notification_settings_my_sites.xml new file mode 100644 index 000000000000..7bf2aa65d884 --- /dev/null +++ b/WordPress/src/main/res/xml/notification_settings_my_sites.xml @@ -0,0 +1,4 @@ + + + + From 275795ffbe3fd9f40c4203b2007b12cc6b072388 Mon Sep 17 00:00:00 2001 From: Jasjeet Singh <98077881+07jasjeet@users.noreply.github.com> Date: Thu, 11 Jan 2024 02:06:45 +0530 Subject: [PATCH 11/14] Migrated NotificationsSettingsFragment to AndroidX Why? PreferenceFragment has been deprecated in favour of PreferenceFragmentCompat Changes: 1) Previous java to kotlin migration fixes such as dependency injection fixes and null safety. 2) Removed Notification Types Child preference screen in favour of recommended implementation. 3) Removed Notification Types Child preference screen in favour of recommended implementation. 4) Removed Deprecated DialogPreference in favour of androidx implementation. 5) Ringtone Preference migration to Preference as support for it has been deprecated. References: https://stackoverflow.com/questions/60029806/why-does-the-nested-preferencescreen-not-open-when-using-androidx (cites high quality resource for problem and its solution) --- .../android/models/NotificationsSettings.java | 29 +- .../wordpress/android/ui/RequestCodes.java | 1 + .../NotificationsSettingsFragment.kt | 796 +++++++----------- 3 files changed, 337 insertions(+), 489 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/models/NotificationsSettings.java b/WordPress/src/main/java/org/wordpress/android/models/NotificationsSettings.java index 56cca449f174..62334cb4adaa 100644 --- a/WordPress/src/main/java/org/wordpress/android/models/NotificationsSettings.java +++ b/WordPress/src/main/java/org/wordpress/android/models/NotificationsSettings.java @@ -1,5 +1,6 @@ package org.wordpress.android.models; +import androidx.annotation.NonNull; import androidx.collection.LongSparseArray; import org.json.JSONArray; @@ -26,7 +27,20 @@ public class NotificationsSettings { public enum Channel { OTHER, BLOGS, - WPCOM + WPCOM; + + public static Channel toNotificationChannel(Integer ordinal) { + switch (ordinal) { + case 0: + return OTHER; + case 1: + return BLOGS; + case 2: + return WPCOM; + default: + throw new IllegalArgumentException("Ordinal does not conform to any existing enum."); + } + } } // The notification setting type, used in BLOGS and OTHER channels @@ -35,6 +49,19 @@ public enum Type { EMAIL, DEVICE; + public static Type toNotificationType(Integer ordinal) { + switch (ordinal) { + case 0: + return TIMELINE; + case 1: + return EMAIL; + case 2: + return DEVICE; + default: + throw new IllegalArgumentException("Ordinal does not conform to any existing enum."); + } + } + public String toString() { switch (this) { case TIMELINE: diff --git a/WordPress/src/main/java/org/wordpress/android/ui/RequestCodes.java b/WordPress/src/main/java/org/wordpress/android/ui/RequestCodes.java index e46b5cd8a090..1a51263620a5 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/RequestCodes.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/RequestCodes.java @@ -28,6 +28,7 @@ public class RequestCodes { public static final int SMART_LOCK_SAVE = 1400; public static final int SMART_LOCK_READ = 1500; public static final int NOTIFICATION_SETTINGS = 1600; + public static final int NOTIFICATION_SETTINGS_ALERT_RINGTONE = 1610; public static final int ACTIVITY_LOG_DETAIL = 1700; public static final int BACKUP_DOWNLOAD = 1710; public static final int RESTORE = 1720; diff --git a/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsFragment.kt index fcf0cb41ab87..4b9c887bb13a 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsFragment.kt @@ -5,13 +5,11 @@ import android.content.Context import android.content.Intent import android.content.SharedPreferences import android.content.SharedPreferences.OnSharedPreferenceChangeListener -import android.graphics.PorterDuff +import android.media.RingtoneManager +import android.net.Uri import android.os.Build import android.os.Bundle -import android.preference.Preference -import android.preference.PreferenceCategory -import android.preference.PreferenceFragment -import android.preference.PreferenceScreen +import android.provider.Settings import android.text.TextUtils import android.view.LayoutInflater import android.view.Menu @@ -19,13 +17,18 @@ import android.view.MenuInflater import android.view.MenuItem import android.view.View import android.widget.ListView -import androidx.annotation.DrawableRes +import android.widget.TextView import androidx.annotation.StringRes import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.SearchView +import androidx.core.content.edit import androidx.core.view.ViewCompat -import androidx.lifecycle.ViewModelProvider +import androidx.preference.DialogPreference +import androidx.preference.Preference +import androidx.preference.PreferenceCategory +import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceManager +import androidx.preference.PreferenceScreen import com.wordpress.rest.RestRequest import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.Subscribe @@ -39,101 +42,82 @@ import org.wordpress.android.WordPress.Companion.getRestClientUtilsV1_1 import org.wordpress.android.analytics.AnalyticsTracker import org.wordpress.android.analytics.AnalyticsTracker.Stat import org.wordpress.android.databinding.JetpackBadgeFooterBinding -import org.wordpress.android.datasets.ReaderBlogTable import org.wordpress.android.fluxc.Dispatcher import org.wordpress.android.fluxc.generated.AccountActionBuilder import org.wordpress.android.fluxc.model.SiteModel import org.wordpress.android.fluxc.store.AccountStore -import org.wordpress.android.fluxc.store.AccountStore.AddOrDeleteSubscriptionPayload -import org.wordpress.android.fluxc.store.AccountStore.AddOrDeleteSubscriptionPayload.SubscriptionAction import org.wordpress.android.fluxc.store.AccountStore.OnSubscriptionUpdated import org.wordpress.android.fluxc.store.AccountStore.OnSubscriptionsChanged import org.wordpress.android.fluxc.store.AccountStore.SubscriptionType import org.wordpress.android.fluxc.store.AccountStore.UpdateSubscriptionPayload -import org.wordpress.android.fluxc.store.AccountStore.UpdateSubscriptionPayload.SubscriptionFrequency import org.wordpress.android.fluxc.store.SiteStore import org.wordpress.android.models.JetpackPoweredScreen import org.wordpress.android.models.NotificationsSettings import org.wordpress.android.ui.RequestCodes import org.wordpress.android.ui.WPLaunchActivity -import org.wordpress.android.ui.bloggingreminders.BloggingReminderUtils.observeBottomSheet -import org.wordpress.android.ui.bloggingreminders.BloggingRemindersViewModel import org.wordpress.android.ui.mysite.jetpackbadge.JetpackPoweredBottomSheetFragment import org.wordpress.android.ui.notifications.NotificationEvents.NotificationsSettingsStatusChanged import org.wordpress.android.ui.notifications.utils.NotificationsUtils import org.wordpress.android.ui.prefs.notifications.FollowedBlogsProvider.PreferenceModel -import org.wordpress.android.ui.prefs.notifications.NotificationsSettingsDialogPreference.BloggingRemindersProvider import org.wordpress.android.ui.prefs.notifications.NotificationsSettingsDialogPreference.OnNotificationsSettingsChangedListener +import org.wordpress.android.ui.prefs.notifications.NotificationsSettingsMySitesFragment.Companion.ARG_IS_FOLLOWED +import org.wordpress.android.ui.prefs.notifications.NotificationsSettingsTypesFragment.Companion.ARG_BLOG_ID import org.wordpress.android.ui.utils.UiHelpers -import org.wordpress.android.ui.utils.UiString import org.wordpress.android.util.AppLog import org.wordpress.android.util.BuildConfigWrapper import org.wordpress.android.util.JetpackBrandingUtils import org.wordpress.android.util.SiteUtils import org.wordpress.android.util.ToastUtils -import org.wordpress.android.util.WPActivityUtils import org.wordpress.android.util.WPPermissionUtils -import org.wordpress.android.util.extensions.getColorStateListFromAttribute -import java.util.Collections import javax.inject.Inject -class NotificationsSettingsFragment : PreferenceFragment(), OnSharedPreferenceChangeListener { + +class NotificationsSettingsFragment : PreferenceFragmentCompat(), NotificationsMySitesSettingsFragment, + OnSharedPreferenceChangeListener { private var mNotificationsSettings: NotificationsSettings? = null private var mSearchView: SearchView? = null private var mSearchMenuItem: MenuItem? = null private var mSearchMenuItemCollapsed = true private var mDeviceId: String? = null - private var mNotificationUpdatedSite: String? = null - private var mPreviousEmailPostsFrequency: String? = null private var mRestoredQuery: String? = null - private var mUpdateSubscriptionFrequencyPayload: UpdateSubscriptionPayload? = null private var mNotificationsEnabled = false - private var mPreviousEmailComments = false - private var mPreviousEmailPosts = false - private var mPreviousNotifyPosts = false - private var mUpdateEmailPostsFirst = false + override var mNotificationUpdatedSite: String? = null + override var mPreviousEmailPostsFrequency: String? = null + override var mUpdateSubscriptionFrequencyPayload: UpdateSubscriptionPayload? = null + override var mPreviousEmailComments = false + override var mPreviousEmailPosts = false + override var mPreviousNotifyPosts = false + override var mUpdateEmailPostsFirst = false private var mSiteCount = 0 private var mSubscriptionCount = 0 private val mTypePreferenceCategories: MutableList = ArrayList() private var mBlogsCategory: PreferenceCategory? = null private var mFollowedBlogsCategory: PreferenceCategory? = null - @JvmField @Inject - var mAccountStore: AccountStore? = null + lateinit var mAccountStore: AccountStore - @JvmField @Inject - var mSiteStore: SiteStore? = null + lateinit var mSiteStore: SiteStore - @JvmField @Inject - var mDispatcher: Dispatcher? = null + override lateinit var mDispatcher: Dispatcher - @JvmField @Inject - var mFollowedBlogsProvider: FollowedBlogsProvider? = null + lateinit var mFollowedBlogsProvider: FollowedBlogsProvider - @JvmField @Inject - var mBuildConfigWrapper: BuildConfigWrapper? = null + lateinit var mBuildConfigWrapper: BuildConfigWrapper - @JvmField @Inject - var mViewModelFactory: ViewModelProvider.Factory? = null + lateinit var mJetpackBrandingUtils: JetpackBrandingUtils - @JvmField @Inject - var mJetpackBrandingUtils: JetpackBrandingUtils? = null + lateinit var mUiHelpers: UiHelpers - @JvmField - @Inject - var mUiHelpers: UiHelpers? = null - private var mBloggingRemindersViewModel: BloggingRemindersViewModel? = null - private val mBloggingRemindersSummariesBySiteId: MutableMap = HashMap() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - (activity.application as WordPress).component().inject(this) + (requireActivity().application as WordPress).component().inject(this) addPreferencesFromResource(R.xml.notifications_settings) setHasOptionsMenu(true) removeSightAndSoundsForAPI26() @@ -145,87 +129,116 @@ class NotificationsSettingsFragment : PreferenceFragment(), OnSharedPreferenceCh } } + override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {} + + @Suppress("DEPRECATION") + override fun onDisplayPreferenceDialog(preference: Preference) { + if (preference is NotificationsSettingsDialogPreferenceX) { + if (parentFragmentManager.findFragmentByTag(NotificationsSettingsDialogFragment.TAG) != null) { + return + } + with(preference) { + NotificationsSettingsDialogFragment( + channel = channel, + type = type, + blogId = blogId, + settings = settings, + onNotificationsSettingsChangedListener = listener, + bloggingRemindersProvider = bloggingRemindersProvider, + title = context.getString(dialogTitleRes) + ).apply { + setTargetFragment( + this@NotificationsSettingsFragment, + RequestCodes.NOTIFICATION_SETTINGS + ) + }.show( + parentFragmentManager, + NotificationsSettingsDialogFragment.TAG + ) + } + } else { + super.onDisplayPreferenceDialog(preference) + } + } + private fun removeSightAndSoundsForAPI26() { // on API26 we removed the Sight & Sounds category altogether, as it can always be - // overriden by the user in the Device settings, and the settings here + // overridden by the user in the Device settings, and the settings here // wouldn't either reflect nor have any effect anyway. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - val preferenceScreen = - findPreference(activity.getString(R.string.wp_pref_notifications_root)) as PreferenceScreen - val categorySightsAndSounds = preferenceScreen - .findPreference(activity.getString(R.string.pref_notification_sights_sounds)) as PreferenceCategory - preferenceScreen.removePreference(categorySightsAndSounds) + val (preferenceScreen, categorySightsAndSounds) = + getPreferenceScreenAndCategory(R.string.pref_notification_sights_sounds) + + if (categorySightsAndSounds != null) { + preferenceScreen?.removePreference(categorySightsAndSounds) + } } } private fun removeFollowedBlogsPreferenceForIfDisabled() { - if (!mBuildConfigWrapper!!.isFollowedSitesSettingsEnabled) { - val preferenceScreen = - findPreference(activity.getString(R.string.wp_pref_notifications_root)) as PreferenceScreen - val categoryFollowedBlogs = preferenceScreen - .findPreference(activity.getString(R.string.pref_notification_blogs_followed)) as PreferenceCategory - preferenceScreen.removePreference(categoryFollowedBlogs) + if (!mBuildConfigWrapper.isFollowedSitesSettingsEnabled) { + val (preferenceScreen, categoryFollowedBlogs) = + getPreferenceScreenAndCategory(R.string.pref_notification_blogs_followed) + + if (categoryFollowedBlogs != null) { + preferenceScreen?.removePreference(categoryFollowedBlogs) + } } } + private fun getPreferenceScreenAndCategory(pref: Int): Pair { + val preferenceScreen = + findPreference(requireActivity().getString(R.string.wp_pref_notifications_root)) as PreferenceScreen? + val requiredPreference = preferenceScreen + ?.findPreference(requireActivity().getString(pref)) as PreferenceCategory? + return Pair(preferenceScreen, requiredPreference) + } + + @Deprecated("Deprecated in Java") + @Suppress("DEPRECATION") override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) - val isLoggedIn = mAccountStore!!.hasAccessToken() + val isLoggedIn = mAccountStore.hasAccessToken() if (!isLoggedIn) { // Not logged in users can start Notification Settings from App info > Notifications menu. // If there isn't a logged in user, just show the entry screen. val intent = Intent(context, WPLaunchActivity::class.java) intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK) startActivity(intent) - activity.finish() + requireActivity().finish() return } - val settings = PreferenceManager.getDefaultSharedPreferences(activity) + val settings = PreferenceManager.getDefaultSharedPreferences(requireActivity()) mDeviceId = settings.getString(NotificationsUtils.WPCOM_PUSH_DEVICE_SERVER_ID, "") if (hasNotificationsSettings()) { loadNotificationsAndUpdateUI(true) } - if (savedInstanceState != null && savedInstanceState.containsKey( - NotificationsSettingsFragment.Companion.KEY_SEARCH_QUERY - ) - ) { - mRestoredQuery = - savedInstanceState.getString(NotificationsSettingsFragment.Companion.KEY_SEARCH_QUERY) + if (savedInstanceState != null && savedInstanceState.containsKey(KEY_SEARCH_QUERY)) { + mRestoredQuery = savedInstanceState.getString(KEY_SEARCH_QUERY) } } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - val lv = view.findViewById(android.R.id.list) as ListView + val lv = view.findViewById(R.id.list) as ListView? if (lv != null) { ViewCompat.setNestedScrollingEnabled(lv, true) addJetpackBadgeAsFooterIfEnabled(lv) } - initBloggingReminders() - } - - override fun onViewStateRestored(savedInstanceState: Bundle) { - super.onViewStateRestored(savedInstanceState) - val otherBlogsScreen = findPreference( - getString(R.string.pref_notification_other_blogs) - ) as PreferenceScreen - addToolbarToDialog(otherBlogsScreen) } private fun addJetpackBadgeAsFooterIfEnabled(listView: ListView) { - if (mJetpackBrandingUtils!!.shouldShowJetpackBranding()) { - val screen: JetpackPoweredScreen = - JetpackPoweredScreen.WithDynamicText.NOTIFICATIONS_SETTINGS - val context = context + if (mJetpackBrandingUtils.shouldShowJetpackBranding()) { + val screen: JetpackPoweredScreen = JetpackPoweredScreen.WithDynamicText.NOTIFICATIONS_SETTINGS val inflater = LayoutInflater.from(context) - val binding = JetpackBadgeFooterBinding.inflate(inflater) - binding.footerJetpackBadge.jetpackPoweredBadge.text = mUiHelpers!!.getTextOfUiString( - context, - mJetpackBrandingUtils!!.getBrandingTextForScreen(screen) + val binding: JetpackBadgeFooterBinding = JetpackBadgeFooterBinding.inflate(inflater) + binding.footerJetpackBadge.jetpackPoweredBadge.text = mUiHelpers.getTextOfUiString( + requireContext(), + mJetpackBrandingUtils.getBrandingTextForScreen(screen) ) - if (mJetpackBrandingUtils!!.shouldShowJetpackPoweredBottomSheet()) { - binding.footerJetpackBadge.jetpackPoweredBadge.setOnClickListener { v: View? -> - mJetpackBrandingUtils!!.trackBadgeTapped(screen) + if (mJetpackBrandingUtils.shouldShowJetpackPoweredBottomSheet()) { + binding.footerJetpackBadge.jetpackPoweredBadge.setOnClickListener { + mJetpackBrandingUtils.trackBadgeTapped(screen) JetpackPoweredBottomSheetFragment().show( (activity as AppCompatActivity).supportFragmentManager, JetpackPoweredBottomSheetFragment.TAG @@ -238,33 +251,34 @@ class NotificationsSettingsFragment : PreferenceFragment(), OnSharedPreferenceCh override fun onStart() { super.onStart() - mDispatcher!!.register(this) - preferenceManager.sharedPreferences.registerOnSharedPreferenceChangeListener(this) + mDispatcher.register(this) + preferenceManager.sharedPreferences?.registerOnSharedPreferenceChangeListener(this) } override fun onResume() { super.onResume() mNotificationsEnabled = NotificationsUtils.isNotificationsEnabled(activity) + setToolbarTitle() refreshSettings() } override fun onStop() { super.onStop() - mDispatcher!!.unregister(this) - preferenceManager.sharedPreferences.unregisterOnSharedPreferenceChangeListener(this) + mDispatcher.unregister(this) + preferenceManager.sharedPreferences?.unregisterOnSharedPreferenceChangeListener(this) } override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { inflater.inflate(R.menu.notifications_settings, menu) mSearchMenuItem = menu.findItem(R.id.menu_notifications_settings_search) - mSearchView = mSearchMenuItem?.getActionView() as SearchView? - mSearchView!!.queryHint = getString(R.string.search_sites) + mSearchView = mSearchMenuItem?.actionView as SearchView? + mSearchView?.queryHint = getString(R.string.search_sites) mBlogsCategory = findPreference( getString(R.string.pref_notification_blogs) - ) as PreferenceCategory + ) as PreferenceCategory? mFollowedBlogsCategory = findPreference( getString(R.string.pref_notification_blogs_followed) - ) as PreferenceCategory + ) as PreferenceCategory? mSearchView!!.setOnQueryTextListener(object : SearchView.OnQueryTextListener { override fun onQueryTextSubmit(query: String): Boolean { configureBlogsSettings(mBlogsCategory, true) @@ -301,124 +315,33 @@ class NotificationsSettingsFragment : PreferenceFragment(), OnSharedPreferenceCh // Check for a restored search query (if device was rotated, etc) if (!TextUtils.isEmpty(mRestoredQuery)) { mSearchMenuItem?.expandActionView() - mSearchView!!.setQuery(mRestoredQuery, true) + mSearchView?.setQuery(mRestoredQuery, true) } } override fun onSaveInstanceState(outState: Bundle) { if (mSearchView != null && !TextUtils.isEmpty(mSearchView!!.query)) { - outState.putString( - NotificationsSettingsFragment.Companion.KEY_SEARCH_QUERY, - mSearchView!!.query.toString() - ) + outState.putString(KEY_SEARCH_QUERY, mSearchView!!.query.toString()) } super.onSaveInstanceState(outState) } - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) { - super.onActivityResult(requestCode, resultCode, data) - if (data != null && requestCode == RequestCodes.NOTIFICATION_SETTINGS) { - val notifyPosts = data.getBooleanExtra( - NotificationSettingsFollowedDialog.KEY_NOTIFICATION_POSTS, - false - ) - val emailPosts = - data.getBooleanExtra(NotificationSettingsFollowedDialog.KEY_EMAIL_POSTS, false) - val emailPostsFrequency = - data.getStringExtra(NotificationSettingsFollowedDialog.KEY_EMAIL_POSTS_FREQUENCY) - val emailComments = - data.getBooleanExtra(NotificationSettingsFollowedDialog.KEY_EMAIL_COMMENTS, false) - if (notifyPosts != mPreviousNotifyPosts) { - ReaderBlogTable.setNotificationsEnabledByBlogId( - mNotificationUpdatedSite!!.toLong(), - notifyPosts - ) - val payload: AddOrDeleteSubscriptionPayload - payload = if (notifyPosts) { - AnalyticsTracker.track(Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_ON) - AddOrDeleteSubscriptionPayload( - mNotificationUpdatedSite!!, - SubscriptionAction.NEW - ) - } else { - AnalyticsTracker.track(Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_OFF) - AddOrDeleteSubscriptionPayload( - mNotificationUpdatedSite!!, - SubscriptionAction.DELETE - ) - } - mDispatcher!!.dispatch( - AccountActionBuilder.newUpdateSubscriptionNotificationPostAction( - payload - ) - ) - } - if (emailPosts != mPreviousEmailPosts) { - val payload: AddOrDeleteSubscriptionPayload - payload = if (emailPosts) { - AnalyticsTracker.track(Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_EMAIL_ON) - AddOrDeleteSubscriptionPayload( - mNotificationUpdatedSite!!, - SubscriptionAction.NEW - ) - } else { - AnalyticsTracker.track(Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_EMAIL_OFF) - AddOrDeleteSubscriptionPayload( - mNotificationUpdatedSite!!, - SubscriptionAction.DELETE - ) - } - mDispatcher!!.dispatch( - AccountActionBuilder.newUpdateSubscriptionEmailPostAction( - payload - ) - ) - } - if (emailPostsFrequency != null && !emailPostsFrequency.equals( - mPreviousEmailPostsFrequency, - ignoreCase = true - ) - ) { - val subscriptionFrequency = getSubscriptionFrequencyFromString(emailPostsFrequency) - mUpdateSubscriptionFrequencyPayload = UpdateSubscriptionPayload( - mNotificationUpdatedSite!!, - subscriptionFrequency - ) - /* - * The email post frequency update will be overridden by the email post update if the email post - * frequency callback returns first. Thus, the updates must be dispatched sequentially when the - * email post update is switched from disabled to enabled. - */if (emailPosts != mPreviousEmailPosts && emailPosts) { - mUpdateEmailPostsFirst = true - } else { - mDispatcher!!.dispatch( - AccountActionBuilder.newUpdateSubscriptionEmailPostFrequencyAction( - mUpdateSubscriptionFrequencyPayload - ) - ) - } - } - if (emailComments != mPreviousEmailComments) { - val payload: AddOrDeleteSubscriptionPayload - payload = if (emailComments) { - AnalyticsTracker.track(Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_COMMENTS_ON) - AddOrDeleteSubscriptionPayload( - mNotificationUpdatedSite!!, - SubscriptionAction.NEW - ) - } else { - AnalyticsTracker.track(Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_COMMENTS_OFF) - AddOrDeleteSubscriptionPayload( - mNotificationUpdatedSite!!, - SubscriptionAction.DELETE - ) - } - mDispatcher!!.dispatch( - AccountActionBuilder.newUpdateSubscriptionEmailCommentAction( - payload - ) + @Deprecated("Deprecated in Java") + @Suppress("DEPRECATION") + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + if (requestCode == RequestCodes.NOTIFICATION_SETTINGS) { + this.onMySiteSettingsChanged(data) + } else if (requestCode == RequestCodes.NOTIFICATION_SETTINGS_ALERT_RINGTONE && data != null) { + val ringtone: Uri? = data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI) + val settings = PreferenceManager.getDefaultSharedPreferences(requireContext()) + settings.edit { + putString( + getString(R.string.wp_pref_custom_notification_sound), + (ringtone ?: "").toString() ) } + } else { + super.onActivityResult(requestCode, resultCode, data) } } @@ -426,10 +349,7 @@ class NotificationsSettingsFragment : PreferenceFragment(), OnSharedPreferenceCh @Subscribe(threadMode = ThreadMode.MAIN) fun onSubscriptionsChanged(event: OnSubscriptionsChanged) { if (event.isError) { - AppLog.e( - AppLog.T.API, - "NotificationsSettingsFragment.onSubscriptionsChanged: " + event.error.message - ) + AppLog.e(AppLog.T.API, "NotificationsSettingsFragment.onSubscriptionsChanged: " + event.error.message) } else { configureFollowedBlogsSettings(mFollowedBlogsCategory, !mSearchMenuItemCollapsed) } @@ -439,32 +359,16 @@ class NotificationsSettingsFragment : PreferenceFragment(), OnSharedPreferenceCh @Subscribe(threadMode = ThreadMode.MAIN) fun onSubscriptionUpdated(event: OnSubscriptionUpdated) { if (event.isError) { - AppLog.e( - AppLog.T.API, - "NotificationsSettingsFragment.onSubscriptionUpdated: " + event.error.message - ) + AppLog.e(AppLog.T.API, "NotificationsSettingsFragment.onSubscriptionUpdated: " + event.error.message) } else if (event.type == SubscriptionType.EMAIL_POST && mUpdateEmailPostsFirst) { mUpdateEmailPostsFirst = false - mDispatcher!!.dispatch( + mDispatcher.dispatch( AccountActionBuilder.newUpdateSubscriptionEmailPostFrequencyAction( mUpdateSubscriptionFrequencyPayload ) ) } else { - mDispatcher!!.dispatch(AccountActionBuilder.newFetchSubscriptionsAction()) - } - } - - private fun getSubscriptionFrequencyFromString(s: String): SubscriptionFrequency { - return if (s.equals(SubscriptionFrequency.DAILY.toString(), ignoreCase = true)) { - AnalyticsTracker.track(Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_EMAIL_DAILY) - SubscriptionFrequency.DAILY - } else if (s.equals(SubscriptionFrequency.WEEKLY.toString(), ignoreCase = true)) { - AnalyticsTracker.track(Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_EMAIL_WEEKLY) - SubscriptionFrequency.WEEKLY - } else { - AnalyticsTracker.track(Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_EMAIL_INSTANTLY) - SubscriptionFrequency.INSTANTLY + mDispatcher.dispatch(AccountActionBuilder.newFetchSubscriptionsAction()) } } @@ -476,7 +380,7 @@ class NotificationsSettingsFragment : PreferenceFragment(), OnSharedPreferenceCh if (hasNotificationsSettings()) { updateUIForNotificationsEnabledState() } - if (!mAccountStore!!.hasAccessToken()) { + if (!mAccountStore.hasAccessToken()) { return } NotificationsUtils.getPushNotificationSettings(activity, RestRequest.Listener { response -> @@ -488,12 +392,11 @@ class NotificationsSettingsFragment : PreferenceFragment(), OnSharedPreferenceCh if (!settingsExisted) { EventBus.getDefault().post(NotificationsSettingsStatusChanged(null)) } - val settings = PreferenceManager.getDefaultSharedPreferences(activity) - val editor = settings.edit() - editor.putString( - NotificationsUtils.WPCOM_PUSH_DEVICE_NOTIFICATION_SETTINGS, - response.toString() + val settings = PreferenceManager.getDefaultSharedPreferences( + requireActivity() ) + val editor = settings.edit() + editor.putString(NotificationsUtils.WPCOM_PUSH_DEVICE_NOTIFICATION_SETTINGS, response.toString()) editor.apply() loadNotificationsAndUpdateUI(!settingsExisted) updateUIForNotificationsEnabledState() @@ -513,16 +416,12 @@ class NotificationsSettingsFragment : PreferenceFragment(), OnSharedPreferenceCh } private fun loadNotificationsAndUpdateUI(shouldUpdateUI: Boolean) { - val settingsJson: JSONObject - settingsJson = try { + val settingsJson: JSONObject = try { val sharedPreferences = PreferenceManager.getDefaultSharedPreferences( - activity + requireActivity() ) JSONObject( - sharedPreferences.getString( - NotificationsUtils.WPCOM_PUSH_DEVICE_NOTIFICATION_SETTINGS, - "" - ) + sharedPreferences.getString(NotificationsUtils.WPCOM_PUSH_DEVICE_NOTIFICATION_SETTINGS, "")!! ) } catch (e: JSONException) { AppLog.e(AppLog.T.NOTIFS, "Could not parse notifications settings JSON") @@ -537,12 +436,12 @@ class NotificationsSettingsFragment : PreferenceFragment(), OnSharedPreferenceCh if (mBlogsCategory == null) { mBlogsCategory = findPreference( getString(R.string.pref_notification_blogs) - ) as PreferenceCategory + ) as PreferenceCategory? } if (mFollowedBlogsCategory == null) { mFollowedBlogsCategory = findPreference( getString(R.string.pref_notification_blogs_followed) - ) as PreferenceCategory + ) as PreferenceCategory? } configureBlogsSettings(mBlogsCategory, false) configureFollowedBlogsSettings(mFollowedBlogsCategory, false) @@ -553,7 +452,7 @@ class NotificationsSettingsFragment : PreferenceFragment(), OnSharedPreferenceCh private fun hasNotificationsSettings(): Boolean { val sharedPreferences = PreferenceManager.getDefaultSharedPreferences( - activity + requireActivity() ) return sharedPreferences.contains(NotificationsUtils.WPCOM_PUSH_DEVICE_NOTIFICATION_SETTINGS) } @@ -564,30 +463,29 @@ class NotificationsSettingsFragment : PreferenceFragment(), OnSharedPreferenceCh return } for (category in mTypePreferenceCategories) { - if (mNotificationsEnabled && category.preferenceCount > NotificationsSettingsFragment.Companion.TYPE_COUNT) { - category.removePreference(category.getPreference(NotificationsSettingsFragment.Companion.TYPE_COUNT)) - } else if (!mNotificationsEnabled && category.preferenceCount == NotificationsSettingsFragment.Companion.TYPE_COUNT) { - val disabledMessage = Preference(activity) + if (mNotificationsEnabled && category.preferenceCount > TYPE_COUNT) { + category.removePreference(category.getPreference(TYPE_COUNT)) + } else if (!mNotificationsEnabled && category.preferenceCount == TYPE_COUNT) { + val disabledMessage = Preference(requireActivity()) category.addPreference(disabledMessage) } - if (category.preferenceCount >= NotificationsSettingsFragment.Companion.TYPE_COUNT - && category.getPreference(NotificationsSettingsFragment.Companion.TYPE_COUNT - 1) != null + if (category.preferenceCount >= TYPE_COUNT ) { - category.getPreference(NotificationsSettingsFragment.Companion.TYPE_COUNT - 1).isEnabled = + category.getPreference(TYPE_COUNT - 1).isEnabled = mNotificationsEnabled } - if (category.preferenceCount > NotificationsSettingsFragment.Companion.TYPE_COUNT - && category.getPreference(NotificationsSettingsFragment.Companion.TYPE_COUNT) != null + if (category.preferenceCount > TYPE_COUNT ) { - updateDisabledMessagePreference(category.getPreference(NotificationsSettingsFragment.Companion.TYPE_COUNT)) + updateDisabledMessagePreference(category.getPreference(TYPE_COUNT)) } } } + @Suppress("DEPRECATION") private fun updateDisabledMessagePreference(disabledMessagePreference: Preference) { disabledMessagePreference.setSummary(disabledMessageResId) disabledMessagePreference.onPreferenceClickListener = - Preference.OnPreferenceClickListener { preference: Preference? -> + Preference.OnPreferenceClickListener { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && shouldRequestRuntimePermission()) { // Request runtime permission. requestPermissions( @@ -596,7 +494,7 @@ class NotificationsSettingsFragment : PreferenceFragment(), OnSharedPreferenceCh ) } else { // Navigate to app settings. - WPPermissionUtils.showNotificationsSettings(context) + WPPermissionUtils.showNotificationsSettings(requireContext()) } true } @@ -604,33 +502,26 @@ class NotificationsSettingsFragment : PreferenceFragment(), OnSharedPreferenceCh private fun shouldRequestRuntimePermission(): Boolean { return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU - && !WPPermissionUtils.isPermissionAlwaysDenied( - activity, - Manifest.permission.POST_NOTIFICATIONS - )) + && !WPPermissionUtils.isPermissionAlwaysDenied(requireActivity(), Manifest.permission.POST_NOTIFICATIONS)) } @get:StringRes private val disabledMessageResId: Int - private get() = if (shouldRequestRuntimePermission()) { + get() = if (shouldRequestRuntimePermission()) { R.string.notifications_disabled_permission_dialog } else { R.string.notifications_disabled } + @Deprecated("Deprecated in Java") + @Suppress("DEPRECATION") override fun onRequestPermissionsResult( requestCode: Int, permissions: Array, grantResults: IntArray ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) - WPPermissionUtils.setPermissionListAsked( - activity, - requestCode, - permissions, - grantResults, - false - ) + WPPermissionUtils.setPermissionListAsked(requireActivity(), requestCode, permissions, grantResults, false) } private fun configureBlogsSettings(blogsCategory: PreferenceCategory?, showAll: Boolean) { @@ -641,80 +532,79 @@ class NotificationsSettingsFragment : PreferenceFragment(), OnSharedPreferenceCh var trimmedQuery = "" if (mSearchView != null && !TextUtils.isEmpty(mSearchView!!.query)) { trimmedQuery = mSearchView!!.query.toString().trim { it <= ' ' } - sites = mSiteStore!!.getSitesAccessedViaWPComRestByNameOrUrlMatching(trimmedQuery) + sites = mSiteStore.getSitesAccessedViaWPComRestByNameOrUrlMatching(trimmedQuery) } else { - sites = mSiteStore!!.sitesAccessedViaWPComRest + sites = mSiteStore.sitesAccessedViaWPComRest } mSiteCount = sites.size if (mSiteCount > 0) { - Collections.sort(sites) { o1, o2 -> - SiteUtils.getSiteNameOrHomeURL(o1).compareTo( - SiteUtils.getSiteNameOrHomeURL(o2), ignoreCase = true - ) + sites.sortedWith { o1, o2 -> + SiteUtils.getSiteNameOrHomeURL(o1) + .compareTo(SiteUtils.getSiteNameOrHomeURL(o2), ignoreCase = true) } } val context: Context? = activity blogsCategory!!.removeAll() - val maxSitesToShow: Int = - if (showAll) NotificationsSettingsFragment.Companion.NO_MAXIMUM else NotificationsSettingsFragment.Companion.MAX_SITES_TO_SHOW_ON_FIRST_SCREEN + val maxSitesToShow = if (showAll) NO_MAXIMUM else MAX_SITES_TO_SHOW_ON_FIRST_SCREEN var count = 0 for (site in sites) { if (context == null) { return } count++ - if (maxSitesToShow != NotificationsSettingsFragment.Companion.NO_MAXIMUM && count > maxSitesToShow) { + if (maxSitesToShow != NO_MAXIMUM && count > maxSitesToShow) { break } val prefScreen = preferenceManager.createPreferenceScreen(context) prefScreen.title = SiteUtils.getSiteNameOrHomeURL(site) prefScreen.summary = SiteUtils.getHomeURLOrHostName(site) - addPreferencesForPreferenceScreen( - prefScreen, - NotificationsSettings.Channel.BLOGS, - site.siteId - ) + prefScreen.extras.apply { + putLong(ARG_BLOG_ID, site.siteId) + putInt( + NotificationsSettingsTypesFragment.ARG_NOTIFICATION_CHANNEL, + NotificationsSettings.Channel.BLOGS.ordinal + ) + } + prefScreen.fragment = NotificationsSettingsTypesFragment::class.qualifiedName blogsCategory.addPreference(prefScreen) } // Add a message in a preference if there are no matching search results if (mSiteCount == 0 && !TextUtils.isEmpty(trimmedQuery)) { - val searchResultsPref = Preference(context) + val searchResultsPref = Preference(requireContext()) searchResultsPref.summary = String.format(getString(R.string.notifications_no_search_results), trimmedQuery) blogsCategory.addPreference(searchResultsPref) } if (mSiteCount > maxSitesToShow && !showAll) { // append a "view all" option - appendViewAllSitesOption(context, getString(R.string.pref_notification_blogs), false) + appendViewAllSitesOption(getString(R.string.pref_notification_blogs), false) } updateSearchMenuVisibility() } - private fun configureFollowedBlogsSettings( - blogsCategory: PreferenceCategory?, - showAll: Boolean - ) { + @Suppress("DEPRECATION") + private fun configureFollowedBlogsSettings(blogsCategory: PreferenceCategory?, showAll: Boolean) { if (!isAdded || blogsCategory == null) { return } - val models: List + var models: List var query = "" if (mSearchView != null && !TextUtils.isEmpty(mSearchView!!.query)) { query = mSearchView!!.query.toString().trim { it <= ' ' } - models = mFollowedBlogsProvider!!.getAllFollowedBlogs(query) + models = mFollowedBlogsProvider.getAllFollowedBlogs(query) } else { - models = mFollowedBlogsProvider!!.getAllFollowedBlogs(null) + models = mFollowedBlogsProvider.getAllFollowedBlogs(null) } val context: Context? = activity blogsCategory.removeAll() - val maxSitesToShow: Int = - if (showAll) NotificationsSettingsFragment.Companion.NO_MAXIMUM else NotificationsSettingsFragment.Companion.MAX_SITES_TO_SHOW_ON_FIRST_SCREEN + val maxSitesToShow = if (showAll) NO_MAXIMUM else MAX_SITES_TO_SHOW_ON_FIRST_SCREEN mSubscriptionCount = 0 - if (models.size > 0) { - Collections.sort(models) { (title): PreferenceModel, (title1): PreferenceModel -> + if (models.isNotEmpty()) { + models = models.sortedWith { (title): PreferenceModel, (otherTitle): PreferenceModel -> title.compareTo( - title1, ignoreCase = true + otherTitle, + ignoreCase = true ) } } @@ -731,36 +621,37 @@ class NotificationsSettingsFragment : PreferenceFragment(), OnSharedPreferenceCh prefScreen.summary = summary if (clickHandler != null) { prefScreen.onPreferenceClickListener = - Preference.OnPreferenceClickListener { preference: Preference? -> + Preference.OnPreferenceClickListener { mNotificationUpdatedSite = blogId mPreviousNotifyPosts = clickHandler.shouldNotifyPosts mPreviousEmailPosts = clickHandler.shouldEmailPosts mPreviousEmailPostsFrequency = clickHandler.emailPostFrequency mPreviousEmailComments = clickHandler.shouldEmailComments val dialog = NotificationSettingsFollowedDialog() - val args = Bundle() - args.putBoolean( - NotificationSettingsFollowedDialog.ARG_NOTIFICATION_POSTS, - mPreviousNotifyPosts - ) - args.putBoolean( - NotificationSettingsFollowedDialog.ARG_EMAIL_POSTS, - mPreviousEmailPosts - ) - args.putString( - NotificationSettingsFollowedDialog.ARG_EMAIL_POSTS_FREQUENCY, - mPreviousEmailPostsFrequency - ) - args.putBoolean( - NotificationSettingsFollowedDialog.ARG_EMAIL_COMMENTS, - mPreviousEmailComments - ) + val args = Bundle().apply { + putBoolean( + NotificationSettingsFollowedDialog.ARG_NOTIFICATION_POSTS, + mPreviousNotifyPosts + ) + putBoolean( + NotificationSettingsFollowedDialog.ARG_EMAIL_POSTS, + mPreviousEmailPosts + ) + putString( + NotificationSettingsFollowedDialog.ARG_EMAIL_POSTS_FREQUENCY, + mPreviousEmailPostsFrequency + ) + putBoolean( + NotificationSettingsFollowedDialog.ARG_EMAIL_COMMENTS, + mPreviousEmailComments + ) + } dialog.arguments = args dialog.setTargetFragment( this@NotificationsSettingsFragment, RequestCodes.NOTIFICATION_SETTINGS ) - dialog.show(childFragmentManager, NotificationSettingsFollowedDialog.TAG) + dialog.show(parentFragmentManager, NotificationSettingsFollowedDialog.TAG) true } } else { @@ -771,146 +662,100 @@ class NotificationsSettingsFragment : PreferenceFragment(), OnSharedPreferenceCh // Add message if there are no matching search results. if (mSubscriptionCount == 0 && !TextUtils.isEmpty(query)) { - val searchResultsPref = Preference(context) - searchResultsPref.summary = - String.format(getString(R.string.notifications_no_search_results), query) + val searchResultsPref = Preference(requireContext()) + searchResultsPref.summary = String.format(getString(R.string.notifications_no_search_results), query) blogsCategory.addPreference(searchResultsPref) } // Add view all entry when more sites than maximum to show. if (!showAll && mSubscriptionCount > maxSitesToShow) { - appendViewAllSitesOption( - context, - getString(R.string.pref_notification_blogs_followed), - true - ) + appendViewAllSitesOption(getString(R.string.pref_notification_blogs_followed), true) } updateSearchMenuVisibility() } - private fun appendViewAllSitesOption( - context: Context?, - preference: String, - isFollowed: Boolean - ) { - val blogsCategory = findPreference(preference) as PreferenceCategory - val prefScreen = preferenceManager.createPreferenceScreen(context) - prefScreen.setTitle(if (isFollowed) R.string.notification_settings_item_your_sites_all_followed_sites else R.string.notification_settings_item_your_sites_all_your_sites) + private fun appendViewAllSitesOption(preference: String, isFollowed: Boolean) { + val blogsCategory = findPreference(preference) as PreferenceCategory? + val prefScreen = preferenceManager.createPreferenceScreen(requireContext()) + prefScreen.fragment = NotificationsSettingsMySitesFragment::class.qualifiedName + prefScreen.setTitle( + if (isFollowed) + R.string.notification_settings_item_your_sites_all_followed_sites + else + R.string.notification_settings_item_your_sites_all_your_sites + ) + prefScreen.extras.apply { + putBoolean(ARG_IS_FOLLOWED, isFollowed) + } addSitesForViewAllSitesScreen(prefScreen, isFollowed) - blogsCategory.addPreference(prefScreen) + blogsCategory?.addPreference(prefScreen) } private fun updateSearchMenuVisibility() { // Show the search menu item in the toolbar if we have enough sites if (mSearchMenuItem != null) { - mSearchMenuItem!!.isVisible = - (mSiteCount > NotificationsSettingsFragment.Companion.SITE_SEARCH_VISIBILITY_COUNT - || mSubscriptionCount > NotificationsSettingsFragment.Companion.SITE_SEARCH_VISIBILITY_COUNT) + mSearchMenuItem!!.isVisible = (mSiteCount > SITE_SEARCH_VISIBILITY_COUNT + || mSubscriptionCount > SITE_SEARCH_VISIBILITY_COUNT) } } private fun configureOtherSettings() { val otherBlogsScreen = findPreference( getString(R.string.pref_notification_other_blogs) - ) as PreferenceScreen - addPreferencesForPreferenceScreen(otherBlogsScreen, NotificationsSettings.Channel.OTHER, 0) + ) as PreferenceScreen? + otherBlogsScreen?.let { + it.extras.apply { + putLong(ARG_BLOG_ID, 0) + putInt( + NotificationsSettingsTypesFragment.ARG_NOTIFICATION_CHANNEL, + NotificationsSettings.Channel.OTHER.ordinal + ) + } + it.fragment = NotificationsSettingsTypesFragment::class.qualifiedName + } } private fun configureWPComSettings() { val otherPreferenceCategory = findPreference( getString(R.string.pref_notification_other_category) - ) as PreferenceCategory - val devicePreference = NotificationsSettingsDialogPreference( - activity, - null, - NotificationsSettings.Channel.WPCOM, - NotificationsSettings.Type.DEVICE, - 0, - mNotificationsSettings, - mOnSettingsChangedListener - ) - devicePreference.setTitle(R.string.notification_settings_item_other_account_emails) - devicePreference.setDialogTitle(R.string.notification_settings_item_other_account_emails) - devicePreference.setSummary(R.string.notification_settings_item_other_account_emails_summary) - otherPreferenceCategory.addPreference(devicePreference) - } + ) as PreferenceCategory? - private fun addPreferencesForPreferenceScreen( - preferenceScreen: PreferenceScreen, - channel: NotificationsSettings.Channel, - blogId: Long - ) { - val context = activity ?: return - val rootCategory = PreferenceCategory(context) - rootCategory.setTitle(R.string.notification_types) - preferenceScreen.addPreference(rootCategory) - val timelinePreference = NotificationsSettingsDialogPreference( - context, - null, - channel, - NotificationsSettings.Type.TIMELINE, - blogId, - mNotificationsSettings, - mOnSettingsChangedListener - ) - setPreferenceIcon(timelinePreference, R.drawable.ic_bell_white_24dp) - timelinePreference.setTitle(R.string.notifications_tab) - timelinePreference.setDialogTitle(R.string.notifications_tab) - timelinePreference.setSummary(R.string.notifications_tab_summary) - rootCategory.addPreference(timelinePreference) - val emailPreference = NotificationsSettingsDialogPreference( - context, - null, - channel, - NotificationsSettings.Type.EMAIL, - blogId, - mNotificationsSettings, - mOnSettingsChangedListener - ) - setPreferenceIcon(emailPreference, R.drawable.ic_mail_white_24dp) - emailPreference.setTitle(R.string.email) - emailPreference.setDialogTitle(R.string.email) - emailPreference.setSummary(R.string.notifications_email_summary) - rootCategory.addPreference(emailPreference) - val settings = PreferenceManager.getDefaultSharedPreferences(context) - val deviceID = settings.getString(NotificationsUtils.WPCOM_PUSH_DEVICE_SERVER_ID, null) - if (!TextUtils.isEmpty(deviceID)) { - val devicePreference = NotificationsSettingsDialogPreference( - context, - null, - channel, - NotificationsSettings.Type.DEVICE, - blogId, - mNotificationsSettings, - mOnSettingsChangedListener, - mBloggingRemindersProvider - ) - setPreferenceIcon(devicePreference, R.drawable.ic_phone_white_24dp) - devicePreference.setTitle(R.string.app_notifications) - devicePreference.setDialogTitle(R.string.app_notifications) - devicePreference.setSummary(R.string.notifications_push_summary) - devicePreference.isEnabled = mNotificationsEnabled - rootCategory.addPreference(devicePreference) + // Remove previously configured preference. + val previouslyConfiguredPreference = otherPreferenceCategory?.findPreference( + getString(R.string.notification_settings_item_other_account_emails) + ) as DialogPreference? + if (previouslyConfiguredPreference != null) { + otherPreferenceCategory?.removePreference(previouslyConfiguredPreference) } - mTypePreferenceCategories.add(rootCategory) - } - private fun setPreferenceIcon( - preference: NotificationsSettingsDialogPreference, - @DrawableRes drawableRes: Int - ) { - preference.setIcon(drawableRes) - preference.icon.setTintMode(PorterDuff.Mode.SRC_IN) - preference.icon.setTintList(preference.context.getColorStateListFromAttribute(R.attr.wpColorOnSurfaceMedium)) + // Add the preference back with updated details + val devicePreference = NotificationsSettingsDialogPreferenceX( + context = requireContext(), + attrs = null, + channel = NotificationsSettings.Channel.WPCOM, + type = NotificationsSettings.Type.DEVICE, + blogId = 0, + settings = mNotificationsSettings!!, + listener = mOnSettingsChangedListener, + dialogTitleRes = R.string.notification_settings_item_other_account_emails + ).apply { + setTitle(R.string.notification_settings_item_other_account_emails) + key = getString(R.string.notification_settings_item_other_account_emails) + setSummary(R.string.notification_settings_item_other_account_emails_summary) + } + + otherPreferenceCategory?.addPreference(devicePreference) } - private fun addSitesForViewAllSitesScreen( - preferenceScreen: PreferenceScreen, - isFollowed: Boolean - ) { + private fun addSitesForViewAllSitesScreen(preferenceScreen: PreferenceScreen, isFollowed: Boolean) { val context = activity ?: return val rootCategory = PreferenceCategory(context) - rootCategory.setTitle(if (isFollowed) R.string.notification_settings_category_followed_sites else R.string.notification_settings_category_your_sites) + rootCategory.setTitle( + if (isFollowed) + R.string.notification_settings_category_followed_sites + else + R.string.notification_settings_category_your_sites + ) preferenceScreen.addPreference(rootCategory) if (isFollowed) { configureFollowedBlogsSettings(rootCategory, true) @@ -927,7 +772,7 @@ class NotificationsSettingsFragment : PreferenceFragment(), OnSharedPreferenceCh // Construct a new settings JSONObject to send back to WP.com val settingsObject = JSONObject() - when (channel) { + when (channel!!) { NotificationsSettings.Channel.BLOGS -> try { val blogObject = JSONObject() blogObject.put(NotificationsSettings.KEY_BLOG_ID, blogId) @@ -974,36 +819,48 @@ class NotificationsSettingsFragment : PreferenceFragment(), OnSharedPreferenceCh } } - override fun onPreferenceTreeClick( - preferenceScreen: PreferenceScreen, - preference: Preference - ): Boolean { - super.onPreferenceTreeClick(preferenceScreen, preference) + @Suppress("DEPRECATION") + override fun onPreferenceTreeClick(preference: Preference): Boolean { if (preference is PreferenceScreen) { - addToolbarToDialog(preference) AnalyticsTracker.track(Stat.NOTIFICATION_SETTINGS_STREAMS_OPENED) } else { AnalyticsTracker.track(Stat.NOTIFICATION_SETTINGS_DETAILS_OPENED) } - return false - } - private fun addToolbarToDialog(preference: Preference) { - val prefDialog = (preference as PreferenceScreen).dialog - if (prefDialog != null) { - val title = preference.getTitle().toString() - WPActivityUtils.addToolbarToDialog(this, prefDialog, title) + /* Since ringtone preference has been removed in androidx.preference, we use a workaround as + * recommended here: https://issuetracker.google.com/issues/37057453#comment3 */ + val notificationSoundPreferenceKey = getString(R.string.wp_pref_custom_notification_sound) + return if (preference.key?.equals(notificationSoundPreferenceKey) == true) { + val intent = Intent(RingtoneManager.ACTION_RINGTONE_PICKER) + intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_NOTIFICATION) + intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true) + intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, true) + intent.putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI, Settings.System.DEFAULT_NOTIFICATION_URI) + val settings = PreferenceManager.getDefaultSharedPreferences(requireContext()) + val existingValue: String? = settings.getString(notificationSoundPreferenceKey, null) + if (existingValue != null) { + if (existingValue.isEmpty()) { + // Select "Silent" + intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, null as Uri?) + } else { + intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, Uri.parse(existingValue)) + } + } else { + // No ringtone has been selected, set to the default + intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, Settings.System.DEFAULT_NOTIFICATION_URI) + } + startActivityForResult(intent, RequestCodes.NOTIFICATION_SETTINGS_ALERT_RINGTONE) + true + } else { + super.onPreferenceTreeClick(preference) } } override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String?) { if (key == getString(R.string.pref_key_notification_pending_drafts)) { - if (activity != null) { - val prefs = PreferenceManager.getDefaultSharedPreferences( - activity - ) - val shouldNotifyOfPendingDrafts = - prefs.getBoolean("wp_pref_notification_pending_drafts", true) + activity?.let { + val prefs = PreferenceManager.getDefaultSharedPreferences(it) + val shouldNotifyOfPendingDrafts = prefs.getBoolean("wp_pref_notification_pending_drafts", true) if (shouldNotifyOfPendingDrafts) { AnalyticsTracker.track(Stat.NOTIFICATION_PENDING_DRAFTS_SETTINGS_ENABLED) } else { @@ -1011,8 +868,7 @@ class NotificationsSettingsFragment : PreferenceFragment(), OnSharedPreferenceCh } } } else if (key == getString(R.string.wp_pref_custom_notification_sound)) { - val defaultPath = - getString(R.string.notification_settings_item_sights_and_sounds_choose_sound_default) + val defaultPath = getString(R.string.notification_settings_item_sights_and_sounds_choose_sound_default) val value = sharedPreferences.getString(key, defaultPath) if (value!!.trim { it <= ' ' }.lowercase().startsWith("file://")) { // sound path begins with 'file://` which will lead to FileUriExposedException when used. Revert to @@ -1022,59 +878,24 @@ class NotificationsSettingsFragment : PreferenceFragment(), OnSharedPreferenceCh "Notification sound starts with unacceptable scheme: $value" ) val context = WordPress.getContext() - if (context != null) { - // let the user know we won't be using the selected sound - ToastUtils.showToast( - context, - R.string.notification_sound_has_invalid_path, - ToastUtils.Duration.LONG - ) - } + ToastUtils.showToast( + context, + R.string.notification_sound_has_invalid_path, + ToastUtils.Duration.LONG + ) } } } - private val appCompatActivity: AppCompatActivity? - private get() { - val activity = activity - return if (activity is AppCompatActivity) { - activity - } else null - } - private val mBloggingRemindersProvider: BloggingRemindersProvider = - object : BloggingRemindersProvider { - override fun getSummary(blogId: Long): String? { - val uiString = mBloggingRemindersSummariesBySiteId[blogId] - return if (uiString != null) mUiHelpers!!.getTextOfUiString(context, uiString) - .toString() else null - } - - override fun onClick(blogId: Long) { - mBloggingRemindersViewModel!!.onNotificationSettingsItemClicked(blogId) - } - } - - private fun initBloggingReminders() { - if (!isAdded) { - return - } - val appCompatActivity = appCompatActivity - if (appCompatActivity != null) { - mBloggingRemindersViewModel = ViewModelProvider(appCompatActivity, mViewModelFactory!!) - .get(BloggingRemindersViewModel::class.java) - observeBottomSheet( - mBloggingRemindersViewModel!!.isBottomSheetShowing, - appCompatActivity, - NotificationsSettingsFragment.Companion.BLOGGING_REMINDERS_BOTTOM_SHEET_TAG - ) { appCompatActivity.supportFragmentManager } - mBloggingRemindersViewModel!!.notificationsSettingsUiState - .observe(appCompatActivity) { map -> - mBloggingRemindersSummariesBySiteId.putAll(map) - } + private fun setToolbarTitle() { + with(requireActivity() as AppCompatActivity) { + val titleView = findViewById(R.id.toolbar_title) + titleView.text = getString(R.string.notification_settings) } } companion object { + const val TAG = "NOTIFICATION_SETTINGS_FRAGMENT_TAG" private const val KEY_SEARCH_QUERY = "search_query" private const val SITE_SEARCH_VISIBILITY_COUNT = 15 @@ -1082,6 +903,5 @@ class NotificationsSettingsFragment : PreferenceFragment(), OnSharedPreferenceCh private const val TYPE_COUNT = 3 private const val NO_MAXIMUM = -1 private const val MAX_SITES_TO_SHOW_ON_FIRST_SCREEN = 3 - private const val BLOGGING_REMINDERS_BOTTOM_SHEET_TAG = "blogging-reminders-dialog-tag" } } From 4015eb2cf24210c924994b6237ab94158ca58140 Mon Sep 17 00:00:00 2001 From: Jasjeet Singh <98077881+07jasjeet@users.noreply.github.com> Date: Thu, 11 Jan 2024 02:07:24 +0530 Subject: [PATCH 12/14] Dependency injection declaration for new child preference fragments --- .../java/org/wordpress/android/modules/AppComponent.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/WordPress/src/main/java/org/wordpress/android/modules/AppComponent.java b/WordPress/src/main/java/org/wordpress/android/modules/AppComponent.java index 9561a8ab4fca..5b25d97a5b35 100644 --- a/WordPress/src/main/java/org/wordpress/android/modules/AppComponent.java +++ b/WordPress/src/main/java/org/wordpress/android/modules/AppComponent.java @@ -121,6 +121,8 @@ import org.wordpress.android.ui.prefs.homepage.HomepageSettingsDialog; import org.wordpress.android.ui.prefs.language.LocalePickerBottomSheet; import org.wordpress.android.ui.prefs.notifications.NotificationsSettingsFragment; +import org.wordpress.android.ui.prefs.notifications.NotificationsSettingsMySitesFragment; +import org.wordpress.android.ui.prefs.notifications.NotificationsSettingsTypesFragment; import org.wordpress.android.ui.prefs.timezone.SiteSettingsTimezoneBottomSheet; import org.wordpress.android.ui.publicize.PublicizeAccountChooserListAdapter; import org.wordpress.android.ui.publicize.PublicizeButtonPrefsFragment; @@ -294,6 +296,10 @@ public interface AppComponent { void inject(NotificationsSettingsFragment object); + void inject(NotificationsSettingsTypesFragment object); + + void inject(NotificationsSettingsMySitesFragment object); + void inject(NotificationsDetailActivity object); void inject(NotificationsPendingDraftsReceiver object); From 686ceaf50614ba639f6087083db7c691fa0dbfa8 Mon Sep 17 00:00:00 2001 From: Jasjeet Singh <98077881+07jasjeet@users.noreply.github.com> Date: Sat, 13 Jan 2024 02:16:39 +0530 Subject: [PATCH 13/14] Check-style issues resolved --- .../android/models/NotificationsSettings.java | 1 - .../NotificationsMySitesSettingsFragment.kt | 49 ++++++++++--------- .../NotificationsSettingsMySitesFragment.kt | 6 ++- 3 files changed, 29 insertions(+), 27 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/models/NotificationsSettings.java b/WordPress/src/main/java/org/wordpress/android/models/NotificationsSettings.java index 62334cb4adaa..8f43cc67b609 100644 --- a/WordPress/src/main/java/org/wordpress/android/models/NotificationsSettings.java +++ b/WordPress/src/main/java/org/wordpress/android/models/NotificationsSettings.java @@ -1,6 +1,5 @@ package org.wordpress.android.models; -import androidx.annotation.NonNull; import androidx.collection.LongSparseArray; import org.json.JSONArray; diff --git a/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsMySitesSettingsFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsMySitesSettingsFragment.kt index 80eff22f69fb..aa453aaf57ae 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsMySitesSettingsFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsMySitesSettingsFragment.kt @@ -5,7 +5,8 @@ import org.wordpress.android.analytics.AnalyticsTracker import org.wordpress.android.datasets.ReaderBlogTable import org.wordpress.android.fluxc.Dispatcher import org.wordpress.android.fluxc.generated.AccountActionBuilder -import org.wordpress.android.fluxc.store.AccountStore +import org.wordpress.android.fluxc.store.AccountStore.AddOrDeleteSubscriptionPayload +import org.wordpress.android.fluxc.store.AccountStore.UpdateSubscriptionPayload /** Any notification preference fragment that deals with **My Sites** or **My Followed Sites** * should implement this interface.*/ @@ -16,7 +17,7 @@ interface NotificationsMySitesSettingsFragment { var mPreviousNotifyPosts: Boolean var mUpdateEmailPostsFirst: Boolean var mPreviousEmailPostsFrequency: String? - var mUpdateSubscriptionFrequencyPayload: AccountStore.UpdateSubscriptionPayload? + var mUpdateSubscriptionFrequencyPayload: UpdateSubscriptionPayload? var mDispatcher: Dispatcher fun onMySiteSettingsChanged(data: Intent?) { @@ -29,33 +30,33 @@ interface NotificationsMySitesSettingsFragment { val emailComments = data.getBooleanExtra(NotificationSettingsFollowedDialog.KEY_EMAIL_COMMENTS, false) if (notifyPosts != mPreviousNotifyPosts) { ReaderBlogTable.setNotificationsEnabledByBlogId(mNotificationUpdatedSite!!.toLong(), notifyPosts) - val payload: AccountStore.AddOrDeleteSubscriptionPayload = if (notifyPosts) { + val payload: AddOrDeleteSubscriptionPayload = if (notifyPosts) { AnalyticsTracker.track(AnalyticsTracker.Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_ON) - AccountStore.AddOrDeleteSubscriptionPayload( + AddOrDeleteSubscriptionPayload( mNotificationUpdatedSite!!, - AccountStore.AddOrDeleteSubscriptionPayload.SubscriptionAction.NEW + AddOrDeleteSubscriptionPayload.SubscriptionAction.NEW ) } else { AnalyticsTracker.track(AnalyticsTracker.Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_OFF) - AccountStore.AddOrDeleteSubscriptionPayload( + AddOrDeleteSubscriptionPayload( mNotificationUpdatedSite!!, - AccountStore.AddOrDeleteSubscriptionPayload.SubscriptionAction.DELETE + AddOrDeleteSubscriptionPayload.SubscriptionAction.DELETE ) } mDispatcher.dispatch(AccountActionBuilder.newUpdateSubscriptionNotificationPostAction(payload)) } if (emailPosts != mPreviousEmailPosts) { - val payload: AccountStore.AddOrDeleteSubscriptionPayload = if (emailPosts) { + val payload: AddOrDeleteSubscriptionPayload = if (emailPosts) { AnalyticsTracker.track(AnalyticsTracker.Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_EMAIL_ON) - AccountStore.AddOrDeleteSubscriptionPayload( + AddOrDeleteSubscriptionPayload( mNotificationUpdatedSite!!, - AccountStore.AddOrDeleteSubscriptionPayload.SubscriptionAction.NEW + AddOrDeleteSubscriptionPayload.SubscriptionAction.NEW ) } else { AnalyticsTracker.track(AnalyticsTracker.Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_EMAIL_OFF) - AccountStore.AddOrDeleteSubscriptionPayload( + AddOrDeleteSubscriptionPayload( mNotificationUpdatedSite!!, - AccountStore.AddOrDeleteSubscriptionPayload.SubscriptionAction.DELETE + AddOrDeleteSubscriptionPayload.SubscriptionAction.DELETE ) } mDispatcher.dispatch(AccountActionBuilder.newUpdateSubscriptionEmailPostAction(payload)) @@ -66,7 +67,7 @@ interface NotificationsMySitesSettingsFragment { ) ) { val subscriptionFrequency = getSubscriptionFrequencyFromString(emailPostsFrequency) - mUpdateSubscriptionFrequencyPayload = AccountStore.UpdateSubscriptionPayload( + mUpdateSubscriptionFrequencyPayload = UpdateSubscriptionPayload( mNotificationUpdatedSite!!, subscriptionFrequency ) @@ -86,33 +87,33 @@ interface NotificationsMySitesSettingsFragment { } } if (emailComments != mPreviousEmailComments) { - val payload: AccountStore.AddOrDeleteSubscriptionPayload = if (emailComments) { + val payload: AddOrDeleteSubscriptionPayload = if (emailComments) { AnalyticsTracker.track(AnalyticsTracker.Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_COMMENTS_ON) - AccountStore.AddOrDeleteSubscriptionPayload( + AddOrDeleteSubscriptionPayload( mNotificationUpdatedSite!!, - AccountStore.AddOrDeleteSubscriptionPayload.SubscriptionAction.NEW + AddOrDeleteSubscriptionPayload.SubscriptionAction.NEW ) } else { AnalyticsTracker.track(AnalyticsTracker.Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_COMMENTS_OFF) - AccountStore.AddOrDeleteSubscriptionPayload( + AddOrDeleteSubscriptionPayload( mNotificationUpdatedSite!!, - AccountStore.AddOrDeleteSubscriptionPayload.SubscriptionAction.DELETE + AddOrDeleteSubscriptionPayload.SubscriptionAction.DELETE ) } mDispatcher.dispatch(AccountActionBuilder.newUpdateSubscriptionEmailCommentAction(payload)) } } - fun getSubscriptionFrequencyFromString(s: String): AccountStore.UpdateSubscriptionPayload.SubscriptionFrequency { - return if (s.equals(AccountStore.UpdateSubscriptionPayload.SubscriptionFrequency.DAILY.toString(), ignoreCase = true)) { + fun getSubscriptionFrequencyFromString(s: String): UpdateSubscriptionPayload.SubscriptionFrequency { + return if (s.equals(UpdateSubscriptionPayload.SubscriptionFrequency.DAILY.toString(), ignoreCase = true)) { AnalyticsTracker.track(AnalyticsTracker.Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_EMAIL_DAILY) - AccountStore.UpdateSubscriptionPayload.SubscriptionFrequency.DAILY - } else if (s.equals(AccountStore.UpdateSubscriptionPayload.SubscriptionFrequency.WEEKLY.toString(), ignoreCase = true)) { + UpdateSubscriptionPayload.SubscriptionFrequency.DAILY + } else if (s.equals(UpdateSubscriptionPayload.SubscriptionFrequency.WEEKLY.toString(), ignoreCase = true)) { AnalyticsTracker.track(AnalyticsTracker.Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_EMAIL_WEEKLY) - AccountStore.UpdateSubscriptionPayload.SubscriptionFrequency.WEEKLY + UpdateSubscriptionPayload.SubscriptionFrequency.WEEKLY } else { AnalyticsTracker.track(AnalyticsTracker.Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_EMAIL_INSTANTLY) - AccountStore.UpdateSubscriptionPayload.SubscriptionFrequency.INSTANTLY + UpdateSubscriptionPayload.SubscriptionFrequency.INSTANTLY } } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsMySitesFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsMySitesFragment.kt index 44076bd74efb..0bc7e7002db1 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsMySitesFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsMySitesFragment.kt @@ -13,6 +13,8 @@ import org.wordpress.android.fluxc.Dispatcher import org.wordpress.android.fluxc.generated.AccountActionBuilder import org.wordpress.android.fluxc.model.SiteModel import org.wordpress.android.fluxc.store.AccountStore +import org.wordpress.android.fluxc.store.AccountStore.OnSubscriptionsChanged +import org.wordpress.android.fluxc.store.AccountStore.OnSubscriptionUpdated import org.wordpress.android.fluxc.store.SiteStore import org.wordpress.android.models.NotificationsSettings import org.wordpress.android.ui.RequestCodes @@ -82,7 +84,7 @@ class NotificationsSettingsMySitesFragment: ChildNotificationSettingsFragment(), @Suppress("unused") @Subscribe(threadMode = ThreadMode.MAIN) - fun onSubscriptionsChanged(event: AccountStore.OnSubscriptionsChanged) { + fun onSubscriptionsChanged(event: OnSubscriptionsChanged) { if (event.isError) { AppLog.e(AppLog.T.API, "NotificationsSettingsFragment.onSubscriptionsChanged: " + event.error.message) } else { @@ -92,7 +94,7 @@ class NotificationsSettingsMySitesFragment: ChildNotificationSettingsFragment(), @Suppress("unused") @Subscribe(threadMode = ThreadMode.MAIN) - fun onSubscriptionUpdated(event: AccountStore.OnSubscriptionUpdated) { + fun onSubscriptionUpdated(event: OnSubscriptionUpdated) { if (event.isError) { AppLog.e(AppLog.T.API, "NotificationsSettingsFragment.onSubscriptionUpdated: " + event.error.message) } else if (event.type == AccountStore.SubscriptionType.EMAIL_POST && mUpdateEmailPostsFirst) { From 409d8b97b1c5a019d4dd71745111e36cf300c9fd Mon Sep 17 00:00:00 2001 From: Jasjeet Singh <98077881+07jasjeet@users.noreply.github.com> Date: Sun, 14 Jan 2024 00:56:02 +0530 Subject: [PATCH 14/14] Partially solved detekt warnings On running detekt again, 8 unavoidable warning show up which existed prior to this PR's changes. --- .../ChildNotificationSettingsFragment.kt | 3 +- .../NotificationsMySitesSettingsFragment.kt | 49 ++----- .../NotificationsSettingsDialogFragment.kt | 47 +++---- .../NotificationsSettingsDialogPreferenceX.kt | 1 + .../NotificationsSettingsFragment.kt | 125 +++++++++--------- .../NotificationsSettingsMySitesFragment.kt | 43 +++--- .../NotificationsSettingsTypesFragment.kt | 3 +- 7 files changed, 111 insertions(+), 160 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/ChildNotificationSettingsFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/ChildNotificationSettingsFragment.kt index 43d6c16be22b..358c8606ab7d 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/ChildNotificationSettingsFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/ChildNotificationSettingsFragment.kt @@ -9,6 +9,7 @@ import androidx.transition.Transition import androidx.transition.TransitionManager import com.google.android.material.appbar.AppBarLayout import org.wordpress.android.R +import org.wordpress.android.util.AniUtils /** Child Notification fragments should inherit from this class in order to make navigation consistent.*/ abstract class ChildNotificationSettingsFragment: PreferenceFragmentCompat() { @@ -27,7 +28,7 @@ abstract class ChildNotificationSettingsFragment: PreferenceFragmentCompat() { val mainSwitchToolBarView = findViewById(R.id.main_switch) val rootView = findViewById(R.id.app_bar_layout) val transition: Transition = Slide(Gravity.TOP) - transition.duration = 200 + transition.duration = AniUtils.Duration.SHORT.toMillis(context) transition.addTarget(R.id.main_switch) TransitionManager.beginDelayedTransition(rootView, transition) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsMySitesSettingsFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsMySitesSettingsFragment.kt index aa453aaf57ae..5bbff34b0f91 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsMySitesSettingsFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsMySitesSettingsFragment.kt @@ -6,6 +6,7 @@ import org.wordpress.android.datasets.ReaderBlogTable import org.wordpress.android.fluxc.Dispatcher import org.wordpress.android.fluxc.generated.AccountActionBuilder import org.wordpress.android.fluxc.store.AccountStore.AddOrDeleteSubscriptionPayload +import org.wordpress.android.fluxc.store.AccountStore.AddOrDeleteSubscriptionPayload.SubscriptionAction import org.wordpress.android.fluxc.store.AccountStore.UpdateSubscriptionPayload /** Any notification preference fragment that deals with **My Sites** or **My Followed Sites** @@ -21,9 +22,7 @@ interface NotificationsMySitesSettingsFragment { var mDispatcher: Dispatcher fun onMySiteSettingsChanged(data: Intent?) { - if (data == null) - return - + if (data == null) return val notifyPosts = data.getBooleanExtra(NotificationSettingsFollowedDialog.KEY_NOTIFICATION_POSTS, false) val emailPosts = data.getBooleanExtra(NotificationSettingsFollowedDialog.KEY_EMAIL_POSTS, false) val emailPostsFrequency = data.getStringExtra(NotificationSettingsFollowedDialog.KEY_EMAIL_POSTS_FREQUENCY) @@ -32,45 +31,28 @@ interface NotificationsMySitesSettingsFragment { ReaderBlogTable.setNotificationsEnabledByBlogId(mNotificationUpdatedSite!!.toLong(), notifyPosts) val payload: AddOrDeleteSubscriptionPayload = if (notifyPosts) { AnalyticsTracker.track(AnalyticsTracker.Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_ON) - AddOrDeleteSubscriptionPayload( - mNotificationUpdatedSite!!, - AddOrDeleteSubscriptionPayload.SubscriptionAction.NEW - ) + AddOrDeleteSubscriptionPayload(mNotificationUpdatedSite!!, SubscriptionAction.NEW) } else { AnalyticsTracker.track(AnalyticsTracker.Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_OFF) - AddOrDeleteSubscriptionPayload( - mNotificationUpdatedSite!!, - AddOrDeleteSubscriptionPayload.SubscriptionAction.DELETE - ) + AddOrDeleteSubscriptionPayload(mNotificationUpdatedSite!!, SubscriptionAction.DELETE) } mDispatcher.dispatch(AccountActionBuilder.newUpdateSubscriptionNotificationPostAction(payload)) } if (emailPosts != mPreviousEmailPosts) { val payload: AddOrDeleteSubscriptionPayload = if (emailPosts) { AnalyticsTracker.track(AnalyticsTracker.Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_EMAIL_ON) - AddOrDeleteSubscriptionPayload( - mNotificationUpdatedSite!!, - AddOrDeleteSubscriptionPayload.SubscriptionAction.NEW - ) + AddOrDeleteSubscriptionPayload(mNotificationUpdatedSite!!, SubscriptionAction.NEW) } else { AnalyticsTracker.track(AnalyticsTracker.Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_EMAIL_OFF) - AddOrDeleteSubscriptionPayload( - mNotificationUpdatedSite!!, - AddOrDeleteSubscriptionPayload.SubscriptionAction.DELETE - ) + AddOrDeleteSubscriptionPayload(mNotificationUpdatedSite!!, SubscriptionAction.DELETE) } mDispatcher.dispatch(AccountActionBuilder.newUpdateSubscriptionEmailPostAction(payload)) } - if (emailPostsFrequency != null && !emailPostsFrequency.equals( - mPreviousEmailPostsFrequency, - ignoreCase = true - ) + if (emailPostsFrequency != null && !emailPostsFrequency.equals(mPreviousEmailPostsFrequency, ignoreCase = true) ) { val subscriptionFrequency = getSubscriptionFrequencyFromString(emailPostsFrequency) - mUpdateSubscriptionFrequencyPayload = UpdateSubscriptionPayload( - mNotificationUpdatedSite!!, - subscriptionFrequency - ) + mUpdateSubscriptionFrequencyPayload = UpdateSubscriptionPayload(mNotificationUpdatedSite!!, + subscriptionFrequency) /* * The email post frequency update will be overridden by the email post update if the email post * frequency callback returns first. Thus, the updates must be dispatched sequentially when the @@ -81,24 +63,17 @@ interface NotificationsMySitesSettingsFragment { } else { mDispatcher.dispatch( AccountActionBuilder.newUpdateSubscriptionEmailPostFrequencyAction( - mUpdateSubscriptionFrequencyPayload - ) + mUpdateSubscriptionFrequencyPayload) ) } } if (emailComments != mPreviousEmailComments) { val payload: AddOrDeleteSubscriptionPayload = if (emailComments) { AnalyticsTracker.track(AnalyticsTracker.Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_COMMENTS_ON) - AddOrDeleteSubscriptionPayload( - mNotificationUpdatedSite!!, - AddOrDeleteSubscriptionPayload.SubscriptionAction.NEW - ) + AddOrDeleteSubscriptionPayload(mNotificationUpdatedSite!!, SubscriptionAction.NEW) } else { AnalyticsTracker.track(AnalyticsTracker.Stat.FOLLOWED_BLOG_NOTIFICATIONS_SETTINGS_COMMENTS_OFF) - AddOrDeleteSubscriptionPayload( - mNotificationUpdatedSite!!, - AddOrDeleteSubscriptionPayload.SubscriptionAction.DELETE - ) + AddOrDeleteSubscriptionPayload(mNotificationUpdatedSite!!, SubscriptionAction.DELETE) } mDispatcher.dispatch(AccountActionBuilder.newUpdateSubscriptionEmailCommentAction(payload)) } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsDialogFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsDialogFragment.kt index 6ac16fe64557..9e5a9c41e24a 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsDialogFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsDialogFragment.kt @@ -32,7 +32,8 @@ class NotificationsSettingsDialogFragment( private val type: NotificationsSettings.Type, private val blogId: Long = 0, private val settings: NotificationsSettings, - private val onNotificationsSettingsChangedListener: NotificationsSettingsDialogPreference.OnNotificationsSettingsChangedListener, + private val onNotificationsSettingsChangedListener: + NotificationsSettingsDialogPreference.OnNotificationsSettingsChangedListener, private val bloggingRemindersProvider: NotificationsSettingsDialogPreference.BloggingRemindersProvider? = null, private val title: String ): DialogFragment(), PrefMainSwitchToolbarView.MainSwitchToolbarListener, DialogInterface.OnClickListener { @@ -58,12 +59,10 @@ class NotificationsSettingsDialogFragment( override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { val context = requireContext() - @SuppressLint("InflateParams") - val layout = requireActivity().layoutInflater.inflate( - R.layout.notifications_settings_types_dialog, null) - val outerView = layout.findViewById(R.id.outer_view) + val layout = requireActivity().layoutInflater.inflate(R.layout.notifications_settings_types_dialog, null) + val outerView = layout.findViewById(R.id.outer_view) outerView.layoutParams = LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT @@ -110,16 +109,13 @@ class NotificationsSettingsDialogFragment( setNegativeButton(R.string.cancel, this@NotificationsSettingsDialogFragment) setView(layout) } - if (mShouldDisplayMainSwitch) { setupTitleViewWithMainSwitch(outerView) - if (mTitleViewWithMainSwitch == null) { + if (mTitleViewWithMainSwitch == null) AppLog.e(AppLog.T.NOTIFS, "Main switch enabled but layout not set") - } else { + else builder.setCustomTitle(mTitleViewWithMainSwitch) - } } - return builder.create() } @@ -172,15 +168,12 @@ class NotificationsSettingsDialogFragment( } private fun configureLayoutForView(view: LinearLayout): View { - val settingsJson = settings.getSettingsJsonForChannelAndType(this.channel, - this.type, this.blogId - ) + val settingsJson = settings.getSettingsJsonForChannelAndType(this.channel, this.type, this.blogId) var summaryArray = arrayOfNulls(0) when (this.channel) { NotificationsSettings.Channel.BLOGS -> { mSettingsArray = requireContext().resources.getStringArray(R.array.notifications_blog_settings) - mSettingsValues = requireContext().resources - .getStringArray(R.array.notifications_blog_settings_values) + mSettingsValues = requireContext().resources.getStringArray(R.array.notifications_blog_settings_values) } NotificationsSettings.Channel.OTHER -> { @@ -222,7 +215,7 @@ class NotificationsSettingsDialogFragment( } } if (shouldShowLocalNotifications) { - val isBloggingRemindersEnabled = this.bloggingRemindersProvider != null + val isBloggingRemindersEnabled = bloggingRemindersProvider != null addWeeklyRoundupSetting(view, !isBloggingRemindersEnabled) if (isBloggingRemindersEnabled) { addBloggingReminderSetting(view) @@ -257,11 +250,9 @@ class NotificationsSettingsDialogFragment( }) } - private fun setupSwitchSettingView( - settingName: String, settingValue: String?, - settingSummary: String?, isSettingChecked: Boolean, - isSettingLast: Boolean, - onCheckedChangeListener: CompoundButton.OnCheckedChangeListener + private fun setupSwitchSettingView(settingName: String, settingValue: String?, settingSummary: String?, + isSettingChecked: Boolean, isSettingLast: Boolean, + onCheckedChangeListener: CompoundButton.OnCheckedChangeListener ): View { return setupSettingView( settingName, settingValue, settingSummary, isSettingChecked, @@ -269,9 +260,8 @@ class NotificationsSettingsDialogFragment( ) } - private fun setupClickSettingView( - settingName: String, settingSummary: String?, isSettingLast: Boolean, - onClickListener: View.OnClickListener + private fun setupClickSettingView(settingName: String, settingSummary: String?, isSettingLast: Boolean, + onClickListener: View.OnClickListener ): View { return setupSettingView( settingName, null, settingSummary, false, @@ -279,11 +269,10 @@ class NotificationsSettingsDialogFragment( ) } - private fun setupSettingView( - settingName: String, settingValue: String?, settingSummary: String?, - isSettingChecked: Boolean, isSettingLast: Boolean, - onCheckedChangeListener: CompoundButton.OnCheckedChangeListener?, - onClickListener: View.OnClickListener? + private fun setupSettingView(settingName: String, settingValue: String?, settingSummary: String?, + isSettingChecked: Boolean, isSettingLast: Boolean, + onCheckedChangeListener: CompoundButton.OnCheckedChangeListener?, + onClickListener: View.OnClickListener? ): View { NotificationsSettingsSwitchBinding.inflate(layoutInflater).apply { notificationsSwitchTitle.text = settingName diff --git a/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsDialogPreferenceX.kt b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsDialogPreferenceX.kt index 48474d224c09..121f959b4521 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsDialogPreferenceX.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsDialogPreferenceX.kt @@ -5,6 +5,7 @@ import android.util.AttributeSet import androidx.annotation.StringRes import androidx.preference.DialogPreference import org.wordpress.android.models.NotificationsSettings + class NotificationsSettingsDialogPreferenceX( context: Context, attrs: AttributeSet?, diff --git a/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsFragment.kt index 4b9c887bb13a..8ac032452e19 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsFragment.kt @@ -71,7 +71,6 @@ import org.wordpress.android.util.ToastUtils import org.wordpress.android.util.WPPermissionUtils import javax.inject.Inject - class NotificationsSettingsFragment : PreferenceFragmentCompat(), NotificationsMySitesSettingsFragment, OnSharedPreferenceChangeListener { private var mNotificationsSettings: NotificationsSettings? = null @@ -129,7 +128,7 @@ class NotificationsSettingsFragment : PreferenceFragmentCompat(), NotificationsM } } - override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {} + override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) = Unit @Suppress("DEPRECATION") override fun onDisplayPreferenceDialog(preference: Preference) { @@ -501,8 +500,8 @@ class NotificationsSettingsFragment : PreferenceFragmentCompat(), NotificationsM } private fun shouldRequestRuntimePermission(): Boolean { - return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU - && !WPPermissionUtils.isPermissionAlwaysDenied(requireActivity(), Manifest.permission.POST_NOTIFICATIONS)) + return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && + !WPPermissionUtils.isPermissionAlwaysDenied(requireActivity(), Manifest.permission.POST_NOTIFICATIONS)) } @get:StringRes @@ -543,9 +542,28 @@ class NotificationsSettingsFragment : PreferenceFragmentCompat(), NotificationsM .compareTo(SiteUtils.getSiteNameOrHomeURL(o2), ignoreCase = true) } } - val context: Context? = activity blogsCategory!!.removeAll() val maxSitesToShow = if (showAll) NO_MAXIMUM else MAX_SITES_TO_SHOW_ON_FIRST_SCREEN + + setBlogsPreferenceScreen(sites, maxSitesToShow, blogsCategory) + + // Add a message in a preference if there are no matching search results + if (mSiteCount == 0 && !TextUtils.isEmpty(trimmedQuery)) { + val searchResultsPref = Preference(requireContext()) + searchResultsPref.summary = + String.format(getString(R.string.notifications_no_search_results), trimmedQuery) + blogsCategory.addPreference(searchResultsPref) + } + if (mSiteCount > maxSitesToShow && !showAll) { + // append a "view all" option + appendViewAllSitesOption(getString(R.string.pref_notification_blogs), false) + } + updateSearchMenuVisibility() + } + + private fun setBlogsPreferenceScreen(sites: List, maxSitesToShow: Int, + blogsCategory: PreferenceCategory) { + val context: Context? = activity var count = 0 for (site in sites) { if (context == null) { @@ -568,26 +586,12 @@ class NotificationsSettingsFragment : PreferenceFragmentCompat(), NotificationsM prefScreen.fragment = NotificationsSettingsTypesFragment::class.qualifiedName blogsCategory.addPreference(prefScreen) } - - // Add a message in a preference if there are no matching search results - if (mSiteCount == 0 && !TextUtils.isEmpty(trimmedQuery)) { - val searchResultsPref = Preference(requireContext()) - searchResultsPref.summary = - String.format(getString(R.string.notifications_no_search_results), trimmedQuery) - blogsCategory.addPreference(searchResultsPref) - } - if (mSiteCount > maxSitesToShow && !showAll) { - // append a "view all" option - appendViewAllSitesOption(getString(R.string.pref_notification_blogs), false) - } - updateSearchMenuVisibility() } - @Suppress("DEPRECATION") private fun configureFollowedBlogsSettings(blogsCategory: PreferenceCategory?, showAll: Boolean) { - if (!isAdded || blogsCategory == null) { + if (!isAdded || blogsCategory == null) return - } + var models: List var query = "" if (mSearchView != null && !TextUtils.isEmpty(mSearchView!!.query)) { @@ -596,26 +600,41 @@ class NotificationsSettingsFragment : PreferenceFragmentCompat(), NotificationsM } else { models = mFollowedBlogsProvider.getAllFollowedBlogs(null) } - val context: Context? = activity blogsCategory.removeAll() + val maxSitesToShow = if (showAll) NO_MAXIMUM else MAX_SITES_TO_SHOW_ON_FIRST_SCREEN mSubscriptionCount = 0 - if (models.isNotEmpty()) { - models = models.sortedWith { (title): PreferenceModel, (otherTitle): PreferenceModel -> - title.compareTo( - otherTitle, - ignoreCase = true - ) - } + + models = models.sortedWith { (title): PreferenceModel, (otherTitle): PreferenceModel -> + title.compareTo(otherTitle, ignoreCase = true) } + + setFollowedBlogsPreferenceScreen(models, maxSitesToShow, showAll, blogsCategory) + + // Add message if there are no matching search results. + if (mSubscriptionCount == 0 && !TextUtils.isEmpty(query)) { + val searchResultsPref = Preference(requireContext()) + searchResultsPref.summary = String.format(getString(R.string.notifications_no_search_results), query) + blogsCategory.addPreference(searchResultsPref) + } + + // Add view all entry when more sites than maximum to show. + if (!showAll && mSubscriptionCount > maxSitesToShow) { + appendViewAllSitesOption(getString(R.string.pref_notification_blogs_followed), true) + } + updateSearchMenuVisibility() + } + + @Suppress("DEPRECATION") + private fun setFollowedBlogsPreferenceScreen(models: List, maxSitesToShow: Int, showAll: Boolean, + blogsCategory: PreferenceCategory) { + val context: Context? = activity for ((title, summary, blogId, clickHandler) in models) { - if (context == null) { + if (context == null) return - } mSubscriptionCount++ - if (!showAll && mSubscriptionCount > maxSitesToShow) { + if (!showAll && mSubscriptionCount > maxSitesToShow) break - } val prefScreen = preferenceManager.createPreferenceScreen(context) prefScreen.title = title prefScreen.summary = summary @@ -629,28 +648,15 @@ class NotificationsSettingsFragment : PreferenceFragmentCompat(), NotificationsM mPreviousEmailComments = clickHandler.shouldEmailComments val dialog = NotificationSettingsFollowedDialog() val args = Bundle().apply { - putBoolean( - NotificationSettingsFollowedDialog.ARG_NOTIFICATION_POSTS, - mPreviousNotifyPosts - ) - putBoolean( - NotificationSettingsFollowedDialog.ARG_EMAIL_POSTS, - mPreviousEmailPosts - ) - putString( - NotificationSettingsFollowedDialog.ARG_EMAIL_POSTS_FREQUENCY, - mPreviousEmailPostsFrequency - ) - putBoolean( - NotificationSettingsFollowedDialog.ARG_EMAIL_COMMENTS, - mPreviousEmailComments - ) + putBoolean(NotificationSettingsFollowedDialog.ARG_NOTIFICATION_POSTS, mPreviousNotifyPosts) + putBoolean(NotificationSettingsFollowedDialog.ARG_EMAIL_POSTS, mPreviousEmailPosts) + putString(NotificationSettingsFollowedDialog.ARG_EMAIL_POSTS_FREQUENCY, + mPreviousEmailPostsFrequency) + putBoolean(NotificationSettingsFollowedDialog.ARG_EMAIL_COMMENTS, mPreviousEmailComments) } dialog.arguments = args - dialog.setTargetFragment( - this@NotificationsSettingsFragment, - RequestCodes.NOTIFICATION_SETTINGS - ) + dialog.setTargetFragment(this@NotificationsSettingsFragment, + RequestCodes.NOTIFICATION_SETTINGS) dialog.show(parentFragmentManager, NotificationSettingsFollowedDialog.TAG) true } @@ -659,19 +665,6 @@ class NotificationsSettingsFragment : PreferenceFragmentCompat(), NotificationsM } blogsCategory.addPreference(prefScreen) } - - // Add message if there are no matching search results. - if (mSubscriptionCount == 0 && !TextUtils.isEmpty(query)) { - val searchResultsPref = Preference(requireContext()) - searchResultsPref.summary = String.format(getString(R.string.notifications_no_search_results), query) - blogsCategory.addPreference(searchResultsPref) - } - - // Add view all entry when more sites than maximum to show. - if (!showAll && mSubscriptionCount > maxSitesToShow) { - appendViewAllSitesOption(getString(R.string.pref_notification_blogs_followed), true) - } - updateSearchMenuVisibility() } private fun appendViewAllSitesOption(preference: String, isFollowed: Boolean) { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsMySitesFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsMySitesFragment.kt index 0bc7e7002db1..610027a2d000 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsMySitesFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsMySitesFragment.kt @@ -13,8 +13,8 @@ import org.wordpress.android.fluxc.Dispatcher import org.wordpress.android.fluxc.generated.AccountActionBuilder import org.wordpress.android.fluxc.model.SiteModel import org.wordpress.android.fluxc.store.AccountStore -import org.wordpress.android.fluxc.store.AccountStore.OnSubscriptionsChanged import org.wordpress.android.fluxc.store.AccountStore.OnSubscriptionUpdated +import org.wordpress.android.fluxc.store.AccountStore.OnSubscriptionsChanged import org.wordpress.android.fluxc.store.SiteStore import org.wordpress.android.models.NotificationsSettings import org.wordpress.android.ui.RequestCodes @@ -109,11 +109,10 @@ class NotificationsSettingsMySitesFragment: ChildNotificationSettingsFragment(), } } - @Suppress("DEPRECATION") private fun configureFollowedBlogsSettings(blogsCategory: PreferenceCategory?) { - if (!isAdded || blogsCategory == null) { + if (!isAdded || blogsCategory == null) return - } + val models: List = mFollowedBlogsProvider.getAllFollowedBlogs(null) .sortedWith { (title): FollowedBlogsProvider.PreferenceModel, @@ -125,11 +124,16 @@ class NotificationsSettingsMySitesFragment: ChildNotificationSettingsFragment(), } blogsCategory.removeAll() + setFollowedBlogsPreferenceScreen(models, blogsCategory) + } + + @Suppress("DEPRECATION") + private fun setFollowedBlogsPreferenceScreen(models: List, + blogsCategory: PreferenceCategory) { val context: Context? = activity for ((title, summary, blogId, clickHandler) in models) { - if (context == null) { + if (context == null) return - } val prefScreen = preferenceManager.createPreferenceScreen(context) prefScreen.title = title prefScreen.summary = summary @@ -143,28 +147,15 @@ class NotificationsSettingsMySitesFragment: ChildNotificationSettingsFragment(), mPreviousEmailComments = clickHandler.shouldEmailComments val dialog = NotificationSettingsFollowedDialog() val args = Bundle().apply { - putBoolean( - NotificationSettingsFollowedDialog.ARG_NOTIFICATION_POSTS, - mPreviousNotifyPosts - ) - putBoolean( - NotificationSettingsFollowedDialog.ARG_EMAIL_POSTS, - mPreviousEmailPosts - ) - putString( - NotificationSettingsFollowedDialog.ARG_EMAIL_POSTS_FREQUENCY, - mPreviousEmailPostsFrequency - ) - putBoolean( - NotificationSettingsFollowedDialog.ARG_EMAIL_COMMENTS, - mPreviousEmailComments - ) + putBoolean(NotificationSettingsFollowedDialog.ARG_NOTIFICATION_POSTS, mPreviousNotifyPosts) + putBoolean(NotificationSettingsFollowedDialog.ARG_EMAIL_POSTS, mPreviousEmailPosts) + putString(NotificationSettingsFollowedDialog.ARG_EMAIL_POSTS_FREQUENCY, + mPreviousEmailPostsFrequency) + putBoolean(NotificationSettingsFollowedDialog.ARG_EMAIL_COMMENTS, mPreviousEmailComments) } dialog.arguments = args - dialog.setTargetFragment( - this@NotificationsSettingsMySitesFragment, - RequestCodes.NOTIFICATION_SETTINGS - ) + dialog.setTargetFragment(this@NotificationsSettingsMySitesFragment, + RequestCodes.NOTIFICATION_SETTINGS) dialog.show(parentFragmentManager, NotificationSettingsFollowedDialog.TAG) true } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsTypesFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsTypesFragment.kt index a1d5073668c0..65c2aa61e076 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsTypesFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/prefs/notifications/NotificationsSettingsTypesFragment.kt @@ -150,7 +150,8 @@ class NotificationsSettingsTypesFragment: ChildNotificationSettingsFragment() { } private val mOnSettingsChangedListener = - NotificationsSettingsDialogPreference.OnNotificationsSettingsChangedListener { channel, type, blogId, newValues -> + NotificationsSettingsDialogPreference.OnNotificationsSettingsChangedListener { channel, type, blogId, + newValues -> if (!isAdded) { return@OnNotificationsSettingsChangedListener }