Add lazy thread creation throughout in preparation for CFV2.

This commit is contained in:
Alex Hart
2023-07-12 15:33:34 -03:00
committed by Clark Chen
parent 6ca9cb6da1
commit 8f253ffc43
24 changed files with 176 additions and 82 deletions

View File

@@ -2050,7 +2050,7 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
@Override
public void goToMediaPreview(ConversationItem parent, View sharedElement, MediaIntentFactory.MediaPreviewArgs args) {
if (listener.isInBubble()) {
Intent intent = ConversationIntents.createBuilder(requireActivity(), recipient.getId(), threadId)
Intent intent = ConversationIntents.createBuilderSync(requireActivity(), recipient.getId(), threadId)
.withStartingPosition(list.getChildAdapterPosition(parent))
.build();

View File

@@ -6,6 +6,7 @@ import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import androidx.annotation.MainThread;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -28,6 +29,10 @@ import java.util.Collection;
import java.util.List;
import java.util.Objects;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Single;
import io.reactivex.rxjava3.schedulers.Schedulers;
public class ConversationIntents {
private static final String TAG = Log.tag(ConversationIntents.class);
@@ -52,8 +57,26 @@ public class ConversationIntents {
private ConversationIntents() {
}
public static @NonNull Builder createBuilder(@NonNull Context context, @NonNull RecipientId recipientId, long threadId) {
return new Builder(context, recipientId, threadId);
/**
* Create a conversation builder for the given recipientId / threadId. Thread ids are required for CFV2,
* so we will resolve the Recipient into a ThreadId if the threadId is invalid (below 0)
*
* @param context Context for Intent creation
* @param recipientId The RecipientId to query the thread ID for if the passed one is invalid.
* @param threadId The threadId, or -1L
*
* @return A Single that will return a builder to create the conversation intent.
*/
@MainThread
public static @NonNull Single<Builder> createBuilder(@NonNull Context context, @NonNull RecipientId recipientId, long threadId) {
if (threadId > 0L) {
return Single.just(createBuilderSync(context, recipientId, threadId));
} else {
return Single.fromCallable(() -> {
long newThreadId = SignalDatabase.threads().getOrCreateThreadIdFor(Recipient.resolved(recipientId));
return createBuilderSync(context, recipientId, newThreadId);
}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
}
}
public static @NonNull Builder createPopUpBuilder(@NonNull Context context, @NonNull RecipientId recipientId, long threadId) {
@@ -64,6 +87,20 @@ public class ConversationIntents {
return new Builder(context, BubbleConversationActivity.class, recipientId, threadId).build();
}
/**
* Create a Builder for a Conversation Intent. Does not perform a lookup for the thread id if the thread id is < 1. For CFV2, this is
* considered an invalid state and will be met with an IllegalArgumentException.
*
* @param context Context for Intent creation
* @param recipientId The recipientId, only used if the threadId is not valid
* @param threadId The threadId, required for CFV2.
*
* @return A builder that can be used to create a conversation intent.
*/
public static @NonNull Builder createBuilderSync(@NonNull Context context, @NonNull RecipientId recipientId, long threadId) {
return new Builder(context, recipientId, threadId);
}
static boolean isInvalid(@NonNull Bundle arguments) {
Uri uri = getIntentData(arguments);
if (isBubbleIntentUri(uri)) {
@@ -308,7 +345,7 @@ public class ConversationIntents {
this.context = context;
this.conversationActivityClass = conversationActivityClass;
this.recipientId = recipientId;
this.threadId = resolveThreadId(recipientId, threadId);
this.threadId = checkThreadId(threadId);
this.conversationScreenType = ConversationScreenType.fromActivityClass(conversationActivityClass);
}
@@ -475,11 +512,9 @@ public class ConversationIntents {
}
}
private static long resolveThreadId(@NonNull RecipientId recipientId, long threadId) {
private static long checkThreadId(long threadId) {
if (threadId < 0 && SignalStore.internalValues().useConversationFragmentV2()) {
Log.w(TAG, "Getting thread id from database...");
// TODO [alex] -- Yes, this hits the database. No, we shouldn't be doing this.
return SignalDatabase.threads().getOrCreateThreadIdFor(Recipient.resolved(recipientId));
throw new IllegalArgumentException("ThreadId is a required field in CFV2");
} else {
return threadId;
}

View File

@@ -4451,7 +4451,7 @@ public class ConversationParentFragment extends Fragment
@Override
public void onNavigateToMessage(long threadId, @NonNull RecipientId threadRecipientId, @NonNull RecipientId senderId, long messageTimestamp, long messagePositionInThread) {
if (threadId != ConversationParentFragment.this.threadId) {
startActivity(ConversationIntents.createBuilder(requireActivity(), threadRecipientId, threadId)
startActivity(ConversationIntents.createBuilderSync(requireActivity(), threadRecipientId, threadId)
.withStartingPosition((int) messagePositionInThread)
.build());
} else {