mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-05-03 23:15:44 +01:00
Move media attachment long-click event to context menu.
Long-click on a media attachment will now bring up the normal context menu for a ConversationItem long-click, but with the addition of a "save attachment" option. This allows users to long-click on messages with media in them and still see the other contextual menu options. // FREEBIE
This commit is contained in:
@@ -17,17 +17,14 @@
|
||||
package org.thoughtcrime.securesms;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.media.MediaScannerConnection;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.provider.Contacts.Intents;
|
||||
@@ -35,12 +32,10 @@ import android.provider.ContactsContract.QuickContact;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.webkit.MimeTypeMap;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.MmsDatabase;
|
||||
@@ -53,18 +48,12 @@ import org.thoughtcrime.securesms.mms.SlideDeck;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.service.SendReceiveService;
|
||||
import org.thoughtcrime.securesms.util.DateUtils;
|
||||
import org.thoughtcrime.securesms.util.Emoji;
|
||||
import org.thoughtcrime.securesms.util.Dialogs;
|
||||
import org.thoughtcrime.securesms.util.Emoji;
|
||||
import org.whispersystems.textsecure.crypto.MasterSecret;
|
||||
import org.whispersystems.textsecure.util.FutureTaskListener;
|
||||
import org.whispersystems.textsecure.util.ListenableFutureTask;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* A view that displays an individual conversation item within a conversation
|
||||
* thread. Used by ComposeMessageActivity's ListActivity via a ConversationAdapter.
|
||||
@@ -182,9 +171,9 @@ public class ConversationItem extends LinearLayout {
|
||||
setEvents(messageRecord);
|
||||
setMinimumWidth();
|
||||
|
||||
if (messageRecord instanceof NotificationMmsMessageRecord) {
|
||||
if (messageRecord.isMmsNotification()) {
|
||||
setNotificationMmsAttributes((NotificationMmsMessageRecord)messageRecord);
|
||||
} else if (messageRecord instanceof MediaMmsMessageRecord) {
|
||||
} else if (messageRecord.isMms()) {
|
||||
setMediaMmsAttributes((MediaMmsMessageRecord)messageRecord);
|
||||
}
|
||||
}
|
||||
@@ -365,9 +354,13 @@ public class ConversationItem extends LinearLayout {
|
||||
for (Slide slide : result.getSlides()) {
|
||||
if (slide.hasImage()) {
|
||||
slide.setThumbnailOn(mmsThumbnail);
|
||||
// mmsThumbnail.setImageBitmap(slide.getThumbnail());
|
||||
mmsThumbnail.setOnClickListener(new ThumbnailClickListener(slide));
|
||||
mmsThumbnail.setOnLongClickListener(new ThumbnailSaveListener(slide));
|
||||
mmsThumbnail.setOnLongClickListener(new OnLongClickListener() {
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
mmsThumbnail.setVisibility(View.VISIBLE);
|
||||
return;
|
||||
}
|
||||
@@ -439,127 +432,6 @@ public class ConversationItem extends LinearLayout {
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
private class ThumbnailSaveListener extends Handler implements View.OnLongClickListener, Runnable, MediaScannerConnection.MediaScannerConnectionClient {
|
||||
private static final int SUCCESS = 0;
|
||||
private static final int FAILURE = 1;
|
||||
private static final int WRITE_ACCESS_FAILURE = 2;
|
||||
|
||||
private final Slide slide;
|
||||
private ProgressDialog progressDialog;
|
||||
private MediaScannerConnection mediaScannerConnection;
|
||||
private File mediaFile;
|
||||
|
||||
public ThumbnailSaveListener(Slide slide) {
|
||||
this.slide = slide;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
if (!Environment.getExternalStorageDirectory().canWrite()) {
|
||||
this.obtainMessage(WRITE_ACCESS_FAILURE).sendToTarget();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
mediaFile = constructOutputFile();
|
||||
InputStream inputStream = slide.getPartDataInputStream();
|
||||
OutputStream outputStream = new FileOutputStream(mediaFile);
|
||||
|
||||
byte[] buffer = new byte[4096];
|
||||
int read;
|
||||
|
||||
while ((read = inputStream.read(buffer)) != -1) {
|
||||
outputStream.write(buffer, 0, read);
|
||||
}
|
||||
|
||||
outputStream.close();
|
||||
inputStream.close();
|
||||
|
||||
mediaScannerConnection = new MediaScannerConnection(context, this);
|
||||
mediaScannerConnection.connect();
|
||||
} catch (IOException ioe) {
|
||||
Log.w(TAG, ioe);
|
||||
this.obtainMessage(FAILURE).sendToTarget();
|
||||
}
|
||||
}
|
||||
|
||||
private File constructOutputFile() throws IOException {
|
||||
File sdCard = Environment.getExternalStorageDirectory();
|
||||
File outputDirectory;
|
||||
|
||||
if (slide.hasVideo())
|
||||
outputDirectory = new File(sdCard.getAbsoluteFile() + File.separator + "Movies");
|
||||
else if (slide.hasAudio())
|
||||
outputDirectory = new File(sdCard.getAbsolutePath() + File.separator + "Music");
|
||||
else
|
||||
outputDirectory = new File(sdCard.getAbsolutePath() + File.separator + "Pictures");
|
||||
outputDirectory.mkdirs();
|
||||
|
||||
MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
|
||||
String extension = mimeTypeMap.getExtensionFromMimeType(slide.getContentType());
|
||||
if (extension == null)
|
||||
extension = "attach";
|
||||
|
||||
return File.createTempFile("textsecure", "." + extension, outputDirectory);
|
||||
}
|
||||
|
||||
private void saveToSdCard() {
|
||||
progressDialog = new ProgressDialog(context);
|
||||
progressDialog.setTitle(context.getString(R.string.ConversationItem_saving_attachment));
|
||||
progressDialog.setMessage(context.getString(R.string.ConversationItem_saving_attachment_to_sd_card));
|
||||
progressDialog.setCancelable(false);
|
||||
progressDialog.setIndeterminate(true);
|
||||
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
|
||||
progressDialog.show();
|
||||
new Thread(this).start();
|
||||
}
|
||||
|
||||
public boolean onLongClick(View v) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
builder.setTitle(R.string.ConversationItem_save_to_sd_card);
|
||||
builder.setIcon(Dialogs.resolveIcon(context, R.attr.dialog_alert_icon));
|
||||
builder.setCancelable(true);
|
||||
builder.setMessage(R.string.ConversationItem_this_media_has_been_stored_in_an_encrypted_database_warning);
|
||||
builder.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
saveToSdCard();
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton(R.string.no, null);
|
||||
builder.show();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message message) {
|
||||
switch (message.what) {
|
||||
case FAILURE:
|
||||
Toast.makeText(context, R.string.ConversationItem_error_while_saving_attachment_to_sd_card,
|
||||
Toast.LENGTH_LONG).show();
|
||||
break;
|
||||
case SUCCESS:
|
||||
Toast.makeText(context, R.string.ConversationItem_success_exclamation,
|
||||
Toast.LENGTH_LONG).show();
|
||||
break;
|
||||
case WRITE_ACCESS_FAILURE:
|
||||
Toast.makeText(context, R.string.ConversationItem_unable_to_write_to_sd_card_exclamation,
|
||||
Toast.LENGTH_LONG).show();
|
||||
break;
|
||||
}
|
||||
|
||||
progressDialog.dismiss();
|
||||
}
|
||||
|
||||
public void onMediaScannerConnected() {
|
||||
mediaScannerConnection.scanFile(mediaFile.getAbsolutePath(), slide.getContentType());
|
||||
}
|
||||
|
||||
public void onScanCompleted(String path, Uri uri) {
|
||||
mediaScannerConnection.disconnect();
|
||||
this.obtainMessage(SUCCESS).sendToTarget();
|
||||
}
|
||||
}
|
||||
|
||||
private class ThumbnailClickListener implements View.OnClickListener {
|
||||
private final Slide slide;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user