mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-02-23 11:15:44 +00:00
Add 'tick' to update conversation bubble timestamps every 1m.
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user