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 97257fc45e..ace0e59c1e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationDataSource.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationDataSource.java @@ -14,7 +14,6 @@ import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.MmsSmsDatabase; import org.thoughtcrime.securesms.database.model.MessageRecord; import org.thoughtcrime.securesms.logging.Log; -import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.concurrent.SignalExecutors; import org.thoughtcrime.securesms.util.paging.Invalidator; import org.thoughtcrime.securesms.util.paging.SizeFixResult; @@ -83,9 +82,10 @@ class ConversationDataSource extends PositionalDataSource { .toList(); callback.onResult(items, params.requestedStartPosition, result.getTotal()); + Log.d(TAG, "[Initial Load] " + (System.currentTimeMillis() - start) + " ms | thread: " + threadId + ", start: " + params.requestedStartPosition + ", requestedSize: " + params.requestedLoadSize + ", actualSize: " + result.getItems().size() + ", totalCount: " + result.getTotal()); + } else { + Log.d(TAG, "[Initial Load] " + (System.currentTimeMillis() - start) + " ms | thread: " + threadId + ", start: " + params.requestedStartPosition + ", requestedSize: " + params.requestedLoadSize + ", totalCount: " + totalCount + " -- invalidated"); } - - Log.d(TAG, "[Initial Load] " + (System.currentTimeMillis() - start) + " ms | thread: " + threadId + ", start: " + params.requestedStartPosition + ", size: " + params.requestedLoadSize + (isInvalid() ? " -- invalidated" : "")); } @Override diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListDataSource.java b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListDataSource.java index a8e35902c6..b80874a250 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListDataSource.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListDataSource.java @@ -17,6 +17,7 @@ import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.util.ThrottledDebouncer; +import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.concurrent.SignalExecutors; import org.thoughtcrime.securesms.util.paging.Invalidator; import org.thoughtcrime.securesms.util.paging.SizeFixResult; @@ -84,11 +85,11 @@ abstract class ConversationListDataSource extends PositionalDataSource result = SizeFixResult.ensureMultipleOfPageSize(conversations, params.requestedStartPosition, params.pageSize, totalCount); - callback.onResult(result.getItems(), params.requestedStartPosition, result.getTotal()); + Log.d(TAG, "[Initial Load] " + (System.currentTimeMillis() - start) + " ms | start: " + params.requestedStartPosition + ", requestedSize: " + params.requestedLoadSize + ", actualSize: " + result.getItems().size() + ", totalCount: " + result.getTotal() + ", class: " + getClass().getSimpleName()); + } else { + Log.d(TAG, "[Initial Load] " + (System.currentTimeMillis() - start) + " ms | start: " + params.requestedStartPosition + ", requestedSize: " + params.requestedLoadSize + ", totalCount: " + totalCount + ", class: " + getClass().getSimpleName() + " -- invalidated"); } - - Log.d(TAG, "[Initial Load] " + (System.currentTimeMillis() - start) + " ms | start: " + params.requestedStartPosition + ", size: " + params.requestedLoadSize + ", totalCount: " + totalCount + ", class: " + getClass().getSimpleName() + (isInvalid() ? " -- invalidated" : "")); } @Override diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListFragment.java b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListFragment.java index c66e648374..3bc63d78ce 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListFragment.java @@ -500,9 +500,9 @@ public class ConversationListFragment extends MainFragment implements ActionMode private void initializeViewModel() { viewModel = ViewModelProviders.of(this, new ConversationListViewModel.Factory(isArchived())).get(ConversationListViewModel.class); - viewModel.getSearchResult().observe(this, this::onSearchResultChanged); - viewModel.getMegaphone().observe(this, this::onMegaphoneChanged); - viewModel.getConversationList().observe(this, this::onSubmitList); + viewModel.getSearchResult().observe(getViewLifecycleOwner(), this::onSearchResultChanged); + viewModel.getMegaphone().observe(getViewLifecycleOwner(), this::onMegaphoneChanged); + viewModel.getConversationList().observe(getViewLifecycleOwner(), this::onSubmitList); ProcessLifecycleOwner.get().getLifecycle().addObserver(new DefaultLifecycleObserver() { @Override @@ -751,6 +751,7 @@ public class ConversationListFragment extends MainFragment implements ActionMode private void onSubmitList(@NonNull ConversationListViewModel.ConversationList conversationList) { if (conversationList.isEmpty()) { + Log.i(TAG, "Received an empty data set."); list.setVisibility(View.INVISIBLE); emptyState.setVisibility(View.VISIBLE); emptyImage.setImageResource(EMPTY_IMAGES[(int) (Math.random() * EMPTY_IMAGES.length)]); diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListViewModel.java b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListViewModel.java index 1e21310446..700158c5e7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListViewModel.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListViewModel.java @@ -8,6 +8,7 @@ import android.text.TextUtils; import androidx.annotation.NonNull; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; +import androidx.lifecycle.Transformations; import androidx.lifecycle.ViewModel; import androidx.lifecycle.ViewModelProvider; import androidx.paging.DataSource; @@ -19,6 +20,7 @@ import org.thoughtcrime.securesms.conversationlist.model.SearchResult; import org.thoughtcrime.securesms.database.DatabaseContentProviders; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; +import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.megaphone.Megaphone; import org.thoughtcrime.securesms.megaphone.MegaphoneRepository; import org.thoughtcrime.securesms.megaphone.Megaphones; @@ -31,10 +33,11 @@ import org.thoughtcrime.securesms.util.paging.Invalidator; class ConversationListViewModel extends ViewModel { + private static final String TAG = Log.tag(ConversationListViewModel.class); + private final Application application; private final MutableLiveData megaphone; private final MutableLiveData searchResult; - private final MutableLiveData archivedCount; private final LiveData conversationList; private final SearchRepository searchRepository; private final MegaphoneRepository megaphoneRepository; @@ -48,7 +51,6 @@ class ConversationListViewModel extends ViewModel { this.application = application; this.megaphone = new MutableLiveData<>(); this.searchResult = new MutableLiveData<>(); - this.archivedCount = new MutableLiveData<>(); this.searchRepository = searchRepository; this.megaphoneRepository = ApplicationDependencies.getMegaphoneRepository(); this.debouncer = new Debouncer(300); @@ -59,10 +61,6 @@ class ConversationListViewModel extends ViewModel { if (!TextUtils.isEmpty(getLastQuery())) { searchRepository.query(getLastQuery(), searchResult::postValue); } - - if (!isArchived) { - updateArchivedCount(); - } } }; @@ -77,15 +75,27 @@ class ConversationListViewModel extends ViewModel { .setInitialLoadKey(0) .build(); - if (isArchived) { - this.archivedCount.setValue(0); - } else { - updateArchivedCount(); - } - application.getContentResolver().registerContentObserver(DatabaseContentProviders.ConversationList.CONTENT_URI, true, observer); - this.conversationList = LiveDataUtil.combineLatest(conversationList, this.archivedCount, ConversationList::new); + this.conversationList = Transformations.switchMap(conversationList, conversation -> { + if (conversation.getDataSource().isInvalid()) { + Log.w(TAG, "Received an invalid conversation list. Ignoring."); + return new MutableLiveData<>(); + } + + MutableLiveData updated = new MutableLiveData<>(); + + if (isArchived) { + updated.postValue(new ConversationList(conversation, 0)); + } else { + SignalExecutors.BOUNDED.execute(() -> { + int archiveCount = DatabaseFactory.getThreadDatabase(application).getArchivedConversationListCount(); + updated.postValue(new ConversationList(conversation, archiveCount)); + }); + } + + return updated; + }); } @NonNull LiveData getSearchResult() { @@ -140,12 +150,6 @@ class ConversationListViewModel extends ViewModel { application.getContentResolver().unregisterContentObserver(observer); } - private void updateArchivedCount() { - SignalExecutors.BOUNDED.execute(() -> { - archivedCount.postValue(DatabaseFactory.getThreadDatabase(application).getArchivedConversationListCount()); - }); - } - public static class Factory extends ViewModelProvider.NewInstanceFactory { private final boolean isArchived;