From c2df0381313ffe5e155b7dc3d6d4c7271a4b73a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roman=20Smr=C5=BE?= Date: Sun, 8 Jan 2023 22:31:08 +0100 Subject: Contact name setting and property lookup --- include/erebos/contact.h | 2 ++ src/contact.cpp | 40 +++++++++++++++++++++++++++++-- src/main.cpp | 27 ++++++++++++++++++++- test/contact.test | 62 ++++++++++++++++++++++++++++++++++++++++++------ 4 files changed, 121 insertions(+), 10 deletions(-) diff --git a/include/erebos/contact.h b/include/erebos/contact.h index ef9c3b6..24a4c89 100644 --- a/include/erebos/contact.h +++ b/include/erebos/contact.h @@ -32,12 +32,14 @@ public: optional identity() const; optional customName() const; + Contact customName(const Storage & st, const string & name) const; string name() const; bool operator==(const Contact &) const; bool operator!=(const Contact &) const; vector> data() const; + Digest leastRoot() const; private: struct Priv; diff --git a/src/contact.cpp b/src/contact.cpp index 796e896..787831c 100644 --- a/src/contact.cpp +++ b/src/contact.cpp @@ -2,8 +2,11 @@ #include "identity.h" +#include + using namespace erebos; +using std::array; using std::move; DEFINE_SHARED_TYPE(Set, @@ -34,6 +37,19 @@ optional Contact::customName() const return p->name; } +Contact Contact::customName(const Storage & st, const string & name) const +{ + auto cdata = st.store(ContactData { + .prev = p->data, + .identity = {}, + .name = name, + }); + + return Contact(shared_ptr(new Contact::Priv { + .data = { cdata }, + })); +} + string Contact::name() const { if (auto cust = customName()) @@ -59,13 +75,33 @@ vector> Contact::data() const return p->data; } +Digest Contact::leastRoot() const +{ + if (p->data.empty()) + return Digest(array {}); + + vector roots; + for (const auto & d : p->data) + for (const auto & r : d.ref().roots()) + roots.push_back(r); + roots.erase(std::unique(roots.begin(), roots.end()), roots.end()); + return roots[0]; +} + void Contact::Priv::init() { std::call_once(initFlag, [this]() { - // TODO: property lookup - identity = Identity::load(data[0]->identity); + vector>> idata; + for (const auto & c : findPropertyComponents(data, "identity")) + for (const auto & i : c->identity) + idata.push_back(i); + + identity = Identity::load(idata); if (identity) name = identity->name(); + + if (auto opt = findPropertyComponent(data, "name")) + name = (*opt)->name; }); } diff --git a/src/main.cpp b/src/main.cpp index 12f46ac..edf68d7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -465,7 +465,7 @@ void contactList(const vector &) }; for (const auto & c : h->behavior().lens().lens>().get().view(cmp)) { ostringstream ss; - ss << "contact-list-item " << c.name(); + ss << "contact-list-item " << string(c.leastRoot()) << " " << c.name(); if (auto id = c.identity()) if (auto iname = id->name()) ss << " " << *iname; @@ -474,6 +474,30 @@ void contactList(const vector &) printLine("contact-list-done"); } +void contactSetName(const vector & args) +{ + auto id = args.at(0); + auto name = args.at(1); + + auto cmp = [](const Contact & x, const Contact & y) { + return x.data() < y.data(); + }; + for (const auto & c : h->behavior().lens().lens>().get().view(cmp)) { + if (string(c.leastRoot()) == id) { + auto nh = h->update([&] (const Stored & loc) { + auto st = loc.ref().storage(); + auto cc = c.customName(st, name); + auto contacts = loc->shared>(); + return st.store(loc->shared>(contacts.add(st, cc))); + }); + if (nh) + *h = *nh; + break; + } + } + printLine("contact-set-name-done"); +} + vector commands = { { "store", store }, { "stored-generation", storedGeneration }, @@ -496,6 +520,7 @@ vector commands = { { "contact-accept", contactAccept }, { "contact-reject", contactReject }, { "contact-list", contactList }, + { "contact-set-name", contactSetName }, }; } diff --git a/test/contact.test b/test/contact.test index b0005fd..084dd93 100644 --- a/test/contact.test +++ b/test/contact.test @@ -76,12 +76,12 @@ test Contact: send "contact-list" to p1 expect from p1: - /contact-list-item Owner2 Owner2/ + /contact-list-item [a-z0-9#]+ Owner2 Owner2/ /contact-list-(.*)/ capture done1_1 guard done1_1 == "done" send "contact-list" to p2 expect from p2: - /contact-list-item Owner1 Owner1/ + /contact-list-item [a-z0-9#]+ Owner1 Owner1/ /contact-list-(.*)/ capture done1_2 guard done1_2 == "done" @@ -118,7 +118,7 @@ test Contact: send "contact-list" to p3 expect from p3: - /contact-list-item Owner1 Owner1/ + /contact-list-item [a-z0-9#]+ Owner1 Owner1/ /contact-list-(.*)/ capture done2_3 guard done2_3 == "done" @@ -129,8 +129,8 @@ test Contact: send "contact-list" to p4 expect from p4: - /contact-list-item Owner2 Owner2/ - /contact-list-item Owner3 Owner3/ + /contact-list-item ([a-z0-9#]+) Owner2 Owner2/ capture c4_2 + /contact-list-item ([a-z0-9#]+) Owner3 Owner3/ capture c4_3 /contact-list-(.*)/ capture done2_4 guard done2_4 == "done" @@ -143,7 +143,55 @@ test Contact: send "contact-list" to p1 expect from p1: - /contact-list-item Owner2 Owner2/ - /contact-list-item Owner3 Owner3/ + /contact-list-item ([a-z0-9#]+) Owner2 Owner2/ capture c1_2 + /contact-list-item ([a-z0-9#]+) Owner3 Owner3/ capture c1_3 /contact-list-(.*)/ capture done2_1 guard done2_1 == "done" + + # Update custom name + + send "contact-set-name $c4_2 Custom2" to p4 + expect /contact-set-name-done/ from p4 + + send "contact-list" to p4 + expect from p4: + /contact-list-item $c4_2 Custom2 Owner2/ + /contact-list-item $c4_3 Owner3 Owner3/ + /contact-list-(.*)/ capture done3_4 + guard done3_4 == "done" + + send "shared-state-get" to p4 + expect /shared-state-get (.*)/ from p4 capture s4b + send "shared-state-wait $s4b" to p1 + expect /shared-state-wait $s4b/ from p1 + + send "contact-list" to p1 + expect from p1: + /contact-list-item $c4_2 Custom2 Owner2/ + /contact-list-item $c4_3 Owner3 Owner3/ + /contact-list-(.*)/ capture done3_1 + guard done3_1 == "done" + + send "contact-set-name $c1_2 Custom2B" to p1 + expect /contact-set-name-done/ from p1 + send "contact-set-name $c1_3 Custom3B" to p1 + expect /contact-set-name-done/ from p1 + + send "contact-list" to p1 + expect from p1: + /contact-list-item $c1_2 Custom2B Owner2/ + /contact-list-item $c1_3 Custom3B Owner3/ + /contact-list-(.*)/ capture done4_1 + guard done4_1 == "done" + + send "shared-state-get" to p1 + expect /shared-state-get (.*)/ from p1 capture s1b + send "shared-state-wait $s1b" to p4 + expect /shared-state-wait $s1b/ from p4 + + send "contact-list" to p4 + expect from p4: + /contact-list-item $c4_2 Custom2B Owner2/ + /contact-list-item $c4_3 Custom3B Owner3/ + /contact-list-(.*)/ capture done4_4 + guard done4_4 == "done" -- cgit v1.2.3