/**
* Copyright (c) 2013, Redsolution LTD. All rights reserved.
*
* This file is part of Xabber project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License, Version 3.
*
* Xabber 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License,
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
package com.xabber.android.data.extension.attention;
import android.media.AudioManager;
import android.net.Uri;
import com.xabber.android.R;
import com.xabber.android.data.Application;
import com.xabber.android.data.NetworkException;
import com.xabber.android.data.OnLoadListener;
import com.xabber.android.data.SettingsManager;
import com.xabber.android.data.account.AccountItem;
import com.xabber.android.data.account.AccountManager;
import com.xabber.android.data.connection.ConnectionItem;
import com.xabber.android.data.connection.StanzaSender;
import com.xabber.android.data.connection.listeners.OnPacketListener;
import com.xabber.android.data.entity.AccountJid;
import com.xabber.android.data.entity.UserJid;
import com.xabber.android.data.extension.capability.CapabilitiesManager;
import com.xabber.android.data.log.LogManager;
import com.xabber.android.data.message.AbstractChat;
import com.xabber.android.data.message.ChatAction;
import com.xabber.android.data.message.MessageManager;
import com.xabber.android.data.message.RegularChat;
import com.xabber.android.data.notification.EntityNotificationProvider;
import com.xabber.android.data.notification.NotificationManager;
import com.xabber.android.data.roster.RosterManager;
import org.jivesoftware.smack.ConnectionCreationListener;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPConnectionRegistry;
import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smackx.attention.packet.AttentionExtension;
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
import org.jxmpp.jid.Jid;
import org.jxmpp.jid.parts.Resourcepart;
/**
* XEP-0224: Attention.
*
* @author alexander.ivanov
*/
public class AttentionManager implements OnPacketListener, OnLoadListener {
@SuppressWarnings("WeakerAccess")
final static Object enabledLock;
private static AttentionManager instance;
static {
enabledLock = new Object();
XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() {
@Override
public void connectionCreated(final XMPPConnection connection) {
synchronized (enabledLock) {
if (SettingsManager.chatsAttention())
ServiceDiscoveryManager.getInstanceFor(connection).addFeature(AttentionExtension.NAMESPACE);
}
}
});
}
private final EntityNotificationProvider<AttentionRequest> attentionRequestProvider = new EntityNotificationProvider<AttentionRequest>(
R.drawable.ic_stat_error) {
@Override
public Uri getSound() {
return SettingsManager.chatsAttentionSound();
}
@Override
public int getStreamType() {
return AudioManager.STREAM_RING;
}
};
public static AttentionManager getInstance() {
if (instance == null) {
instance = new AttentionManager();
}
return instance;
}
private AttentionManager() {
}
public void onSettingsChanged() {
synchronized (enabledLock) {
for (AccountJid account : AccountManager.getInstance().getEnabledAccounts()) {
AccountItem accountItem = AccountManager.getInstance().getAccount(account);
if (accountItem == null) {
continue;
}
ServiceDiscoveryManager manager = ServiceDiscoveryManager.getInstanceFor(accountItem.getConnection());
if (manager == null) {
continue;
}
boolean contains = false;
for (String feature : manager.getFeatures()) {
if (AttentionExtension.NAMESPACE.equals(feature)) {
contains = true;
}
}
if (SettingsManager.chatsAttention() == contains) {
continue;
}
if (SettingsManager.chatsAttention()) {
manager.addFeature(AttentionExtension.NAMESPACE);
} else {
manager.removeFeature(AttentionExtension.NAMESPACE);
}
}
AccountManager.getInstance().resendPresence();
}
}
@Override
public void onLoad() {
Application.getInstance().runOnUiThread(new Runnable() {
@Override
public void run() {
onLoaded();
}
});
}
@SuppressWarnings("WeakerAccess")
void onLoaded() {
NotificationManager.getInstance().registerNotificationProvider(
attentionRequestProvider);
}
@Override
public void onStanza(ConnectionItem connection, Stanza stanza) {
if (!(stanza instanceof Message)) {
return;
}
if (!SettingsManager.chatsAttention()) {
return;
}
final AccountJid account = connection.getAccount();
UserJid from;
try {
from = UserJid.from(stanza.getFrom());
} catch (UserJid.UserJidCreateException e) {
e.printStackTrace();
return;
}
for (ExtensionElement packetExtension : stanza.getExtensions()) {
if (packetExtension instanceof AttentionExtension) {
MessageManager.getInstance().openChat(account, from);
MessageManager.getInstance()
.getOrCreateChat(account, from)
.newAction(null, null, ChatAction.attention_requested);
attentionRequestProvider.add(new AttentionRequest(account, from.getBareUserJid()), true);
}
}
}
public void sendAttention(AccountJid account, UserJid user) throws NetworkException {
AbstractChat chat = MessageManager.getInstance().getOrCreateChat(account, user);
if (!(chat instanceof RegularChat)) {
throw new NetworkException(R.string.ENTRY_IS_NOT_FOUND);
}
Jid to = chat.getTo();
if (to.getResourceOrNull() == null || to.getResourceOrNull().equals(Resourcepart.EMPTY)) {
final Presence presence = RosterManager.getInstance().getPresence(account, user);
if (presence == null) {
to = null;
} else {
to = presence.getFrom();
}
}
if (to == null) {
throw new NetworkException(R.string.ENTRY_IS_NOT_AVAILABLE);
}
if (!CapabilitiesManager.getInstance().isFeatureSupported(to, AttentionExtension.NAMESPACE)) {
throw new NetworkException(R.string.ATTENTION_IS_NOT_SUPPORTED);
}
Message message = new Message();
message.setTo(to);
message.setType(Message.Type.headline);
message.addExtension(new AttentionExtension());
StanzaSender.sendStanza(account, message);
chat.newAction(null, null, ChatAction.attention_called);
}
public void removeAccountNotifications(AccountJid accountJid, UserJid userJid) {
LogManager.i(this, "removeAccountNotifications " + userJid);
attentionRequestProvider.remove(accountJid, userJid.getBareUserJid());
}
}