sync and delivery (and unused read) states and other smaller refactors

This commit is contained in:
Green Sky 2024-01-12 16:45:52 +01:00
parent 7c576dd4d0
commit 20b4cdc5f1
No known key found for this signature in database
9 changed files with 147 additions and 25 deletions

@ -1 +1 @@
Subproject commit d0a53a6366e3f52e8c84d9fd63dd925ef93e10ce Subproject commit 4ae7c4068f91cedd4291521a5777af00c0ff052f

@ -1 +1 @@
Subproject commit c01d91144ce10486ff6e98a2e6e8cc5e20a5c412 Subproject commit 75ed1dffebe254d9cc79753d31f4c73c40238f72

@ -1 +1 @@
Subproject commit 80140ae9b6cc9d6280cfc8c16c6f8c3e40b51f2a Subproject commit 9d3d81d4ff55b152cb779cec2a37b960fcedd584

View File

@ -123,14 +123,20 @@ void ChatGui4::render(float time_delta) {
if (_selected_contact) { if (_selected_contact) {
const std::string chat_label = "chat " + std::to_string(entt::to_integral(*_selected_contact)); const std::string chat_label = "chat " + std::to_string(entt::to_integral(*_selected_contact));
const std::vector<Contact3>* sub_contacts = nullptr;
if (_cr.all_of<Contact::Components::ParentOf>(*_selected_contact)) {
sub_contacts = &_cr.get<Contact::Components::ParentOf>(*_selected_contact).subs;
}
if (ImGui::BeginChild(chat_label.c_str(), {0, 0}, true)) { if (ImGui::BeginChild(chat_label.c_str(), {0, 0}, true)) {
if (_cr.all_of<Contact::Components::ParentOf>(*_selected_contact)) { //if (_cr.all_of<Contact::Components::ParentOf>(*_selected_contact)) {
const auto sub_contacts = _cr.get<Contact::Components::ParentOf>(*_selected_contact).subs; if (sub_contacts != nullptr) {
if (!sub_contacts.empty()) { if (!sub_contacts->empty()) {
if (ImGui::BeginChild("subcontacts", {150, -100}, true)) { if (ImGui::BeginChild("subcontacts", {150, -100}, true)) {
ImGui::Text("subs: %zu", sub_contacts.size()); ImGui::Text("subs: %zu", sub_contacts->size());
ImGui::Separator(); ImGui::Separator();
for (const auto& c : sub_contacts) { for (const auto& c : *sub_contacts) {
// TODO: can a sub be selected? no // TODO: can a sub be selected? no
if (renderSubContactListContact(c, _selected_contact.has_value() && *_selected_contact == c)) { if (renderSubContactListContact(c, _selected_contact.has_value() && *_selected_contact == c)) {
_text_input_buffer.insert(0, (_cr.all_of<Contact::Components::Name>(c) ? _cr.get<Contact::Components::Name>(c).name : "<unk>") + ": "); _text_input_buffer.insert(0, (_cr.all_of<Contact::Components::Name>(c) ? _cr.get<Contact::Components::Name>(c).name : "<unk>") + ": ");
@ -233,9 +239,10 @@ void ChatGui4::render(float time_delta) {
ImGuiTableFlags_RowBg | ImGuiTableFlags_RowBg |
ImGuiTableFlags_SizingFixedFit ImGuiTableFlags_SizingFixedFit
; ;
if (msg_reg_ptr != nullptr && ImGui::BeginTable("chat_table", 4, table_flags)) { if (msg_reg_ptr != nullptr && ImGui::BeginTable("chat_table", 5, table_flags)) {
ImGui::TableSetupColumn("name", 0, TEXT_BASE_WIDTH * 15.f); ImGui::TableSetupColumn("name", 0, TEXT_BASE_WIDTH * 15.f);
ImGui::TableSetupColumn("message", ImGuiTableColumnFlags_WidthStretch); ImGui::TableSetupColumn("message", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableSetupColumn("delivered/read");
ImGui::TableSetupColumn("timestamp"); ImGui::TableSetupColumn("timestamp");
ImGui::TableSetupColumn("extra_info", _show_chat_extra_info ? ImGuiTableColumnFlags_None : ImGuiTableColumnFlags_Disabled); ImGui::TableSetupColumn("extra_info", _show_chat_extra_info ? ImGuiTableColumnFlags_None : ImGuiTableColumnFlags_Disabled);
@ -354,6 +361,84 @@ void ChatGui4::render(float time_delta) {
ImGui::TextDisabled("---"); ImGui::TextDisabled("---");
} }
// remote received and read state
if (ImGui::TableNextColumn()) {
// TODO: theming for hardcoded values
if (msg_reg.all_of<Message::Components::Remote::TimestampReceived>(e)) {
const auto list = msg_reg.get<Message::Components::Remote::TimestampReceived>(e).ts;
// wrongly assumes contacts never get removed from a group
if (sub_contacts != nullptr && list.size() < sub_contacts->size()) {
// if partically delivered
ImGui::TextColored(ImVec4{0.7f, 0.7f, 0.1f, 0.5f}, "d");
} else {
// if fully delivered
ImGui::TextColored(ImVec4{0.1f, 0.8f, 0.1f, 0.5f}, "D");
}
if (ImGui::BeginItemTooltip()) {
std::string synced_by_text {"delivery confirmed by:"};
const int64_t now_ts_s = int64_t(Message::getTimeMS() / 1000u);
for (const auto& [c, syned_ts] : list) {
if (_cr.all_of<Contact::Components::TagSelfStrong>(c)) {
synced_by_text += "\n sself(!)"; // makes no sense
} else if (_cr.all_of<Contact::Components::TagSelfWeak>(c)) {
synced_by_text += "\n wself";
} else {
synced_by_text += "\n >" + (_cr.all_of<Contact::Components::Name>(c) ? _cr.get<Contact::Components::Name>(c).name : "<unk>");
}
const int64_t seconds_ago = (int64_t(syned_ts / 1000u) - now_ts_s) * -1;
synced_by_text += " (" + std::to_string(seconds_ago) + "sec ago)";
}
ImGui::Text("%s", synced_by_text.c_str());
ImGui::EndTooltip();
}
} else {
ImGui::TextDisabled("_");
}
ImGui::SameLine();
// TODO: dedup
if (msg_reg.all_of<Message::Components::Remote::TimestampRead>(e)) {
const auto list = msg_reg.get<Message::Components::Remote::TimestampRead>(e).ts;
// wrongly assumes contacts never get removed from a group
if (sub_contacts != nullptr && list.size() < sub_contacts->size()) {
// if partially read
ImGui::TextColored(ImVec4{0.7f, 0.7f, 0.1f, 0.5f}, "r");
} else {
// if fully read
ImGui::TextColored(ImVec4{0.1f, 0.8f, 0.1f, 0.5f}, "R");
}
if (ImGui::BeginItemTooltip()) {
std::string synced_by_text {"read confirmed by:"};
const int64_t now_ts_s = int64_t(Message::getTimeMS() / 1000u);
for (const auto& [c, syned_ts] : list) {
if (_cr.all_of<Contact::Components::TagSelfStrong>(c)) {
synced_by_text += "\n sself(!)"; // makes no sense
} else if (_cr.all_of<Contact::Components::TagSelfWeak>(c)) {
synced_by_text += "\n wself";
} else {
synced_by_text += "\n >" + (_cr.all_of<Contact::Components::Name>(c) ? _cr.get<Contact::Components::Name>(c).name : "<unk>");
}
const int64_t seconds_ago = (int64_t(syned_ts / 1000u) - now_ts_s) * -1;
synced_by_text += " (" + std::to_string(seconds_ago) + "sec ago)";
}
ImGui::Text("%s", synced_by_text.c_str());
ImGui::EndTooltip();
}
} else {
ImGui::TextDisabled("_");
}
}
// ts // ts
if (ImGui::TableNextColumn()) { if (ImGui::TableNextColumn()) {
auto time = std::chrono::system_clock::to_time_t( auto time = std::chrono::system_clock::to_time_t(
@ -707,8 +792,9 @@ void ChatGui4::renderMessageExtra(Message3Registry& reg, const Message3 e) {
if (reg.all_of<Message::Components::SyncedBy>(e)) { if (reg.all_of<Message::Components::SyncedBy>(e)) {
std::string synced_by_text {"syncedBy:"}; std::string synced_by_text {"syncedBy:"};
const auto& synced_by = reg.get<Message::Components::SyncedBy>(e).list; const int64_t now_ts_s = int64_t(Message::getTimeMS() / 1000u);
for (const auto& c : synced_by) {
for (const auto& [c, syned_ts] : reg.get<Message::Components::SyncedBy>(e).ts) {
if (_cr.all_of<Contact::Components::TagSelfStrong>(c)) { if (_cr.all_of<Contact::Components::TagSelfStrong>(c)) {
synced_by_text += "\n sself"; synced_by_text += "\n sself";
} else if (_cr.all_of<Contact::Components::TagSelfWeak>(c)) { } else if (_cr.all_of<Contact::Components::TagSelfWeak>(c)) {
@ -716,7 +802,30 @@ void ChatGui4::renderMessageExtra(Message3Registry& reg, const Message3 e) {
} else { } else {
synced_by_text += "\n >" + (_cr.all_of<Contact::Components::Name>(c) ? _cr.get<Contact::Components::Name>(c).name : "<unk>"); synced_by_text += "\n >" + (_cr.all_of<Contact::Components::Name>(c) ? _cr.get<Contact::Components::Name>(c).name : "<unk>");
} }
const int64_t seconds_ago = (int64_t(syned_ts / 1000u) - now_ts_s) * -1;
synced_by_text += " (" + std::to_string(seconds_ago) + "sec ago)";
} }
ImGui::TextDisabled("%s", synced_by_text.c_str());
}
// TODO: remove?
if (reg.all_of<Message::Components::Remote::TimestampReceived>(e)) {
std::string synced_by_text {"receivedBy:"};
const int64_t now_ts_s = int64_t(Message::getTimeMS() / 1000u);
for (const auto& [c, syned_ts] : reg.get<Message::Components::Remote::TimestampReceived>(e).ts) {
if (_cr.all_of<Contact::Components::TagSelfStrong>(c)) {
synced_by_text += "\n sself(!)"; // makes no sense
} else if (_cr.all_of<Contact::Components::TagSelfWeak>(c)) {
synced_by_text += "\n wself";
} else {
synced_by_text += "\n >" + (_cr.all_of<Contact::Components::Name>(c) ? _cr.get<Contact::Components::Name>(c).name : "<unk>");
}
const int64_t seconds_ago = (int64_t(syned_ts / 1000u) - now_ts_s) * -1;
synced_by_text += " (" + std::to_string(seconds_ago) + "sec ago)";
}
ImGui::TextDisabled("%s", synced_by_text.c_str()); ImGui::TextDisabled("%s", synced_by_text.c_str());
} }
} }

View File

@ -12,6 +12,11 @@
#include <cassert> #include <cassert>
#include <vector> #include <vector>
// fwd
namespace Message {
uint64_t getTimeMS(void);
}
MessageImageLoader::MessageImageLoader(void) { MessageImageLoader::MessageImageLoader(void) {
_image_loaders.push_back(std::make_unique<ImageLoaderSDLBMP>()); _image_loaders.push_back(std::make_unique<ImageLoaderSDLBMP>());
_image_loaders.push_back(std::make_unique<ImageLoaderWebP>()); _image_loaders.push_back(std::make_unique<ImageLoaderWebP>());
@ -52,7 +57,7 @@ std::optional<TextureEntry> MessageImageLoader::load(TextureUploaderI& tu, Messa
} }
TextureEntry new_entry; TextureEntry new_entry;
new_entry.timestamp_last_rendered = getNowMS(); new_entry.timestamp_last_rendered = Message::getTimeMS();
new_entry.current_texture = 0; new_entry.current_texture = 0;
for (const auto& [ms, data] : res.frames) { for (const auto& [ms, data] : res.frames) {
const auto n_t = tu.uploadRGBA(data.data(), res.width, res.height); const auto n_t = tu.uploadRGBA(data.data(), res.width, res.height);

View File

@ -6,6 +6,11 @@
#include <imgui/imgui.h> #include <imgui/imgui.h>
// fwd
namespace Message {
uint64_t getTimeMS(void);
}
SendImagePopup::SendImagePopup(TextureUploaderI& tu) : _tu(tu) { SendImagePopup::SendImagePopup(TextureUploaderI& tu) : _tu(tu) {
_image_loaders.push_back(std::make_unique<ImageLoaderSDLBMP>()); _image_loaders.push_back(std::make_unique<ImageLoaderSDLBMP>());
_image_loaders.push_back(std::make_unique<ImageLoaderWebP>()); _image_loaders.push_back(std::make_unique<ImageLoaderWebP>());
@ -76,7 +81,7 @@ bool SendImagePopup::load(void) {
} }
} }
preview_image.timestamp_last_rendered = getNowMS(); preview_image.timestamp_last_rendered = Message::getTimeMS();
preview_image.current_texture = 0; preview_image.current_texture = 0;
for (const auto& [ms, data] : original_image.frames) { for (const auto& [ms, data] : original_image.frames) {
const auto n_t = _tu.uploadRGBA(data.data(), original_image.width, original_image.height); const auto n_t = _tu.uploadRGBA(data.data(), original_image.width, original_image.height);
@ -169,7 +174,7 @@ void SendImagePopup::render(float time_delta) {
const auto TEXT_BASE_WIDTH = ImGui::CalcTextSize("A").x; const auto TEXT_BASE_WIDTH = ImGui::CalcTextSize("A").x;
const auto TEXT_BASE_HEIGHT = ImGui::GetTextLineHeightWithSpacing(); const auto TEXT_BASE_HEIGHT = ImGui::GetTextLineHeightWithSpacing();
preview_image.doAnimation(getNowMS()); preview_image.doAnimation(Message::getTimeMS());
time += time_delta; time += time_delta;
time = fmod(time, 1.f); // fract() time = fmod(time, 1.f); // fract()

View File

@ -21,7 +21,7 @@ void TextureEntry::doAnimation(const int64_t ts_now) {
TextureEntry generateTestAnim(TextureUploaderI& tu) { TextureEntry generateTestAnim(TextureUploaderI& tu) {
TextureEntry new_entry; TextureEntry new_entry;
new_entry.timestamp_last_rendered = getNowMS(); new_entry.timestamp_last_rendered = Message::getTimeMS();
new_entry.current_texture = 0; new_entry.current_texture = 0;
for (size_t i = 0; i < 4; i++) { for (size_t i = 0; i < 4; i++) {
// hack // hack
@ -54,7 +54,3 @@ TextureEntry generateTestAnim(TextureUploaderI& tu) {
return new_entry; return new_entry;
} }
uint64_t getNowMS(void) {
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
}

View File

@ -71,8 +71,10 @@ struct TextureEntry {
TextureEntry generateTestAnim(TextureUploaderI& tu); TextureEntry generateTestAnim(TextureUploaderI& tu);
// TODO: move to utils or something // fwd
uint64_t getNowMS(void); namespace Message {
uint64_t getTimeMS(void);
}
template<typename TextureType, typename KeyType, class Loader> template<typename TextureType, typename KeyType, class Loader>
struct TextureCache { struct TextureCache {
@ -132,7 +134,7 @@ struct TextureCache {
} }
void update(void) { void update(void) {
const uint64_t ts_now = getNowMS(); const uint64_t ts_now = Message::getTimeMS();
std::vector<KeyType> to_purge; std::vector<KeyType> to_purge;
for (auto&& [key, te] : _cache) { for (auto&& [key, te] : _cache) {

View File

@ -14,6 +14,11 @@
#include <cassert> #include <cassert>
#include <vector> #include <vector>
// fwd
namespace Message {
uint64_t getTimeMS(void);
}
ToxAvatarLoader::ToxAvatarLoader(Contact3Registry& cr) : _cr(cr) { ToxAvatarLoader::ToxAvatarLoader(Contact3Registry& cr) : _cr(cr) {
_image_loaders.push_back(std::make_unique<ImageLoaderSDLBMP>()); _image_loaders.push_back(std::make_unique<ImageLoaderSDLBMP>());
_image_loaders.push_back(std::make_unique<ImageLoaderWebP>()); _image_loaders.push_back(std::make_unique<ImageLoaderWebP>());
@ -121,7 +126,7 @@ std::optional<TextureEntry> ToxAvatarLoader::load(TextureUploaderI& tu, Contact3
const auto& a_m = _cr.get<Contact::Components::AvatarMemory>(c); const auto& a_m = _cr.get<Contact::Components::AvatarMemory>(c);
TextureEntry new_entry; TextureEntry new_entry;
new_entry.timestamp_last_rendered = getNowMS(); new_entry.timestamp_last_rendered = Message::getTimeMS();
new_entry.current_texture = 0; new_entry.current_texture = 0;
new_entry.width = a_m.width; new_entry.width = a_m.width;
@ -159,7 +164,7 @@ std::optional<TextureEntry> ToxAvatarLoader::load(TextureUploaderI& tu, Contact3
} }
TextureEntry new_entry; TextureEntry new_entry;
new_entry.timestamp_last_rendered = getNowMS(); new_entry.timestamp_last_rendered = Message::getTimeMS();
new_entry.current_texture = 0; new_entry.current_texture = 0;
for (const auto& [ms, data] : res.frames) { for (const auto& [ms, data] : res.frames) {
const auto n_t = tu.uploadRGBA(data.data(), res.width, res.height); const auto n_t = tu.uploadRGBA(data.data(), res.width, res.height);
@ -195,7 +200,7 @@ std::optional<TextureEntry> ToxAvatarLoader::load(TextureUploaderI& tu, Contact3
} }
TextureEntry new_entry; TextureEntry new_entry;
new_entry.timestamp_last_rendered = getNowMS(); new_entry.timestamp_last_rendered = Message::getTimeMS();
new_entry.current_texture = 0; new_entry.current_texture = 0;
const auto n_t = tu.uploadRGBA(pixels.data(), 5, 5); const auto n_t = tu.uploadRGBA(pixels.data(), 5, 5);