From 34b53a3c594c078ea56701602545364dc8829887 Mon Sep 17 00:00:00 2001 From: Konrad Pozniak Date: Wed, 5 Jun 2024 19:36:58 +0200 Subject: [PATCH] Replace "Hide compose button while scrolling" setting with bottom padding (#4486) As discussed in our contributors meeting. Advantages: - last element of list never obscured by action button - less code that runs on every scroll - less settings to worry about Additionally: - Added a (smaller) padding to the bottom of lists without action button, I think it looks nice if there is a bit of white space and the nav bar divider and the last list divider don't touch. - The list of filters had no dividers, I added them. - Recyclerviews with fixed height (Drafts, Filters, edits) now have scrollbars - code formatted all touched xml files closes https://github.com/tuskyapp/Tusky/issues/1563 --- .../keylesspalace/tusky/TuskyApplication.kt | 4 +++ .../components/account/AccountActivity.kt | 13 +------ .../conversation/ConversationsFragment.kt | 25 -------------- .../components/filters/FiltersActivity.kt | 5 +++ .../followedtags/FollowedTagsActivity.kt | 15 -------- .../notifications/NotificationsFragment.kt | 24 ------------- .../preference/PreferencesFragment.kt | 7 ---- .../components/timeline/TimelineFragment.kt | 34 +++++-------------- .../tusky/settings/SettingsConstants.kt | 5 ++- .../res/layout-sw640dp/fragment_timeline.xml | 1 + .../fragment_timeline_notifications.xml | 7 ++-- .../layout-sw640dp/fragment_view_thread.xml | 13 ++++--- .../res/layout/activity_announcements.xml | 4 ++- app/src/main/res/layout/activity_drafts.xml | 10 ++++-- app/src/main/res/layout/activity_filters.xml | 6 ++-- .../res/layout/activity_followed_tags.xml | 13 ++++--- app/src/main/res/layout/activity_lists.xml | 4 ++- .../main/res/layout/fragment_account_list.xml | 4 ++- .../res/layout/fragment_domain_blocks.xml | 4 ++- app/src/main/res/layout/fragment_search.xml | 2 ++ app/src/main/res/layout/fragment_timeline.xml | 1 + .../fragment_timeline_notifications.xml | 7 ++-- .../res/layout/fragment_trending_tags.xml | 4 ++- .../main/res/layout/fragment_view_edits.xml | 19 ++++++----- .../main/res/layout/fragment_view_thread.xml | 13 ++++--- app/src/main/res/values/dimens.xml | 4 +++ app/src/main/res/values/strings.xml | 1 - 27 files changed, 98 insertions(+), 151 deletions(-) diff --git a/app/src/main/java/com/keylesspalace/tusky/TuskyApplication.kt b/app/src/main/java/com/keylesspalace/tusky/TuskyApplication.kt index 7e374ba7c..26518eac0 100644 --- a/app/src/main/java/com/keylesspalace/tusky/TuskyApplication.kt +++ b/app/src/main/java/com/keylesspalace/tusky/TuskyApplication.kt @@ -134,6 +134,10 @@ class TuskyApplication : Application(), Configuration.Provider { editor.remove(PrefKeys.TAB_SHOW_HOME_SELF_BOOSTS) } + if (oldVersion < 2024060201) { + editor.remove(PrefKeys.Deprecated.FAB_HIDE) + } + editor.putInt(PrefKeys.SCHEMA_VERSION, newVersion) editor.apply() } diff --git a/app/src/main/java/com/keylesspalace/tusky/components/account/AccountActivity.kt b/app/src/main/java/com/keylesspalace/tusky/components/account/AccountActivity.kt index 00605189e..f3e8e070a 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/account/AccountActivity.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/account/AccountActivity.kt @@ -129,8 +129,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvide private var animateAvatar: Boolean = false private var animateEmojis: Boolean = false - // fields for scroll animation - private var hideFab: Boolean = false + // for scroll animation private var oldOffset: Int = 0 @ColorInt @@ -170,7 +169,6 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvide animateAvatar = preferences.getBoolean(PrefKeys.ANIMATE_GIF_AVATARS, false) animateEmojis = preferences.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false) - hideFab = preferences.getBoolean(PrefKeys.FAB_HIDE, false) handleWindowInsets() setupToolbar() @@ -364,15 +362,6 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvide supportActionBar?.setDisplayShowTitleEnabled(false) } - if (hideFab && !blocking) { - if (verticalOffset > oldOffset) { - binding.accountFloatingActionButton.show() - } - if (verticalOffset < oldOffset) { - binding.accountFloatingActionButton.hide() - } - } - val scaledAvatarSize = (avatarSize + verticalOffset) / avatarSize binding.accountAvatarImageView.scaleX = scaledAvatarSize diff --git a/app/src/main/java/com/keylesspalace/tusky/components/conversation/ConversationsFragment.kt b/app/src/main/java/com/keylesspalace/tusky/components/conversation/ConversationsFragment.kt index 90aae62fe..b32c4bb17 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/conversation/ConversationsFragment.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/conversation/ConversationsFragment.kt @@ -44,7 +44,6 @@ import com.keylesspalace.tusky.appstore.PreferenceChangedEvent import com.keylesspalace.tusky.components.account.AccountActivity import com.keylesspalace.tusky.databinding.FragmentTimelineBinding import com.keylesspalace.tusky.fragment.SFragment -import com.keylesspalace.tusky.interfaces.ActionButtonActivity import com.keylesspalace.tusky.interfaces.ReselectableFragment import com.keylesspalace.tusky.interfaces.StatusActionListener import com.keylesspalace.tusky.settings.PrefKeys @@ -86,8 +85,6 @@ class ConversationsFragment : private var adapter: ConversationAdapter? = null - private var hideFab = false - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { requireActivity().addMenuProvider(this, viewLifecycleOwner, Lifecycle.State.RESUMED) @@ -173,24 +170,6 @@ class ConversationsFragment : } }) - hideFab = preferences.getBoolean(PrefKeys.FAB_HIDE, false) - binding.recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() { - override fun onScrolled(view: RecyclerView, dx: Int, dy: Int) { - val composeButton = (activity as ActionButtonActivity).actionButton - if (composeButton != null) { - if (hideFab) { - if (dy > 0 && composeButton.isShown) { - composeButton.hide() // hides the button if we're scrolling down - } else if (dy < 0 && !composeButton.isShown) { - composeButton.show() // shows it if we are scrolling up - } - } else if (!composeButton.isShown) { - composeButton.show() - } - } - } - }) - viewLifecycleOwner.lifecycleScope.launch { viewModel.conversationFlow.collectLatest { pagingData -> adapter.submitData(pagingData) @@ -407,10 +386,6 @@ class ConversationsFragment : private fun onPreferenceChanged(adapter: ConversationAdapter, key: String) { when (key) { - PrefKeys.FAB_HIDE -> { - hideFab = preferences.getBoolean(PrefKeys.FAB_HIDE, false) - } - PrefKeys.MEDIA_PREVIEW_ENABLED -> { val enabled = accountManager.activeAccount!!.mediaPreviewEnabled val oldMediaPreviewEnabled = adapter.mediaPreviewEnabled diff --git a/app/src/main/java/com/keylesspalace/tusky/components/filters/FiltersActivity.kt b/app/src/main/java/com/keylesspalace/tusky/components/filters/FiltersActivity.kt index 94a0c59c2..8d8e91ebb 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/filters/FiltersActivity.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/filters/FiltersActivity.kt @@ -6,6 +6,7 @@ import android.os.Bundle import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.viewModels import androidx.lifecycle.lifecycleScope +import androidx.recyclerview.widget.DividerItemDecoration import com.keylesspalace.tusky.BaseActivity import com.keylesspalace.tusky.R import com.keylesspalace.tusky.databinding.ActivityFiltersBinding @@ -51,6 +52,10 @@ class FiltersActivity : BaseActivity(), FiltersListener { setTitle(R.string.pref_title_timeline_filters) + binding.filtersList.addItemDecoration( + DividerItemDecoration(this, DividerItemDecoration.VERTICAL) + ) + observeViewModel() } diff --git a/app/src/main/java/com/keylesspalace/tusky/components/followedtags/FollowedTagsActivity.kt b/app/src/main/java/com/keylesspalace/tusky/components/followedtags/FollowedTagsActivity.kt index 0a843eec1..2be476067 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/followedtags/FollowedTagsActivity.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/followedtags/FollowedTagsActivity.kt @@ -13,7 +13,6 @@ import androidx.lifecycle.lifecycleScope import androidx.paging.LoadState import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager -import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.SimpleItemAnimator import at.connyduck.calladapter.networkresult.fold import com.google.android.material.snackbar.Snackbar @@ -24,7 +23,6 @@ import com.keylesspalace.tusky.components.compose.ComposeAutoCompleteAdapter import com.keylesspalace.tusky.databinding.ActivityFollowedTagsBinding import com.keylesspalace.tusky.interfaces.HashtagActionListener import com.keylesspalace.tusky.network.MastodonApi -import com.keylesspalace.tusky.settings.PrefKeys import com.keylesspalace.tusky.util.copyToClipboard import com.keylesspalace.tusky.util.hide import com.keylesspalace.tusky.util.show @@ -85,19 +83,6 @@ class FollowedTagsActivity : DividerItemDecoration(this, DividerItemDecoration.VERTICAL) ) (binding.followedTagsView.itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false - - val hideFab = sharedPreferences.getBoolean(PrefKeys.FAB_HIDE, false) - if (hideFab) { - binding.followedTagsView.addOnScrollListener(object : RecyclerView.OnScrollListener() { - override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { - if (dy > 0 && binding.fab.isShown) { - binding.fab.hide() - } else if (dy < 0 && !binding.fab.isShown) { - binding.fab.show() - } - } - }) - } } private fun setupAdapter(): FollowedTagsAdapter { diff --git a/app/src/main/java/com/keylesspalace/tusky/components/notifications/NotificationsFragment.kt b/app/src/main/java/com/keylesspalace/tusky/components/notifications/NotificationsFragment.kt index a8021bd2b..8398f953c 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/notifications/NotificationsFragment.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/notifications/NotificationsFragment.kt @@ -55,7 +55,6 @@ import com.keylesspalace.tusky.databinding.NotificationsFilterBinding import com.keylesspalace.tusky.entity.Notification import com.keylesspalace.tusky.fragment.SFragment import com.keylesspalace.tusky.interfaces.AccountActionListener -import com.keylesspalace.tusky.interfaces.ActionButtonActivity import com.keylesspalace.tusky.interfaces.ReselectableFragment import com.keylesspalace.tusky.interfaces.StatusActionListener import com.keylesspalace.tusky.settings.PrefKeys @@ -100,7 +99,6 @@ class NotificationsFragment : private var adapter: NotificationsPagingAdapter? = null - private var hideFab: Boolean = false private var showNotificationsFilterBar: Boolean = true private var readingOrder: ReadingOrder = ReadingOrder.NEWEST_FIRST @@ -180,26 +178,8 @@ class NotificationsFragment : DividerItemDecoration(context, DividerItemDecoration.VERTICAL) ) - hideFab = preferences.getBoolean(PrefKeys.FAB_HIDE, false) readingOrder = ReadingOrder.from(preferences.getString(PrefKeys.READING_ORDER, null)) - binding.recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() { - override fun onScrolled(view: RecyclerView, dx: Int, dy: Int) { - val composeButton = (activity as ActionButtonActivity).actionButton - if (composeButton != null) { - if (hideFab) { - if (dy > 0 && composeButton.isShown) { - composeButton.hide() // hides the button if we're scrolling down - } else if (dy < 0 && !composeButton.isShown) { - composeButton.show() // shows it if we are scrolling up - } - } else if (!composeButton.isShown) { - composeButton.show() - } - } - } - }) - adapter.addLoadStateListener { loadState -> if (loadState.refresh != LoadState.Loading && loadState.source.refresh != LoadState.Loading) { binding.swipeRefreshLayout.isRefreshing = false @@ -481,10 +461,6 @@ class NotificationsFragment : private fun onPreferenceChanged(adapter: NotificationsPagingAdapter, key: String) { when (key) { - PrefKeys.FAB_HIDE -> { - hideFab = preferences.getBoolean(PrefKeys.FAB_HIDE, false) - } - PrefKeys.MEDIA_PREVIEW_ENABLED -> { val enabled = accountManager.activeAccount!!.mediaPreviewEnabled val oldMediaPreviewEnabled = adapter.mediaPreviewEnabled diff --git a/app/src/main/java/com/keylesspalace/tusky/components/preference/PreferencesFragment.kt b/app/src/main/java/com/keylesspalace/tusky/components/preference/PreferencesFragment.kt index d1379ce2d..3ca6ca6a0 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/preference/PreferencesFragment.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/preference/PreferencesFragment.kt @@ -170,13 +170,6 @@ class PreferencesFragment : PreferenceFragmentCompat() { isSingleLineTitle = false } - switchPreference { - setDefaultValue(false) - key = PrefKeys.FAB_HIDE - setTitle(R.string.pref_title_hide_follow_button) - isSingleLineTitle = false - } - switchPreference { setDefaultValue(false) key = PrefKeys.ABSOLUTE_TIME_VIEW diff --git a/app/src/main/java/com/keylesspalace/tusky/components/timeline/TimelineFragment.kt b/app/src/main/java/com/keylesspalace/tusky/components/timeline/TimelineFragment.kt index db27aa377..796ee7b2e 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/timeline/TimelineFragment.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/timeline/TimelineFragment.kt @@ -25,6 +25,7 @@ import android.view.View import android.view.accessibility.AccessibilityManager import androidx.core.content.getSystemService import androidx.core.view.MenuProvider +import androidx.core.view.updatePadding import androidx.lifecycle.Lifecycle import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope @@ -109,7 +110,6 @@ class TimelineFragment : private var adapter: TimelinePagingAdapter? = null private var isSwipeToRefreshEnabled = true - private var hideFab = false /** * Adapter position of the placeholder that was most recently clicked to "Load more". If null @@ -279,26 +279,6 @@ class TimelineFragment : } } - if (actionButtonPresent()) { - hideFab = preferences.getBoolean(PrefKeys.FAB_HIDE, false) - binding.recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() { - override fun onScrolled(view: RecyclerView, dx: Int, dy: Int) { - val composeButton = (activity as ActionButtonActivity).actionButton - if (composeButton != null) { - if (hideFab) { - if (dy > 0 && composeButton.isShown) { - composeButton.hide() // hides the button if we're scrolling down - } else if (dy < 0 && !composeButton.isShown) { - composeButton.show() // shows it if we are scrolling up - } - } else if (!composeButton.isShown) { - composeButton.show() - } - } - } - }) - } - viewLifecycleOwner.lifecycleScope.launch { eventHub.events.collect { event -> when (event) { @@ -411,6 +391,14 @@ class TimelineFragment : val divider = DividerItemDecoration(context, RecyclerView.VERTICAL) binding.recyclerView.addItemDecoration(divider) + val recyclerViewBottomPadding = if ((activity as? ActionButtonActivity?)?.actionButton != null) { + resources.getDimensionPixelSize(R.dimen.recyclerview_bottom_padding_actionbutton) + } else { + resources.getDimensionPixelSize(R.dimen.recyclerview_bottom_padding_no_actionbutton) + } + + binding.recyclerView.updatePadding(bottom = recyclerViewBottomPadding) + // CWs are expanded without animation, buttons animate itself, we don't need it basically (binding.recyclerView.itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false binding.recyclerView.adapter = adapter @@ -573,10 +561,6 @@ class TimelineFragment : private fun onPreferenceChanged(adapter: TimelinePagingAdapter, key: String) { when (key) { - PrefKeys.FAB_HIDE -> { - hideFab = preferences.getBoolean(PrefKeys.FAB_HIDE, false) - } - PrefKeys.MEDIA_PREVIEW_ENABLED -> { val enabled = accountManager.activeAccount!!.mediaPreviewEnabled val oldMediaPreviewEnabled = adapter.mediaPreviewEnabled diff --git a/app/src/main/java/com/keylesspalace/tusky/settings/SettingsConstants.kt b/app/src/main/java/com/keylesspalace/tusky/settings/SettingsConstants.kt index 8e7d9d932..e6061e6b2 100644 --- a/app/src/main/java/com/keylesspalace/tusky/settings/SettingsConstants.kt +++ b/app/src/main/java/com/keylesspalace/tusky/settings/SettingsConstants.kt @@ -56,7 +56,6 @@ object PrefKeys { const val SCHEMA_VERSION: String = "schema_version" const val APP_THEME = "appTheme" - const val FAB_HIDE = "fabHide" const val LANGUAGE = "language" const val STATUS_TEXT_SIZE = "statusTextSize" const val READING_ORDER = "readingOrder" @@ -112,4 +111,8 @@ object PrefKeys { /** UI text scaling factor, stored as float, 100 = 100% = no scaling */ const val UI_TEXT_SCALE_RATIO = "uiTextScaleRatio" + + object Deprecated { + const val FAB_HIDE = "fabHide" + } } diff --git a/app/src/main/res/layout-sw640dp/fragment_timeline.xml b/app/src/main/res/layout-sw640dp/fragment_timeline.xml index af49280d9..f2fd7001f 100644 --- a/app/src/main/res/layout-sw640dp/fragment_timeline.xml +++ b/app/src/main/res/layout-sw640dp/fragment_timeline.xml @@ -32,6 +32,7 @@ diff --git a/app/src/main/res/layout-sw640dp/fragment_timeline_notifications.xml b/app/src/main/res/layout-sw640dp/fragment_timeline_notifications.xml index 99b19573e..1a9dab8b2 100644 --- a/app/src/main/res/layout-sw640dp/fragment_timeline_notifications.xml +++ b/app/src/main/res/layout-sw640dp/fragment_timeline_notifications.xml @@ -1,5 +1,4 @@ - - + 88dp + 32dp + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 36265cf5e..0ffef2cf3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -314,7 +314,6 @@ Browser Use Chrome Custom Tabs - Hide compose button while scrolling Language Show indicator for bots Animate GIF avatars