mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-06-28 01:55:45 +01:00
Fix active chat highlighting when navigating directly to conversation settings.
This commit is contained in:
committed by
jeffrey-signal
parent
97897a84aa
commit
52750e726a
@@ -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<Long> 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<Long> typingThreads);
|
||||
void updateTimestamp();
|
||||
}
|
||||
|
||||
@@ -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<MainNavigationDetailLocation.Conversation>()
|
||||
.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 }
|
||||
|
||||
+10
-8
@@ -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<Conversation, RecyclerView.Vie
|
||||
private final OnConversationClickListener onConversationClickListener;
|
||||
private final ClearFilterViewHolder.OnClearFilterClickListener onClearFilterClicked;
|
||||
private final EmptyFolderViewHolder.OnFolderSettingsClickListener onFolderSettingsClicked;
|
||||
private final Set<Long> typingSet = new HashSet<>();
|
||||
private final Set<Long> 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<Conversation, RecyclerView.Vie
|
||||
case TYPING_INDICATOR -> 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<Conversation, RecyclerView.Vie
|
||||
Locale.getDefault(),
|
||||
typingSet,
|
||||
selectedConversations,
|
||||
activeThreadId);
|
||||
activeRecipientId);
|
||||
} else if (holder.getItemViewType() == TYPE_HEADER) {
|
||||
HeaderViewHolder casted = (HeaderViewHolder) holder;
|
||||
Conversation conversation = Objects.requireNonNull(getItem(position));
|
||||
@@ -232,8 +234,8 @@ class ConversationListAdapter extends ListAdapter<Conversation, RecyclerView.Vie
|
||||
notifyItemRangeChanged(0, getItemCount(), Payload.SELECTION);
|
||||
}
|
||||
|
||||
void setActiveThreadId(long activeThreadId) {
|
||||
this.activeThreadId = activeThreadId;
|
||||
void setActiveRecipientId(@Nullable RecipientId activeRecipientId) {
|
||||
this.activeRecipientId = activeRecipientId;
|
||||
notifyItemRangeChanged(0, getItemCount(), Payload.ACTIVE);
|
||||
}
|
||||
|
||||
|
||||
+12
-12
@@ -44,7 +44,6 @@ import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.content.res.AppCompatResources;
|
||||
import org.signal.core.ui.compose.Snackbars;
|
||||
import androidx.compose.ui.platform.ComposeView;
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
||||
import androidx.core.content.ContextCompat;
|
||||
@@ -66,7 +65,13 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
import org.signal.core.ui.BottomSheetUtil;
|
||||
import org.signal.core.ui.WindowSizeClassExtensionsKt;
|
||||
import org.signal.core.ui.compose.Snackbars;
|
||||
import org.signal.core.ui.view.Stub;
|
||||
import org.signal.core.util.AppForegroundObserver;
|
||||
import org.signal.core.util.DimensionUnit;
|
||||
import org.signal.core.util.ServiceUtil;
|
||||
import org.signal.core.util.Stopwatch;
|
||||
import org.signal.core.util.concurrent.LifecycleDisposable;
|
||||
import org.signal.core.util.concurrent.SignalExecutors;
|
||||
@@ -88,13 +93,13 @@ import org.thoughtcrime.securesms.badges.self.expired.ExpiredOneTimeBadgeBottomS
|
||||
import org.thoughtcrime.securesms.badges.self.expired.MonthlyDonationCanceledBottomSheetDialogFragment;
|
||||
import org.thoughtcrime.securesms.banner.Banner;
|
||||
import org.thoughtcrime.securesms.banner.BannerManager;
|
||||
import org.thoughtcrime.securesms.banner.banners.ArchiveRestoreStatusBanner;
|
||||
import org.thoughtcrime.securesms.banner.banners.ArchiveUploadStatusBanner;
|
||||
import org.thoughtcrime.securesms.banner.banners.CdsPermanentErrorBanner;
|
||||
import org.thoughtcrime.securesms.banner.banners.CdsTemporaryErrorBanner;
|
||||
import org.thoughtcrime.securesms.banner.banners.DeprecatedBuildBanner;
|
||||
import org.thoughtcrime.securesms.banner.banners.DeprecatedSdkBanner;
|
||||
import org.thoughtcrime.securesms.banner.banners.DozeBanner;
|
||||
import org.thoughtcrime.securesms.banner.banners.ArchiveRestoreStatusBanner;
|
||||
import org.thoughtcrime.securesms.banner.banners.OutdatedBuildBanner;
|
||||
import org.thoughtcrime.securesms.banner.banners.ServiceOutageBanner;
|
||||
import org.thoughtcrime.securesms.banner.banners.UnauthorizedBanner;
|
||||
@@ -123,7 +128,6 @@ import org.thoughtcrime.securesms.contacts.paged.ContactSearchRepository;
|
||||
import org.thoughtcrime.securesms.contacts.paged.ContactSearchState;
|
||||
import org.thoughtcrime.securesms.contacts.paged.ContactSearchViewModel;
|
||||
import org.thoughtcrime.securesms.contacts.paged.ContactSearchViewModelKt;
|
||||
import org.thoughtcrime.securesms.search.SearchRepository;
|
||||
import org.thoughtcrime.securesms.contacts.selection.ContactSelectionArguments;
|
||||
import org.thoughtcrime.securesms.conversation.ConversationUpdateTick;
|
||||
import org.thoughtcrime.securesms.conversationlist.chatfilter.ConversationFilterRequest;
|
||||
@@ -156,23 +160,19 @@ import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.thoughtcrime.securesms.search.MessageResult;
|
||||
import org.thoughtcrime.securesms.search.SearchFilter;
|
||||
import org.thoughtcrime.securesms.search.SearchFilterBottomSheet;
|
||||
import org.thoughtcrime.securesms.search.SearchRepository;
|
||||
import org.thoughtcrime.securesms.sms.MessageSender;
|
||||
import org.signal.core.util.AppForegroundObserver;
|
||||
import org.thoughtcrime.securesms.util.AppStartup;
|
||||
import org.signal.core.ui.BottomSheetUtil;
|
||||
import org.signal.core.ui.view.Stub;
|
||||
import org.thoughtcrime.securesms.util.CachedInflater;
|
||||
import org.thoughtcrime.securesms.util.ConversationUtil;
|
||||
import org.signal.core.util.ServiceUtil;
|
||||
import org.thoughtcrime.securesms.util.RemoteConfig;
|
||||
import org.thoughtcrime.securesms.util.SignalLocalMetrics;
|
||||
import org.thoughtcrime.securesms.util.SignalProxyUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.SnapToTopDataObserver;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.PagingMappingAdapter;
|
||||
import org.thoughtcrime.securesms.verify.SelfVerificationFailureSheet;
|
||||
import org.signal.core.ui.WindowSizeClassExtensionsKt;
|
||||
import org.whispersystems.signalservice.api.websocket.WebSocketConnectionState;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
@@ -479,11 +479,11 @@ public class ConversationListFragment extends MainFragment implements Conversati
|
||||
}));
|
||||
|
||||
if (isSplitPane(getResources())) {
|
||||
lifecycleDisposable.add(mainNavigationViewModel.getObservableActiveChatThreadId()
|
||||
lifecycleDisposable.add(mainNavigationViewModel.getObservableActiveRecipientId()
|
||||
.subscribeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(defaultAdapter::setActiveThreadId));
|
||||
.subscribe(id -> defaultAdapter.setActiveRecipientId(id.orElse(null))));
|
||||
} else {
|
||||
defaultAdapter.setActiveThreadId(0);
|
||||
defaultAdapter.setActiveRecipientId(null);
|
||||
}
|
||||
|
||||
requireCallback().bindScrollHelper(list, getViewLifecycleOwner(), chatFolderList, color -> {
|
||||
|
||||
+11
-11
@@ -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<Long> 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
|
||||
|
||||
+4
-2
@@ -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<Long> 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) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -229,7 +229,7 @@ object ConversationListSearchModels {
|
||||
model.thread.query,
|
||||
true,
|
||||
false,
|
||||
0
|
||||
null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Boolean> = internalIsFullScreenPane
|
||||
|
||||
val observableActiveChatThreadId: Observable<Long> =
|
||||
snapshotFlow { chatsBackStack.activeConversationThreadId ?: -1L }
|
||||
.combine(isFullScreenPane) { id, expanded -> if (expanded) -1L else id }
|
||||
val observableActiveRecipientId: Observable<Optional<out RecipientId>> =
|
||||
snapshotFlow { chatsBackStack.activeRecipientId }
|
||||
.combine(isFullScreenPane) { id, expanded -> if (expanded) Optional.ofNullable(null) else Optional.ofNullable(id) }
|
||||
.asObservable()
|
||||
|
||||
private val internalActiveCallId = MutableStateFlow<CallLogRow.Id?>(null)
|
||||
|
||||
Reference in New Issue
Block a user