Search in sources :

Example 61 with Event

use of org.matrix.androidsdk.rest.model.Event in project matrix-android-sdk by matrix-org.

the class MatrixMessageListFragment method addMessageRow.

// create a dummy message row for the message
// It is added to the Adapter
// return the created Message
private MessageRow addMessageRow(RoomMediaMessage roomMediaMessage) {
    // a message row can only be added if there is a defined room
    if (null != mRoom) {
        Event event = roomMediaMessage.getEvent();
        MessageRow newMessageRow = new MessageRow(event, mRoom.getState());
        mAdapter.add(newMessageRow);
        // Move read marker if necessary
        MessageRow currentReadMarkerRow = getReadMarkerMessageRow(newMessageRow);
        if (canUpdateReadMarker(newMessageRow, currentReadMarkerRow)) {
            View childView = mMessageListView.getChildAt(mMessageListView.getChildCount() - 1);
            // Previous message was the last read
            if ((null != childView) && (childView.getTop() >= 0)) {
                // New message is fully visible, keep reference to move the read marker once server echo is received
                mFutureReadMarkerEventId = event.eventId;
                mAdapter.resetReadMarker();
            }
        }
        scrollToBottom();
        getSession().getDataHandler().getStore().commit();
        return newMessageRow;
    } else {
        return null;
    }
}
Also used : MessageRow(org.matrix.androidsdk.adapters.MessageRow) MotionEvent(android.view.MotionEvent) Event(org.matrix.androidsdk.rest.model.Event) View(android.view.View) AbsListView(android.widget.AbsListView) AutoScrollDownListView(org.matrix.androidsdk.view.AutoScrollDownListView)

Example 62 with Event

use of org.matrix.androidsdk.rest.model.Event in project matrix-android-sdk by matrix-org.

the class RoomMediaMessagesSender method uploadMedias.

// ==============================================================================================================
// Upload medias management
// ==============================================================================================================
/**
 * Upload the medias.
 *
 * @param roomMediaMessage the roomMediaMessage
 * @return true if a media is uploaded
 */
private boolean uploadMedias(final RoomMediaMessage roomMediaMessage) {
    final Event event = roomMediaMessage.getEvent();
    final Message message = JsonUtils.toMessage(event.getContent());
    if (!(message instanceof MediaMessage)) {
        return false;
    }
    final MediaMessage mediaMessage = (MediaMessage) message;
    final String url;
    final String fMimeType;
    if (mediaMessage.isThumbnailLocalContent()) {
        url = mediaMessage.getThumbnailUrl();
        fMimeType = "image/jpeg";
    } else if (mediaMessage.isLocalContent()) {
        url = mediaMessage.getUrl();
        fMimeType = mediaMessage.getMimeType();
    } else {
        return false;
    }
    mEncodingHandler.post(new Runnable() {

        @Override
        public void run() {
            final MXMediasCache mediasCache = mDataHandler.getMediasCache();
            Uri uri = Uri.parse(url);
            String mimeType = fMimeType;
            final MXEncryptedAttachments.EncryptionResult encryptionResult;
            final Uri encryptedUri;
            InputStream stream;
            try {
                stream = new FileInputStream(new File(uri.getPath()));
                if (mRoom.isEncrypted() && mDataHandler.isCryptoEnabled() && (null != stream)) {
                    encryptionResult = MXEncryptedAttachments.encryptAttachment(stream, mimeType);
                    stream.close();
                    if (null != encryptionResult) {
                        mimeType = "application/octet-stream";
                        encryptedUri = Uri.parse(mediasCache.saveMedia(encryptionResult.mEncryptedStream, null, fMimeType));
                        File file = new File(encryptedUri.getPath());
                        stream = new FileInputStream(file);
                    } else {
                        skip();
                        mUiHandler.post(new Runnable() {

                            @Override
                            public void run() {
                                mDataHandler.updateEventState(roomMediaMessage.getEvent(), Event.SentState.UNDELIVERABLE);
                                mRoom.storeOutgoingEvent(roomMediaMessage.getEvent());
                                mDataHandler.getStore().commit();
                                roomMediaMessage.onEncryptionFailed();
                            }
                        });
                        return;
                    }
                } else {
                    encryptionResult = null;
                    encryptedUri = null;
                }
            } catch (Exception e) {
                skip();
                return;
            }
            mDataHandler.updateEventState(roomMediaMessage.getEvent(), Event.SentState.SENDING);
            mediasCache.uploadContent(stream, mediaMessage.isThumbnailLocalContent() ? ("thumb" + message.body) : message.body, mimeType, url, new MXMediaUploadListener() {

                @Override
                public void onUploadStart(final String uploadId) {
                    mUiHandler.post(new Runnable() {

                        @Override
                        public void run() {
                            if (null != roomMediaMessage.getMediaUploadListener()) {
                                roomMediaMessage.getMediaUploadListener().onUploadStart(uploadId);
                            }
                        }
                    });
                }

                @Override
                public void onUploadCancel(final String uploadId) {
                    mUiHandler.post(new Runnable() {

                        @Override
                        public void run() {
                            mDataHandler.updateEventState(roomMediaMessage.getEvent(), Event.SentState.UNDELIVERABLE);
                            if (null != roomMediaMessage.getMediaUploadListener()) {
                                roomMediaMessage.getMediaUploadListener().onUploadCancel(uploadId);
                                roomMediaMessage.setMediaUploadListener(null);
                                roomMediaMessage.setEventSendingCallback(null);
                            }
                            skip();
                        }
                    });
                }

                @Override
                public void onUploadError(final String uploadId, final int serverResponseCode, final String serverErrorMessage) {
                    mUiHandler.post(new Runnable() {

                        @Override
                        public void run() {
                            mDataHandler.updateEventState(roomMediaMessage.getEvent(), Event.SentState.UNDELIVERABLE);
                            if (null != roomMediaMessage.getMediaUploadListener()) {
                                roomMediaMessage.getMediaUploadListener().onUploadError(uploadId, serverResponseCode, serverErrorMessage);
                                roomMediaMessage.setMediaUploadListener(null);
                                roomMediaMessage.setEventSendingCallback(null);
                            }
                            skip();
                        }
                    });
                }

                @Override
                public void onUploadComplete(final String uploadId, final String contentUri) {
                    mUiHandler.post(new Runnable() {

                        @Override
                        public void run() {
                            boolean isThumbnailUpload = mediaMessage.isThumbnailLocalContent();
                            if (isThumbnailUpload) {
                                mediaMessage.setThumbnailUrl(encryptionResult, contentUri);
                                if (null != encryptionResult) {
                                    mediasCache.saveFileMediaForUrl(contentUri, encryptedUri.toString(), -1, -1, "image/jpeg");
                                    try {
                                        new File(Uri.parse(url).getPath()).delete();
                                    } catch (Exception e) {
                                        Log.e(LOG_TAG, "## cannot delete the uncompress media");
                                    }
                                } else {
                                    Pair<Integer, Integer> thumbnailSize = roomMediaMessage.getThumnailSize();
                                    mediasCache.saveFileMediaForUrl(contentUri, url, thumbnailSize.first, thumbnailSize.second, "image/jpeg");
                                }
                                // update the event content with the new message info
                                event.updateContent(JsonUtils.toJson(message));
                                // force to save the room events list
                                // https://github.com/vector-im/riot-android/issues/1390
                                mDataHandler.getStore().flushRoomEvents(mRoom.getRoomId());
                                // upload the media
                                uploadMedias(roomMediaMessage);
                            } else {
                                if (null != encryptedUri) {
                                    // replace the thumbnail and the media contents by the computed one
                                    mediasCache.saveFileMediaForUrl(contentUri, encryptedUri.toString(), mediaMessage.getMimeType());
                                    try {
                                        new File(Uri.parse(url).getPath()).delete();
                                    } catch (Exception e) {
                                        Log.e(LOG_TAG, "## cannot delete the uncompress media");
                                    }
                                } else {
                                    // replace the thumbnail and the media contents by the computed one
                                    mediasCache.saveFileMediaForUrl(contentUri, url, mediaMessage.getMimeType());
                                }
                                mediaMessage.setUrl(encryptionResult, contentUri);
                                // update the event content with the new message info
                                event.updateContent(JsonUtils.toJson(message));
                                // force to save the room events list
                                // https://github.com/vector-im/riot-android/issues/1390
                                mDataHandler.getStore().flushRoomEvents(mRoom.getRoomId());
                                Log.d(LOG_TAG, "Uploaded to " + contentUri);
                                // send
                                sendEvent(event);
                            }
                            if (null != roomMediaMessage.getMediaUploadListener()) {
                                roomMediaMessage.getMediaUploadListener().onUploadComplete(uploadId, contentUri);
                                if (!isThumbnailUpload) {
                                    roomMediaMessage.setMediaUploadListener(null);
                                }
                            }
                        }
                    });
                }
            });
        }
    });
    return true;
}
Also used : MediaMessage(org.matrix.androidsdk.rest.model.message.MediaMessage) MXMediasCache(org.matrix.androidsdk.db.MXMediasCache) Message(org.matrix.androidsdk.rest.model.message.Message) FileMessage(org.matrix.androidsdk.rest.model.message.FileMessage) ImageMessage(org.matrix.androidsdk.rest.model.message.ImageMessage) MediaMessage(org.matrix.androidsdk.rest.model.message.MediaMessage) AudioMessage(org.matrix.androidsdk.rest.model.message.AudioMessage) VideoMessage(org.matrix.androidsdk.rest.model.message.VideoMessage) FileInputStream(java.io.FileInputStream) InputStream(java.io.InputStream) Uri(android.net.Uri) FileInputStream(java.io.FileInputStream) MXMediaUploadListener(org.matrix.androidsdk.listeners.MXMediaUploadListener) Event(org.matrix.androidsdk.rest.model.Event) File(java.io.File) Pair(android.util.Pair)

Example 63 with Event

use of org.matrix.androidsdk.rest.model.Event in project matrix-android-sdk by matrix-org.

the class RoomState method applyState.

/**
 * Apply the given event (relevant for state changes) to our state.
 *
 * @param store     the store to use
 * @param event     the event
 * @param direction how the event should affect the state: Forwards for applying, backwards for un-applying (applying the previous state)
 * @return true if the event is managed
 */
public boolean applyState(IMXStore store, Event event, EventTimeline.Direction direction) {
    if (event.stateKey == null) {
        return false;
    }
    JsonObject contentToConsider = (direction == EventTimeline.Direction.FORWARDS) ? event.getContentAsJsonObject() : event.getPrevContentAsJsonObject();
    String eventType = event.getType();
    try {
        if (Event.EVENT_TYPE_STATE_ROOM_NAME.equals(eventType)) {
            name = JsonUtils.toRoomState(contentToConsider).name;
        } else if (Event.EVENT_TYPE_STATE_ROOM_TOPIC.equals(eventType)) {
            topic = JsonUtils.toRoomState(contentToConsider).topic;
        } else if (Event.EVENT_TYPE_STATE_ROOM_CREATE.equals(eventType)) {
            creator = JsonUtils.toRoomState(contentToConsider).creator;
        } else if (Event.EVENT_TYPE_STATE_ROOM_JOIN_RULES.equals(eventType)) {
            join_rule = JsonUtils.toRoomState(contentToConsider).join_rule;
        } else if (Event.EVENT_TYPE_STATE_ROOM_GUEST_ACCESS.equals(eventType)) {
            guest_access = JsonUtils.toRoomState(contentToConsider).guest_access;
        } else if (Event.EVENT_TYPE_STATE_ROOM_ALIASES.equals(eventType)) {
            if (!TextUtils.isEmpty(event.stateKey)) {
                // backward compatibility
                aliases = JsonUtils.toRoomState(contentToConsider).aliases;
                // sanity check
                if (null != aliases) {
                    mAliasesByDomain.put(event.stateKey, aliases);
                    mRoomAliases.put(event.stateKey, event);
                } else {
                    mAliasesByDomain.put(event.stateKey, new ArrayList<String>());
                }
            }
        } else if (Event.EVENT_TYPE_MESSAGE_ENCRYPTION.equals(eventType)) {
            algorithm = JsonUtils.toRoomState(contentToConsider).algorithm;
            // This flag should not be cleared if a later m.room.encryption event changes the configuration. This is to avoid a situation where a MITM can simply ask participants to disable encryption. In short: once encryption is enabled in a room, it can never be disabled.
            if (null == algorithm) {
                algorithm = "";
            }
        } else if (Event.EVENT_TYPE_STATE_CANONICAL_ALIAS.equals(eventType)) {
            // SPEC-125
            alias = JsonUtils.toRoomState(contentToConsider).alias;
        } else if (Event.EVENT_TYPE_STATE_HISTORY_VISIBILITY.equals(eventType)) {
            // SPEC-134
            history_visibility = JsonUtils.toRoomState(contentToConsider).history_visibility;
        } else if (Event.EVENT_TYPE_STATE_ROOM_AVATAR.equals(eventType)) {
            url = JsonUtils.toRoomState(contentToConsider).url;
        } else if (Event.EVENT_TYPE_STATE_RELATED_GROUPS.equals(eventType)) {
            groups = JsonUtils.toRoomState(contentToConsider).groups;
        } else if (Event.EVENT_TYPE_STATE_ROOM_MEMBER.equals(eventType)) {
            RoomMember member = JsonUtils.toRoomMember(contentToConsider);
            String userId = event.stateKey;
            if (null == userId) {
                Log.e(LOG_TAG, "## applyState() : null stateKey in " + roomId);
            } else if (null == member) {
                // the member has already been removed
                if (null == getMember(userId)) {
                    Log.e(LOG_TAG, "## applyState() : the user " + userId + " is not anymore a member of " + roomId);
                    return false;
                }
                removeMember(userId);
            } else {
                try {
                    member.setUserId(userId);
                    member.setOriginServerTs(event.getOriginServerTs());
                    member.setOriginalEventId(event.eventId);
                    member.mSender = event.getSender();
                    if ((null != store) && (direction == EventTimeline.Direction.FORWARDS)) {
                        store.storeRoomStateEvent(roomId, event);
                    }
                    RoomMember currentMember = getMember(userId);
                    // duplicated message ?
                    if (member.equals(currentMember)) {
                        Log.e(LOG_TAG, "## applyState() : seems being a duplicated event for " + userId + " in room " + roomId);
                        return false;
                    }
                    // when a member leaves a room, his avatar / display name is not anymore provided
                    if (null != currentMember) {
                        if (TextUtils.equals(member.membership, RoomMember.MEMBERSHIP_LEAVE) || TextUtils.equals(member.membership, (RoomMember.MEMBERSHIP_BAN))) {
                            if (null == member.getAvatarUrl()) {
                                member.setAvatarUrl(currentMember.getAvatarUrl());
                            }
                            if (null == member.displayname) {
                                member.displayname = currentMember.displayname;
                            }
                            // remove the cached display name
                            if (null != mMemberDisplayNameByUserId) {
                                mMemberDisplayNameByUserId.remove(userId);
                            }
                            // test if the user has been kicked
                            if (!TextUtils.equals(event.getSender(), event.stateKey) && TextUtils.equals(currentMember.membership, RoomMember.MEMBERSHIP_JOIN) && TextUtils.equals(member.membership, RoomMember.MEMBERSHIP_LEAVE)) {
                                member.membership = RoomMember.MEMBERSHIP_KICK;
                            }
                        }
                    }
                    if ((direction == EventTimeline.Direction.FORWARDS) && (null != store)) {
                        store.updateUserWithRoomMemberEvent(member);
                    }
                    // Cache room member event that is successor of a third party invite event
                    if (!TextUtils.isEmpty(member.getThirdPartyInviteToken())) {
                        mMembersWithThirdPartyInviteTokenCache.put(member.getThirdPartyInviteToken(), member);
                    }
                } catch (Exception e) {
                    Log.e(LOG_TAG, "## applyState() - EVENT_TYPE_STATE_ROOM_MEMBER failed " + e.getMessage());
                }
                setMember(userId, member);
            }
        } else if (Event.EVENT_TYPE_STATE_ROOM_POWER_LEVELS.equals(eventType)) {
            powerLevels = JsonUtils.toPowerLevels(contentToConsider);
        } else if (Event.EVENT_TYPE_STATE_ROOM_THIRD_PARTY_INVITE.equals(event.getType())) {
            if (null != contentToConsider) {
                RoomThirdPartyInvite thirdPartyInvite = JsonUtils.toRoomThirdPartyInvite(contentToConsider);
                thirdPartyInvite.token = event.stateKey;
                if ((direction == EventTimeline.Direction.FORWARDS) && (null != store)) {
                    store.storeRoomStateEvent(roomId, event);
                }
                if (!TextUtils.isEmpty(thirdPartyInvite.token)) {
                    mThirdPartyInvites.put(thirdPartyInvite.token, thirdPartyInvite);
                }
            }
        }
        // they are saved elsewhere
        if (!TextUtils.isEmpty(eventType) && !Event.EVENT_TYPE_STATE_ROOM_MEMBER.equals(eventType)) {
            List<Event> eventsList = mStateEvents.get(eventType);
            if (null == eventsList) {
                eventsList = new ArrayList<>();
                mStateEvents.put(eventType, eventsList);
            }
            eventsList.add(event);
        }
    } catch (Exception e) {
        Log.e(LOG_TAG, "applyState failed with error " + e.getMessage());
    }
    return true;
}
Also used : RoomThirdPartyInvite(org.matrix.androidsdk.rest.model.pid.RoomThirdPartyInvite) RoomMember(org.matrix.androidsdk.rest.model.RoomMember) ArrayList(java.util.ArrayList) JsonObject(com.google.gson.JsonObject) Event(org.matrix.androidsdk.rest.model.Event) IOException(java.io.IOException)

Example 64 with Event

use of org.matrix.androidsdk.rest.model.Event in project matrix-android-sdk by matrix-org.

the class MXFileStore method loadRoomToken.

/**
 * Load the room token from the file system.
 *
 * @param roomId the room id.
 * @return true if it succeeds.
 */
private boolean loadRoomToken(final String roomId) {
    boolean succeed = true;
    Room room = getRoom(roomId);
    // should always be true
    if (null != room) {
        String token = null;
        try {
            File messagesListFile = new File(mStoreRoomsTokensFolderFile, roomId);
            Object tokenAsVoid = readObject("loadRoomToken " + roomId, messagesListFile);
            if (null == tokenAsVoid) {
                succeed = false;
            } else {
                token = (String) tokenAsVoid;
                // check if the oldest event has a token.
                LinkedHashMap<String, Event> eventsHash = mRoomEvents.get(roomId);
                if ((null != eventsHash) && (eventsHash.size() > 0)) {
                    Event event = eventsHash.values().iterator().next();
                    // so, if the oldest messages has a token, use it instead of the stored token.
                    if (null != event.mToken) {
                        token = event.mToken;
                    }
                }
            }
        } catch (Exception e) {
            succeed = false;
            Log.e(LOG_TAG, "loadRoomToken failed : " + e.toString());
        }
        if (null != token) {
            mRoomTokens.put(roomId, token);
        } else {
            deleteRoom(roomId);
        }
    } else {
        try {
            File messagesListFile = new File(mStoreRoomsTokensFolderFile, roomId);
            messagesListFile.delete();
        } catch (Exception e) {
            Log.e(LOG_TAG, "loadRoomToken failed with error " + e.getMessage());
        }
    }
    return succeed;
}
Also used : Event(org.matrix.androidsdk.rest.model.Event) Room(org.matrix.androidsdk.data.Room) File(java.io.File)

Example 65 with Event

use of org.matrix.androidsdk.rest.model.Event in project matrix-android-sdk by matrix-org.

the class MXFileStore method getSavedEventsMap.

// ================================================================================
// Room messages management
// ================================================================================
/**
 * Computes the saved events map to reduce storage footprint.
 *
 * @param roomId the room id
 * @return the saved eventMap
 */
private LinkedHashMap<String, Event> getSavedEventsMap(String roomId) {
    LinkedHashMap<String, Event> eventsMap;
    synchronized (mRoomEventsLock) {
        eventsMap = mRoomEvents.get(roomId);
    }
    List<Event> eventsList;
    synchronized (mRoomEventsLock) {
        eventsList = new ArrayList<>(eventsMap.values());
    }
    int startIndex = 0;
    // if some messages are received, the token is stored in the event.
    if (eventsList.size() > MAX_STORED_MESSAGES_COUNT) {
        // search backward the first known token
        for (startIndex = eventsList.size() - MAX_STORED_MESSAGES_COUNT; !eventsList.get(startIndex).hasToken() && (startIndex > 0); startIndex--) ;
        if (startIndex > 0) {
            Log.d(LOG_TAG, "## getSavedEveventsMap() : " + roomId + " reduce the number of messages " + eventsList.size() + " -> " + (eventsList.size() - startIndex));
        }
    }
    LinkedHashMap<String, Event> savedEvents = new LinkedHashMap<>();
    for (int index = startIndex; index < eventsList.size(); index++) {
        Event event = eventsList.get(index);
        savedEvents.put(event.eventId, event);
    }
    return savedEvents;
}
Also used : Event(org.matrix.androidsdk.rest.model.Event) LinkedHashMap(java.util.LinkedHashMap)

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