enable media forwarding

fixes #1362
closes #4589
// FREEBIE
This commit is contained in:
Jake McGinty 2015-11-18 12:54:40 -08:00
parent 6a99c6c4ac
commit 02c37e815c
7 changed files with 101 additions and 79 deletions

View File

@ -154,11 +154,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
public static final String RECIPIENTS_EXTRA = "recipients"; public static final String RECIPIENTS_EXTRA = "recipients";
public static final String THREAD_ID_EXTRA = "thread_id"; public static final String THREAD_ID_EXTRA = "thread_id";
public static final String DRAFT_TEXT_EXTRA = "draft_text"; public static final String TEXT_EXTRA = "draft_text";
public static final String DRAFT_IMAGE_EXTRA = "draft_image";
public static final String DRAFT_GIF_EXTRA = "draft_gif";
public static final String DRAFT_AUDIO_EXTRA = "draft_audio";
public static final String DRAFT_VIDEO_EXTRA = "draft_video";
public static final String DISTRIBUTION_TYPE_EXTRA = "distribution_type"; public static final String DISTRIBUTION_TYPE_EXTRA = "distribution_type";
private static final int PICK_IMAGE = 1; private static final int PICK_IMAGE = 1;
@ -709,20 +705,14 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
///// Initializers ///// Initializers
private void initializeDraft() { private void initializeDraft() {
String draftText = getIntent().getStringExtra(DRAFT_TEXT_EXTRA); final String draftText = getIntent().getStringExtra(TEXT_EXTRA);
Uri draftGif = getIntent().getParcelableExtra(DRAFT_GIF_EXTRA); final Uri draftMedia = getIntent().getData();
Uri draftImage = getIntent().getParcelableExtra(DRAFT_IMAGE_EXTRA); final MediaType draftMediaType = MediaType.from(getIntent().getType());
Uri draftAudio = getIntent().getParcelableExtra(DRAFT_AUDIO_EXTRA);
Uri draftVideo = getIntent().getParcelableExtra(DRAFT_VIDEO_EXTRA);
if (draftText != null) composeText.setText(draftText); if (draftText != null) composeText.setText(draftText);
if (draftMedia != null && draftMediaType != null) setMedia(draftMedia, draftMediaType);
if (draftGif != null) setMedia(draftGif, MediaType.GIF); if (draftText == null && draftMedia == null && draftMediaType == null) {
if (draftImage != null) setMedia(draftImage, MediaType.IMAGE);
else if (draftAudio != null) setMedia(draftAudio, MediaType.AUDIO);
else if (draftVideo != null) setMedia(draftVideo, MediaType.VIDEO);
if (draftText == null && draftImage == null && draftAudio == null && draftVideo == null) {
initializeDraftFromDatabase(); initializeDraftFromDatabase();
} else { } else {
updateToggleButtonState(); updateToggleButtonState();

View File

@ -105,7 +105,8 @@ public class ConversationFragment extends Fragment
loadMoreView = inflater.inflate(R.layout.load_more_header, container, false); loadMoreView = inflater.inflate(R.layout.load_more_header, container, false);
loadMoreView.setOnClickListener(new OnClickListener() { loadMoreView.setOnClickListener(new OnClickListener() {
@Override public void onClick(View v) { @Override
public void onClick(View v) {
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putLong("limit", 0); args.putLong("limit", 0);
getLoaderManager().restartLoader(0, args, ConversationFragment.this); getLoaderManager().restartLoader(0, args, ConversationFragment.this);
@ -305,6 +306,14 @@ public class ConversationFragment extends Fragment
private void handleForwardMessage(MessageRecord message) { private void handleForwardMessage(MessageRecord message) {
Intent composeIntent = new Intent(getActivity(), ShareActivity.class); Intent composeIntent = new Intent(getActivity(), ShareActivity.class);
composeIntent.putExtra(Intent.EXTRA_TEXT, message.getDisplayBody().toString()); composeIntent.putExtra(Intent.EXTRA_TEXT, message.getDisplayBody().toString());
if (message.isMms()) {
MediaMmsMessageRecord mediaMessage = (MediaMmsMessageRecord) message;
if (mediaMessage.containsMediaSlide()) {
Slide slide = mediaMessage.getSlideDeck().getSlides().get(0);
composeIntent.putExtra(Intent.EXTRA_STREAM, slide.getUri());
composeIntent.setType(slide.getContentType());
}
}
startActivity(composeIntent); startActivity(composeIntent);
} }

View File

@ -52,13 +52,9 @@ public class NewConversationActivity extends ContactSelectionActivity {
public void onContactSelected(String number) { public void onContactSelected(String number) {
Recipients recipients = RecipientFactory.getRecipientsFromString(this, number, true); Recipients recipients = RecipientFactory.getRecipientsFromString(this, number, true);
if (recipients != null) {
Intent intent = new Intent(this, ConversationActivity.class); Intent intent = new Intent(this, ConversationActivity.class);
intent.putExtra(ConversationActivity.RECIPIENTS_EXTRA, recipients.getIds()); intent.putExtra(ConversationActivity.RECIPIENTS_EXTRA, recipients.getIds());
intent.putExtra(ConversationActivity.DRAFT_TEXT_EXTRA, getIntent().getStringExtra(ConversationActivity.DRAFT_TEXT_EXTRA)); intent.setDataAndType(getIntent().getData(), getIntent().getType());
intent.putExtra(ConversationActivity.DRAFT_AUDIO_EXTRA, getIntent().getParcelableExtra(ConversationActivity.DRAFT_AUDIO_EXTRA));
intent.putExtra(ConversationActivity.DRAFT_VIDEO_EXTRA, getIntent().getParcelableExtra(ConversationActivity.DRAFT_VIDEO_EXTRA));
intent.putExtra(ConversationActivity.DRAFT_IMAGE_EXTRA, getIntent().getParcelableExtra(ConversationActivity.DRAFT_IMAGE_EXTRA));
long existingThread = DatabaseFactory.getThreadDatabase(this).getThreadIdIfExistsFor(recipients); long existingThread = DatabaseFactory.getThreadDatabase(this).getThreadIdIfExistsFor(recipients);
@ -67,7 +63,6 @@ public class NewConversationActivity extends ContactSelectionActivity {
startActivity(intent); startActivity(intent);
finish(); finish();
} }
}
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {

View File

@ -32,18 +32,16 @@ import android.view.ViewGroup;
import android.webkit.MimeTypeMap; import android.webkit.MimeTypeMap;
import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.mms.PartAuthority;
import org.thoughtcrime.securesms.providers.PersistentBlobProvider; import org.thoughtcrime.securesms.providers.PersistentBlobProvider;
import org.thoughtcrime.securesms.recipients.Recipients; import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.util.DynamicLanguage; import org.thoughtcrime.securesms.util.DynamicLanguage;
import org.thoughtcrime.securesms.util.DynamicTheme; import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.MediaUtil;
import org.thoughtcrime.securesms.util.ViewUtil; import org.thoughtcrime.securesms.util.ViewUtil;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import ws.com.google.android.mms.ContentType;
/** /**
* An activity to quickly share content with contacts * An activity to quickly share content with contacts
* *
@ -110,35 +108,18 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity
private void initializeMedia() { private void initializeMedia() {
final Context context = this; final Context context = this;
isPassingAlongMedia = false; isPassingAlongMedia = false;
Uri streamExtra = getIntent().getParcelableExtra(Intent.EXTRA_STREAM);
if (streamExtra != null && PartAuthority.isLocalUri(streamExtra)) {
isPassingAlongMedia = true;
resolvedExtra = streamExtra;
fragmentContainer.setVisibility(View.VISIBLE);
progressWheel.setVisibility(View.GONE);
} else {
fragmentContainer.setVisibility(View.GONE); fragmentContainer.setVisibility(View.GONE);
progressWheel.setVisibility(View.VISIBLE); progressWheel.setVisibility(View.VISIBLE);
new AsyncTask<Uri, Void, Uri>() { new ResolveMediaTask(context).execute(streamExtra);
@Override
protected Uri doInBackground(Uri... uris) {
try {
if (uris.length != 1 || uris[0] == null) {
return null;
} }
InputStream input = context.getContentResolver().openInputStream(uris[0]);
if (input == null) {
return null;
}
return PersistentBlobProvider.getInstance(context).create(masterSecret, input);
} catch (IOException ioe) {
Log.w(TAG, ioe);
return null;
}
}
@Override
protected void onPostExecute(Uri uri) {
resolvedExtra = uri;
ViewUtil.fadeIn(fragmentContainer, 300);
ViewUtil.fadeOut(progressWheel, 300);
}
}.execute(getIntent().<Uri>getParcelableExtra(Intent.EXTRA_STREAM));
} }
@Override @Override
@ -187,19 +168,8 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity
final String textExtra = getIntent().getStringExtra(Intent.EXTRA_TEXT); final String textExtra = getIntent().getStringExtra(Intent.EXTRA_TEXT);
final Uri streamExtra = getIntent().getParcelableExtra(Intent.EXTRA_STREAM); final Uri streamExtra = getIntent().getParcelableExtra(Intent.EXTRA_STREAM);
final String type = streamExtra != null ? getMimeType(streamExtra) : getIntent().getType(); final String type = streamExtra != null ? getMimeType(streamExtra) : getIntent().getType();
intent.putExtra(ConversationActivity.TEXT_EXTRA, textExtra);
if (resolvedExtra != null) { if (resolvedExtra != null) intent.setDataAndType(resolvedExtra, type);
if (MediaUtil.isGif(type)) {
intent.putExtra(ConversationActivity.DRAFT_GIF_EXTRA, resolvedExtra);
} else if (ContentType.isImageType(type)) {
intent.putExtra(ConversationActivity.DRAFT_IMAGE_EXTRA, resolvedExtra);
} else if (ContentType.isAudioType(type)) {
intent.putExtra(ConversationActivity.DRAFT_AUDIO_EXTRA, resolvedExtra);
} else if (ContentType.isVideoType(type)) {
intent.putExtra(ConversationActivity.DRAFT_VIDEO_EXTRA, resolvedExtra);
}
}
intent.putExtra(ConversationActivity.DRAFT_TEXT_EXTRA, textExtra);
return intent; return intent;
} }
@ -212,6 +182,40 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity
type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension); type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
} }
return type; return type == null ? getIntent().getType() : type;
}
private class ResolveMediaTask extends AsyncTask<Uri, Void, Uri> {
private final Context context;
public ResolveMediaTask(Context context) {
this.context = context;
}
@Override
protected Uri doInBackground(Uri... uris) {
try {
if (uris.length != 1 || uris[0] == null) {
return null;
}
InputStream input = context.getContentResolver().openInputStream(uris[0]);
if (input == null) {
return null;
}
return PersistentBlobProvider.getInstance(context).create(masterSecret, input);
} catch (IOException ioe) {
Log.w(TAG, ioe);
return null;
}
}
@Override
protected void onPostExecute(Uri uri) {
resolvedExtra = uri;
ViewUtil.fadeIn(fragmentContainer, 300);
ViewUtil.fadeOut(progressWheel, 300);
}
} }
} }

View File

@ -42,13 +42,13 @@ public class SmsSendtoActivity extends Activity {
long threadId = DatabaseFactory.getThreadDatabase(this).getThreadIdIfExistsFor(recipients); long threadId = DatabaseFactory.getThreadDatabase(this).getThreadIdIfExistsFor(recipients);
final Intent nextIntent; final Intent nextIntent;
if (recipients == null || recipients.isEmpty()) { if (recipients.isEmpty()) {
nextIntent = new Intent(this, NewConversationActivity.class); nextIntent = new Intent(this, NewConversationActivity.class);
nextIntent.putExtra(ConversationActivity.DRAFT_TEXT_EXTRA, destination.getBody()); nextIntent.putExtra(ConversationActivity.TEXT_EXTRA, 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 {
nextIntent = new Intent(this, ConversationActivity.class); nextIntent = new Intent(this, ConversationActivity.class);
nextIntent.putExtra(ConversationActivity.DRAFT_TEXT_EXTRA, destination.getBody()); nextIntent.putExtra(ConversationActivity.TEXT_EXTRA, destination.getBody());
nextIntent.putExtra(ConversationActivity.THREAD_ID_EXTRA, threadId); nextIntent.putExtra(ConversationActivity.THREAD_ID_EXTRA, threadId);
nextIntent.putExtra(ConversationActivity.RECIPIENTS_EXTRA, recipients.getIds()); nextIntent.putExtra(ConversationActivity.RECIPIENTS_EXTRA, recipients.getIds());
} }

View File

@ -27,6 +27,7 @@ import android.provider.ContactsContract;
import android.provider.MediaStore; import android.provider.MediaStore;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import android.widget.Toast; import android.widget.Toast;
@ -46,6 +47,8 @@ import org.whispersystems.libaxolotl.util.guava.Optional;
import java.io.IOException; import java.io.IOException;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import ws.com.google.android.mms.ContentType;
public class AttachmentManager { public class AttachmentManager {
private final static String TAG = AttachmentManager.class.getSimpleName(); private final static String TAG = AttachmentManager.class.getSimpleName();
@ -279,5 +282,14 @@ public class AttachmentManager {
default: throw new AssertionError("unrecognized enum"); default: throw new AssertionError("unrecognized enum");
} }
} }
public static @Nullable MediaType from(final @Nullable String mimeType) {
if (TextUtils.isEmpty(mimeType)) return null;
if (MediaUtil.isGif(mimeType)) return GIF;
if (ContentType.isImageType(mimeType)) return IMAGE;
if (ContentType.isAudioType(mimeType)) return AUDIO;
if (ContentType.isVideoType(mimeType)) return VIDEO;
return null;
}
} }
} }

View File

@ -76,4 +76,16 @@ public class PartAuthority {
Uri uri = Uri.withAppendedPath(THUMB_CONTENT_URI, String.valueOf(attachmentId.getUniqueId())); Uri uri = Uri.withAppendedPath(THUMB_CONTENT_URI, String.valueOf(attachmentId.getUniqueId()));
return ContentUris.withAppendedId(uri, attachmentId.getRowId()); return ContentUris.withAppendedId(uri, attachmentId.getRowId());
} }
public static boolean isLocalUri(final @NonNull Uri uri) {
int match = uriMatcher.match(uri);
switch (match) {
case PART_ROW:
case THUMB_ROW:
case PERSISTENT_ROW:
case SINGLE_USE_ROW:
return true;
}
return false;
}
} }