/** * Called to indicate that sending typing notification has failed. * * @param evt a <tt>TypingNotificationEvent</tt> containing the sender of the notification and its * type. */ public void typingNotificationDeliveryFailed(TypingNotificationEvent evt) { if (typingTimer.isRunning()) typingTimer.stop(); String notificationMsg = ""; MetaContact metaContact = GuiActivator.getContactListService().findMetaContactByContact(evt.getSourceContact()); String contactName = metaContact.getDisplayName(); if (contactName.equals("")) { contactName = GuiActivator.getResources().getI18NString("service.gui.UNKNOWN") + " "; } ChatPanel chatPanel = chatWindowManager.getContactChat(metaContact, false); notificationMsg = GuiActivator.getResources() .getI18NString("service.gui.CONTACT_TYPING_SEND_FAILED", new String[] {contactName}); // Proactive typing notification if (!chatWindowManager.isChatOpenedFor(metaContact)) { return; } if (chatPanel != null) chatPanel.addErrorSendingTypingNotification(notificationMsg); typingTimer.setMetaContact(metaContact); typingTimer.start(); }
/** * Shows a warning message to the user when message delivery has failed. * * @param evt the event containing details on the message delivery failure */ public void messageDeliveryFailed(MessageDeliveryFailedEvent evt) { logger.error(evt.getReason()); String errorMsg = null; Message sourceMessage = (Message) evt.getSource(); Contact sourceContact = evt.getDestinationContact(); MetaContact metaContact = GuiActivator.getContactListService().findMetaContactByContact(sourceContact); if (evt.getErrorCode() == MessageDeliveryFailedEvent.OFFLINE_MESSAGES_NOT_SUPPORTED) { errorMsg = GuiActivator.getResources() .getI18NString( "service.gui.MSG_DELIVERY_NOT_SUPPORTED", new String[] {sourceContact.getDisplayName()}); } else if (evt.getErrorCode() == MessageDeliveryFailedEvent.NETWORK_FAILURE) { errorMsg = GuiActivator.getResources().getI18NString("service.gui.MSG_NOT_DELIVERED"); } else if (evt.getErrorCode() == MessageDeliveryFailedEvent.PROVIDER_NOT_REGISTERED) { errorMsg = GuiActivator.getResources().getI18NString("service.gui.MSG_SEND_CONNECTION_PROBLEM"); } else if (evt.getErrorCode() == MessageDeliveryFailedEvent.INTERNAL_ERROR) { errorMsg = GuiActivator.getResources().getI18NString("service.gui.MSG_DELIVERY_INTERNAL_ERROR"); } else { errorMsg = GuiActivator.getResources().getI18NString("service.gui.MSG_DELIVERY_ERROR"); } String reason = evt.getReason(); if (reason != null) errorMsg += " " + GuiActivator.getResources() .getI18NString("service.gui.ERROR_WAS", new String[] {reason}); ChatPanel chatPanel = chatWindowManager.getContactChat(metaContact, sourceContact); chatPanel.addMessage( sourceContact.getAddress(), metaContact.getDisplayName(), new Date(), Chat.OUTGOING_MESSAGE, sourceMessage.getContent(), sourceMessage.getContentType(), sourceMessage.getMessageUID(), evt.getCorrectedMessageUID()); chatPanel.addErrorMessage(metaContact.getDisplayName(), errorMsg); chatWindowManager.openChat(chatPanel, false); }
/** * Permanently removes locally stored message history for the metacontact, remove any recent * contacts if any. */ public void eraseLocallyStoredHistory(MetaContact contact) throws IOException { List<ComparableEvtObj> toRemove = null; synchronized (recentMessages) { toRemove = new ArrayList<ComparableEvtObj>(); Iterator<Contact> iter = contact.getContacts(); while (iter.hasNext()) { Contact item = iter.next(); String id = item.getAddress(); ProtocolProviderService provider = item.getProtocolProvider(); for (ComparableEvtObj msc : recentMessages) { if (msc.getProtocolProviderService().equals(provider) && msc.getContactAddress().equals(id)) { toRemove.add(msc); } } } recentMessages.removeAll(toRemove); } if (recentQuery != null) { for (ComparableEvtObj msc : toRemove) { recentQuery.fireContactRemoved(msc); } } }
/** * Returns <tt>true</tt> if the given meta contact is online, <tt>false</tt> otherwise. * * @param contact the meta contact * @return <tt>true</tt> if the given meta contact is online, <tt>false</tt> otherwise */ private boolean isContactOnline(MetaContact contact) { // If for some reason the default contact is null we return false. Contact defaultContact = contact.getDefaultContact(); if (defaultContact == null) return false; // Lays on the fact that the default contact is the most connected. return defaultContact.getPresenceStatus().getStatus() >= PresenceStatus.ONLINE_THRESHOLD; }
/** * Informs the user what is the typing state of his chat contacts. * * @param evt the event containing details on the typing notification */ public void typingNotificationReceived(TypingNotificationEvent evt) { if (typingTimer.isRunning()) typingTimer.stop(); String notificationMsg = ""; MetaContact metaContact = GuiActivator.getContactListService().findMetaContactByContact(evt.getSourceContact()); String contactName = metaContact.getDisplayName() + " "; if (contactName.equals("")) { contactName = GuiActivator.getResources().getI18NString("service.gui.UNKNOWN") + " "; } int typingState = evt.getTypingState(); ChatPanel chatPanel = chatWindowManager.getContactChat(metaContact, false); if (typingState == OperationSetTypingNotifications.STATE_TYPING) { notificationMsg = GuiActivator.getResources() .getI18NString("service.gui.CONTACT_TYPING", new String[] {contactName}); // Proactive typing notification if (!chatWindowManager.isChatOpenedFor(metaContact)) { return; } if (chatPanel != null) chatPanel.addTypingNotification(notificationMsg); typingTimer.setMetaContact(metaContact); typingTimer.start(); } else if (typingState == OperationSetTypingNotifications.STATE_PAUSED) { notificationMsg = GuiActivator.getResources() .getI18NString("service.gui.CONTACT_PAUSED_TYPING", new String[] {contactName}); if (chatPanel != null) chatPanel.addTypingNotification(notificationMsg); typingTimer.setMetaContact(metaContact); typingTimer.start(); } else { if (chatPanel != null) chatPanel.removeTypingNotification(); } }
/** * Initializes buttons panel. * * @param uiContact the <tt>UIContact</tt> for which we initialize the button panel */ private void initButtonsPanel(UIContact uiContact) { this.remove(chatButton); this.remove(callButton); this.remove(callVideoButton); this.remove(desktopSharingButton); this.remove(addContactButton); clearCustomActionButtons(); if (!isSelected) return; UIContactDetail imContact = null; // For now we support instance messaging only for contacts in our // contact list until it's implemented for external source contacts. if (uiContact.getDescriptor() instanceof MetaContact) imContact = uiContact.getDefaultContactDetail(OperationSetBasicInstantMessaging.class); int x = (statusIcon == null ? 0 : statusIcon.getIconWidth()) + LEFT_BORDER + H_GAP; // Re-initialize the x grid. constraints.gridx = 0; int gridX = 0; if (imContact != null) { x += addButton(chatButton, ++gridX, x, false); } UIContactDetail telephonyContact = uiContact.getDefaultContactDetail(OperationSetBasicTelephony.class); // Check if contact has additional phone numbers, if yes show the // call button ContactPhoneUtil contactPhoneUtil = null; // check for phone stored in contact info only // if telephony contact is missing if (uiContact.getDescriptor() != null && uiContact.getDescriptor() instanceof MetaContact && telephonyContact == null) { contactPhoneUtil = ContactPhoneUtil.getPhoneUtil((MetaContact) uiContact.getDescriptor()); MetaContact metaContact = (MetaContact) uiContact.getDescriptor(); Iterator<Contact> contacts = metaContact.getContacts(); while (contacts.hasNext()) // && !hasPhone) { Contact contact = contacts.next(); if (!contact.getProtocolProvider().isRegistered()) continue; contactPhoneUtil.addDetailsResponseListener( contact, new DetailsListener(treeNode, callButton, uiContact)); } } // for SourceContact in history that do not support telephony, we // show the button but disabled List<ProtocolProviderService> providers = AccountUtils.getOpSetRegisteredProviders(OperationSetBasicTelephony.class, null, null); if ((telephonyContact != null && telephonyContact.getAddress() != null) || (contactPhoneUtil != null && contactPhoneUtil.isCallEnabled() && providers.size() > 0)) { x += addButton(callButton, ++gridX, x, false); } UIContactDetail videoContact = uiContact.getDefaultContactDetail(OperationSetVideoTelephony.class); if (videoContact != null || (contactPhoneUtil != null && contactPhoneUtil.isVideoCallEnabled())) { x += addButton(callVideoButton, ++gridX, x, false); } UIContactDetail desktopContact = uiContact.getDefaultContactDetail(OperationSetDesktopSharingServer.class); if (desktopContact != null || (contactPhoneUtil != null && contactPhoneUtil.isDesktopSharingEnabled())) { x += addButton(desktopSharingButton, ++gridX, x, false); } // enable add contact button if contact source has indicated // that this is possible if (uiContact.getDescriptor() instanceof SourceContact && uiContact.getDefaultContactDetail(OperationSetPersistentPresence.class) != null && AccountUtils.getOpSetRegisteredProviders( OperationSetPersistentPresence.class, null, null) .size() > 0 && !ConfigurationUtils.isAddContactDisabled()) { x += addButton(addContactButton, ++gridX, x, false); } // The list of the contact actions // we will create a button for every action Collection<SIPCommButton> contactActions = uiContact.getContactCustomActionButtons(); int lastGridX = gridX; if (contactActions != null && contactActions.size() > 0) { lastGridX = initContactActionButtons(contactActions, gridX, x); } else { addLabels(gridX); } if (lastAddedButton != null) setButtonBg(lastAddedButton, lastGridX, true); this.setBounds(0, 0, treeContactList.getWidth(), getPreferredSize().height); }
/** * Adds all contacts contained in the given <tt>MetaContactGroup</tt> matching the current filter * and not contained in the contact list. * * @param metaGroup the <tt>MetaContactGroup</tt>, which matching contacts to add * @param query the <tt>MetaContactQuery</tt> that notifies interested listeners of the results of * this matching * @param resultCount the initial result count we would insert directly to the contact list * without firing events */ private void addMatching(MetaContactGroup metaGroup, MetaContactQuery query, int resultCount) { Iterator<MetaContact> childContacts = metaGroup.getChildContacts(); while (childContacts.hasNext() && !query.isCanceled()) { MetaContact metaContact = childContacts.next(); if (isMatching(metaContact)) { resultCount++; if (resultCount <= INITIAL_CONTACT_COUNT) { UIGroup uiGroup = null; if (!MetaContactListSource.isRootGroup(metaGroup)) { synchronized (metaGroup) { uiGroup = MetaContactListSource.getUIGroup(metaGroup); if (uiGroup == null) uiGroup = MetaContactListSource.createUIGroup(metaGroup); } } if (logger.isDebugEnabled()) logger.debug("Presence filter contact added: " + metaContact.getDisplayName()); UIContactImpl newUIContact; synchronized (metaContact) { newUIContact = MetaContactListSource.getUIContact(metaContact); if (newUIContact == null) { newUIContact = MetaContactListSource.createUIContact(metaContact); } } GuiActivator.getContactList().addContact(newUIContact, uiGroup, true, true); query.setInitialResultCount(resultCount); } else { query.fireQueryEvent(metaContact); } } } // If in the meantime the filtering has been stopped we return here. if (query.isCanceled()) return; Iterator<MetaContactGroup> subgroups = metaGroup.getSubgroups(); while (subgroups.hasNext() && !query.isCanceled()) { MetaContactGroup subgroup = subgroups.next(); if (isMatching(subgroup)) { UIGroup uiGroup; synchronized (subgroup) { uiGroup = MetaContactListSource.getUIGroup(subgroup); if (uiGroup == null) uiGroup = MetaContactListSource.createUIGroup(subgroup); } GuiActivator.getContactList().addGroup(uiGroup, true); addMatching(subgroup, query, resultCount); } } }
/** * Implements the ContactListListener.contactSelected method. * * @param evt the <tt>ContactListEvent</tt> that notified us */ public void contactClicked(ContactListEvent evt) { // We're interested only in two click events. if (evt.getClickCount() < 2) return; UIContact descriptor = evt.getSourceContact(); // We're currently only interested in MetaContacts. if (descriptor.getDescriptor() instanceof MetaContact) { MetaContact metaContact = (MetaContact) descriptor.getDescriptor(); // Searching for the right proto contact to use as default for the // chat conversation. Contact defaultContact = metaContact.getDefaultContact(OperationSetBasicInstantMessaging.class); // do nothing if (defaultContact == null) { defaultContact = metaContact.getDefaultContact(OperationSetSmsMessaging.class); if (defaultContact == null) return; } ProtocolProviderService defaultProvider = defaultContact.getProtocolProvider(); OperationSetBasicInstantMessaging defaultIM = defaultProvider.getOperationSet(OperationSetBasicInstantMessaging.class); ProtocolProviderService protoContactProvider; OperationSetBasicInstantMessaging protoContactIM; boolean isOfflineMessagingSupported = defaultIM != null && !defaultIM.isOfflineMessagingSupported(); if (defaultContact.getPresenceStatus().getStatus() < 1 && (!isOfflineMessagingSupported || !defaultProvider.isRegistered())) { Iterator<Contact> protoContacts = metaContact.getContacts(); while (protoContacts.hasNext()) { Contact contact = protoContacts.next(); protoContactProvider = contact.getProtocolProvider(); protoContactIM = protoContactProvider.getOperationSet(OperationSetBasicInstantMessaging.class); if (protoContactIM != null && protoContactIM.isOfflineMessagingSupported() && protoContactProvider.isRegistered()) { defaultContact = contact; } } } ContactEventHandler contactHandler = mainFrame.getContactHandler(defaultContact.getProtocolProvider()); contactHandler.contactClicked(defaultContact, evt.getClickCount()); } else if (descriptor.getDescriptor() instanceof SourceContact) { SourceContact contact = (SourceContact) descriptor.getDescriptor(); List<ContactDetail> imDetails = contact.getContactDetails(OperationSetBasicInstantMessaging.class); List<ContactDetail> mucDetails = contact.getContactDetails(OperationSetMultiUserChat.class); if (imDetails != null && imDetails.size() > 0) { ProtocolProviderService pps = imDetails.get(0).getPreferredProtocolProvider(OperationSetBasicInstantMessaging.class); GuiActivator.getUIService() .getChatWindowManager() .startChat(contact.getContactAddress(), pps); } else if (mucDetails != null && mucDetails.size() > 0) { ChatRoomWrapper room = GuiActivator.getMUCService().findChatRoomWrapperFromSourceContact(contact); if (room == null) { // lets check by id ProtocolProviderService pps = mucDetails.get(0).getPreferredProtocolProvider(OperationSetMultiUserChat.class); room = GuiActivator.getMUCService() .findChatRoomWrapperFromChatRoomID(contact.getContactAddress(), pps); if (room == null) { GuiActivator.getMUCService() .createChatRoom( contact.getContactAddress(), pps, new ArrayList<String>(), "", false, false, false); } } if (room != null) GuiActivator.getMUCService().openChatRoom(room); } else { List<ContactDetail> smsDetails = contact.getContactDetails(OperationSetSmsMessaging.class); if (smsDetails != null && smsDetails.size() > 0) { GuiActivator.getUIService() .getChatWindowManager() .startChat(contact.getContactAddress(), true); } } } }