From fb12a0384e145eaaccf06149b633a25e0813a307 Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Mon, 16 Sep 2019 19:18:19 -0700 Subject: [PATCH] modules/m_breadcrumb_rooms: Hook breadcrumb rooms to track focused room; prefetch viewport. --- modules/m_breadcrumb_rooms.cc | 128 ++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) diff --git a/modules/m_breadcrumb_rooms.cc b/modules/m_breadcrumb_rooms.cc index a37f18269..e9b2ddcde 100644 --- a/modules/m_breadcrumb_rooms.cc +++ b/modules/m_breadcrumb_rooms.cc @@ -8,12 +8,140 @@ // copyright notice and this permission notice is present in all copies. The // full license for this software is available in the LICENSE file. +namespace ircd::m +{ + static void handle_breadcrumb_rooms_focus_out(const event &, vm::eval &, const json::array &); + static void handle_breadcrumb_rooms_focus_in(const event &, vm::eval &, const json::array &); + static void handle_breadcrumb_rooms(const event &, vm::eval &); + extern hookfn hook_breadcrumb_rooms; +} + ircd::mapi::header IRCD_MODULE { "Matrix Breadcrumb Rooms" }; +decltype(ircd::m::hook_breadcrumb_rooms) +ircd::m::hook_breadcrumb_rooms +{ + handle_breadcrumb_rooms, + { + { "_site", "vm.effect" }, + { "type", "ircd.account_data" }, + { "state_key", "im.vector.riot.breadcrumb_rooms" }, + }, +}; + +void +ircd::m::handle_breadcrumb_rooms(const event &event, + vm::eval &eval) +try +{ + const m::user::id &sender + { + at<"sender"_>(event) + }; + + const m::user::room user_room + { + sender + }; + + // We only want to hook events in the user's user room. + if(at<"room_id"_>(event) != user_room.room_id) + return; + + const auto &content + { + json::get<"content"_>(event) + }; + + const json::array &rooms + { + content.get("rooms") + }; + + handle_breadcrumb_rooms_focus_out(event, eval, rooms); + handle_breadcrumb_rooms_focus_in(event, eval, rooms); +} +catch(const ctx::interrupted &) +{ + throw; +} +catch(const std::exception &e) +{ + log::error + { + m::log, "breadcrumb_rooms hook :%s", + e.what(), + }; +} + +void +ircd::m::handle_breadcrumb_rooms_focus_in(const event &event, + vm::eval &eval, + const json::array &rooms) +{ + const room::id &focus_in + { + valid(id::ROOM, json::string{rooms[0]})? + room::id{json::string{rooms[0]}}: + room::id{} + }; + + if(!focus_in) + return; + + room::events it + { + focus_in + }; + + ssize_t prefetched(0), i(0); + const ssize_t prefetch_max + { + ssize_t(room::events::viewport_size) / 2 + }; + + for(; it && i < prefetch_max / 2; ++i, --it) + prefetched += m::prefetch(it.event_idx()); + + log::debug + { + m::log, "Prefetched %zu/%zu viewport:%zu of %s for %s now in focus", + prefetched, + i, + prefetch_max, + string_view{focus_in}, + at<"sender"_>(event), + rooms.size(), + }; +} + +void +ircd::m::handle_breadcrumb_rooms_focus_out(const event &event, + vm::eval &eval, + const json::array &rooms) +{ + const room::id &focus_out + { + valid(id::ROOM, json::string{rooms[1]})? + room::id{json::string{rooms[1]}}: + room::id{} + }; + + if(!focus_out) + return; + + log::debug + { + m::log, "%s for %s out of focus", + string_view{focus_out}, + at<"sender"_>(event), + }; +} + ircd::m::event::id::buf ircd::m::breadcrumb_rooms::set(const json::array &rooms) const