diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationDataSource.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationDataSource.java index 739d248aa6..ec5f22b7f9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationDataSource.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationDataSource.java @@ -30,16 +30,13 @@ class ConversationDataSource extends PositionalDataSource { private final Context context; private final long threadId; - private final DataUpdatedCallback dataUpdateCallback; private ConversationDataSource(@NonNull Context context, long threadId, - @NonNull Invalidator invalidator, - @NonNull DataUpdatedCallback dataUpdateCallback) + @NonNull Invalidator invalidator) { this.context = context; this.threadId = threadId; - this.dataUpdateCallback = dataUpdateCallback; ContentObserver contentObserver = new ContentObserver(null) { @Override @@ -82,7 +79,6 @@ class ConversationDataSource extends PositionalDataSource { SizeFixResult result = ensureMultipleOfPageSize(records, params.requestedStartPosition, params.pageSize, totalCount); callback.onResult(result.messages, params.requestedStartPosition, result.total); - Util.runOnMain(dataUpdateCallback::onDataUpdated); } Log.d(TAG, "[Initial Load] " + (System.currentTimeMillis() - start) + " ms" + (isInvalid() ? " -- invalidated" : "")); @@ -104,10 +100,6 @@ class ConversationDataSource extends PositionalDataSource { callback.onResult(records); - if (!isInvalid()) { - Util.runOnMain(dataUpdateCallback::onDataUpdated); - } - Log.d(TAG, "[Update] " + (System.currentTimeMillis() - start) + " ms" + (isInvalid() ? " -- invalidated" : "")); } @@ -164,18 +156,16 @@ class ConversationDataSource extends PositionalDataSource { private final Context context; private final long threadId; private final Invalidator invalidator; - private final DataUpdatedCallback callback; - Factory(Context context, long threadId, @NonNull Invalidator invalidator, @NonNull DataUpdatedCallback callback) { + Factory(Context context, long threadId, @NonNull Invalidator invalidator) { this.context = context; this.threadId = threadId; this.invalidator = invalidator; - this.callback = callback; } @Override public @NonNull DataSource create() { - return new ConversationDataSource(context, threadId, invalidator, callback); + return new ConversationDataSource(context, threadId, invalidator); } } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java index 888cf8d5a3..9d2621ddbe 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java @@ -941,17 +941,15 @@ public class ConversationFragment extends Fragment { } private void moveToMessagePosition(int position, @Nullable Runnable onMessageNotFound) { - if (position >= 0) { - list.scrollToPosition(position); + int itemCount = getListAdapter() != null ? getListAdapter().getItemCount() : 0; - if (getListAdapter() == null || getListAdapter().getItem(position) == null) { - Log.i(TAG, "[moveToMessagePosition] Position " + position + " not currently populated. Scheduling a jump."); - conversationViewModel.scheduleForNextMessageUpdate(() -> { - list.scrollToPosition(position); - getListAdapter().pulseHighlightItem(position); - }); + if (position >= 0 && position < itemCount) { + if (getListAdapter().getItem(position) == null) { + conversationViewModel.onConversationDataAvailable(threadId, position); + deferred.setDeferred(true); + deferred.defer(() -> moveToMessagePosition(position, onMessageNotFound)); } else { - getListAdapter().pulseHighlightItem(position); + scrollToStartingPosition(position); } } else { Log.w(TAG, "[moveToMessagePosition] Tried to navigate to message, but it wasn't found."); diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationViewModel.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationViewModel.java index 838d8f000e..d2624a234a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationViewModel.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationViewModel.java @@ -40,7 +40,6 @@ class ConversationViewModel extends ViewModel { private final MutableLiveData threadId; private final LiveData> messages; private final LiveData conversationMetadata; - private final List onNextMessageLoad; private final Invalidator invalidator; private int jumpToPosition; @@ -51,28 +50,31 @@ class ConversationViewModel extends ViewModel { this.conversationRepository = new ConversationRepository(); this.recentMedia = new MutableLiveData<>(); this.threadId = new MutableLiveData<>(); - this.onNextMessageLoad = new CopyOnWriteArrayList<>(); this.invalidator = new Invalidator(); - LiveData conversationDataForRequestedThreadId = Transformations.switchMap(threadId, thread -> { - return conversationRepository.getConversationData(thread, jumpToPosition); + LiveData metadata = Transformations.switchMap(threadId, thread -> { + LiveData conversationData = conversationRepository.getConversationData(thread, jumpToPosition); + + jumpToPosition = -1; + + return conversationData; }); - LiveData>> messagesForThreadId = Transformations.switchMap(conversationDataForRequestedThreadId, data -> { - DataSource.Factory factory = new ConversationDataSource.Factory(context, data.getThreadId(), invalidator, this::onMessagesUpdated); + LiveData>> messagesForThreadId = Transformations.switchMap(metadata, data -> { + DataSource.Factory factory = new ConversationDataSource.Factory(context, data.getThreadId(), invalidator); PagedList.Config config = new PagedList.Config.Builder() .setPageSize(25) .setInitialLoadSizeHint(25) .build(); final int startPosition; - if (jumpToPosition > 0) { - startPosition = jumpToPosition; + if (data.shouldJumpToMessage()) { + startPosition = data.getJumpToPosition(); } else { startPosition = data.getLastSeenPosition(); } - Log.d(TAG, "Starting at position " + startPosition + " :: " + jumpToPosition + " :: " + data.getLastSeenPosition()); + Log.d(TAG, "Starting at position " + startPosition + " :: " + data.getJumpToPosition() + " :: " + data.getLastSeenPosition()); return Transformations.map(new LivePagedListBuilder<>(factory, config).setFetchExecutor(ConversationDataSource.EXECUTOR) .setInitialLoadKey(Math.max(startPosition, 0)) @@ -82,13 +84,9 @@ class ConversationViewModel extends ViewModel { this.messages = Transformations.map(messagesForThreadId, Pair::second); - LiveData threadIdForLoadedMessages = Transformations.distinctUntilChanged(Transformations.map(messagesForThreadId, Pair::first)); + LiveData distinctThread = Transformations.distinctUntilChanged(threadId); - conversationMetadata = Transformations.switchMap(threadIdForLoadedMessages, m -> { - LiveData data = conversationRepository.getConversationData(m, jumpToPosition); - jumpToPosition = -1; - return data; - }); + conversationMetadata = Transformations.switchMap(distinctThread, thread -> metadata); } void onAttachmentKeyboardOpen() { @@ -122,24 +120,12 @@ class ConversationViewModel extends ViewModel { return conversationMetadata.getValue() != null ? conversationMetadata.getValue().getLastSeenPosition() : 0; } - void scheduleForNextMessageUpdate(@NonNull Runnable runnable) { - onNextMessageLoad.add(runnable); - } - @Override protected void onCleared() { super.onCleared(); invalidator.invalidate(); } - private void onMessagesUpdated() { - for (Runnable runnable : onNextMessageLoad) { - runnable.run(); - } - - onNextMessageLoad.clear(); - } - static class Factory extends ViewModelProvider.NewInstanceFactory { @Override public @NonNull T create(@NonNull Class modelClass) {