Fix various bugs around unread counts and scroll to bottom.

fork-5.53.8
Cody Henthorne 2021-09-28 17:03:32 -04:00
rodzic 3310246351
commit 76f52b9086
4 zmienionych plików z 37 dodań i 36 usunięć

Wyświetl plik

@ -217,6 +217,7 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
private Animation mentionButtonOutAnimation; private Animation mentionButtonOutAnimation;
private OnScrollListener conversationScrollListener; private OnScrollListener conversationScrollListener;
private int pulsePosition = -1; private int pulsePosition = -1;
private int lastSeenScrollOffset;
private View toolbarShadow; private View toolbarShadow;
private Stopwatch startupStopwatch; private Stopwatch startupStopwatch;
@ -365,7 +366,10 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
getViewLifecycleOwner().getLifecycle().addObserver(conversationUpdateTick); getViewLifecycleOwner().getLifecycle().addObserver(conversationUpdateTick);
listener.getVoiceNoteMediaController().getVoiceNotePlayerViewState().observe(getViewLifecycleOwner(), state -> conversationViewModel.setInlinePlayerVisible(state.isPresent())); 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; return view;
} }
@ -1101,7 +1105,7 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
.submit(); .submit();
} else if (conversation.getMessageRequestData().isMessageRequestAccepted()) { } else if (conversation.getMessageRequestData().isMessageRequestAccepted()) {
snapToTopDataObserver.buildScrollPosition(conversation.shouldScrollToLastSeen() ? lastSeenPosition : lastScrolledPosition) 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) .withOnScrollRequestComplete(afterScroll)
.submit(); .submit();
} else { } else {
@ -1247,7 +1251,7 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
public void onGlobalLayout() { public void onGlobalLayout() {
Rect rect = new Rect(); Rect rect = new Rect();
toolbar.getGlobalVisibleRect(rect); toolbar.getGlobalVisibleRect(rect);
conversationViewModel.setToolbarBottom(rect.bottom + ViewUtil.dpToPx(8)); conversationViewModel.setToolbarBottom(rect.bottom);
ViewUtil.setTopMargin(conversationBanner, rect.bottom + ViewUtil.dpToPx(16)); ViewUtil.setTopMargin(conversationBanner, rect.bottom + ViewUtil.dpToPx(16));
toolbar.getViewTreeObserver().removeOnGlobalLayoutListener(this); toolbar.getViewTreeObserver().removeOnGlobalLayoutListener(this);
} }

Wyświetl plik

@ -75,7 +75,7 @@ public class ConversationViewModel extends ViewModel {
private final LiveData<ChatColors> chatColors; private final LiveData<ChatColors> chatColors;
private final MutableLiveData<Integer> toolbarBottom; private final MutableLiveData<Integer> toolbarBottom;
private final MutableLiveData<Integer> inlinePlayerHeight; private final MutableLiveData<Integer> inlinePlayerHeight;
private final LiveData<Integer> scrollDateTopMargin; private final LiveData<Integer> conversationTopMargin;
private final Map<GroupId, Set<Recipient>> sessionMemberCache = new HashMap<>(); 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.messageInsertObserver = messageId -> pagingController.onDataItemInserted(messageId, 0);
this.toolbarBottom = new MutableLiveData<>(); this.toolbarBottom = new MutableLiveData<>();
this.inlinePlayerHeight = 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<Recipient> recipientLiveData = LiveDataUtil.mapAsync(recipientId, Recipient::resolved);
LiveData<ThreadAndRecipient> threadAndRecipient = LiveDataUtil.combineLatest(threadId, recipientLiveData, ThreadAndRecipient::new); LiveData<ThreadAndRecipient> threadAndRecipient = LiveDataUtil.combineLatest(threadId, recipientLiveData, ThreadAndRecipient::new);
@ -161,11 +161,11 @@ public class ConversationViewModel extends ViewModel {
} }
void setToolbarBottom(int bottom) { void setToolbarBottom(int bottom) {
toolbarBottom.postValue(bottom); toolbarBottom.setValue(bottom);
} }
void setInlinePlayerVisible(boolean isVisible) { void setInlinePlayerVisible(boolean isVisible) {
inlinePlayerHeight.postValue(isVisible ? ViewUtil.dpToPx(36) : 0); inlinePlayerHeight.setValue(isVisible ? ViewUtil.dpToPx(36) : 0);
} }
void onAttachmentKeyboardOpen() { void onAttachmentKeyboardOpen() {
@ -186,8 +186,8 @@ public class ConversationViewModel extends ViewModel {
this.threadId.postValue(-1L); this.threadId.postValue(-1L);
} }
@NonNull LiveData<Integer> getScrollDateTopMargin() { @NonNull LiveData<Integer> getConversationTopMargin() {
return scrollDateTopMargin; return conversationTopMargin;
} }
@NonNull LiveData<Boolean> canShowAsBubble() { @NonNull LiveData<Boolean> canShowAsBubble() {

Wyświetl plik

@ -2,7 +2,6 @@ package org.thoughtcrime.securesms.conversation;
import android.app.Application; import android.app.Application;
import android.content.Context; import android.content.Context;
import android.database.ContentObserver;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.lifecycle.LiveData; import androidx.lifecycle.LiveData;
@ -11,10 +10,9 @@ import androidx.lifecycle.Transformations;
import androidx.lifecycle.ViewModel; import androidx.lifecycle.ViewModel;
import org.signal.core.util.concurrent.SignalExecutors; import org.signal.core.util.concurrent.SignalExecutors;
import org.thoughtcrime.securesms.database.DatabaseContentProviders;
import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MessageDatabase; import org.thoughtcrime.securesms.database.DatabaseObserver;
import org.thoughtcrime.securesms.database.MmsSmsDatabase; import org.thoughtcrime.securesms.database.model.ThreadRecord;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.util.concurrent.SerialMonoLifoExecutor; import org.thoughtcrime.securesms.util.concurrent.SerialMonoLifoExecutor;
import org.whispersystems.libsignal.util.Pair; 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 static final Executor EXECUTOR = new SerialMonoLifoExecutor(SignalExecutors.BOUNDED);
private final Application context; 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 final LiveData<Pair<Integer, Integer>> unreadCounts;
private ContentObserver observer; private DatabaseObserver.Observer observer;
public MessageCountsViewModel() { public MessageCountsViewModel() {
this.context = ApplicationDependencies.getApplication(); this.context = ApplicationDependencies.getApplication();
@ -41,18 +39,24 @@ public class MessageCountsViewModel extends ViewModel {
return counts; return counts;
} }
observer = new ContentObserver(null) { observer = new DatabaseObserver.Observer() {
private int previousUnreadCount = -1;
@Override @Override
public void onChange(boolean selfChange) { public void onChanged() {
EXECUTOR.execute(() -> { 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; return counts;
}); });
@ -75,19 +79,19 @@ public class MessageCountsViewModel extends ViewModel {
return Transformations.map(unreadCounts, Pair::second); return Transformations.map(unreadCounts, Pair::second);
} }
private Pair<Integer, Integer> getCounts(@NonNull Context context, long threadId) { private int getUnreadCount(@NonNull Context context, long threadId) {
MmsSmsDatabase mmsSmsDatabase = DatabaseFactory.getMmsSmsDatabase(context); ThreadRecord threadRecord = DatabaseFactory.getThreadDatabase(context).getThreadRecord(threadId);
MessageDatabase mmsDatabase = DatabaseFactory.getMmsDatabase(context); return threadRecord != null ? threadRecord.getUnreadCount() : 0;
int unreadCount = mmsSmsDatabase.getUnreadCount(threadId); }
int unreadMentionCount = mmsDatabase.getUnreadMentionCount(threadId);
return new Pair<>(unreadCount, unreadMentionCount); private int getUnreadMentionsCount(@NonNull Context context, long threadId) {
return DatabaseFactory.getMmsDatabase(context).getUnreadMentionCount(threadId);
} }
@Override @Override
protected void onCleared() { protected void onCleared() {
if (observer != null) { if (observer != null) {
context.getContentResolver().unregisterContentObserver(observer); ApplicationDependencies.getDatabaseObserver().unregisterObserver(observer);
} }
} }
} }

Wyświetl plik

@ -256,13 +256,6 @@ public class MmsSmsDatabase extends Database {
} }
} }
public Cursor getUnread() {
String order = MmsSmsColumns.NORMALIZED_DATE_RECEIVED + " ASC";
String selection = MmsSmsColumns.NOTIFIED + " = 0 AND (" + MmsSmsColumns.READ + " = 0 OR " + MmsSmsColumns.REACTIONS_UNREAD + " = 1)";
return queryTables(PROJECTION, selection, order, null);
}
public Cursor getMessagesForNotificationState(Collection<MessageNotifierV2.StickyThread> stickyThreads) { public Cursor getMessagesForNotificationState(Collection<MessageNotifierV2.StickyThread> stickyThreads) {
StringBuilder stickyQuery = new StringBuilder(); StringBuilder stickyQuery = new StringBuilder();
for (MessageNotifierV2.StickyThread stickyThread : stickyThreads) { for (MessageNotifierV2.StickyThread stickyThread : stickyThreads) {
@ -286,13 +279,13 @@ public class MmsSmsDatabase extends Database {
} }
public int getUnreadCount(long threadId) { public int getUnreadCount(long threadId) {
String selection = MmsSmsColumns.READ + " = 0 AND " + MmsSmsColumns.NOTIFIED + " = 0 AND " + MmsSmsColumns.THREAD_ID + " = " + threadId; String selection = MmsSmsColumns.READ + " = 0 AND " + MmsSmsColumns.THREAD_ID + " = " + threadId;
Cursor cursor = queryTables(PROJECTION, selection, null, null); Cursor cursor = queryTables(PROJECTION, selection, null, null);
try { try {
return cursor != null ? cursor.getCount() : 0; return cursor != null ? cursor.getCount() : 0;
} finally { } finally {
if (cursor != null) cursor.close();; if (cursor != null) cursor.close();
} }
} }