Localize Conversation Intent creation.

This commit is contained in:
Alex Hart
2020-11-25 11:36:33 -04:00
parent 13c014215d
commit e57a35ab3e
18 changed files with 473 additions and 170 deletions

View File

@@ -9,7 +9,7 @@ import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import org.thoughtcrime.securesms.conversation.ConversationActivity; import org.thoughtcrime.securesms.conversation.ConversationIntents;
import org.thoughtcrime.securesms.conversationlist.ConversationListArchiveFragment; import org.thoughtcrime.securesms.conversationlist.ConversationListArchiveFragment;
import org.thoughtcrime.securesms.conversationlist.ConversationListFragment; import org.thoughtcrime.securesms.conversationlist.ConversationListFragment;
import org.thoughtcrime.securesms.groups.ui.creategroup.CreateGroupActivity; import org.thoughtcrime.securesms.groups.ui.creategroup.CreateGroupActivity;
@@ -59,7 +59,10 @@ public class MainNavigator {
} }
public void goToConversation(@NonNull RecipientId recipientId, long threadId, int distributionType, int startingPosition) { public void goToConversation(@NonNull RecipientId recipientId, long threadId, int distributionType, int startingPosition) {
Intent intent = ConversationActivity.buildIntent(activity, recipientId, threadId, distributionType, startingPosition); Intent intent = ConversationIntents.createBuilder(activity, recipientId, threadId)
.withDistributionType(distributionType)
.withStartingPosition(startingPosition)
.build();
activity.startActivity(intent); activity.startActivity(intent);
activity.overridePendingTransition(R.anim.slide_from_end, R.anim.fade_scale_out); activity.overridePendingTransition(R.anim.slide_from_end, R.anim.fade_scale_out);

View File

@@ -25,6 +25,7 @@ import androidx.appcompat.app.AlertDialog;
import org.thoughtcrime.securesms.contacts.sync.DirectoryHelper; import org.thoughtcrime.securesms.contacts.sync.DirectoryHelper;
import org.thoughtcrime.securesms.conversation.ConversationActivity; import org.thoughtcrime.securesms.conversation.ConversationActivity;
import org.thoughtcrime.securesms.conversation.ConversationIntents;
import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.ThreadDatabase; import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.groups.ui.creategroup.CreateGroupActivity; import org.thoughtcrime.securesms.groups.ui.creategroup.CreateGroupActivity;
@@ -99,15 +100,13 @@ public class NewConversationActivity extends ContactSelectionActivity
} }
private void launch(Recipient recipient) { private void launch(Recipient recipient) {
Intent intent = new Intent(this, ConversationActivity.class); long existingThread = DatabaseFactory.getThreadDatabase(this).getThreadIdIfExistsFor(recipient.getId());
intent.putExtra(ConversationActivity.RECIPIENT_EXTRA, recipient.getId().serialize()); Intent intent = ConversationIntents.createBuilder(this, recipient.getId(), existingThread)
intent.putExtra(ConversationActivity.TEXT_EXTRA, getIntent().getStringExtra(ConversationActivity.TEXT_EXTRA)); .withDraftText(getIntent().getStringExtra(Intent.EXTRA_TEXT))
intent.setDataAndType(getIntent().getData(), getIntent().getType()); .withDataUri(getIntent().getData())
.withDataType(getIntent().getType())
.build();
long existingThread = DatabaseFactory.getThreadDatabase(this).getThreadIdIfExistsFor(recipient.getId());
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, existingThread);
intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, ThreadDatabase.DistributionTypes.DEFAULT);
startActivity(intent); startActivity(intent);
finish(); finish();
} }

View File

@@ -5,14 +5,14 @@ import android.content.Intent;
import android.database.Cursor; import android.database.Cursor;
import android.os.Bundle; import android.os.Bundle;
import android.provider.ContactsContract; import android.provider.ContactsContract;
import androidx.annotation.NonNull;
import android.text.TextUtils; import android.text.TextUtils;
import org.thoughtcrime.securesms.conversation.ConversationActivity;
import org.thoughtcrime.securesms.logging.Log;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.NonNull;
import org.thoughtcrime.securesms.conversation.ConversationIntents;
import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.Rfc5724Uri; import org.thoughtcrime.securesms.util.Rfc5724Uri;
@@ -44,16 +44,15 @@ public class SmsSendtoActivity extends Activity {
if (TextUtils.isEmpty(destination.destination)) { if (TextUtils.isEmpty(destination.destination)) {
nextIntent = new Intent(this, NewConversationActivity.class); nextIntent = new Intent(this, NewConversationActivity.class);
nextIntent.putExtra(ConversationActivity.TEXT_EXTRA, destination.getBody()); nextIntent.putExtra(Intent.EXTRA_TEXT, destination.getBody());
Toast.makeText(this, R.string.ConversationActivity_specify_recipient, Toast.LENGTH_LONG).show(); Toast.makeText(this, R.string.ConversationActivity_specify_recipient, Toast.LENGTH_LONG).show();
} else { } else {
Recipient recipient = Recipient.external(this, destination.getDestination()); Recipient recipient = Recipient.external(this, destination.getDestination());
long threadId = DatabaseFactory.getThreadDatabase(this).getThreadIdIfExistsFor(recipient.getId()); long threadId = DatabaseFactory.getThreadDatabase(this).getThreadIdIfExistsFor(recipient.getId());
nextIntent = new Intent(this, ConversationActivity.class); nextIntent = ConversationIntents.createBuilder(this, recipient.getId(), threadId)
nextIntent.putExtra(ConversationActivity.TEXT_EXTRA, destination.getBody()); .withDraftText(destination.getBody())
nextIntent.putExtra(ConversationActivity.THREAD_ID_EXTRA, threadId); .build();
nextIntent.putExtra(ConversationActivity.RECIPIENT_EXTRA, recipient.getId().serialize());
} }
return nextIntent; return nextIntent;
} }

View File

@@ -17,8 +17,7 @@ import com.google.android.exoplayer2.ui.PlayerNotificationManager;
import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.color.MaterialColor; import org.thoughtcrime.securesms.color.MaterialColor;
import org.thoughtcrime.securesms.contacts.avatars.ContactColors; import org.thoughtcrime.securesms.contacts.avatars.ContactColors;
import org.thoughtcrime.securesms.conversation.ConversationActivity; import org.thoughtcrime.securesms.conversation.ConversationIntents;
import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.notifications.NotificationChannels; import org.thoughtcrime.securesms.notifications.NotificationChannels;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.recipients.RecipientId;
@@ -103,11 +102,9 @@ class VoiceNoteNotificationManager {
notificationManager.setColor(color.toNotificationColor(context)); notificationManager.setColor(color.toNotificationColor(context));
Intent conversationActivity = ConversationActivity.buildIntent(context, Intent conversationActivity = ConversationIntents.createBuilder(context, recipientId, threadId)
recipientId, .withStartingPosition(startingPosition)
threadId, .build();
ThreadDatabase.DistributionTypes.DEFAULT,
startingPosition);
conversationActivity.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); conversationActivity.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

View File

@@ -320,15 +320,6 @@ public class ConversationActivity extends PassphraseRequiredActivity
private static final String STATE_REACT_WITH_ANY_PAGE = "STATE_REACT_WITH_ANY_PAGE"; private static final String STATE_REACT_WITH_ANY_PAGE = "STATE_REACT_WITH_ANY_PAGE";
public static final String RECIPIENT_EXTRA = "recipient_id";
public static final String THREAD_ID_EXTRA = "thread_id";
public static final String TEXT_EXTRA = "draft_text";
public static final String MEDIA_EXTRA = "media_list";
public static final String STICKER_EXTRA = "sticker_extra";
public static final String BORDERLESS_EXTRA = "borderless_extra";
public static final String DISTRIBUTION_TYPE_EXTRA = "distribution_type";
public static final String STARTING_POSITION_EXTRA = "starting_position";
private static final int PICK_GALLERY = 1; private static final int PICK_GALLERY = 1;
private static final int PICK_DOCUMENT = 2; private static final int PICK_DOCUMENT = 2;
private static final int PICK_AUDIO = 3; private static final int PICK_AUDIO = 3;
@@ -398,35 +389,6 @@ public class ConversationActivity extends PassphraseRequiredActivity
private final DynamicTheme dynamicTheme = new DynamicDarkToolbarTheme(); private final DynamicTheme dynamicTheme = new DynamicDarkToolbarTheme();
private final DynamicLanguage dynamicLanguage = new DynamicLanguage(); private final DynamicLanguage dynamicLanguage = new DynamicLanguage();
public static @NonNull Intent buildIntent(@NonNull Context context,
@NonNull RecipientId recipientId,
long threadId,
int distributionType,
int startingPosition)
{
Intent intent = buildIntent(context, recipientId, threadId);
intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, distributionType);
intent.putExtra(ConversationActivity.STARTING_POSITION_EXTRA, startingPosition);
return intent;
}
public static @NonNull Intent buildIntent(@NonNull Context context,
@NonNull RecipientId recipientId,
long threadId)
{
Intent intent = new Intent(context, ConversationActivity.class);
intent.putExtra(ConversationActivity.RECIPIENT_EXTRA, recipientId.serialize());
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, threadId);
intent.setAction(Intent.ACTION_DEFAULT);
return intent;
}
public static @NonNull RecipientId getRecipientId(@NonNull Intent intent) {
return RecipientId.from(Objects.requireNonNull(intent.getStringExtra(RECIPIENT_EXTRA)));
}
@Override @Override
protected void onPreCreate() { protected void onPreCreate() {
dynamicTheme.onCreate(this); dynamicTheme.onCreate(this);
@@ -435,7 +397,7 @@ public class ConversationActivity extends PassphraseRequiredActivity
@Override @Override
protected void onCreate(Bundle state, boolean ready) { protected void onCreate(Bundle state, boolean ready) {
if (getIntent().getStringExtra(RECIPIENT_EXTRA) == null) { if (ConversationIntents.isInvalid(getIntent())) {
Log.w(TAG, "[onCreate] Missing recipientId!"); Log.w(TAG, "[onCreate] Missing recipientId!");
// TODO [greyson] Navigation // TODO [greyson] Navigation
startActivity(new Intent(this, MainActivity.class)); startActivity(new Intent(this, MainActivity.class));
@@ -443,9 +405,9 @@ public class ConversationActivity extends PassphraseRequiredActivity
return; return;
} }
RecipientId recipientId = getRecipientId(getIntent()); ConversationIntents.Args args = ConversationIntents.Args.from(getIntent());
reportShortcutLaunch(recipientId); reportShortcutLaunch(args.getRecipientId());
setContentView(R.layout.conversation_activity); setContentView(R.layout.conversation_activity);
getWindow().getDecorView().setBackgroundResource(R.color.signal_background_primary); getWindow().getDecorView().setBackgroundResource(R.color.signal_background_primary);
@@ -455,11 +417,11 @@ public class ConversationActivity extends PassphraseRequiredActivity
initializeReceivers(); initializeReceivers();
initializeActionBar(); initializeActionBar();
initializeViews(); initializeViews();
initializeResources(); initializeResources(args);
initializeLinkPreviewObserver(); initializeLinkPreviewObserver();
initializeSearchObserver(); initializeSearchObserver();
initializeStickerObserver(); initializeStickerObserver();
initializeViewModel(); initializeViewModel(args);
initializeGroupViewModel(); initializeGroupViewModel();
initializeMentionsViewModel(); initializeMentionsViewModel();
initializeEnabledCheck(); initializeEnabledCheck();
@@ -470,7 +432,7 @@ public class ConversationActivity extends PassphraseRequiredActivity
public void onSuccess(Boolean result) { public void onSuccess(Boolean result) {
initializeProfiles(); initializeProfiles();
initializeGv1Migration(); initializeGv1Migration();
initializeDraft().addListener(new AssertedSuccessListener<Boolean>() { initializeDraft(args).addListener(new AssertedSuccessListener<Boolean>() {
@Override @Override
public void onSuccess(Boolean loadedDraft) { public void onSuccess(Boolean loadedDraft) {
if (loadedDraft != null && loadedDraft) { if (loadedDraft != null && loadedDraft) {
@@ -513,9 +475,7 @@ public class ConversationActivity extends PassphraseRequiredActivity
silentlySetComposeText(""); silentlySetComposeText("");
} }
RecipientId recipientId = getRecipientId(intent); if (ConversationIntents.isInvalid(intent)) {
if (recipientId == null) {
Log.w(TAG, "[onNewIntent] Missing recipientId!"); Log.w(TAG, "[onNewIntent] Missing recipientId!");
// TODO [greyson] Navigation // TODO [greyson] Navigation
startActivity(new Intent(this, MainActivity.class)); startActivity(new Intent(this, MainActivity.class));
@@ -523,13 +483,16 @@ public class ConversationActivity extends PassphraseRequiredActivity
return; return;
} }
reportShortcutLaunch(recipientId);
setIntent(intent); setIntent(intent);
initializeResources();
viewModel.setArgs(ConversationIntents.Args.from(intent));
reportShortcutLaunch(viewModel.getArgs().getRecipientId());
initializeResources(viewModel.getArgs());
initializeSecurity(recipient.get().isRegistered(), isDefaultSms).addListener(new AssertedSuccessListener<Boolean>() { initializeSecurity(recipient.get().isRegistered(), isDefaultSms).addListener(new AssertedSuccessListener<Boolean>() {
@Override @Override
public void onSuccess(Boolean result) { public void onSuccess(Boolean result) {
initializeDraft(); initializeDraft(viewModel.getArgs());
} }
}); });
@@ -1454,16 +1417,16 @@ public class ConversationActivity extends PassphraseRequiredActivity
///// Initializers ///// Initializers
private ListenableFuture<Boolean> initializeDraft() { private ListenableFuture<Boolean> initializeDraft(@NonNull ConversationIntents.Args args) {
final SettableFuture<Boolean> result = new SettableFuture<>(); final SettableFuture<Boolean> result = new SettableFuture<>();
final CharSequence draftText = getIntent().getCharSequenceExtra(TEXT_EXTRA); final CharSequence draftText = args.getDraftText();
final Uri draftMedia = getIntent().getData(); final Uri draftMedia = getIntent().getData();
final String draftContentType = getIntent().getType(); final String draftContentType = getIntent().getType();
final MediaType draftMediaType = MediaType.from(draftContentType); final MediaType draftMediaType = MediaType.from(draftContentType);
final List<Media> mediaList = getIntent().getParcelableArrayListExtra(MEDIA_EXTRA); final List<Media> mediaList = args.getMedia();
final StickerLocator stickerLocator = getIntent().getParcelableExtra(STICKER_EXTRA); final StickerLocator stickerLocator = args.getStickerLocator();
final boolean borderless = getIntent().getBooleanExtra(BORDERLESS_EXTRA, false); final boolean borderless = args.isBorderless();
if (stickerLocator != null && draftMedia != null) { if (stickerLocator != null && draftMedia != null) {
Log.d(TAG, "Handling shared sticker."); Log.d(TAG, "Handling shared sticker.");
@@ -1972,14 +1935,14 @@ public class ConversationActivity extends PassphraseRequiredActivity
supportActionBar.setDisplayShowTitleEnabled(false); supportActionBar.setDisplayShowTitleEnabled(false);
} }
private void initializeResources() { private void initializeResources(@NonNull ConversationIntents.Args args) {
if (recipient != null) { if (recipient != null) {
recipient.removeObservers(this); recipient.removeObservers(this);
} }
recipient = Recipient.live(getRecipientId(getIntent())); recipient = Recipient.live(args.getRecipientId());
threadId = getIntent().getLongExtra(THREAD_ID_EXTRA, -1); threadId = args.getThreadId();
distributionType = getIntent().getIntExtra(DISTRIBUTION_TYPE_EXTRA, ThreadDatabase.DistributionTypes.DEFAULT); distributionType = args.getDistributionType();
glideRequests = GlideApp.with(this); glideRequests = GlideApp.with(this);
recipient.observe(this, this::onRecipientChanged); recipient.observe(this, this::onRecipientChanged);
@@ -2049,8 +2012,10 @@ public class ConversationActivity extends PassphraseRequiredActivity
}); });
} }
private void initializeViewModel() { private void initializeViewModel(@NonNull ConversationIntents.Args args) {
this.viewModel = ViewModelProviders.of(this, new ConversationViewModel.Factory()).get(ConversationViewModel.class); this.viewModel = ViewModelProviders.of(this, new ConversationViewModel.Factory()).get(ConversationViewModel.class);
this.viewModel.setArgs(args);
} }
private void initializeGroupViewModel() { private void initializeGroupViewModel() {
@@ -3572,9 +3537,9 @@ public class ConversationActivity extends PassphraseRequiredActivity
} }
private void presentMessageRequestState(@Nullable MessageRequestViewModel.MessageData messageData) { private void presentMessageRequestState(@Nullable MessageRequestViewModel.MessageData messageData) {
if ((getIntent().hasExtra(TEXT_EXTRA) && !Util.isEmpty(getIntent().getStringExtra(TEXT_EXTRA))) || if (!Util.isEmpty(viewModel.getArgs().getDraftText()) ||
getIntent().hasExtra(MEDIA_EXTRA) || viewModel.getArgs().getMedia() != null ||
getIntent().hasExtra(STICKER_EXTRA)) viewModel.getArgs().getStickerLocator() != null)
{ {
Log.d(TAG, "[presentMessageRequestState] Have extra, so ignoring provided state."); Log.d(TAG, "[presentMessageRequestState] Have extra, so ignoring provided state.");
messageRequestBottomView.setVisibility(View.GONE); messageRequestBottomView.setVisibility(View.GONE);

View File

@@ -114,7 +114,7 @@ import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.recipients.ui.bottomsheet.RecipientBottomSheetDialogFragment; import org.thoughtcrime.securesms.recipients.ui.bottomsheet.RecipientBottomSheetDialogFragment;
import org.thoughtcrime.securesms.revealable.ViewOnceMessageActivity; import org.thoughtcrime.securesms.revealable.ViewOnceMessageActivity;
import org.thoughtcrime.securesms.revealable.ViewOnceUtil; import org.thoughtcrime.securesms.revealable.ViewOnceUtil;
import org.thoughtcrime.securesms.sharing.ShareActivity; import org.thoughtcrime.securesms.sharing.ShareIntents;
import org.thoughtcrime.securesms.sms.MessageSender; import org.thoughtcrime.securesms.sms.MessageSender;
import org.thoughtcrime.securesms.sms.OutgoingTextMessage; import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
import org.thoughtcrime.securesms.stickers.StickerLocator; import org.thoughtcrime.securesms.stickers.StickerLocator;
@@ -389,7 +389,7 @@ public class ConversationFragment extends LoggingFragment {
} }
private int getStartPosition() { private int getStartPosition() {
return requireActivity().getIntent().getIntExtra(ConversationActivity.STARTING_POSITION_EXTRA, -1); return conversationViewModel.getArgs().getStartingPosition();
} }
private void initializeMessageRequestViewModel() { private void initializeMessageRequestViewModel() {
@@ -481,8 +481,8 @@ public class ConversationFragment extends LoggingFragment {
int startingPosition = getStartPosition(); int startingPosition = getStartPosition();
this.recipient = Recipient.live(ConversationActivity.getRecipientId(requireActivity().getIntent())); this.recipient = Recipient.live(conversationViewModel.getArgs().getRecipientId());
this.threadId = this.getActivity().getIntent().getLongExtra(ConversationActivity.THREAD_ID_EXTRA, -1); this.threadId = conversationViewModel.getArgs().getThreadId();
this.markReadHelper = new MarkReadHelper(threadId, requireContext()); this.markReadHelper = new MarkReadHelper(threadId, requireContext());
conversationViewModel.onConversationDataAvailable(threadId, startingPosition); conversationViewModel.onConversationDataAvailable(threadId, startingPosition);
@@ -773,8 +773,8 @@ public class ConversationFragment extends LoggingFragment {
listener.onForwardClicked(); listener.onForwardClicked();
SimpleTask.run(getLifecycle(), () -> { SimpleTask.run(getLifecycle(), () -> {
Intent composeIntent = new Intent(getActivity(), ShareActivity.class); ShareIntents.Builder shareIntentBuilder = new ShareIntents.Builder(requireActivity());
composeIntent.putExtra(Intent.EXTRA_TEXT, conversationMessage.getDisplayBody(requireContext())); shareIntentBuilder.setText(conversationMessage.getDisplayBody(requireContext()));
if (conversationMessage.getMessageRecord().isMms()) { if (conversationMessage.getMessageRecord().isMms()) {
MmsMessageRecord mediaMessage = (MmsMessageRecord) conversationMessage.getMessageRecord(); MmsMessageRecord mediaMessage = (MmsMessageRecord) conversationMessage.getMessageRecord();
@@ -810,31 +810,24 @@ public class ConversationFragment extends LoggingFragment {
} }
if (!mediaList.isEmpty()) { if (!mediaList.isEmpty()) {
composeIntent.putExtra(ConversationActivity.MEDIA_EXTRA, mediaList); shareIntentBuilder.setMedia(mediaList);
} }
} else if (mediaMessage.containsMediaSlide()) { } else if (mediaMessage.containsMediaSlide()) {
Slide slide = mediaMessage.getSlideDeck().getSlides().get(0); Slide slide = mediaMessage.getSlideDeck().getSlides().get(0);
composeIntent.putExtra(Intent.EXTRA_STREAM, slide.getUri()); shareIntentBuilder.setSlide(slide);
composeIntent.setType(slide.getContentType());
composeIntent.putExtra(ConversationActivity.BORDERLESS_EXTRA, slide.isBorderless());
if (slide.hasSticker()) {
composeIntent.putExtra(ConversationActivity.STICKER_EXTRA, slide.asAttachment().getSticker());
composeIntent.setType(slide.asAttachment().getContentType());
}
} }
if (mediaMessage.getSlideDeck().getTextSlide() != null && mediaMessage.getSlideDeck().getTextSlide().getUri() != null) { if (mediaMessage.getSlideDeck().getTextSlide() != null && mediaMessage.getSlideDeck().getTextSlide().getUri() != null) {
try (InputStream stream = PartAuthority.getAttachmentStream(requireContext(), mediaMessage.getSlideDeck().getTextSlide().getUri())) { try (InputStream stream = PartAuthority.getAttachmentStream(requireContext(), mediaMessage.getSlideDeck().getTextSlide().getUri())) {
String fullBody = Util.readFullyAsString(stream); String fullBody = Util.readFullyAsString(stream);
composeIntent.putExtra(Intent.EXTRA_TEXT, fullBody); shareIntentBuilder.setText(fullBody);
} catch (IOException e) { } catch (IOException e) {
Log.w(TAG, "Failed to read long message text when forwarding."); Log.w(TAG, "Failed to read long message text when forwarding.");
} }
} }
} }
return composeIntent; return shareIntentBuilder.build();
}, this::startActivity); }, this::startActivity);
} }

View File

@@ -0,0 +1,229 @@
package org.thoughtcrime.securesms.conversation;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.mediasend.Media;
import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.sharing.ShareIntents;
import org.thoughtcrime.securesms.stickers.StickerLocator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Objects;
public class ConversationIntents {
private static final String EXTRA_RECIPIENT = "recipient_id";
private static final String EXTRA_THREAD_ID = "thread_id";
private static final String EXTRA_TEXT = "draft_text";
private static final String EXTRA_MEDIA = "media_list";
private static final String EXTRA_STICKER = "sticker_extra";
private static final String EXTRA_BORDERLESS = "borderless_extra";
private static final String EXTRA_DISTRIBUTION_TYPE = "distribution_type";
private static final String EXTRA_STARTING_POSITION = "starting_position";
private ConversationIntents() {
}
public static @NonNull Builder createBuilder(@NonNull Context context, @NonNull RecipientId recipientId, long threadId) {
return new Builder(context, recipientId, threadId);
}
public static @NonNull Builder createPopUpBuilder(@NonNull Context context, @NonNull RecipientId recipientId, long threadId) {
return new Builder(context, ConversationPopupActivity.class, recipientId, threadId);
}
static boolean isInvalid(@NonNull Intent intent) {
return !intent.hasExtra(EXTRA_RECIPIENT);
}
final static class Args {
private final RecipientId recipientId;
private final long threadId;
private final String draftText;
private final ArrayList<Media> media;
private final StickerLocator stickerLocator;
private final boolean isBorderless;
private final int distributionType;
private final int startingPosition;
static Args from(@NonNull Intent intent) {
return new Args(RecipientId.from(Objects.requireNonNull(intent.getStringExtra(EXTRA_RECIPIENT))),
intent.getLongExtra(EXTRA_THREAD_ID, -1),
intent.getStringExtra(EXTRA_TEXT),
intent.getParcelableArrayListExtra(EXTRA_MEDIA),
intent.getParcelableExtra(EXTRA_STICKER),
intent.getBooleanExtra(EXTRA_BORDERLESS, false),
intent.getIntExtra(EXTRA_DISTRIBUTION_TYPE, ThreadDatabase.DistributionTypes.DEFAULT),
intent.getIntExtra(EXTRA_STARTING_POSITION, -1));
}
private Args(@NonNull RecipientId recipientId,
long threadId,
@Nullable String draftText,
@Nullable ArrayList<Media> media,
@Nullable StickerLocator stickerLocator,
boolean isBorderless,
int distributionType,
int startingPosition)
{
this.recipientId = recipientId;
this.threadId = threadId;
this.draftText = draftText;
this.media = media;
this.stickerLocator = stickerLocator;
this.isBorderless = isBorderless;
this.distributionType = distributionType;
this.startingPosition = startingPosition;
}
public @NonNull RecipientId getRecipientId() {
return recipientId;
}
public long getThreadId() {
return threadId;
}
public @Nullable String getDraftText() {
return draftText;
}
public @Nullable ArrayList<Media> getMedia() {
return media;
}
public @Nullable StickerLocator getStickerLocator() {
return stickerLocator;
}
public int getDistributionType() {
return distributionType;
}
public int getStartingPosition() {
return startingPosition;
}
public boolean isBorderless() {
return isBorderless;
}
}
public final static class Builder {
private final Context context;
private final Class<? extends ConversationActivity> conversationActivityClass;
private final RecipientId recipientId;
private final long threadId;
private String draftText;
private ArrayList<Media> media;
private StickerLocator stickerLocator;
private boolean isBorderless;
private int distributionType = ThreadDatabase.DistributionTypes.DEFAULT;
private int startingPosition = -1;
private Uri dataUri;
private String dataType;
private Builder(@NonNull Context context,
@NonNull RecipientId recipientId,
long threadId)
{
this(context, ConversationActivity.class, recipientId, threadId);
}
private Builder(@NonNull Context context,
@NonNull Class<? extends ConversationActivity> conversationActivityClass,
@NonNull RecipientId recipientId,
long threadId)
{
this.context = context;
this.conversationActivityClass = conversationActivityClass;
this.recipientId = recipientId;
this.threadId = threadId;
}
public @NonNull Builder withDraftText(@Nullable String draftText) {
this.draftText = draftText;
return this;
}
public @NonNull Builder withMedia(@Nullable Collection<Media> media) {
this.media = media != null ? new ArrayList<>(media) : null;
return this;
}
public @NonNull Builder withStickerLocator(@Nullable StickerLocator stickerLocator) {
this.stickerLocator = stickerLocator;
return this;
}
public @NonNull Builder asBorderless(boolean isBorderless) {
this.isBorderless = isBorderless;
return this;
}
public @NonNull Builder withDistributionType(int distributionType) {
this.distributionType = distributionType;
return this;
}
public @NonNull Builder withStartingPosition(int startingPosition) {
this.startingPosition = startingPosition;
return this;
}
public @NonNull Builder withDataUri(@Nullable Uri dataUri) {
this.dataUri = dataUri;
return this;
}
public @NonNull Builder withDataType(@Nullable String dataType) {
this.dataType = dataType;
return this;
}
public @NonNull Intent build() {
if (stickerLocator != null && media != null) {
throw new IllegalStateException("Cannot have both sticker and media array");
}
Intent intent = new Intent(context, conversationActivityClass);
intent.setAction(Intent.ACTION_DEFAULT);
intent.putExtra(EXTRA_RECIPIENT, recipientId.serialize());
intent.putExtra(EXTRA_THREAD_ID, threadId);
intent.putExtra(EXTRA_DISTRIBUTION_TYPE, distributionType);
intent.putExtra(EXTRA_STARTING_POSITION, startingPosition);
intent.putExtra(EXTRA_BORDERLESS, isBorderless);
if (draftText != null) {
intent.putExtra(EXTRA_TEXT, draftText);
}
if (media != null) {
intent.putParcelableArrayListExtra(EXTRA_MEDIA, media);
}
if (stickerLocator != null) {
intent.putExtra(EXTRA_STICKER, stickerLocator);
}
if (dataUri != null && dataType != null) {
intent.setDataAndType(dataUri, dataType);
} else if (dataUri != null) {
intent.setData(dataUri);
} else if (dataType != null) {
intent.setType(dataType);
}
return intent;
}
}
}

View File

@@ -1,13 +1,7 @@
package org.thoughtcrime.securesms.conversation; package org.thoughtcrime.securesms.conversation;
import android.content.Intent; import android.content.Intent;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.os.Bundle; import android.os.Bundle;
import androidx.core.app.ActivityOptionsCompat;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.logging.Log;
import android.view.Display; import android.view.Display;
import android.view.Gravity; import android.view.Gravity;
import android.view.Menu; import android.view.Menu;
@@ -16,6 +10,10 @@ import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.WindowManager; import android.view.WindowManager;
import androidx.core.app.ActivityOptionsCompat;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.util.concurrent.ListenableFuture; import org.thoughtcrime.securesms.util.concurrent.ListenableFuture;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
@@ -83,9 +81,8 @@ public class ConversationPopupActivity extends ConversationActivity {
@Override @Override
public void onSuccess(Long result) { public void onSuccess(Long result) {
ActivityOptionsCompat transition = ActivityOptionsCompat.makeScaleUpAnimation(getWindow().getDecorView(), 0, 0, getWindow().getAttributes().width, getWindow().getAttributes().height); ActivityOptionsCompat transition = ActivityOptionsCompat.makeScaleUpAnimation(getWindow().getDecorView(), 0, 0, getWindow().getAttributes().width, getWindow().getAttributes().height);
Intent intent = new Intent(ConversationPopupActivity.this, ConversationActivity.class); Intent intent = ConversationIntents.createBuilder(ConversationPopupActivity.this, getRecipient().getId(), result)
intent.putExtra(ConversationActivity.RECIPIENT_EXTRA, getRecipient().getId().serialize()); .build();
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, result);
startActivity(intent, transition.toBundle()); startActivity(intent, transition.toBundle());

View File

@@ -4,6 +4,7 @@ import android.app.Application;
import androidx.annotation.MainThread; import androidx.annotation.MainThread;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.LiveData; import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.Transformations; import androidx.lifecycle.Transformations;
@@ -39,6 +40,7 @@ class ConversationViewModel extends ViewModel {
private final MutableLiveData<Boolean> showScrollButtons; private final MutableLiveData<Boolean> showScrollButtons;
private final MutableLiveData<Boolean> hasUnreadMentions; private final MutableLiveData<Boolean> hasUnreadMentions;
private ConversationIntents.Args args;
private int jumpToPosition; private int jumpToPosition;
private ConversationViewModel() { private ConversationViewModel() {
@@ -147,6 +149,14 @@ class ConversationViewModel extends ViewModel {
return conversationMetadata.getValue() != null ? conversationMetadata.getValue().getLastSeenPosition() : 0; return conversationMetadata.getValue() != null ? conversationMetadata.getValue().getLastSeenPosition() : 0;
} }
void setArgs(@NonNull ConversationIntents.Args args) {
this.args = args;
}
@NonNull ConversationIntents.Args getArgs() {
return Objects.requireNonNull(args);
}
@Override @Override
protected void onCleared() { protected void onCleared() {
super.onCleared(); super.onCleared();

View File

@@ -12,7 +12,7 @@ import androidx.navigation.Navigation;
import org.thoughtcrime.securesms.PassphraseRequiredActivity; import org.thoughtcrime.securesms.PassphraseRequiredActivity;
import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.conversation.ConversationActivity; import org.thoughtcrime.securesms.conversation.ConversationIntents;
import org.thoughtcrime.securesms.database.ThreadDatabase; import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.groups.ui.managegroup.dialogs.GroupInviteSentDialog; import org.thoughtcrime.securesms.groups.ui.managegroup.dialogs.GroupInviteSentDialog;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
@@ -73,11 +73,8 @@ public class AddGroupDetailsActivity extends PassphraseRequiredActivity implemen
} }
void goToConversation(@NonNull RecipientId recipientId, long threadId) { void goToConversation(@NonNull RecipientId recipientId, long threadId) {
Intent intent = ConversationActivity.buildIntent(this, Intent intent = ConversationIntents.createBuilder(this, recipientId, threadId)
recipientId, .build();
threadId,
ThreadDatabase.DistributionTypes.DEFAULT,
-1);
startActivity(intent); startActivity(intent);
setResult(RESULT_OK); setResult(RESULT_OK);

View File

@@ -23,7 +23,7 @@ import org.thoughtcrime.securesms.color.MaterialColor;
import org.thoughtcrime.securesms.components.AvatarImageView; import org.thoughtcrime.securesms.components.AvatarImageView;
import org.thoughtcrime.securesms.contacts.avatars.FallbackContactPhoto; import org.thoughtcrime.securesms.contacts.avatars.FallbackContactPhoto;
import org.thoughtcrime.securesms.contacts.avatars.ResourceContactPhoto; import org.thoughtcrime.securesms.contacts.avatars.ResourceContactPhoto;
import org.thoughtcrime.securesms.conversation.ConversationActivity; import org.thoughtcrime.securesms.conversation.ConversationIntents;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.groups.v2.GroupInviteLinkUrl; import org.thoughtcrime.securesms.groups.v2.GroupInviteLinkUrl;
import org.thoughtcrime.securesms.jobs.RetrieveProfileJob; import org.thoughtcrime.securesms.jobs.RetrieveProfileJob;
@@ -152,7 +152,8 @@ public final class GroupJoinBottomSheetDialogFragment extends BottomSheetDialogF
viewModel.getJoinSuccess().observe(getViewLifecycleOwner(), joinGroupSuccess -> { viewModel.getJoinSuccess().observe(getViewLifecycleOwner(), joinGroupSuccess -> {
Log.i(TAG, "Group joined, navigating to group"); Log.i(TAG, "Group joined, navigating to group");
Intent intent = ConversationActivity.buildIntent(requireContext(), joinGroupSuccess.getGroupRecipient().getId(), joinGroupSuccess.getGroupThreadId()); Intent intent = ConversationIntents.createBuilder(requireContext(), joinGroupSuccess.getGroupRecipient().getId(), joinGroupSuccess.getGroupThreadId())
.build();
requireActivity().startActivity(intent); requireActivity().startActivity(intent);
dismiss(); dismiss();

View File

@@ -47,6 +47,7 @@ import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.contactshare.Contact; import org.thoughtcrime.securesms.contactshare.Contact;
import org.thoughtcrime.securesms.contactshare.ContactUtil; import org.thoughtcrime.securesms.contactshare.ContactUtil;
import org.thoughtcrime.securesms.conversation.ConversationActivity; import org.thoughtcrime.securesms.conversation.ConversationActivity;
import org.thoughtcrime.securesms.conversation.ConversationIntents;
import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MentionUtil; import org.thoughtcrime.securesms.database.MentionUtil;
import org.thoughtcrime.securesms.database.MmsSmsColumns; import org.thoughtcrime.securesms.database.MmsSmsColumns;
@@ -135,12 +136,11 @@ public class DefaultMessageNotifier implements MessageNotifier {
if (visibleThread == threadId) { if (visibleThread == threadId) {
sendInThreadNotification(context, recipient); sendInThreadNotification(context, recipient);
} else { } else {
Intent intent = new Intent(context, ConversationActivity.class); Intent intent = ConversationIntents.createBuilder(context, recipient.getId(), threadId)
intent.putExtra(ConversationActivity.RECIPIENT_EXTRA, recipient.getId().serialize()); .withDataUri(Uri.parse("custom://" + System.currentTimeMillis()))
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, threadId); .build();
intent.setData((Uri.parse("custom://" + System.currentTimeMillis())));
FailedNotificationBuilder builder = new FailedNotificationBuilder(context, TextSecurePreferences.getNotificationPrivacy(context), intent); FailedNotificationBuilder builder = new FailedNotificationBuilder(context, TextSecurePreferences.getNotificationPrivacy(context), intent);
((NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE)) ((NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE))
.notify((int)threadId, builder.build()); .notify((int)threadId, builder.build());
} }

View File

@@ -9,7 +9,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.core.app.TaskStackBuilder; import androidx.core.app.TaskStackBuilder;
import org.thoughtcrime.securesms.conversation.ConversationActivity; import org.thoughtcrime.securesms.conversation.ConversationIntents;
import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.mms.SlideDeck; import org.thoughtcrime.securesms.mms.SlideDeck;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
@@ -90,7 +90,9 @@ public class NotificationItem {
Recipient recipient = threadRecipient != null ? threadRecipient : conversationRecipient; Recipient recipient = threadRecipient != null ? threadRecipient : conversationRecipient;
int startingPosition = jumpToMessage ? getStartingPosition(context, threadId, messageReceivedTimestamp) : -1; int startingPosition = jumpToMessage ? getStartingPosition(context, threadId, messageReceivedTimestamp) : -1;
Intent intent = ConversationActivity.buildIntent(context, recipient.getId(), threadId, 0, startingPosition); Intent intent = ConversationIntents.createBuilder(context, recipient.getId(), threadId)
.withStartingPosition(startingPosition)
.build();
makeIntentUniqueToPreventMerging(intent); makeIntentUniqueToPreventMerging(intent);

View File

@@ -10,6 +10,7 @@ import androidx.annotation.Nullable;
import org.thoughtcrime.securesms.contacts.TurnOffContactJoinedNotificationsActivity; import org.thoughtcrime.securesms.contacts.TurnOffContactJoinedNotificationsActivity;
import org.thoughtcrime.securesms.conversation.ConversationActivity; import org.thoughtcrime.securesms.conversation.ConversationActivity;
import org.thoughtcrime.securesms.conversation.ConversationIntents;
import org.thoughtcrime.securesms.conversation.ConversationPopupActivity; import org.thoughtcrime.securesms.conversation.ConversationPopupActivity;
import org.thoughtcrime.securesms.database.RecipientDatabase.VibrateState; import org.thoughtcrime.securesms.database.RecipientDatabase.VibrateState;
import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.logging.Log;
@@ -181,10 +182,9 @@ public class NotificationState {
public PendingIntent getQuickReplyIntent(Context context, Recipient recipient) { public PendingIntent getQuickReplyIntent(Context context, Recipient recipient) {
if (threads.size() != 1) throw new AssertionError("We only support replies to single thread notifications! " + threads.size()); if (threads.size() != 1) throw new AssertionError("We only support replies to single thread notifications! " + threads.size());
Intent intent = new Intent(context, ConversationPopupActivity.class); Intent intent = ConversationIntents.createPopUpBuilder(context, recipient.getId(), (long) threads.toArray()[0])
intent.putExtra(ConversationActivity.RECIPIENT_EXTRA, recipient.getId().serialize()); .withDataUri(Uri.parse("custom://"+System.currentTimeMillis()))
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, (long)threads.toArray()[0]); .build();
intent.setData((Uri.parse("custom://"+System.currentTimeMillis())));
return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
} }

View File

@@ -20,32 +20,29 @@ package org.thoughtcrime.securesms.sharing;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.lifecycle.ViewModelProviders;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.widget.Toolbar;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.Toolbar;
import androidx.lifecycle.ViewModelProviders;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import org.thoughtcrime.securesms.ContactSelectionListFragment; import org.thoughtcrime.securesms.ContactSelectionListFragment;
import org.thoughtcrime.securesms.PassphraseRequiredActivity; import org.thoughtcrime.securesms.PassphraseRequiredActivity;
import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.components.SearchToolbar; import org.thoughtcrime.securesms.components.SearchToolbar;
import org.thoughtcrime.securesms.contacts.ContactsCursorLoader.DisplayMode; import org.thoughtcrime.securesms.contacts.ContactsCursorLoader.DisplayMode;
import org.thoughtcrime.securesms.conversation.ConversationActivity; import org.thoughtcrime.securesms.conversation.ConversationIntents;
import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.mediasend.Media;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.stickers.StickerLocator;
import org.thoughtcrime.securesms.util.DynamicLanguage; import org.thoughtcrime.securesms.util.DynamicLanguage;
import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme; import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme;
import org.thoughtcrime.securesms.util.DynamicTheme; import org.thoughtcrime.securesms.util.DynamicTheme;
@@ -56,7 +53,6 @@ import org.thoughtcrime.securesms.util.views.SimpleProgressDialog;
import org.whispersystems.libsignal.util.Pair; import org.whispersystems.libsignal.util.Pair;
import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.libsignal.util.guava.Optional;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
@@ -300,37 +296,30 @@ public class ShareActivity extends PassphraseRequiredActivity
} }
private void openConversation(long threadId, @NonNull RecipientId recipientId, @Nullable ShareData shareData) { private void openConversation(long threadId, @NonNull RecipientId recipientId, @Nullable ShareData shareData) {
Intent intent = new Intent(this, ConversationActivity.class); ShareIntents.Args args = ShareIntents.Args.from(getIntent());
CharSequence textExtra = getIntent().getCharSequenceExtra(Intent.EXTRA_TEXT); ConversationIntents.Builder builder = ConversationIntents.createBuilder(this, recipientId, threadId)
ArrayList<Media> mediaExtra = getIntent().getParcelableArrayListExtra(ConversationActivity.MEDIA_EXTRA); .withMedia(args.getExtraMedia())
StickerLocator stickerExtra = getIntent().getParcelableExtra(ConversationActivity.STICKER_EXTRA); .withDraftText(args.getExtraText() != null ? args.getExtraText().toString() : null)
boolean borderlessExtra = getIntent().getBooleanExtra(ConversationActivity.BORDERLESS_EXTRA, false); .withStickerLocator(args.getExtraSticker())
.asBorderless(args.isBorderless());
intent.putExtra(ConversationActivity.TEXT_EXTRA, textExtra);
intent.putExtra(ConversationActivity.MEDIA_EXTRA, mediaExtra);
intent.putExtra(ConversationActivity.STICKER_EXTRA, stickerExtra);
intent.putExtra(ConversationActivity.BORDERLESS_EXTRA, borderlessExtra);
if (shareData != null && shareData.isForIntent()) { if (shareData != null && shareData.isForIntent()) {
Log.i(TAG, "Shared data is a single file."); Log.i(TAG, "Shared data is a single file.");
intent.setDataAndType(shareData.getUri(), shareData.getMimeType()); builder.withDataUri(shareData.getUri())
.withDataType(shareData.getMimeType());
} else if (shareData != null && shareData.isForMedia()) { } else if (shareData != null && shareData.isForMedia()) {
Log.i(TAG, "Shared data is set of media."); Log.i(TAG, "Shared data is set of media.");
intent.putExtra(ConversationActivity.MEDIA_EXTRA, shareData.getMedia()); builder.withMedia(shareData.getMedia());
} else if (shareData != null && shareData.isForPrimitive()) { } else if (shareData != null && shareData.isForPrimitive()) {
Log.i(TAG, "Shared data is a primitive type."); Log.i(TAG, "Shared data is a primitive type.");
} else if (shareData == null && stickerExtra != null) { } else if (shareData == null && args.getExtraSticker() != null) {
intent.setType(getIntent().getType()); builder.withDataType(getIntent().getType());
} else { } else {
Log.i(TAG, "Shared data was not external."); Log.i(TAG, "Shared data was not external.");
} }
intent.putExtra(ConversationActivity.RECIPIENT_EXTRA, recipientId.serialize());
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, threadId);
intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, ThreadDatabase.DistributionTypes.DEFAULT);
viewModel.onSuccessulShare(); viewModel.onSuccessulShare();
startActivity(intent); startActivity(builder.build());
} }
} }

View File

@@ -0,0 +1,120 @@
package org.thoughtcrime.securesms.sharing;
import android.content.Context;
import android.content.Intent;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.thoughtcrime.securesms.mediasend.Media;
import org.thoughtcrime.securesms.mms.Slide;
import org.thoughtcrime.securesms.stickers.StickerLocator;
import java.util.ArrayList;
import java.util.Collection;
public final class ShareIntents {
private static final String EXTRA_MEDIA = "extra_media";
private static final String EXTRA_BORDERLESS = "extra_borderless";
private static final String EXTRA_STICKER = "extra_sticker";
private ShareIntents() {
}
public static final class Args {
private final CharSequence extraText;
private final ArrayList<Media> extraMedia;
private final StickerLocator extraSticker;
private final boolean isBorderless;
public static Args from(@NonNull Intent intent) {
return new Args(intent.getStringExtra(Intent.EXTRA_TEXT),
intent.getParcelableArrayListExtra(EXTRA_MEDIA),
intent.getParcelableExtra(EXTRA_STICKER),
intent.getBooleanExtra(EXTRA_BORDERLESS, false));
}
private Args(@Nullable CharSequence extraText,
@Nullable ArrayList<Media> extraMedia,
@Nullable StickerLocator extraSticker,
boolean isBorderless)
{
this.extraText = extraText;
this.extraMedia = extraMedia;
this.extraSticker = extraSticker;
this.isBorderless = isBorderless;
}
public @Nullable ArrayList<Media> getExtraMedia() {
return extraMedia;
}
public @Nullable CharSequence getExtraText() {
return extraText;
}
public @Nullable StickerLocator getExtraSticker() {
return extraSticker;
}
public boolean isBorderless() {
return isBorderless;
}
}
public static final class Builder {
private final Context context;
private String extraText;
private ArrayList<Media> extraMedia;
private Slide slide;
public Builder(@NonNull Context context) {
this.context = context;
}
public @NonNull Builder setText(@NonNull CharSequence extraText) {
this.extraText = extraText.toString();
return this;
}
public @NonNull Builder setMedia(@NonNull Collection<Media> extraMedia) {
this.extraMedia = new ArrayList<>(extraMedia);
return this;
}
public @NonNull Builder setSlide(@NonNull Slide slide) {
this.slide = slide;
return this;
}
public @NonNull Intent build() {
if (slide != null && extraMedia != null) {
throw new IllegalStateException("Cannot create intent with both Slide and [Media]");
}
Intent intent = new Intent(context, ShareActivity.class);
intent.putExtra(Intent.EXTRA_TEXT, extraText);
if (extraMedia != null) {
intent.putParcelableArrayListExtra(EXTRA_MEDIA, extraMedia);
} else if (slide != null) {
intent.putExtra(Intent.EXTRA_STREAM, slide.getUri());
intent.putExtra(EXTRA_BORDERLESS, slide.isBorderless());
if (slide.hasSticker()) {
intent.putExtra(EXTRA_STICKER, slide.asAttachment().getSticker());
intent.setType(slide.asAttachment().getContentType());
} else {
intent.setType(slide.getContentType());
}
}
return intent;
}
}
}

View File

@@ -23,6 +23,7 @@ import androidx.fragment.app.FragmentActivity;
import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.WebRtcCallActivity; import org.thoughtcrime.securesms.WebRtcCallActivity;
import org.thoughtcrime.securesms.conversation.ConversationActivity; import org.thoughtcrime.securesms.conversation.ConversationActivity;
import org.thoughtcrime.securesms.conversation.ConversationIntents;
import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.GroupDatabase; import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.groups.GroupId; import org.thoughtcrime.securesms.groups.GroupId;
@@ -103,12 +104,12 @@ public class CommunicationActions {
@Override @Override
protected void onPostExecute(Long threadId) { protected void onPostExecute(Long threadId) {
Intent intent = ConversationActivity.buildIntent(context, recipient.getId(), threadId); ConversationIntents.Builder builder = ConversationIntents.createBuilder(context, recipient.getId(), threadId);
if (!TextUtils.isEmpty(text)) { if (!TextUtils.isEmpty(text)) {
intent.putExtra(ConversationActivity.TEXT_EXTRA, text); builder.withDraftText(text);
} }
Intent intent = builder.build();
if (backStack != null) { if (backStack != null) {
backStack.addNextIntent(intent); backStack.addNextIntent(intent);
backStack.startActivities(); backStack.startActivities();

View File

@@ -15,6 +15,7 @@ import com.annimon.stream.Stream;
import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.conversation.ConversationActivity; import org.thoughtcrime.securesms.conversation.ConversationActivity;
import org.thoughtcrime.securesms.conversation.ConversationIntents;
import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.GroupDatabase; import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.groups.GroupId; import org.thoughtcrime.securesms.groups.GroupId;
@@ -176,7 +177,7 @@ public final class ConversationUtil {
return new ShortcutInfo.Builder(context, getShortcutId(resolved)) return new ShortcutInfo.Builder(context, getShortcutId(resolved))
.setLongLived(true) .setLongLived(true)
.setIntent(ConversationActivity.buildIntent(context, resolved.getId(), threadId)) .setIntent(ConversationIntents.createBuilder(context, resolved.getId(), threadId).build())
.setShortLabel(shortName) .setShortLabel(shortName)
.setLongLabel(longName) .setLongLabel(longName)
.setIcon(AvatarUtil.getIconForShortcut(context, resolved)) .setIcon(AvatarUtil.getIconForShortcut(context, resolved))