keep conference members in memory and show them in conference details

This commit is contained in:
Daniel Gultsch 2016-05-16 14:10:40 +02:00
parent d7c5264ad0
commit 8d0693ed6a
10 changed files with 186 additions and 99 deletions

View file

@ -643,7 +643,6 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
jids = Arrays.asList(conversation.getJid().toBareJid());
} else {
jids = conversation.getMucOptions().getMembers();
jids.remove(account.getJid().toBareJid());
}
return jids;
}

View file

@ -5,9 +5,7 @@ import android.annotation.SuppressLint;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import eu.siacs.conversations.R;
@ -28,6 +26,15 @@ public class MucOptions {
this.self = user;
}
public void changeAffiliation(Jid jid, Affiliation affiliation) {
User user = findUserByRealJid(jid);
if (user != null) {
users.remove(user);
user.affiliation = affiliation;
users.add(user);
}
}
public enum Affiliation {
OWNER("owner", 4, R.string.owner),
ADMIN("admin", 3, R.string.admin),
@ -127,7 +134,7 @@ public class MucOptions {
public static class User {
private Role role = Role.NONE;
private Affiliation affiliation = Affiliation.NONE;
private Jid jid;
private Jid realJid;
private Jid fullJid;
private long pgpKeyId = 0;
private Avatar avatar;
@ -139,15 +146,15 @@ public class MucOptions {
}
public String getName() {
return this.fullJid.getResourcepart();
return fullJid == null ? null : fullJid.getResourcepart();
}
public void setJid(Jid jid) {
this.jid = jid;
public void setRealJid(Jid jid) {
this.realJid = jid != null ? jid.toBareJid() : null;
}
public Jid getJid() {
return this.jid;
public Jid getRealJid() {
return this.realJid;
}
public Role getRole() {
@ -155,6 +162,10 @@ public class MucOptions {
}
public void setRole(String role) {
if (role == null) {
this.role = Role.NONE;
return;
}
role = role.toLowerCase();
switch (role) {
case "moderator":
@ -172,26 +183,15 @@ public class MucOptions {
}
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
} else if (!(other instanceof User)) {
return false;
} else {
User o = (User) other;
return getName() != null && getName().equals(o.getName())
&& jid != null && jid.equals(o.jid)
&& affiliation == o.affiliation
&& role == o.role;
}
}
public Affiliation getAffiliation() {
return this.affiliation;
}
public void setAffiliation(String affiliation) {
if (affiliation == null) {
this.affiliation = Affiliation.NONE;
return;
}
affiliation = affiliation.toLowerCase();
switch (affiliation) {
case "admin":
@ -220,7 +220,7 @@ public class MucOptions {
}
public Contact getContact() {
return getAccount().getRoster().getContactFromRoster(getJid());
return getAccount().getRoster().getContactFromRoster(getRealJid());
}
public boolean setAvatar(Avatar avatar) {
@ -243,11 +243,39 @@ public class MucOptions {
public Jid getFullJid() {
return fullJid;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
if (role != user.role) return false;
if (affiliation != user.affiliation) return false;
if (realJid != null ? !realJid.equals(user.realJid) : user.realJid != null)
return false;
return fullJid != null ? fullJid.equals(user.fullJid) : user.fullJid == null;
}
@Override
public int hashCode() {
int result = role != null ? role.hashCode() : 0;
result = 31 * result + (affiliation != null ? affiliation.hashCode() : 0);
result = 31 * result + (realJid != null ? realJid.hashCode() : 0);
result = 31 * result + (fullJid != null ? fullJid.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "[fulljid:"+String.valueOf(fullJid)+",realjid:"+String.valueOf(realJid)+",affiliation"+affiliation.toString()+"]";
}
}
private Account account;
private final Map<String, User> users = Collections.synchronizedMap(new LinkedHashMap<String, User>());
private final Set<Jid> members = Collections.synchronizedSet(new HashSet<Jid>());
private final Set<User> users = Collections.synchronizedSet(new HashSet<User>());
private final List<String> features = new ArrayList<>();
private Data form = new Data();
private Conversation conversation;
@ -315,20 +343,66 @@ public class MucOptions {
return hasFeature("muc_moderated");
}
public User deleteUser(String name) {
return this.users.remove(name);
public User deleteUser(Jid jid) {
User user = findUserByFullJid(jid);
if (user != null) {
users.remove(user);
if (user.affiliation.ranks(Affiliation.MEMBER)) {
user.role = Role.NONE;
user.avatar = null;
user.fullJid = null;
users.add(user);
}
}
return user;
}
public void addUser(User user) {
this.users.put(user.getName(), user);
User old;
if (user.fullJid == null && user.realJid != null) {
old = findUserByRealJid(user.realJid);
if (old != null) {
return; //don't add. user already exists
}
} else if (user.realJid != null) {
old = findUserByRealJid(user.realJid);
if (old != null && old.fullJid == null) {
users.remove(old);
}
}
old = findUserByFullJid(user.getFullJid());
if (old != null) {
users.remove(old);
}
this.users.add(user);
}
public User findUser(String name) {
return this.users.get(name);
public User findUserByFullJid(Jid jid) {
if (jid == null) {
return null;
}
for(User user : users) {
if (jid.equals(user.getFullJid())) {
return user;
}
}
return null;
}
public boolean isUserInRoom(String name) {
return findUser(name) != null;
public User findUserByRealJid(Jid jid) {
if (jid == null) {
return null;
}
for(User user : users) {
if (jid.equals(user.getRealJid())) {
return user;
}
}
return null;
}
public boolean isUserInRoom(Jid jid) {
return findUserByFullJid(jid) != null;
}
public void setError(Error error) {
@ -341,7 +415,7 @@ public class MucOptions {
}
public ArrayList<User> getUsers() {
return new ArrayList<>(users.values());
return new ArrayList<>(users);
}
public List<User> getUsers(int max) {
@ -410,7 +484,7 @@ public class MucOptions {
Contact contact = user.getContact();
if (contact != null && !contact.getDisplayName().isEmpty()) {
names.add(contact.getDisplayName().split("\\s+")[0]);
} else {
} else if (user.getName() != null){
names.add(user.getName());
}
}
@ -429,7 +503,7 @@ public class MucOptions {
public long[] getPgpKeyIds() {
List<Long> ids = new ArrayList<>();
for (User user : this.users.values()) {
for (User user : this.users) {
if (user.getPgpKeyId() != 0) {
ids.add(user.getPgpKeyId());
}
@ -443,7 +517,7 @@ public class MucOptions {
}
public boolean pgpKeysInUse() {
for (User user : this.users.values()) {
for (User user : this.users) {
if (user.getPgpKeyId() != 0) {
return true;
}
@ -452,7 +526,7 @@ public class MucOptions {
}
public boolean everybodyHasKeys() {
for (User user : this.users.values()) {
for (User user : this.users) {
if (user.getPgpKeyId() == 0) {
return false;
}
@ -468,12 +542,12 @@ public class MucOptions {
}
}
public Jid getTrueCounterpart(String name) {
if (name.equals(getSelf().getName())) {
public Jid getTrueCounterpart(Jid jid) {
if (jid.equals(getSelf().getFullJid())) {
return account.getJid().toBareJid();
}
User user = findUser(name);
return user == null ? null : user.getJid();
User user = findUserByFullJid(jid);
return user == null ? null : user.getRealJid();
}
public String getPassword() {
@ -499,11 +573,21 @@ public class MucOptions {
return this.conversation;
}
public void putMember(Jid jid) {
members.add(jid);
public void putMember(Jid fullJid, Jid realJid, String affiliation, String role) {
User user = new User(this, fullJid);
user.setRealJid(realJid);
user.setAffiliation(affiliation);
user.setRole(role);
addUser(user);
}
public List<Jid> getMembers() {
return new ArrayList<>(members);
ArrayList<Jid> members = new ArrayList<>();
for(User user : users) {
if (user.affiliation.ranks(Affiliation.MEMBER) && user.getRealJid() != null) {
members.add(user.getRealJid());
}
}
return members;
}
}

View file

@ -402,7 +402,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
} else if (axolotlEncrypted != null && Config.supportOmemo()) {
Jid origin;
if (conversation.getMode() == Conversation.MODE_MULTI) {
origin = conversation.getMucOptions().getTrueCounterpart(counterpart.getResourcepart());
origin = conversation.getMucOptions().getTrueCounterpart(counterpart);
if (origin == null) {
Log.d(Config.LOGTAG,"axolotl message in non anonymous conference received");
return;
@ -430,7 +430,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
message.setOob(isOob);
message.markable = packet.hasChild("markable", "urn:xmpp:chat-markers:0");
if (conversation.getMode() == Conversation.MODE_MULTI) {
Jid trueCounterpart = conversation.getMucOptions().getTrueCounterpart(counterpart.getResourcepart());
Jid trueCounterpart = conversation.getMucOptions().getTrueCounterpart(counterpart);
message.setTrueCounterpart(trueCounterpart);
if (!isTypeGroupChat) {
message.setType(Message.TYPE_PRIVATE);

View file

@ -14,15 +14,12 @@ import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.entities.MucOptions;
import eu.siacs.conversations.entities.Presence;
import eu.siacs.conversations.entities.ServiceDiscoveryResult;
import eu.siacs.conversations.generator.PresenceGenerator;
import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xmpp.OnIqPacketReceived;
import eu.siacs.conversations.xmpp.OnPresencePacketReceived;
import eu.siacs.conversations.xmpp.jid.Jid;
import eu.siacs.conversations.xmpp.pep.Avatar;
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
import eu.siacs.conversations.xmpp.stanzas.PresencePacket;
public class PresenceParser extends AbstractParser implements
@ -67,11 +64,7 @@ public class PresenceParser extends AbstractParser implements
MucOptions.User user = new MucOptions.User(mucOptions, from);
user.setAffiliation(item.getAttribute("affiliation"));
user.setRole(item.getAttribute("role"));
Jid real = item.getAttributeAsJid("jid");
if (real != null) {
user.setJid(real);
mucOptions.putMember(real.toBareJid());
}
user.setRealJid(item.getAttributeAsJid("jid"));
if (codes.contains(MucOptions.STATUS_CODE_SELF_PRESENCE) || packet.getFrom().equals(mucOptions.getConversation().getJid())) {
mucOptions.setOnline();
mucOptions.setSelf(user);
@ -127,7 +120,7 @@ public class PresenceParser extends AbstractParser implements
Log.d(Config.LOGTAG, "unknown error in conference: " + packet);
}
} else if (!from.isBareJid()){
MucOptions.User user = mucOptions.deleteUser(from.getResourcepart());
MucOptions.User user = mucOptions.deleteUser(from);
if (user != null) {
mXmppConnectionService.getAvatarService().clear(user);
}

View file

@ -246,7 +246,7 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
if (c != null && (c.getProfilePhoto() != null || c.getAvatar() != null)) {
return get(c, size, cachedOnly);
} else if (message.getConversation().getMode() == Conversation.MODE_MULTI){
MucOptions.User user = conversation.getMucOptions().findUser(message.getCounterpart().getResourcepart());
MucOptions.User user = conversation.getMucOptions().findUserByFullJid(message.getCounterpart());
if (user != null) {
return getImpl(user,size,cachedOnly);
}

View file

@ -1899,11 +1899,26 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
@Override
public void onIqPacketReceived(Account account, IqPacket packet) {
Element query = packet.query("http://jabber.org/protocol/muc#admin");
if (packet.getType() == IqPacket.TYPE.RESULT && query != null) {
final String local = conversation.getJid().getLocalpart();
final String domain = conversation.getJid().getDomainpart();
for(Element child : query.getChildren()) {
if ("item".equals(child.getName())) {
conversation.getMucOptions().putMember(child.getAttributeAsJid("jid"));
String affiliation = child.getAttribute("affiliation");
String role = child.getAttribute("role");
String nick = child.getAttribute("nick");
Jid fullJid;
try {
fullJid = nick != null ? Jid.fromParts(local, domain, nick) : null;
} catch (InvalidJidException e) {
fullJid = null;
}
Jid realJid = child.getAttributeAsJid("jid");
if (realJid != null && !realJid.equals(account.getJid().toBareJid())) {
conversation.getMucOptions().putMember(fullJid, realJid, affiliation, role);
}
}
}
} else {
@ -2175,13 +2190,14 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
}
}
public void changeAffiliationInConference(final Conversation conference, Jid user, MucOptions.Affiliation affiliation, final OnAffiliationChanged callback) {
public void changeAffiliationInConference(final Conversation conference, Jid user, final MucOptions.Affiliation affiliation, final OnAffiliationChanged callback) {
final Jid jid = user.toBareJid();
IqPacket request = this.mIqGenerator.changeAffiliation(conference, jid, affiliation.toString());
sendIqPacket(conference.getAccount(), request, new OnIqPacketReceived() {
@Override
public void onIqPacketReceived(Account account, IqPacket packet) {
if (packet.getType() == IqPacket.TYPE.RESULT) {
conference.getMucOptions().changeAffiliation(jid, affiliation);
callback.onAffiliationChangedSuccessful(jid);
} else {
callback.onAffiliationChangeFailed(jid, R.string.could_not_change_affiliation);
@ -2193,8 +2209,8 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
public void changeAffiliationsInConference(final Conversation conference, MucOptions.Affiliation before, MucOptions.Affiliation after) {
List<Jid> jids = new ArrayList<>();
for (MucOptions.User user : conference.getMucOptions().getUsers()) {
if (user.getAffiliation() == before && user.getJid() != null) {
jids.add(user.getJid());
if (user.getAffiliation() == before && user.getRealJid() != null) {
jids.add(user.getRealJid());
}
}
IqPacket request = this.mIqGenerator.changeAffiliation(conference, jids, after.toString());
@ -2574,7 +2590,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
} 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());
MucOptions.User user = conversation.getMucOptions().findUserByFullJid(avatar.owner);
if (user != null) {
if (user.setAvatar(avatar)) {
getAvatarService().clear(user);

View file

@ -1,6 +1,5 @@
package eu.siacs.conversations.ui;
import android.annotation.TargetApi;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.ActivityNotFoundException;
@ -8,7 +7,6 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentSender.SendIntentException;
import android.os.Build;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.LayoutInflater;
@ -365,13 +363,13 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
final Contact contact = user.getContact();
if (contact != null) {
name = contact.getDisplayName();
} else if (user.getJid() != null){
name = user.getJid().toBareJid().toString();
} else if (user.getRealJid() != null){
name = user.getRealJid().toBareJid().toString();
} else {
name = user.getName();
}
menu.setHeaderTitle(name);
if (user.getJid() != null) {
if (user.getRealJid() != null) {
MenuItem showContactDetails = menu.findItem(R.id.action_contact_details);
MenuItem startConversation = menu.findItem(R.id.start_conversation);
MenuItem giveMembership = menu.findItem(R.id.give_membership);
@ -424,22 +422,22 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
startConversation(mSelectedUser);
return true;
case R.id.give_admin_privileges:
xmppConnectionService.changeAffiliationInConference(mConversation,mSelectedUser.getJid(), MucOptions.Affiliation.ADMIN,this);
xmppConnectionService.changeAffiliationInConference(mConversation,mSelectedUser.getRealJid(), MucOptions.Affiliation.ADMIN,this);
return true;
case R.id.give_membership:
xmppConnectionService.changeAffiliationInConference(mConversation,mSelectedUser.getJid(), MucOptions.Affiliation.MEMBER,this);
xmppConnectionService.changeAffiliationInConference(mConversation,mSelectedUser.getRealJid(), MucOptions.Affiliation.MEMBER,this);
return true;
case R.id.remove_membership:
xmppConnectionService.changeAffiliationInConference(mConversation,mSelectedUser.getJid(), MucOptions.Affiliation.NONE,this);
xmppConnectionService.changeAffiliationInConference(mConversation,mSelectedUser.getRealJid(), MucOptions.Affiliation.NONE,this);
return true;
case R.id.remove_admin_privileges:
xmppConnectionService.changeAffiliationInConference(mConversation,mSelectedUser.getJid(), MucOptions.Affiliation.MEMBER,this);
xmppConnectionService.changeAffiliationInConference(mConversation,mSelectedUser.getRealJid(), MucOptions.Affiliation.MEMBER,this);
return true;
case R.id.remove_from_room:
removeFromRoom(mSelectedUser);
return true;
case R.id.ban_from_conference:
xmppConnectionService.changeAffiliationInConference(mConversation,mSelectedUser.getJid(), MucOptions.Affiliation.OUTCAST,this);
xmppConnectionService.changeAffiliationInConference(mConversation,mSelectedUser.getRealJid(), MucOptions.Affiliation.OUTCAST,this);
xmppConnectionService.changeRoleInConference(mConversation,mSelectedUser.getName(), MucOptions.Role.NONE,this);
return true;
case R.id.send_private_message:
@ -452,7 +450,7 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
private void removeFromRoom(final User user) {
if (mConversation.getMucOptions().membersOnly()) {
xmppConnectionService.changeAffiliationInConference(mConversation,user.getJid(), MucOptions.Affiliation.NONE,this);
xmppConnectionService.changeAffiliationInConference(mConversation,user.getRealJid(), MucOptions.Affiliation.NONE,this);
xmppConnectionService.changeRoleInConference(mConversation,mSelectedUser.getName(), MucOptions.Role.NONE,ConferenceDetailsActivity.this);
} else {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
@ -462,7 +460,7 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
builder.setPositiveButton(R.string.ban_now,new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
xmppConnectionService.changeAffiliationInConference(mConversation,user.getJid(), MucOptions.Affiliation.OUTCAST,ConferenceDetailsActivity.this);
xmppConnectionService.changeAffiliationInConference(mConversation,user.getRealJid(), MucOptions.Affiliation.OUTCAST,ConferenceDetailsActivity.this);
xmppConnectionService.changeRoleInConference(mConversation,mSelectedUser.getName(), MucOptions.Role.NONE,ConferenceDetailsActivity.this);
}
});
@ -471,8 +469,8 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
}
protected void startConversation(User user) {
if (user.getJid() != null) {
Conversation conversation = xmppConnectionService.findOrCreateConversation(this.mConversation.getAccount(),user.getJid().toBareJid(),false);
if (user.getRealJid() != null) {
Conversation conversation = xmppConnectionService.findOrCreateConversation(this.mConversation.getAccount(),user.getRealJid().toBareJid(),false);
switchToConversation(conversation);
}
}
@ -577,8 +575,8 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
final ArrayList<User> users = mucOptions.getUsers();
Collections.sort(users,new Comparator<User>() {
@Override
public int compare(User lhs, User rhs) {
return lhs.getName().compareToIgnoreCase(rhs.getName());
public int compare(User l, User r) {
return l.getName() == null || r.getName() == null ? 0 : l.getName().compareToIgnoreCase(r.getName());
}
});
for (final User user : users) {
@ -607,11 +605,12 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
tvKey.setText(OpenPgpUtils.convertKeyIdToHex(user.getPgpKeyId()));
}
Contact contact = user.getContact();
String name = user.getName();
if (contact != null) {
tvDisplayName.setText(contact.getDisplayName());
tvStatus.setText(user.getName() + " \u2022 " + getStatus(user));
tvStatus.setText((name != null ? name+ " \u2022 " : "") + getStatus(user));
} else {
tvDisplayName.setText(user.getName());
tvDisplayName.setText(name == null ? "" : name);
tvStatus.setText(getStatus(user));
}
@ -657,7 +656,7 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
@Override
public void onAffiliationChangedSuccessful(Jid jid) {
refreshUi();
}
@Override

View file

@ -461,12 +461,12 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
public void onContactPictureClicked(Message message) {
if (message.getStatus() <= Message.STATUS_RECEIVED) {
if (message.getConversation().getMode() == Conversation.MODE_MULTI) {
if (message.getCounterpart() != null) {
String user = message.getCounterpart().isBareJid() ? message.getCounterpart().toString() : message.getCounterpart().getResourcepart();
Jid user = message.getCounterpart();
if (user != null && !user.isBareJid()) {
if (!message.getConversation().getMucOptions().isUserInRoom(user)) {
Toast.makeText(activity,activity.getString(R.string.user_has_left_conference,user),Toast.LENGTH_SHORT).show();
Toast.makeText(activity,activity.getString(R.string.user_has_left_conference,user.getResourcepart()),Toast.LENGTH_SHORT).show();
}
highlightInConference(user);
highlightInConference(user.getResourcepart());
}
} else {
if (!message.getContact().isSelf()) {
@ -495,14 +495,12 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
public void onContactPictureLongClicked(Message message) {
if (message.getStatus() <= Message.STATUS_RECEIVED) {
if (message.getConversation().getMode() == Conversation.MODE_MULTI) {
if (message.getCounterpart() != null) {
String user = message.getCounterpart().getResourcepart();
if (user != null) {
if (message.getConversation().getMucOptions().isUserInRoom(user)) {
privateMessageWith(message.getCounterpart());
} else {
Toast.makeText(activity, activity.getString(R.string.user_has_left_conference, user), Toast.LENGTH_SHORT).show();
}
Jid user = message.getCounterpart();
if (user != null && !user.isBareJid()) {
if (message.getConversation().getMucOptions().isUserInRoom(user)) {
privateMessageWith(user);
} else {
Toast.makeText(activity, activity.getString(R.string.user_has_left_conference, user.getResourcepart()), Toast.LENGTH_SHORT).show();
}
}
}

View file

@ -42,7 +42,6 @@ import android.preference.PreferenceManager;
import android.text.InputType;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
@ -68,7 +67,6 @@ import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.RunnableFuture;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
@ -481,7 +479,7 @@ public abstract class XmppActivity extends Activity {
List<String> contacts = new ArrayList<>();
if (conversation.getMode() == Conversation.MODE_MULTI) {
for (MucOptions.User user : conversation.getMucOptions().getUsers()) {
Jid jid = user.getJid();
Jid jid = user.getRealJid();
if (jid != null) {
contacts.add(jid.toBareJid().toString());
}

View file

@ -447,7 +447,7 @@
<string name="disable_all_accounts">Disable all accounts</string>
<string name="perform_action_with">Perform action with</string>
<string name="no_affiliation">No affiliation</string>
<string name="no_role">No role</string>
<string name="no_role">Offline</string>
<string name="outcast">Outcast</string>
<string name="member">Member</string>
<string name="advanced_mode">Advanced mode</string>
@ -542,7 +542,7 @@
<string name="pref_use_white_background_summary">Show received messages as black text on a white background</string>
<string name="account_status_tor_unavailable">Tor network unavailable</string>
<string name="account_status_bind_failure">Bind failure</string>
<string name="account_status_host_unknown">Domain not recognized</string>
<string name="account_status_host_unknown">Host unknown</string>
<string name="server_info_broken">Broken</string>
<string name="pref_presence_settings">Presence</string>
<string name="pref_away_when_screen_off">Away when screen is off</string>