use of org.matrix.androidsdk.rest.model.Event in project matrix-android-sdk by matrix-org.
the class RoomState method getStateEvents.
/**
* Provides the loaded states event list.
* The room member events are NOT included.
*
* @param types the allowed event types.
* @return the filtered state events list.
*/
public List<Event> getStateEvents(final Set<String> types) {
final List<Event> filteredStateEvents = new ArrayList<>();
final List<Event> stateEvents = new ArrayList<>();
// merge the values lists
Collection<List<Event>> currentStateEvents = mStateEvents.values();
for (List<Event> eventsList : currentStateEvents) {
stateEvents.addAll(eventsList);
}
if ((null != types) && !types.isEmpty()) {
for (Event stateEvent : stateEvents) {
if ((null != stateEvent.getType()) && types.contains(stateEvent.getType())) {
filteredStateEvents.add(stateEvent);
}
}
} else {
filteredStateEvents.addAll(stateEvents);
}
return filteredStateEvents;
}
use of org.matrix.androidsdk.rest.model.Event in project matrix-android-sdk by matrix-org.
the class RoomState method readExternal.
@Override
public void readExternal(ObjectInput input) throws IOException, ClassNotFoundException {
if (input.readBoolean()) {
roomId = input.readUTF();
}
if (input.readBoolean()) {
powerLevels = (PowerLevels) input.readObject();
}
if (input.readBoolean()) {
aliases = (List<String>) input.readObject();
}
List<Event> roomAliasesEvents = (List<Event>) input.readObject();
for (Event e : roomAliasesEvents) {
mRoomAliases.put(e.stateKey, e);
}
mAliasesByDomain = (Map<String, List<String>>) input.readObject();
if (input.readBoolean()) {
mMergedAliasesList = (List<String>) input.readObject();
}
Map<String, List<Event>> stateEvents = (Map<String, List<Event>>) input.readObject();
if (null != stateEvents) {
mStateEvents = new HashMap<>(stateEvents);
}
if (input.readBoolean()) {
alias = input.readUTF();
}
if (input.readBoolean()) {
name = input.readUTF();
}
if (input.readBoolean()) {
topic = input.readUTF();
}
if (input.readBoolean()) {
url = input.readUTF();
}
if (input.readBoolean()) {
avatar_url = input.readUTF();
}
if (input.readBoolean()) {
creator = input.readUTF();
}
if (input.readBoolean()) {
join_rule = input.readUTF();
}
if (input.readBoolean()) {
guest_access = input.readUTF();
}
if (input.readBoolean()) {
history_visibility = input.readUTF();
}
if (input.readBoolean()) {
roomAliasName = input.readUTF();
}
if (input.readBoolean()) {
visibility = input.readUTF();
}
if (input.readBoolean()) {
algorithm = input.readUTF();
}
mNotificationCount = input.readInt();
mHighlightCount = input.readInt();
if (input.readBoolean()) {
token = input.readUTF();
}
List<RoomMember> members = (List<RoomMember>) input.readObject();
for (RoomMember r : members) {
mMembers.put(r.getUserId(), r);
}
List<RoomThirdPartyInvite> invites = (List<RoomThirdPartyInvite>) input.readObject();
for (RoomThirdPartyInvite i : invites) {
mThirdPartyInvites.put(i.token, i);
}
List<RoomMember> inviteTokens = (List<RoomMember>) input.readObject();
for (RoomMember r : inviteTokens) {
mMembersWithThirdPartyInviteTokenCache.put(r.getThirdPartyInviteToken(), r);
}
if (input.readBoolean()) {
mMembership = input.readUTF();
}
mIsLive = input.readBoolean();
if (input.readBoolean()) {
mIsConferenceUserRoom = input.readBoolean();
}
if (input.readBoolean()) {
groups = (List<String>) input.readObject();
}
}
use of org.matrix.androidsdk.rest.model.Event in project matrix-android-sdk by matrix-org.
the class EventTimeline method handleJoinedRoomSync.
/**
* Manage the joined room events.
*
* @param roomSync the roomSync.
* @param isGlobalInitialSync true if the sync has been triggered by a global initial sync
*/
public void handleJoinedRoomSync(RoomSync roomSync, boolean isGlobalInitialSync) {
String membership = null;
String myUserId = mDataHandler.getMyUser().user_id;
RoomSummary currentSummary = null;
RoomMember selfMember = mState.getMember(mDataHandler.getMyUser().user_id);
if (null != selfMember) {
membership = selfMember.membership;
}
boolean isRoomInitialSync = (null == membership) || TextUtils.equals(membership, RoomMember.MEMBERSHIP_INVITE);
// Check whether the room was pending on an invitation.
if (TextUtils.equals(membership, RoomMember.MEMBERSHIP_INVITE)) {
// Reset the storage of this room. An initial sync of the room will be done with the provided 'roomSync'.
Log.d(LOG_TAG, "handleJoinedRoomSync: clean invited room from the store " + mRoomId);
mStore.deleteRoomData(mRoomId);
// clear the states
RoomState state = new RoomState();
state.roomId = mRoomId;
state.setDataHandler(mDataHandler);
this.mBackState = this.mState = state;
}
if ((null != roomSync.state) && (null != roomSync.state.events) && (roomSync.state.events.size() > 0)) {
if (isRoomInitialSync) {
Log.d(LOG_TAG, "## handleJoinedRoomSync() : " + roomSync.state.events.size() + " events for room " + mRoomId + " in store " + getStore());
}
// Note: We consider it is not required to clone the existing room state here, because no notification is posted for these events.
if (mDataHandler.isAlive()) {
for (Event event : roomSync.state.events) {
try {
processStateEvent(event, Direction.FORWARDS);
} catch (Exception e) {
Log.e(LOG_TAG, "processStateEvent failed " + e.getMessage());
}
}
mRoom.setReadyState(true);
} else {
Log.e(LOG_TAG, "## handleJoinedRoomSync() : mDataHandler.isAlive() is false");
}
// so the back state must also be initialized
if (isRoomInitialSync) {
Log.d(LOG_TAG, "## handleJoinedRoomSync() : retrieve " + this.mState.getMembers().size() + " members for room " + mRoomId);
this.mBackState = this.mState.deepCopy();
}
}
// Handle now timeline.events, the room state is updated during this step too (Note: timeline events are in chronological order)
if (null != roomSync.timeline) {
if (roomSync.timeline.limited) {
if (!isRoomInitialSync) {
currentSummary = mStore.getSummary(mRoomId);
// define a summary if some messages are left
// the unsent messages are often displayed messages.
Event oldestEvent = mStore.getOldestEvent(mRoomId);
// Flush the existing messages for this room by keeping state events.
mStore.deleteAllRoomMessages(mRoomId, true);
if (oldestEvent != null) {
if (RoomSummary.isSupportedEvent(oldestEvent)) {
if (null != currentSummary) {
currentSummary.setLatestReceivedEvent(oldestEvent, mState);
mStore.storeSummary(currentSummary);
} else {
mStore.storeSummary(new RoomSummary(null, oldestEvent, mState, myUserId));
}
}
}
}
// it implies there is no more data on server side.
if (null == roomSync.timeline.prevBatch) {
roomSync.timeline.prevBatch = Event.PAGINATE_BACK_TOKEN_END;
}
// In case of limited timeline, update token where to start back pagination
mStore.storeBackToken(mRoomId, roomSync.timeline.prevBatch);
// reset the state back token
// because it does not make anymore sense
// by setting at null, the events cache will be cleared when a requesthistory will be called
mBackState.setToken(null);
// reset the back paginate lock
mCanBackPaginate = true;
}
// any event ?
if ((null != roomSync.timeline.events) && (roomSync.timeline.events.size() > 0)) {
List<Event> events = roomSync.timeline.events;
// save the back token
events.get(0).mToken = roomSync.timeline.prevBatch;
// They will be added at the end of the stored events, so we keep the chronological order.
for (Event event : events) {
// the roomId is not defined.
event.roomId = mRoomId;
try {
boolean isLimited = (null != roomSync.timeline) && roomSync.timeline.limited;
// digest the forward event
handleLiveEvent(event, !isLimited && !isGlobalInitialSync, !isGlobalInitialSync && !isRoomInitialSync);
} catch (Exception e) {
Log.e(LOG_TAG, "timeline event failed " + e.getMessage());
}
}
}
}
if (isRoomInitialSync) {
// any request history can be triggered by now.
mRoom.setReadyState(true);
} else // Finalize initial sync
{
if ((null != roomSync.timeline) && roomSync.timeline.limited) {
// The room has been synced with a limited timeline
mDataHandler.onRoomFlush(mRoomId);
}
}
// so, the following items should only be called when it is a live one.
if (mIsLiveTimeline) {
// after a sync, the room summary might not be defined because the latest message did not generate a room summary/
if (null != mStore.getRoom(mRoomId)) {
RoomSummary summary = mStore.getSummary(mRoomId);
// we have to create a new one
if (null == summary) {
// define a summary if some messages are left
// the unsent messages are often displayed messages.
Event oldestEvent = mStore.getOldestEvent(mRoomId);
// if there is an oldest event, use it to set a summary
if (oldestEvent != null) {
// always defined a room summary else the room won't be displayed in the recents
mStore.storeSummary(new RoomSummary(null, oldestEvent, mState, myUserId));
mStore.commit();
// back paginate until to find a valid one
if (!RoomSummary.isSupportedEvent(oldestEvent)) {
Log.e(LOG_TAG, "the room " + mRoomId + " has no valid summary, back paginate once to find a valid one");
}
} else // use the latest known event
if (null != currentSummary) {
currentSummary.setLatestReceivedEvent(currentSummary.getLatestReceivedEvent(), mState);
mStore.storeSummary(currentSummary);
mStore.commit();
} else // try to build a summary from the state events
if ((null != roomSync.state) && (null != roomSync.state.events) && (roomSync.state.events.size() > 0)) {
ArrayList<Event> events = new ArrayList<>(roomSync.state.events);
Collections.reverse(events);
for (Event event : events) {
event.roomId = mRoomId;
if (RoomSummary.isSupportedEvent(event)) {
if (null == summary) {
summary = new RoomSummary(mStore.getSummary(mRoomId), event, mState, myUserId);
} else {
summary.setLatestReceivedEvent(event, mState);
}
mStore.storeSummary(summary);
String eventType = event.getType();
// Watch for potential room name changes
if (Event.EVENT_TYPE_STATE_ROOM_NAME.equals(eventType) || Event.EVENT_TYPE_STATE_ROOM_ALIASES.equals(eventType) || Event.EVENT_TYPE_STATE_ROOM_MEMBER.equals(eventType)) {
if (null != summary) {
summary.setName(mRoom.getName(myUserId));
}
}
mStore.commit();
break;
}
}
}
}
}
if (null != roomSync.unreadNotifications) {
int notifCount = 0;
int highlightCount = 0;
if (null != roomSync.unreadNotifications.highlightCount) {
highlightCount = roomSync.unreadNotifications.highlightCount;
}
if (null != roomSync.unreadNotifications.notificationCount) {
notifCount = roomSync.unreadNotifications.notificationCount;
}
if ((notifCount != mState.getNotificationCount()) || (mState.getHighlightCount() != highlightCount)) {
Log.d(LOG_TAG, "## handleJoinedRoomSync() : update room state notifs count for room id " + getRoom().getRoomId() + ": highlightCount " + highlightCount + " - notifCount " + notifCount);
mState.setNotificationCount(notifCount);
mState.setHighlightCount(highlightCount);
mStore.storeLiveStateForRoom(mRoomId);
mDataHandler.onNotificationCountUpdate(mRoomId);
}
// some users reported that the summary notification counts were sometimes invalid
// so check roomstates and summaries separately
RoomSummary summary = mStore.getSummary(mRoomId);
if ((null != summary) && ((notifCount != summary.getNotificationCount()) || (summary.getHighlightCount() != highlightCount))) {
Log.d(LOG_TAG, "## handleJoinedRoomSync() : update room summary notifs count for room id " + getRoom().getRoomId() + ": highlightCount " + highlightCount + " - notifCount " + notifCount);
summary.setNotificationCount(notifCount);
summary.setHighlightCount(highlightCount);
mStore.flushSummary(summary);
mDataHandler.onNotificationCountUpdate(mRoomId);
}
}
}
}
use of org.matrix.androidsdk.rest.model.Event in project matrix-android-sdk by matrix-org.
the class EventTimeline method handleLiveEvent.
/**
* Handle events coming down from the event stream.
*
* @param event the live event
* @param checkRedactedStateEvent set to true to check if it triggers a state event redaction
* @param withPush set to true to trigger pushes when it is required
*/
private void handleLiveEvent(Event event, boolean checkRedactedStateEvent, boolean withPush) {
MyUser myUser = mDataHandler.getMyUser();
// Decrypt event if necessary
mDataHandler.decryptEvent(event, getTimelineId());
// dispatch the call events to the calls manager
if (event.isCallEvent()) {
mDataHandler.getCallsManager().handleCallEvent(mStore, event);
storeLiveRoomEvent(event, false);
// because the users don't need to see the peer exchanges.
if (!TextUtils.equals(event.getType(), Event.EVENT_TYPE_CALL_CANDIDATES)) {
// warn the listeners
// general listeners
mDataHandler.onLiveEvent(event, mState);
// timeline listeners
onEvent(event, Direction.FORWARDS, mState);
}
// trigger pushes when it is required
if (withPush) {
triggerPush(event);
}
} else {
Event storedEvent = mStore.getEvent(event.eventId, event.roomId);
// avoid processing event twice
if (null != storedEvent) {
// an event has been echoed
if (storedEvent.getAge() == Event.DUMMY_EVENT_AGE) {
mStore.deleteEvent(storedEvent);
mStore.storeLiveRoomEvent(event);
mStore.commit();
Log.d(LOG_TAG, "handleLiveEvent : the event " + event.eventId + " in " + event.roomId + " has been echoed");
} else {
Log.d(LOG_TAG, "handleLiveEvent : the event " + event.eventId + " in " + event.roomId + " already exist.");
return;
}
}
// Room event
if (event.roomId != null) {
// instead of being done in the application
if (Event.EVENT_TYPE_STATE_ROOM_MEMBER.equals(event.getType()) && TextUtils.equals(event.getSender(), mDataHandler.getUserId())) {
EventContent eventContent = JsonUtils.toEventContent(event.getContentAsJsonObject());
EventContent prevEventContent = event.getPrevContent();
String prevMembership = null;
if (null != prevEventContent) {
prevMembership = prevEventContent.membership;
}
// it should mean that the user profile has been updated.
if (!event.isRedacted() && TextUtils.equals(prevMembership, eventContent.membership) && TextUtils.equals(RoomMember.MEMBERSHIP_JOIN, eventContent.membership)) {
// check if the user updates his profile from another device.
boolean hasAccountInfoUpdated = false;
if (!TextUtils.equals(eventContent.displayname, myUser.displayname)) {
hasAccountInfoUpdated = true;
myUser.displayname = eventContent.displayname;
mStore.setDisplayName(myUser.displayname, event.getOriginServerTs());
}
if (!TextUtils.equals(eventContent.avatar_url, myUser.getAvatarUrl())) {
hasAccountInfoUpdated = true;
myUser.setAvatarUrl(eventContent.avatar_url);
mStore.setAvatarURL(myUser.avatar_url, event.getOriginServerTs());
}
if (hasAccountInfoUpdated) {
mDataHandler.onAccountInfoUpdate(myUser);
}
}
}
RoomState previousState = mState;
if (event.stateKey != null) {
// copy the live state before applying any update
deepCopyState(Direction.FORWARDS);
// check if the event has been processed
if (!processStateEvent(event, Direction.FORWARDS)) {
// assume that the event is a duplicated one.
return;
}
}
storeLiveRoomEvent(event, checkRedactedStateEvent);
// warn the listeners
// general listeners
mDataHandler.onLiveEvent(event, previousState);
// timeline listeners
onEvent(event, Direction.FORWARDS, previousState);
// trigger pushes when it is required
if (withPush) {
triggerPush(event);
}
} else {
Log.e(LOG_TAG, "Unknown live event type: " + event.getType());
}
}
}
use of org.matrix.androidsdk.rest.model.Event in project matrix-android-sdk by matrix-org.
the class EventTimeline method handleInvitedRoomSync.
/**
* Handle the invitation room events
*
* @param invitedRoomSync the invitation room events.
*/
public void handleInvitedRoomSync(InvitedRoomSync invitedRoomSync) {
// Handle the state events as live events (the room state will be updated, and the listeners (if any) will be notified).
if ((null != invitedRoomSync) && (null != invitedRoomSync.inviteState) && (null != invitedRoomSync.inviteState.events)) {
for (Event event : invitedRoomSync.inviteState.events) {
// Add a fake event id if none in order to be able to store the event
if (null == event.eventId) {
event.eventId = mRoomId + "-" + System.currentTimeMillis() + "-" + event.hashCode();
}
// The roomId is not defined.
event.roomId = mRoomId;
handleLiveEvent(event, false, true);
}
// The room related to the pending invite can be considered as ready from now
mRoom.setReadyState(true);
}
}
Aggregations