diff --git a/solanaceae/tox_contacts/components.hpp b/solanaceae/tox_contacts/components.hpp index d46cf82..f1590e5 100644 --- a/solanaceae/tox_contacts/components.hpp +++ b/solanaceae/tox_contacts/components.hpp @@ -4,9 +4,9 @@ namespace Contact::Components { - // ========== - // friend - // ========== + // ==================== + // friends + // ==================== struct ToxFriendPersistent { ToxKey key; @@ -17,9 +17,9 @@ namespace Contact::Components { }; - // ========== - // TODO: conference (old groups) - // ========== + // ==================== + // TODO: conferences (old groups) + // ==================== struct ToxConfPersistent { ToxKey key; @@ -30,9 +30,9 @@ namespace Contact::Components { }; - // ========== + // ==================== // groups (ngc) - // ========== + // ==================== struct ToxGroupPersistent { ToxKey chat_id; @@ -43,7 +43,6 @@ namespace Contact::Components { }; struct ToxGroupIncomingRequest { - //Contact3 friend_c; uint32_t friend_number; std::vector invite_data; }; diff --git a/solanaceae/tox_contacts/tox_contact_model2.cpp b/solanaceae/tox_contacts/tox_contact_model2.cpp index 41dc354..c1d46a4 100644 --- a/solanaceae/tox_contacts/tox_contact_model2.cpp +++ b/solanaceae/tox_contacts/tox_contact_model2.cpp @@ -4,6 +4,7 @@ #include #include +#include // TODO: move #include @@ -16,7 +17,7 @@ #include #include -ToxContactModel2::ToxContactModel2(Contact3Registry& cr, ToxI& t, ToxEventProviderI& tep) : _cr(cr), _t(t), _tep_sr(tep.newSubRef(this)) { +ToxContactModel2::ToxContactModel2(ContactStore4I& cs, ToxI& t, ToxEventProviderI& tep) : _cs(cs), _t(t), _tep_sr(tep.newSubRef(this)) { _tep_sr .subscribe(Tox_Event_Type::TOX_EVENT_FRIEND_CONNECTION_STATUS) .subscribe(Tox_Event_Type::TOX_EVENT_FRIEND_STATUS) @@ -34,19 +35,23 @@ ToxContactModel2::ToxContactModel2(Contact3Registry& cr, ToxI& t, ToxEventProvid .subscribe(Tox_Event_Type::TOX_EVENT_GROUP_TOPIC) ; + auto& cr = _cs.registry(); + // add tox profile root - _root = _cr.create(); - _cr.emplace(_root); - _cr.emplace(_root, this); + _root = cr.create(); + cr.emplace(_root); + cr.emplace(_root, this); + cs.throwEventConstruct(_root); // add self - _friend_self = _cr.create(); - _cr.emplace(_friend_self, this); - _cr.emplace(_friend_self, _root); - _cr.emplace(_friend_self); - _cr.emplace(_friend_self, _t.toxSelfGetName()); + _friend_self = cr.create(); + cr.emplace(_friend_self, this); + cr.emplace(_friend_self, _root); + cr.emplace(_friend_self); + cr.emplace(_friend_self, _t.toxSelfGetName()); // TODO: can contact with id preexist here? - _cr.emplace(_friend_self, _t.toxSelfGetPublicKey()); + cr.emplace(_friend_self, _t.toxSelfGetPublicKey()); + cs.throwEventConstruct(_friend_self); // fill in contacts for (const uint32_t f_id : _t.toxSelfGetFriendList()) { @@ -68,76 +73,121 @@ void ToxContactModel2::iterate(float delta) { if (_group_status_timer >= 1.f) { _group_status_timer = 0.f; - _cr.view().each([this](auto c, const auto& tox_peer, auto& con) { + std::vector updated; + + _cs.registry().view().each([this, &updated](auto c, const auto& tox_peer, auto& con) { auto state_opt = std::get<0>(_t.toxGroupPeerGetConnectionStatus(tox_peer.group_number, tox_peer.peer_number)); - if (state_opt.has_value()) { - if (state_opt.value() == TOX_CONNECTION_UDP) { - con.state = Contact::Components::ConnectionState::State::direct; - } else if (state_opt.value() == TOX_CONNECTION_TCP) { - con.state = Contact::Components::ConnectionState::State::cloud; - } + if (!state_opt.has_value()) { + return; } + + Contact::Components::ConnectionState::State new_state{Contact::Components::ConnectionState::State::disconnected}; + if (state_opt.value() == TOX_CONNECTION_UDP) { + new_state = Contact::Components::ConnectionState::State::direct; + } else if (state_opt.value() == TOX_CONNECTION_TCP) { + new_state = Contact::Components::ConnectionState::State::cloud; + } + + if (con.state != new_state) { + updated.push_back(c); + } + + con.state = new_state; }); + + for (const auto c : updated) { + _cs.throwEventUpdate(c); + } } } -void ToxContactModel2::acceptRequest(Contact3 c, std::string_view self_name, std::string_view password) { - assert(!_cr.any_of(c)); - assert(_cr.all_of(c)); +bool ToxContactModel2::addContact(Contact4 c) { + // TODO: implement me + return false; +} - if (_cr.all_of(c)) { - const auto& key = _cr.get(c).key.data; +bool ToxContactModel2::acceptRequest(Contact4 c, std::string_view self_name, std::string_view password) { + auto& cr = _cs.registry(); + + if ( + cr.any_of(c) || + !cr.all_of(c) + ) { + return false; + } + + assert(!cr.any_of(c)); + assert(cr.all_of(c)); + + if (cr.all_of(c)) { + const auto& key = cr.get(c).key.data; auto [friend_number_opt, _] = _t.toxFriendAddNorequest({key.cbegin(), key.cend()}); if (friend_number_opt.has_value()) { - _cr.emplace(c, friend_number_opt.value()); - _cr.remove(c); + cr.emplace(c, friend_number_opt.value()); + cr.remove(c); } else { std::cerr << "TCM2 error: failed to accept friend request/invite\n"; + return false; } } else if (false) { // conf - } else if (_cr.all_of(c)) { // group - const auto& ir = _cr.get(c); + } else if (cr.all_of(c)) { // group + const auto& ir = cr.get(c); auto [group_number_opt, _] = _t.toxGroupInviteAccept(ir.friend_number, ir.invite_data, self_name, password); - if (group_number_opt.has_value()) { - _cr.emplace(c, group_number_opt.value()); - - if (auto group_chatid_opt = _t.toxGroupGetChatId(group_number_opt.value()); group_chatid_opt.has_value()) { - _cr.emplace_or_replace(c, group_chatid_opt.value()); - } else { - std::cerr << "TCM2 error: getting chatid for group" << group_number_opt.value() << "!!\n"; - } - - if (auto self_opt = _t.toxGroupSelfGetPeerId(group_number_opt.value()); self_opt.has_value()) { - _cr.emplace_or_replace(c, getContactGroupPeer(group_number_opt.value(), self_opt.value())); - } else { - std::cerr << "TCM2 error: getting self for group" << group_number_opt.value() << "!!\n"; - } - - _cr.remove(c); - _cr.remove(c); - } else { + if (!group_number_opt.has_value()) { std::cerr << "TCM2 error: failed to accept group request/invite\n"; + return false; } + + // FIXME: we are changing the contact there without event, do we just not? + cr.emplace(c, group_number_opt.value()); + + if (auto group_chatid_opt = _t.toxGroupGetChatId(group_number_opt.value()); group_chatid_opt.has_value()) { + cr.emplace_or_replace(c, group_chatid_opt.value()); + } else { + std::cerr << "TCM2 error: getting chatid for group" << group_number_opt.value() << "!!\n"; + return false; + } + + if (auto self_opt = _t.toxGroupSelfGetPeerId(group_number_opt.value()); self_opt.has_value()) { + cr.emplace_or_replace(c, getContactGroupPeer(group_number_opt.value(), self_opt.value())); + } else { + std::cerr << "TCM2 error: getting self for group" << group_number_opt.value() << "!!\n"; + return false; + } + + cr.remove(c); + cr.remove(c); } else { std::cerr << "TCM2 error: failed to accept request (unk)\n"; + return false; } + + _cs.throwEventUpdate(c); + + return true; } -Contact3Handle ToxContactModel2::getContactFriend(uint32_t friend_number) { - Contact3 c = entt::null; +bool ToxContactModel2::leave(Contact4 c, std::string_view reason) { + // TODO: implement me + return false; +} + +ContactHandle4 ToxContactModel2::getContactFriend(uint32_t friend_number) { + auto& cr = _cs.registry(); + Contact4 c {entt::null}; // first check contacts with friend id // TODO: lookup table //_cr.view().each([&c, friend_number](const Contact3 e, const Contact::Components::ToxFriendEphemeral& f_id) { - for (const auto e : _cr.view()) { - if (_cr.get(e).friend_number == friend_number) { + for (const auto e : cr.view()) { + if (cr.get(e).friend_number == friend_number) { c = e; break; } } - if (_cr.valid(c)) { - return {_cr, c}; + if (cr.valid(c)) { + return {cr, c}; } // else check by pubkey @@ -146,89 +196,94 @@ Contact3Handle ToxContactModel2::getContactFriend(uint32_t friend_number) { const ToxKey& f_key = f_key_opt.value(); //_cr.view().each([&c, &f_key](const Contact3 e, const Contact::Components::ToxFriendPersistent& f_key_comp) { - for (const auto e : _cr.view()) { - if (f_key == _cr.get(e).key) { + for (const auto e : cr.view()) { + if (f_key == cr.get(e).key) { c = e; break; } } - if (_cr.valid(c)) { + if (cr.valid(c)) { // param friend number matches pubkey in db, add - _cr.emplace_or_replace(c, friend_number); + cr.emplace_or_replace(c, friend_number); - return {_cr, c}; + _cs.throwEventUpdate(c); + return {cr, c}; } // check for id (empty contact) and merge - for (const auto e : _cr.view()) { - if (f_key_opt.value() == _cr.get(e).data) { - c = e; - break; - } - } + c = _cs.getOneContactByID(_root, ByteSpan{f_key_opt.value()}); - if (!_cr.valid(c)) { + bool created {false}; + if (!cr.valid(c)) { // else, new ent - c = _cr.create(); - _cr.emplace(c, f_key_opt.value()); + c = cr.create(); + created = true; + cr.emplace(c, f_key_opt.value()); } - _cr.emplace_or_replace(c); - _cr.emplace_or_replace(c, this); - _cr.emplace_or_replace(c, friend_number); - _cr.emplace_or_replace(c, f_key); - _cr.emplace_or_replace(c, _root); - _cr.get_or_emplace(_root).subs.push_back(c); - _cr.emplace_or_replace(c).subs.assign({_friend_self, c}); - _cr.emplace_or_replace(c); - _cr.emplace_or_replace(c, _friend_self); - _cr.emplace_or_replace(c, _t.toxFriendGetName(friend_number).value_or("")); - _cr.emplace_or_replace(c, _t.toxFriendGetStatusMessage(friend_number).value_or("")).fillFirstLineLength(); + cr.emplace_or_replace(c); + cr.emplace_or_replace(c, this); + cr.emplace_or_replace(c, friend_number); + cr.emplace_or_replace(c, f_key); + cr.emplace_or_replace(c, _root); + cr.get_or_emplace(_root).subs.push_back(c); + cr.emplace_or_replace(c).subs.assign({_friend_self, c}); + cr.emplace_or_replace(c); + cr.emplace_or_replace(c, _friend_self); + cr.emplace_or_replace(c, _t.toxFriendGetName(friend_number).value_or("")); + cr.emplace_or_replace(c, _t.toxFriendGetStatusMessage(friend_number).value_or("")).fillFirstLineLength(); const auto ts = getTimeMS(); - if (!_cr.all_of(c)) { + if (!cr.all_of(c)) { auto lo_opt = _t.toxFriendGetLastOnline(friend_number); if (lo_opt.has_value()) { - _cr.emplace_or_replace(c, lo_opt.value()*1000ull); + cr.emplace_or_replace(c, lo_opt.value()*1000ull); } } - if (!_cr.all_of(c)) { - if (_cr.all_of(c)) { - _cr.emplace_or_replace(c, + if (!cr.all_of(c)) { + if (cr.all_of(c)) { + cr.emplace_or_replace(c, std::min( - _cr.get(c).ts, + cr.get(c).ts, ts ) ); } else { // TODO: did we? - _cr.emplace_or_replace(c, ts); + cr.emplace_or_replace(c, ts); } } std::cout << "TCM2: created friend contact " << friend_number << "\n"; - return {_cr, c}; + if (created) { + _cs.throwEventConstruct(c); + } else { + _cs.throwEventUpdate(c); + } + + return {cr, c}; } -Contact3Handle ToxContactModel2::getContactGroup(uint32_t group_number) { - Contact3 c = entt::null; +ContactHandle4 ToxContactModel2::getContactGroup(uint32_t group_number) { + auto& cr = _cs.registry(); + Contact4 c = entt::null; // first check contacts with group_number // TODO: lookup table //_cr.view().each([&c, group_number](const Contact3 e, const Contact::Components::ToxGroupEphemeral& g_e) { - for (const auto e : _cr.view()) { - if (_cr.get(e).group_number == group_number) { + for (const auto e : cr.view()) { + if (cr.get(e).group_number == group_number) { c = e; break; } } - if (_cr.valid(c)) { - return {_cr, c}; + if (cr.valid(c)) { + return {cr, c}; } // else check by pubkey @@ -237,45 +292,43 @@ Contact3Handle ToxContactModel2::getContactGroup(uint32_t group_number) { const ToxKey& g_key = g_key_opt.value(); //_cr.view().each([&c, &g_key](const Contact3 e, const Contact::Components::ToxGroupPersistent& g_key_comp) { - for (const auto e : _cr.view()) { - if (g_key == _cr.get(e).chat_id) { + for (const auto e : cr.view()) { + if (g_key == cr.get(e).chat_id) { c = e; break; } } - if (_cr.valid(c)) { + if (cr.valid(c)) { // param group number matches pubkey in db, add - _cr.emplace_or_replace(c, group_number); + cr.emplace_or_replace(c, group_number); - return {_cr, c}; + _cs.throwEventUpdate(c); + return {cr, c}; } // check for id (empty contact) and merge - for (const auto e : _cr.view()) { - if (g_key_opt.value() == _cr.get(e).data) { - c = e; - break; - } - } + c = _cs.getOneContactByID(_root, ByteSpan{g_key_opt.value()}); - if (!_cr.valid(c)) { + bool created{false}; + if (!cr.valid(c)) { // else, new ent - c = _cr.create(); - _cr.emplace(c, g_key_opt.value()); + c = cr.create(); + created = true; + cr.emplace(c, g_key_opt.value()); } - _cr.emplace_or_replace(c, this); - _cr.emplace_or_replace(c); - _cr.emplace_or_replace(c, _root); - _cr.get_or_emplace(_root).subs.push_back(c); - _cr.emplace_or_replace(c); // start empty - _cr.emplace_or_replace(c, group_number); - _cr.emplace_or_replace(c, g_key); - _cr.emplace_or_replace(c); - _cr.emplace_or_replace(c, _t.toxGroupGetName(group_number).value_or("")); - _cr.emplace_or_replace(c, _t.toxGroupGetTopic(group_number).value_or("")).fillFirstLineLength(); - _cr.emplace_or_replace( + cr.emplace_or_replace(c, this); + cr.emplace_or_replace(c); + cr.emplace_or_replace(c, _root); + cr.get_or_emplace(_root).subs.push_back(c); + cr.emplace_or_replace(c); // start empty + cr.emplace_or_replace(c, group_number); + cr.emplace_or_replace(c, g_key); + cr.emplace_or_replace(c); + cr.emplace_or_replace(c, _t.toxGroupGetName(group_number).value_or("")); + cr.emplace_or_replace(c, _t.toxGroupGetTopic(group_number).value_or("")).fillFirstLineLength(); + cr.emplace_or_replace( c, _t.toxGroupIsConnected(group_number).value_or(false) ? Contact::Components::ConnectionState::State::cloud @@ -283,7 +336,7 @@ Contact3Handle ToxContactModel2::getContactGroup(uint32_t group_number) { ); // TODO: remove and add OnNewContact - _cr.emplace_or_replace(c, + cr.emplace_or_replace(c, [](Message3Handle lh, Message3Handle rh) -> bool { if (!lh.all_of() || !rh.all_of()) { return false; // cant compare @@ -312,37 +365,45 @@ Contact3Handle ToxContactModel2::getContactGroup(uint32_t group_number) { } ); + // TODO: move after event? throw first if create? auto self_opt = _t.toxGroupSelfGetPeerId(group_number); if (self_opt.has_value()) { - _cr.emplace_or_replace(c, getContactGroupPeer(group_number, self_opt.value())); + cr.emplace_or_replace(c, getContactGroupPeer(group_number, self_opt.value())); } else { std::cerr << "TCM2 error: getting self for group" << group_number << "!!\n"; } std::cout << "TCM2: created group contact " << group_number << "\n"; - return {_cr, c}; + if (created) { + _cs.throwEventConstruct(c); + } else { + _cs.throwEventUpdate(c); + } + + return {cr, c}; } -Contact3Handle ToxContactModel2::getContactGroupPeer(uint32_t group_number, uint32_t peer_number) { - Contact3 c = entt::null; +ContactHandle4 ToxContactModel2::getContactGroupPeer(uint32_t group_number, uint32_t peer_number) { + auto& cr = _cs.registry(); + Contact4 c{entt::null}; - Contact3Handle group_c = getContactGroup(group_number); + ContactHandle4 group_c = getContactGroup(group_number); assert(static_cast(group_c)); // first check contacts with peer id // TODO: lookup table - for (const auto e : _cr.view()) { - const auto& p_comp = _cr.get(e); + for (const auto e : cr.view()) { + const auto& p_comp = cr.get(e); if (p_comp.group_number == group_number && p_comp.peer_number == peer_number) { c = e; break; } } - if (_cr.valid(c)) { - return {_cr, c}; + if (cr.valid(c)) { + return {cr, c}; } const auto& g_key = group_c.get().chat_id; @@ -357,74 +418,83 @@ Contact3Handle ToxContactModel2::getContactGroupPeer(uint32_t group_number, uint } const ToxKey& g_p_key = g_p_key_opt.value(); - for (const auto e : _cr.view()) { - const auto& g_p_key_comp = _cr.get(e); + for (const auto e : cr.view()) { + const auto& g_p_key_comp = cr.get(e); if (g_p_key == g_p_key_comp.peer_key && g_key == g_p_key_comp.chat_id) { c = e; break; } } - if (_cr.valid(c)) { + if (cr.valid(c)) { // param numbers matches pubkey in db, add - _cr.emplace_or_replace(c, group_number, peer_number); + cr.emplace_or_replace(c, group_number, peer_number); - return {_cr, c}; + _cs.throwEventUpdate(c); + return {cr, c}; } // check for id (empty contact) and merge - for (const auto e : _cr.view()) { - if (g_p_key_opt.value() == _cr.get(e).data) { - c = e; - break; - } - } + //c = _cs.getOneContactByID(_root, ByteSpan{g_p_key_opt.value()}); + // technically it should be possible to have multiple contacts with the same ID in the same tox profile + // since ngcs have their own ids, and someone might have copied the keys and uses them in multiple + c = _cs.getOneContactByID(group_c, ByteSpan{g_p_key_opt.value()}); - if (!_cr.valid(c)) { + bool created{false}; + if (!cr.valid(c)) { // else, new ent - c = _cr.create(); - _cr.emplace(c, g_p_key_opt.value()); + c = cr.create(); + created = true; + cr.emplace(c, g_p_key_opt.value()); } - _cr.emplace_or_replace(c, group_c); + cr.emplace_or_replace(c, group_c); { // add sub to parent auto& parent_sub_list = group_c.get_or_emplace().subs; if (std::find(parent_sub_list.cbegin(), parent_sub_list.cend(), c) == parent_sub_list.cend()) { parent_sub_list.push_back(c); } } - _cr.emplace_or_replace(c, this); - _cr.emplace_or_replace(c, group_number, peer_number); - _cr.emplace_or_replace(c, g_key, g_p_key); - _cr.emplace_or_replace(c); + cr.emplace_or_replace(c, this); + cr.emplace_or_replace(c, group_number, peer_number); + cr.emplace_or_replace(c, g_key, g_p_key); + cr.emplace_or_replace(c); const auto name_opt = std::get<0>(_t.toxGroupPeerGetName(group_number, peer_number)); if (name_opt.has_value()) { - _cr.emplace_or_replace(c, name_opt.value()); + cr.emplace_or_replace(c, name_opt.value()); } { // self - // TODO: this is very flaky + // TODO: this is very flaky <- what did i mean with this + // since we have the group contact, self is likely working auto self_number_opt = _t.toxGroupSelfGetPeerId(group_number); - if (peer_number == self_number_opt.value()) { - _cr.emplace_or_replace(c); + if (self_number_opt.has_value()) { + if (peer_number == self_number_opt.value()) { + cr.emplace_or_replace(c); + } else { + cr.emplace_or_replace(c, getContactGroupPeer(group_number, self_number_opt.value())); + } } else { - _cr.emplace_or_replace(c, getContactGroupPeer(group_number, self_number_opt.value())); + std::cerr << "TCM2 error: getting self for group" << group_number << "!!\n"; } } std::cout << "TCM2: created group peer contact " << group_number << " " << peer_number << "\n"; - return {_cr, c}; + if (created) { + _cs.throwEventConstruct(c); + } else { + _cs.throwEventUpdate(c); + } + + return {cr, c}; } -//Contact3Handle ToxContactModel2::getContactGroupPeer(const ToxKey& group_key, const ToxKey& peer_key) { - //return {}; -//} +ContactHandle4 ToxContactModel2::getContactGroupPeer(uint32_t group_number, const ToxKey& peer_key) { + auto& cr = _cs.registry(); + Contact4 c{entt::null}; -Contact3Handle ToxContactModel2::getContactGroupPeer(uint32_t group_number, const ToxKey& peer_key) { - Contact3 c = entt::null; - - Contact3Handle group_c = getContactGroup(group_number); + auto group_c = getContactGroup(group_number); assert(static_cast(group_c)); @@ -432,57 +502,59 @@ Contact3Handle ToxContactModel2::getContactGroupPeer(uint32_t group_number, cons // search by key //_cr.view().each([&c, &g_key, &peer_key](const Contact3 e, const Contact::Components::ToxGroupPeerPersistent& g_p_key_comp) { - for (const auto e : _cr.view()) { - const auto& g_p_key_comp = _cr.get(e); + for (const auto e : cr.view()) { + const auto& g_p_key_comp = cr.get(e); if (peer_key == g_p_key_comp.peer_key && g_key == g_p_key_comp.chat_id) { c = e; break; } } - if (_cr.valid(c)) { - return {_cr, c}; + if (cr.valid(c)) { + return {cr, c}; } // TODO: maybe not create contacts via history sync // check for id (empty contact) and merge - const std::vector peer_key_vec{peer_key.data.cbegin(), peer_key.data.cend()}; - for (const auto e : _cr.view()) { - if (peer_key_vec == _cr.get(e).data) { - c = e; - break; - } - } + c = _cs.getOneContactByID(group_c, ByteSpan{peer_key.data}); - if (!_cr.valid(c)) { + bool created{false}; + if (!cr.valid(c)) { // else, new ent - c = _cr.create(); - _cr.emplace(c, peer_key_vec); + c = cr.create(); + created = true; + cr.emplace(c, std::vector(ByteSpan{peer_key.data})); } - _cr.emplace_or_replace(c, group_c); + cr.emplace_or_replace(c, group_c); { // add sub to parent auto& parent_sub_list = group_c.get_or_emplace().subs; if (std::find(parent_sub_list.cbegin(), parent_sub_list.cend(), c) == parent_sub_list.cend()) { parent_sub_list.push_back(c); } } - _cr.emplace_or_replace(c, this); - //_cr.emplace_or_replace(c, group_number, peer_number); - _cr.emplace_or_replace(c, g_key, peer_key); - _cr.emplace_or_replace(c); - //_cr.emplace_or_replace(c, ""); - //_cr.emplace_or_replace(c, std::get<0>(_t.toxGroupPeerGetName(group_number, peer_number)).value_or("")); + cr.emplace_or_replace(c, this); + //cr.emplace_or_replace(c, group_number, peer_number); + cr.emplace_or_replace(c, g_key, peer_key); + cr.emplace_or_replace(c); + //cr.emplace_or_replace(c, ""); + //cr.emplace_or_replace(c, std::get<0>(_t.toxGroupPeerGetName(group_number, peer_number)).value_or("")); { // self // TODO: this is very flaky auto self_number_opt = _t.toxGroupSelfGetPeerId(group_number); - _cr.emplace_or_replace(c, getContactGroupPeer(group_number, self_number_opt.value())); + cr.emplace_or_replace(c, getContactGroupPeer(group_number, self_number_opt.value())); } std::cout << "TCM2: created group peer contact via pubkey " << group_number << "\n"; - return {_cr, c}; + if (created) { + _cs.throwEventConstruct(c); + } else { + _cs.throwEventUpdate(c); + } + + return {cr, c}; } bool ToxContactModel2::groupPeerCanSpeak(uint32_t group_number, uint32_t peer_number) { @@ -524,17 +596,20 @@ bool ToxContactModel2::onToxEvent(const Tox_Event_Friend_Connection_Status* e) { } else { const auto ts = getTimeMS(); - _cr.emplace_or_replace(c, ts); + c.emplace_or_replace(ts); - if (!_cr.all_of(c)) { - _cr.emplace_or_replace(c, ts); + if (!c.all_of()) { + c.emplace_or_replace(ts); } } + _cs.throwEventUpdate(c); + return false; } bool ToxContactModel2::onToxEvent(const Tox_Event_Friend_Status* e) { + // TODO: add status codes (or strings?) and implement me //tox_event_friend_status_get_status(e); //TOX_USER_STATUS_NONE, @@ -542,6 +617,9 @@ bool ToxContactModel2::onToxEvent(const Tox_Event_Friend_Status* e) { //TOX_USER_STATUS_BUSY, //auto c = getContactFriend(tox_event_friend_status_get_friend_number(e)); + + //_cs.throwEventUpdate(c); + return false; } @@ -554,6 +632,8 @@ bool ToxContactModel2::onToxEvent(const Tox_Event_Friend_Name* e) { auto c = getContactFriend(tox_event_friend_name_get_friend_number(e)); c.emplace_or_replace(std::string{name}); + _cs.throwEventUpdate(c); + return false; // return true? } @@ -566,57 +646,65 @@ bool ToxContactModel2::onToxEvent(const Tox_Event_Friend_Status_Message* e) { auto c = getContactFriend(tox_event_friend_status_message_get_friend_number(e)); c.emplace_or_replace(std::string{status_message}).fillFirstLineLength(); + _cs.throwEventUpdate(c); + return false; // true? } bool ToxContactModel2::onToxEvent(const Tox_Event_Friend_Request* e) { const ToxKey pub_key{tox_event_friend_request_get_public_key(e), TOX_PUBLIC_KEY_SIZE}; - Contact3 c = entt::null; + auto& cr = _cs.registry(); + Contact4 c{entt::null}; // check for existing - for (const auto e : _cr.view()) { - if (pub_key == _cr.get(e).key) { + for (const auto e : cr.view()) { + if (pub_key == cr.get(e).key) { c = e; break; } } - if (_cr.valid(c)) { - _cr.emplace_or_replace(c); - _cr.remove(c); + if (cr.valid(c)) { + cr.emplace_or_replace(c); + cr.remove(c); std::cout << "TCM2: marked friend contact as requested\n"; + + _cs.throwEventUpdate(c); + return false; // return false, so tox_message can handle the message } // check for id (empty contact) and merge - const std::vector pub_key_vec{pub_key.data.cbegin(), pub_key.data.cend()}; - for (const auto e : _cr.view()) { - if (pub_key_vec == _cr.get(e).data) { - c = e; - break; - } - } + c = _cs.getOneContactByID(_root, ByteSpan{pub_key.data}); - if (!_cr.valid(c)) { + bool created{false}; + if (!cr.valid(c)) { // else, new ent - c = _cr.create(); - _cr.emplace(c, pub_key_vec); + c = cr.create(); + created = true; + cr.emplace(c, static_cast>(ByteSpan{pub_key.data})); } - _cr.emplace_or_replace(c); - _cr.emplace_or_replace(c); - _cr.emplace_or_replace(c, this); - _cr.emplace_or_replace(c, pub_key); - _cr.emplace_or_replace(c, _root); - _cr.get_or_emplace(_root).subs.push_back(c); - _cr.emplace_or_replace(c).subs.assign({_friend_self, c}); - _cr.emplace_or_replace(c); - _cr.emplace_or_replace(c, _friend_self); + cr.emplace_or_replace(c); + cr.emplace_or_replace(c); + cr.emplace_or_replace(c, this); + cr.emplace_or_replace(c, pub_key); + cr.emplace_or_replace(c, _root); + cr.get_or_emplace(_root).subs.push_back(c); + cr.emplace_or_replace(c).subs.assign({_friend_self, c}); + cr.emplace_or_replace(c); + cr.emplace_or_replace(c, _friend_self); std::cout << "TCM2: created friend contact (requested)\n"; + if (created) { + _cs.throwEventConstruct(c); + } else { + _cs.throwEventUpdate(c); + } + return false; // return false, so tox_message can handle the message } @@ -627,61 +715,63 @@ bool ToxContactModel2::onToxEvent(const Tox_Event_Group_Invite* e) { }; // HACK: extract chatid - // TODO: request better api + // TODO: request better api // I forgor assert(tox_event_group_invite_get_invite_data_length(e) == TOX_GROUP_CHAT_ID_SIZE + TOX_GROUP_PEER_PUBLIC_KEY_SIZE); const ToxKey chat_id{tox_event_group_invite_get_invite_data(e), TOX_GROUP_CHAT_ID_SIZE}; - Contact3 c = entt::null; + auto& cr = _cs.registry(); + Contact4 c{entt::null}; // check for existing - for (const auto e : _cr.view()) { - if (chat_id == _cr.get(e).chat_id) { + for (const auto e : cr.view()) { + if (chat_id == cr.get(e).chat_id) { c = e; break; } } - if (_cr.valid(c)) { + if (cr.valid(c)) { std::cout << "TCM2: already in group from invite\n"; return false; } // check for id (empty contact) and merge - const std::vector chat_id_vec{chat_id.data.cbegin(), chat_id.data.cend()}; - for (const auto e : _cr.view()) { - if (chat_id_vec == _cr.get(e).data) { - c = e; - break; - } - } + c = _cs.getOneContactByID(_root, ByteSpan{chat_id.data}); - if (!_cr.valid(c)) { + bool created{false}; + if (!cr.valid(c)) { // else, new ent - c = _cr.create(); - _cr.emplace(c, chat_id_vec); + c = cr.create(); + created = true; + cr.emplace(c, static_cast>(ByteSpan{chat_id.data})); } - _cr.emplace_or_replace(c, true, true); - _cr.emplace_or_replace(c); - _cr.emplace_or_replace(c, this); - _cr.emplace_or_replace(c, _root); - _cr.get_or_emplace(_root).subs.push_back(c); - _cr.emplace_or_replace(c, chat_id); - _cr.emplace_or_replace(c); - _cr.emplace_or_replace(c, std::string(group_name)); + cr.emplace_or_replace(c, true, true); + cr.emplace_or_replace(c); + cr.emplace_or_replace(c, this); + cr.emplace_or_replace(c, _root); + cr.get_or_emplace(_root).subs.push_back(c); + cr.emplace_or_replace(c, chat_id); + cr.emplace_or_replace(c); + cr.emplace_or_replace(c, std::string(group_name)); - auto& ir = _cr.emplace(c); + auto& ir = cr.emplace(c); ir.friend_number = tox_event_group_invite_get_friend_number(e); ir.invite_data = { tox_event_group_invite_get_invite_data(e), tox_event_group_invite_get_invite_data(e) + tox_event_group_invite_get_invite_data_length(e) }; - // TODO: self - //_cr.emplace(c, _friend_self); + // there is no self yet std::cout << "TCM2: created group contact (requested)\n"; + if (created) { + _cs.throwEventConstruct(c); + } else { + _cs.throwEventUpdate(c); + } + return false; } @@ -689,6 +779,11 @@ bool ToxContactModel2::onToxEvent(const Tox_Event_Group_Self_Join* e) { const uint32_t group_number = tox_event_group_self_join_get_group_number(e); if (const auto self_id_opt = _t.toxGroupSelfGetPeerId(group_number); self_id_opt.has_value()) { auto c = getContactGroupPeer(group_number, self_id_opt.value()); + + if (!static_cast(c)) { + return false; + } + c.emplace_or_replace(); c.emplace_or_replace(Contact::Components::ConnectionState::State::direct); @@ -699,6 +794,7 @@ bool ToxContactModel2::onToxEvent(const Tox_Event_Group_Self_Join* e) { ? Contact::Components::ConnectionState::State::cloud : Contact::Components::ConnectionState::State::disconnected ); + _cs.throwEventUpdate(gc); } else { assert(false); } @@ -712,6 +808,10 @@ bool ToxContactModel2::onToxEvent(const Tox_Event_Group_Peer_Join* e) { auto c = getContactGroupPeer(group_number, peer_number); + if (!static_cast(c)) { + return false; + } + // ensure its set c.emplace_or_replace(group_number, peer_number); @@ -724,18 +824,20 @@ bool ToxContactModel2::onToxEvent(const Tox_Event_Group_Peer_Join* e) { const auto ts = getTimeMS(); - _cr.emplace_or_replace(c, ts); + c.emplace_or_replace(ts); - if (!_cr.all_of(c)) { - _cr.emplace_or_replace(c, ts); + if (!c.all_of()) { + c.emplace_or_replace(ts); } // update name const auto name_opt = std::get<0>(_t.toxGroupPeerGetName(group_number, peer_number)); if (name_opt.has_value()) { - _cr.emplace_or_replace(c, name_opt.value()); + c.emplace_or_replace(name_opt.value()); } + _cs.throwEventUpdate(c); + return false; } @@ -761,6 +863,7 @@ bool ToxContactModel2::onToxEvent(const Tox_Event_Group_Peer_Exit* e) { } c.emplace_or_replace(Contact::Components::ConnectionState::State::disconnected); + _cs.throwEventUpdate(c); // HACK: throw update before removing ephemeral ids, so they can be used in the look up (but after setting disconnected) c.remove(); // TODO: produce system message with reason? @@ -784,9 +887,14 @@ bool ToxContactModel2::onToxEvent(const Tox_Event_Group_Peer_Name* e) { }; auto c = getContactGroupPeer(group_number, peer_number); + if (!static_cast(c)) { + return false; + } c.emplace_or_replace(std::string{name}); + _cs.throwEventUpdate(c); + return false; } @@ -799,8 +907,14 @@ bool ToxContactModel2::onToxEvent(const Tox_Event_Group_Topic* e) { }; auto c = getContactGroup(group_number); + if (!static_cast(c)) { + return false; + } + c.emplace_or_replace(std::string{topic}).fillFirstLineLength(); + _cs.throwEventUpdate(c); + return false; // message model needs to produce a system message } diff --git a/solanaceae/tox_contacts/tox_contact_model2.hpp b/solanaceae/tox_contacts/tox_contact_model2.hpp index 5f802c4..3096680 100644 --- a/solanaceae/tox_contacts/tox_contact_model2.hpp +++ b/solanaceae/tox_contacts/tox_contact_model2.hpp @@ -1,45 +1,49 @@ #pragma once #include -#include +#include #include // fwd struct ToxI; -// tox contact model for ContactModel3I -class ToxContactModel2 : public ContactModel3I, public ToxEventI { - Contact3Registry& _cr; +// tox contact model for ContactModel4I +class ToxContactModel2 : public ContactModel4I, public ToxEventI { + ContactStore4I& _cs; ToxI& _t; ToxEventProviderI::SubscriptionReference _tep_sr; - Contact3 _root; - Contact3 _friend_self; + Contact4 _root; + Contact4 _friend_self; float _group_status_timer {0.f}; public: - static constexpr const char* version {"3"}; + static constexpr const char* version {"4"}; - ToxContactModel2(Contact3Registry& cr, ToxI& t, ToxEventProviderI& tep); + ToxContactModel2(ContactStore4I& cs, ToxI& t, ToxEventProviderI& tep); virtual ~ToxContactModel2(void); // TODO: continually fetch group peer connection state, since JF does not want to add cb/event void iterate(float delta); protected: // mmi + bool addContact(Contact4 c) override; + // accept incoming request - void acceptRequest(Contact3 c, std::string_view self_name, std::string_view password) override; + bool acceptRequest(Contact4 c, std::string_view self_name, std::string_view password) override; + + bool leave(Contact4 c, std::string_view reason) override; public: // util for tox code // also creates if non existant - Contact3Handle getContactFriend(uint32_t friend_number); + ContactHandle4 getContactFriend(uint32_t friend_number); - Contact3Handle getContactGroup(uint32_t group_number); - Contact3Handle getContactGroupPeer(uint32_t group_number, uint32_t peer_number); - //Contact3Handle getContactGroupPeer(const ToxKey& group_key, const ToxKey& peer_key); - Contact3Handle getContactGroupPeer(uint32_t group_number, const ToxKey& peer_key); + ContactHandle4 getContactGroup(uint32_t group_number); + ContactHandle4 getContactGroupPeer(uint32_t group_number, uint32_t peer_number); + //ContactHandle4 getContactGroupPeer(const ToxKey& group_key, const ToxKey& peer_key); + ContactHandle4 getContactGroupPeer(uint32_t group_number, const ToxKey& peer_key); // TODO: add proper perm api to contacts bool groupPeerCanSpeak(uint32_t group_number, uint32_t peer_number); diff --git a/solanaceae/tox_messages/msg_components.hpp b/solanaceae/tox_messages/msg_components.hpp index 69044e7..432a3f4 100644 --- a/solanaceae/tox_messages/msg_components.hpp +++ b/solanaceae/tox_messages/msg_components.hpp @@ -1,7 +1,5 @@ #pragma once -#include - #include namespace Message::Components { diff --git a/solanaceae/tox_messages/tox_message_manager.cpp b/solanaceae/tox_messages/tox_message_manager.cpp index 758e8e1..57a1ac4 100644 --- a/solanaceae/tox_messages/tox_message_manager.cpp +++ b/solanaceae/tox_messages/tox_message_manager.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -17,14 +18,14 @@ ToxMessageManager::ToxMessageManager( RegistryMessageModelI& rmm, - Contact3Registry& cr, + ContactStore4I& cs, ToxContactModel2& tcm, ToxI& t, ToxEventProviderI& tep ) : _rmm(rmm), _rmm_sr(_rmm.newSubRef(this)), - _cr(cr), + _cs(cs), _tcm(tcm), _t(t), _tep_sr(tep.newSubRef(this)) @@ -52,8 +53,9 @@ ToxMessageManager::ToxMessageManager( ToxMessageManager::~ToxMessageManager(void) { } -bool ToxMessageManager::sendText(const Contact3 c, std::string_view message, bool action) { - if (!_cr.valid(c)) { +bool ToxMessageManager::sendText(const Contact4 c, std::string_view message, bool action) { + const auto& cr = _cs.registry(); + if (!cr.valid(c)) { return false; } @@ -61,12 +63,12 @@ bool ToxMessageManager::sendText(const Contact3 c, std::string_view message, boo return false; // TODO: empty messages allowed? } - if (_cr.all_of(c)) { + if (cr.all_of(c)) { return false; // message to self? not with tox } // testing for persistent is enough - if (!_cr.any_of< + if (!cr.any_of< Contact::Components::ToxFriendPersistent, // TODO: conf Contact::Components::ToxGroupPersistent, @@ -82,11 +84,11 @@ bool ToxMessageManager::sendText(const Contact3 c, std::string_view message, boo Message3Registry& reg = *reg_ptr; - if (!_cr.all_of(c)) { + if (!cr.all_of(c)) { std::cerr << "TMM error: cant get self\n"; return false; } - const Contact3 c_self = _cr.get(c).self; + const Contact4 c_self = cr.get(c).self; // get current time unix epoch utc uint64_t ts = getTimeMS(); @@ -114,8 +116,8 @@ bool ToxMessageManager::sendText(const Contact3 c, std::string_view message, boo reg.emplace(new_msg_e).ts[c_self] = ts; - if (_cr.any_of(c)) { - const uint32_t friend_number = _cr.get(c).friend_number; + if (cr.any_of(c)) { + const uint32_t friend_number = cr.get(c).friend_number; auto [res, _] = _t.toxFriendSendMessage( friend_number, @@ -132,16 +134,16 @@ bool ToxMessageManager::sendText(const Contact3 c, std::string_view message, boo } else { reg.emplace(new_msg_e, res.value()); } - } else if (_cr.any_of(c)) { + } else if (cr.any_of(c)) { // here we just assume friend not online (no ephemeral id) // set manually, so it can still be synced const uint32_t msg_id = randombytes_random(); reg.emplace(new_msg_e, msg_id); std::cerr << "TMM: failed to send friend message, offline and not in tox profile\n"; } else if ( - _cr.any_of(c) + cr.any_of(c) ) { - const uint32_t group_number = _cr.get(c).group_number; + const uint32_t group_number = cr.get(c).group_number; auto [message_id_opt, _] = _t.toxGroupSendMessage( group_number, @@ -164,7 +166,7 @@ bool ToxMessageManager::sendText(const Contact3 c, std::string_view message, boo } } else if ( // non online group - _cr.any_of(c) + cr.any_of(c) ) { // create msg_id const uint32_t msg_id = randombytes_random(); @@ -173,9 +175,9 @@ bool ToxMessageManager::sendText(const Contact3 c, std::string_view message, boo // TODO: generalize? reg.emplace(new_msg_e).ts.emplace(c_self, ts); } else if ( - _cr.any_of(c) + cr.any_of(c) ) { - const auto& numbers = _cr.get(c); + const auto& numbers = cr.get(c); auto [message_id_opt, _] = _t.toxGroupSendPrivateMessage( numbers.group_number, diff --git a/solanaceae/tox_messages/tox_message_manager.hpp b/solanaceae/tox_messages/tox_message_manager.hpp index 2bdd2f9..6ac4765 100644 --- a/solanaceae/tox_messages/tox_message_manager.hpp +++ b/solanaceae/tox_messages/tox_message_manager.hpp @@ -11,19 +11,20 @@ class ToxMessageManager : public RegistryMessageModelEventI, public ToxEventI { protected: RegistryMessageModelI& _rmm; RegistryMessageModelI::SubscriptionReference _rmm_sr; - Contact3Registry& _cr; + ContactStore4I& _cs; ToxContactModel2& _tcm; ToxI& _t; ToxEventProviderI::SubscriptionReference _tep_sr; public: - ToxMessageManager(RegistryMessageModelI& rmm, Contact3Registry& cr, ToxContactModel2& tcm, ToxI& t, ToxEventProviderI& tep); + ToxMessageManager(RegistryMessageModelI& rmm, ContactStore4I& cs, ToxContactModel2& tcm, ToxI& t, ToxEventProviderI& tep); virtual ~ToxMessageManager(void); public: // mm3 - bool sendText(const Contact3 c, std::string_view message, bool action = false) override; + bool sendText(const Contact4 c, std::string_view message, bool action = false) override; protected: // tox events + // TODO: add friend request message handling bool onToxEvent(const Tox_Event_Friend_Message* e) override; bool onToxEvent(const Tox_Event_Friend_Read_Receipt* e) override; diff --git a/solanaceae/tox_messages/tox_transfer_manager.cpp b/solanaceae/tox_messages/tox_transfer_manager.cpp index b6eaba1..8cf4d42 100644 --- a/solanaceae/tox_messages/tox_transfer_manager.cpp +++ b/solanaceae/tox_messages/tox_transfer_manager.cpp @@ -3,6 +3,7 @@ #include #include +#include #include @@ -11,8 +12,6 @@ #include #include "./msg_components.hpp" #include "./obj_components.hpp" -#include "solanaceae/object_store/meta_components.hpp" -#include "solanaceae/util/span.hpp" #include @@ -81,12 +80,12 @@ ObjectHandle ToxTransferManager::toxFriendLookupReceiving(const uint32_t friend_ ToxTransferManager::ToxTransferManager( RegistryMessageModelI& rmm, - Contact3Registry& cr, + ContactStore4I& cs, ToxContactModel2& tcm, ToxI& t, ToxEventProviderI& tep, ObjectStore2& os -) : _rmm(rmm), _rmm_sr(_rmm.newSubRef(this)), _cr(cr), _tcm(tcm), _t(t), _tep_sr(tep.newSubRef(this)), _os(os), _os_sr(_os.newSubRef(this)), _ftb(os) { +) : _rmm(rmm), _rmm_sr(_rmm.newSubRef(this)), _cs(cs), _tcm(tcm), _t(t), _tep_sr(tep.newSubRef(this)), _os(os), _os_sr(_os.newSubRef(this)), _ftb(os) { _tep_sr .subscribe(Tox_Event_Type::TOX_EVENT_FRIEND_CONNECTION_STATUS) .subscribe(Tox_Event_Type::TOX_EVENT_FILE_RECV) @@ -110,10 +109,11 @@ void ToxTransferManager::iterate(void) { // TODO: time out transfers } -Message3Handle ToxTransferManager::toxSendFilePath(const Contact3 c, uint32_t file_kind, std::string_view file_name, std::string_view file_path, std::vector file_id) { +Message3Handle ToxTransferManager::toxSendFilePath(const Contact4 c, uint32_t file_kind, std::string_view file_name, std::string_view file_path, std::vector file_id) { + const auto& cr = _cs.registry(); if ( // TODO: add support of offline queuing - !_cr.all_of(c) + !cr.all_of(c) ) { std::cerr << "TTM error: unsupported contact type\n"; return {}; @@ -142,8 +142,8 @@ Message3Handle ToxTransferManager::toxSendFilePath(const Contact3 c, uint32_t fi } assert(file_id.size() == 32); - const auto c_self = _cr.get(c).self; - if (!_cr.valid(c_self)) { + const auto c_self = cr.get(c).self; + if (!cr.valid(c_self)) { std::cerr << "TTM error: failed to get self!\n"; return {}; } @@ -173,7 +173,7 @@ Message3Handle ToxTransferManager::toxSendFilePath(const Contact3 c, uint32_t fi msg.emplace().ts.try_emplace(c_self, ts); msg.emplace(o); - const auto friend_number = _cr.get(c).friend_number; + const auto friend_number = cr.get(c).friend_number; const auto&& [transfer_id, err] = _t.toxFileSend(friend_number, file_kind, file_impl->_file_size, file_id, file_name); if (err == TOX_ERR_FILE_SEND_OK) { assert(transfer_id.has_value()); @@ -383,10 +383,11 @@ bool ToxTransferManager::accept(ObjectHandle transfer, std::string_view file_pat return true; } -bool ToxTransferManager::sendFilePath(const Contact3 c, std::string_view file_name, std::string_view file_path) { +bool ToxTransferManager::sendFilePath(const Contact4 c, std::string_view file_name, std::string_view file_path) { + const auto& cr = _cs.registry(); if ( // TODO: add support of offline queuing - !_cr.all_of(c) + !cr.all_of(c) ) { // TODO: add support for persistant friend filesends return false; @@ -504,7 +505,9 @@ bool ToxTransferManager::onToxEvent(const Tox_Event_File_Recv* e) { // get current time unix epoch utc uint64_t ts = getTimeMS(); - auto self_c = _cr.get(c).self; + const auto& cr = _cs.registry(); + + auto self_c = cr.get(c).self; o = _ftb.newObject(ByteSpan{f_id_opt.value()}, false); @@ -628,7 +631,7 @@ bool ToxTransferManager::onToxEvent(const Tox_Event_File_Recv_Chunk* e) { auto c = _tcm.getContactFriend(friend_number); if (static_cast(c)) { - auto self_c = _cr.get(c).self; + auto self_c = c.get().self; auto& rb = msg.get_or_emplace().ts; rb.try_emplace(self_c, ts); // on completion } diff --git a/solanaceae/tox_messages/tox_transfer_manager.hpp b/solanaceae/tox_messages/tox_transfer_manager.hpp index 6fe4c88..68646ec 100644 --- a/solanaceae/tox_messages/tox_transfer_manager.hpp +++ b/solanaceae/tox_messages/tox_transfer_manager.hpp @@ -7,8 +7,9 @@ #include "./backends/tox_ft_filesystem.hpp" -// switch to fwd or remove -#include +//#include +// fwd +struct File2I; #include @@ -20,12 +21,12 @@ struct ToxI; class ToxTransferManager : public RegistryMessageModelEventI, public ObjectStoreEventI, public ToxEventI { public: - static constexpr const char* version {"2"}; + static constexpr const char* version {"3"}; protected: RegistryMessageModelI& _rmm; RegistryMessageModelI::SubscriptionReference _rmm_sr; - Contact3Registry& _cr; + ContactStore4I& _cs; ToxContactModel2& _tcm; ToxI& _t; ToxEventProviderI::SubscriptionReference _tep_sr; @@ -48,7 +49,7 @@ class ToxTransferManager : public RegistryMessageModelEventI, public ObjectStore public: ToxTransferManager( RegistryMessageModelI& rmm, - Contact3Registry& cr, + ContactStore4I& cs, ToxContactModel2& tcm, ToxI& t, ToxEventProviderI& tep, @@ -59,7 +60,7 @@ class ToxTransferManager : public RegistryMessageModelEventI, public ObjectStore virtual void iterate(void); public: // TODO: private? - Message3Handle toxSendFilePath(const Contact3 c, uint32_t file_kind, std::string_view file_name, std::string_view file_path, std::vector file_id = {}); + Message3Handle toxSendFilePath(const Contact4 c, uint32_t file_kind, std::string_view file_name, std::string_view file_path, std::vector file_id = {}); bool resume(ObjectHandle transfer); bool pause(ObjectHandle transfer); @@ -72,7 +73,7 @@ class ToxTransferManager : public RegistryMessageModelEventI, public ObjectStore bool accept(ObjectHandle transfer, std::string_view file_path, bool path_is_file); protected: // (r)mm - bool sendFilePath(const Contact3 c, std::string_view file_name, std::string_view file_path) override; + bool sendFilePath(const Contact4 c, std::string_view file_name, std::string_view file_path) override; protected: // os //bool onEvent(const ObjectStore::Events::ObjectConstruct&) override;