Scroll date header in CFV2.

This commit is contained in:
Alex Hart
2023-07-13 14:03:27 -03:00
committed by Nicholas Tinsley
parent 5731bf023a
commit 980f4e00e2
3 changed files with 112 additions and 0 deletions

View File

@@ -31,6 +31,7 @@ import android.view.View
import android.view.View.OnFocusChangeListener
import android.view.ViewGroup
import android.view.ViewTreeObserver
import android.view.animation.AnimationUtils
import android.view.inputmethod.EditorInfo
import android.widget.ImageButton
import android.widget.TextView
@@ -274,6 +275,7 @@ import org.thoughtcrime.securesms.util.BottomSheetUtil
import org.thoughtcrime.securesms.util.BubbleUtil
import org.thoughtcrime.securesms.util.CommunicationActions
import org.thoughtcrime.securesms.util.ContextUtil
import org.thoughtcrime.securesms.util.DateUtils
import org.thoughtcrime.securesms.util.Debouncer
import org.thoughtcrime.securesms.util.DeleteDialog
import org.thoughtcrime.securesms.util.Dialogs
@@ -332,6 +334,9 @@ class ConversationFragment :
private const val ACTION_PINNED_SHORTCUT = "action_pinned_shortcut"
private const val SAVED_STATE_IS_SEARCH_REQUESTED = "is_search_requested"
private const val EMOJI_SEARCH_FRAGMENT_TAG = "EmojiSearchFragment"
private const val SCROLL_HEADER_ANIMATION_DURATION: Long = 100L
private const val SCROLL_HEADER_CLOSE_DELAY: Long = SCROLL_HEADER_ANIMATION_DURATION * 4
}
private val args: ConversationIntents.Args by lazy {
@@ -1159,6 +1164,17 @@ class ConversationFragment :
R.color.signal_colorBackground
}
binding.scrollDateHeader.setBackgroundResource(
if (wallpaperEnabled) R.drawable.sticky_date_header_background_wallpaper else R.drawable.sticky_date_header_background
)
binding.scrollDateHeader.setTextColor(
ContextCompat.getColor(
requireContext(),
if (wallpaperEnabled) R.color.sticky_header_foreground_wallpaper else R.color.signal_colorOnSurfaceVariant
)
)
WindowUtil.setNavigationBarColor(requireActivity(), ContextCompat.getColor(requireContext(), navColor))
}
@@ -2019,9 +2035,63 @@ class ConversationFragment :
return layoutManager.findFirstCompletelyVisibleItemPosition() > 4
}
/**
* Controls animation and visibility of the scrollDateHeader.
*/
private inner class ScrollDateHeaderHelper {
private val slideIn = AnimationUtils.loadAnimation(
requireContext(),
R.anim.slide_from_top
).apply {
duration = SCROLL_HEADER_ANIMATION_DURATION
}
private val slideOut = AnimationUtils.loadAnimation(
requireContext(),
R.anim.conversation_scroll_date_header_slide_to_top
).apply {
duration = SCROLL_HEADER_ANIMATION_DURATION
}
private var pendingHide = false
fun show() {
if (binding.scrollDateHeader.text.isNullOrEmpty()) {
return
}
if (pendingHide) {
pendingHide = false
} else {
ViewUtil.animateIn(binding.scrollDateHeader, slideIn)
}
}
fun bind(message: ConversationMessage?) {
if (message != null) {
binding.scrollDateHeader.text = DateUtils.getConversationDateHeaderString(requireContext(), Locale.getDefault(), message.conversationTimestamp)
} else {
binding.scrollDateHeader.text = null
}
}
fun hide() {
pendingHide = true
binding.scrollDateHeader.postDelayed({
if (pendingHide) {
pendingHide = false
ViewUtil.animateOut(binding.scrollDateHeader, slideOut)
}
}, SCROLL_HEADER_CLOSE_DELAY)
}
}
private inner class ScrollListener : RecyclerView.OnScrollListener() {
private var wasAtBottom = true
private val scrollDateHeaderHelper = ScrollDateHeaderHelper()
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
if (isScrolledToBottom()) {
@@ -2032,10 +2102,21 @@ class ConversationFragment :
presentComposeDivider()
val message = adapter.getConversationMessage(layoutManager.findLastVisibleItemPosition())
scrollDateHeaderHelper.bind(message)
val timestamp = MarkReadHelper.getLatestTimestamp(adapter, layoutManager)
timestamp.ifPresent(markReadHelper::onViewsRevealed)
}
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
if (newState == RecyclerView.SCROLL_STATE_DRAGGING) {
scrollDateHeaderHelper.show()
} else {
scrollDateHeaderHelper.hide()
}
}
private fun presentComposeDivider() {
val isAtBottom = isScrolledToBottom()
if (isAtBottom && !wasAtBottom) {

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:fromAlpha="1"
android:toAlpha="0" />
<translate
android:fromYDelta="0%"
android:toYDelta="-100%" />
</set>

View File

@@ -51,6 +51,27 @@
tools:itemCount="20"
tools:listitem="@layout/conversation_item_sent_text_only" />
<TextView
android:id="@+id/scroll_date_header"
style="@style/Signal.Text.BodySmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:background="@drawable/sticky_date_header_background"
android:elevation="9dp"
android:gravity="center"
android:paddingStart="12dp"
android:paddingTop="4dp"
android:paddingEnd="12dp"
android:paddingBottom="4dp"
android:textColor="@color/signal_colorOnSurfaceVariant"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/conversation_banner"
tools:text="March 1, 2015"
tools:visibility="visible" />
<View
android:id="@+id/toolbar_background"
android:layout_width="0dp"