fix: Show the FAB according to the user's preferences (#29)
The previous code didn't collect the uiState, so it was fixed at the default value, ignoring any changes that happened over the life of the viewmodel. Fix that, so that the FAB will hide/show on scroll according to the user's preferences. While I'm here simplify the show/hide logic. The previous code would ignore the user's preference if scrolling up. There doesn't seem to be a good reason for that, and spelunking 6+ years back through the history didn't find a justification for that behaviour in the original commit. Fixes #15
This commit is contained in:
parent
ecd81e80b0
commit
ec66942ae9
@ -2599,7 +2599,7 @@
|
||||
errorLine2=" ~~~~~~~">
|
||||
<location
|
||||
file="src/main/java/app/pachli/components/conversation/ConversationsFragment.kt"
|
||||
line="154"
|
||||
line="155"
|
||||
column="25"/>
|
||||
</issue>
|
||||
|
||||
@ -2610,7 +2610,7 @@
|
||||
errorLine2=" ~~~~~~~">
|
||||
<location
|
||||
file="src/main/java/app/pachli/components/conversation/ConversationsFragment.kt"
|
||||
line="156"
|
||||
line="157"
|
||||
column="33"/>
|
||||
</issue>
|
||||
|
||||
@ -2661,45 +2661,12 @@
|
||||
<issue
|
||||
id="SyntheticAccessor"
|
||||
message="Access to `private` method `getBinding` of class `FollowedTagsActivity` requires synthetic accessor"
|
||||
errorLine1=" if (dy > 0 && binding.fab.isShown) {"
|
||||
errorLine2=" ~~~~~~~">
|
||||
errorLine1=" binding.fab.visible(dy == 0)"
|
||||
errorLine2=" ~~~~~~~">
|
||||
<location
|
||||
file="src/main/java/app/pachli/components/followedtags/FollowedTagsActivity.kt"
|
||||
line="92"
|
||||
column="39"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="SyntheticAccessor"
|
||||
message="Access to `private` method `getBinding` of class `FollowedTagsActivity` requires synthetic accessor"
|
||||
errorLine1=" binding.fab.hide()"
|
||||
errorLine2=" ~~~~~~~">
|
||||
<location
|
||||
file="src/main/java/app/pachli/components/followedtags/FollowedTagsActivity.kt"
|
||||
line="93"
|
||||
column="29"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="SyntheticAccessor"
|
||||
message="Access to `private` method `getBinding` of class `FollowedTagsActivity` requires synthetic accessor"
|
||||
errorLine1=" } else if (dy < 0 && !binding.fab.isShown) {"
|
||||
errorLine2=" ~~~~~~~">
|
||||
<location
|
||||
file="src/main/java/app/pachli/components/followedtags/FollowedTagsActivity.kt"
|
||||
line="94"
|
||||
column="47"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="SyntheticAccessor"
|
||||
message="Access to `private` method `getBinding` of class `FollowedTagsActivity` requires synthetic accessor"
|
||||
errorLine1=" binding.fab.show()"
|
||||
errorLine2=" ~~~~~~~">
|
||||
<location
|
||||
file="src/main/java/app/pachli/components/followedtags/FollowedTagsActivity.kt"
|
||||
line="95"
|
||||
column="29"/>
|
||||
column="25"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
@ -2709,7 +2676,7 @@
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="src/main/java/app/pachli/components/followedtags/FollowedTagsActivity.kt"
|
||||
line="204"
|
||||
line="200"
|
||||
column="21"/>
|
||||
</issue>
|
||||
|
||||
@ -3750,12 +3717,12 @@
|
||||
<issue
|
||||
id="SyntheticAccessor"
|
||||
message="Access to `private` method `getViewModel` of class `NotificationsFragment` requires synthetic accessor"
|
||||
errorLine1=" if (!viewModel.uiState.value.showFabWhileScrolling) {"
|
||||
errorLine2=" ~~~~~~~~~">
|
||||
errorLine1=" actionButton?.visible(viewModel.uiState.value.showFabWhileScrolling || dy == 0)"
|
||||
errorLine2=" ~~~~~~~~~">
|
||||
<location
|
||||
file="src/main/java/app/pachli/components/notifications/NotificationsFragment.kt"
|
||||
line="176"
|
||||
column="30"/>
|
||||
column="43"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
@ -3838,12 +3805,12 @@
|
||||
<issue
|
||||
id="SyntheticAccessor"
|
||||
message="Access to `private` method `getViewModel` of class `TimelineFragment` requires synthetic accessor"
|
||||
errorLine1=" if (!viewModel.uiState.value.showFabWhileScrolling) {"
|
||||
errorLine2=" ~~~~~~~~~">
|
||||
errorLine1=" actionButton?.visible(viewModel.uiState.value.showFabWhileScrolling || dy == 0)"
|
||||
errorLine2=" ~~~~~~~~~">
|
||||
<location
|
||||
file="src/main/java/app/pachli/components/timeline/TimelineFragment.kt"
|
||||
line="177"
|
||||
column="34"/>
|
||||
line="178"
|
||||
column="47"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
|
@ -54,6 +54,7 @@ import app.pachli.util.StatusDisplayOptions
|
||||
import app.pachli.util.hide
|
||||
import app.pachli.util.show
|
||||
import app.pachli.util.viewBinding
|
||||
import app.pachli.util.visible
|
||||
import app.pachli.viewdata.AttachmentViewData
|
||||
import at.connyduck.sparkbutton.helpers.Utils
|
||||
import com.google.android.material.color.MaterialColors
|
||||
@ -87,7 +88,7 @@ class ConversationsFragment :
|
||||
|
||||
private lateinit var adapter: ConversationAdapter
|
||||
|
||||
private var hideFab = false
|
||||
private var showFabWhileScrolling = false
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.fragment_timeline, container, false)
|
||||
@ -161,22 +162,13 @@ class ConversationsFragment :
|
||||
},
|
||||
)
|
||||
|
||||
hideFab = preferences.getBoolean(PrefKeys.FAB_HIDE, false)
|
||||
showFabWhileScrolling = !preferences.getBoolean(PrefKeys.FAB_HIDE, false)
|
||||
binding.recyclerView.addOnScrollListener(
|
||||
object : RecyclerView.OnScrollListener() {
|
||||
val actionButton = (activity as? ActionButtonActivity)?.actionButton
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
actionButton?.visible(showFabWhileScrolling || dy == 0)
|
||||
}
|
||||
},
|
||||
)
|
||||
@ -375,7 +367,7 @@ class ConversationsFragment :
|
||||
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||
when (key) {
|
||||
PrefKeys.FAB_HIDE -> {
|
||||
hideFab = sharedPreferences.getBoolean(PrefKeys.FAB_HIDE, false)
|
||||
showFabWhileScrolling = sharedPreferences.getBoolean(PrefKeys.FAB_HIDE, false)
|
||||
}
|
||||
PrefKeys.MEDIA_PREVIEW_ENABLED -> {
|
||||
val enabled = accountManager.activeAccount!!.mediaPreviewEnabled
|
||||
|
@ -89,11 +89,7 @@ class FollowedTagsActivity :
|
||||
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()
|
||||
}
|
||||
binding.fab.visible(dy == 0)
|
||||
}
|
||||
},
|
||||
)
|
||||
|
@ -65,6 +65,7 @@ import app.pachli.util.hide
|
||||
import app.pachli.util.openLink
|
||||
import app.pachli.util.show
|
||||
import app.pachli.util.viewBinding
|
||||
import app.pachli.util.visible
|
||||
import app.pachli.viewdata.AttachmentViewData.Companion.list
|
||||
import app.pachli.viewdata.NotificationViewData
|
||||
import at.connyduck.sparkbutton.helpers.Utils
|
||||
@ -169,26 +170,18 @@ class NotificationsFragment :
|
||||
|
||||
binding.recyclerView.addOnScrollListener(
|
||||
object : RecyclerView.OnScrollListener() {
|
||||
val actionButton = (activity as ActionButtonActivity).actionButton
|
||||
val actionButton = (activity as? ActionButtonActivity)?.actionButton
|
||||
|
||||
override fun onScrolled(view: RecyclerView, dx: Int, dy: Int) {
|
||||
actionButton?.let { fab ->
|
||||
if (!viewModel.uiState.value.showFabWhileScrolling) {
|
||||
if (dy > 0 && fab.isShown) {
|
||||
fab.hide() // Hide when scrolling down
|
||||
} else if (dy < 0 && !fab.isShown) {
|
||||
fab.show() // Show when scrolling up
|
||||
}
|
||||
} else if (!fab.isShown) {
|
||||
fab.show()
|
||||
}
|
||||
}
|
||||
actionButton?.visible(viewModel.uiState.value.showFabWhileScrolling || dy == 0)
|
||||
}
|
||||
|
||||
@Suppress("SyntheticAccessor")
|
||||
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
|
||||
newState != SCROLL_STATE_IDLE && return
|
||||
|
||||
actionButton?.show()
|
||||
|
||||
// Save the ID of the first notification visible in the list, so the user's
|
||||
// reading position is always restorable.
|
||||
layoutManager.findFirstVisibleItemPosition().takeIf { it != NO_POSITION }?.let { position ->
|
||||
|
@ -71,6 +71,7 @@ import app.pachli.util.hide
|
||||
import app.pachli.util.show
|
||||
import app.pachli.util.unsafeLazy
|
||||
import app.pachli.util.viewBinding
|
||||
import app.pachli.util.visible
|
||||
import app.pachli.util.withPresentationState
|
||||
import app.pachli.viewdata.AttachmentViewData
|
||||
import app.pachli.viewdata.StatusViewData
|
||||
@ -171,23 +172,17 @@ class TimelineFragment :
|
||||
if (actionButtonPresent()) {
|
||||
binding.recyclerView.addOnScrollListener(
|
||||
object : RecyclerView.OnScrollListener() {
|
||||
val actionButton = (activity as? ActionButtonActivity)?.actionButton
|
||||
|
||||
override fun onScrolled(view: RecyclerView, dx: Int, dy: Int) {
|
||||
val composeButton = (activity as ActionButtonActivity).actionButton
|
||||
if (composeButton != null) {
|
||||
if (!viewModel.uiState.value.showFabWhileScrolling) {
|
||||
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()
|
||||
}
|
||||
}
|
||||
actionButton?.visible(viewModel.uiState.value.showFabWhileScrolling || dy == 0)
|
||||
}
|
||||
|
||||
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
|
||||
newState != SCROLL_STATE_IDLE && return
|
||||
|
||||
actionButton?.show()
|
||||
|
||||
saveVisibleId()
|
||||
}
|
||||
},
|
||||
@ -310,6 +305,11 @@ class TimelineFragment :
|
||||
}
|
||||
}
|
||||
|
||||
// Collect the uiState. Nothing is done with it, but if you don't collect it then
|
||||
// accessing viewModel.uiState.value (e.g., to check whether the FAB should be
|
||||
// hidden) always returns the initial state.
|
||||
launch { viewModel.uiState.collect() }
|
||||
|
||||
// Update status display from statusDisplayOptions. If the new options request
|
||||
// relative time display collect the flow to periodically re-bind the UI.
|
||||
launch {
|
||||
|
Loading…
x
Reference in New Issue
Block a user