mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-02-20 17:57:29 +00:00
Add lazy thread creation throughout in preparation for CFV2.
This commit is contained in:
@@ -7,20 +7,27 @@ import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import org.signal.core.util.concurrent.LifecycleDisposable;
|
||||
import org.thoughtcrime.securesms.components.settings.app.AppSettingsActivity;
|
||||
import org.thoughtcrime.securesms.conversation.ConversationIntents;
|
||||
import org.thoughtcrime.securesms.groups.ui.creategroup.CreateGroupActivity;
|
||||
import org.thoughtcrime.securesms.insights.InsightsLauncher;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
|
||||
import io.reactivex.rxjava3.disposables.Disposable;
|
||||
|
||||
public class MainNavigator {
|
||||
|
||||
public static final int REQUEST_CONFIG_CHANGES = 901;
|
||||
|
||||
private final MainActivity activity;
|
||||
private final MainActivity activity;
|
||||
private final LifecycleDisposable lifecycleDisposable;
|
||||
|
||||
public MainNavigator(@NonNull MainActivity activity) {
|
||||
this.activity = activity;
|
||||
this.activity = activity;
|
||||
this.lifecycleDisposable = new LifecycleDisposable();
|
||||
|
||||
lifecycleDisposable.bindTo(activity);
|
||||
}
|
||||
|
||||
public static MainNavigator get(@NonNull Activity activity) {
|
||||
@@ -33,7 +40,7 @@ public class MainNavigator {
|
||||
|
||||
/**
|
||||
* @return True if the back pressed was handled in our own custom way, false if it should be given
|
||||
* to the system to do the default behavior.
|
||||
* to the system to do the default behavior.
|
||||
*/
|
||||
public boolean onBackPressed() {
|
||||
Fragment fragment = getFragmentManager().findFragmentById(R.id.fragment_container);
|
||||
@@ -46,13 +53,16 @@ public class MainNavigator {
|
||||
}
|
||||
|
||||
public void goToConversation(@NonNull RecipientId recipientId, long threadId, int distributionType, int startingPosition) {
|
||||
Intent intent = ConversationIntents.createBuilder(activity, recipientId, threadId)
|
||||
.withDistributionType(distributionType)
|
||||
.withStartingPosition(startingPosition)
|
||||
.build();
|
||||
Disposable disposable = ConversationIntents.createBuilder(activity, recipientId, threadId)
|
||||
.map(builder -> builder.withDistributionType(distributionType)
|
||||
.withStartingPosition(startingPosition)
|
||||
.build())
|
||||
.subscribe(intent -> {
|
||||
activity.startActivity(intent);
|
||||
activity.overridePendingTransition(R.anim.slide_from_end, R.anim.fade_scale_out);
|
||||
});
|
||||
|
||||
activity.startActivity(intent);
|
||||
activity.overridePendingTransition(R.anim.slide_from_end, R.anim.fade_scale_out);
|
||||
lifecycleDisposable.add(disposable);
|
||||
}
|
||||
|
||||
public void goToAppSettings() {
|
||||
@@ -79,7 +89,7 @@ public class MainNavigator {
|
||||
public interface BackHandler {
|
||||
/**
|
||||
* @return True if the back pressed was handled in our own custom way, false if it should be given
|
||||
* to the system to do the default behavior.
|
||||
* to the system to do the default behavior.
|
||||
*/
|
||||
boolean onBackPressed();
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
|
||||
import org.signal.core.util.DimensionUnit;
|
||||
import org.signal.core.util.concurrent.LifecycleDisposable;
|
||||
import org.signal.core.util.concurrent.SimpleTask;
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.components.menu.ActionItem;
|
||||
@@ -45,14 +46,12 @@ import org.thoughtcrime.securesms.contacts.management.ContactsManagementViewMode
|
||||
import org.thoughtcrime.securesms.contacts.paged.ContactSearchKey;
|
||||
import org.thoughtcrime.securesms.contacts.sync.ContactDiscovery;
|
||||
import org.thoughtcrime.securesms.conversation.ConversationIntents;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.groups.ui.creategroup.CreateGroupActivity;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.thoughtcrime.securesms.util.CommunicationActions;
|
||||
import org.thoughtcrime.securesms.util.FeatureFlags;
|
||||
import org.signal.core.util.concurrent.LifecycleDisposable;
|
||||
import org.thoughtcrime.securesms.util.views.SimpleProgressDialog;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -64,6 +63,8 @@ import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import io.reactivex.rxjava3.disposables.Disposable;
|
||||
|
||||
/**
|
||||
* Activity container for starting a new conversation.
|
||||
*
|
||||
@@ -163,15 +164,18 @@ public class NewConversationActivity extends ContactSelectionActivity
|
||||
}
|
||||
|
||||
private void launch(Recipient recipient) {
|
||||
long existingThread = SignalDatabase.threads().getThreadIdIfExistsFor(recipient.getId());
|
||||
Intent intent = ConversationIntents.createBuilder(this, recipient.getId(), existingThread)
|
||||
.withDraftText(getIntent().getStringExtra(Intent.EXTRA_TEXT))
|
||||
.withDataUri(getIntent().getData())
|
||||
.withDataType(getIntent().getType())
|
||||
.build();
|
||||
Disposable disposable = ConversationIntents.createBuilder(this, recipient.getId(), -1L)
|
||||
.map(builder -> builder
|
||||
.withDraftText(getIntent().getStringExtra(Intent.EXTRA_TEXT))
|
||||
.withDataUri(getIntent().getData())
|
||||
.withDataType(getIntent().getType())
|
||||
.build())
|
||||
.subscribe(intent -> {
|
||||
startActivity(intent);
|
||||
finish();
|
||||
});
|
||||
|
||||
startActivity(intent);
|
||||
finish();
|
||||
disposables.add(disposable);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -233,8 +237,8 @@ public class NewConversationActivity extends ContactSelectionActivity
|
||||
|
||||
@Override
|
||||
public boolean onLongClick(View anchorView, ContactSearchKey contactSearchKey, RecyclerView recyclerView) {
|
||||
RecipientId recipientId = contactSearchKey.requireRecipientSearchKey().getRecipientId();
|
||||
List<ActionItem> actions = generateContextualActionsForRecipient(recipientId);
|
||||
RecipientId recipientId = contactSearchKey.requireRecipientSearchKey().getRecipientId();
|
||||
List<ActionItem> actions = generateContextualActionsForRecipient(recipientId);
|
||||
if (actions.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
@@ -269,7 +273,12 @@ public class NewConversationActivity extends ContactSelectionActivity
|
||||
R.drawable.ic_chat_message_24,
|
||||
getString(R.string.NewConversationActivity__message),
|
||||
R.color.signal_colorOnSurface,
|
||||
() -> startActivity(ConversationIntents.createBuilder(this, recipient.getId(), -1L).build())
|
||||
() -> {
|
||||
Disposable disposable = ConversationIntents.createBuilder(this, recipient.getId(), -1L)
|
||||
.subscribe(builder -> startActivity(builder.build()));
|
||||
|
||||
disposables.add(disposable);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -370,7 +379,7 @@ public class NewConversationActivity extends ContactSelectionActivity
|
||||
.show();
|
||||
}
|
||||
|
||||
private void displaySnackbar(@StringRes int message, Object ... formatArgs) {
|
||||
private void displaySnackbar(@StringRes int message, Object... formatArgs) {
|
||||
Snackbar.make(findViewById(android.R.id.content), getString(message, formatArgs), Snackbar.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,9 +48,9 @@ public class SmsSendtoActivity extends Activity {
|
||||
Toast.makeText(this, R.string.ConversationActivity_specify_recipient, Toast.LENGTH_LONG).show();
|
||||
} else {
|
||||
Recipient recipient = Recipient.external(this, destination.getDestination());
|
||||
long threadId = SignalDatabase.threads().getThreadIdIfExistsFor(recipient.getId());
|
||||
long threadId = SignalDatabase.threads().getOrCreateThreadIdFor(recipient);
|
||||
|
||||
nextIntent = ConversationIntents.createBuilder(this, recipient.getId(), threadId)
|
||||
nextIntent = ConversationIntents.createBuilderSync(this, recipient.getId(), threadId)
|
||||
.withDraftText(destination.getBody())
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -264,12 +264,14 @@ class GiftFlowConfirmationFragment :
|
||||
|
||||
override fun onPaymentComplete(gatewayRequest: GatewayRequest) {
|
||||
val mainActivityIntent = MainActivity.clearTop(requireContext())
|
||||
val conversationIntent = ConversationIntents
|
||||
.createBuilder(requireContext(), viewModel.snapshot.recipient!!.id, -1L)
|
||||
.withGiftBadge(viewModel.snapshot.giftBadge!!)
|
||||
.build()
|
||||
|
||||
requireActivity().startActivities(arrayOf(mainActivityIntent, conversationIntent))
|
||||
lifecycleDisposable += ConversationIntents
|
||||
.createBuilder(requireContext(), viewModel.snapshot.recipient!!.id, -1L)
|
||||
.subscribe { conversationIntent ->
|
||||
requireActivity().startActivities(
|
||||
arrayOf(mainActivityIntent, conversationIntent.withGiftBadge(viewModel.snapshot.giftBadge!!).build())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onProcessorActionProcessed() = Unit
|
||||
|
||||
@@ -4,6 +4,8 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import io.reactivex.rxjava3.kotlin.subscribeBy
|
||||
import org.signal.core.util.concurrent.LifecycleDisposable
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.calls.links.details.CallLinkDetailsActivity
|
||||
import org.thoughtcrime.securesms.components.menu.ActionItem
|
||||
@@ -21,6 +23,9 @@ class CallLogContextMenu(
|
||||
private val fragment: Fragment,
|
||||
private val callbacks: Callbacks
|
||||
) {
|
||||
|
||||
private val lifecycleDisposable by lazy { LifecycleDisposable().bindTo(fragment.viewLifecycleOwner) }
|
||||
|
||||
fun show(recyclerView: RecyclerView, anchor: View, call: CallLogRow.Call) {
|
||||
recyclerView.suppressLayout(true)
|
||||
anchor.isSelected = true
|
||||
@@ -91,7 +96,10 @@ class CallLogContextMenu(
|
||||
iconRes = R.drawable.symbol_open_24,
|
||||
title = fragment.getString(R.string.CallContextMenu__go_to_chat)
|
||||
) {
|
||||
fragment.startActivity(ConversationIntents.createBuilder(fragment.requireContext(), call.peer.id, -1L).build())
|
||||
lifecycleDisposable += ConversationIntents.createBuilder(fragment.requireContext(), call.peer.id, -1L)
|
||||
.subscribeBy {
|
||||
fragment.startActivity(it.build())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import app.cash.exhaustive.Exhaustive
|
||||
import com.google.android.flexbox.FlexboxLayoutManager
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import io.reactivex.rxjava3.kotlin.subscribeBy
|
||||
import org.signal.core.util.DimensionUnit
|
||||
import org.signal.core.util.concurrent.LifecycleDisposable
|
||||
import org.signal.core.util.getParcelableArrayListExtraCompat
|
||||
@@ -387,7 +388,7 @@ class ConversationSettingsFragment : DSLSettingsFragment(
|
||||
enabled = !state.isDeprecatedOrUnregistered,
|
||||
onMessageClick = {
|
||||
val intent = ConversationIntents
|
||||
.createBuilder(requireContext(), state.recipient.id, state.threadId)
|
||||
.createBuilderSync(requireContext(), state.recipient.id, state.threadId)
|
||||
.build()
|
||||
|
||||
startActivity(intent)
|
||||
@@ -432,12 +433,15 @@ class ConversationSettingsFragment : DSLSettingsFragment(
|
||||
}
|
||||
},
|
||||
onSearchClick = {
|
||||
val intent = ConversationIntents.createBuilder(requireContext(), state.recipient.id, state.threadId)
|
||||
.withSearchOpen(true)
|
||||
.build()
|
||||
lifecycleDisposable += ConversationIntents.createBuilder(requireContext(), state.recipient.id, state.threadId)
|
||||
.subscribeBy { builder ->
|
||||
val intent = builder
|
||||
.withSearchOpen(true)
|
||||
.build()
|
||||
|
||||
startActivity(intent)
|
||||
requireActivity().finish()
|
||||
startActivity(intent)
|
||||
requireActivity().finish()
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
@@ -99,7 +99,7 @@ class VoiceNoteNotificationManager {
|
||||
|
||||
notificationManager.setColor(color);
|
||||
|
||||
Intent conversationActivity = ConversationIntents.createBuilder(context, recipientId, threadId)
|
||||
Intent conversationActivity = ConversationIntents.createBuilderSync(context, recipientId, threadId)
|
||||
.withStartingPosition(startingPosition)
|
||||
.build();
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -73,7 +73,7 @@ public class AddGroupDetailsActivity extends PassphraseRequiredActivity implemen
|
||||
}
|
||||
|
||||
void goToConversation(@NonNull RecipientId recipientId, long threadId) {
|
||||
Intent intent = ConversationIntents.createBuilder(this, recipientId, threadId)
|
||||
Intent intent = ConversationIntents.createBuilderSync(this, recipientId, threadId)
|
||||
.firstTimeInSelfCreatedGroup()
|
||||
.build();
|
||||
|
||||
|
||||
@@ -132,7 +132,7 @@ public final class GroupJoinBottomSheetDialogFragment extends BottomSheetDialogF
|
||||
viewModel.getJoinSuccess().observe(getViewLifecycleOwner(), joinGroupSuccess -> {
|
||||
Log.i(TAG, "Group joined, navigating to group");
|
||||
|
||||
Intent intent = ConversationIntents.createBuilder(requireContext(), joinGroupSuccess.getGroupRecipient().getId(), joinGroupSuccess.getGroupThreadId())
|
||||
Intent intent = ConversationIntents.createBuilderSync(requireContext(), joinGroupSuccess.getGroupRecipient().getId(), joinGroupSuccess.getGroupThreadId())
|
||||
.build();
|
||||
requireActivity().startActivity(intent);
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@ class MediaPreviewRepository {
|
||||
stopwatch.split("get recipient ID")
|
||||
|
||||
stopwatch.stop(TAG)
|
||||
ConversationIntents.createBuilder(context, recipientId, threadId)
|
||||
ConversationIntents.createBuilderSync(context, recipientId, threadId)
|
||||
.withStartingPosition(messagePosition)
|
||||
.build()
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@ data class NotificationConversation(
|
||||
)
|
||||
)
|
||||
} else {
|
||||
ConversationIntents.createBuilder(context, recipient.id, thread.threadId)
|
||||
ConversationIntents.createBuilderSync(context, recipient.id, thread.threadId)
|
||||
.withStartingPosition(mostRecentNotification.getStartingPosition(context))
|
||||
.build()
|
||||
}.makeUniqueToPreventMerging()
|
||||
|
||||
@@ -349,7 +349,7 @@ object NotificationFactory {
|
||||
val intent: Intent = if (recipient.isDistributionList || thread.groupStoryId != null) {
|
||||
Intent(context, MyStoriesActivity::class.java)
|
||||
} else {
|
||||
ConversationIntents.createBuilder(context, recipient.id, thread.threadId)
|
||||
ConversationIntents.createBuilderSync(context, recipient.id, thread.threadId)
|
||||
.build()
|
||||
}.makeUniqueToPreventMerging()
|
||||
|
||||
@@ -419,7 +419,7 @@ object NotificationFactory {
|
||||
val intent: Intent = if (recipient.isDistributionList || thread.groupStoryId != null) {
|
||||
Intent(context, MyStoriesActivity::class.java)
|
||||
} else {
|
||||
ConversationIntents.createBuilder(context, recipient.id, thread.threadId)
|
||||
ConversationIntents.createBuilderSync(context, recipient.id, thread.threadId)
|
||||
.build()
|
||||
}.makeUniqueToPreventMerging()
|
||||
|
||||
|
||||
@@ -118,7 +118,7 @@ public class PaymentRecipientSelectionFragment extends LoggingFragment implement
|
||||
|
||||
private void openConversation(@NonNull RecipientId recipientId) {
|
||||
SimpleTask.run(getViewLifecycleOwner().getLifecycle(),
|
||||
() -> SignalDatabase.threads().getThreadIdIfExistsFor(recipientId),
|
||||
threadId -> startActivity(ConversationIntents.createBuilder(requireContext(), recipientId, threadId).build()));
|
||||
() -> SignalDatabase.threads().getOrCreateThreadIdFor(Recipient.resolved(recipientId)),
|
||||
threadId -> startActivity(ConversationIntents.createBuilderSync(requireContext(), recipientId, threadId).build()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ class ScheduledMessageManager(
|
||||
|
||||
@WorkerThread
|
||||
override fun scheduleAlarm(application: Application, event: Event, delay: Long) {
|
||||
val conversationIntent = ConversationIntents.createBuilder(application, event.recipientId, event.threadId).build()
|
||||
val conversationIntent = ConversationIntents.createBuilderSync(application, event.recipientId, event.threadId).build()
|
||||
|
||||
trySetExactAlarm(
|
||||
application,
|
||||
|
||||
@@ -13,6 +13,7 @@ import androidx.activity.viewModels
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.content.pm.ShortcutManagerCompat
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.rxjava3.kotlin.subscribeBy
|
||||
import org.signal.core.util.Result
|
||||
import org.signal.core.util.concurrent.LifecycleDisposable
|
||||
import org.signal.core.util.getParcelableArrayListCompat
|
||||
@@ -164,11 +165,13 @@ class ShareActivity : PassphraseRequiredActivity(), MultiselectForwardFragment.C
|
||||
Result.success(UnresolvedShareData.ExternalPrimitiveShare(stringBuilder))
|
||||
} ?: Result.failure(IntentError.SEND_MULTIPLE_TEXT)
|
||||
}
|
||||
|
||||
intent.action == Intent.ACTION_SEND_MULTIPLE && intent.hasExtra(Intent.EXTRA_STREAM) -> {
|
||||
intent.getParcelableArrayListExtraCompat(Intent.EXTRA_STREAM, Uri::class.java)?.let {
|
||||
Result.success(UnresolvedShareData.ExternalMultiShare(it))
|
||||
} ?: Result.failure(IntentError.SEND_MULTIPLE_STREAM)
|
||||
}
|
||||
|
||||
intent.action == Intent.ACTION_SEND && intent.hasExtra(Intent.EXTRA_STREAM) -> {
|
||||
val uri: Uri? = intent.getParcelableExtraCompat(Intent.EXTRA_STREAM, Uri::class.java)
|
||||
if (uri == null) {
|
||||
@@ -178,9 +181,11 @@ class ShareActivity : PassphraseRequiredActivity(), MultiselectForwardFragment.C
|
||||
Result.success(UnresolvedShareData.ExternalSingleShare(uri, intent.type, text))
|
||||
}
|
||||
}
|
||||
|
||||
intent.action == Intent.ACTION_SEND && intent.hasExtra(Intent.EXTRA_TEXT) -> {
|
||||
extractSingleExtraTextFromIntent()
|
||||
}
|
||||
|
||||
else -> null
|
||||
} ?: Result.failure(IntentError.UNKNOWN)
|
||||
}
|
||||
@@ -221,18 +226,21 @@ class ShareActivity : PassphraseRequiredActivity(), MultiselectForwardFragment.C
|
||||
Log.d(TAG, "Opening conversation...")
|
||||
|
||||
val multiShareArgs = shareEvent.getMultiShareArgs()
|
||||
val conversationIntentBuilder = ConversationIntents.createBuilder(this, shareEvent.contact.recipientId, -1L)
|
||||
.withDataUri(multiShareArgs.dataUri)
|
||||
.withDataType(multiShareArgs.dataType)
|
||||
.withMedia(multiShareArgs.media)
|
||||
.withDraftText(multiShareArgs.draftText)
|
||||
.withStickerLocator(multiShareArgs.stickerLocator)
|
||||
.asBorderless(multiShareArgs.isBorderless)
|
||||
.withShareDataTimestamp(System.currentTimeMillis())
|
||||
lifecycleDisposable += ConversationIntents.createBuilder(this, shareEvent.contact.recipientId, -1L)
|
||||
.subscribeBy { conversationIntentBuilder ->
|
||||
conversationIntentBuilder
|
||||
.withDataUri(multiShareArgs.dataUri)
|
||||
.withDataType(multiShareArgs.dataType)
|
||||
.withMedia(multiShareArgs.media)
|
||||
.withDraftText(multiShareArgs.draftText)
|
||||
.withStickerLocator(multiShareArgs.stickerLocator)
|
||||
.asBorderless(multiShareArgs.isBorderless)
|
||||
.withShareDataTimestamp(System.currentTimeMillis())
|
||||
|
||||
val mainActivityIntent = MainActivity.clearTop(this)
|
||||
finish()
|
||||
startActivities(arrayOf(mainActivityIntent, conversationIntentBuilder.build()))
|
||||
val mainActivityIntent = MainActivity.clearTop(this)
|
||||
finish()
|
||||
startActivities(arrayOf(mainActivityIntent, conversationIntentBuilder.build()))
|
||||
}
|
||||
}
|
||||
|
||||
private fun openMediaInterstitial(shareEvent: ShareEvent.OpenMediaInterstitial) {
|
||||
|
||||
@@ -183,6 +183,7 @@ class StoriesLandingFragment : DSLSettingsFragment(layoutId = R.layout.stories_l
|
||||
R.id.reminder_action_update_now -> {
|
||||
PlayStoreUtil.openPlayStoreOrOurApkDownloadPage(requireContext())
|
||||
}
|
||||
|
||||
R.id.reminder_action_re_register -> {
|
||||
startActivity(RegistrationNavigationActivity.newIntentForReRegistration(requireContext()))
|
||||
}
|
||||
@@ -324,8 +325,11 @@ class StoriesLandingFragment : DSLSettingsFragment(layoutId = R.layout.stories_l
|
||||
MultiselectForwardFragment.showBottomSheet(childFragmentManager, args)
|
||||
}
|
||||
},
|
||||
onGoToChat = {
|
||||
startActivityIfAble(ConversationIntents.createBuilder(requireContext(), it.data.storyRecipient.id, -1L).build())
|
||||
onGoToChat = { model ->
|
||||
lifecycleDisposable += ConversationIntents.createBuilder(requireContext(), model.data.storyRecipient.id, -1L)
|
||||
.subscribeBy {
|
||||
startActivityIfAble(it.build())
|
||||
}
|
||||
},
|
||||
onHideStory = {
|
||||
if (!it.data.isHidden) {
|
||||
|
||||
@@ -6,6 +6,7 @@ import androidx.appcompat.widget.Toolbar
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import io.reactivex.rxjava3.kotlin.subscribeBy
|
||||
import org.signal.core.util.concurrent.LifecycleDisposable
|
||||
import org.signal.core.util.dp
|
||||
import org.thoughtcrime.securesms.R
|
||||
@@ -45,8 +46,10 @@ class GroupStorySettingsFragment : DSLSettingsFragment(menuId = R.menu.story_gro
|
||||
iconRes = R.drawable.ic_open_24_tinted,
|
||||
title = getString(R.string.StoriesLandingItem__go_to_chat),
|
||||
action = {
|
||||
lifecycleDisposable += viewModel.getConversationData().subscribe { data ->
|
||||
startActivity(ConversationIntents.createBuilder(requireContext(), data.groupRecipientId, data.groupThreadId).build())
|
||||
lifecycleDisposable += viewModel.getConversationData().flatMap { data ->
|
||||
ConversationIntents.createBuilder(requireContext(), data.groupRecipientId, data.groupThreadId)
|
||||
}.subscribeBy {
|
||||
startActivity(it.build())
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
@@ -34,6 +34,7 @@ import com.google.android.material.progressindicator.CircularProgressIndicatorSp
|
||||
import com.google.android.material.progressindicator.IndeterminateDrawable
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.rxjava3.core.Observable
|
||||
import io.reactivex.rxjava3.kotlin.subscribeBy
|
||||
import org.signal.core.util.DimensionUnit
|
||||
import org.signal.core.util.concurrent.LifecycleDisposable
|
||||
import org.signal.core.util.dp
|
||||
@@ -1064,7 +1065,9 @@ class StoryViewerPageFragment :
|
||||
}
|
||||
},
|
||||
onGoToChat = {
|
||||
startActivity(ConversationIntents.createBuilder(requireContext(), storyViewerPageArgs.recipientId, -1L).build())
|
||||
lifecycleDisposable += ConversationIntents.createBuilder(requireContext(), storyViewerPageArgs.recipientId, -1L).subscribeBy {
|
||||
startActivity(it.build())
|
||||
}
|
||||
},
|
||||
onHide = {
|
||||
viewModel.setIsDisplayingHideDialog(true)
|
||||
|
||||
@@ -5,6 +5,8 @@ import android.view.View
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.viewModels
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import io.reactivex.rxjava3.kotlin.subscribeBy
|
||||
import org.signal.core.util.concurrent.LifecycleDisposable
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
@@ -37,9 +39,13 @@ class StoryViewsFragment :
|
||||
private val storyId: Long
|
||||
get() = requireArguments().getLong(ARG_STORY_ID)
|
||||
|
||||
private val lifecycleDisposable = LifecycleDisposable()
|
||||
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
StoryViewItem.register(adapter)
|
||||
|
||||
lifecycleDisposable.bindTo(viewLifecycleOwner)
|
||||
|
||||
val emptyNotice: View = requireView().findViewById(R.id.empty_notice)
|
||||
val disabledNotice: View = requireView().findViewById(R.id.disabled_notice)
|
||||
val disabledButton: View = requireView().findViewById(R.id.disabled_button)
|
||||
@@ -74,9 +80,11 @@ class StoryViewsFragment :
|
||||
StoryViewItem.Model(
|
||||
storyViewItemData = storyViewItemData,
|
||||
canRemoveMember = state.storyRecipient?.isDistributionList ?: false,
|
||||
goToChat = {
|
||||
val chatIntent = ConversationIntents.createBuilder(requireContext(), it.storyViewItemData.recipient.id, -1L).build()
|
||||
startActivity(chatIntent)
|
||||
goToChat = { model ->
|
||||
lifecycleDisposable += ConversationIntents.createBuilder(requireContext(), model.storyViewItemData.recipient.id, -1L).subscribeBy {
|
||||
val chatIntent = it.build()
|
||||
startActivity(chatIntent)
|
||||
}
|
||||
},
|
||||
removeFromStory = {
|
||||
if (state.storyRecipient?.isDistributionList == true) {
|
||||
|
||||
@@ -48,6 +48,7 @@ import org.thoughtcrime.securesms.util.views.SimpleProgressDialog;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@@ -142,13 +143,12 @@ public class CommunicationActions {
|
||||
new AsyncTask<Void, Void, Long>() {
|
||||
@Override
|
||||
protected Long doInBackground(Void... voids) {
|
||||
return SignalDatabase.threads().getThreadIdFor(recipient.getId());
|
||||
return SignalDatabase.threads().getOrCreateThreadIdFor(recipient);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(@Nullable Long threadId) {
|
||||
// TODO [alex] -- ThreadID should *always* exist
|
||||
ConversationIntents.Builder builder = ConversationIntents.createBuilder(context, recipient.getId(), threadId != null ? threadId : -1);
|
||||
protected void onPostExecute(@NonNull Long threadId) {
|
||||
ConversationIntents.Builder builder = ConversationIntents.createBuilderSync(context, recipient.getId(), Objects.requireNonNull(threadId));
|
||||
if (!TextUtils.isEmpty(text)) {
|
||||
builder.withDraftText(text);
|
||||
}
|
||||
|
||||
@@ -216,14 +216,14 @@ public final class ConversationUtil {
|
||||
{
|
||||
Recipient resolved = recipient.resolve();
|
||||
Person[] persons = buildPersons(context, resolved);
|
||||
Long threadId = SignalDatabase.threads().getThreadIdFor(resolved.getId());
|
||||
long threadId = SignalDatabase.threads().getOrCreateThreadIdFor(resolved);
|
||||
String shortName = resolved.isSelf() ? context.getString(R.string.note_to_self) : resolved.getShortDisplayName(context);
|
||||
String longName = resolved.isSelf() ? context.getString(R.string.note_to_self) : resolved.getDisplayName(context);
|
||||
String shortcutId = getShortcutId(resolved);
|
||||
|
||||
ShortcutInfoCompat.Builder builder = new ShortcutInfoCompat.Builder(context, shortcutId)
|
||||
.setLongLived(true)
|
||||
.setIntent(ConversationIntents.createBuilder(context, resolved.getId(), threadId != null ? threadId : -1).build())
|
||||
.setIntent(ConversationIntents.createBuilderSync(context, resolved.getId(), threadId).build())
|
||||
.setShortLabel(shortName)
|
||||
.setLongLabel(longName)
|
||||
.setIcon(AvatarUtil.getIconCompatForShortcut(context, resolved))
|
||||
|
||||
Reference in New Issue
Block a user