diff --git a/app/src/main/java/org/thoughtcrime/securesms/BindableConversationListItem.java b/app/src/main/java/org/thoughtcrime/securesms/BindableConversationListItem.java index 8d7ae0137c..e46249bba1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/BindableConversationListItem.java +++ b/app/src/main/java/org/thoughtcrime/securesms/BindableConversationListItem.java @@ -1,12 +1,14 @@ package org.thoughtcrime.securesms; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.lifecycle.LifecycleOwner; import com.bumptech.glide.RequestManager; import org.thoughtcrime.securesms.conversationlist.model.ConversationSet; import org.thoughtcrime.securesms.database.model.ThreadWithRecipient; +import org.thoughtcrime.securesms.recipients.RecipientId; import java.util.Locale; import java.util.Set; @@ -18,10 +20,10 @@ public interface BindableConversationListItem extends Unbindable { @NonNull RequestManager requestManager, @NonNull Locale locale, @NonNull Set typingThreads, @NonNull ConversationSet selectedConversations, - long activeThreadId); + @Nullable RecipientId activeRecipientId); void setSelectedConversations(@NonNull ConversationSet conversations); - void setActiveThreadId(long activeThreadId); + void setActiveRecipientId(@Nullable RecipientId activeRecipientId); void updateTypingIndicator(@NonNull Set typingThreads); void updateTimestamp(); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/chats/ChatsBackStack.kt b/app/src/main/java/org/thoughtcrime/securesms/chats/ChatsBackStack.kt index d85d80e1e0..d7a0f1a35e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/chats/ChatsBackStack.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/chats/ChatsBackStack.kt @@ -12,6 +12,7 @@ import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewmodel.compose.SavedStateHandleSaveableApi import androidx.lifecycle.viewmodel.compose.saveable import org.thoughtcrime.securesms.main.MainNavigationDetailLocation +import org.thoughtcrime.securesms.recipients.RecipientId /** * Controls the navigation stack used by the chats screen. @@ -35,11 +36,14 @@ class ChatsBackStack(savedStateHandle: SavedStateHandle) { mutableStateListOf() } - val activeConversationThreadId: Long? - get() = entries - .filterIsInstance() - .lastOrNull() - ?.controllerKey + val activeRecipientId: RecipientId? + get() = entries.asReversed().firstNotNullOfOrNull { + when (it) { + is MainNavigationDetailLocation.Conversation -> it.conversationArgs.recipientId + is MainNavigationDetailLocation.Chats -> it.controllerKey + else -> null + } + } val hasConversation: Boolean get() = entries.any { it is MainNavigationDetailLocation.Conversation } diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListAdapter.java b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListAdapter.java index 48bc6529bc..fcf4135dcc 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListAdapter.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListAdapter.java @@ -8,6 +8,7 @@ import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; + import androidx.lifecycle.LifecycleOwner; import androidx.recyclerview.widget.DiffUtil; import androidx.recyclerview.widget.ListAdapter; @@ -20,6 +21,7 @@ import org.thoughtcrime.securesms.BindableConversationListItem; import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.conversationlist.model.Conversation; import org.thoughtcrime.securesms.conversationlist.model.ConversationSet; +import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.util.CachedInflater; import org.thoughtcrime.securesms.util.ViewUtil; @@ -53,11 +55,11 @@ class ConversationListAdapter extends ListAdapter typingSet = new HashSet<>(); + private final Set typingSet = new HashSet<>(); - private ConversationSet selectedConversations = new ConversationSet(); - private long activeThreadId = 0; - private PagingController pagingController; + private ConversationSet selectedConversations = new ConversationSet(); + private @Nullable RecipientId activeRecipientId = null; + private PagingController pagingController; protected ConversationListAdapter(@NonNull LifecycleOwner lifecycleOwner, @NonNull RequestManager requestManager, @@ -154,7 +156,7 @@ class ConversationListAdapter extends ListAdapter vh.getConversationListItem().updateTypingIndicator(typingSet); case SELECTION -> vh.getConversationListItem().setSelectedConversations(selectedConversations); case TIMESTAMP -> vh.getConversationListItem().updateTimestamp(); - case ACTIVE -> vh.getConversationListItem().setActiveThreadId(activeThreadId); + case ACTIVE -> vh.getConversationListItem().setActiveRecipientId(activeRecipientId); } } } @@ -173,7 +175,7 @@ class ConversationListAdapter extends ListAdapter defaultAdapter.setActiveRecipientId(id.orElse(null)))); } else { - defaultAdapter.setActiveThreadId(0); + defaultAdapter.setActiveRecipientId(null); } requireCallback().bindScrollHelper(list, getViewLifecycleOwner(), chatFolderList, color -> { diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListItem.java b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListItem.java index 2fe7da05f7..7968a824cd 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListItem.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListItem.java @@ -50,7 +50,9 @@ import com.makeramen.roundedimageview.RoundedDrawable; import org.signal.core.util.ContextUtil; import org.signal.core.util.DimensionUnit; import org.signal.core.util.StringUtil; +import org.signal.core.util.Util; import org.signal.core.util.logging.Log; +import org.signal.glide.decryptableuri.DecryptableUri; import org.thoughtcrime.securesms.BindableConversationListItem; import org.thoughtcrime.securesms.OverlayTransformation; import org.thoughtcrime.securesms.R; @@ -74,7 +76,6 @@ import org.thoughtcrime.securesms.database.model.ThreadWithRecipient; import org.thoughtcrime.securesms.database.model.UpdateDescription; import org.thoughtcrime.securesms.fonts.SignalSymbols.Glyph; import org.thoughtcrime.securesms.glide.targets.GlideLiveDataTarget; -import org.signal.glide.decryptableuri.DecryptableUri; import org.thoughtcrime.securesms.recipients.LiveRecipient; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; @@ -85,7 +86,6 @@ import org.thoughtcrime.securesms.util.MediaUtil; import org.thoughtcrime.securesms.util.SearchUtil; import org.thoughtcrime.securesms.util.SignalE164Util; import org.thoughtcrime.securesms.util.SpanUtil; -import org.signal.core.util.Util; import org.thoughtcrime.securesms.util.livedata.LiveDataUtil; import java.util.List; @@ -214,9 +214,9 @@ public final class ConversationListItem extends ConstraintLayout implements Bind @NonNull Locale locale, @NonNull Set typingThreads, @NonNull ConversationSet selectedConversations, - long activeThreadId) + @Nullable RecipientId activeRecipientId) { - bindThread(lifecycleOwner, thread, glideRequests, locale, typingThreads, selectedConversations, null, false, true, activeThreadId); + bindThread(lifecycleOwner, thread, glideRequests, locale, typingThreads, selectedConversations, null, false, true, activeRecipientId); } public void bindThread(@NonNull LifecycleOwner lifecycleOwner, @@ -228,7 +228,7 @@ public final class ConversationListItem extends ConstraintLayout implements Bind @Nullable String highlightSubstring, boolean appendSystemContactIcon, boolean showPinned, - long activeThreadId) + @Nullable RecipientId activeRecipientId) { this.threadId = thread.getThreadId(); this.requestManager = requestManager; @@ -285,7 +285,7 @@ public final class ConversationListItem extends ConstraintLayout implements Bind this.archivedView.setVisibility(View.GONE); } - setActiveThreadId(activeThreadId); + setActiveRecipientId(activeRecipientId); setStatusIcons(thread); setSelectedConversations(selectedConversations); setBadgeFromRecipient(recipient.get()); @@ -336,7 +336,7 @@ public final class ConversationListItem extends ConstraintLayout implements Bind alertView.setNone(); setSelectedConversations(new ConversationSet()); - setActiveThreadId(0); + setActiveRecipientId(null); setBadgeFromRecipient(recipient.get()); contactPhotoImage.setAvatar(requestManager, recipient.get(), !batchMode, false); } @@ -376,7 +376,7 @@ public final class ConversationListItem extends ConstraintLayout implements Bind alertView.setNone(); setSelectedConversations(new ConversationSet()); - setActiveThreadId(0); + setActiveRecipientId(null); setBadgeFromRecipient(recipient.get()); contactPhotoImage.setAvatar(requestManager, recipient.get(), !batchMode); } @@ -397,7 +397,7 @@ public final class ConversationListItem extends ConstraintLayout implements Bind if (this.recipient != null) { observeRecipient(null, null); setSelectedConversations(new ConversationSet()); - setActiveThreadId(0); + setActiveRecipientId(null); contactPhotoImage.setAvatar(requestManager, null, !batchMode); } @@ -407,8 +407,8 @@ public final class ConversationListItem extends ConstraintLayout implements Bind } @Override - public void setActiveThreadId(long activeThreadId) { - setActivated(activeThreadId > 0 && this.threadId == activeThreadId); + public void setActiveRecipientId(@Nullable RecipientId activeRecipientId) { + setActivated(activeRecipientId != null && this.recipient != null && this.recipient.getId().equals(activeRecipientId)); } @Override diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListItemAction.java b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListItemAction.java index 07cd75ffc5..b061a30999 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListItemAction.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListItemAction.java @@ -6,11 +6,13 @@ import android.widget.FrameLayout; import android.widget.TextView; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.lifecycle.LifecycleOwner; import com.bumptech.glide.RequestManager; import org.thoughtcrime.securesms.BindableConversationListItem; +import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.conversationlist.model.ConversationSet; import org.thoughtcrime.securesms.database.model.ThreadWithRecipient; @@ -47,7 +49,7 @@ public class ConversationListItemAction extends FrameLayout implements BindableC @NonNull Locale locale, @NonNull Set typingThreads, @NonNull ConversationSet selectedConversations, - long activeThreadId) + @Nullable RecipientId activeRecipientId) { this.description.setText(getContext().getString(R.string.ConversationListItemAction_archived_conversations_d, thread.getUnreadCount())); } @@ -58,7 +60,7 @@ public class ConversationListItemAction extends FrameLayout implements BindableC } @Override - public void setActiveThreadId(long activeThreadId) { + public void setActiveRecipientId(@Nullable RecipientId activeRecipientId) { } diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListSearchModels.kt b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListSearchModels.kt index d5ed1ffe71..5e12296942 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListSearchModels.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListSearchModels.kt @@ -229,7 +229,7 @@ object ConversationListSearchModels { model.thread.query, true, false, - 0 + null ) } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/main/MainNavigationViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/main/MainNavigationViewModel.kt index ac9cd8d23a..7cf11491ab 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/main/MainNavigationViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/main/MainNavigationViewModel.kt @@ -46,6 +46,7 @@ import org.thoughtcrime.securesms.megaphone.Megaphone import org.thoughtcrime.securesms.megaphone.Megaphones import org.thoughtcrime.securesms.notifications.profiles.NotificationProfile import org.thoughtcrime.securesms.recipients.Recipient +import org.thoughtcrime.securesms.recipients.RecipientId import org.thoughtcrime.securesms.stories.Stories import org.thoughtcrime.securesms.util.delegate import org.thoughtcrime.securesms.window.AppScaffoldNavigator @@ -92,9 +93,9 @@ class MainNavigationViewModel( private val internalIsFullScreenPane = MutableStateFlow(false) val isFullScreenPane: StateFlow = internalIsFullScreenPane - val observableActiveChatThreadId: Observable = - snapshotFlow { chatsBackStack.activeConversationThreadId ?: -1L } - .combine(isFullScreenPane) { id, expanded -> if (expanded) -1L else id } + val observableActiveRecipientId: Observable> = + snapshotFlow { chatsBackStack.activeRecipientId } + .combine(isFullScreenPane) { id, expanded -> if (expanded) Optional.ofNullable(null) else Optional.ofNullable(id) } .asObservable() private val internalActiveCallId = MutableStateFlow(null)