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;
}
}
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;
}
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;
}
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;
}
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;
}
Aggregations