use of org.matrix.androidsdk.rest.model.ReceiptData in project matrix-android-sdk by matrix-org.
the class MXMemoryStore method getReceipt.
/**
* Get the receipt for an user in a dedicated room.
*
* @param roomId the room id.
* @param userId the user id.
* @return the dedicated receipt
*/
@Override
public ReceiptData getReceipt(String roomId, String userId) {
ReceiptData res = null;
// sanity checks
if (!TextUtils.isEmpty(roomId) && !TextUtils.isEmpty(userId)) {
synchronized (mReceiptsByRoomIdLock) {
if (mReceiptsByRoomId.containsKey(roomId)) {
Map<String, ReceiptData> receipts = mReceiptsByRoomId.get(roomId);
res = receipts.get(userId);
}
}
}
return res;
}
use of org.matrix.androidsdk.rest.model.ReceiptData in project matrix-android-sdk by matrix-org.
the class MXMemoryStore method storeReceipt.
/**
* Store the receipt for an user in a room.
* The receipt validity is checked i.e the receipt is not for an already read message.
*
* @param receipt The event
* @param roomId The roomId
* @return true if the receipt has been stored
*/
@Override
public boolean storeReceipt(ReceiptData receipt, String roomId) {
try {
// sanity check
if (TextUtils.isEmpty(roomId) || (null == receipt)) {
return false;
}
Map<String, ReceiptData> receiptsByUserId;
synchronized (mReceiptsByRoomIdLock) {
if (!mReceiptsByRoomId.containsKey(roomId)) {
receiptsByUserId = new HashMap<>();
mReceiptsByRoomId.put(roomId, receiptsByUserId);
} else {
receiptsByUserId = mReceiptsByRoomId.get(roomId);
}
}
ReceiptData curReceipt = null;
if (receiptsByUserId.containsKey(receipt.userId)) {
curReceipt = receiptsByUserId.get(receipt.userId);
}
if (null == curReceipt) {
// Log.d(LOG_TAG, "## storeReceipt() : there was no receipt from this user");
receiptsByUserId.put(receipt.userId, receipt);
return true;
}
if (TextUtils.equals(receipt.eventId, curReceipt.eventId)) {
// Log.d(LOG_TAG, "## storeReceipt() : receipt for the same event");
return false;
}
if (receipt.originServerTs < curReceipt.originServerTs) {
// Log.d(LOG_TAG, "## storeReceipt() : the receipt is older that the current one");
return false;
}
// check if the read receipt is not for an already read message
if (TextUtils.equals(receipt.userId, mCredentials.userId)) {
synchronized (mReceiptsByRoomIdLock) {
LinkedHashMap<String, Event> eventsMap = mRoomEvents.get(roomId);
// test if the event is know
if ((null != eventsMap) && eventsMap.containsKey(receipt.eventId)) {
ArrayList<String> eventIds = new ArrayList<>(eventsMap.keySet());
int curEventPos = eventIds.indexOf(curReceipt.eventId);
int newEventPos = eventIds.indexOf(receipt.eventId);
if (curEventPos >= newEventPos) {
Log.d(LOG_TAG, "## storeReceipt() : the read message is already read (cur pos " + curEventPos + " receipt event pos " + newEventPos + ")");
return false;
}
}
}
}
// Log.d(LOG_TAG, "## storeReceipt() : updated");
receiptsByUserId.put(receipt.userId, receipt);
} catch (OutOfMemoryError e) {
dispatchOOM(e);
}
return true;
}
use of org.matrix.androidsdk.rest.model.ReceiptData in project matrix-android-sdk by matrix-org.
the class EventTimeline method storeEvent.
/**
* Store the event and update the dedicated room summary
*
* @param event the event to store
*/
private void storeEvent(Event event) {
String myUserId = mDataHandler.getCredentials().userId;
// to avoid not synchronized read receipt and event
if ((null != event.getSender()) && (null != event.eventId)) {
mRoom.handleReceiptData(new ReceiptData(event.getSender(), event.eventId, event.originServerTs));
}
mStore.storeLiveRoomEvent(event);
if (RoomSummary.isSupportedEvent(event)) {
RoomSummary summary = mStore.getSummary(event.roomId);
if (null == summary) {
summary = new RoomSummary(summary, 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));
}
}
}
}
use of org.matrix.androidsdk.rest.model.ReceiptData in project matrix-android-sdk by matrix-org.
the class Room method sendReadMarkers.
/**
* Send the read markers
*
* @param aReadMarkerEventId the new read marker event id (if null use the latest known event id)
* @param aReadReceiptEventId the new read receipt event id (if null use the latest known event id)
* @param aRespCallback asynchronous response callback
* @return true if the request is sent, false otherwise
*/
public boolean sendReadMarkers(final String aReadMarkerEventId, final String aReadReceiptEventId, final ApiCallback<Void> aRespCallback) {
final Event lastEvent = (null != getStore()) ? getStore().getLatestEvent(getRoomId()) : null;
// reported by GA
if (null == lastEvent) {
Log.e(LOG_TAG, "## sendReadMarkers(): no last event");
return false;
}
Log.d(LOG_TAG, "## sendReadMarkers(): readMarkerEventId " + aReadMarkerEventId + " readReceiptEventId " + aReadReceiptEventId + " in room " + getRoomId());
boolean hasUpdate = false;
String readMarkerEventId = aReadMarkerEventId;
if (!TextUtils.isEmpty(aReadMarkerEventId)) {
if (!MXSession.isMessageId(aReadMarkerEventId)) {
Log.e(LOG_TAG, "## sendReadMarkers() : invalid event id " + readMarkerEventId);
// Read marker is invalid, ignore it
readMarkerEventId = null;
} else {
// Check if the read marker is updated
RoomSummary summary = getStore().getSummary(getRoomId());
if ((null != summary) && !TextUtils.equals(readMarkerEventId, summary.getReadMarkerEventId())) {
// Make sure the new read marker event is newer than the current one
final Event newReadMarkerEvent = getStore().getEvent(readMarkerEventId, getRoomId());
final Event currentReadMarkerEvent = getStore().getEvent(summary.getReadMarkerEventId(), getRoomId());
if (newReadMarkerEvent == null || currentReadMarkerEvent == null || newReadMarkerEvent.getOriginServerTs() > currentReadMarkerEvent.getOriginServerTs()) {
// Event is not in store (assume it is in the past), or is older than current one
Log.d(LOG_TAG, "## sendReadMarkers(): set new read marker event id " + readMarkerEventId + " in room " + getRoomId());
summary.setReadMarkerEventId(readMarkerEventId);
getStore().flushSummary(summary);
hasUpdate = true;
}
}
}
}
final String readReceiptEventId = (null == aReadReceiptEventId) ? lastEvent.eventId : aReadReceiptEventId;
// check if the read receipt event id is already read
if ((null != getStore()) && !getStore().isEventRead(getRoomId(), getDataHandler().getUserId(), readReceiptEventId)) {
// check if the event id update is allowed
if (handleReceiptData(new ReceiptData(mMyUserId, readReceiptEventId, System.currentTimeMillis()))) {
// (asap there is a valid network connection)
if (TextUtils.equals(lastEvent.eventId, readReceiptEventId)) {
clearUnreadCounters(getStore().getSummary(getRoomId()));
}
hasUpdate = true;
}
}
if (hasUpdate) {
setReadMarkers(readMarkerEventId, readReceiptEventId, aRespCallback);
}
return hasUpdate;
}
use of org.matrix.androidsdk.rest.model.ReceiptData in project matrix-android-sdk by matrix-org.
the class Room method handleReceiptEvent.
/**
* Handle receipt event.
*
* @param event the event receipts.
* @return the sender user IDs list.
*/
private List<String> handleReceiptEvent(Event event) {
List<String> senderIDs = new ArrayList<>();
try {
// the receipts dictionnaries
// key : $EventId
// value : dict key $UserId
// value dict key ts
// dict value ts value
Type type = new TypeToken<HashMap<String, HashMap<String, HashMap<String, HashMap<String, Object>>>>>() {
}.getType();
HashMap<String, HashMap<String, HashMap<String, HashMap<String, Object>>>> receiptsDict = gson.fromJson(event.getContent(), type);
for (String eventId : receiptsDict.keySet()) {
HashMap<String, HashMap<String, HashMap<String, Object>>> receiptDict = receiptsDict.get(eventId);
for (String receiptType : receiptDict.keySet()) {
// only the read receipts are managed
if (TextUtils.equals(receiptType, "m.read")) {
HashMap<String, HashMap<String, Object>> userIdsDict = receiptDict.get(receiptType);
for (String userID : userIdsDict.keySet()) {
HashMap<String, Object> paramsDict = userIdsDict.get(userID);
for (String paramName : paramsDict.keySet()) {
if (TextUtils.equals("ts", paramName)) {
Double value = (Double) paramsDict.get(paramName);
long ts = value.longValue();
if (handleReceiptData(new ReceiptData(userID, eventId, ts))) {
senderIDs.add(userID);
}
}
}
}
}
}
}
} catch (Exception e) {
Log.e(LOG_TAG, "handleReceiptEvent : failed" + e.getMessage());
}
return senderIDs;
}
Aggregations