Add 'tick' to update conversation bubble timestamps every 1m.

This commit is contained in:
Alex Hart
2021-06-09 16:35:36 -03:00
committed by GitHub
parent d5f63da9e4
commit a3e3667dc2
6 changed files with 184 additions and 1 deletions

View File

@@ -52,6 +52,10 @@ public interface BindableConversationItem extends Unbindable, GiphyMp4Playable,
void setEventListener(@Nullable EventListener listener);
default void updateTimestamps() {
// Intentionally Blank.
}
interface EventListener {
void onQuoteClicked(MmsMessageRecord messageRecord);
void onLinkPreviewClicked(@NonNull LinkPreview linkPreview);

View File

@@ -48,12 +48,12 @@ import org.thoughtcrime.securesms.conversation.colors.Colorizer;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.giph.mp4.GiphyMp4Playable;
import org.thoughtcrime.securesms.giph.mp4.GiphyMp4PlaybackPolicyEnforcer;
import org.thoughtcrime.securesms.util.Projection;
import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.util.CachedInflater;
import org.thoughtcrime.securesms.util.DateUtils;
import org.thoughtcrime.securesms.util.Projection;
import org.thoughtcrime.securesms.util.StickyHeaderDecoration;
import org.thoughtcrime.securesms.util.ThemeUtil;
import org.thoughtcrime.securesms.util.Util;
@@ -100,6 +100,8 @@ public class ConversationAdapter
private static final int MESSAGE_TYPE_FOOTER = 6;
private static final int MESSAGE_TYPE_PLACEHOLDER = 7;
private static final int PAYLOAD_TIMESTAMP = 0;
private static final long HEADER_ID = Long.MIN_VALUE;
private static final long FOOTER_ID = Long.MIN_VALUE + 1;
@@ -247,6 +249,24 @@ public class ConversationAdapter
}
}
@Override public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position, @NonNull List<Object> payloads) {
if (payloads.contains(PAYLOAD_TIMESTAMP)) {
switch (getItemViewType(position)) {
case MESSAGE_TYPE_INCOMING_TEXT:
case MESSAGE_TYPE_INCOMING_MULTIMEDIA:
case MESSAGE_TYPE_OUTGOING_TEXT:
case MESSAGE_TYPE_OUTGOING_MULTIMEDIA:
case MESSAGE_TYPE_UPDATE:
ConversationViewHolder conversationViewHolder = (ConversationViewHolder) holder;
conversationViewHolder.getBindable().updateTimestamps();
default:
return;
}
} else {
super.onBindViewHolder(holder, position, payloads);
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
switch (getItemViewType(position)) {
@@ -640,6 +660,10 @@ public class ConversationAdapter
}
}
public void updateTimestamps() {
notifyItemRangeChanged(0, getItemCount(), PAYLOAD_TIMESTAMP);
}
final static class ConversationViewHolder extends RecyclerView.ViewHolder implements GiphyMp4Playable, Colorizable {
public ConversationViewHolder(final @NonNull View itemView) {
super(itemView);

View File

@@ -221,6 +221,7 @@ public class ConversationFragment extends LoggingFragment {
private GiphyMp4ProjectionRecycler giphyMp4ProjectionRecycler;
private Colorizer colorizer;
private ConversationUpdateTick conversationUpdateTick;
public static void prepare(@NonNull Context context) {
FrameLayout parent = new FrameLayout(context);
@@ -332,6 +333,9 @@ public class ConversationFragment extends LoggingFragment {
}
});
conversationUpdateTick = new ConversationUpdateTick(this::updateConversationItemTimestamps);
getViewLifecycleOwner().getLifecycle().addObserver(conversationUpdateTick);
return view;
}
@@ -387,6 +391,13 @@ public class ConversationFragment extends LoggingFragment {
listener.onListVerticalTranslationChanged(list.getTranslationY() - offset);
}
private void updateConversationItemTimestamps() {
ConversationAdapter conversationAdapter = getListAdapter();
if (conversationAdapter != null) {
getListAdapter().updateTimestamps();
}
}
@Override
public void onActivityCreated(Bundle bundle) {
super.onActivityCreated(bundle);

View File

@@ -323,6 +323,11 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
setFooter(messageRecord, nextMessageRecord, locale, groupThread, hasWallpaper);
}
@Override
public void updateTimestamps() {
getActiveFooter(messageRecord).setMessageRecord(messageRecord, locale);
}
@Override
protected void onDetachedFromWindow() {
ConversationSwipeAnimationHelper.update(this, 0f, 1f);

View File

@@ -0,0 +1,51 @@
package org.thoughtcrime.securesms.conversation
import android.os.Handler
import android.os.Looper
import androidx.annotation.VisibleForTesting
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import java.util.concurrent.TimeUnit
/**
* Lifecycle-aware class which will call onTick every 1 minute.
* Used to ensure that conversation timestamps are updated appropriately.
*/
class ConversationUpdateTick(
private val onTickListener: OnTickListener
) : DefaultLifecycleObserver {
private val handler = Handler(Looper.getMainLooper())
private var isResumed = false
override fun onResume(owner: LifecycleOwner) {
isResumed = true
handler.removeCallbacksAndMessages(null)
handler.postDelayed(this::onTick, TIMEOUT)
}
override fun onPause(owner: LifecycleOwner) {
isResumed = false
handler.removeCallbacksAndMessages(null)
}
private fun onTick() {
if (isResumed) {
onTickListener.onTick()
handler.removeCallbacksAndMessages(null)
handler.postDelayed(this::onTick, TIMEOUT)
}
}
interface OnTickListener {
fun onTick()
}
companion object {
@VisibleForTesting
val TIMEOUT = TimeUnit.MINUTES.toMillis(1)
}
}