From 4eedb599d8de5559daa4678c7520bb36968e767e Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Sat, 28 Jan 2023 21:24:11 +0100 Subject: Server to client: diffs --- html/whiteboard.js | 27 +++++++++++++++++++++++---- whiteboard.cpp | 32 +++++++++++++++++++------------- whiteboard.h | 3 ++- 3 files changed, 44 insertions(+), 18 deletions(-) diff --git a/html/whiteboard.js b/html/whiteboard.js index 58023fe..3e09621 100644 --- a/html/whiteboard.js +++ b/html/whiteboard.js @@ -48,6 +48,26 @@ function on_getfile(data, rev, pos) textAreaSetPos("board", pos); } +function on_getdiff(diff, rev) +{ + if (rev != revision + 1) + alert("Revision skipped: " + rev + " after " + revision); + + var board = document.getElementById("board"); + + var old_version_ptr = allocateUTF8(board.value); + var diff_ptr = allocateUTF8(new XMLSerializer().serializeToString(diff)); + var new_version_ptr = Module._diff_apply(old_version_ptr, diff_ptr); + var data = UTF8ToString(new_version_ptr); + board.value = data; + _free(old_version_ptr); + _free(new_version_ptr); + _free(diff_ptr); + + revision = rev; + baseline = data; +} + function on_getpos(pos) { textAreaSetPos("board", pos); @@ -88,6 +108,9 @@ function on_message(e) { on_getfile(xmlDocument.getElementsByTagName("data")[0].textContent, parseInt(xmlDocument.getElementsByTagName("revision")[0].textContent), parseInt(xmlDocument.getElementsByTagName("pos")[0].textContent)); + } else if (type == "getdiff") { + on_getdiff(xmlDocument.getElementsByTagName("diff")[0], + parseInt(xmlDocument.getElementsByTagName("revision")[0].textContent)); } else if (type == "getpos") { on_getpos(parseInt(xmlDocument.getElementsByTagName("pos")[0].textContent)); } else if (type == "modify") { @@ -216,10 +239,6 @@ function on_input() idElement.appendChild(document.createTextNode(get_id())); requestElement.appendChild(idElement); - var dataElement = xmlDocument.createElement("data"); - dataElement.appendChild(document.createTextNode(document.getElementById("board").value)); - requestElement.appendChild(dataElement); - baseline_candidate = document.getElementById("board").value; var revisionElement = xmlDocument.createElement("baserev"); diff --git a/whiteboard.cpp b/whiteboard.cpp index 059571d..35ae30b 100644 --- a/whiteboard.cpp +++ b/whiteboard.cpp @@ -83,33 +83,39 @@ void Whiteboard::storage_cleanup() } } -std::string make_xml(const std::initializer_list>& key_values) +pt::ptree make_ptree(const std::initializer_list>& key_values) { - pt::ptree xml; + pt::ptree ptree; for (const auto& i: key_values) { - xml.put(fmt::format("serverinfo.{}", i.first), i.second); + ptree.put(fmt::format("serverinfo.{}", i.first), i.second); } - return Reichwein::XML::plain_xml(xml); + return ptree; +} + +std::string make_xml(const std::initializer_list>& key_values) +{ + pt::ptree ptree{make_ptree(key_values)}; + return Reichwein::XML::plain_xml(ptree); } -void Whiteboard::notify_other_connections_file(Whiteboard::connection& c, const std::string& id) +void Whiteboard::notify_other_connections_diff(Whiteboard::connection& c, const std::string& id, const Diff& diff) { std::for_each(m_registry.begin(id), m_registry.end(id), [&](const Whiteboard::connection& ci) { if (c != ci) { boost::beast::flat_buffer buffer; - boost::beast::ostream(buffer) << make_xml({ - {"type", "getfile"}, - {"data", m_storage->getDocument(id)}, - {"revision", std::to_string(m_storage->getRevision(id)) }, - {"pos", std::to_string(m_storage->getCursorPos(id)) } - }); + pt::ptree ptree {make_ptree({ + {"type", "getdiff"}, + {"revision", std::to_string(m_storage->getRevision(id)) } + })}; + ptree.put_child("serverinfo.diff", diff.get_structure().get_child("diff")); + boost::beast::ostream(buffer) << Reichwein::XML::plain_xml(ptree); std::lock_guard lock(m_websocket_mutex); try { ci->write(buffer.data()); } catch (const std::exception& ex) { - std::cerr << "Warning: Notify getfile write for " << ci << " not possible, id " << id << std::endl; + std::cerr << "Warning: Notify getdiff write for " << ci << " not possible, id " << id << std::endl; m_registry.dump(); } } @@ -165,7 +171,7 @@ std::string Whiteboard::handle_request(Whiteboard::connection& c, const std::str m_storage->setDocument(id, data); m_registry.setId(c, id); - notify_other_connections_file(c, id); + notify_other_connections_diff(c, id, d); int pos {xml.get("request.pos")}; if (m_storage->getCursorPos(id) != pos) { diff --git a/whiteboard.h b/whiteboard.h index 818fcfe..c000e36 100644 --- a/whiteboard.h +++ b/whiteboard.h @@ -7,6 +7,7 @@ #include +#include "diff.h" #include "config.h" #include "connectionregistry.h" #include "storage.h" @@ -27,7 +28,7 @@ private: using connection = std::shared_ptr>; std::string handle_request(connection& c, const std::string& request); - void notify_other_connections_file(connection& c, const std::string& id); // notify all other id-related connections about changes + void notify_other_connections_diff(connection& c, const std::string& id, const Diff& diff); // notify all other id-related connections about changes void notify_other_connections_pos(connection& c, const std::string& id); // notify all other id-related connections about changes void do_session(boost::asio::ip::tcp::socket socket); void storage_cleanup(); -- cgit v1.2.3