summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRoland Reichwein <mail@reichwein.it>2023-01-28 21:24:11 +0100
committerRoland Reichwein <mail@reichwein.it>2023-01-28 21:24:11 +0100
commit4eedb599d8de5559daa4678c7520bb36968e767e (patch)
tree43830f8cf5c880d8be76b8f98bb2f73d78e38c78
parenta69b1d0c580bc779740ef79a7d16b69229896785 (diff)
Server to client: diffs
-rw-r--r--html/whiteboard.js27
-rw-r--r--whiteboard.cpp32
-rw-r--r--whiteboard.h3
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<std::pair<std::string, std::string>>& key_values)
+pt::ptree make_ptree(const std::initializer_list<std::pair<std::string, std::string>>& 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<std::pair<std::string, std::string>>& 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<std::mutex> 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<int>("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 <boost/asio/ip/tcp.hpp>
+#include "diff.h"
#include "config.h"
#include "connectionregistry.h"
#include "storage.h"
@@ -27,7 +28,7 @@ private:
using connection = std::shared_ptr<boost::beast::websocket::stream<boost::asio::ip::tcp::socket>>;
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();