continue transfer object refactor, re-enabling avatar receiving
Some checks failed
ContinuousDelivery / linux-ubuntu (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android-23]) (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:armeabi-v7a vcpkg_toolkit:arm-neon-android-23]) (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android-23]) (push) Has been cancelled
ContinuousDelivery / windows (push) Has been cancelled
ContinuousDelivery / windows-asan (push) Has been cancelled
ContinuousDelivery / dumpsyms (push) Has been cancelled
ContinuousDelivery / release (push) Has been cancelled
ContinuousIntegration / linux (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android-23]) (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:armeabi-v7a vcpkg_toolkit:arm-neon-android-23]) (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android-23]) (push) Has been cancelled
ContinuousIntegration / macos (push) Has been cancelled
ContinuousIntegration / windows (push) Has been cancelled
Some checks failed
ContinuousDelivery / linux-ubuntu (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android-23]) (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:armeabi-v7a vcpkg_toolkit:arm-neon-android-23]) (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android-23]) (push) Has been cancelled
ContinuousDelivery / windows (push) Has been cancelled
ContinuousDelivery / windows-asan (push) Has been cancelled
ContinuousDelivery / dumpsyms (push) Has been cancelled
ContinuousDelivery / release (push) Has been cancelled
ContinuousIntegration / linux (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android-23]) (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:armeabi-v7a vcpkg_toolkit:arm-neon-android-23]) (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android-23]) (push) Has been cancelled
ContinuousIntegration / macos (push) Has been cancelled
ContinuousIntegration / windows (push) Has been cancelled
This commit is contained in:
parent
7021e092b1
commit
2654cd1b19
2
external/solanaceae_contact
vendored
2
external/solanaceae_contact
vendored
@ -1 +1 @@
|
||||
Subproject commit 99d9633ff109321e78cf2817d3b8631d364a2483
|
||||
Subproject commit a5508ff6f3443ca5ca22ef0d7d91ac0f9319230f
|
2
external/solanaceae_message3
vendored
2
external/solanaceae_message3
vendored
@ -1 +1 @@
|
||||
Subproject commit 2a3828b30d7ec5fb9e7c8a8a82d1be66e040ea74
|
||||
Subproject commit c8e3e9374360fa241ccebd070e1d70abf6ba665b
|
2
external/solanaceae_object_store
vendored
2
external/solanaceae_object_store
vendored
@ -1 +1 @@
|
||||
Subproject commit 738e1a2071b95000bbed64e2262261cfbdc7dbab
|
||||
Subproject commit 889761f538eda8feb7ee0ea224c98e6ea05f6246
|
2
external/solanaceae_tox
vendored
2
external/solanaceae_tox
vendored
@ -1 +1 @@
|
||||
Subproject commit 4e75bd64aedf6c252456da0ca7c30a414f0fcaaf
|
||||
Subproject commit 7e12cdfb232a412f6052102fb9d8d3ceb04db4f4
|
@ -30,6 +30,9 @@ target_sources(tomato PUBLIC
|
||||
./main_screen.hpp
|
||||
./main_screen.cpp
|
||||
|
||||
./backends/std_fs.hpp
|
||||
./backends/std_fs.cpp
|
||||
|
||||
./tox_client.hpp
|
||||
./tox_client.cpp
|
||||
./auto_dirty.hpp
|
||||
|
107
src/backends/std_fs.cpp
Normal file
107
src/backends/std_fs.cpp
Normal file
@ -0,0 +1,107 @@
|
||||
#include "./std_fs.hpp"
|
||||
|
||||
#include <solanaceae/object_store/meta_components.hpp>
|
||||
#include <solanaceae/object_store/meta_components_file.hpp>
|
||||
|
||||
#include <solanaceae/file/file2_std.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace Backends {
|
||||
|
||||
STDFS::STDFS(
|
||||
ObjectStore2& os
|
||||
) : _os(os) {
|
||||
}
|
||||
|
||||
STDFS::~STDFS(void) {
|
||||
}
|
||||
|
||||
ObjectHandle STDFS::newObject(ByteSpan id, bool throw_construct) {
|
||||
ObjectHandle o{_os.registry(), _os.registry().create()};
|
||||
|
||||
o.emplace<ObjComp::Ephemeral::BackendMeta>(this); // ?
|
||||
o.emplace<ObjComp::Ephemeral::BackendFile2>(this);
|
||||
o.emplace<ObjComp::ID>(std::vector<uint8_t>{id});
|
||||
//o.emplace<ObjComp::Ephemeral::FilePath>(object_file_path.generic_u8string());
|
||||
|
||||
if (throw_construct) {
|
||||
_os.throwEventConstruct(o);
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
bool STDFS::attach(Object ov) {
|
||||
auto o = _os.objectHandle(ov);
|
||||
if (!static_cast<bool>(o)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (o.any_of<
|
||||
ObjComp::Ephemeral::BackendMeta,
|
||||
ObjComp::Ephemeral::BackendFile2
|
||||
>()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
o.emplace<ObjComp::Ephemeral::BackendMeta>(this); // ?
|
||||
o.emplace<ObjComp::Ephemeral::BackendFile2>(this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<File2I> STDFS::file2(Object ov, FILE2_FLAGS flags) {
|
||||
if (flags & FILE2_RAW) {
|
||||
std::cerr << "STDFS error: does not support raw modes\n";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (flags == FILE2_NONE) {
|
||||
std::cerr << "STDFS error: no file mode set\n";
|
||||
assert(false);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ObjectHandle o{_os.registry(), ov};
|
||||
|
||||
if (!static_cast<bool>(o)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// will this do if we go and support enc?
|
||||
// use ObjComp::Ephemeral::FilePath instead??
|
||||
if (!o.all_of<ObjComp::F::SingleInfoLocal>()) {
|
||||
std::cerr << "STDFS error: no SingleInfoLocal\n";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto& file_path = o.get<ObjComp::F::SingleInfoLocal>().file_path;
|
||||
if (file_path.empty()) {
|
||||
std::cerr << "STDFS error: SingleInfoLocal path empty\n";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<File2I> res;
|
||||
if ((flags & FILE2_WRITE) != 0 && (flags & FILE2_READ) != 0) {
|
||||
res = std::make_unique<File2RWFile>(file_path);
|
||||
} else if (flags & FILE2_READ) {
|
||||
res = std::make_unique<File2RFile>(file_path);
|
||||
} else if ((flags & FILE2_WRITE) && o.all_of<ObjComp::File::SingleInfo>()) {
|
||||
// HACK: use info and presize the file AND truncate
|
||||
// TODO: actually support streaming :P
|
||||
res = std::make_unique<File2RWFile>(file_path, o.get<ObjComp::File::SingleInfo>().file_size, true);
|
||||
} else if (flags & FILE2_WRITE) {
|
||||
res = std::make_unique<File2WFile>(file_path);
|
||||
}
|
||||
|
||||
if (!res || !res->isGood()) {
|
||||
std::cerr << "STDFS error: failed constructing file '" << file_path << "'\n";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
} // Backends
|
||||
|
24
src/backends/std_fs.hpp
Normal file
24
src/backends/std_fs.hpp
Normal file
@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <solanaceae/object_store/object_store.hpp>
|
||||
|
||||
namespace Backends {
|
||||
|
||||
struct STDFS : public StorageBackendIMeta, public StorageBackendIFile2 {
|
||||
ObjectStore2& _os;
|
||||
|
||||
STDFS(
|
||||
ObjectStore2& os
|
||||
);
|
||||
~STDFS(void);
|
||||
|
||||
ObjectHandle newObject(ByteSpan id, bool throw_construct = true) override;
|
||||
|
||||
// TODO: interface?
|
||||
bool attach(Object ov);
|
||||
|
||||
std::unique_ptr<File2I> file2(Object o, FILE2_FLAGS flags) override;
|
||||
};
|
||||
|
||||
} // Backends
|
||||
|
@ -55,9 +55,9 @@ MainScreen::MainScreen(const SimpleConfigModel& conf_, SDL_Renderer* renderer_,
|
||||
#endif
|
||||
theme(theme_),
|
||||
mmil(rmm),
|
||||
tam(/*rmm, */ os, cs, conf),
|
||||
tam(os, cs, conf, tcm),
|
||||
sdlrtu(renderer_),
|
||||
tal(cs),
|
||||
tal(cs, os),
|
||||
contact_tc(tal, sdlrtu),
|
||||
mil(),
|
||||
msg_tc(mil, sdlrtu),
|
||||
|
@ -8,6 +8,9 @@
|
||||
#include <solanaceae/contact/contact_store_i.hpp>
|
||||
#include <solanaceae/contact/components.hpp>
|
||||
#include <solanaceae/tox_contacts/components.hpp>
|
||||
#include <solanaceae/object_store/object_store.hpp>
|
||||
#include <solanaceae/object_store/meta_components_file.hpp>
|
||||
#include <solanaceae/file/file2.hpp>
|
||||
|
||||
#include <entt/entity/registry.hpp>
|
||||
|
||||
@ -18,7 +21,82 @@
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
|
||||
ToxAvatarLoader::ToxAvatarLoader(ContactStore4I& cs) : _cs(cs) {
|
||||
ByteSpanWithOwnership ToxAvatarLoader::loadDataFromObj(Contact4 cv) {
|
||||
auto c = _cs.contactHandle(cv);
|
||||
auto o = _os.objectHandle(c.get<Contact::Components::AvatarObj>().obj);
|
||||
if (!static_cast<bool>(o)) {
|
||||
std::cerr << "TAL error: avatar object set, but invalid\n";
|
||||
return ByteSpan{};
|
||||
}
|
||||
|
||||
if (!o.all_of<ObjComp::F::TagLocalHaveAll>()) {
|
||||
return ByteSpan{}; // we dont have all data
|
||||
}
|
||||
|
||||
if (!o.all_of<ObjComp::Ephemeral::BackendFile2, ObjComp::F::SingleInfo>()) {
|
||||
std::cerr << "TAL error: object missing file backend/file info (?)\n";
|
||||
return ByteSpan{};
|
||||
}
|
||||
|
||||
// TODO: handle collections
|
||||
const auto file_size = o.get<ObjComp::F::SingleInfo>().file_size;
|
||||
if (file_size > 2*1024*1024) {
|
||||
std::cerr << "TAL error: image file too large (" << file_size << " > 2MiB)\n";
|
||||
return ByteSpan{};
|
||||
}
|
||||
|
||||
auto* file_backend = o.get<ObjComp::Ephemeral::BackendFile2>().ptr;
|
||||
if (file_backend == nullptr) {
|
||||
std::cerr << "TAL error: object backend nullptr\n";
|
||||
return ByteSpan{};
|
||||
}
|
||||
|
||||
auto file2 = file_backend->file2(o, StorageBackendIFile2::FILE2_READ);
|
||||
if (!file2 || !file2->isGood() || !file2->can_read) {
|
||||
std::cerr << "TAL error: creating file2 from object via backendI\n";
|
||||
return ByteSpan{};
|
||||
}
|
||||
|
||||
auto read_data = file2->read(file_size, 0);
|
||||
if (read_data.ptr == nullptr) {
|
||||
std::cerr << "TAL error: reading from file2 returned nullptr\n";
|
||||
return ByteSpan{};
|
||||
}
|
||||
|
||||
if (read_data.size != file_size) {
|
||||
std::cerr << "TAL error: reading from file2 size missmatch, should be " << file_size << ", is " << read_data.size << "\n";
|
||||
return ByteSpan{};
|
||||
}
|
||||
|
||||
return read_data;
|
||||
}
|
||||
|
||||
ByteSpanWithOwnership ToxAvatarLoader::loadData(Contact4 cv) {
|
||||
auto c = _cs.contactHandle(cv);
|
||||
if (c.all_of<Contact::Components::AvatarFile>()) {
|
||||
// TODO: factor out
|
||||
const auto& a_f = c.get<Contact::Components::AvatarFile>();
|
||||
|
||||
std::vector<uint8_t> tmp_buffer;
|
||||
std::ifstream file(a_f.file_path, std::ios::binary);
|
||||
if (file.is_open()) {
|
||||
tmp_buffer = std::vector<uint8_t>{};
|
||||
while (file.good()) {
|
||||
auto ch = file.get();
|
||||
if (ch == EOF) {
|
||||
break;
|
||||
} else {
|
||||
tmp_buffer.push_back(ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
return tmp_buffer;
|
||||
} else { // obj assumed
|
||||
return loadDataFromObj(cv);
|
||||
}
|
||||
}
|
||||
|
||||
ToxAvatarLoader::ToxAvatarLoader(ContactStore4I& cs, ObjectStore2& os) : _cs(cs), _os(os) {
|
||||
_image_loaders.push_back(std::make_unique<ImageLoaderSDLBMP>());
|
||||
_image_loaders.push_back(std::make_unique<ImageLoaderQOI>());
|
||||
_image_loaders.push_back(std::make_unique<ImageLoaderWebP>());
|
||||
@ -142,24 +220,13 @@ TextureLoaderResult ToxAvatarLoader::load(TextureUploaderI& tu, Contact4 c) {
|
||||
return {new_entry};
|
||||
}
|
||||
|
||||
if (cr.all_of<Contact::Components::AvatarFile>(c)) {
|
||||
const auto& a_f = cr.get<Contact::Components::AvatarFile>(c);
|
||||
|
||||
std::ifstream file(a_f.file_path, std::ios::binary);
|
||||
if (file.is_open()) {
|
||||
std::vector<uint8_t> tmp_buffer;
|
||||
while (file.good()) {
|
||||
auto ch = file.get();
|
||||
if (ch == EOF) {
|
||||
break;
|
||||
} else {
|
||||
tmp_buffer.push_back(ch);
|
||||
}
|
||||
}
|
||||
if (cr.any_of<Contact::Components::AvatarFile, Contact::Components::AvatarObj>(c)) {
|
||||
const auto tmp_buffer = loadData(c);
|
||||
|
||||
if (!tmp_buffer.empty()) {
|
||||
// try all loaders after another
|
||||
for (auto& il : _image_loaders) {
|
||||
auto res = il->loadFromMemoryRGBA(tmp_buffer.data(), tmp_buffer.size());
|
||||
auto res = il->loadFromMemoryRGBA(tmp_buffer.ptr, tmp_buffer.size);
|
||||
if (res.frames.empty() || res.height == 0 || res.width == 0) {
|
||||
continue;
|
||||
}
|
||||
@ -176,7 +243,11 @@ TextureLoaderResult ToxAvatarLoader::load(TextureUploaderI& tu, Contact4 c) {
|
||||
new_entry.width = res.width;
|
||||
new_entry.height = res.height;
|
||||
|
||||
std::cout << "TAL: loaded image file " << a_f.file_path << "\n";
|
||||
if (cr.all_of<Contact::Components::AvatarFile>(c)) {
|
||||
std::cout << "TAL: loaded image file " << cr.get<Contact::Components::AvatarFile>(c).file_path << "\n";
|
||||
} else {
|
||||
std::cout << "TAL: loaded image object " << entt::to_integral(cr.get<Contact::Components::AvatarObj>(c).obj) << "\n";
|
||||
}
|
||||
|
||||
return {new_entry};
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <solanaceae/contact/fwd.hpp>
|
||||
#include <solanaceae/object_store/fwd.hpp>
|
||||
|
||||
#include <solanaceae/file/file2.hpp>
|
||||
|
||||
#include "./image_loader.hpp"
|
||||
#include "./texture_cache.hpp"
|
||||
@ -9,11 +12,15 @@
|
||||
|
||||
class ToxAvatarLoader {
|
||||
ContactStore4I& _cs;
|
||||
ObjectStore2& _os;
|
||||
|
||||
std::vector<std::unique_ptr<ImageLoaderI>> _image_loaders;
|
||||
|
||||
ByteSpanWithOwnership loadDataFromObj(Contact4 cv);
|
||||
ByteSpanWithOwnership loadData(Contact4 cv);
|
||||
|
||||
public:
|
||||
ToxAvatarLoader(ContactStore4I& cr);
|
||||
ToxAvatarLoader(ContactStore4I& cs, ObjectStore2& os);
|
||||
TextureLoaderResult load(TextureUploaderI& tu, Contact4 c);
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include "./tox_avatar_manager.hpp"
|
||||
|
||||
// TODO: this whole thing needs a rewrite and is currently disabled
|
||||
// TODO: this whole thing needs a rewrite, seperating tcs and rng uid os
|
||||
|
||||
#include <solanaceae/util/config_model.hpp>
|
||||
|
||||
@ -33,11 +33,13 @@ namespace Components {
|
||||
ToxAvatarManager::ToxAvatarManager(
|
||||
ObjectStore2& os,
|
||||
ContactStore4I& cs,
|
||||
ConfigModelI& conf
|
||||
) : _os(os), _os_sr(_os.newSubRef(this)), _cs(cs), _conf(conf) {
|
||||
ConfigModelI& conf,
|
||||
ToxContactModel2& tcm
|
||||
) : _os(os), _os_sr(_os.newSubRef(this)), _cs(cs), _conf(conf), _tcm(tcm), _sb_tcs(os) {
|
||||
_os_sr
|
||||
.subscribe(ObjectStore_Event::object_construct)
|
||||
.subscribe(ObjectStore_Event::object_update)
|
||||
.subscribe(ObjectStore_Event::object_destroy)
|
||||
;
|
||||
|
||||
if (!_conf.has_string("ToxAvatarManager", "save_path")) {
|
||||
@ -45,20 +47,21 @@ ToxAvatarManager::ToxAvatarManager(
|
||||
_conf.set("ToxAvatarManager", "save_path", std::string_view{"tmp_avatar_dir"});
|
||||
}
|
||||
|
||||
//_conf.set("TransferAutoAccept", "autoaccept_limit", int64_t(50l*1024l*1024l)); // sane default
|
||||
|
||||
const std::string_view avatar_save_path {_conf.get_string("ToxAvatarManager", "save_path").value()};
|
||||
// make sure it exists
|
||||
std::filesystem::create_directories(avatar_save_path);
|
||||
|
||||
// TODO: instead listen for new contacts, and attach
|
||||
{ // scan tox contacts for cached avatars
|
||||
// old sts says pubkey.png
|
||||
|
||||
_cs.registry().view<Contact::Components::ToxFriendPersistent>().each([this](auto c, const Contact::Components::ToxFriendPersistent& tox_pers) {
|
||||
// try
|
||||
addAvatarFileToContact(c, tox_pers.key);
|
||||
});
|
||||
|
||||
_cs.registry().view<Contact::Components::ToxGroupPersistent>().each([this](auto c, const Contact::Components::ToxGroupPersistent& tox_pers) {
|
||||
// try
|
||||
addAvatarFileToContact(c, tox_pers.chat_id);
|
||||
});
|
||||
|
||||
@ -88,30 +91,70 @@ void ToxAvatarManager::iterate(void) {
|
||||
|
||||
std::string ToxAvatarManager::getAvatarPath(const ToxKey& key) const {
|
||||
const std::string_view avatar_save_path {_conf.get_string("ToxAvatarManager", "save_path").value()};
|
||||
const auto pub_key_string = bin2hex({key.data.cbegin(), key.data.cend()});
|
||||
const auto file_path = std::filesystem::path(avatar_save_path) / (pub_key_string + ".png");
|
||||
const auto file_path = std::filesystem::path(avatar_save_path) / getAvatarFileName(key);
|
||||
return file_path.generic_u8string();
|
||||
}
|
||||
|
||||
std::string ToxAvatarManager::getAvatarFileName(const ToxKey& key) const {
|
||||
const auto pub_key_string = bin2hex({key.data.cbegin(), key.data.cend()});
|
||||
return pub_key_string + ".png"; // TODO: remove png?
|
||||
}
|
||||
|
||||
void ToxAvatarManager::addAvatarFileToContact(const Contact4 c, const ToxKey& key) {
|
||||
const auto file_path = getAvatarPath(key);
|
||||
if (std::filesystem::is_regular_file(file_path)) {
|
||||
// avatar file png file exists
|
||||
_cs.registry().emplace_or_replace<Contact::Components::AvatarFile>(c, file_path);
|
||||
_cs.registry().emplace_or_replace<Contact::Components::TagAvatarInvalidate>(c);
|
||||
|
||||
_cs.throwEventUpdate(c);
|
||||
if (!std::filesystem::is_regular_file(file_path)) {
|
||||
return;
|
||||
}
|
||||
|
||||
//std::cout << "TAM: found '" << file_path << "'\n";
|
||||
|
||||
// TODO: use guid instead
|
||||
auto o = _sb_tcs.newObject(ByteSpan{key.data}, false);
|
||||
o.emplace_or_replace<ObjComp::F::SingleInfoLocal>(file_path);
|
||||
o.emplace_or_replace<ObjComp::F::TagLocalHaveAll>();
|
||||
|
||||
// for file size
|
||||
o.emplace_or_replace<ObjComp::F::SingleInfo>(
|
||||
getAvatarFileName(key),
|
||||
std::filesystem::file_size(file_path)
|
||||
);
|
||||
|
||||
_os.throwEventConstruct(o);
|
||||
|
||||
// avatar file "png" exists
|
||||
//_cs.registry().emplace_or_replace<Contact::Components::AvatarFile>(c, file_path);
|
||||
_cs.registry().emplace_or_replace<Contact::Components::AvatarObj>(c, o);
|
||||
_cs.registry().emplace_or_replace<Contact::Components::TagAvatarInvalidate>(c);
|
||||
|
||||
_cs.throwEventUpdate(c);
|
||||
}
|
||||
|
||||
void ToxAvatarManager::clearAvatarFromContact(const Contact4 c) {
|
||||
auto& cr = _cs.registry();
|
||||
if (cr.all_of<Contact::Components::AvatarFile>(c)) {
|
||||
std::filesystem::remove(cr.get<Contact::Components::AvatarFile>(c).file_path);
|
||||
cr.remove<Contact::Components::AvatarFile>(c);
|
||||
if (cr.any_of<Contact::Components::AvatarFile, Contact::Components::AvatarObj>(c)) {
|
||||
if (cr.all_of<Contact::Components::AvatarFile>(c)) {
|
||||
std::filesystem::remove(cr.get<Contact::Components::AvatarFile>(c).file_path);
|
||||
} else if (cr.all_of<Contact::Components::AvatarObj>(c)) {
|
||||
auto o = _os.objectHandle(cr.get<Contact::Components::AvatarObj>(c).obj);
|
||||
if (o) {
|
||||
if (o.all_of<ObjComp::F::SingleInfoLocal>()) {
|
||||
std::filesystem::remove(o.get<ObjComp::F::SingleInfoLocal>().file_path);
|
||||
}
|
||||
// TODO: make destruction more ergonomic
|
||||
//_sb_tcs.destroy() ??
|
||||
_os.throwEventDestroy(o);
|
||||
o.destroy();
|
||||
}
|
||||
}
|
||||
cr.remove<
|
||||
Contact::Components::AvatarFile,
|
||||
Contact::Components::AvatarObj
|
||||
>(c);
|
||||
cr.emplace_or_replace<Contact::Components::TagAvatarInvalidate>(c);
|
||||
|
||||
_cs.throwEventUpdate(c);
|
||||
|
||||
std::cout << "TAM: cleared avatar from " << entt::to_integral(c) << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
@ -131,13 +174,12 @@ void ToxAvatarManager::checkObj(ObjectHandle o) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: non tox code path?
|
||||
if (!o.all_of<
|
||||
ObjComp::Tox::TagIncomming,
|
||||
//ObjComp::Ephemeral::Backend,
|
||||
ObjComp::F::SingleInfo,
|
||||
ObjComp::Tox::FileKind
|
||||
// TODO: mesage? how do we know where a file is from??
|
||||
//Message::Components::ContactFrom // should always be there, just making sure
|
||||
ObjComp::Tox::FileKind,
|
||||
ObjComp::Ephemeral::ToxContact
|
||||
>()) {
|
||||
return;
|
||||
}
|
||||
@ -159,10 +201,14 @@ void ToxAvatarManager::checkObj(ObjectHandle o) {
|
||||
return; // too large
|
||||
}
|
||||
|
||||
#if 0 // TODO: make avatars work again !!!!!
|
||||
auto contact = o.get<ObjComp::Ephemeral::ToxContact>().c;
|
||||
if (!static_cast<bool>(contact)) {
|
||||
std::cerr << "TAM error: failed to attribute object to contact\n";
|
||||
}
|
||||
|
||||
// TCS-2.2.10
|
||||
if (file_info.file_name.empty() || file_info.file_size == 0) {
|
||||
std::cout << "TAM: no filename or filesize, deleting avatar\n";
|
||||
// reset
|
||||
clearAvatarFromContact(contact);
|
||||
// TODO: cancel
|
||||
@ -175,30 +221,38 @@ void ToxAvatarManager::checkObj(ObjectHandle o) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string file_path;
|
||||
if (_cr.all_of<Contact::Components::ToxFriendPersistent>(contact)) {
|
||||
file_path = getAvatarPath(_cr.get<Contact::Components::ToxFriendPersistent>(contact).key);
|
||||
} else if (_cr.all_of<Contact::Components::ToxGroupPersistent>(contact)) {
|
||||
file_path = getAvatarPath(_cr.get<Contact::Components::ToxGroupPersistent>(contact).chat_id);
|
||||
} else {
|
||||
std::cerr << "TAM error: cant get toxkey for contact\n";
|
||||
// TODO: mark handled?
|
||||
return;
|
||||
}
|
||||
|
||||
if (o.all_of<ObjComp::F::TagLocalHaveAll>()) {
|
||||
std::cout << "TAM: full avatar received\n";
|
||||
|
||||
if (_cr.all_of<Contact::Components::ToxFriendPersistent>(contact)) {
|
||||
addAvatarFileToContact(contact, _cr.get<Contact::Components::ToxFriendPersistent>(contact).key);
|
||||
} else if (_cr.all_of<Contact::Components::ToxGroupPersistent>(contact)) {
|
||||
addAvatarFileToContact(contact, _cr.get<Contact::Components::ToxGroupPersistent>(contact).chat_id);
|
||||
} else {
|
||||
std::cerr << "TAM error: cant get toxkey for contact\n";
|
||||
}
|
||||
// old code no longer works, we already have the object (right here lol)
|
||||
|
||||
contact.emplace_or_replace<Contact::Components::AvatarObj>(o);
|
||||
contact.emplace_or_replace<Contact::Components::TagAvatarInvalidate>();
|
||||
|
||||
o.emplace_or_replace<Components::TagAvatarImageHandled>();
|
||||
} else {
|
||||
} else if (!o.all_of<
|
||||
ObjComp::Ephemeral::BackendMeta, // hmm
|
||||
ObjComp::Ephemeral::BackendFile2,
|
||||
ObjComp::Ephemeral::BackendAtomic // to be safe
|
||||
>()) {
|
||||
std::string file_path;
|
||||
if (contact.all_of<Contact::Components::ToxFriendPersistent>()) {
|
||||
file_path = getAvatarPath(contact.get<Contact::Components::ToxFriendPersistent>().key);
|
||||
} else if (contact.all_of<Contact::Components::ToxGroupPersistent>()) {
|
||||
file_path = getAvatarPath(contact.get<Contact::Components::ToxGroupPersistent>().chat_id);
|
||||
} else {
|
||||
std::cerr << "TAM error: cant get toxkey for contact\n";
|
||||
// TODO: mark handled?
|
||||
return;
|
||||
}
|
||||
|
||||
// already has avatar, delete old (TODO: or check hash)
|
||||
if (contact.all_of<Contact::Components::AvatarObj>()) {
|
||||
clearAvatarFromContact(contact);
|
||||
}
|
||||
|
||||
// crude
|
||||
// TODO: queue/async instead
|
||||
// check file id for existing hash
|
||||
if (std::filesystem::is_regular_file(file_path)) {
|
||||
//const auto& supposed_file_hash = h.get<Message::Components::Transfer::FileID>().id;
|
||||
@ -209,12 +263,18 @@ void ToxAvatarManager::checkObj(ObjectHandle o) {
|
||||
std::filesystem::remove(file_path); // hack, hard replace existing file
|
||||
}
|
||||
|
||||
std::cout << "TAM: accepted avatar ft\n";
|
||||
if (!_sb_tcs.attach(o)) {
|
||||
std::cerr << "TAM error: failed to attach backend??\n";
|
||||
return;
|
||||
}
|
||||
|
||||
// if not already on disk
|
||||
_accept_queue.push_back(AcceptEntry{o, file_path});
|
||||
o.emplace_or_replace<ObjComp::F::SingleInfoLocal>(file_path);
|
||||
|
||||
// ... do we do anything here?
|
||||
// like set "accepted" tag comp or something
|
||||
|
||||
std::cout << "TAM: accepted avatar ft\n";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool ToxAvatarManager::onEvent(const ObjectStore::Events::ObjectConstruct& e) {
|
||||
@ -227,3 +287,42 @@ bool ToxAvatarManager::onEvent(const ObjectStore::Events::ObjectUpdate& e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ToxAvatarManager::onEvent(const ObjectStore::Events::ObjectDestory& e) {
|
||||
// TODO: avatar contact comp instead?
|
||||
// TODO: generic contact comp? (hard, very usecase dep)
|
||||
#if 0
|
||||
if (!e.e.all_of<ObjComp::Ephemeral::File::Sender>()) {
|
||||
// cant be reasonable be attributed to a contact
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: remove obj from contact
|
||||
#endif
|
||||
if (!e.e.all_of<ObjComp::Ephemeral::ToxContact>()) {
|
||||
// cant be reasonable be attributed to a contact
|
||||
return false;
|
||||
}
|
||||
|
||||
auto c = e.e.get<ObjComp::Ephemeral::ToxContact>().c;
|
||||
if (!static_cast<bool>(c)) {
|
||||
// meh
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!c.all_of<Contact::Components::AvatarObj>()) {
|
||||
// funny
|
||||
return false;
|
||||
}
|
||||
|
||||
if (c.get<Contact::Components::AvatarObj>().obj != e.e) {
|
||||
// maybe got replace?
|
||||
// TODO: make error and do proper cleanup
|
||||
return false;
|
||||
}
|
||||
|
||||
c.remove<Contact::Components::AvatarObj>();
|
||||
c.emplace_or_replace<Contact::Components::TagAvatarInvalidate>();
|
||||
// TODO: throw contact update!!!
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -2,6 +2,9 @@
|
||||
|
||||
#include <solanaceae/object_store/object_store.hpp>
|
||||
#include <solanaceae/contact/fwd.hpp>
|
||||
#include <solanaceae/tox_contacts/tox_contact_model2.hpp>
|
||||
|
||||
#include "./backends/std_fs.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@ -17,6 +20,9 @@ class ToxAvatarManager : public ObjectStoreEventI {
|
||||
ObjectStore2::SubscriptionReference _os_sr;
|
||||
ContactStore4I& _cs;
|
||||
ConfigModelI& _conf;
|
||||
ToxContactModel2& _tcm;
|
||||
|
||||
Backends::STDFS _sb_tcs;
|
||||
|
||||
struct AcceptEntry {
|
||||
ObjectHandle m;
|
||||
@ -28,7 +34,8 @@ class ToxAvatarManager : public ObjectStoreEventI {
|
||||
ToxAvatarManager(
|
||||
ObjectStore2& os,
|
||||
ContactStore4I& cs,
|
||||
ConfigModelI& conf
|
||||
ConfigModelI& conf,
|
||||
ToxContactModel2& tcm
|
||||
);
|
||||
|
||||
void iterate(void);
|
||||
@ -36,12 +43,15 @@ class ToxAvatarManager : public ObjectStoreEventI {
|
||||
protected:
|
||||
// TODO: become backend and work in objects instead
|
||||
std::string getAvatarPath(const ToxKey& key) const;
|
||||
std::string getAvatarFileName(const ToxKey& key) const;
|
||||
void addAvatarFileToContact(const Contact4 c, const ToxKey& key);
|
||||
void clearAvatarFromContact(const Contact4 c);
|
||||
void checkObj(ObjectHandle o);
|
||||
|
||||
protected: // os
|
||||
// on new obj, check for ToxTransferFriend and emplace own contact tracker
|
||||
bool onEvent(const ObjectStore::Events::ObjectConstruct& e) override;
|
||||
bool onEvent(const ObjectStore::Events::ObjectUpdate& e) override;
|
||||
bool onEvent(const ObjectStore::Events::ObjectDestory& e) override;
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user