/*
* Copyright 2015 OpenMarket Ltd
* Copyright 2017 Vector Creations Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.matrix.androidsdk.data;
import android.text.TextUtils;
import org.matrix.androidsdk.util.Log;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import org.matrix.androidsdk.rest.model.Event;
import org.matrix.androidsdk.rest.model.EventContent;
import org.matrix.androidsdk.rest.model.Message;
import org.matrix.androidsdk.rest.model.RoomMember;
/**
* Stores summarised information about the room.
*/
public class RoomSummary implements java.io.Serializable {
private static final String LOG_TAG = "RoomSummary";
private static final long serialVersionUID = -3683013938626566489L;
private String mRoomId = null;
private String mName = null;
private String mTopic = null;
private Event mLatestReceivedEvent = null;
// the room state is only used to check
// 1- the invitation status
// 2- the members display name
private transient RoomState mLatestRoomState = null;
// defines the late
private String mLatestReadEventId;
private int mUnreadEventsCount;
// invitation status
// retrieved at initial sync
// the roomstate is not always known
private String mInviterUserId = null;
// retrieved from the roomState
private boolean mIsInvited = false;
private String mInviterName = null;
private String mMatrixId = null;
private boolean mIsHighlighted = false;
public RoomSummary() {
}
/**
* Create a room summary
*
* @param roomId the room id
* @param name the room display name
* @param topic the topic
* @param event the latest received event
*/
public RoomSummary(String roomId, String name, String topic, Event event) {
mLatestReceivedEvent = event;
mRoomId = roomId;
mName = name;
mTopic = topic;
mLatestReadEventId = null;
}
/**
* Test if the event can be summarized.
* Some event types are not yet supported.
*
* @param event the event to test.
* @return true if the event can be summarized
*/
public static boolean isSupportedEvent(Event event) {
String type = event.getType();
boolean isSupported = false;
// check if the msgtype is supported
if (TextUtils.equals(Event.EVENT_TYPE_MESSAGE, type)) {
try {
JsonObject eventContent = event.getContentAsJsonObject();
String msgType = "";
JsonElement element = eventContent.get("msgtype");
if (null != element) {
msgType = element.getAsString();
}
isSupported = TextUtils.equals(msgType, Message.MSGTYPE_TEXT) ||
TextUtils.equals(msgType, Message.MSGTYPE_EMOTE) ||
TextUtils.equals(msgType, Message.MSGTYPE_NOTICE) ||
TextUtils.equals(msgType, Message.MSGTYPE_IMAGE) ||
TextUtils.equals(msgType, Message.MSGTYPE_AUDIO) ||
TextUtils.equals(msgType, Message.MSGTYPE_VIDEO) ||
TextUtils.equals(msgType, Message.MSGTYPE_FILE);
if (!isSupported && !TextUtils.isEmpty(msgType)) {
Log.e(LOG_TAG, "isSupportedEvent : Unsupported msg type " + msgType);
}
} catch (Exception e) {
Log.e(LOG_TAG, "isSupportedEvent failed " + e.getMessage());
}
} else if (TextUtils.equals(Event.EVENT_TYPE_MESSAGE_ENCRYPTED, type)) {
isSupported = event.hasContentFields();
} else if (!TextUtils.isEmpty(type)) {
isSupported = TextUtils.equals(Event.EVENT_TYPE_STATE_ROOM_TOPIC, type) ||
TextUtils.equals(Event.EVENT_TYPE_MESSAGE_ENCRYPTED, type) ||
TextUtils.equals(Event.EVENT_TYPE_MESSAGE_ENCRYPTION, type) ||
TextUtils.equals(Event.EVENT_TYPE_STATE_ROOM_NAME, type) ||
TextUtils.equals(Event.EVENT_TYPE_STATE_ROOM_MEMBER, type) ||
TextUtils.equals(Event.EVENT_TYPE_STATE_ROOM_CREATE, type) ||
TextUtils.equals(Event.EVENT_TYPE_STATE_HISTORY_VISIBILITY, type) ||
TextUtils.equals(Event.EVENT_TYPE_STATE_ROOM_THIRD_PARTY_INVITE, type) ||
(event.isCallEvent() && !Event.EVENT_TYPE_CALL_CANDIDATES.equals(type));
if (!isSupported) {
// some events are known to be never traced
// avoid warning when it is not required.
if (!TextUtils.equals(Event.EVENT_TYPE_TYPING, type) &&
!TextUtils.equals(Event.EVENT_TYPE_STATE_ROOM_POWER_LEVELS, type) &&
!TextUtils.equals(Event.EVENT_TYPE_STATE_ROOM_JOIN_RULES, type) &&
!TextUtils.equals(Event.EVENT_TYPE_STATE_CANONICAL_ALIAS, type) &&
!TextUtils.equals(Event.EVENT_TYPE_STATE_ROOM_ALIASES, type)
) {
Log.e(LOG_TAG, "isSupportedEvent : Unsupported event type " + type);
}
} else if (TextUtils.equals(Event.EVENT_TYPE_STATE_ROOM_MEMBER, type)) {
JsonObject eventContentAsJsonObject = event.getContentAsJsonObject();
if (null != eventContentAsJsonObject) {
if (0 == eventContentAsJsonObject.entrySet().size()) {
isSupported = false;
Log.d(LOG_TAG, "isSupportedEvent : room member with no content is not supported");
} else {
// do not display the avatar / display name update
EventContent prevEventContent = event.getPrevContent();
EventContent eventContent = event.getEventContent();
String membership = null;
String preMembership = null;
if (null != prevEventContent) {
membership = eventContent.membership;
}
if (null != prevEventContent) {
preMembership = prevEventContent.membership;
}
isSupported = (null == membership) || !TextUtils.equals(membership, preMembership);
if (!isSupported) {
Log.d(LOG_TAG, "isSupportedEvent : do not support avatar display name update");
}
}
}
}
}
return isSupported;
}
/**
* @return the matrix id
*/
public String getMatrixId() {
return mMatrixId;
}
/**
* @return the room id
*/
public String getRoomId() {
return mRoomId;
}
/**
* Compute the room summary display name.
*
* @return the room summary display name.
*/
public String getRoomName() {
String name = mName;
// when invited, the only received message should be the invitation one
if (isInvited()) {
if (null != mLatestReceivedEvent) {
String inviterName;
// try to retrieve a display name
if (null != mLatestRoomState) {
inviterName = mLatestRoomState.getMemberName(mLatestReceivedEvent.getSender());
} else {
// use the stored one
inviterName = mInviterName;
}
if (null != inviterName) {
name = inviterName;
}
}
}
return name;
}
/**
* @return the topic.
*/
public String getRoomTopic() {
return mTopic;
}
/**
* @return the room summary event.
*/
public Event getLatestReceivedEvent() {
return mLatestReceivedEvent;
}
/**
* @return the dedicated room state.
*/
public RoomState getLatestRoomState() {
return mLatestRoomState;
}
/**
* @return true if the current user is invited
*/
public boolean isInvited() {
return mIsInvited || (mInviterUserId != null);
}
/**
* @return the inviter user id.
*/
public String getInviterUserId() {
return mInviterUserId;
}
/**
* Update the linked matrix id.
*
* @param matrixId the new matrix id.
*/
public void setMatrixId(String matrixId) {
mMatrixId = matrixId;
}
/**
* Set the room's {@link org.matrix.androidsdk.rest.model.Event#EVENT_TYPE_STATE_ROOM_TOPIC}.
*
* @param topic The topic
* @return This summary for chaining calls.
*/
public RoomSummary setTopic(String topic) {
mTopic = topic;
return this;
}
/**
* Set the room's {@link org.matrix.androidsdk.rest.model.Event#EVENT_TYPE_STATE_ROOM_NAME}.
*
* @param name The name
* @return This summary for chaining calls.
*/
public RoomSummary setName(String name) {
mName = name;
return this;
}
/**
* Set the room's ID..
*
* @param roomId The room ID
* @return This summary for chaining calls.
*/
public RoomSummary setRoomId(String roomId) {
mRoomId = roomId;
return this;
}
/**
* Set the latest tracked event (e.g. the latest m.room.message)
*
* @param event The most-recent event.
* @return This summary for chaining calls.
*/
public RoomSummary setLatestReceivedEvent(Event event) {
mLatestReceivedEvent = event;
return this;
}
/**
* Set the latest tracked event (e.g. the latest m.room.message)
*
* @param roomState The room state of the latest event.
* @return This summary for chaining calls.
*/
public RoomSummary setLatestRoomState(RoomState roomState) {
mLatestRoomState = roomState;
// check for the invitation status
if (null != mLatestRoomState) {
RoomMember member = mLatestRoomState.getMember(mMatrixId);
mIsInvited = (null != member) && RoomMember.MEMBERSHIP_INVITE.equals(member.membership);
}
// when invited, the only received message should be the invitation one
if (mIsInvited) {
mInviterName = null;
if (null != mLatestReceivedEvent) {
mInviterName = mInviterUserId = mLatestReceivedEvent.getSender();
// try to retrieve a display name
if (null != mLatestRoomState) {
mInviterName = mLatestRoomState.getMemberName(mLatestReceivedEvent.getSender());
}
}
} else {
mInviterUserId = mInviterName = null;
}
return this;
}
/**
* @return true if the room summay must be highlighted
*/
public boolean isHighlighted() {
return mIsHighlighted || isInvited();
}
/**
* Set the highlight status.
*
* @param isHighlighted the new highlight status.
* @return true if there is an update
*/
public boolean setHighlighted(boolean isHighlighted) {
boolean isUpdated = (mIsHighlighted != isHighlighted);
mIsHighlighted = isHighlighted;
return isUpdated;
}
/**
* Set the user ID of the person who invited the user to this room.
*
* @param inviterUserId The user ID of the inviter
* @return This summary for chaining calls.
*/
public RoomSummary setInviterUserId(String inviterUserId) {
mInviterUserId = inviterUserId;
return this;
}
/**
* Update the latest read event Id
*
* @param eventId the event id.
*/
public void setLatestReadEventId(String eventId) {
mLatestReadEventId = eventId;
}
/**
* @return the latest event id
*/
public String getLatestReadEventId() {
return mLatestReadEventId;
}
/**
* Update the unread message counter
*
* @param count the unread events count.
*/
public void setUnreadEventsCount(int count) {
mUnreadEventsCount = count;
if (0 == mUnreadEventsCount) {
setHighlighted(false);
}
}
/**
* @return the unread events count
*/
public int getUnreadEventsCount() {
return mUnreadEventsCount;
}
}