Search in sources :

Example 1 with ReceiptData

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

Example 2 with ReceiptData

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

Example 3 with ReceiptData

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

Example 4 with ReceiptData

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

Example 5 with ReceiptData

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;
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Type(java.lang.reflect.Type) JsonObject(com.google.gson.JsonObject) ReceiptData(org.matrix.androidsdk.rest.model.ReceiptData)

Aggregations

ReceiptData (org.matrix.androidsdk.rest.model.ReceiptData)12 ArrayList (java.util.ArrayList)7 Event (org.matrix.androidsdk.rest.model.Event)6 File (java.io.File)2 HandlerThread (android.os.HandlerThread)1 MotionEvent (android.view.MotionEvent)1 JsonObject (com.google.gson.JsonObject)1 Type (java.lang.reflect.Type)1 HashMap (java.util.HashMap)1 List (java.util.List)1 Room (org.matrix.androidsdk.data.Room)1 RoomSummary (org.matrix.androidsdk.data.RoomSummary)1 IMXStore (org.matrix.androidsdk.data.store.IMXStore)1