refactored avatar workers into single class

This commit is contained in:
Daniel Gultsch 2019-01-25 10:07:02 +01:00
parent 18807305c1
commit 7f170276a9
17 changed files with 203 additions and 402 deletions

View File

@ -22,12 +22,14 @@ import eu.siacs.conversations.R;
import eu.siacs.conversations.crypto.PgpDecryptionService; import eu.siacs.conversations.crypto.PgpDecryptionService;
import eu.siacs.conversations.crypto.axolotl.AxolotlService; import eu.siacs.conversations.crypto.axolotl.AxolotlService;
import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession; import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession;
import eu.siacs.conversations.services.AvatarService;
import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.utils.UIHelper;
import eu.siacs.conversations.utils.XmppUri; import eu.siacs.conversations.utils.XmppUri;
import eu.siacs.conversations.xmpp.XmppConnection; import eu.siacs.conversations.xmpp.XmppConnection;
import rocks.xmpp.addr.Jid; import rocks.xmpp.addr.Jid;
public class Account extends AbstractEntity { public class Account extends AbstractEntity implements AvatarService.Avatarable {
public static final String TABLENAME = "accounts"; public static final String TABLENAME = "accounts";
@ -579,6 +581,11 @@ public class Account extends AbstractEntity {
return this.getStatus() == State.ONLINE && this.getXmppConnection() != null; return this.getStatus() == State.ONLINE && this.getXmppConnection() != null;
} }
@Override
public int getAvatarBackgroundColor() {
return UIHelper.getColorForName(jid.asBareJid().toString());
}
public enum State { public enum State {
DISABLED(false, false), DISABLED(false, false),
OFFLINE(false), OFFLINE(false),

View File

@ -181,4 +181,9 @@ public class Bookmark extends Element implements ListItem {
} }
return StringUtils.changed(before, name); return StringUtils.changed(before, name);
} }
@Override
public int getAvatarBackgroundColor() {
return UIHelper.getColorForName(jid != null ? jid.asBareJid().toString() : getDisplayName());
}
} }

View File

@ -537,6 +537,11 @@ public class Contact implements ListItem, Blockable {
} }
} }
@Override
public int getAvatarBackgroundColor() {
return UIHelper.getColorForName(jid != null ? jid.asBareJid().toString() : getDisplayName());
}
public final class Options { public final class Options {
public static final int TO = 0; public static final int TO = 0;
public static final int FROM = 1; public static final int FROM = 1;

View File

@ -2,6 +2,7 @@ package eu.siacs.conversations.entities;
import android.content.ContentValues; import android.content.ContentValues;
import android.database.Cursor; import android.database.Cursor;
import android.graphics.Color;
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.text.TextUtils;
@ -24,8 +25,10 @@ import eu.siacs.conversations.crypto.OmemoSetting;
import eu.siacs.conversations.crypto.PgpDecryptionService; import eu.siacs.conversations.crypto.PgpDecryptionService;
import eu.siacs.conversations.crypto.axolotl.AxolotlService; import eu.siacs.conversations.crypto.axolotl.AxolotlService;
import eu.siacs.conversations.persistance.DatabaseBackend; import eu.siacs.conversations.persistance.DatabaseBackend;
import eu.siacs.conversations.services.AvatarService;
import eu.siacs.conversations.services.QuickConversationsService; import eu.siacs.conversations.services.QuickConversationsService;
import eu.siacs.conversations.utils.JidHelper; import eu.siacs.conversations.utils.JidHelper;
import eu.siacs.conversations.utils.UIHelper;
import eu.siacs.conversations.xmpp.InvalidJid; import eu.siacs.conversations.xmpp.InvalidJid;
import eu.siacs.conversations.xmpp.chatstate.ChatState; import eu.siacs.conversations.xmpp.chatstate.ChatState;
import eu.siacs.conversations.xmpp.mam.MamReference; import eu.siacs.conversations.xmpp.mam.MamReference;
@ -34,7 +37,7 @@ import rocks.xmpp.addr.Jid;
import static eu.siacs.conversations.entities.Bookmark.printableValue; import static eu.siacs.conversations.entities.Bookmark.printableValue;
public class Conversation extends AbstractEntity implements Blockable, Comparable<Conversation>, Conversational { public class Conversation extends AbstractEntity implements Blockable, Comparable<Conversation>, Conversational, AvatarService.Avatarable {
public static final String TABLENAME = "conversations"; public static final String TABLENAME = "conversations";
public static final int STATUS_AVAILABLE = 0; public static final int STATUS_AVAILABLE = 0;
@ -991,6 +994,11 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
return 0; return 0;
} }
@Override
public int getAvatarBackgroundColor() {
return UIHelper.getColorForName(getName().toString());
}
public interface OnMessageFound { public interface OnMessageFound {
void onMessageFound(final Message message); void onMessageFound(final Message message);
} }

View File

@ -4,10 +4,11 @@ import android.content.Context;
import java.util.List; import java.util.List;
import eu.siacs.conversations.services.AvatarService;
import rocks.xmpp.addr.Jid; import rocks.xmpp.addr.Jid;
public interface ListItem extends Comparable<ListItem> { public interface ListItem extends Comparable<ListItem>, AvatarService.Avatarable {
String getDisplayName(); String getDisplayName();
Jid getJid(); Jid getJid();

View File

@ -2,6 +2,8 @@ package eu.siacs.conversations.entities;
import android.content.ContentValues; import android.content.ContentValues;
import android.database.Cursor; import android.database.Cursor;
import android.graphics.Color;
import android.support.annotation.ColorInt;
import android.text.SpannableStringBuilder; import android.text.SpannableStringBuilder;
import android.util.Log; import android.util.Log;
@ -19,6 +21,7 @@ import java.util.Set;
import eu.siacs.conversations.Config; import eu.siacs.conversations.Config;
import eu.siacs.conversations.crypto.axolotl.FingerprintStatus; import eu.siacs.conversations.crypto.axolotl.FingerprintStatus;
import eu.siacs.conversations.services.AvatarService;
import eu.siacs.conversations.utils.CryptoHelper; import eu.siacs.conversations.utils.CryptoHelper;
import eu.siacs.conversations.utils.Emoticons; import eu.siacs.conversations.utils.Emoticons;
import eu.siacs.conversations.utils.GeoHelper; import eu.siacs.conversations.utils.GeoHelper;
@ -27,7 +30,7 @@ import eu.siacs.conversations.utils.MimeUtils;
import eu.siacs.conversations.utils.UIHelper; import eu.siacs.conversations.utils.UIHelper;
import rocks.xmpp.addr.Jid; import rocks.xmpp.addr.Jid;
public class Message extends AbstractEntity { public class Message extends AbstractEntity implements AvatarService.Avatarable {
public static final String TABLENAME = "messages"; public static final String TABLENAME = "messages";
@ -627,6 +630,15 @@ public class Message extends AbstractEntity {
return this.counterparts; return this.counterparts;
} }
@Override
public int getAvatarBackgroundColor() {
if (type == Message.TYPE_STATUS && getCounterparts() != null && getCounterparts().size() > 1) {
return Color.TRANSPARENT;
} else {
return UIHelper.getColorForName(UIHelper.getMessageDisplayName(this));
}
}
public static class MergeSeparator { public static class MergeSeparator {
} }

View File

@ -13,6 +13,7 @@ import android.graphics.Typeface;
import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.net.Uri; import android.net.Uri;
import android.support.annotation.ColorInt;
import android.support.annotation.DrawableRes; import android.support.annotation.DrawableRes;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v4.content.res.ResourcesCompat; import android.support.v4.content.res.ResourcesCompat;
@ -41,6 +42,7 @@ import eu.siacs.conversations.entities.MucOptions;
import eu.siacs.conversations.utils.UIHelper; import eu.siacs.conversations.utils.UIHelper;
import eu.siacs.conversations.xmpp.OnAdvancedStreamFeaturesLoaded; import eu.siacs.conversations.xmpp.OnAdvancedStreamFeaturesLoaded;
import eu.siacs.conversations.xmpp.XmppConnection; import eu.siacs.conversations.xmpp.XmppConnection;
import eu.siacs.conversations.xmpp.pep.Avatar;
import rocks.xmpp.addr.Jid; import rocks.xmpp.addr.Jid;
public class AvatarService implements OnAdvancedStreamFeaturesLoaded { public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
@ -69,6 +71,20 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
return (int) (SYSTEM_UI_AVATAR_SIZE * context.getResources().getDisplayMetrics().density); return (int) (SYSTEM_UI_AVATAR_SIZE * context.getResources().getDisplayMetrics().density);
} }
public Bitmap get(final Avatarable avatarable, final int size, final boolean cachedOnly) {
if (avatarable instanceof Account) {
return get((Account) avatarable,size,cachedOnly);
} else if (avatarable instanceof Conversation) {
return get((Conversation) avatarable, size, cachedOnly);
} else if (avatarable instanceof Message) {
return get((Message) avatarable, size, cachedOnly);
} else if (avatarable instanceof ListItem) {
return get((ListItem) avatarable, size, cachedOnly);
}
throw new AssertionError("AvatarService does not know how to generate avatar from "+avatarable.getClass().getName());
}
private Bitmap get(final Contact contact, final int size, boolean cachedOnly) { private Bitmap get(final Contact contact, final int size, boolean cachedOnly) {
if (contact.isSelf()) { if (contact.isSelf()) {
return get(contact.getAccount(), size, cachedOnly); return get(contact.getAccount(), size, cachedOnly);
@ -646,4 +662,8 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
private static String emptyOnNull(@Nullable Jid value) { private static String emptyOnNull(@Nullable Jid value) {
return value == null ? "" : value.toString(); return value == null ? "" : value.toString();
} }
public interface Avatarable {
@ColorInt int getAvatarBackgroundColor();
}
} }

View File

@ -55,6 +55,7 @@ import eu.siacs.conversations.ui.adapter.MediaAdapter;
import eu.siacs.conversations.ui.interfaces.OnMediaLoaded; import eu.siacs.conversations.ui.interfaces.OnMediaLoaded;
import eu.siacs.conversations.ui.service.EmojiService; import eu.siacs.conversations.ui.service.EmojiService;
import eu.siacs.conversations.ui.util.Attachment; import eu.siacs.conversations.ui.util.Attachment;
import eu.siacs.conversations.ui.util.AvatarWorkerTask;
import eu.siacs.conversations.ui.util.GridManager; import eu.siacs.conversations.ui.util.GridManager;
import eu.siacs.conversations.ui.util.MenuDoubleTabUtil; import eu.siacs.conversations.ui.util.MenuDoubleTabUtil;
import eu.siacs.conversations.ui.util.MucDetailsContextMenuHelper; import eu.siacs.conversations.ui.util.MucDetailsContextMenuHelper;
@ -544,7 +545,7 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
this.binding.editMucNameButton.setVisibility((self.getAffiliation().ranks(MucOptions.Affiliation.OWNER) || mucOptions.canChangeSubject()) ? View.VISIBLE : View.GONE); this.binding.editMucNameButton.setVisibility((self.getAffiliation().ranks(MucOptions.Affiliation.OWNER) || mucOptions.canChangeSubject()) ? View.VISIBLE : View.GONE);
this.binding.detailsAccount.setText(getString(R.string.using_account, account)); this.binding.detailsAccount.setText(getString(R.string.using_account, account));
this.binding.jid.setText(mConversation.getJid().asBareJid().toEscapedString()); this.binding.jid.setText(mConversation.getJid().asBareJid().toEscapedString());
this.binding.yourPhoto.setImageBitmap(avatarService().get(mConversation,(int) getResources().getDimension(R.dimen.avatar_on_details_screen_size))); AvatarWorkerTask.loadAvatar(mConversation,binding.yourPhoto,R.dimen.avatar_on_details_screen_size);
String roomName = mucOptions.getName(); String roomName = mucOptions.getName();
String subject = mucOptions.getSubject(); String subject = mucOptions.getSubject();
final boolean hasTitle; final boolean hasTitle;

View File

@ -43,6 +43,7 @@ import eu.siacs.conversations.services.XmppConnectionService.OnRosterUpdate;
import eu.siacs.conversations.ui.adapter.MediaAdapter; import eu.siacs.conversations.ui.adapter.MediaAdapter;
import eu.siacs.conversations.ui.interfaces.OnMediaLoaded; import eu.siacs.conversations.ui.interfaces.OnMediaLoaded;
import eu.siacs.conversations.ui.util.Attachment; import eu.siacs.conversations.ui.util.Attachment;
import eu.siacs.conversations.ui.util.AvatarWorkerTask;
import eu.siacs.conversations.ui.util.GridManager; import eu.siacs.conversations.ui.util.GridManager;
import eu.siacs.conversations.ui.util.JidDialog; import eu.siacs.conversations.ui.util.JidDialog;
import eu.siacs.conversations.ui.util.MenuDoubleTabUtil; import eu.siacs.conversations.ui.util.MenuDoubleTabUtil;
@ -402,7 +403,7 @@ public class ContactDetailsActivity extends OmemoActivity implements OnAccountUp
account = contact.getAccount().getJid().asBareJid().toString(); account = contact.getAccount().getJid().asBareJid().toString();
} }
binding.detailsAccount.setText(getString(R.string.using_account, account)); binding.detailsAccount.setText(getString(R.string.using_account, account));
binding.detailsContactBadge.setImageBitmap(avatarService().get(contact, (int) getResources().getDimension(R.dimen.avatar_on_details_screen_size))); AvatarWorkerTask.loadAvatar(contact,binding.detailsContactBadge,R.dimen.avatar_on_details_screen_size);
binding.detailsContactBadge.setOnClickListener(this.onBadgeClick); binding.detailsContactBadge.setOnClickListener(this.onBadgeClick);
binding.detailsContactKeys.removeAllViews(); binding.detailsContactKeys.removeAllViews();

View File

@ -58,6 +58,7 @@ import eu.siacs.conversations.services.XmppConnectionService.OnAccountUpdate;
import eu.siacs.conversations.services.XmppConnectionService.OnCaptchaRequested; import eu.siacs.conversations.services.XmppConnectionService.OnCaptchaRequested;
import eu.siacs.conversations.ui.adapter.KnownHostsAdapter; import eu.siacs.conversations.ui.adapter.KnownHostsAdapter;
import eu.siacs.conversations.ui.adapter.PresenceTemplateAdapter; import eu.siacs.conversations.ui.adapter.PresenceTemplateAdapter;
import eu.siacs.conversations.ui.util.AvatarWorkerTask;
import eu.siacs.conversations.ui.util.MenuDoubleTabUtil; import eu.siacs.conversations.ui.util.MenuDoubleTabUtil;
import eu.siacs.conversations.ui.util.PendingItem; import eu.siacs.conversations.ui.util.PendingItem;
import eu.siacs.conversations.ui.util.SoftKeyboardUtils; import eu.siacs.conversations.ui.util.SoftKeyboardUtils;
@ -604,7 +605,7 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat
} }
private void refreshAvatar() { private void refreshAvatar() {
binding.avater.setImageBitmap(avatarService().get(mAccount, (int) getResources().getDimension(R.dimen.avatar_on_details_screen_size))); AvatarWorkerTask.loadAvatar(mAccount,binding.avater,R.dimen.avatar_on_details_screen_size);
} }
@Override @Override
@ -952,7 +953,7 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat
if (!mInitMode) { if (!mInitMode) {
this.binding.avater.setVisibility(View.VISIBLE); this.binding.avater.setVisibility(View.VISIBLE);
this.binding.avater.setImageBitmap(avatarService().get(this.mAccount, (int) getResources().getDimension(R.dimen.avatar_on_details_screen_size))); AvatarWorkerTask.loadAvatar(mAccount,binding.avater,R.dimen.avatar_on_details_screen_size);
} else { } else {
this.binding.avater.setVisibility(View.GONE); this.binding.avater.setVisibility(View.GONE);
} }

View File

@ -36,6 +36,7 @@ import android.os.PowerManager;
import android.os.SystemClock; import android.os.SystemClock;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.support.annotation.BoolRes; import android.support.annotation.BoolRes;
import android.support.annotation.NonNull;
import android.support.annotation.StringRes; import android.support.annotation.StringRes;
import android.support.v4.content.ContextCompat; import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
@ -993,11 +994,12 @@ public abstract class XmppActivity extends ActionBarActivity {
} }
} }
public static XmppActivity find(WeakReference<ImageView> viewWeakReference) { public static XmppActivity find(@NonNull WeakReference<ImageView> viewWeakReference) {
final View view = viewWeakReference.get(); final View view = viewWeakReference.get();
if (view == null) { return view == null ? null : find(view);
return null;
} }
public static XmppActivity find(@NonNull final View view) {
final Context context = view.getContext(); final Context context = view.getContext();
if (context instanceof XmppActivity) { if (context instanceof XmppActivity) {
return (XmppActivity) context; return (XmppActivity) context;

View File

@ -22,6 +22,7 @@ import eu.siacs.conversations.R;
import eu.siacs.conversations.databinding.AccountRowBinding; import eu.siacs.conversations.databinding.AccountRowBinding;
import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.ui.XmppActivity; import eu.siacs.conversations.ui.XmppActivity;
import eu.siacs.conversations.ui.util.AvatarWorkerTask;
import eu.siacs.conversations.ui.util.StyledAttributes; import eu.siacs.conversations.ui.util.StyledAttributes;
import eu.siacs.conversations.utils.UIHelper; import eu.siacs.conversations.utils.UIHelper;
@ -59,7 +60,7 @@ public class AccountAdapter extends ArrayAdapter<Account> {
} else { } else {
viewHolder.binding.accountJid.setText(account.getJid().asBareJid().toString()); viewHolder.binding.accountJid.setText(account.getJid().asBareJid().toString());
} }
loadAvatar(account, viewHolder.binding.accountImage); AvatarWorkerTask.loadAvatar(account, viewHolder.binding.accountImage, R.dimen.avatar);
viewHolder.binding.accountStatus.setText(getContext().getString(account.getStatus().getReadableId())); viewHolder.binding.accountStatus.setText(getContext().getString(account.getStatus().getReadableId()));
switch (account.getStatus()) { switch (account.getStatus()) {
case ONLINE: case ONLINE:
@ -97,97 +98,10 @@ public class AccountAdapter extends ArrayAdapter<Account> {
} }
} }
private static class BitmapWorkerTask extends AsyncTask<Account, Void, Bitmap> {
private final WeakReference<ImageView> imageViewReference;
private Account account = null;
BitmapWorkerTask(ImageView imageView) {
imageViewReference = new WeakReference<>(imageView);
}
@Override
protected Bitmap doInBackground(Account... params) {
this.account = params[0];
final XmppActivity activity = XmppActivity.find(imageViewReference);
if (activity == null) {
return null;
}
return activity.avatarService().get(this.account, activity.getPixel(48), isCancelled());
}
@Override
protected void onPostExecute(Bitmap bitmap) {
if (bitmap != null && !isCancelled()) {
final ImageView imageView = imageViewReference.get();
if (imageView != null) {
imageView.setImageBitmap(bitmap);
imageView.setBackgroundColor(0x00000000);
}
}
}
}
private void loadAvatar(Account account, ImageView imageView) {
if (cancelPotentialWork(account, imageView)) {
final Bitmap bm = activity.avatarService().get(account, activity.getPixel(48), true);
if (bm != null) {
cancelPotentialWork(account, imageView);
imageView.setImageBitmap(bm);
imageView.setBackgroundColor(0x00000000);
} else {
imageView.setBackgroundColor(UIHelper.getColorForName(account.getJid().asBareJid().toString()));
imageView.setImageDrawable(null);
final BitmapWorkerTask task = new BitmapWorkerTask(imageView);
final AsyncDrawable asyncDrawable = new AsyncDrawable(activity.getResources(), null, task);
imageView.setImageDrawable(asyncDrawable);
try {
task.execute(account);
} catch (final RejectedExecutionException ignored) {
}
}
}
}
public interface OnTglAccountState { public interface OnTglAccountState {
void onClickTglAccountState(Account account, boolean state); void onClickTglAccountState(Account account, boolean state);
} }
private static boolean cancelPotentialWork(Account account, ImageView imageView) {
final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
if (bitmapWorkerTask != null) {
final Account oldAccount = bitmapWorkerTask.account;
if (oldAccount == null || account != oldAccount) {
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;
AsyncDrawable(Resources res, Bitmap bitmap, BitmapWorkerTask bitmapWorkerTask) {
super(res, bitmap);
bitmapWorkerTaskReference = new WeakReference<>(bitmapWorkerTask);
}
BitmapWorkerTask getBitmapWorkerTask() {
return bitmapWorkerTaskReference.get();
}
}
} }

View File

@ -1,36 +1,24 @@
package eu.siacs.conversations.ui.adapter; package eu.siacs.conversations.ui.adapter;
import android.content.Context;
import android.content.res.Resources;
import android.databinding.DataBindingUtil; import android.databinding.DataBindingUtil;
import android.graphics.Bitmap;
import android.graphics.Typeface; import android.graphics.Typeface;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.util.Pair; import android.util.Pair;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import java.lang.ref.WeakReference;
import java.util.List; import java.util.List;
import java.util.concurrent.RejectedExecutionException;
import eu.siacs.conversations.R; import eu.siacs.conversations.R;
import eu.siacs.conversations.databinding.ConversationListRowBinding; import eu.siacs.conversations.databinding.ConversationListRowBinding;
import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.entities.Transferable;
import eu.siacs.conversations.ui.ConversationFragment; import eu.siacs.conversations.ui.ConversationFragment;
import eu.siacs.conversations.ui.XmppActivity; import eu.siacs.conversations.ui.XmppActivity;
import eu.siacs.conversations.ui.util.AvatarWorkerTask;
import eu.siacs.conversations.ui.util.StyledAttributes; import eu.siacs.conversations.ui.util.StyledAttributes;
import eu.siacs.conversations.ui.widget.UnreadCountCustomView;
import eu.siacs.conversations.utils.EmojiWrapper; import eu.siacs.conversations.utils.EmojiWrapper;
import eu.siacs.conversations.utils.IrregularUnicodeDetector; import eu.siacs.conversations.utils.IrregularUnicodeDetector;
import eu.siacs.conversations.utils.UIHelper; import eu.siacs.conversations.utils.UIHelper;
@ -47,30 +35,6 @@ public class ConversationAdapter extends RecyclerView.Adapter<ConversationAdapte
this.conversations = conversations; this.conversations = conversations;
} }
private static boolean cancelPotentialWork(Conversation conversation, ImageView imageView) {
final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
if (bitmapWorkerTask != null) {
final Conversation oldConversation = bitmapWorkerTask.conversation;
if (oldConversation == null || conversation != oldConversation) {
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;
}
@NonNull @NonNull
@Override @Override
@ -219,7 +183,7 @@ public class ConversationAdapter extends RecyclerView.Adapter<ConversationAdapte
timestamp = conversation.getLatestMessage().getTimeSent(); timestamp = conversation.getLatestMessage().getTimeSent();
} }
viewHolder.binding.conversationLastupdate.setText(UIHelper.readableTimeDifference(activity, timestamp)); viewHolder.binding.conversationLastupdate.setText(UIHelper.readableTimeDifference(activity, timestamp));
loadAvatar(conversation, viewHolder.binding.conversationImage); AvatarWorkerTask.loadAvatar(conversation, viewHolder.binding.conversationImage, R.dimen.avatar_on_conversation_overview);
viewHolder.itemView.setOnClickListener(v -> listener.onConversationClick(v, conversation)); viewHolder.itemView.setOnClickListener(v -> listener.onConversationClick(v, conversation));
} }
@ -232,26 +196,6 @@ public class ConversationAdapter extends RecyclerView.Adapter<ConversationAdapte
this.listener = listener; this.listener = listener;
} }
private void loadAvatar(Conversation conversation, ImageView imageView) {
if (cancelPotentialWork(conversation, imageView)) {
final Bitmap bm = activity.avatarService().get(conversation, activity.getPixel(56), true);
if (bm != null) {
cancelPotentialWork(conversation, imageView);
imageView.setImageBitmap(bm);
imageView.setBackgroundColor(0x00000000);
} else {
imageView.setBackgroundColor(UIHelper.getColorForName(conversation.getName().toString()));
imageView.setImageDrawable(null);
final BitmapWorkerTask task = new BitmapWorkerTask(imageView);
final AsyncDrawable asyncDrawable = new AsyncDrawable(activity.getResources(), null, task);
imageView.setImageDrawable(asyncDrawable);
try {
task.execute(conversation);
} catch (final RejectedExecutionException ignored) {
}
}
}
}
public void insert(Conversation c, int position) { public void insert(Conversation c, int position) {
conversations.add(position, c); conversations.add(position, c);
@ -277,47 +221,4 @@ public class ConversationAdapter extends RecyclerView.Adapter<ConversationAdapte
} }
static class AsyncDrawable extends BitmapDrawable {
private final WeakReference<BitmapWorkerTask> bitmapWorkerTaskReference;
AsyncDrawable(Resources res, Bitmap bitmap, BitmapWorkerTask bitmapWorkerTask) {
super(res, bitmap);
bitmapWorkerTaskReference = new WeakReference<>(bitmapWorkerTask);
}
BitmapWorkerTask getBitmapWorkerTask() {
return bitmapWorkerTaskReference.get();
}
}
static class BitmapWorkerTask extends AsyncTask<Conversation, Void, Bitmap> {
private final WeakReference<ImageView> imageViewReference;
private Conversation conversation = null;
BitmapWorkerTask(ImageView imageView) {
imageViewReference = new WeakReference<>(imageView);
}
@Override
protected Bitmap doInBackground(Conversation... params) {
this.conversation = params[0];
final XmppActivity activity = XmppActivity.find(imageViewReference);
if (activity == null) {
return null;
}
return activity.avatarService().get(this.conversation, activity.getPixel(56), isCancelled());
}
@Override
protected void onPostExecute(Bitmap bitmap) {
if (bitmap != null && !isCancelled()) {
final ImageView imageView = imageViewReference.get();
if (imageView != null) {
imageView.setImageBitmap(bitmap);
imageView.setBackgroundColor(0x00000000);
}
}
}
}
} }

View File

@ -26,6 +26,7 @@ import eu.siacs.conversations.databinding.ContactBinding;
import eu.siacs.conversations.entities.ListItem; import eu.siacs.conversations.entities.ListItem;
import eu.siacs.conversations.ui.SettingsActivity; import eu.siacs.conversations.ui.SettingsActivity;
import eu.siacs.conversations.ui.XmppActivity; import eu.siacs.conversations.ui.XmppActivity;
import eu.siacs.conversations.ui.util.AvatarWorkerTask;
import eu.siacs.conversations.utils.EmojiWrapper; import eu.siacs.conversations.utils.EmojiWrapper;
import eu.siacs.conversations.utils.IrregularUnicodeDetector; import eu.siacs.conversations.utils.IrregularUnicodeDetector;
import eu.siacs.conversations.utils.UIHelper; import eu.siacs.conversations.utils.UIHelper;
@ -49,30 +50,6 @@ public class ListItemAdapter extends ArrayAdapter<ListItem> {
this.activity = activity; this.activity = activity;
} }
private static boolean cancelPotentialWork(ListItem item, ImageView imageView) {
final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
if (bitmapWorkerTask != null) {
final ListItem oldItem = bitmapWorkerTask.item;
if (oldItem == null || item != oldItem) {
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;
}
public void refreshSettings() { public void refreshSettings() {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity); SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
@ -114,7 +91,7 @@ public class ListItemAdapter extends ArrayAdapter<ListItem> {
viewHolder.jid.setVisibility(View.GONE); viewHolder.jid.setVisibility(View.GONE);
} }
viewHolder.name.setText(EmojiWrapper.transform(item.getDisplayName())); viewHolder.name.setText(EmojiWrapper.transform(item.getDisplayName()));
loadAvatar(item, viewHolder.avatar); AvatarWorkerTask.loadAvatar(item, viewHolder.avatar, R.dimen.avatar);
return view; return view;
} }
@ -122,27 +99,6 @@ public class ListItemAdapter extends ArrayAdapter<ListItem> {
this.mOnTagClickedListener = listener; this.mOnTagClickedListener = listener;
} }
private void loadAvatar(ListItem item, ImageView imageView) {
if (cancelPotentialWork(item, imageView)) {
final Bitmap bm = activity.avatarService().get(item, activity.getPixel(48), true);
if (bm != null) {
cancelPotentialWork(item, imageView);
imageView.setImageBitmap(bm);
imageView.setBackgroundColor(0x00000000);
} else {
String seed = item.getJid() != null ? item.getJid().asBareJid().toString() : item.getDisplayName();
imageView.setBackgroundColor(UIHelper.getColorForName(seed));
imageView.setImageDrawable(null);
final BitmapWorkerTask task = new BitmapWorkerTask(imageView);
final AsyncDrawable asyncDrawable = new AsyncDrawable(activity.getResources(), null, task);
imageView.setImageDrawable(asyncDrawable);
try {
task.execute(item);
} catch (final RejectedExecutionException ignored) {
}
}
}
}
public interface OnTagClickedListener { public interface OnTagClickedListener {
void onTagClicked(String tag); void onTagClicked(String tag);
@ -169,47 +125,4 @@ public class ListItemAdapter extends ArrayAdapter<ListItem> {
} }
} }
static class AsyncDrawable extends BitmapDrawable {
private final WeakReference<BitmapWorkerTask> bitmapWorkerTaskReference;
AsyncDrawable(Resources res, Bitmap bitmap, BitmapWorkerTask bitmapWorkerTask) {
super(res, bitmap);
bitmapWorkerTaskReference = new WeakReference<>(bitmapWorkerTask);
}
BitmapWorkerTask getBitmapWorkerTask() {
return bitmapWorkerTaskReference.get();
}
}
private static class BitmapWorkerTask extends AsyncTask<ListItem, Void, Bitmap> {
private final WeakReference<ImageView> imageViewReference;
private ListItem item = null;
BitmapWorkerTask(ImageView imageView) {
imageViewReference = new WeakReference<>(imageView);
}
@Override
protected Bitmap doInBackground(ListItem... params) {
this.item = params[0];
final XmppActivity activity = XmppActivity.find(imageViewReference);
if (activity == null) {
return null;
}
return activity.avatarService().get(this.item, activity.getPixel(48), isCancelled());
}
@Override
protected void onPostExecute(Bitmap bitmap) {
if (bitmap != null && !isCancelled()) {
final ImageView imageView = imageViewReference.get();
if (imageView != null) {
imageView.setImageBitmap(bitmap);
imageView.setBackgroundColor(0x00000000);
}
}
}
}
} }

View File

@ -2,21 +2,11 @@ package eu.siacs.conversations.ui.adapter;
import android.Manifest; import android.Manifest;
import android.app.Activity; import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Typeface; import android.graphics.Typeface;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.support.annotation.ColorInt;
import android.support.v4.app.ActivityCompat; import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat; import android.support.v4.content.ContextCompat;
import android.text.Spannable; import android.text.Spannable;
@ -28,7 +18,6 @@ import android.text.style.ForegroundColorSpan;
import android.text.style.RelativeSizeSpan; import android.text.style.RelativeSizeSpan;
import android.text.style.StyleSpan; import android.text.style.StyleSpan;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.util.Log;
import android.view.ActionMode; import android.view.ActionMode;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
@ -43,10 +32,8 @@ import android.widget.RelativeLayout;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import java.lang.ref.WeakReference;
import java.net.URL; import java.net.URL;
import java.util.List; import java.util.List;
import java.util.concurrent.RejectedExecutionException;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -64,12 +51,13 @@ import eu.siacs.conversations.http.P1S3UrlStreamHandler;
import eu.siacs.conversations.persistance.FileBackend; import eu.siacs.conversations.persistance.FileBackend;
import eu.siacs.conversations.services.MessageArchiveService; import eu.siacs.conversations.services.MessageArchiveService;
import eu.siacs.conversations.services.NotificationService; import eu.siacs.conversations.services.NotificationService;
import eu.siacs.conversations.ui.ConversationsActivity;
import eu.siacs.conversations.ui.ConversationFragment; import eu.siacs.conversations.ui.ConversationFragment;
import eu.siacs.conversations.ui.ConversationsActivity;
import eu.siacs.conversations.ui.XmppActivity; import eu.siacs.conversations.ui.XmppActivity;
import eu.siacs.conversations.ui.service.AudioPlayer; import eu.siacs.conversations.ui.service.AudioPlayer;
import eu.siacs.conversations.ui.text.DividerSpan; import eu.siacs.conversations.ui.text.DividerSpan;
import eu.siacs.conversations.ui.text.QuoteSpan; import eu.siacs.conversations.ui.text.QuoteSpan;
import eu.siacs.conversations.ui.util.AvatarWorkerTask;
import eu.siacs.conversations.ui.util.MyLinkify; import eu.siacs.conversations.ui.util.MyLinkify;
import eu.siacs.conversations.ui.util.ViewUtil; import eu.siacs.conversations.ui.util.ViewUtil;
import eu.siacs.conversations.ui.widget.ClickableMovementMethod; import eu.siacs.conversations.ui.widget.ClickableMovementMethod;
@ -109,30 +97,6 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
} }
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;
}
private static void resetClickListener(View... views) { private static void resetClickListener(View... views) {
for (View view : views) { for (View view : views) {
@ -704,10 +668,10 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
boolean showAvatar; boolean showAvatar;
if (conversation.getMode() == Conversation.MODE_SINGLE) { if (conversation.getMode() == Conversation.MODE_SINGLE) {
showAvatar = true; showAvatar = true;
loadAvatar(message, viewHolder.contact_picture, activity.getPixel(32)); AvatarWorkerTask.loadAvatar(message, viewHolder.contact_picture, R.dimen.avatar_on_status_message);
} else if (message.getCounterpart() != null || message.getTrueCounterpart() != null || (message.getCounterparts() != null && message.getCounterparts().size() > 0)) { } else if (message.getCounterpart() != null || message.getTrueCounterpart() != null || (message.getCounterparts() != null && message.getCounterparts().size() > 0)) {
showAvatar = true; showAvatar = true;
loadAvatar(message, viewHolder.contact_picture, activity.getPixel(32)); AvatarWorkerTask.loadAvatar(message, viewHolder.contact_picture, R.dimen.avatar_on_status_message);
} else { } else {
showAvatar = false; showAvatar = false;
} }
@ -720,7 +684,7 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
} }
return view; return view;
} else { } else {
loadAvatar(message, viewHolder.contact_picture, activity.getPixel(48)); AvatarWorkerTask.loadAvatar(message, viewHolder.contact_picture, R.dimen.avatar);
} }
resetClickListener(viewHolder.message_box, viewHolder.messageBody); resetClickListener(viewHolder.message_box, viewHolder.messageBody);
@ -918,32 +882,6 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
this.mUseGreenBackground = p.getBoolean("use_green_background", activity.getResources().getBoolean(R.bool.use_green_background)); this.mUseGreenBackground = p.getBoolean("use_green_background", activity.getResources().getBoolean(R.bool.use_green_background));
} }
private void loadAvatar(Message message, ImageView imageView, int size) {
if (cancelPotentialWork(message, imageView)) {
final Bitmap bm = activity.avatarService().get(message, size, true);
if (bm != null) {
cancelPotentialWork(message, imageView);
imageView.setImageBitmap(bm);
imageView.setBackgroundColor(Color.TRANSPARENT);
} else {
@ColorInt int bg;
if (message.getType() == Message.TYPE_STATUS && message.getCounterparts() != null && message.getCounterparts().size() > 1) {
bg = Color.TRANSPARENT;
} else {
bg = UIHelper.getColorForName(UIHelper.getMessageDisplayName(message));
}
imageView.setBackgroundColor(bg);
imageView.setImageDrawable(null);
final BitmapWorkerTask task = new BitmapWorkerTask(imageView, size);
final AsyncDrawable asyncDrawable = new AsyncDrawable(activity.getResources(), null, task);
imageView.setImageDrawable(asyncDrawable);
try {
task.execute(message);
} catch (final RejectedExecutionException ignored) {
}
}
}
}
public void setHighlightedTerm(List<String> terms) { public void setHighlightedTerm(List<String> terms) {
this.highlightedTerm = terms == null ? null : StylingHelper.filterHighlightedWords(terms); this.highlightedTerm = terms == null ? null : StylingHelper.filterHighlightedWords(terms);
@ -978,18 +916,6 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
protected TextView encryption; protected TextView encryption;
} }
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();
}
}
private class MessageBodyActionModeCallback implements ActionMode.Callback { private class MessageBodyActionModeCallback implements ActionMode.Callback {
@ -1036,36 +962,4 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
public void onDestroyActionMode(ActionMode mode) { public void onDestroyActionMode(ActionMode mode) {
} }
} }
private static class BitmapWorkerTask extends AsyncTask<Message, Void, Bitmap> {
private final WeakReference<ImageView> imageViewReference;
private final int size;
private Message message = null;
BitmapWorkerTask(ImageView imageView, int size) {
imageViewReference = new WeakReference<>(imageView);
this.size = size;
}
@Override
protected Bitmap doInBackground(Message... params) {
this.message = params[0];
final XmppActivity activity = XmppActivity.find(imageViewReference);
if (activity == null) {
return null;
}
return activity.avatarService().get(this.message, size, isCancelled());
}
@Override
protected void onPostExecute(Bitmap bitmap) {
if (bitmap != null && !isCancelled()) {
final ImageView imageView = imageViewReference.get();
if (imageView != null) {
imageView.setImageBitmap(bitmap);
imageView.setBackgroundColor(0x00000000);
}
}
}
}
} }

View File

@ -0,0 +1,113 @@
package eu.siacs.conversations.ui.util;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.support.annotation.DimenRes;
import android.widget.ImageView;
import java.lang.ref.WeakReference;
import java.util.concurrent.RejectedExecutionException;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.services.AvatarService;
import eu.siacs.conversations.ui.XmppActivity;
import eu.siacs.conversations.ui.adapter.AccountAdapter;
import eu.siacs.conversations.utils.UIHelper;
public class AvatarWorkerTask extends AsyncTask<AvatarService.Avatarable, Void, Bitmap> {
private final WeakReference<ImageView> imageViewReference;
private AvatarService.Avatarable avatarable = null;
private @DimenRes int size;
public AvatarWorkerTask(ImageView imageView, @DimenRes int size) {
imageViewReference = new WeakReference<>(imageView);
this.size = size;
}
@Override
protected Bitmap doInBackground(AvatarService.Avatarable... params) {
this.avatarable = params[0];
final XmppActivity activity = XmppActivity.find(imageViewReference);
if (activity == null) {
return null;
}
return activity.avatarService().get(avatarable, (int) activity.getResources().getDimension(size), isCancelled());
}
@Override
protected void onPostExecute(Bitmap bitmap) {
if (bitmap != null && !isCancelled()) {
final ImageView imageView = imageViewReference.get();
if (imageView != null) {
imageView.setImageBitmap(bitmap);
imageView.setBackgroundColor(0x00000000);
}
}
}
public static boolean cancelPotentialWork(AvatarService.Avatarable avatarable, ImageView imageView) {
final AvatarWorkerTask workerTask = getBitmapWorkerTask(imageView);
if (workerTask != null) {
final AvatarService.Avatarable old= workerTask.avatarable;
if (old == null || avatarable != old) {
workerTask.cancel(true);
} else {
return false;
}
}
return true;
}
public static AvatarWorkerTask getBitmapWorkerTask(ImageView imageView) {
if (imageView != null) {
final Drawable drawable = imageView.getDrawable();
if (drawable instanceof AsyncDrawable) {
final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
return asyncDrawable.getAvatarWorkerTask();
}
}
return null;
}
public static void loadAvatar(final AvatarService.Avatarable avatarable, final ImageView imageView, final @DimenRes int size) {
if (cancelPotentialWork(avatarable, imageView)) {
final XmppActivity activity = XmppActivity.find(imageView);
if (activity == null) {
return;
}
final Bitmap bm = activity.avatarService().get(avatarable, (int) activity.getResources().getDimension(size), true);
if (bm != null) {
cancelPotentialWork(avatarable, imageView);
imageView.setImageBitmap(bm);
imageView.setBackgroundColor(0x00000000);
} else {
imageView.setBackgroundColor(avatarable.getAvatarBackgroundColor());
imageView.setImageDrawable(null);
final AvatarWorkerTask task = new AvatarWorkerTask(imageView, size);
final AsyncDrawable asyncDrawable = new AsyncDrawable(activity.getResources(), null, task);
imageView.setImageDrawable(asyncDrawable);
try {
task.execute(avatarable);
} catch (final RejectedExecutionException ignored) {
}
}
}
}
static class AsyncDrawable extends BitmapDrawable {
private final WeakReference<AvatarWorkerTask> avatarWorkerTaskReference;
AsyncDrawable(Resources res, Bitmap bitmap, AvatarWorkerTask workerTask) {
super(res, bitmap);
avatarWorkerTaskReference = new WeakReference<>(workerTask);
}
AvatarWorkerTask getAvatarWorkerTask() {
return avatarWorkerTaskReference.get();
}
}
}

View File

@ -18,7 +18,10 @@
<dimen name="publish_avatar_top_margin">8dp</dimen> <dimen name="publish_avatar_top_margin">8dp</dimen>
<dimen name="publish_avatar_size">96dp</dimen> <dimen name="publish_avatar_size">96dp</dimen>
<dimen name="avatar_on_status_message">32dp</dimen>
<dimen name="avatar">48dp</dimen>
<dimen name="avatar_on_details_screen_size">56dp</dimen> <dimen name="avatar_on_details_screen_size">56dp</dimen>
<dimen name="avatar_on_conversation_overview">56dp</dimen>
<dimen name="input_label_vertical_spacing">4dp</dimen> <dimen name="input_label_vertical_spacing">4dp</dimen>
<dimen name="input_label_horizontal_spacing">4dp</dimen> <dimen name="input_label_horizontal_spacing">4dp</dimen>