/*
*
* Copyright (C) 2007-2015 Licensed to the Comunes Association (CA) under
* one or more contributor license agreements (see COPYRIGHT for details).
* The CA licenses this file to you under the GNU Affero General Public
* License version 3, (the "License"); you may not use this file except in
* compliance with the License. This file is part of kune.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package cc.kune.chat.client;
import static com.google.gwt.query.client.GQuery.$;
import java.util.Date;
import br.com.rpa.client._paperelements.PaperIconButton;
import cc.kune.chat.client.ShowChatDialogEvent.ShowChatDialogHandler;
import cc.kune.chat.client.ToggleShowChatDialogEvent.ToggleShowChatDialogHandler;
import cc.kune.chat.client.snd.KuneSoundManager;
import cc.kune.common.client.actions.AbstractExtendedAction;
import cc.kune.common.client.actions.ActionEvent;
import cc.kune.common.client.actions.KeyStroke;
import cc.kune.common.client.actions.Shortcut;
import cc.kune.common.client.log.Log;
import cc.kune.common.client.notify.NotifyUser;
import cc.kune.common.client.shortcuts.GlobalShortcutRegister;
import cc.kune.common.client.tooltip.Tooltip;
import cc.kune.common.client.utils.WindowUtils;
import cc.kune.common.shared.i18n.I18nTranslationService;
import cc.kune.common.shared.utils.SimpleResponseCallback;
import cc.kune.common.shared.utils.TextUtils;
import cc.kune.core.client.events.AppStartEvent;
import cc.kune.core.client.events.AppStopEvent;
import cc.kune.core.client.events.AvatarChangedEvent;
import cc.kune.core.client.events.UserSignInEvent;
import cc.kune.core.client.events.UserSignInEvent.UserSignInHandler;
import cc.kune.core.client.events.UserSignOutEvent;
import cc.kune.core.client.events.UserSignOutEvent.UserSignOutHandler;
import cc.kune.core.client.resources.CoreResources;
import cc.kune.core.client.services.ClientFileDownloadUtils;
import cc.kune.core.client.sitebar.SitebarActions;
import cc.kune.core.client.state.Session;
import cc.kune.core.shared.dto.UserInfoDTO;
import cc.kune.gspace.client.armor.GSpaceArmor;
import cc.kune.polymer.client.PolymerId;
import cc.kune.polymer.client.PolymerUtils;
import com.calclab.emite.browser.client.AutoConfig;
import com.calclab.emite.core.client.xmpp.session.XmppSession;
import com.calclab.emite.core.client.xmpp.stanzas.XmppURI;
import com.calclab.emite.im.client.chat.ChatManager;
import com.calclab.emite.im.client.presence.PresenceManager;
import com.calclab.emite.im.client.roster.RosterItem;
import com.calclab.emite.im.client.roster.SubscriptionHandler;
import com.calclab.emite.im.client.roster.SubscriptionHandler.Behaviour;
import com.calclab.emite.im.client.roster.SubscriptionManager;
import com.calclab.emite.im.client.roster.SubscriptionState;
import com.calclab.emite.im.client.roster.XmppRoster;
import com.calclab.emite.im.client.roster.events.SubscriptionRequestReceivedEvent;
import com.calclab.emite.im.client.roster.events.SubscriptionRequestReceivedHandler;
import com.calclab.emite.xep.avatar.client.AvatarManager;
import com.calclab.emite.xep.chatstate.client.StateManager;
import com.calclab.emite.xep.muc.client.Room;
import com.calclab.emite.xep.muc.client.RoomManager;
import com.calclab.emite.xep.muc.client.subject.RoomSubject;
import com.calclab.emite.xep.mucchatstate.client.MUCChatStateManager;
import com.calclab.emite.xep.mucdisco.client.RoomDiscoveryManager;
import com.calclab.emite.xep.storage.client.PrivateStorageManager;
import com.calclab.hablar.chat.client.HablarChat;
import com.calclab.hablar.client.HablarConfig;
import com.calclab.hablar.core.client.Hablar;
import com.calclab.hablar.core.client.HablarCore;
import com.calclab.hablar.core.client.browser.BrowserFocusHandler;
import com.calclab.hablar.dock.client.HablarDock;
import com.calclab.hablar.editbuddy.client.HablarEditBuddy;
import com.calclab.hablar.group.client.HablarGroup;
import com.calclab.hablar.groupchat.client.HablarGroupChat;
import com.calclab.hablar.icons.client.AvatarProviderRegistry;
import com.calclab.hablar.openchat.client.HablarOpenChat;
import com.calclab.hablar.rooms.client.HablarRooms;
import com.calclab.hablar.roster.client.HablarRoster;
import com.calclab.hablar.roster.client.page.RosterPage;
import com.calclab.hablar.signals.client.sound.HablarSoundSignals;
import com.calclab.hablar.user.client.HablarUser;
import com.calclab.hablar.usergroups.client.HablarUserGroups;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.UIObject;
import com.google.gwt.user.client.ui.Widget;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.web.bindery.event.shared.EventBus;
// TODO: Auto-generated Javadoc
/**
* The Class ChatClientDefault.
*
* @author vjrj@ourproject.org (Vicente J. Ruiz Jurado)
*/
public class ChatClientDefault implements ChatClient {
/**
* The Class ChatClientAction.
*
* @author vjrj@ourproject.org (Vicente J. Ruiz Jurado)
*/
public class ChatClientAction extends AbstractExtendedAction {
@Override
public void actionPerformed(final ActionEvent event) {
kuneEventBus.fireEvent(new ToggleShowChatDialogEvent());
}
}
/** The Constant CHAT_TITLE. */
private static final String CHAT_TITLE = "Chat ;)";
/** The action. */
private final ChatClientAction action;
private final GSpaceArmor armor;
/** The avatar config. */
private final Provider<KuneChatAvatarConfig> avatarConfig;
/** The avatar manager. */
private final Provider<AvatarManager> avatarManager;
/** The avatar provider registry. */
private final Provider<AvatarProviderRegistry> avatarProviderRegistry;
private final Element chatDiv;
private PaperIconButton chatIcon;
/** The chat manager. */
private final Provider<ChatManager> chatManager;
/** The chat options. */
private final ChatOptions chatOptions;
/** The down utils. */
private final ClientFileDownloadUtils downUtils;
private boolean emiteInit;
/** The i18n. */
private final I18nTranslationService i18n;
/** The kune event bus. */
private final EventBus kuneEventBus;
/** The muc chat state manager. */
private final Provider<MUCChatStateManager> mucChatStateManager;
/** The presence manager. */
private final Provider<PresenceManager> presenceManager;
/** The private storage manager. */
private final Provider<PrivateStorageManager> privateStorageManager;
/** The res. */
private final CoreResources res;
/** The room discovery manager. */
private final Provider<RoomDiscoveryManager> roomDiscoveryManager;
/** The room manager. */
private final Provider<RoomManager> roomManager;
/** The roster. */
private final Provider<XmppRoster> roster;
/** The session. */
private final Session session;
/** The shorcut register. */
private final GlobalShortcutRegister shorcutRegister;
/** The subscription handler. */
private final Provider<SubscriptionHandler> subscriptionHandler;
/** The subscription manager. */
private final Provider<SubscriptionManager> subscriptionManager;
/** The xmpp session. */
private final Provider<XmppSession> xmppSession;
/** The xmpp state manager. */
private final Provider<StateManager> xmppStateManager;
/**
* Instantiates a new chat client default.
*
* @param kuneEventBus
* the kune event bus
* @param i18n
* the i18n
* @param siteActions
* the site actions
* @param session
* the session
* @param res
* the res
* @param downUtils
* the down utils
* @param shorcutRegister
* the shorcut register
* @param chatOptions
* the chat options
* @param chatResources
* the chat resources
* @param xmppSession
* the xmpp session
* @param roster
* the roster
* @param chatManager
* the chat manager
* @param roomManager
* the room manager
* @param avatarManager
* the avatar manager
* @param subscriptionManager
* the subscription manager
* @param presenceManager
* the presence manager
* @param xmppStateManager
* the xmpp state manager
* @param roomDiscoveryManager
* the room discovery manager
* @param mucChatStateManager
* the muc chat state manager
* @param avatarProviderRegistry
* the avatar provider registry
* @param privateStorageManager
* the private storage manager
* @param subscriptionHandler
* the subscription handler
* @param avatarConfig
* the avatar config
*/
@Inject
public ChatClientDefault(final EventBus kuneEventBus, final I18nTranslationService i18n,
final SitebarActions siteActions, final Session session, final CoreResources res,
final ClientFileDownloadUtils downUtils, final GlobalShortcutRegister shorcutRegister,
final ChatOptions chatOptions, final Provider<XmppSession> xmppSession,
final Provider<XmppRoster> roster, final Provider<ChatManager> chatManager,
final Provider<RoomManager> roomManager, final Provider<AvatarManager> avatarManager,
final Provider<SubscriptionManager> subscriptionManager,
final Provider<PresenceManager> presenceManager, final Provider<StateManager> xmppStateManager,
final Provider<RoomDiscoveryManager> roomDiscoveryManager,
final Provider<MUCChatStateManager> mucChatStateManager,
final Provider<AvatarProviderRegistry> avatarProviderRegistry,
final Provider<PrivateStorageManager> privateStorageManager,
final Provider<SubscriptionHandler> subscriptionHandler,
final Provider<KuneChatAvatarConfig> avatarConfig, final AutoConfig autoconfig,
final GSpaceArmor armor) {
this.kuneEventBus = kuneEventBus;
this.i18n = i18n;
this.res = res;
this.downUtils = downUtils;
this.presenceManager = presenceManager;
this.xmppStateManager = xmppStateManager;
this.roomDiscoveryManager = roomDiscoveryManager;
this.mucChatStateManager = mucChatStateManager;
this.avatarProviderRegistry = avatarProviderRegistry;
this.privateStorageManager = privateStorageManager;
this.subscriptionHandler = subscriptionHandler;
this.session = session;
this.shorcutRegister = shorcutRegister;
this.chatOptions = chatOptions;
this.xmppSession = xmppSession;
this.roster = roster;
this.chatManager = chatManager;
this.roomManager = roomManager;
this.avatarManager = avatarManager;
this.subscriptionManager = subscriptionManager;
this.avatarConfig = avatarConfig;
this.armor = armor;
chatDiv = armor.getElement(PolymerId.CHAT_PANEL);
action = new ChatClientAction();
session.onAppStart(true, new AppStartEvent.AppStartHandler() {
@Override
public void onAppStart(final AppStartEvent event) {
chatOptions.domain = event.getInitData().getChatDomain();
chatOptions.httpBase = event.getInitData().getChatHttpBase();
chatOptions.roomHost = event.getInitData().getChatRoomHost();
checkChatDomain(chatOptions.domain);
session.onUserSignIn(true, new UserSignInHandler() {
@Override
public void onUserSignIn(final UserSignInEvent event) {
doLogin();
}
});
session.onUserSignOut(true, new UserSignOutHandler() {
@Override
public void onUserSignOut(final UserSignOutEvent event) {
createActionIfNeeded();
chatIcon.setVisible(false);
logout();
}
});
kuneEventBus.addHandler(ShowChatDialogEvent.getType(), new ShowChatDialogHandler() {
@Override
public void onShowChatDialog(final ShowChatDialogEvent event) {
createActionIfNeeded();
showDialog(event.show);
}
});
kuneEventBus.addHandler(ToggleShowChatDialogEvent.getType(), new ToggleShowChatDialogHandler() {
@Override
public void onToggleShowChatDialog(final ToggleShowChatDialogEvent event) {
toggleShowDialog();
}
});
kuneEventBus.addHandler(AvatarChangedEvent.getType(),
new AvatarChangedEvent.AvatarChangedHandler() {
@Override
public void onAvatarChanged(final AvatarChangedEvent event) {
setAvatar(event.getPhotoBinary());
}
});
}
});
kuneEventBus.addHandler(AppStopEvent.getType(), new AppStopEvent.AppStopHandler() {
@Override
public void onAppStop(final AppStopEvent event) {
logout();
}
});
}
/*
* (non-Javadoc)
*
* @see
* cc.kune.core.client.contacts.SimpleContactManager#addNewBuddy(java.lang
* .String)
*/
@Override
public void addNewBuddy(final String shortName) {
roster.get().requestAddItem(uriFrom(shortName), shortName);
}
/*
* (non-Javadoc)
*
* @see
* cc.kune.core.client.contacts.SimpleContactManager#chat(java.lang.String)
*/
@Override
public void chat(final String shortName) {
chat(uriFrom(shortName));
}
/*
* (non-Javadoc)
*
* @see
* cc.kune.chat.client.ChatClient#chat(com.calclab.emite.core.client.xmpp.
* stanzas.XmppURI)
*/
@Override
public void chat(final XmppURI jid) {
chatManager.get().open(jid);
}
// Put this in Panel object
/**
* Check chat domain.
*
* @param chatDomain
* the chat domain
*/
private void checkChatDomain(final String chatDomain) {
final String httpDomain = WindowUtils.getHostName();
if (!chatDomain.equals(httpDomain)) {
Log.warn("Your http domain (" + httpDomain + ") is different from the chat domain (" + chatDomain
+ "). This will cause problems with the chat functionality. "
+ "Please check kune.properties on the server.");
}
}
/**
* Creates the action if needed.
*/
private void createActionIfNeeded() {
if (chatIcon == null) {
chatIcon = PaperIconButton.wrap("sitebar_chat_icon");
chatIcon.addClickHandler(new ClickHandler() {
@Override
public void onClick(final ClickEvent event) {
action.actionPerformed(null);
}
});
chatIcon.getElement().setId(PolymerId.CHAT_SITEBAR_ICON.getId());
chatIcon.setText(i18n.t(CHAT_TITLE));
Tooltip.to(chatIcon, i18n.t("Show/hide the chat window"));
final KeyStroke shortcut = Shortcut.getShortcut(false, true, false, false, Character.valueOf('C'));
shorcutRegister.put(shortcut, action);
action.setShortcut(shortcut);
chatIcon.setVisible(session.isLogged());
}
}
/**
* Creates the dialog.
*
* @param widget
* the widget
* @param htmlConfig
* the html config
*/
private void createDialog(final KuneHablarWidget widget, final CustomHtmlConfig htmlConfig) {
widget.addStyleName("k-chat-panel");
armor.wrapDiv(PolymerId.CHAT_PANEL).add(widget);
}
/**
* Creates the dialog if needed.
*/
private void createDialogIfNeeded() {
if (!emiteInit) {
// dialog.getItem(0).getFocusSupport().setIgnore(true);
initEmite();
emiteInit = true;
}
}
/*
* (non-Javadoc)
*
* @see cc.kune.chat.client.ChatClient#doLogin()
*/
@Override
public void doLogin() {
assert session.getCurrentUserInfo() != null;
doLogin(session.getCurrentUserInfo(), session.getUserHash());
}
/**
* Do login.
*
* @param user
* the user
* @param tokenOrPassword
* the token or password
*/
private void doLogin(final UserInfoDTO user, final String tokenOrPassword) {
createActionIfNeeded();
createDialogIfNeeded();
chatOptions.username = user.getChatName();
chatOptions.passwd = tokenOrPassword;
chatOptions.resource = "emite-" + new Date().getTime() + "-kune";
chatOptions.useruri = XmppURI.uri(chatOptions.username, chatOptions.domain, chatOptions.resource);
createActionIfNeeded();
createDialogIfNeeded();
chatIcon.setVisible(true);
showDialog(false);
login(chatOptions.useruri, chatOptions.passwd);
}
/**
* Inits the emite.
*/
private void initEmite() {
// Adapted from HablarHtml.java
BrowserFocusHandler.getInstance();
final HablarConfig config = HablarConfig.getFromMeta();
final CustomHtmlConfig htmlConfig = CustomHtmlConfig.getFromMeta();
config.dockConfig.headerSize = 0;
config.dockConfig.rosterWidth = 150;
config.dockConfig.rosterDock = "left";
final KuneHablarWidget widget = new KuneHablarWidget(config.layout, config.tabHeaderSize);
final Hablar hablar = widget.getHablar();
avatarProviderRegistry.get().put("kune-avatars", avatarConfig.get());
new HablarCore(hablar);
new HablarChat(hablar, config.chatConfig, roster.get(), chatManager.get(), xmppStateManager.get(),
avatarProviderRegistry.get());
new HablarRooms(hablar, config.roomsConfig, xmppSession.get(), roster.get(), roomManager.get(),
roomDiscoveryManager.get(), mucChatStateManager.get(), avatarProviderRegistry.get());
new HablarGroupChat(hablar, config.roomsConfig, xmppSession.get(), roster.get(), chatManager.get(),
roomManager.get(), avatarProviderRegistry.get());
new HablarDock(hablar, config.dockConfig);
new HablarUser(hablar, xmppSession.get(), presenceManager.get(), privateStorageManager.get());
final HablarRoster hablarRoster = new HablarRoster(hablar, config.rosterConfig, xmppSession.get(),
roster.get(), chatManager.get(), subscriptionHandler.get());
final RosterPage rosterPage = hablarRoster.getRosterPage();
new HablarOpenChat(hablar, xmppSession.get(), roster.get(), chatManager.get());
new HablarEditBuddy(hablar, roster.get());
new HablarUserGroups(rosterPage, hablar, roster.get());
new HablarGroup(hablar, xmppSession.get(), roster.get(), avatarProviderRegistry.get());
hablarRoster.addLowPriorityActions();
new KuneHablarSignals(kuneEventBus, xmppSession.get(), hablar, action, privateStorageManager.get(),
i18n, downUtils, chatIcon);
new HablarSoundSignals(hablar);
// if (htmlConfig.hasLogger) {
// new HablarConsole(hablar, ginjector.getXmppConnection(), session);
// }
//
// if (htmlConfig.hasLogin) {
// new HablarLogin(hablar, LoginConfig.getFromMeta(), session);
// }
new KuneSoundManager(kuneEventBus);
createDialog(widget, htmlConfig);
subscriptionHandler.get().setBehaviour(Behaviour.none);
subscriptionManager.get().addSubscriptionRequestReceivedHandler(
new SubscriptionRequestReceivedHandler() {
@Override
public void onSubscriptionRequestReceived(final SubscriptionRequestReceivedEvent event) {
final XmppURI uri = event.getFrom();
final String nick = event.getNick();
NotifyUser.askConfirmation(res.question32(), i18n.t("Confirm new buddy"), i18n.t(
"[%s] had added you as a buddy. Do you want to add him/her also?",
uri.getJID().toString()), new SimpleResponseCallback() {
@Override
public void onCancel() {
subscriptionManager.get().refuseSubscriptionRequest(uri.getJID());
}
@Override
public void onSuccess() {
subscriptionManager.get().approveSubscriptionRequest(uri.getJID(), nick);
}
});
}
});
}
/*
* (non-Javadoc)
*
* @see
* cc.kune.core.client.contacts.SimpleContactManager#isBuddy(java.lang.String)
*/
@Override
public boolean isBuddy(final String shortName) {
return isBuddy(uriFrom(shortName));
}
/*
* (non-Javadoc)
*
* @see
* cc.kune.chat.client.ChatClient#isBuddy(com.calclab.emite.core.client.xmpp
* .stanzas.XmppURI)
*/
@Override
public boolean isBuddy(final XmppURI jid) {
if (roster.get().isRosterReady()) {
final RosterItem rosterItem = roster.get().getItemByJID(jid);
if (rosterItem != null && rosterItem.getSubscriptionState().equals(SubscriptionState.both)) {
return true;
}
}
return false;
}
/*
* (non-Javadoc)
*
* @see cc.kune.chat.client.ChatClient#isXmppLoggedIn()
*/
@Override
public boolean isXmppLoggedIn() {
return xmppSession.get().isReady();
}
/*
* (non-Javadoc)
*
* @see cc.kune.chat.client.ChatClient#joinRoom(java.lang.String,
* java.lang.String)
*/
@Override
public Room joinRoom(final String roomName, final String userAlias) {
return joinRoom(roomName, null, userAlias);
}
/*
* (non-Javadoc)
*
* @see cc.kune.chat.client.ChatClient#joinRoom(java.lang.String,
* java.lang.String, java.lang.String)
*/
@Override
public Room joinRoom(final String roomName, final String subject, final String userAlias) {
Room room = null;
if (xmppSession.get().isReady()) {
final XmppURI roomURI = XmppURI.uri(roomName + "@" + chatOptions.roomHost + "/"
+ chatOptions.username);
room = roomManager.get().open(roomURI, roomManager.get().getDefaultHistoryOptions());
if (TextUtils.notEmpty(subject)) {
RoomSubject.requestSubjectChange(room, subject);
}
} else {
NotifyUser.error(i18n.t("Error"), i18n.t("In order to join a chatroom you need to be 'online'"),
true);
}
return room;
}
/*
* (non-Javadoc)
*
* @see
* cc.kune.chat.client.ChatClient#login(com.calclab.emite.core.client.xmpp
* .stanzas.XmppURI, java.lang.String)
*/
@Override
public void login(final XmppURI uri, final String passwd) {
xmppSession.get().login(uri, passwd);
}
/*
* (non-Javadoc)
*
* @see cc.kune.chat.client.ChatClient#loginIfNecessary()
*/
@Override
public boolean loginIfNecessary() {
if (!isXmppLoggedIn() && session.isLogged()) {
doLogin();
return true;
}
return false;
}
/*
* (non-Javadoc)
*
* @see cc.kune.chat.client.ChatClient#logout()
*/
@Override
public void logout() {
// if (dialogVisible()) {
// // dialog.hide();
// }
if (isXmppLoggedIn()) {
xmppSession.get().logout();
}
}
/*
* (non-Javadoc)
*
* @see cc.kune.chat.client.ChatClient#roomUriFrom(java.lang.String)
*/
@Override
public XmppURI roomUriFrom(final String shortName) {
return XmppURI.jid(shortName + "@" + chatOptions.roomHost);
}
/*
* (non-Javadoc)
*
* @see cc.kune.chat.client.ChatClient#setAvatar(java.lang.String)
*/
@Override
public void setAvatar(final String photoBinary) {
avatarManager.get().setVCardAvatar(photoBinary);
}
/*
* (non-Javadoc)
*
* @see cc.kune.chat.client.ChatClient#show()
*/
@Override
public void show() {
// PolymerUtils.setBeatAnimation(PolymerId.CHAT_PANEL.getId(), true);
showDialog(true);
}
/**
* Show dialog.
*
* @param show
* the show
*/
private void showDialog(final boolean show) {
Log.info("Show dialog: " + show);
if (session.isLogged()) {
createDialogIfNeeded();
if (show) {
PolymerUtils.setDrawerSelected();
chatDiv.getStyle().setDisplay(Display.BLOCK);
$(".searchPanelWidget").css("bottom", "50%");
} else {
PolymerUtils.setMainSelected();
chatDiv.getStyle().setDisplay(Display.NONE);
$(".searchPanelWidget").css("bottom", "0px");
}
}
}
/**
* Toggle show dialog.
*/
private void toggleShowDialog() {
Log.info("Toggle!");
final Boolean isVisible = UIObject.isVisible(chatDiv) && !PolymerUtils.isMainSelected();
showDialog(!isVisible);
}
/*
* (non-Javadoc)
*
* @see cc.kune.chat.client.ChatClient#uriFrom(java.lang.String)
*/
@Override
public XmppURI uriFrom(final String shortName) {
return chatOptions.uriFrom(shortName);
}
}