parse vcard avatars from muc presences

This commit is contained in:
Daniel Gultsch 2015-12-03 18:18:34 +01:00
parent f1c0b7372f
commit 6b592435cd
6 changed files with 299 additions and 185 deletions

View File

@ -4,20 +4,25 @@ import android.annotation.SuppressLint;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import eu.siacs.conversations.R; import eu.siacs.conversations.R;
import eu.siacs.conversations.crypto.PgpEngine;
import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xmpp.forms.Data; import eu.siacs.conversations.xmpp.forms.Data;
import eu.siacs.conversations.xmpp.forms.Field; import eu.siacs.conversations.xmpp.forms.Field;
import eu.siacs.conversations.xmpp.jid.InvalidJidException; import eu.siacs.conversations.xmpp.jid.InvalidJidException;
import eu.siacs.conversations.xmpp.jid.Jid; import eu.siacs.conversations.xmpp.jid.Jid;
import eu.siacs.conversations.xmpp.stanzas.PresencePacket; import eu.siacs.conversations.xmpp.pep.Avatar;
@SuppressLint("DefaultLocale") @SuppressLint("DefaultLocale")
public class MucOptions { public class MucOptions {
public Account getAccount() {
return this.conversation.getAccount();
}
public void setSelf(User user) {
this.self = user;
}
public enum Affiliation { public enum Affiliation {
OWNER("owner", 4, R.string.owner), OWNER("owner", 4, R.string.owner),
ADMIN("admin", 3, R.string.admin), ADMIN("admin", 3, R.string.admin),
@ -100,28 +105,31 @@ public class MucOptions {
public static final String STATUS_CODE_LOST_MEMBERSHIP = "321"; public static final String STATUS_CODE_LOST_MEMBERSHIP = "321";
private interface OnEventListener { private interface OnEventListener {
public void onSuccess(); void onSuccess();
public void onFailure(); void onFailure();
} }
public interface OnRenameListener extends OnEventListener { public interface OnRenameListener extends OnEventListener {
} }
public class User { public static class User {
private Role role = Role.NONE; private Role role = Role.NONE;
private Affiliation affiliation = Affiliation.NONE; private Affiliation affiliation = Affiliation.NONE;
private String name;
private Jid jid; private Jid jid;
private Jid fullJid;
private long pgpKeyId = 0; private long pgpKeyId = 0;
private Avatar avatar;
private MucOptions options;
public String getName() { public User(MucOptions options, Jid from) {
return name; this.options = options;
this.fullJid = from;
} }
public void setName(String user) { public String getName() {
this.name = user; return this.fullJid.getResourcepart();
} }
public void setJid(Jid jid) { public void setJid(Jid jid) {
@ -162,7 +170,7 @@ public class MucOptions {
return false; return false;
} else { } else {
User o = (User) other; User o = (User) other;
return name != null && name.equals(o.name) return getName() != null && getName().equals(o.getName())
&& jid != null && jid.equals(o.jid) && jid != null && jid.equals(o.jid)
&& affiliation == o.affiliation && affiliation == o.affiliation
&& role == o.role; && role == o.role;
@ -202,26 +210,43 @@ public class MucOptions {
} }
public Contact getContact() { public Contact getContact() {
return account.getRoster().getContactFromRoster(getJid()); return getAccount().getRoster().getContactFromRoster(getJid());
}
public void setAvatar(Avatar avatar) {
this.avatar = avatar;
}
public String getAvatar() {
return avatar == null ? null : avatar.getFilename();
}
public Account getAccount() {
return options.getAccount();
}
public Jid getFullJid() {
return fullJid;
} }
} }
private Account account; private Account account;
private List<User> users = new CopyOnWriteArrayList<>(); private final List<User> users = new ArrayList<>();
private List<String> features = new ArrayList<>(); private List<String> features = new ArrayList<>();
private Data form = new Data(); private Data form = new Data();
private Conversation conversation; private Conversation conversation;
private boolean isOnline = false; private boolean isOnline = false;
private int error = ERROR_UNKNOWN; private int error = ERROR_UNKNOWN;
private OnRenameListener onRenameListener = null; public OnRenameListener onRenameListener = null;
private User self = new User(); private User self;
private String subject = null; private String subject = null;
private String password = null; private String password = null;
private boolean mNickChangingInProgress = false; public boolean mNickChangingInProgress = false;
public MucOptions(Conversation conversation) { public MucOptions(Conversation conversation) {
this.account = conversation.getAccount(); this.account = conversation.getAccount();
this.conversation = conversation; this.conversation = conversation;
this.self = new User(this,conversation.getJid());
} }
public void updateFeatures(ArrayList<String> features) { public void updateFeatures(ArrayList<String> features) {
@ -273,135 +298,67 @@ public class MucOptions {
} }
public void deleteUser(String name) { public void deleteUser(String name) {
for (int i = 0; i < users.size(); ++i) { synchronized (this.users) {
if (users.get(i).getName().equals(name)) { for (int i = 0; i < users.size(); ++i) {
users.remove(i); if (users.get(i).getName().equals(name)) {
return; users.remove(i);
return;
}
} }
} }
} }
public void addUser(User user) { public void addUser(User user) {
for (int i = 0; i < users.size(); ++i) { synchronized (this.users) {
if (users.get(i).getName().equals(user.getName())) { for (int i = 0; i < users.size(); ++i) {
users.set(i, user); if (users.get(i).getName().equals(user.getName())) {
return; users.set(i, user);
return;
}
}
users.add(user);
}
}
public User findUser(String name) {
if (name == null) {
return null;
}
synchronized (this.users) {
for (User user : users) {
if (user.getName().equals(name)) {
return user;
}
} }
} }
users.add(user); return null;
} }
public boolean isUserInRoom(String name) { public boolean isUserInRoom(String name) {
for (int i = 0; i < users.size(); ++i) { return findUser(name) != null;
if (users.get(i).getName().equals(name)) {
return true;
}
}
return false;
} }
public void processPacket(PresencePacket packet, PgpEngine pgp) { public void setError(int error) {
final Jid from = packet.getFrom(); this.isOnline = error == ERROR_NO_ERROR;
if (!from.isBareJid()) {
final String name = from.getResourcepart();
final String type = packet.getAttribute("type");
final Element x = packet.findChild("x", "http://jabber.org/protocol/muc#user");
final List<String> codes = getStatusCodes(x);
if (type == null) {
User user = new User();
if (x != null) {
Element item = x.findChild("item");
if (item != null && name != null) {
user.setName(name);
user.setAffiliation(item.getAttribute("affiliation"));
user.setRole(item.getAttribute("role"));
user.setJid(item.getAttributeAsJid("jid"));
if (codes.contains(STATUS_CODE_SELF_PRESENCE) || packet.getFrom().equals(this.conversation.getJid())) {
this.isOnline = true;
this.error = ERROR_NO_ERROR;
self = user;
if (mNickChangingInProgress) {
if (onRenameListener != null) {
onRenameListener.onSuccess();
}
mNickChangingInProgress = false;
}
} else {
addUser(user);
}
if (pgp != null) {
Element signed = packet.findChild("x", "jabber:x:signed");
if (signed != null) {
Element status = packet.findChild("status");
String msg = status == null ? "" : status.getContent();
long keyId = pgp.fetchKeyId(account, msg, signed.getContent());
if (keyId != 0) {
user.setPgpKeyId(keyId);
}
}
}
}
}
} else if (type.equals("unavailable")) {
if (codes.contains(STATUS_CODE_SELF_PRESENCE) ||
packet.getFrom().equals(this.conversation.getJid())) {
if (codes.contains(STATUS_CODE_CHANGED_NICK)) {
this.mNickChangingInProgress = true;
} else if (codes.contains(STATUS_CODE_KICKED)) {
setError(KICKED_FROM_ROOM);
} else if (codes.contains(STATUS_CODE_BANNED)) {
setError(ERROR_BANNED);
} else if (codes.contains(STATUS_CODE_LOST_MEMBERSHIP)) {
setError(ERROR_MEMBERS_ONLY);
} else {
setError(ERROR_UNKNOWN);
}
} else {
deleteUser(name);
}
} else if (type.equals("error")) {
Element error = packet.findChild("error");
if (error != null && error.hasChild("conflict")) {
if (isOnline) {
if (onRenameListener != null) {
onRenameListener.onFailure();
}
} else {
setError(ERROR_NICK_IN_USE);
}
} else if (error != null && error.hasChild("not-authorized")) {
setError(ERROR_PASSWORD_REQUIRED);
} else if (error != null && error.hasChild("forbidden")) {
setError(ERROR_BANNED);
} else if (error != null && error.hasChild("registration-required")) {
setError(ERROR_MEMBERS_ONLY);
}
}
}
}
private void setError(int error) {
this.isOnline = false;
this.error = error; this.error = error;
} }
private List<String> getStatusCodes(Element x) { public ArrayList<User> getUsers() {
List<String> codes = new ArrayList<>(); synchronized (this.users) {
if (x != null) { return new ArrayList(this.users);
for (Element child : x.getChildren()) {
if (child.getName().equals("status")) {
String code = child.getAttribute("code");
if (code != null) {
codes.add(code);
}
}
}
} }
return codes;
} }
public List<User> getUsers() { public List<User> getUsers(int max) {
return this.users; synchronized (this.users) {
return new ArrayList<>(users.subList(0,Math.min(users.size(),5)));
}
}
public int getUserCount() {
synchronized (this.users) {
return this.users.size();
}
} }
public String getProposedNick() { public String getProposedNick() {
@ -455,34 +412,38 @@ public class MucOptions {
} }
public String createNameFromParticipants() { public String createNameFromParticipants() {
if (users.size() >= 2) { synchronized (this.users) {
List<String> names = new ArrayList<String>(); if (users.size() >= 2) {
for (User user : users) { List<String> names = new ArrayList<String>();
Contact contact = user.getContact(); for (User user : users) {
if (contact != null && !contact.getDisplayName().isEmpty()) { Contact contact = user.getContact();
names.add(contact.getDisplayName().split("\\s+")[0]); if (contact != null && !contact.getDisplayName().isEmpty()) {
} else { names.add(contact.getDisplayName().split("\\s+")[0]);
names.add(user.getName()); } else {
names.add(user.getName());
}
} }
} StringBuilder builder = new StringBuilder();
StringBuilder builder = new StringBuilder(); for (int i = 0; i < names.size(); ++i) {
for (int i = 0; i < names.size(); ++i) { builder.append(names.get(i));
builder.append(names.get(i)); if (i != names.size() - 1) {
if (i != names.size() - 1) { builder.append(", ");
builder.append(", "); }
} }
return builder.toString();
} else {
return null;
} }
return builder.toString();
} else {
return null;
} }
} }
public long[] getPgpKeyIds() { public long[] getPgpKeyIds() {
List<Long> ids = new ArrayList<>(); List<Long> ids = new ArrayList<>();
for (User user : getUsers()) { synchronized (this.users) {
if (user.getPgpKeyId() != 0) { for (User user : this.users) {
ids.add(user.getPgpKeyId()); if (user.getPgpKeyId() != 0) {
ids.add(user.getPgpKeyId());
}
} }
} }
ids.add(account.getPgpId()); ids.add(account.getPgpId());
@ -494,18 +455,22 @@ public class MucOptions {
} }
public boolean pgpKeysInUse() { public boolean pgpKeysInUse() {
for (User user : getUsers()) { synchronized (this.users) {
if (user.getPgpKeyId() != 0) { for (User user : this.users) {
return true; if (user.getPgpKeyId() != 0) {
return true;
}
} }
} }
return false; return false;
} }
public boolean everybodyHasKeys() { public boolean everybodyHasKeys() {
for (User user : getUsers()) { synchronized (this.users) {
if (user.getPgpKeyId() == 0) { for (User user : this.users) {
return false; if (user.getPgpKeyId() == 0) {
return false;
}
} }
} }
return true; return true;
@ -520,9 +485,11 @@ public class MucOptions {
} }
public Jid getTrueCounterpart(String counterpart) { public Jid getTrueCounterpart(String counterpart) {
for (User user : this.getUsers()) { synchronized (this.users) {
if (user.getName().equals(counterpart)) { for (User user : this.users) {
return user.getJid(); if (user.getName().equals(counterpart)) {
return user.getJid();
}
} }
} }
return null; return null;

View File

@ -169,7 +169,7 @@ public class MessageParser extends AbstractParser implements
if ("urn:xmpp:avatar:metadata".equals(node)) { if ("urn:xmpp:avatar:metadata".equals(node)) {
Avatar avatar = Avatar.parseMetadata(items); Avatar avatar = Avatar.parseMetadata(items);
if (avatar != null) { if (avatar != null) {
avatar.owner = from; avatar.owner = from.toBareJid();
if (mXmppConnectionService.getFileBackend().isAvatarCached(avatar)) { if (mXmppConnectionService.getFileBackend().isAvatarCached(avatar)) {
if (account.getJid().toBareJid().equals(from)) { if (account.getJid().toBareJid().equals(from)) {
if (account.setAvatar(avatar.getFilename())) { if (account.setAvatar(avatar.getFilename())) {

View File

@ -1,7 +1,11 @@
package eu.siacs.conversations.parser; package eu.siacs.conversations.parser;
import java.util.ArrayList; import android.util.Log;
import java.util.ArrayList;
import java.util.List;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.crypto.PgpEngine; import eu.siacs.conversations.crypto.PgpEngine;
import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.entities.Contact;
@ -25,19 +29,18 @@ public class PresenceParser extends AbstractParser implements
} }
public void parseConferencePresence(PresencePacket packet, Account account) { public void parseConferencePresence(PresencePacket packet, Account account) {
PgpEngine mPgpEngine = mXmppConnectionService.getPgpEngine();
final Conversation conversation = packet.getFrom() == null ? null : mXmppConnectionService.find(account, packet.getFrom().toBareJid()); final Conversation conversation = packet.getFrom() == null ? null : mXmppConnectionService.find(account, packet.getFrom().toBareJid());
if (conversation != null) { if (conversation != null) {
final MucOptions mucOptions = conversation.getMucOptions(); final MucOptions mucOptions = conversation.getMucOptions();
boolean before = mucOptions.online(); boolean before = mucOptions.online();
int count = mucOptions.getUsers().size(); int count = mucOptions.getUserCount();
final ArrayList<MucOptions.User> tileUserBefore = new ArrayList<>(mucOptions.getUsers().subList(0,Math.min(mucOptions.getUsers().size(),5))); final List<MucOptions.User> tileUserBefore = mucOptions.getUsers(5);
mucOptions.processPacket(packet, mPgpEngine); processConferencePresence(packet, mucOptions);
final ArrayList<MucOptions.User> tileUserAfter = new ArrayList<>(mucOptions.getUsers().subList(0,Math.min(mucOptions.getUsers().size(),5))); final List<MucOptions.User> tileUserAfter = mucOptions.getUsers(5);
if (!tileUserAfter.equals(tileUserBefore)) { if (!tileUserAfter.equals(tileUserBefore)) {
mXmppConnectionService.getAvatarService().clear(conversation); mXmppConnectionService.getAvatarService().clear(conversation);
} }
if (before != mucOptions.online() || (mucOptions.online() && count != mucOptions.getUsers().size())) { if (before != mucOptions.online() || (mucOptions.online() && count != mucOptions.getUserCount())) {
mXmppConnectionService.updateConversationUi(); mXmppConnectionService.updateConversationUi();
} else if (mucOptions.online()) { } else if (mucOptions.online()) {
mXmppConnectionService.updateMucRosterUi(); mXmppConnectionService.updateMucRosterUi();
@ -45,6 +48,108 @@ public class PresenceParser extends AbstractParser implements
} }
} }
private void processConferencePresence(PresencePacket packet, MucOptions mucOptions) {
final Jid from = packet.getFrom();
if (!from.isBareJid()) {
final String type = packet.getAttribute("type");
final Element x = packet.findChild("x", "http://jabber.org/protocol/muc#user");
Avatar avatar = Avatar.parsePresence(packet.findChild("x", "vcard-temp:x:update"));
final List<String> codes = getStatusCodes(x);
if (type == null) {
if (x != null) {
Element item = x.findChild("item");
if (item != null && !from.isBareJid()) {
MucOptions.User user = new MucOptions.User(mucOptions,from);
user.setAffiliation(item.getAttribute("affiliation"));
user.setRole(item.getAttribute("role"));
user.setJid(item.getAttributeAsJid("jid"));
if (codes.contains(MucOptions.STATUS_CODE_SELF_PRESENCE) || packet.getFrom().equals(mucOptions.getConversation().getJid())) {
mucOptions.setError(MucOptions.ERROR_NO_ERROR);
mucOptions.setSelf(user);
if (mucOptions.mNickChangingInProgress) {
if (mucOptions.onRenameListener != null) {
mucOptions.onRenameListener.onSuccess();
}
mucOptions.mNickChangingInProgress = false;
}
} else {
mucOptions.addUser(user);
}
if (mXmppConnectionService.getPgpEngine() != null) {
Element signed = packet.findChild("x", "jabber:x:signed");
if (signed != null) {
Element status = packet.findChild("status");
String msg = status == null ? "" : status.getContent();
long keyId = mXmppConnectionService.getPgpEngine().fetchKeyId(mucOptions.getAccount(), msg, signed.getContent());
if (keyId != 0) {
user.setPgpKeyId(keyId);
}
}
}
if (avatar != null) {
avatar.owner = from;
if (mXmppConnectionService.getFileBackend().isAvatarCached(avatar)) {
user.setAvatar(avatar);
} else {
mXmppConnectionService.fetchAvatar(mucOptions.getAccount(), avatar);
}
Log.d(Config.LOGTAG, "user " + avatar.owner + " has avatar");
}
}
}
} else if (type.equals("unavailable")) {
if (codes.contains(MucOptions.STATUS_CODE_SELF_PRESENCE) ||
packet.getFrom().equals(mucOptions.getConversation().getJid())) {
if (codes.contains(MucOptions.STATUS_CODE_CHANGED_NICK)) {
mucOptions.mNickChangingInProgress = true;
} else if (codes.contains(MucOptions.STATUS_CODE_KICKED)) {
mucOptions.setError(MucOptions.KICKED_FROM_ROOM);
} else if (codes.contains(MucOptions.STATUS_CODE_BANNED)) {
mucOptions.setError(MucOptions.ERROR_BANNED);
} else if (codes.contains(MucOptions.STATUS_CODE_LOST_MEMBERSHIP)) {
mucOptions.setError(MucOptions.ERROR_MEMBERS_ONLY);
} else {
mucOptions.setError(MucOptions.ERROR_UNKNOWN);
}
} else if (!from.isBareJid()){
mucOptions.deleteUser(from.getResourcepart());
}
} else if (type.equals("error")) {
Element error = packet.findChild("error");
if (error != null && error.hasChild("conflict")) {
if (mucOptions.online()) {
if (mucOptions.onRenameListener != null) {
mucOptions.onRenameListener.onFailure();
}
} else {
mucOptions.setError(MucOptions.ERROR_NICK_IN_USE);
}
} else if (error != null && error.hasChild("not-authorized")) {
mucOptions.setError(MucOptions.ERROR_PASSWORD_REQUIRED);
} else if (error != null && error.hasChild("forbidden")) {
mucOptions.setError(MucOptions.ERROR_BANNED);
} else if (error != null && error.hasChild("registration-required")) {
mucOptions.setError(MucOptions.ERROR_MEMBERS_ONLY);
}
}
}
}
private static List<String> getStatusCodes(Element x) {
List<String> codes = new ArrayList<>();
if (x != null) {
for (Element child : x.getChildren()) {
if (child.getName().equals("status")) {
String code = child.getAttribute("code");
if (code != null) {
codes.add(code);
}
}
}
}
return codes;
}
public void parseContactPresence(final PresencePacket packet, final Account account) { public void parseContactPresence(final PresencePacket packet, final Account account) {
final PresenceGenerator mPresenceGenerator = mXmppConnectionService.getPresenceGenerator(); final PresenceGenerator mPresenceGenerator = mXmppConnectionService.getPresenceGenerator();
final Jid from = packet.getFrom(); final Jid from = packet.getFrom();

View File

@ -58,6 +58,22 @@ public class AvatarService {
return avatar; return avatar;
} }
public Bitmap get(final MucOptions.User user, final int size, boolean cachedOnly) {
final String KEY = key(user, size);
Bitmap avatar = this.mXmppConnectionService.getBitmapCache().get(KEY);
if (avatar != null || cachedOnly) {
return avatar;
}
if (user.getAvatar() != null) {
avatar = mXmppConnectionService.getFileBackend().getAvatar(user.getAvatar(), size);
}
if (avatar == null) {
avatar = get(user.getName(), size, cachedOnly);
}
this.mXmppConnectionService.getBitmapCache().put(KEY, avatar);
return avatar;
}
public void clear(Contact contact) { public void clear(Contact contact) {
synchronized (this.sizes) { synchronized (this.sizes) {
for (Integer size : sizes) { for (Integer size : sizes) {
@ -77,6 +93,16 @@ public class AvatarService {
+ contact.getJid() + "_" + String.valueOf(size); + contact.getJid() + "_" + String.valueOf(size);
} }
private String key(MucOptions.User user, int size) {
synchronized (this.sizes) {
if (!this.sizes.contains(size)) {
this.sizes.add(size);
}
}
return PREFIX_CONTACT + "_" + user.getAccount().getJid().toBareJid() + "_"
+ user.getFullJid() + "_" + String.valueOf(size);
}
public Bitmap get(ListItem item, int size) { public Bitmap get(ListItem item, int size) {
return get(item,size,false); return get(item,size,false);
} }
@ -122,7 +148,7 @@ public class AvatarService {
if (bitmap != null || cachedOnly) { if (bitmap != null || cachedOnly) {
return bitmap; return bitmap;
} }
final List<MucOptions.User> users = new ArrayList<>(mucOptions.getUsers()); final List<MucOptions.User> users = mucOptions.getUsers();
int count = users.size(); int count = users.size();
bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap); Canvas canvas = new Canvas(bitmap);
@ -198,15 +224,20 @@ public class AvatarService {
} }
public Bitmap get(Message message, int size, boolean cachedOnly) { public Bitmap get(Message message, int size, boolean cachedOnly) {
final Conversation conversation = message.getConversation();
if (message.getStatus() == Message.STATUS_RECEIVED) { if (message.getStatus() == Message.STATUS_RECEIVED) {
Contact contact = message.getContact(); Contact c = message.getContact();
if (contact != null) { if (c != null && (c.getProfilePhoto() != null || c.getAvatar() != null)) {
return get(contact, size, cachedOnly); return get(c, size, cachedOnly);
} else { } else if (message.getConversation().getMode() == Conversation.MODE_MULTI){
return get(UIHelper.getMessageDisplayName(message), size, cachedOnly); MucOptions.User user = conversation.getMucOptions().findUser(message.getCounterpart().getResourcepart());
if (user != null) {
return get(user,size,cachedOnly);
}
} }
return get(UIHelper.getMessageDisplayName(message), size, cachedOnly);
} else { } else {
return get(message.getConversation().getAccount(), size, cachedOnly); return get(conversation.getAccount(), size, cachedOnly);
} }
} }
@ -290,6 +321,11 @@ public class AvatarService {
if (drawTile(canvas, uri, left, top, right, bottom)) { if (drawTile(canvas, uri, left, top, right, bottom)) {
return true; return true;
} }
} else if (user.getAvatar() != null) {
Uri uri = mXmppConnectionService.getFileBackend().getAvatarUri(user.getAvatar());
if (drawTile(canvas, uri, left, top, right, bottom)) {
return true;
}
} }
String name = contact != null ? contact.getDisplayName() : user.getName(); String name = contact != null ? contact.getDisplayName() : user.getName();
drawTile(canvas, name, left, top, right, bottom); drawTile(canvas, name, left, top, right, bottom);

View File

@ -2358,12 +2358,22 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
if (getFileBackend().save(avatar)) { if (getFileBackend().save(avatar)) {
Log.d(Config.LOGTAG, account.getJid().toBareJid() Log.d(Config.LOGTAG, account.getJid().toBareJid()
+ ": successfully fetched vCard avatar for " + avatar.owner); + ": successfully fetched vCard avatar for " + avatar.owner);
Contact contact = account.getRoster() if (avatar.owner.isBareJid()) {
.getContact(avatar.owner); Contact contact = account.getRoster()
contact.setAvatar(avatar); .getContact(avatar.owner);
getAvatarService().clear(contact); contact.setAvatar(avatar);
updateConversationUi(); getAvatarService().clear(contact);
updateRosterUi(); updateConversationUi();
updateRosterUi();
} else {
Conversation conversation = find(account,avatar.owner.toBareJid());
if (conversation != null && conversation.getMode() == Conversation.MODE_MULTI) {
MucOptions.User user = conversation.getMucOptions().findUser(avatar.owner.getResourcepart());
if (user != null) {
user.setAvatar(avatar);
}
}
}
} }
} }
} }

View File

@ -494,8 +494,7 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
} }
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
membersView.removeAllViews(); membersView.removeAllViews();
final ArrayList<User> users = new ArrayList<>(); final ArrayList<User> users = mucOptions.getUsers();
users.addAll(mConversation.getMucOptions().getUsers());
Collections.sort(users,new Comparator<User>() { Collections.sort(users,new Comparator<User>() {
@Override @Override
public int compare(User lhs, User rhs) { public int compare(User lhs, User rhs) {
@ -527,20 +526,17 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
}); });
tvKey.setText(OpenPgpUtils.convertKeyIdToHex(user.getPgpKeyId())); tvKey.setText(OpenPgpUtils.convertKeyIdToHex(user.getPgpKeyId()));
} }
Bitmap bm;
Contact contact = user.getContact(); Contact contact = user.getContact();
if (contact != null) { if (contact != null) {
bm = avatarService().get(contact, getPixel(48));
tvDisplayName.setText(contact.getDisplayName()); tvDisplayName.setText(contact.getDisplayName());
tvStatus.setText(user.getName() + " \u2022 " + getStatus(user)); tvStatus.setText(user.getName() + " \u2022 " + getStatus(user));
} else { } else {
bm = avatarService().get(user.getName(), getPixel(48));
tvDisplayName.setText(user.getName()); tvDisplayName.setText(user.getName());
tvStatus.setText(getStatus(user)); tvStatus.setText(getStatus(user));
} }
ImageView iv = (ImageView) view.findViewById(R.id.contact_photo); ImageView iv = (ImageView) view.findViewById(R.id.contact_photo);
iv.setImageBitmap(bm); iv.setImageBitmap(avatarService().get(user, getPixel(48), false));
membersView.addView(view); membersView.addView(view);
if (mConversation.getMucOptions().canInvite()) { if (mConversation.getMucOptions().canInvite()) {
mInviteButton.setVisibility(View.VISIBLE); mInviteButton.setVisibility(View.VISIBLE);