Changeset View
Changeset View
Standalone View
Standalone View
src/client/room/room-model.cpp
| Show First 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | bool operator==(const EventReader &a, const EventReader &b) | ||||
| return a.userId == b.userId && a.timestamp == b.timestamp; | return a.userId == b.userId && a.timestamp == b.timestamp; | ||||
| } | } | ||||
| bool operator!=(const EventReader &a, const EventReader &b) | bool operator!=(const EventReader &a, const EventReader &b) | ||||
| { | { | ||||
| return !(a == b); | return !(a == b); | ||||
| } | } | ||||
| auto sortKeyForTimelineEvent(Event e) -> std::tuple<Timestamp, std::string> | |||||
| { | |||||
| return std::make_tuple(e.originServerTs(), e.id()); | |||||
| } | |||||
| RoomModel RoomModel::update(RoomModel r, Action a) | RoomModel RoomModel::update(RoomModel r, Action a) | ||||
| { | { | ||||
| return lager::match(std::move(a))( | return lager::match(std::move(a))( | ||||
| [&](AddStateEventsAction a) { | [&](AddStateEventsAction a) { | ||||
| r.stateEvents = merge(std::move(r.stateEvents), a.stateEvents, keyOfState); | r.stateEvents = merge(std::move(r.stateEvents), a.stateEvents, keyOfState); | ||||
| // If m.room.encryption state event appears, | // If m.room.encryption state event appears, | ||||
| // configure the room to use encryption. | // configure the room to use encryption. | ||||
| Show All 23 Lines | RoomModel RoomModel::update(RoomModel r, Action a) | ||||
| r.messages = merge(std::move(r.messages), a.events, keyOfTimeline); | r.messages = merge(std::move(r.messages), a.events, keyOfTimeline); | ||||
| auto exists = | auto exists = | ||||
| [=](auto eventId) -> bool { | [=](auto eventId) -> bool { | ||||
| return !! oldMessages.find(eventId); | return !! oldMessages.find(eventId); | ||||
| }; | }; | ||||
| auto key = | auto key = | ||||
| [=](auto eventId) { | [=](auto eventId) { | ||||
| // sort first by timestamp, then by id | // sort first by timestamp, then by id | ||||
| return std::make_tuple(r.messages[eventId].originServerTs(), eventId); | return sortKeyForTimelineEvent(r.messages[eventId]); | ||||
| }; | }; | ||||
| auto handleRedaction = | auto handleRedaction = | ||||
| [&r](const auto &event) { | [&r](const auto &event) { | ||||
| if (event.type() == "m.room.redaction") { | if (event.type() == "m.room.redaction") { | ||||
| auto origJson = event.originalJson().get(); | auto origJson = event.originalJson().get(); | ||||
| if (origJson.contains("redacts") && origJson.at("redacts").is_string()) { | if (origJson.contains("redacts") && origJson.at("redacts").is_string()) { | ||||
| auto redactedEventId = origJson.at("redacts").template get<std::string>(); | auto redactedEventId = origJson.at("redacts").template get<std::string>(); | ||||
| ▲ Show 20 Lines • Show All 198 Lines • ▼ Show 20 Lines | RoomModel RoomModel::update(RoomModel r, Action a) | ||||
| return r; | return r; | ||||
| }, | }, | ||||
| [&](UpdateJoinedMemberCountAction a) { | [&](UpdateJoinedMemberCountAction a) { | ||||
| r.joinedMemberCount = a.joinedMemberCount; | r.joinedMemberCount = a.joinedMemberCount; | ||||
| return r; | return r; | ||||
| }, | }, | ||||
| [&](UpdateInvitedMemberCountAction a) { | [&](UpdateInvitedMemberCountAction a) { | ||||
| r.invitedMemberCount = a.invitedMemberCount; | r.invitedMemberCount = a.invitedMemberCount; | ||||
| return r; | |||||
| }, | |||||
| [&](AddLocalNotificationsAction a) { | |||||
| auto readReceiptForCurrentUser = r.readReceipts.count(a.myUserId) ? r.readReceipts[a.myUserId].eventId : ""s; | |||||
| auto newEventIds = intoImmer( | |||||
| immer::flex_vector<std::string>{}, | |||||
| zug::map(&Event::id), | |||||
| a.newEvents | |||||
| ); | |||||
| auto k = [r](const auto &id) { | |||||
| return sortKeyForTimelineEvent(r.messages[id]); | |||||
| }; | |||||
| auto needToAddPredicate = [a, r, k, readReceiptForCurrentUser](const auto &eid) { | |||||
| if (!readReceiptForCurrentUser.empty() | |||||
| && k(readReceiptForCurrentUser) >= k(eid)) { | |||||
| // this means this event is already read | |||||
| return false; | |||||
| } | |||||
| auto e = r.messages[eid]; | |||||
| return e.sender() != a.myUserId | |||||
| && a.pushRulesDesc.handle(e, r).shouldNotify; | |||||
| }; | |||||
| r.unreadNotificationEventIds = sortedUniqueMerge(std::move(r.unreadNotificationEventIds), newEventIds, [needToAddPredicate](const auto &e) { return !needToAddPredicate(e); }, k); | |||||
| return r; | |||||
| }, | |||||
| [&](RemoveReadLocalNotificationsAction a) { | |||||
| if (!r.readReceipts.count(a.myUserId)) { | |||||
| return r; | |||||
| } | |||||
| auto rr = r.readReceipts[a.myUserId].eventId; | |||||
| auto k = [r](const auto &id) { | |||||
| return sortKeyForTimelineEvent(r.messages[id]); | |||||
| }; | |||||
| auto cmp = [k](const auto &a, const auto &b) { | |||||
| return k(a) < k(b); | |||||
| }; | |||||
| auto it = std::upper_bound( | |||||
| r.unreadNotificationEventIds.begin(), | |||||
| r.unreadNotificationEventIds.end(), | |||||
| rr, | |||||
| cmp | |||||
| ); | |||||
| // *it > rr, *(it - 1) <= rr (if it - 1 is valid) | |||||
| if (it == r.unreadNotificationEventIds.end()) { | |||||
| // If it == end(), it means everything is read | |||||
| r.unreadNotificationEventIds = {}; | |||||
| } else if (it == r.unreadNotificationEventIds.begin()) { | |||||
| // If it == begin(), it means everything is unread, so nothing to do | |||||
| } else { | |||||
| // it is somewhere in the middle, pointing to the first element that is unread | |||||
| r.unreadNotificationEventIds = std::move(r.unreadNotificationEventIds).erase(0, it.index()); | |||||
| } | |||||
| return r; | return r; | ||||
| } | } | ||||
| ); | ); | ||||
| } | } | ||||
| RoomListModel RoomListModel::update(RoomListModel l, Action a) | RoomListModel RoomListModel::update(RoomListModel l, Action a) | ||||
| { | { | ||||
| return lager::match(std::move(a))( | return lager::match(std::move(a))( | ||||
| ▲ Show 20 Lines • Show All 286 Lines • Show Last 20 Lines | |||||