Show typing indicators

This commit is contained in:
Niels Andriesse 2021-06-24 11:22:32 +10:00
parent f66309afd8
commit 38710814e2
9 changed files with 84 additions and 12 deletions

View File

@ -8,6 +8,7 @@ import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;
import org.thoughtcrime.securesms.conversation.v2.TypingIndicatorView;
import org.thoughtcrime.securesms.mms.GlideRequests;
import org.session.libsession.utilities.recipients.Recipient;
import org.session.libsession.utilities.ThemeUtil;

View File

@ -26,6 +26,8 @@ import kotlinx.android.synthetic.main.view_input_bar_recording.*
import kotlinx.android.synthetic.main.view_input_bar_recording.view.*
import network.loki.messenger.R
import org.session.libsession.messaging.mentions.MentionsManager
import org.session.libsession.utilities.recipients.Recipient
import org.thoughtcrime.securesms.ApplicationContext
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
import org.thoughtcrime.securesms.conversation.v2.input_bar.InputBarButton
import org.thoughtcrime.securesms.conversation.v2.input_bar.InputBarDelegate
@ -106,6 +108,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
addOpenGroupGuidelinesIfNeeded()
scrollToBottomButton.setOnClickListener { conversationRecyclerView.smoothScrollToPosition(0) }
updateUnreadCount()
setUpTypingObserver()
}
private fun setUpRecyclerView() {
@ -175,6 +178,15 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
conversationRecyclerView.layoutParams = recyclerViewLayoutParams
}
private fun setUpTypingObserver() {
ApplicationContext.getInstance(this).typingStatusRepository.getTypists(threadID).observe(this) { state ->
val recipients = if (state != null) state.typists else listOf()
typingIndicatorViewContainer.isVisible = recipients.isNotEmpty()
typingIndicatorViewContainer.setTypists(recipients)
inputBarHeightChanged(inputBar.height)
}
}
override fun onPrepareOptionsMenu(menu: Menu): Boolean {
ConversationMenuHelper.onPrepareOptionsMenu(menu, menuInflater, thread, this) { onOptionsItemSelected(it) }
super.onPrepareOptionsMenu(menu)
@ -189,9 +201,12 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
// region Updating & Animation
override fun inputBarHeightChanged(newValue: Int) {
// 36 DP is the exact height of the typing indicator view. It's also exactly 18 * 2, and 18 is the large message
// corner radius. This makes 36 DP look "correct" in the context of other messages on the screen.
val typingIndicatorHeight = if (typingIndicatorViewContainer.isVisible) toPx(36, resources) else 0
// Recycler view
val recyclerViewLayoutParams = conversationRecyclerView.layoutParams as RelativeLayout.LayoutParams
recyclerViewLayoutParams.bottomMargin = newValue + additionalContentContainer.height
recyclerViewLayoutParams.bottomMargin = newValue + additionalContentContainer.height + typingIndicatorHeight
conversationRecyclerView.layoutParams = recyclerViewLayoutParams
// Additional content container
val additionalContentContainerLayoutParams = additionalContentContainer.layoutParams as RelativeLayout.LayoutParams

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.components;
package org.thoughtcrime.securesms.conversation.v2;
import android.content.Context;
import android.content.res.TypedArray;
@ -13,18 +13,14 @@ import android.widget.LinearLayout;
import network.loki.messenger.R;
public class TypingIndicatorView extends LinearLayout {
private boolean isActive;
private long startTime;
private static final long DURATION = 300;
private static final long PRE_DELAY = 500;
private static final long POST_DELAY = 500;
private static final long CYCLE_DURATION = 1500;
private static final long DOT_DURATION = 600;
private static final float MIN_ALPHA = 0.4f;
private static final float MIN_SCALE = 0.75f;
private boolean isActive;
private long startTime;
private View dot1;
private View dot2;
private View dot3;
@ -40,7 +36,7 @@ public class TypingIndicatorView extends LinearLayout {
}
private void initialize(@Nullable AttributeSet attrs) {
inflate(getContext(), R.layout.typing_indicator_view, this);
inflate(getContext(), R.layout.view_typing_indicator, this);
setWillNotDraw(false);

View File

@ -0,0 +1,25 @@
package org.thoughtcrime.securesms.conversation.v2
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.LinearLayout
import kotlinx.android.synthetic.main.view_conversation_typing_container.view.*
import network.loki.messenger.R
import org.session.libsession.utilities.recipients.Recipient
class TypingIndicatorViewContainer : LinearLayout {
constructor(context: Context) : super(context) { initialize() }
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { initialize() }
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { initialize() }
private fun initialize() {
LayoutInflater.from(context).inflate(R.layout.view_conversation_typing_container, this)
}
fun setTypists(typists: List<Recipient>) {
if (typists.isEmpty()) { typingIndicator.stopAnimation(); return }
typingIndicator.startAnimation()
}
}

View File

@ -18,6 +18,14 @@
android:layout_height="match_parent"
android:layout_marginBottom="@dimen/input_bar_height" />
<org.thoughtcrime.securesms.conversation.v2.TypingIndicatorViewContainer
android:id="@+id/typingIndicatorViewContainer"
android:layout_width="match_parent"
android:layout_height="36dp"
android:layout_marginBottom="@dimen/input_bar_height"
android:visibility="gone"
android:layout_alignParentBottom="true" />
<org.thoughtcrime.securesms.conversation.v2.input_bar.InputBar
android:id="@+id/inputBar"
android:layout_width="match_parent"

View File

@ -24,7 +24,7 @@
android:padding="12dp"
android:background="@drawable/message_bubble_background">
<org.thoughtcrime.securesms.components.TypingIndicatorView
<org.thoughtcrime.securesms.conversation.v2.TypingIndicatorView
android:id="@+id/typing_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />

View File

@ -126,7 +126,7 @@
android:textColor="@color/text"
tools:text="Sorry, gotta go fight crime again" />
<org.thoughtcrime.securesms.components.TypingIndicatorView
<org.thoughtcrime.securesms.conversation.v2.TypingIndicatorView
android:id="@+id/typingIndicatorView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="12dp"
android:paddingEnd="8dp"
android:paddingBottom="@dimen/small_spacing"
android:gravity="center_vertical">
<FrameLayout
android:id="@+id/typingIndicatorBubble"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="7dp"
android:background="@drawable/message_bubble_background_received_alone"
android:backgroundTint="?message_received_background_color">
<org.thoughtcrime.securesms.conversation.v2.TypingIndicatorView
android:id="@+id/typingIndicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</FrameLayout>
</FrameLayout>

View File

@ -5,7 +5,7 @@
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="org.thoughtcrime.securesms.components.TypingIndicatorView">
tools:context="org.thoughtcrime.securesms.conversation.v2.TypingIndicatorView">
<View
android:id="@+id/typing_dot1"