diff options
Diffstat (limited to 'src/main/java/de/thedevstack/conversationsplus/ui/adapter/MessageAdapter.java')
-rw-r--r-- | src/main/java/de/thedevstack/conversationsplus/ui/adapter/MessageAdapter.java | 789 |
1 files changed, 789 insertions, 0 deletions
diff --git a/src/main/java/de/thedevstack/conversationsplus/ui/adapter/MessageAdapter.java b/src/main/java/de/thedevstack/conversationsplus/ui/adapter/MessageAdapter.java new file mode 100644 index 00000000..09db28d0 --- /dev/null +++ b/src/main/java/de/thedevstack/conversationsplus/ui/adapter/MessageAdapter.java @@ -0,0 +1,789 @@ +package de.thedevstack.conversationsplus.ui.adapter; + +import android.content.ActivityNotFoundException; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.Typeface; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.os.AsyncTask; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.Spanned; +import android.text.style.ForegroundColorSpan; +import android.text.style.RelativeSizeSpan; +import android.text.style.StyleSpan; +import android.text.util.Linkify; +import android.util.DisplayMetrics; +import android.util.Patterns; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.View.OnLongClickListener; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import java.lang.ref.WeakReference; +import java.net.URL; +import java.util.List; +import java.util.concurrent.RejectedExecutionException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import de.thedevstack.conversationsplus.ConversationsPlusPreferences; +import de.thedevstack.conversationsplus.R; +import de.thedevstack.conversationsplus.crypto.axolotl.XmppAxolotlSession; +import de.thedevstack.conversationsplus.entities.Account; +import de.thedevstack.conversationsplus.entities.Conversation; +import de.thedevstack.conversationsplus.entities.DownloadableFile; +import de.thedevstack.conversationsplus.entities.Message; +import de.thedevstack.conversationsplus.entities.Message.FileParams; +import de.thedevstack.conversationsplus.entities.Transferable; +import de.thedevstack.conversationsplus.persistance.FileBackend; +import de.thedevstack.conversationsplus.services.AvatarService; +import de.thedevstack.conversationsplus.ui.ConversationActivity; +import de.thedevstack.conversationsplus.utils.CryptoHelper; +import de.thedevstack.conversationsplus.utils.GeoHelper; +import de.thedevstack.conversationsplus.utils.UIHelper; + +public class MessageAdapter extends ArrayAdapter<Message> { + + private static final int SENT = 0; + private static final int RECEIVED = 1; + private static final int STATUS = 2; + private static final int NULL = 3; + private static final Pattern XMPP_PATTERN = Pattern + .compile("xmpp\\:(?:(?:[" + + Patterns.GOOD_IRI_CHAR + + "\\;\\/\\?\\@\\&\\=\\#\\~\\-\\.\\+\\!\\*\\'\\(\\)\\,\\_])" + + "|(?:\\%[a-fA-F0-9]{2}))+"); + + private ConversationActivity activity; + + private DisplayMetrics metrics; + + private OnContactPictureClicked mOnContactPictureClickedListener; + private OnContactPictureLongClicked mOnContactPictureLongClickedListener; + + private OnLongClickListener openContextMenu = new OnLongClickListener() { + + @Override + public boolean onLongClick(View v) { + v.showContextMenu(); + return true; + } + }; + + public MessageAdapter(ConversationActivity activity, List<Message> messages) { + super(activity, 0, messages); + this.activity = activity; + metrics = getContext().getResources().getDisplayMetrics(); + } + + public void setOnContactPictureClicked(OnContactPictureClicked listener) { + this.mOnContactPictureClickedListener = listener; + } + + public void setOnContactPictureLongClicked( + OnContactPictureLongClicked listener) { + this.mOnContactPictureLongClickedListener = listener; + } + + @Override + public int getViewTypeCount() { + return 3; + } + + public int getItemViewType(Message message) { + if (message.getType() == Message.TYPE_STATUS) { + return STATUS; + } else if (message.getStatus() <= Message.STATUS_RECEIVED) { + return RECEIVED; + } + + return SENT; + } + + @Override + public int getItemViewType(int position) { + return this.getItemViewType(getItem(position)); + } + + private int getMessageTextColor(boolean onDark, boolean primary) { + if (onDark) { + return activity.getResources().getColor(primary ? R.color.white : R.color.white70); + } else { + return activity.getResources().getColor(primary ? R.color.black87 : R.color.black54); + } + } + + private void displayStatus(ViewHolder viewHolder, Message message, int type, boolean darkBackground) { + String filesize = null; + String info = null; + boolean error = false; + if (viewHolder.indicatorReceived != null) { + viewHolder.indicatorReceived.setVisibility(View.GONE); + } + + boolean multiReceived = message.getConversation().getMode() == Conversation.MODE_MULTI + && message.getStatus() <= Message.STATUS_RECEIVED; + if (message.getType() == Message.TYPE_IMAGE || message.getType() == Message.TYPE_FILE || message.getTransferable() != null) { + FileParams params = message.getFileParams(); + if (params.size > (1.5 * 1024 * 1024)) { + filesize = params.size / (1024 * 1024)+ " MiB"; + } else if (params.size > 0) { + filesize = params.size / 1024 + " KiB"; + } + if (message.getTransferable() != null && message.getTransferable().getStatus() == Transferable.STATUS_FAILED) { + error = true; + } + } + switch (message.getStatus()) { + case Message.STATUS_WAITING: + info = getContext().getString(R.string.waiting); + break; + case Message.STATUS_UNSEND: + Transferable d = message.getTransferable(); + if (d!=null) { + info = getContext().getString(R.string.sending_file,d.getProgress()); + } else { + info = getContext().getString(R.string.sending); + } + break; + case Message.STATUS_OFFERED: + info = getContext().getString(R.string.offering); + break; + case Message.STATUS_SEND_RECEIVED: + if (ConversationsPlusPreferences.indicateReceived()) { + viewHolder.indicatorReceived.setVisibility(View.VISIBLE); + } + break; + case Message.STATUS_SEND_DISPLAYED: + if (ConversationsPlusPreferences.indicateReceived()) { + viewHolder.indicatorReceived.setVisibility(View.VISIBLE); + } + break; + case Message.STATUS_SEND_FAILED: + info = getContext().getString(R.string.send_failed); + error = true; + break; + default: + if (multiReceived) { + info = UIHelper.getMessageDisplayName(message); + } + break; + } + if (error && type == SENT) { + viewHolder.time.setTextColor(activity.getWarningTextColor()); + } else { + viewHolder.time.setTextColor(this.getMessageTextColor(darkBackground,false)); + } + if (message.getEncryption() == Message.ENCRYPTION_NONE) { + viewHolder.indicator.setVisibility(View.GONE); + } else { + viewHolder.indicator.setImageResource(darkBackground ? R.drawable.ic_lock_white_18dp : R.drawable.ic_lock_black_18dp); + viewHolder.indicator.setVisibility(View.VISIBLE); + if (message.getEncryption() == Message.ENCRYPTION_AXOLOTL) { + XmppAxolotlSession.Trust trust = message.getConversation() + .getAccount().getAxolotlService().getFingerprintTrust( + message.getAxolotlFingerprint()); + + if(trust == null || (!trust.trusted() && !trust.trustedInactive())) { + viewHolder.indicator.setColorFilter(activity.getWarningTextColor()); + viewHolder.indicator.setAlpha(1.0f); + } else { + viewHolder.indicator.clearColorFilter(); + if (darkBackground) { + viewHolder.indicator.setAlpha(0.7f); + } else { + viewHolder.indicator.setAlpha(0.57f); + } + } + } else { + viewHolder.indicator.clearColorFilter(); + if (darkBackground) { + viewHolder.indicator.setAlpha(0.7f); + } else { + viewHolder.indicator.setAlpha(0.57f); + } + } + } + + String formatedTime = UIHelper.readableTimeDifferenceFull(getContext(), + message.getTimeSent()); + if (message.getStatus() <= Message.STATUS_RECEIVED) { + if ((filesize != null) && (info != null)) { + viewHolder.time.setText(formatedTime + " \u00B7 " + filesize +" \u00B7 " + info); + } else if ((filesize == null) && (info != null)) { + viewHolder.time.setText(formatedTime + " \u00B7 " + info); + } else if ((filesize != null) && (info == null)) { + viewHolder.time.setText(formatedTime + " \u00B7 " + filesize); + } else { + viewHolder.time.setText(formatedTime); + } + } else { + if ((filesize != null) && (info != null)) { + viewHolder.time.setText(filesize + " \u00B7 " + info); + } else if ((filesize == null) && (info != null)) { + if (error) { + viewHolder.time.setText(info + " \u00B7 " + formatedTime); + } else { + viewHolder.time.setText(info); + } + } else if ((filesize != null) && (info == null)) { + viewHolder.time.setText(filesize + " \u00B7 " + formatedTime); + } else { + viewHolder.time.setText(formatedTime); + } + } + } + + private void displayInfoMessage(ViewHolder viewHolder, String text, boolean darkBackground) { + if (viewHolder.download_button != null) { + viewHolder.download_button.setVisibility(View.GONE); + } + viewHolder.image.setVisibility(View.GONE); + viewHolder.messageBody.setVisibility(View.VISIBLE); + viewHolder.messageBody.setText(text); + viewHolder.messageBody.setTextColor(getMessageTextColor(darkBackground, false)); + viewHolder.messageBody.setTypeface(null, Typeface.ITALIC); + viewHolder.messageBody.setTextIsSelectable(false); + } + + private void displayDecryptionFailed(ViewHolder viewHolder, boolean darkBackground) { + if (viewHolder.download_button != null) { + viewHolder.download_button.setVisibility(View.GONE); + } + viewHolder.image.setVisibility(View.GONE); + viewHolder.messageBody.setVisibility(View.VISIBLE); + viewHolder.messageBody.setText(getContext().getString( + R.string.decryption_failed)); + viewHolder.messageBody.setTextColor(getMessageTextColor(darkBackground, false)); + viewHolder.messageBody.setTypeface(null, Typeface.NORMAL); + viewHolder.messageBody.setTextIsSelectable(false); + } + + private void displayTextMessage(final ViewHolder viewHolder, final Message message, boolean darkBackground) { + if (viewHolder.download_button != null) { + viewHolder.download_button.setVisibility(View.GONE); + } + viewHolder.image.setVisibility(View.GONE); + viewHolder.messageBody.setVisibility(View.VISIBLE); + viewHolder.messageBody.setIncludeFontPadding(true); + if (message.getBody() != null) { + final String nick = UIHelper.getMessageDisplayName(message); + String body; + if (message.hasMeCommand()) { + body = message.getBodyReplacedMeCommand(nick); + } else { + body = message.getBody(); + } + final SpannableString formattedBody = new SpannableString(body); + int i = body.indexOf(Message.MERGE_SEPARATOR); + while(i >= 0) { + final int end = i + Message.MERGE_SEPARATOR.length(); + formattedBody.setSpan(new RelativeSizeSpan(0.3f),i,end,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + i = body.indexOf(Message.MERGE_SEPARATOR,end); + } + if (message.getType() != Message.TYPE_PRIVATE) { + if (message.hasMeCommand()) { + final Spannable span = new SpannableString(formattedBody); + span.setSpan(new StyleSpan(Typeface.BOLD_ITALIC), 0, nick.length(), + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + viewHolder.messageBody.setText(span); + } else { + viewHolder.messageBody.setText(formattedBody); + } + } else { + String privateMarker; + if (message.getStatus() <= Message.STATUS_RECEIVED) { + privateMarker = activity + .getString(R.string.private_message); + } else { + final String to; + if (message.getCounterpart() != null) { + to = message.getCounterpart().getResourcepart(); + } else { + to = ""; + } + privateMarker = activity.getString(R.string.private_message_to, to); + } + final Spannable span = new SpannableString(privateMarker + " " + + formattedBody); + span.setSpan(new ForegroundColorSpan(getMessageTextColor(darkBackground,false)), 0, privateMarker + .length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + span.setSpan(new StyleSpan(Typeface.BOLD), 0, + privateMarker.length(), + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + if (message.hasMeCommand()) { + span.setSpan(new StyleSpan(Typeface.BOLD_ITALIC), privateMarker.length() + 1, + privateMarker.length() + 1 + nick.length(), + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + } + viewHolder.messageBody.setText(span); + } + int patternMatchCount = 0; + int oldAutoLinkMask = viewHolder.messageBody.getAutoLinkMask(); + + // first check if we have a match on XMPP_PATTERN so we do not have to check for EMAIL_ADDRESSES + patternMatchCount += countMatches(XMPP_PATTERN, body); + if ((Linkify.EMAIL_ADDRESSES & oldAutoLinkMask) != 0 && patternMatchCount > 0) { + oldAutoLinkMask -= Linkify.EMAIL_ADDRESSES; + } + + // count matches for all patterns + if ((Linkify.WEB_URLS & oldAutoLinkMask) != 0) { + patternMatchCount += countMatches(Patterns.WEB_URL, body); + } + if ((Linkify.EMAIL_ADDRESSES & oldAutoLinkMask) != 0) { + patternMatchCount += countMatches(Patterns.EMAIL_ADDRESS, body); + } + if ((Linkify.PHONE_NUMBERS & oldAutoLinkMask) != 0) { + patternMatchCount += countMatches(Patterns.PHONE, body); + } + + viewHolder.messageBody.setTextIsSelectable(patternMatchCount <= 1); + viewHolder.messageBody.setAutoLinkMask(0); + Linkify.addLinks(viewHolder.messageBody, XMPP_PATTERN, "xmpp"); + viewHolder.messageBody.setAutoLinkMask(oldAutoLinkMask); + } else { + viewHolder.messageBody.setText(""); + viewHolder.messageBody.setTextIsSelectable(false); + } + viewHolder.messageBody.setTextColor(this.getMessageTextColor(darkBackground, true)); + viewHolder.messageBody.setTypeface(null, Typeface.NORMAL); + viewHolder.messageBody.setOnLongClickListener(openContextMenu); + } + + /** + * Counts the number of occurrences of the pattern in body. + * @param pattern the pattern to match + * @param body the body to find the pattern + * @return the number of occurrences + */ + private int countMatches(Pattern pattern, String body) { + Matcher matcher = pattern.matcher(body); + int count = 0; + while (matcher.find()) { + count++; + } + return count; + } + + private void displayDownloadableMessage(ViewHolder viewHolder, + final Message message, String text) { + viewHolder.image.setVisibility(View.GONE); + viewHolder.messageBody.setVisibility(View.GONE); + viewHolder.download_button.setVisibility(View.VISIBLE); + viewHolder.download_button.setText(text); + viewHolder.download_button.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + activity.startDownloadable(message); + } + }); + viewHolder.download_button.setOnLongClickListener(openContextMenu); + } + + private void displayOpenableMessage(ViewHolder viewHolder,final Message message) { + viewHolder.image.setVisibility(View.GONE); + viewHolder.messageBody.setVisibility(View.GONE); + viewHolder.download_button.setVisibility(View.VISIBLE); + viewHolder.download_button.setText(activity.getString(R.string.open_x_file, UIHelper.getFileDescriptionString(activity, message))); + viewHolder.download_button.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + openDownloadable(message); + } + }); + viewHolder.download_button.setOnLongClickListener(openContextMenu); + } + + private void displayLocationMessage(ViewHolder viewHolder, final Message message) { + viewHolder.image.setVisibility(View.GONE); + viewHolder.messageBody.setVisibility(View.GONE); + viewHolder.download_button.setVisibility(View.VISIBLE); + viewHolder.download_button.setText(R.string.show_location); + viewHolder.download_button.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + showLocation(message); + } + }); + viewHolder.download_button.setOnLongClickListener(openContextMenu); + } + + private void displayImageMessage(ViewHolder viewHolder, + final Message message) { + if (viewHolder.download_button != null) { + viewHolder.download_button.setVisibility(View.GONE); + } + viewHolder.messageBody.setVisibility(View.GONE); + viewHolder.image.setVisibility(View.VISIBLE); + FileParams params = message.getFileParams(); + //TODO: Check what value add the following lines have (compared with setting height/width in XmppActivity.loadBitmap from thumbnail after thumbnail is created) + /*double target = metrics.density * 288; + int scalledW; + int scalledH; + if (params.width <= params.height) { + scalledW = (int) (params.width / ((double) params.height / target)); + scalledH = (int) target; + } else { + scalledW = (int) target; + scalledH = (int) (params.height / ((double) params.width / target)); + } + LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(scalledW, scalledH); + layoutParams.setMargins(0, (int) (metrics.density * 4), 0, (int) (metrics.density * 4)); + viewHolder.image.setLayoutParams(layoutParams);*/ + //TODO Why should this be calculated by hand??? + activity.loadBitmap(message, viewHolder.image, true); + viewHolder.image.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + openDownloadable(message); + } + }); + viewHolder.image.setOnLongClickListener(openContextMenu); + } + + @Override + public View getView(int position, View view, ViewGroup parent) { + final Message message = getItem(position); + final boolean isInValidSession = message.isValidInSession(); + final Conversation conversation = message.getConversation(); + final Account account = conversation.getAccount(); + final int type = getItemViewType(position); + ViewHolder viewHolder; + if (view == null) { + viewHolder = new ViewHolder(); + switch (type) { + case SENT: + view = activity.getLayoutInflater().inflate( + R.layout.message_sent, parent, false); + viewHolder.message_box = (LinearLayout) view + .findViewById(R.id.message_box); + viewHolder.contact_picture = (ImageView) view + .findViewById(R.id.message_photo); + viewHolder.download_button = (Button) view + .findViewById(R.id.download_button); + viewHolder.indicator = (ImageView) view + .findViewById(R.id.security_indicator); + viewHolder.image = (ImageView) view + .findViewById(R.id.message_image); + viewHolder.messageBody = (TextView) view + .findViewById(R.id.message_body); + viewHolder.time = (TextView) view + .findViewById(R.id.message_time); + viewHolder.indicatorReceived = (ImageView) view + .findViewById(R.id.indicator_received); + break; + case RECEIVED: + view = activity.getLayoutInflater().inflate( + R.layout.message_received, parent, false); + viewHolder.message_box = (LinearLayout) view + .findViewById(R.id.message_box); + viewHolder.contact_picture = (ImageView) view + .findViewById(R.id.message_photo); + viewHolder.download_button = (Button) view + .findViewById(R.id.download_button); + viewHolder.indicator = (ImageView) view + .findViewById(R.id.security_indicator); + viewHolder.image = (ImageView) view + .findViewById(R.id.message_image); + viewHolder.messageBody = (TextView) view + .findViewById(R.id.message_body); + viewHolder.time = (TextView) view + .findViewById(R.id.message_time); + viewHolder.indicatorReceived = (ImageView) view + .findViewById(R.id.indicator_received); + viewHolder.encryption = (TextView) view.findViewById(R.id.message_encryption); + break; + case STATUS: + view = activity.getLayoutInflater().inflate(R.layout.message_status, parent, false); + viewHolder.contact_picture = (ImageView) view.findViewById(R.id.message_photo); + viewHolder.status_message = (TextView) view.findViewById(R.id.status_message); + break; + default: + viewHolder = null; + break; + } + view.setTag(viewHolder); + } else { + viewHolder = (ViewHolder) view.getTag(); + if (viewHolder == null) { + return view; + } + } + + boolean darkBackground = (type == RECEIVED && !isInValidSession); + + if (type == STATUS) { + viewHolder.status_message.setVisibility(View.VISIBLE); + viewHolder.contact_picture.setVisibility(View.VISIBLE); + if (conversation.getMode() == Conversation.MODE_SINGLE) { + viewHolder.contact_picture.setImageBitmap(AvatarService.getInstance().get(conversation.getContact(), + activity.getPixel(32))); + viewHolder.contact_picture.setAlpha(0.5f); + } + viewHolder.status_message.setText(message.getBody()); + return view; + } else { + loadAvatar(message, viewHolder.contact_picture); + } + + viewHolder.contact_picture + .setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + if (MessageAdapter.this.mOnContactPictureClickedListener != null) { + MessageAdapter.this.mOnContactPictureClickedListener + .onContactPictureClicked(message); + } + + } + }); + viewHolder.contact_picture + .setOnLongClickListener(new OnLongClickListener() { + + @Override + public boolean onLongClick(View v) { + if (MessageAdapter.this.mOnContactPictureLongClickedListener != null) { + MessageAdapter.this.mOnContactPictureLongClickedListener + .onContactPictureLongClicked(message); + return true; + } else { + return false; + } + } + }); + + final Transferable transferable = message.getTransferable(); + if (transferable != null && transferable.getStatus() != Transferable.STATUS_UPLOADING) { + if (transferable.getStatus() == Transferable.STATUS_OFFER) { + displayDownloadableMessage(viewHolder,message,activity.getString(R.string.download_x_file, UIHelper.getFileDescriptionString(activity, message))); + } else if (transferable.getStatus() == Transferable.STATUS_OFFER_CHECK_FILESIZE) { + displayDownloadableMessage(viewHolder, message, activity.getString(R.string.check_x_filesize, UIHelper.getFileDescriptionString(activity, message))); + } else { + displayInfoMessage(viewHolder, UIHelper.getMessagePreview(activity, message).first,darkBackground); + } + } else if (message.getType() == Message.TYPE_IMAGE && message.getEncryption() != Message.ENCRYPTION_PGP && message.getEncryption() != Message.ENCRYPTION_DECRYPTION_FAILED) { + displayImageMessage(viewHolder, message); + } else if (message.getType() == Message.TYPE_FILE && message.getEncryption() != Message.ENCRYPTION_PGP && message.getEncryption() != Message.ENCRYPTION_DECRYPTION_FAILED) { + if (message.getFileParams().width > 0) { + displayImageMessage(viewHolder,message); + } else { + displayOpenableMessage(viewHolder, message); + } + } else if (message.getEncryption() == Message.ENCRYPTION_PGP) { + if (activity.hasPgp()) { + if (account.getPgpDecryptionService().isRunning()) { + displayInfoMessage(viewHolder, activity.getString(R.string.message_decrypting), darkBackground); + } else { + displayInfoMessage(viewHolder, activity.getString(R.string.pgp_message), darkBackground); + } + } else { + displayInfoMessage(viewHolder,activity.getString(R.string.install_openkeychain),darkBackground); + if (viewHolder != null) { + viewHolder.message_box + .setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + activity.showInstallPgpDialog(); + } + }); + } + } + } else if (message.getEncryption() == Message.ENCRYPTION_DECRYPTION_FAILED) { + displayDecryptionFailed(viewHolder,darkBackground); + } else { + if (GeoHelper.isGeoUri(message.getBody())) { + displayLocationMessage(viewHolder,message); + } else if (message.treatAsDownloadable() == Message.Decision.MUST) { + try { + URL url = new URL(message.getBody()); + displayDownloadableMessage(viewHolder, + message, + activity.getString(R.string.check_x_filesize_on_host, + UIHelper.getFileDescriptionString(activity, message), + url.getHost())); + } catch (Exception e) { + displayDownloadableMessage(viewHolder, + message, + activity.getString(R.string.check_x_filesize, + UIHelper.getFileDescriptionString(activity, message))); + } + } else { + displayTextMessage(viewHolder, message, darkBackground); + } + } + + if (type == RECEIVED) { + if(isInValidSession) { + viewHolder.encryption.setVisibility(View.GONE); + } else { + viewHolder.message_box.setBackgroundResource(R.drawable.message_bubble_received_warning); + viewHolder.encryption.setVisibility(View.VISIBLE); + viewHolder.encryption.setText(CryptoHelper.encryptionTypeToText(message.getEncryption())); + } + } + + displayStatus(viewHolder, message, type, darkBackground); + + return view; + } + + public void openDownloadable(Message message) { + DownloadableFile file = FileBackend.getFile(message); + if (!file.exists()) { + Toast.makeText(activity,R.string.file_deleted,Toast.LENGTH_SHORT).show(); + return; + } + Intent openIntent = new Intent(Intent.ACTION_VIEW); + String mime = file.getMimeType(); + if (mime == null) { + mime = "*/*"; + } + openIntent.setDataAndType(Uri.fromFile(file), mime); + PackageManager manager = activity.getPackageManager(); + List<ResolveInfo> infos = manager.queryIntentActivities(openIntent, 0); + if (infos.size() == 0) { + openIntent.setDataAndType(Uri.fromFile(file),"*/*"); + } + try { + getContext().startActivity(openIntent); + return; + } catch (ActivityNotFoundException e) { + //ignored + } + Toast.makeText(activity,R.string.no_application_found_to_open_file,Toast.LENGTH_SHORT).show(); + } + + public void showLocation(Message message) { + for(Intent intent : GeoHelper.createGeoIntentsFromMessage(message)) { + if (intent.resolveActivity(getContext().getPackageManager()) != null) { + getContext().startActivity(intent); + return; + } + } + Toast.makeText(activity,R.string.no_application_found_to_display_location,Toast.LENGTH_SHORT).show(); + } + + public interface OnContactPictureClicked { + void onContactPictureClicked(Message message); + } + + public interface OnContactPictureLongClicked { + void onContactPictureLongClicked(Message message); + } + + private static class ViewHolder { + + protected LinearLayout message_box; + protected Button download_button; + protected ImageView image; + protected ImageView indicator; + protected ImageView indicatorReceived; + protected TextView time; + protected TextView messageBody; + protected ImageView contact_picture; + protected TextView status_message; + protected TextView encryption; + } + + class BitmapWorkerTask extends AsyncTask<Message, Void, Bitmap> { + private final WeakReference<ImageView> imageViewReference; + private Message message = null; + + public BitmapWorkerTask(ImageView imageView) { + imageViewReference = new WeakReference<>(imageView); + } + + @Override + protected Bitmap doInBackground(Message... params) { + return AvatarService.getInstance().get(params[0], activity.getPixel(48), isCancelled()); + } + + @Override + protected void onPostExecute(Bitmap bitmap) { + if (bitmap != null) { + final ImageView imageView = imageViewReference.get(); + if (imageView != null) { + imageView.setImageBitmap(bitmap); + imageView.setBackgroundColor(0x00000000); + } + } + } + } + + public void loadAvatar(Message message, ImageView imageView) { + if (cancelPotentialWork(message, imageView)) { + final Bitmap bm = AvatarService.getInstance().get(message, activity.getPixel(48), true); + if (bm != null) { + imageView.setImageBitmap(bm); + imageView.setBackgroundColor(0x00000000); + } else { + imageView.setBackgroundColor(UIHelper.getColorForName(UIHelper.getMessageDisplayName(message))); + imageView.setImageDrawable(null); + final BitmapWorkerTask task = new BitmapWorkerTask(imageView); + final AsyncDrawable asyncDrawable = new AsyncDrawable(activity.getResources(), null, task); + imageView.setImageDrawable(asyncDrawable); + try { + task.execute(message); + } catch (final RejectedExecutionException ignored) { + } + } + } + } + + public static boolean cancelPotentialWork(Message message, ImageView imageView) { + final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView); + + if (bitmapWorkerTask != null) { + final Message oldMessage = bitmapWorkerTask.message; + if (oldMessage == null || message != oldMessage) { + bitmapWorkerTask.cancel(true); + } else { + return false; + } + } + return true; + } + + private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) { + if (imageView != null) { + final Drawable drawable = imageView.getDrawable(); + if (drawable instanceof AsyncDrawable) { + final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable; + return asyncDrawable.getBitmapWorkerTask(); + } + } + return null; + } + + static class AsyncDrawable extends BitmapDrawable { + private final WeakReference<BitmapWorkerTask> bitmapWorkerTaskReference; + + public AsyncDrawable(Resources res, Bitmap bitmap, BitmapWorkerTask bitmapWorkerTask) { + super(res, bitmap); + bitmapWorkerTaskReference = new WeakReference<>(bitmapWorkerTask); + } + + public BitmapWorkerTask getBitmapWorkerTask() { + return bitmapWorkerTaskReference.get(); + } + } +} |