Search in sources :

Example 21 with Event

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;
}
Also used : ArrayList(java.util.ArrayList) Event(org.matrix.androidsdk.rest.model.Event) ArrayList(java.util.ArrayList) List(java.util.List)

Example 22 with Event

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();
    }
}
Also used : RoomThirdPartyInvite(org.matrix.androidsdk.rest.model.pid.RoomThirdPartyInvite) RoomMember(org.matrix.androidsdk.rest.model.RoomMember) Event(org.matrix.androidsdk.rest.model.Event) ArrayList(java.util.ArrayList) List(java.util.List) HashMap(java.util.HashMap) Map(java.util.Map)

Example 23 with Event

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);
            }
        }
    }
}
Also used : RoomMember(org.matrix.androidsdk.rest.model.RoomMember) ArrayList(java.util.ArrayList) Event(org.matrix.androidsdk.rest.model.Event)

Example 24 with Event

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());
        }
    }
}
Also used : Event(org.matrix.androidsdk.rest.model.Event) EventContent(org.matrix.androidsdk.rest.model.EventContent)

Example 25 with Event

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);
    }
}
Also used : Event(org.matrix.androidsdk.rest.model.Event)

Aggregations

Event (org.matrix.androidsdk.rest.model.Event)73 ArrayList (java.util.ArrayList)31 JsonObject (com.google.gson.JsonObject)28 Room (org.matrix.androidsdk.data.Room)27 MatrixError (org.matrix.androidsdk.rest.model.MatrixError)27 HashMap (java.util.HashMap)23 CountDownLatch (java.util.concurrent.CountDownLatch)22 RoomState (org.matrix.androidsdk.data.RoomState)21 Test (org.junit.Test)20 MXEventListener (org.matrix.androidsdk.listeners.MXEventListener)19 Context (android.content.Context)14 MotionEvent (android.view.MotionEvent)9 EventTimeline (org.matrix.androidsdk.data.EventTimeline)9 IMXStore (org.matrix.androidsdk.data.store.IMXStore)7 ReceiptData (org.matrix.androidsdk.rest.model.ReceiptData)6 RoomMember (org.matrix.androidsdk.rest.model.RoomMember)6 Credentials (org.matrix.androidsdk.rest.model.login.Credentials)6 Uri (android.net.Uri)5 File (java.io.File)4 MessageRow (org.matrix.androidsdk.adapters.MessageRow)4