aboutsummaryrefslogtreecommitdiffstats
path: root/src/net/java/sip
diff options
context:
space:
mode:
authorDamian Minkov <damencho@jitsi.org>2013-10-03 11:31:24 +0300
committerDamian Minkov <damencho@jitsi.org>2013-10-03 11:32:24 +0300
commitc33c7cdfcf8199acb6e14766b13ad2fe9df7c777 (patch)
tree3d79b52836484cc3e3f2029efdebe5585c3738be /src/net/java/sip
parentb0c9b7e4c700c19b18c41a56022b8000603f4c19 (diff)
downloadjitsi-c33c7cdfcf8199acb6e14766b13ad2fe9df7c777.zip
jitsi-c33c7cdfcf8199acb6e14766b13ad2fe9df7c777.tar.gz
jitsi-c33c7cdfcf8199acb6e14766b13ad2fe9df7c777.tar.bz2
Adds mobile indicator icon next contacts when there are detected to be logged in only from a mobile device.
Diffstat (limited to 'src/net/java/sip')
-rwxr-xr-xsrc/net/java/sip/communicator/impl/gui/main/chat/ChatWritePanel.java3
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListTreeCellRenderer.java32
-rw-r--r--src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java6
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/ContactJabberImpl.java26
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/MobileIndicator.java304
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/OperationSetPersistentPresenceJabberImpl.java5
-rw-r--r--src/net/java/sip/communicator/service/protocol/AbstractContact.java9
-rw-r--r--src/net/java/sip/communicator/service/protocol/Contact.java7
8 files changed, 391 insertions, 1 deletions
diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/ChatWritePanel.java b/src/net/java/sip/communicator/impl/gui/main/chat/ChatWritePanel.java
index 35baa43..6feec83 100755
--- a/src/net/java/sip/communicator/impl/gui/main/chat/ChatWritePanel.java
+++ b/src/net/java/sip/communicator/impl/gui/main/chat/ChatWritePanel.java
@@ -1211,7 +1211,8 @@ public class ChatWritePanel
if (transportSelectorBox != null)
transportSelectorBox.removeChatTransport(chatTransport);
- if(transportSelectorBox.getMenu().getItemCount() == 1
+ if(transportSelectorBox != null
+ && transportSelectorBox.getMenu().getItemCount() == 1
&& ConfigurationUtils.isHideAccountSelectionWhenPossibleEnabled())
{
transportSelectorBox.setVisible(false);
diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListTreeCellRenderer.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListTreeCellRenderer.java
index 25e1f86..60225a4 100644
--- a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListTreeCellRenderer.java
+++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListTreeCellRenderer.java
@@ -403,6 +403,9 @@ public class ContactListTreeCellRenderer
}
}
+ // clear icon if any (mobile indicator)
+ this.nameLabel.setIcon(null);
+
// Make appropriate adjustments for contact nodes and group nodes.
if (value instanceof ContactNode)
{
@@ -439,6 +442,15 @@ public class ContactListTreeCellRenderer
// contains a status message.
this.initDisplayDetails(contact.getDisplayDetails());
+ // Checks and set mobile indicator
+ if (contact.getDescriptor() instanceof MetaContact
+ && isMobile((MetaContact)contact.getDescriptor()))
+ {
+ this.nameLabel.setIcon(new ImageIcon(ImageLoader.getImage(
+ ImageLoader.CONTACT_LIST_MOBILE_INDICATOR)));
+ this.nameLabel.setHorizontalTextPosition(SwingConstants.LEFT);
+ }
+
if (this.treeContactList.isContactButtonsVisible())
this.initButtonsPanel(contact);
@@ -528,6 +540,26 @@ public class ContactListTreeCellRenderer
}
/**
+ * Checks whether metaContact has mobile indicator.
+ * Needs all of the contacts to have it to indicate it.
+ * @param metaContact the metacontact to check for mobile indicator
+ * @return whether to indicate contact as mobile one.
+ */
+ private boolean isMobile(MetaContact metaContact)
+ {
+ Iterator<Contact> iter = metaContact.getContacts();
+ while(iter.hasNext())
+ {
+ Contact contact = iter.next();
+
+ if(!contact.isMobile())
+ return false;
+ }
+
+ return metaContact.getContactCount() > 0 ? true : false;
+ }
+
+ /**
* Paints a customized background.
*
* @param g the <tt>Graphics</tt> object through which we paint
diff --git a/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java b/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java
index 7802329..77c6772 100644
--- a/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java
+++ b/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java
@@ -248,6 +248,12 @@ public class ImageLoader
= new ImageID("service.gui.buttons.CONTACT_LIST_BUTTON_SEPARATOR");
/**
+ * The mobile indicator for contacts in contact list.
+ */
+ public static final ImageID CONTACT_LIST_MOBILE_INDICATOR
+ = new ImageID("service.gui.buttons.CONTACT_LIST_MOBILE_INDICATOR");
+
+ /**
* The call button small image.
*/
public static final ImageID CALL_BUTTON_SMALL
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/ContactJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/ContactJabberImpl.java
index 644059a..d0e0f00 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/ContactJabberImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/ContactJabberImpl.java
@@ -80,6 +80,11 @@ public class ContactJabberImpl
private Map<String, ContactResourceJabberImpl> resources = null;
/**
+ * Whether this contact is a mobile one.
+ */
+ private boolean mobile = false;
+
+ /**
* Creates an JabberContactImpl
* @param rosterEntry the RosterEntry object that we will be encapsulating.
* @param ssclCallback a reference to the ServerStoredContactListImpl
@@ -622,4 +627,25 @@ public class ContactJabberImpl
= new ConcurrentHashMap<String, ContactResourceJabberImpl>();
}
}
+
+ /**
+ * Whether contact is mobile one. Logged in from mobile device.
+ * @return whether contact is mobile one.
+ */
+ public boolean isMobile()
+ {
+ if(!getPresenceStatus().isOnline())
+ return false;
+
+ return mobile;
+ }
+
+ /**
+ * Changes the mobile indicator value.
+ * @param mobile is mobile
+ */
+ void setMobile(boolean mobile)
+ {
+ this.mobile = mobile;
+ }
} \ No newline at end of file
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/MobileIndicator.java b/src/net/java/sip/communicator/impl/protocol/jabber/MobileIndicator.java
new file mode 100644
index 0000000..28caec9
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/MobileIndicator.java
@@ -0,0 +1,304 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.impl.protocol.jabber;
+
+import net.java.sip.communicator.impl.protocol.jabber.extensions.caps.*;
+import net.java.sip.communicator.service.protocol.*;
+import net.java.sip.communicator.service.protocol.event.*;
+import org.jivesoftware.smack.util.*;
+
+import java.util.*;
+
+/**
+ * Handles all the logic about mobile indicator for contacts.
+ * Has to modes, the first is searching for particular string in the beginning
+ * of the contact resource and if found and this is the highest priority then
+ * the contact in on mobile.
+ * The second one and the default one is searching for strings in the node
+ * from the contact caps and if found and this is the most connected device
+ * then the contact is a mobile one.
+ *
+ * @author Damian Minkov
+ */
+public class MobileIndicator
+ implements RegistrationStateChangeListener,
+ UserCapsNodeListener
+{
+ /**
+ * The parent provider.
+ */
+ private final ProtocolProviderServiceJabberImpl parentProvider;
+
+ /**
+ * Whether we are using the default method for checking for
+ * mobile indicator.
+ */
+ private boolean isCapsMobileIndicator = true;
+
+ /**
+ * The strings that we will check.
+ */
+ private final String[] checkStrings;
+
+ /**
+ * A reference to the ServerStoredContactListImpl instance.
+ */
+ private final ServerStoredContactListJabberImpl ssclCallback;
+
+ /**
+ * The account property to activate the mode for checking the resource
+ * names, the strings to check whether a resource starts with can be
+ * entered separated by comas.
+ */
+ private static final String MOBILE_INDICATOR_RESOURCE_ACC_PROP =
+ "MOBILE_INDICATOR_RESOURCE";
+
+ /**
+ * The account property to activate the mode for checking the contact
+ * caps, the strings to check whether a caps contains with can be
+ * entered separated by comas.
+ */
+ private static final String MOBILE_INDICATOR_CAPS_ACC_PROP =
+ "MOBILE_INDICATOR_CAPS";
+
+ /**
+ * Construct Mobile indicator.
+ * @param parentProvider the parent provider.
+ * @param ssclCallback the callback for the contact list to obtain contacts.
+ */
+ public MobileIndicator(ProtocolProviderServiceJabberImpl parentProvider,
+ ServerStoredContactListJabberImpl ssclCallback)
+ {
+ this.parentProvider = parentProvider;
+ this.ssclCallback = ssclCallback;
+
+ String indicatorResource = parentProvider.getAccountID()
+ .getAccountProperties().get(MOBILE_INDICATOR_RESOURCE_ACC_PROP);
+ if(indicatorResource != null
+ && indicatorResource.length() > 0)
+ {
+ isCapsMobileIndicator = false;
+ checkStrings = indicatorResource.split(",");
+ }
+ else
+ {
+ String indicatorCaps = parentProvider.getAccountID()
+ .getAccountProperties().get(MOBILE_INDICATOR_CAPS_ACC_PROP);
+ if(indicatorCaps == null
+ || indicatorCaps.length() == 0)
+ {
+ indicatorCaps = "android";
+ }
+
+ checkStrings = indicatorCaps.split(",");
+
+ this.parentProvider.addRegistrationStateChangeListener(this);
+ }
+ }
+
+ /**
+ * Called when resources have been updated for a contact, on
+ * presence changed.
+ * @param contact the contact
+ */
+ public void resourcesUpdated(ContactJabberImpl contact)
+ {
+ if(isCapsMobileIndicator)
+ {
+ // we update it also here, cause sometimes caps update comes
+ // before presence changed and contacts are still offline
+ // and we dispatch wrong initial mobile indicator
+ updateMobileIndicatorUsingCaps(contact.getAddress());
+ return;
+ }
+
+ // checks resource starts with String and is current highest priority
+ int highestPriority = Integer.MIN_VALUE;
+ List<ContactResource> highestPriorityResources =
+ new ArrayList<ContactResource>();
+
+ for(ContactResource res : contact.getResources())
+ {
+ if(!res.getPresenceStatus().isOnline())
+ continue;
+
+ int prio = res.getPriority();
+
+ if(prio >= highestPriority)
+ {
+ if(highestPriority != prio)
+ highestPriorityResources.clear();
+
+ highestPriority = prio;
+
+ highestPriorityResources.add(res);
+ }
+ }
+
+ // check whether all are mobile
+ boolean allMobile = false;
+ for(ContactResource res : highestPriorityResources)
+ {
+ if(startsWithStrings(res.getResourceName(), checkStrings))
+ allMobile = true;
+ else
+ {
+ allMobile = false;
+ break;
+ }
+ }
+
+ if(highestPriorityResources.size() > 0)
+ contact.setMobile(allMobile);
+ else
+ contact.setMobile(false);
+ }
+
+ /**
+ * The method is called by a ProtocolProvider implementation whenever
+ * a change in the registration state of the corresponding provider had
+ * occurred.
+ * @param evt ProviderStatusChangeEvent the event describing the status
+ * change.
+ */
+ public void registrationStateChanged(RegistrationStateChangeEvent evt)
+ {
+ if(evt.getNewState() == RegistrationState.REGISTERED)
+ {
+ this.parentProvider.getDiscoveryManager()
+ .getCapsManager().addUserCapsNodeListener(this);
+ }
+ }
+
+ /**
+ * Caps for user has been changed.
+ * @param user the user (full JID)
+ * @param node the entity caps node#ver
+ * @param online indicates if the user for which we're notified is online
+ */
+ @Override
+ public void userCapsNodeAdded(String user, String node, boolean online)
+ {
+ updateMobileIndicatorUsingCaps(user);
+ }
+
+ /**
+ * Caps for user has been changed.
+ * @param user the user (full JID)
+ * @param node the entity caps node#ver
+ * @param online indicates if the user for which we're notified is online
+ */
+ @Override
+ public void userCapsNodeRemoved(String user, String node, boolean online)
+ {
+ updateMobileIndicatorUsingCaps(user);
+ }
+
+ /**
+ * Update mobile indicator for contact, searching in contact caps.
+ * @param user the contact address with or without resource.
+ */
+ private void updateMobileIndicatorUsingCaps(String user)
+ {
+ ContactJabberImpl contact =
+ ssclCallback.findContactById(StringUtils.parseBareAddress(user));
+
+ if(contact == null)
+ return;
+
+ // Now lets check for mobile indicator
+ EntityCapsManager capsManager = ssclCallback.getParentProvider()
+ .getDiscoveryManager().getCapsManager();
+
+ // 1. Find most connected resources and if all are mobile
+ int currentMostConnectedStatus = 0;
+ List<ContactResource> mostAvailableResources =
+ new ArrayList<ContactResource>();
+
+ for(ContactResource res : contact.getResources())
+ {
+ if(!res.getPresenceStatus().isOnline())
+ continue;
+
+ int status = res.getPresenceStatus().getStatus();
+
+ if(status > currentMostConnectedStatus)
+ {
+ if(currentMostConnectedStatus != status)
+ mostAvailableResources.clear();
+
+ currentMostConnectedStatus = status;
+
+ mostAvailableResources.add(res);
+ }
+ }
+
+ // check whether all are mobile
+ boolean allMobile = false;
+ for(ContactResource res : mostAvailableResources)
+ {
+ EntityCapsManager.Caps caps = capsManager.getCapsByUser(
+ ((ContactResourceJabberImpl)res).getFullJid());
+
+ if(caps == null)
+ {
+ // missing caps, no indicator so its not mobile
+ allMobile = false;
+ break;
+ }
+
+ if(containsStrings(caps.node, checkStrings))
+ allMobile = true;
+ else
+ {
+ allMobile = false;
+ break;
+ }
+ }
+
+ if(mostAvailableResources.size() > 0)
+ contact.setMobile(allMobile);
+ else
+ contact.setMobile(false);
+ }
+
+ /**
+ * Checks whether <tt>value</tt> starts
+ * one of the <tt>checkStrs</> Strings.
+ * @param value the value to check
+ * @param checkStrs an array of strings we are searching for.
+ * @return <tt>true</tt> if <tt>value</tt> starts one of the Strings.
+ */
+ private static boolean startsWithStrings(String value, String[] checkStrs)
+ {
+ for(String str : checkStrs)
+ {
+ if(str.length() > 0 && value.startsWith(str))
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Checks whether <tt>value</tt> contains
+ * one of the <tt>checkStrs</> Strings.
+ * @param value the value to check
+ * @param checkStrs an array of strings we are searching for.
+ * @return <tt>true</tt> if <tt>value</tt> contains one of the Strings.
+ */
+ private static boolean containsStrings(String value, String[] checkStrs)
+ {
+ for(String str : checkStrs)
+ {
+ if(str.length() > 0 && value.contains(str))
+ return true;
+ }
+
+ return false;
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetPersistentPresenceJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetPersistentPresenceJabberImpl.java
index ca90432..d3796ad 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetPersistentPresenceJabberImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetPersistentPresenceJabberImpl.java
@@ -109,6 +109,8 @@ public class OperationSetPersistentPresenceJabberImpl
private VCardTempXUpdatePresenceExtension vCardTempXUpdatePresenceExtension
= null;
+ private final MobileIndicator mobileIndicator;
+
/**
* Creates the OperationSet.
* @param provider the parent provider.
@@ -131,6 +133,8 @@ public class OperationSetPersistentPresenceJabberImpl
parentProvider.addRegistrationStateChangeListener(
new RegistrationStateListener());
+
+ mobileIndicator = new MobileIndicator(parentProvider, ssContactList);
}
/**
@@ -1157,6 +1161,7 @@ public class OperationSetPersistentPresenceJabberImpl
// When status changes this may be related to a change in the
// available resources.
sourceContact.updateResources();
+ mobileIndicator.resourcesUpdated(sourceContact);
PresenceStatus oldStatus
= sourceContact.getPresenceStatus();
diff --git a/src/net/java/sip/communicator/service/protocol/AbstractContact.java b/src/net/java/sip/communicator/service/protocol/AbstractContact.java
index 1a87ecd..5b4052a 100644
--- a/src/net/java/sip/communicator/service/protocol/AbstractContact.java
+++ b/src/net/java/sip/communicator/service/protocol/AbstractContact.java
@@ -179,4 +179,13 @@ public abstract class AbstractContact
{
return getAddress();
}
+
+ /**
+ * Whether contact is mobile one. Logged in only from mobile device.
+ * @return whether contact is mobile one.
+ */
+ public boolean isMobile()
+ {
+ return false;
+ }
}
diff --git a/src/net/java/sip/communicator/service/protocol/Contact.java b/src/net/java/sip/communicator/service/protocol/Contact.java
index 96915cd..335e206 100644
--- a/src/net/java/sip/communicator/service/protocol/Contact.java
+++ b/src/net/java/sip/communicator/service/protocol/Contact.java
@@ -158,4 +158,11 @@ public interface Contact
* @return the address of the contact.
*/
public String getPersistableAddress();
+
+ /**
+ * Whether contact is mobile one. Logged in only from mobile device.
+ * @return whether contact is mobile one.
+ */
+ public boolean isMobile();
+
}