mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-21 17:29:32 +01:00
Fix various bugs around unread counts and scroll to bottom.
This commit is contained in:
@@ -217,6 +217,7 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
|
||||
private Animation mentionButtonOutAnimation;
|
||||
private OnScrollListener conversationScrollListener;
|
||||
private int pulsePosition = -1;
|
||||
private int lastSeenScrollOffset;
|
||||
private View toolbarShadow;
|
||||
private Stopwatch startupStopwatch;
|
||||
|
||||
@@ -365,7 +366,10 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
|
||||
getViewLifecycleOwner().getLifecycle().addObserver(conversationUpdateTick);
|
||||
|
||||
listener.getVoiceNoteMediaController().getVoiceNotePlayerViewState().observe(getViewLifecycleOwner(), state -> conversationViewModel.setInlinePlayerVisible(state.isPresent()));
|
||||
conversationViewModel.getScrollDateTopMargin().observe(getViewLifecycleOwner(), topMargin -> ViewUtil.setTopMargin(scrollDateHeader, topMargin));
|
||||
conversationViewModel.getConversationTopMargin().observe(getViewLifecycleOwner(), topMargin -> {
|
||||
lastSeenScrollOffset = topMargin;
|
||||
ViewUtil.setTopMargin(scrollDateHeader, topMargin + ViewUtil.dpToPx(8));
|
||||
});
|
||||
|
||||
return view;
|
||||
}
|
||||
@@ -1101,7 +1105,7 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
|
||||
.submit();
|
||||
} else if (conversation.getMessageRequestData().isMessageRequestAccepted()) {
|
||||
snapToTopDataObserver.buildScrollPosition(conversation.shouldScrollToLastSeen() ? lastSeenPosition : lastScrolledPosition)
|
||||
.withOnPerformScroll((layoutManager, position) -> layoutManager.scrollToPositionWithOffset(position, list.getHeight()))
|
||||
.withOnPerformScroll((layoutManager, position) -> layoutManager.scrollToPositionWithOffset(position, list.getHeight() - (conversation.shouldScrollToLastSeen() ? lastSeenScrollOffset : 0)))
|
||||
.withOnScrollRequestComplete(afterScroll)
|
||||
.submit();
|
||||
} else {
|
||||
@@ -1247,7 +1251,7 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
|
||||
public void onGlobalLayout() {
|
||||
Rect rect = new Rect();
|
||||
toolbar.getGlobalVisibleRect(rect);
|
||||
conversationViewModel.setToolbarBottom(rect.bottom + ViewUtil.dpToPx(8));
|
||||
conversationViewModel.setToolbarBottom(rect.bottom);
|
||||
ViewUtil.setTopMargin(conversationBanner, rect.bottom + ViewUtil.dpToPx(16));
|
||||
toolbar.getViewTreeObserver().removeOnGlobalLayoutListener(this);
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ public class ConversationViewModel extends ViewModel {
|
||||
private final LiveData<ChatColors> chatColors;
|
||||
private final MutableLiveData<Integer> toolbarBottom;
|
||||
private final MutableLiveData<Integer> inlinePlayerHeight;
|
||||
private final LiveData<Integer> scrollDateTopMargin;
|
||||
private final LiveData<Integer> conversationTopMargin;
|
||||
|
||||
private final Map<GroupId, Set<Recipient>> sessionMemberCache = new HashMap<>();
|
||||
|
||||
@@ -98,7 +98,7 @@ public class ConversationViewModel extends ViewModel {
|
||||
this.messageInsertObserver = messageId -> pagingController.onDataItemInserted(messageId, 0);
|
||||
this.toolbarBottom = new MutableLiveData<>();
|
||||
this.inlinePlayerHeight = new MutableLiveData<>();
|
||||
this.scrollDateTopMargin = Transformations.distinctUntilChanged(LiveDataUtil.combineLatest(toolbarBottom, inlinePlayerHeight, Integer::sum));
|
||||
this.conversationTopMargin = Transformations.distinctUntilChanged(LiveDataUtil.combineLatest(toolbarBottom, inlinePlayerHeight, Integer::sum));
|
||||
|
||||
LiveData<Recipient> recipientLiveData = LiveDataUtil.mapAsync(recipientId, Recipient::resolved);
|
||||
LiveData<ThreadAndRecipient> threadAndRecipient = LiveDataUtil.combineLatest(threadId, recipientLiveData, ThreadAndRecipient::new);
|
||||
@@ -161,11 +161,11 @@ public class ConversationViewModel extends ViewModel {
|
||||
}
|
||||
|
||||
void setToolbarBottom(int bottom) {
|
||||
toolbarBottom.postValue(bottom);
|
||||
toolbarBottom.setValue(bottom);
|
||||
}
|
||||
|
||||
void setInlinePlayerVisible(boolean isVisible) {
|
||||
inlinePlayerHeight.postValue(isVisible ? ViewUtil.dpToPx(36) : 0);
|
||||
inlinePlayerHeight.setValue(isVisible ? ViewUtil.dpToPx(36) : 0);
|
||||
}
|
||||
|
||||
void onAttachmentKeyboardOpen() {
|
||||
@@ -186,8 +186,8 @@ public class ConversationViewModel extends ViewModel {
|
||||
this.threadId.postValue(-1L);
|
||||
}
|
||||
|
||||
@NonNull LiveData<Integer> getScrollDateTopMargin() {
|
||||
return scrollDateTopMargin;
|
||||
@NonNull LiveData<Integer> getConversationTopMargin() {
|
||||
return conversationTopMargin;
|
||||
}
|
||||
|
||||
@NonNull LiveData<Boolean> canShowAsBubble() {
|
||||
|
||||
@@ -2,7 +2,6 @@ package org.thoughtcrime.securesms.conversation;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.database.ContentObserver;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.LiveData;
|
||||
@@ -11,10 +10,9 @@ import androidx.lifecycle.Transformations;
|
||||
import androidx.lifecycle.ViewModel;
|
||||
|
||||
import org.signal.core.util.concurrent.SignalExecutors;
|
||||
import org.thoughtcrime.securesms.database.DatabaseContentProviders;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.MessageDatabase;
|
||||
import org.thoughtcrime.securesms.database.MmsSmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.DatabaseObserver;
|
||||
import org.thoughtcrime.securesms.database.model.ThreadRecord;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.util.concurrent.SerialMonoLifoExecutor;
|
||||
import org.whispersystems.libsignal.util.Pair;
|
||||
@@ -26,10 +24,10 @@ public class MessageCountsViewModel extends ViewModel {
|
||||
private static final Executor EXECUTOR = new SerialMonoLifoExecutor(SignalExecutors.BOUNDED);
|
||||
|
||||
private final Application context;
|
||||
private final MutableLiveData<Long> threadId = new MutableLiveData<>(-1L);
|
||||
private final MutableLiveData<Long> threadId = new MutableLiveData<>(-1L);
|
||||
private final LiveData<Pair<Integer, Integer>> unreadCounts;
|
||||
|
||||
private ContentObserver observer;
|
||||
private DatabaseObserver.Observer observer;
|
||||
|
||||
public MessageCountsViewModel() {
|
||||
this.context = ApplicationDependencies.getApplication();
|
||||
@@ -41,18 +39,24 @@ public class MessageCountsViewModel extends ViewModel {
|
||||
return counts;
|
||||
}
|
||||
|
||||
observer = new ContentObserver(null) {
|
||||
observer = new DatabaseObserver.Observer() {
|
||||
private int previousUnreadCount = -1;
|
||||
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
public void onChanged() {
|
||||
EXECUTOR.execute(() -> {
|
||||
counts.postValue(getCounts(context, id));
|
||||
int unreadCount = getUnreadCount(context, id);
|
||||
if (unreadCount != previousUnreadCount) {
|
||||
previousUnreadCount = unreadCount;
|
||||
counts.postValue(new Pair<>(unreadCount, getUnreadMentionsCount(context, id)));
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
observer.onChange(false);
|
||||
observer.onChanged();
|
||||
|
||||
context.getContentResolver().registerContentObserver(DatabaseContentProviders.Conversation.getUriForThread(id), true, observer);
|
||||
ApplicationDependencies.getDatabaseObserver().registerConversationListObserver(observer);
|
||||
|
||||
return counts;
|
||||
});
|
||||
@@ -75,19 +79,19 @@ public class MessageCountsViewModel extends ViewModel {
|
||||
return Transformations.map(unreadCounts, Pair::second);
|
||||
}
|
||||
|
||||
private Pair<Integer, Integer> getCounts(@NonNull Context context, long threadId) {
|
||||
MmsSmsDatabase mmsSmsDatabase = DatabaseFactory.getMmsSmsDatabase(context);
|
||||
MessageDatabase mmsDatabase = DatabaseFactory.getMmsDatabase(context);
|
||||
int unreadCount = mmsSmsDatabase.getUnreadCount(threadId);
|
||||
int unreadMentionCount = mmsDatabase.getUnreadMentionCount(threadId);
|
||||
private int getUnreadCount(@NonNull Context context, long threadId) {
|
||||
ThreadRecord threadRecord = DatabaseFactory.getThreadDatabase(context).getThreadRecord(threadId);
|
||||
return threadRecord != null ? threadRecord.getUnreadCount() : 0;
|
||||
}
|
||||
|
||||
return new Pair<>(unreadCount, unreadMentionCount);
|
||||
private int getUnreadMentionsCount(@NonNull Context context, long threadId) {
|
||||
return DatabaseFactory.getMmsDatabase(context).getUnreadMentionCount(threadId);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCleared() {
|
||||
if (observer != null) {
|
||||
context.getContentResolver().unregisterContentObserver(observer);
|
||||
ApplicationDependencies.getDatabaseObserver().unregisterObserver(observer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user