Commit 9cbd34fc authored by Robert Bost's avatar Robert Bost

Resolved issue with receiving chat notification when loading history of...

Resolved issue with receiving chat notification when loading history of persistence Conference from server.
parent 14f86fcb
......@@ -215,8 +215,12 @@ public class RoomChat extends AbstractChat {
RosterManager.getInstance().onContactChanged(account, bareAddress);
newAction(resource, subject, ChatAction.subject);
} else {
boolean notify = true;
String packetID = message.getPacketID();
Date delay = Delay.getDelay(message);
if (delay != null) {
notify = false;
}
for (MessageItem messageItem : messages) {
// Search for duplicates
if (packetID != null && packetID.equals(messageItem.getPacketID())) {
......@@ -232,7 +236,7 @@ public class RoomChat extends AbstractChat {
}
updateThreadId(message.getThread());
MessageItem messageItem = newMessage(resource, text, null,
delay, true, true, false, false, true);
delay, true, notify, false, false, true);
messageItem.setPacketID(packetID);
}
} else if (packet instanceof Presence) {
......
/**
* 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.muc;
import com.xabber.android.R;
import com.xabber.android.data.Application;
import com.xabber.android.data.SettingsManager;
import com.xabber.android.data.SettingsManager.ChatsShowStatusChange;
import com.xabber.android.data.account.StatusMode;
import com.xabber.android.data.message.AbstractChat;
import com.xabber.android.data.message.ChatAction;
import com.xabber.android.data.message.MessageItem;
import com.xabber.android.data.roster.RosterManager;
import com.xabber.xmpp.address.Jid;
import com.xabber.xmpp.delay.Delay;
import com.xabber.xmpp.muc.Affiliation;
import com.xabber.xmpp.muc.MUC;
import com.xabber.xmpp.muc.Role;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Message.Type;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smackx.muc.MultiUserChat;
import org.jivesoftware.smackx.packet.MUCUser;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.NoSuchElementException;
/**
* Chat room.
* <p/>
* Warning: We are going to remove SMACK components.
*
* @author alexander.ivanov
*/
public class RoomChat extends AbstractChat {
/**
* Information about occupants for STRING-PREPed resource.
*/
private final Map<String, Occupant> occupants;
/**
* Invited user for the sent packet ID.
*/
private final Map<String, String> invites;
/**
* Joining was requested from the UI.
*/
private boolean requested;
/**
* Nickname used in the room.
*/
private String nickname;
private String password;
private RoomState state;
private String subject;
/**
* SMACK MUC implementation.
*/
private MultiUserChat multiUserChat;
RoomChat(String account, String user, String nickname, String password) {
super(account, user);
this.nickname = nickname;
this.password = password;
requested = false;
state = RoomState.unavailable;
subject = "";
multiUserChat = null;
occupants = new HashMap<>();
invites = new HashMap<>();
}
@Override
public String getTo() {
return user;
}
@Override
public Type getType() {
return Type.groupchat;
}
String getRoom() {
return user;
}
String getNickname() {
return nickname;
}
void setNickname(String nickname) {
this.nickname = nickname;
}
String getPassword() {
return password;
}
void setPassword(String password) {
this.password = password;
}
boolean isRequested() {
return requested;
}
void setRequested(boolean requested) {
this.requested = requested;
}
public RoomState getState() {
return state;
}
void setState(RoomState state) {
this.state = state;
if (!state.inUse()) {
multiUserChat = null;
occupants.clear();
invites.clear();
}
if (state == RoomState.available) {
sendMessages();
}
}
Collection<Occupant> getOccupants() {
return Collections.unmodifiableCollection(occupants.values());
}
String getSubject() {
return subject;
}
MultiUserChat getMultiUserChat() {
return multiUserChat;
}
void setMultiUserChat(MultiUserChat multiUserChat) {
this.multiUserChat = multiUserChat;
}
void putInvite(String packetID, String user) {
invites.put(packetID, user);
}
@Override
protected MessageItem newMessage(String text) {
return newMessage(nickname, text, null, null, false, false, false, false, true);
}
@Override
protected boolean canSendMessage() {
return super.canSendMessage() && state == RoomState.available;
}
@Override
protected boolean notifyAboutMessage() {
return SettingsManager.eventsMessage() == SettingsManager.EventsMessage.chatAndMuc;
}
@Override
protected boolean onPacket(String bareAddress, Packet packet) {
if (!super.onPacket(bareAddress, packet)) {
return false;
}
final String from = packet.getFrom();
final String resource = StringUtils.parseResource(from);
if (packet instanceof Message) {
final Message message = (Message) packet;
if (message.getType() == Message.Type.error) {
String invite = invites.remove(message.getPacketID());
if (invite != null) {
newAction(nickname, invite, ChatAction.invite_error);
}
return true;
}
MUCUser mucUser = MUC.getMUCUserExtension(packet);
if (mucUser != null && mucUser.getDecline() != null) {
onInvitationDeclined(mucUser.getDecline().getFrom(), mucUser.getDecline().getReason());
return true;
}
final String text = message.getBody();
final String subject = message.getSubject();
if (text == null && subject == null) {
return true;
}
if (isSelf(resource)) { // Own message
return true;
}
if (subject != null) {
if (this.subject.equals(subject)) {
return true;
}
this.subject = subject;
RosterManager.getInstance().onContactChanged(account, bareAddress);
newAction(resource, subject, ChatAction.subject);
} else {
String packetID = message.getPacketID();
Date delay = Delay.getDelay(message);
for (MessageItem messageItem : messages) {
// Search for duplicates
if (packetID != null && packetID.equals(messageItem.getPacketID())) {
return true;
}
if (delay != null) {
if (delay.equals(messageItem.getDelayTimestamp())
&& resource.equals(messageItem.getResource())
&& text.equals(messageItem.getText())) {
return true;
}
}
}
updateThreadId(message.getThread());
MessageItem messageItem = newMessage(resource, text, null,
delay, true, true, false, false, true);
messageItem.setPacketID(packetID);
}
} else if (packet instanceof Presence) {
String stringPrep = Jid.getStringPrep(resource);
Presence presence = (Presence) packet;
if (presence.getType() == Presence.Type.available) {
Occupant oldOccupant = occupants.get(stringPrep);
Occupant newOccupant = createOccupant(resource, presence);
occupants.put(stringPrep, newOccupant);
if (oldOccupant == null) {
onAvailable(resource);
RosterManager.getInstance().onContactChanged(account, user);
} else {
boolean changed = false;
if (oldOccupant.getAffiliation() != newOccupant.getAffiliation()) {
changed = true;
onAffiliationChanged(resource, newOccupant.getAffiliation());
}
if (oldOccupant.getRole() != newOccupant.getRole()) {
changed = true;
onRoleChanged(resource, newOccupant.getRole());
}
if (oldOccupant.getStatusMode() != newOccupant.getStatusMode()
|| !oldOccupant.getStatusText().equals(newOccupant.getStatusText())) {
changed = true;
onStatusChanged(resource, newOccupant.getStatusMode(), newOccupant.getStatusText());
}
if (changed) {
RosterManager.getInstance().onContactChanged(account, user);
}
}
} else if (presence.getType() == Presence.Type.unavailable && state == RoomState.available) {
occupants.remove(stringPrep);
MUCUser mucUser = MUC.getMUCUserExtension(presence);
if (mucUser != null && mucUser.getStatus() != null) {
String code = mucUser.getStatus().getCode();
if ("307".equals(code)) {
onKick(resource, mucUser.getItem().getActor());
} else if ("301".equals(code)) {
onBan(resource, mucUser.getItem().getActor());
} else if ("303".equals(code)) {
String newNick = mucUser.getItem().getNick();
if (newNick == null) {
return true;
}
onRename(resource, newNick);
Occupant occupant = createOccupant(newNick, presence);
occupants.put(Jid.getStringPrep(newNick), occupant);
} else if ("321".equals(code)) {
onRevoke(resource, mucUser.getItem().getActor());
}
} else {
onLeave(resource);
}
RosterManager.getInstance().onContactChanged(account, user);
}
}
return true;
}
/**
* @return Whether status change action should be added to the chat history.
*/
private boolean showStatusChange() {
return SettingsManager.chatsShowStatusChange() != ChatsShowStatusChange.never;
}
/**
* @return Whether resource is own nickname.
*/
private boolean isSelf(String resource) {
return Jid.getStringPrep(nickname).equals(Jid.getStringPrep(resource));
}
/**
* Informs that the invitee has declined the invitation.
*/
private void onInvitationDeclined(String from, String reason) {
// TODO
}
/**
* A occupant becomes available.
*/
private void onAvailable(String resource) {
if (isSelf(resource)) {
setState(RoomState.available);
if (isRequested()) {
if (showStatusChange()) {
newMessage(resource, Application.getInstance().getString(
R.string.action_join_complete_to, user),
ChatAction.complete, null, true, true, false, false, true);
}
active = true;
setRequested(false);
} else {
if (showStatusChange()) {
newAction(resource, null, ChatAction.complete);
}
}
} else {
if (state == RoomState.available) {
if (showStatusChange()) {
newAction(resource, null, ChatAction.join);
}
}
}
}
/**
* Warning: this method should be placed with packet provider.
*
* @return New occupant based on presence information.
*/
private Occupant createOccupant(String resource, Presence presence) {
Occupant occupant = new Occupant(resource);
String jid = null;
Affiliation affiliation = Affiliation.none;
Role role = Role.none;
StatusMode statusMode = StatusMode.unavailable;
String statusText = null;
MUCUser mucUser = MUC.getMUCUserExtension(presence);
if (mucUser != null) {
MUCUser.Item item = mucUser.getItem();
if (item != null) {
jid = item.getJid();
try {
affiliation = Affiliation.fromString(item.getAffiliation());
} catch (NoSuchElementException e) {
}
try {
role = Role.fromString(item.getRole());
} catch (NoSuchElementException e) {
}
statusMode = StatusMode.createStatusMode(presence);
statusText = presence.getStatus();
}
}
if (statusText == null) {
statusText = "";
}
occupant.setJid(jid);
occupant.setAffiliation(affiliation);
occupant.setRole(role);
occupant.setStatusMode(statusMode);
occupant.setStatusText(statusText);
return occupant;
}
private void onAffiliationChanged(String resource, Affiliation affiliation) {
}
private void onRoleChanged(String resource, Role role) {
}
private void onStatusChanged(String resource, StatusMode statusMode, String statusText) {
}
/**
* A occupant leaves room.
*/
private void onLeave(String resource) {
if (showStatusChange()) {
newAction(resource, null, ChatAction.leave);
}
if (isSelf(resource)) {
setState(RoomState.waiting);
RosterManager.getInstance().onContactChanged(account, user);
}
}
/**
* A occupant was kicked.
*
*/
private void onKick(String resource, String actor) {
if (showStatusChange()) {
newAction(resource, actor, ChatAction.kick);
}
if (isSelf(resource)) {
MUCManager.getInstance().leaveRoom(account, user);
}
}
/**
* A occupant was banned.
*
*/
private void onBan(String resource, String actor) {
if (showStatusChange()) {
newAction(resource, actor, ChatAction.ban);
}
if (isSelf(resource)) {
MUCManager.getInstance().leaveRoom(account, user);
}
}
/**
* A occupant has changed his nickname in the room.
*
*/
private void onRename(String resource, String newNick) {
if (showStatusChange()) {
newAction(resource, newNick, ChatAction.nickname);
}
}
/**
* A user's membership was revoked from the room
*
*/
private void onRevoke(String resource, String actor) {
if (showStatusChange()) {
newAction(resource, actor, ChatAction.kick);
}
if (isSelf(resource)) {
MUCManager.getInstance().leaveRoom(account, user);
}
}
@Override
protected void onComplete() {
super.onComplete();
if (getState() == RoomState.waiting) {
MUCManager.getInstance().joinRoom(account, user, false);
}
}
@Override
protected void onDisconnect() {
super.onDisconnect();
if (state != RoomState.unavailable) {
setState(RoomState.waiting);
}
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment