Compare commits
	
		
			9 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| b56d581e4b | |||
| aa661aaaa7 | |||
| cc3f430bab | |||
| 139db5b03b | |||
| 7d0e5c80bd | |||
| f716ad9dd1 | |||
| 671772a20e | |||
| b0173f6d68 | |||
| 3da5872df8 | 
							
								
								
									
										2
									
								
								external/solanaceae_contact
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
							
						
						
									
										2
									
								
								external/solanaceae_contact
									
									
									
									
										vendored
									
									
								
							 Submodule external/solanaceae_contact updated: 2d73c7272c...9ca6adee4f
									
								
							
							
								
								
									
										2
									
								
								external/solanaceae_message3
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
							
						
						
									
										2
									
								
								external/solanaceae_message3
									
									
									
									
										vendored
									
									
								
							 Submodule external/solanaceae_message3 updated: ab282235b5...a1f5add8d3
									
								
							
							
								
								
									
										2
									
								
								external/solanaceae_plugin
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
							
						
						
									
										2
									
								
								external/solanaceae_plugin
									
									
									
									
										vendored
									
									
								
							 Submodule external/solanaceae_plugin updated: 17ffaee013...82cfb6d492
									
								
							
							
								
								
									
										2
									
								
								external/solanaceae_util
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
							
						
						
									
										2
									
								
								external/solanaceae_util
									
									
									
									
										vendored
									
									
								
							 Submodule external/solanaceae_util updated: 390b123fb7...d304d719e9
									
								
							@@ -37,7 +37,7 @@ namespace Components {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
} // Components
 | 
					} // Components
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static float lerp(float a, float b, float t) {
 | 
					static constexpr float lerp(float a, float b, float t) {
 | 
				
			||||||
	return a + t * (b - a);
 | 
						return a + t * (b - a);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -121,8 +121,10 @@ ChatGui4::ChatGui4(
 | 
				
			|||||||
	ConfigModelI& conf,
 | 
						ConfigModelI& conf,
 | 
				
			||||||
	RegistryMessageModel& rmm,
 | 
						RegistryMessageModel& rmm,
 | 
				
			||||||
	Contact3Registry& cr,
 | 
						Contact3Registry& cr,
 | 
				
			||||||
	TextureUploaderI& tu
 | 
						TextureUploaderI& tu,
 | 
				
			||||||
) : _conf(conf), _rmm(rmm), _cr(cr), _tal(_cr), _contact_tc(_tal, tu), _msg_tc(_mil, tu), _sip(tu) {
 | 
						ContactTextureCache& contact_tc,
 | 
				
			||||||
 | 
						MessageTextureCache& msg_tc
 | 
				
			||||||
 | 
					) : _conf(conf), _rmm(rmm), _cr(cr), _contact_tc(contact_tc), _msg_tc(msg_tc), _sip(tu) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ChatGui4::~ChatGui4(void) {
 | 
					ChatGui4::~ChatGui4(void) {
 | 
				
			||||||
@@ -136,20 +138,7 @@ ChatGui4::~ChatGui4(void) {
 | 
				
			|||||||
	//}
 | 
						//}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ChatGui4::render(float time_delta) {
 | 
					float ChatGui4::render(float time_delta) {
 | 
				
			||||||
	if (!_cr.storage<Contact::Components::TagAvatarInvalidate>().empty()) { // handle force-reloads for avatars
 | 
					 | 
				
			||||||
		std::vector<Contact3> to_purge;
 | 
					 | 
				
			||||||
		_cr.view<Contact::Components::TagAvatarInvalidate>().each([&to_purge](const Contact3 c) {
 | 
					 | 
				
			||||||
			to_purge.push_back(c);
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
		_cr.remove<Contact::Components::TagAvatarInvalidate>(to_purge.cbegin(), to_purge.cend());
 | 
					 | 
				
			||||||
		_contact_tc.invalidate(to_purge);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// ACTUALLY NOT IF RENDERED, MOVED LOGIC TO ABOVE
 | 
					 | 
				
			||||||
	// it might unload textures, so it needs to be done before rendering
 | 
					 | 
				
			||||||
	_contact_tc.update();
 | 
					 | 
				
			||||||
	_msg_tc.update();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	_fss.render();
 | 
						_fss.render();
 | 
				
			||||||
	_sip.render(time_delta);
 | 
						_sip.render(time_delta);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -627,8 +616,7 @@ void ChatGui4::render(float time_delta) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	ImGui::End();
 | 
						ImGui::End();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_contact_tc.workLoadQueue();
 | 
						return 1000.f; // TODO: higher min fps?
 | 
				
			||||||
	_msg_tc.workLoadQueue();
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ChatGui4::sendFilePath(const char* file_path) {
 | 
					void ChatGui4::sendFilePath(const char* file_path) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,7 +9,8 @@
 | 
				
			|||||||
#include "./message_image_loader.hpp"
 | 
					#include "./message_image_loader.hpp"
 | 
				
			||||||
#include "./file_selector.hpp"
 | 
					#include "./file_selector.hpp"
 | 
				
			||||||
#include "./send_image_popup.hpp"
 | 
					#include "./send_image_popup.hpp"
 | 
				
			||||||
#include "entt/container/dense_map.hpp"
 | 
					
 | 
				
			||||||
 | 
					#include <entt/container/dense_map.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <cstdint>
 | 
					#include <cstdint>
 | 
				
			||||||
#include <vector>
 | 
					#include <vector>
 | 
				
			||||||
@@ -17,15 +18,16 @@
 | 
				
			|||||||
#include <mutex>
 | 
					#include <mutex>
 | 
				
			||||||
#include <memory>
 | 
					#include <memory>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using ContactTextureCache = TextureCache<void*, Contact3, ToxAvatarLoader>;
 | 
				
			||||||
 | 
					using MessageTextureCache = TextureCache<void*, Message3Handle, MessageImageLoader>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ChatGui4 {
 | 
					class ChatGui4 {
 | 
				
			||||||
	ConfigModelI& _conf;
 | 
						ConfigModelI& _conf;
 | 
				
			||||||
	RegistryMessageModel& _rmm;
 | 
						RegistryMessageModel& _rmm;
 | 
				
			||||||
	Contact3Registry& _cr;
 | 
						Contact3Registry& _cr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ToxAvatarLoader _tal;
 | 
						ContactTextureCache& _contact_tc;
 | 
				
			||||||
	TextureCache<void*, Contact3, ToxAvatarLoader> _contact_tc;
 | 
						MessageTextureCache& _msg_tc;
 | 
				
			||||||
	MessageImageLoader _mil;
 | 
					 | 
				
			||||||
	TextureCache<void*, Message3Handle, MessageImageLoader> _msg_tc;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	FileSelector _fss;
 | 
						FileSelector _fss;
 | 
				
			||||||
	SendImagePopup _sip;
 | 
						SendImagePopup _sip;
 | 
				
			||||||
@@ -52,12 +54,14 @@ class ChatGui4 {
 | 
				
			|||||||
			ConfigModelI& conf,
 | 
								ConfigModelI& conf,
 | 
				
			||||||
			RegistryMessageModel& rmm,
 | 
								RegistryMessageModel& rmm,
 | 
				
			||||||
			Contact3Registry& cr,
 | 
								Contact3Registry& cr,
 | 
				
			||||||
			TextureUploaderI& tu
 | 
								TextureUploaderI& tu,
 | 
				
			||||||
 | 
								ContactTextureCache& contact_tc,
 | 
				
			||||||
 | 
								MessageTextureCache& msg_tc
 | 
				
			||||||
		);
 | 
							);
 | 
				
			||||||
		~ChatGui4(void);
 | 
							~ChatGui4(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public:
 | 
						public:
 | 
				
			||||||
		void render(float time_delta);
 | 
							float render(float time_delta);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public:
 | 
						public:
 | 
				
			||||||
		bool any_unread {false};
 | 
							bool any_unread {false};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -178,9 +178,13 @@ int main(int argc, char** argv) {
 | 
				
			|||||||
				//)
 | 
									//)
 | 
				
			||||||
			//));
 | 
								//));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			const float min_delay = std::min<float>(
 | 
								const float min_delay =
 | 
				
			||||||
 | 
									std::min<float>(
 | 
				
			||||||
 | 
										std::min<float>(
 | 
				
			||||||
						screen->nextTick() - time_delta_tick,
 | 
											screen->nextTick() - time_delta_tick,
 | 
				
			||||||
						screen->nextRender() - time_delta_render
 | 
											screen->nextRender() - time_delta_render
 | 
				
			||||||
 | 
										),
 | 
				
			||||||
 | 
										0.25f // dont sleep too long
 | 
				
			||||||
				) * 1000.f;
 | 
									) * 1000.f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (min_delay > 0.f) {
 | 
								if (min_delay > 0.f) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,10 +1,13 @@
 | 
				
			|||||||
#include "./main_screen.hpp"
 | 
					#include "./main_screen.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <solanaceae/contact/components.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <imgui/imgui.h>
 | 
					#include <imgui/imgui.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <SDL3/SDL.h>
 | 
					#include <SDL3/SDL.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <memory>
 | 
					#include <memory>
 | 
				
			||||||
 | 
					#include <cmath>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MainScreen::MainScreen(SDL_Renderer* renderer_, std::string save_path, std::string save_password, std::vector<std::string> plugins) :
 | 
					MainScreen::MainScreen(SDL_Renderer* renderer_, std::string save_path, std::string save_password, std::vector<std::string> plugins) :
 | 
				
			||||||
	renderer(renderer_),
 | 
						renderer(renderer_),
 | 
				
			||||||
@@ -20,7 +23,11 @@ MainScreen::MainScreen(SDL_Renderer* renderer_, std::string save_path, std::stri
 | 
				
			|||||||
	mmil(rmm),
 | 
						mmil(rmm),
 | 
				
			||||||
	tam(rmm, cr, conf),
 | 
						tam(rmm, cr, conf),
 | 
				
			||||||
	sdlrtu(renderer_),
 | 
						sdlrtu(renderer_),
 | 
				
			||||||
	cg(conf, rmm, cr, sdlrtu),
 | 
						tal(cr),
 | 
				
			||||||
 | 
						contact_tc(tal, sdlrtu),
 | 
				
			||||||
 | 
						mil(),
 | 
				
			||||||
 | 
						msg_tc(mil, sdlrtu),
 | 
				
			||||||
 | 
						cg(conf, rmm, cr, sdlrtu, contact_tc, msg_tc),
 | 
				
			||||||
	sw(conf),
 | 
						sw(conf),
 | 
				
			||||||
	tuiu(tc, conf),
 | 
						tuiu(tc, conf),
 | 
				
			||||||
	tdch(tpi)
 | 
						tdch(tpi)
 | 
				
			||||||
@@ -167,7 +174,22 @@ Screen* MainScreen::render(float time_delta, bool&) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	const float pm_interval = pm.render(time_delta); // render
 | 
						const float pm_interval = pm.render(time_delta); // render
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cg.render(time_delta); // render
 | 
						// TODO: move this somewhere else!!!
 | 
				
			||||||
 | 
						// needs both tal and tc <.<
 | 
				
			||||||
 | 
						if (!cr.storage<Contact::Components::TagAvatarInvalidate>().empty()) { // handle force-reloads for avatars
 | 
				
			||||||
 | 
							std::vector<Contact3> to_purge;
 | 
				
			||||||
 | 
							cr.view<Contact::Components::TagAvatarInvalidate>().each([&to_purge](const Contact3 c) {
 | 
				
			||||||
 | 
								to_purge.push_back(c);
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
							cr.remove<Contact::Components::TagAvatarInvalidate>(to_purge.cbegin(), to_purge.cend());
 | 
				
			||||||
 | 
							contact_tc.invalidate(to_purge);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// ACTUALLY NOT IF RENDERED, MOVED LOGIC TO ABOVE
 | 
				
			||||||
 | 
						// it might unload textures, so it needs to be done before rendering
 | 
				
			||||||
 | 
						const float ctc_interval = contact_tc.update();
 | 
				
			||||||
 | 
						const float msgtc_interval = msg_tc.update();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const float cg_interval = cg.render(time_delta); // render
 | 
				
			||||||
	sw.render(); // render
 | 
						sw.render(); // render
 | 
				
			||||||
	tuiu.render(); // render
 | 
						tuiu.render(); // render
 | 
				
			||||||
	tdch.render(); // render
 | 
						tdch.render(); // render
 | 
				
			||||||
@@ -216,20 +238,136 @@ Screen* MainScreen::render(float time_delta, bool&) {
 | 
				
			|||||||
		ImGui::ShowDemoWindow();
 | 
							ImGui::ShowDemoWindow();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (
 | 
						float tc_unfinished_queue_interval;
 | 
				
			||||||
		_fps_perf_mode > 1 // TODO: magic
 | 
						{ // load rendered but not loaded textures
 | 
				
			||||||
	) {
 | 
							bool unfinished_work_queue = contact_tc.workLoadQueue();
 | 
				
			||||||
		// powersave forces 250ms
 | 
							unfinished_work_queue = unfinished_work_queue || msg_tc.workLoadQueue();
 | 
				
			||||||
		_render_interval = 1.f/4.f;
 | 
					
 | 
				
			||||||
	} else if (
 | 
							if (unfinished_work_queue) {
 | 
				
			||||||
		_time_since_event > 1.f && ( // 1sec cool down
 | 
								tc_unfinished_queue_interval = 0.1f; // so we can get images loaded faster
 | 
				
			||||||
			_fps_perf_mode == 1 || // TODO: magic
 | 
					 | 
				
			||||||
			_window_hidden
 | 
					 | 
				
			||||||
		)
 | 
					 | 
				
			||||||
	) {
 | 
					 | 
				
			||||||
		_render_interval = std::min<float>(1.f/4.f, pm_interval);
 | 
					 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
		_render_interval = std::min<float>(1.f/60.f, pm_interval);
 | 
								tc_unfinished_queue_interval = 1.f; // TODO: higher min fps?
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// calculate interval for next frame
 | 
				
			||||||
 | 
						// normal:
 | 
				
			||||||
 | 
						//  - if < 1.5sec since last event
 | 
				
			||||||
 | 
						//    - min all and clamp(1/60, 1/1)
 | 
				
			||||||
 | 
						//  - if < 30sec since last event
 | 
				
			||||||
 | 
						//    - min all (anim + everything else) clamp(1/60, 1/1) (maybe less?)
 | 
				
			||||||
 | 
						//  - else
 | 
				
			||||||
 | 
						//    - min without anim and clamp(1/60, 1/1) (maybe more?)
 | 
				
			||||||
 | 
						// reduced:
 | 
				
			||||||
 | 
						//  - if < 1sec since last event
 | 
				
			||||||
 | 
						//    - min all and clamp(1/60, 1/1)
 | 
				
			||||||
 | 
						//  - if < 10sec since last event
 | 
				
			||||||
 | 
						//    - min all (anim + everything else) clamp(1/10, 1/1)
 | 
				
			||||||
 | 
						//  - else
 | 
				
			||||||
 | 
						//    - min without anim and max clamp(1/10, 1/1)
 | 
				
			||||||
 | 
						// powersave:
 | 
				
			||||||
 | 
						//  - if < 0sec since last event
 | 
				
			||||||
 | 
						//    - (ignored)
 | 
				
			||||||
 | 
						//  - if < 1sec since last event
 | 
				
			||||||
 | 
						//    - min all (anim + everything else) clamp(1/8, 1/1)
 | 
				
			||||||
 | 
						//  - else
 | 
				
			||||||
 | 
						//    - min without anim and clamp(1/1, 1/1)
 | 
				
			||||||
 | 
						struct PerfProfileRender {
 | 
				
			||||||
 | 
							float low_delay_window {1.5f};
 | 
				
			||||||
 | 
							float low_delay_min {1.f/60.f};
 | 
				
			||||||
 | 
							float low_delay_max {1.f/60.f};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							float mid_delay_window {30.f};
 | 
				
			||||||
 | 
							float mid_delay_min {1.f/60.f};
 | 
				
			||||||
 | 
							float mid_delay_max {1.f/2.f};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// also when main window hidden
 | 
				
			||||||
 | 
							float else_delay_min {1.f/60.f};
 | 
				
			||||||
 | 
							float else_delay_max {1.f/2.f};
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const static PerfProfileRender normalPerfProfile{
 | 
				
			||||||
 | 
							//1.5f,		// low_delay_window
 | 
				
			||||||
 | 
							//1.f/60.f,	// low_delay_min
 | 
				
			||||||
 | 
							//1.f/60.f,	// low_delay_max
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//30.f,		// mid_delay_window
 | 
				
			||||||
 | 
							//1.f/60.f,	// mid_delay_min
 | 
				
			||||||
 | 
							//1.f/2.f,	// mid_delay_max
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//1.f/60.f,	// else_delay_min
 | 
				
			||||||
 | 
							//1.f/2.f,	// else_delay_max
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						const static PerfProfileRender reducedPerfProfile{
 | 
				
			||||||
 | 
							1.f,		// low_delay_window
 | 
				
			||||||
 | 
							1.f/60.f,	// low_delay_min
 | 
				
			||||||
 | 
							1.f/30.f,	// low_delay_max
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							10.f,		// mid_delay_window
 | 
				
			||||||
 | 
							1.f/10.f,	// mid_delay_min
 | 
				
			||||||
 | 
							1.f/4.f,	// mid_delay_max
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							1.f/10.f,	// else_delay_min
 | 
				
			||||||
 | 
							1.f,		// else_delay_max
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						// TODO: fix powersave by adjusting it in the events handler (make ppr member)
 | 
				
			||||||
 | 
						const static PerfProfileRender powersavePerfProfile{
 | 
				
			||||||
 | 
							// no window -> ignore first case
 | 
				
			||||||
 | 
							0.f,		// low_delay_window
 | 
				
			||||||
 | 
							1.f,		// low_delay_min
 | 
				
			||||||
 | 
							1.f,		// low_delay_max
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							1.f,		// mid_delay_window
 | 
				
			||||||
 | 
							1.f/8.f,	// mid_delay_min
 | 
				
			||||||
 | 
							1.f/4.f,	// mid_delay_max
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							1.f,		// else_delay_min
 | 
				
			||||||
 | 
							1.f,		// else_delay_max
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const PerfProfileRender& curr_profile =
 | 
				
			||||||
 | 
							// TODO: magic
 | 
				
			||||||
 | 
							_fps_perf_mode > 1
 | 
				
			||||||
 | 
							? powersavePerfProfile
 | 
				
			||||||
 | 
							: (
 | 
				
			||||||
 | 
								_fps_perf_mode == 1
 | 
				
			||||||
 | 
								? reducedPerfProfile
 | 
				
			||||||
 | 
								: normalPerfProfile
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
 | 
						;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// min over non animations in all cases
 | 
				
			||||||
 | 
						_render_interval = std::min<float>(pm_interval, cg_interval);
 | 
				
			||||||
 | 
						_render_interval = std::min<float>(_render_interval, tc_unfinished_queue_interval);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// low delay time window
 | 
				
			||||||
 | 
						if (!_window_hidden && _time_since_event < curr_profile.low_delay_window) {
 | 
				
			||||||
 | 
							_render_interval = std::min<float>(_render_interval, ctc_interval);
 | 
				
			||||||
 | 
							_render_interval = std::min<float>(_render_interval, msgtc_interval);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							_render_interval = std::clamp(
 | 
				
			||||||
 | 
								_render_interval,
 | 
				
			||||||
 | 
								curr_profile.low_delay_min,
 | 
				
			||||||
 | 
								curr_profile.low_delay_max
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
						// mid delay time window
 | 
				
			||||||
 | 
						} else if (!_window_hidden && _time_since_event < curr_profile.mid_delay_window) {
 | 
				
			||||||
 | 
							_render_interval = std::min<float>(_render_interval, ctc_interval);
 | 
				
			||||||
 | 
							_render_interval = std::min<float>(_render_interval, msgtc_interval);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							_render_interval = std::clamp(
 | 
				
			||||||
 | 
								_render_interval,
 | 
				
			||||||
 | 
								curr_profile.mid_delay_min,
 | 
				
			||||||
 | 
								curr_profile.mid_delay_max
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
						// timed out or window hidden
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							// no animation timing here
 | 
				
			||||||
 | 
							_render_interval = std::clamp(
 | 
				
			||||||
 | 
								_render_interval,
 | 
				
			||||||
 | 
								curr_profile.else_delay_min,
 | 
				
			||||||
 | 
								curr_profile.else_delay_max
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_time_since_event += time_delta;
 | 
						_time_since_event += time_delta;
 | 
				
			||||||
@@ -253,7 +391,9 @@ Screen* MainScreen::tick(float time_delta, bool& quit) {
 | 
				
			|||||||
	mts.iterate(); // compute
 | 
						mts.iterate(); // compute
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_min_tick_interval = std::min<float>(
 | 
						_min_tick_interval = std::min<float>(
 | 
				
			||||||
		tc.toxIterationInterval()/1000.f,
 | 
							// HACK: pow by 1.6 to increase 50 -> ~500 (~522)
 | 
				
			||||||
 | 
							// and it does not change 1
 | 
				
			||||||
 | 
							std::pow(tc.toxIterationInterval(), 1.6f)/1000.f,
 | 
				
			||||||
		pm_interval
 | 
							pm_interval
 | 
				
			||||||
	);
 | 
						);
 | 
				
			||||||
	_min_tick_interval = std::min<float>(
 | 
						_min_tick_interval = std::min<float>(
 | 
				
			||||||
@@ -261,6 +401,8 @@ Screen* MainScreen::tick(float time_delta, bool& quit) {
 | 
				
			|||||||
		fo_interval
 | 
							fo_interval
 | 
				
			||||||
	);
 | 
						);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						//std::cout << "MS: min tick interval: " << _min_tick_interval << "\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (_compute_perf_mode) {
 | 
						switch (_compute_perf_mode) {
 | 
				
			||||||
		// normal 1ms lower bound
 | 
							// normal 1ms lower bound
 | 
				
			||||||
		case 0: _min_tick_interval = std::max<float>(_min_tick_interval, 0.001f); break;
 | 
							case 0: _min_tick_interval = std::max<float>(_min_tick_interval, 0.001f); break;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,6 +21,10 @@
 | 
				
			|||||||
#include "./tox_avatar_manager.hpp"
 | 
					#include "./tox_avatar_manager.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "./sdlrenderer_texture_uploader.hpp"
 | 
					#include "./sdlrenderer_texture_uploader.hpp"
 | 
				
			||||||
 | 
					#include "./texture_cache.hpp"
 | 
				
			||||||
 | 
					#include "./tox_avatar_loader.hpp"
 | 
				
			||||||
 | 
					#include "./message_image_loader.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "./chat_gui4.hpp"
 | 
					#include "./chat_gui4.hpp"
 | 
				
			||||||
#include "./settings_window.hpp"
 | 
					#include "./settings_window.hpp"
 | 
				
			||||||
#include "./tox_ui_utils.hpp"
 | 
					#include "./tox_ui_utils.hpp"
 | 
				
			||||||
@@ -61,6 +65,11 @@ struct MainScreen final : public Screen {
 | 
				
			|||||||
	SDLRendererTextureUploader sdlrtu;
 | 
						SDLRendererTextureUploader sdlrtu;
 | 
				
			||||||
	//OpenGLTextureUploader ogltu;
 | 
						//OpenGLTextureUploader ogltu;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ToxAvatarLoader tal;
 | 
				
			||||||
 | 
						TextureCache<void*, Contact3, ToxAvatarLoader> contact_tc;
 | 
				
			||||||
 | 
						MessageImageLoader mil;
 | 
				
			||||||
 | 
						TextureCache<void*, Message3Handle, MessageImageLoader> msg_tc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ChatGui4 cg;
 | 
						ChatGui4 cg;
 | 
				
			||||||
	SettingsWindow sw;
 | 
						SettingsWindow sw;
 | 
				
			||||||
	ToxUIUtils tuiu;
 | 
						ToxUIUtils tuiu;
 | 
				
			||||||
@@ -85,7 +94,7 @@ struct MainScreen final : public Screen {
 | 
				
			|||||||
	// 0 - normal
 | 
						// 0 - normal
 | 
				
			||||||
	// 1 - reduced
 | 
						// 1 - reduced
 | 
				
			||||||
	// 2 - power save
 | 
						// 2 - power save
 | 
				
			||||||
	int _fps_perf_mode {1};
 | 
						int _fps_perf_mode {0};
 | 
				
			||||||
	// 0 - normal
 | 
						// 0 - normal
 | 
				
			||||||
	// 1 - power save
 | 
						// 1 - power save
 | 
				
			||||||
	int _compute_perf_mode {0};
 | 
						int _compute_perf_mode {0};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -32,7 +32,7 @@ struct SendImagePopup {
 | 
				
			|||||||
	Rect crop_rect;
 | 
						Rect crop_rect;
 | 
				
			||||||
	Rect crop_before_drag;
 | 
						Rect crop_before_drag;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool cropping {false};
 | 
						bool cropping {true};
 | 
				
			||||||
	bool dragging_last_frame_ul {false};
 | 
						bool dragging_last_frame_ul {false};
 | 
				
			||||||
	bool dragging_last_frame_lr {false};
 | 
						bool dragging_last_frame_lr {false};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,8 +2,9 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <chrono>
 | 
					#include <chrono>
 | 
				
			||||||
#include <array>
 | 
					#include <array>
 | 
				
			||||||
 | 
					#include <limits>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void TextureEntry::doAnimation(const int64_t ts_now) {
 | 
					int64_t TextureEntry::doAnimation(const int64_t ts_now) {
 | 
				
			||||||
	if (frame_duration.size() > 1) { // is animation
 | 
						if (frame_duration.size() > 1) { // is animation
 | 
				
			||||||
		do { // why is this loop so ugly
 | 
							do { // why is this loop so ugly
 | 
				
			||||||
			const int64_t duration = getDuration();
 | 
								const int64_t duration = getDuration();
 | 
				
			||||||
@@ -11,11 +12,13 @@ void TextureEntry::doAnimation(const int64_t ts_now) {
 | 
				
			|||||||
				timestamp_last_rendered += duration;
 | 
									timestamp_last_rendered += duration;
 | 
				
			||||||
				next();
 | 
									next();
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				break;
 | 
									// return ts for next frame
 | 
				
			||||||
 | 
									return timestamp_last_rendered + duration;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} while(true);
 | 
							} while (true);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		timestamp_last_rendered = ts_now;
 | 
							timestamp_last_rendered = ts_now;
 | 
				
			||||||
 | 
							return std::numeric_limits<int64_t>::max(); // static image
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -50,7 +50,8 @@ struct TextureEntry {
 | 
				
			|||||||
		current_texture = (current_texture + 1) % frame_duration.size();
 | 
							current_texture = (current_texture + 1) % frame_duration.size();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void doAnimation(const int64_t ts_now);
 | 
						// returns ts for next frame
 | 
				
			||||||
 | 
						int64_t doAnimation(const int64_t ts_now);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	template<typename TextureType>
 | 
						template<typename TextureType>
 | 
				
			||||||
	TextureType getID(void) {
 | 
						TextureType getID(void) {
 | 
				
			||||||
@@ -133,14 +134,16 @@ struct TextureCache {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void update(void) {
 | 
						float update(void) {
 | 
				
			||||||
		const uint64_t ts_now = Message::getTimeMS();
 | 
							const uint64_t ts_now = Message::getTimeMS();
 | 
				
			||||||
 | 
							uint64_t ts_min_next = ts_now + ms_before_purge;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		std::vector<KeyType> to_purge;
 | 
							std::vector<KeyType> to_purge;
 | 
				
			||||||
		for (auto&& [key, te] : _cache) {
 | 
							for (auto&& [key, te] : _cache) {
 | 
				
			||||||
			if (te.rendered_this_frame) {
 | 
								if (te.rendered_this_frame) {
 | 
				
			||||||
				te.doAnimation(ts_now);
 | 
									const uint64_t ts_next = te.doAnimation(ts_now);
 | 
				
			||||||
				te.rendered_this_frame = false;
 | 
									te.rendered_this_frame = false;
 | 
				
			||||||
 | 
									ts_min_next = std::min(ts_min_next, ts_next);
 | 
				
			||||||
			} else if (_cache.size() > min_count_before_purge && ts_now - te.timestamp_last_rendered >= ms_before_purge) {
 | 
								} else if (_cache.size() > min_count_before_purge && ts_now - te.timestamp_last_rendered >= ms_before_purge) {
 | 
				
			||||||
				to_purge.push_back(key);
 | 
									to_purge.push_back(key);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@@ -148,7 +151,10 @@ struct TextureCache {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		invalidate(to_purge);
 | 
							invalidate(to_purge);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// we ignore the default texture ts :)
 | 
				
			||||||
		_default_texture.doAnimation(ts_now);
 | 
							_default_texture.doAnimation(ts_now);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return (ts_min_next - ts_now) / 1000.f;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void invalidate(const std::vector<KeyType>& to_purge) {
 | 
						void invalidate(const std::vector<KeyType>& to_purge) {
 | 
				
			||||||
@@ -162,16 +168,22 @@ struct TextureCache {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void workLoadQueue(void) {
 | 
						// returns true if there is still work queued up
 | 
				
			||||||
		for (auto it = _to_load.begin(); it != _to_load.end(); it++) {
 | 
						bool workLoadQueue(void) {
 | 
				
			||||||
 | 
							auto it = _to_load.begin();
 | 
				
			||||||
 | 
							for (; it != _to_load.end(); it++) {
 | 
				
			||||||
			auto new_entry_opt = _l.load(_tu, *it);
 | 
								auto new_entry_opt = _l.load(_tu, *it);
 | 
				
			||||||
			if (new_entry_opt.has_value()) {
 | 
								if (new_entry_opt.has_value()) {
 | 
				
			||||||
				_cache.emplace(*it, new_entry_opt.value());
 | 
									_cache.emplace(*it, new_entry_opt.value());
 | 
				
			||||||
				_to_load.erase(it);
 | 
									it = _to_load.erase(it);
 | 
				
			||||||
				// TODO: not a good idea
 | 
					
 | 
				
			||||||
 | 
									// TODO: not a good idea?
 | 
				
			||||||
				break; // end load from queue/onlyload 1 per update
 | 
									break; // end load from queue/onlyload 1 per update
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// peak
 | 
				
			||||||
 | 
							return it != _to_load.end();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,6 +10,8 @@
 | 
				
			|||||||
#include <limits>
 | 
					#include <limits>
 | 
				
			||||||
#include <cstdint>
 | 
					#include <cstdint>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//#include <iostream>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Message::Components {
 | 
					namespace Message::Components {
 | 
				
			||||||
	struct LastSendAttempt {
 | 
						struct LastSendAttempt {
 | 
				
			||||||
		uint64_t ts {0};
 | 
							uint64_t ts {0};
 | 
				
			||||||
@@ -29,15 +31,17 @@ ToxFriendFauxOfflineMessaging::ToxFriendFauxOfflineMessaging(
 | 
				
			|||||||
	ToxI& t,
 | 
						ToxI& t,
 | 
				
			||||||
	ToxEventProviderI& tep
 | 
						ToxEventProviderI& tep
 | 
				
			||||||
) : _cr(cr), _rmm(rmm), _tcm(tcm), _t(t), _tep(tep) {
 | 
					) : _cr(cr), _rmm(rmm), _tcm(tcm), _t(t), _tep(tep) {
 | 
				
			||||||
 | 
						_tep.subscribe(this, Tox_Event_Type::TOX_EVENT_FRIEND_CONNECTION_STATUS);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
float ToxFriendFauxOfflineMessaging::tick(float time_delta) {
 | 
					float ToxFriendFauxOfflineMessaging::tick(float time_delta) {
 | 
				
			||||||
	// hard limit interval to once per minute
 | 
						_interval_timer -= time_delta;
 | 
				
			||||||
	_interval_timer += time_delta;
 | 
						if (_interval_timer > 0.f) {
 | 
				
			||||||
	if (_interval_timer < 1.f * 60.f) {
 | 
							return std::max(_interval_timer, 0.001f); // TODO: min next timer
 | 
				
			||||||
		return std::max(60.f - _interval_timer, 0.001f); // TODO: min next timer
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	_interval_timer = 0.f;
 | 
						// interval ~ once per minute
 | 
				
			||||||
 | 
						_interval_timer = 60.f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const uint64_t ts_now = Message::getTimeMS();
 | 
						const uint64_t ts_now = Message::getTimeMS();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -50,37 +54,47 @@ float ToxFriendFauxOfflineMessaging::tick(float time_delta) {
 | 
				
			|||||||
			// cleanup
 | 
								// cleanup
 | 
				
			||||||
			if (_cr.all_of<Contact::Components::NextSendAttempt>(c)) {
 | 
								if (_cr.all_of<Contact::Components::NextSendAttempt>(c)) {
 | 
				
			||||||
				_cr.remove<Contact::Components::NextSendAttempt>(c);
 | 
									_cr.remove<Contact::Components::NextSendAttempt>(c);
 | 
				
			||||||
 | 
									auto* mr = static_cast<const RegistryMessageModel&>(_rmm).get(c);
 | 
				
			||||||
 | 
									if (mr != nullptr) {
 | 
				
			||||||
 | 
										mr->storage<Message::Components::LastSendAttempt>().clear();
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			if (!_cr.all_of<Contact::Components::NextSendAttempt>(c)) {
 | 
								if (!_cr.all_of<Contact::Components::NextSendAttempt>(c)) {
 | 
				
			||||||
 | 
									if (false) { // has unsent messages
 | 
				
			||||||
					const auto& nsa = _cr.emplace<Contact::Components::NextSendAttempt>(c, ts_now + uint64_t(_delay_after_cc*1000)); // wait before first message is sent
 | 
										const auto& nsa = _cr.emplace<Contact::Components::NextSendAttempt>(c, ts_now + uint64_t(_delay_after_cc*1000)); // wait before first message is sent
 | 
				
			||||||
					min_next_attempt_ts = std::min(min_next_attempt_ts, nsa.ts);
 | 
										min_next_attempt_ts = std::min(min_next_attempt_ts, nsa.ts);
 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				auto& next_attempt = _cr.get<Contact::Components::NextSendAttempt>(c).ts;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				if (doFriendMessageCheck(c, tfe)) {
 | 
					 | 
				
			||||||
					next_attempt = ts_now + uint64_t(_delay_inbetween*1000);
 | 
					 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
				min_next_attempt_ts = std::min(min_next_attempt_ts, next_attempt);
 | 
									auto ret = doFriendMessageCheck(c, tfe);
 | 
				
			||||||
 | 
									if (ret == dfmc_Ret::SENT_THIS_TICK) {
 | 
				
			||||||
 | 
										const auto ts = _cr.get<Contact::Components::NextSendAttempt>(c).ts = ts_now + uint64_t(_delay_inbetween*1000);
 | 
				
			||||||
 | 
										min_next_attempt_ts = std::min(min_next_attempt_ts, ts);
 | 
				
			||||||
 | 
									} else if (ret == dfmc_Ret::TOO_SOON) {
 | 
				
			||||||
 | 
										// TODO: set to _delay_inbetween? prob expensive for no good reason
 | 
				
			||||||
 | 
										min_next_attempt_ts = std::min(min_next_attempt_ts, _cr.get<Contact::Components::NextSendAttempt>(c).ts);
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										_cr.remove<Contact::Components::NextSendAttempt>(c);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (min_next_attempt_ts <= ts_now) {
 | 
						if (min_next_attempt_ts <= ts_now) {
 | 
				
			||||||
		// we (probably) sent this iterate
 | 
							// we (probably) sent this iterate
 | 
				
			||||||
		_interval_timer = 60.f - 0.1f; // TODO: ugly magic
 | 
							_interval_timer = 0.1f; // TODO: ugly magic
 | 
				
			||||||
		return 0.1f;
 | 
					 | 
				
			||||||
	} else if (min_next_attempt_ts == std::numeric_limits<uint64_t>::max()) {
 | 
						} else if (min_next_attempt_ts == std::numeric_limits<uint64_t>::max()) {
 | 
				
			||||||
		// nothing to sync or all offline that need syncing
 | 
							// nothing to sync or all offline that need syncing
 | 
				
			||||||
		return 60.f; // TODO: ugly magic
 | 
					 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		// TODO: ugly magic
 | 
							_interval_timer = std::min(_interval_timer, (min_next_attempt_ts - ts_now) / 1000.f);
 | 
				
			||||||
		return _interval_timer = 60.f - std::min(60.f, (min_next_attempt_ts - ts_now) / 1000.f);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						//std::cout << "TFFOM: iterate (i:" << _interval_timer << ")\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return _interval_timer;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool ToxFriendFauxOfflineMessaging::doFriendMessageCheck(const Contact3 c, const Contact::Components::ToxFriendEphemeral& tfe) {
 | 
					ToxFriendFauxOfflineMessaging::dfmc_Ret ToxFriendFauxOfflineMessaging::doFriendMessageCheck(const Contact3 c, const Contact::Components::ToxFriendEphemeral& tfe) {
 | 
				
			||||||
	// walk all messages and check if
 | 
						// walk all messages and check if
 | 
				
			||||||
	// unacked message
 | 
						// unacked message
 | 
				
			||||||
	// timeouts for exising unacked messages expired (send)
 | 
						// timeouts for exising unacked messages expired (send)
 | 
				
			||||||
@@ -88,7 +102,7 @@ bool ToxFriendFauxOfflineMessaging::doFriendMessageCheck(const Contact3 c, const
 | 
				
			|||||||
	auto* mr = static_cast<const RegistryMessageModel&>(_rmm).get(c);
 | 
						auto* mr = static_cast<const RegistryMessageModel&>(_rmm).get(c);
 | 
				
			||||||
	if (mr == nullptr) {
 | 
						if (mr == nullptr) {
 | 
				
			||||||
		// no messages
 | 
							// no messages
 | 
				
			||||||
		return false;
 | 
							return dfmc_Ret::NO_MSG;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const uint64_t ts_now = Message::getTimeMS();
 | 
						const uint64_t ts_now = Message::getTimeMS();
 | 
				
			||||||
@@ -98,6 +112,7 @@ bool ToxFriendFauxOfflineMessaging::doFriendMessageCheck(const Contact3 c, const
 | 
				
			|||||||
	// we assume sorted
 | 
						// we assume sorted
 | 
				
			||||||
	// ("reverse" iteration <.<)
 | 
						// ("reverse" iteration <.<)
 | 
				
			||||||
	auto msg_view = mr->view<Message::Components::Timestamp>();
 | 
						auto msg_view = mr->view<Message::Components::Timestamp>();
 | 
				
			||||||
 | 
						bool valid_unsent {false};
 | 
				
			||||||
	// we search for the oldest, not too recently sent, unconfirmed message
 | 
						// we search for the oldest, not too recently sent, unconfirmed message
 | 
				
			||||||
	for (auto it = msg_view.rbegin(), view_end = msg_view.rend(); it != view_end; it++) {
 | 
						for (auto it = msg_view.rbegin(), view_end = msg_view.rend(); it != view_end; it++) {
 | 
				
			||||||
		const Message3 msg = *it;
 | 
							const Message3 msg = *it;
 | 
				
			||||||
@@ -119,6 +134,12 @@ bool ToxFriendFauxOfflineMessaging::doFriendMessageCheck(const Contact3 c, const
 | 
				
			|||||||
			continue; // skip
 | 
								continue; // skip
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (mr->get<Message::Components::ContactTo>(msg).c != c) {
 | 
				
			||||||
 | 
								continue; // not outbound (in private)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							valid_unsent = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		uint64_t msg_ts = msg_view.get<Message::Components::Timestamp>(msg).ts;
 | 
							uint64_t msg_ts = msg_view.get<Message::Components::Timestamp>(msg).ts;
 | 
				
			||||||
		if (mr->all_of<Message::Components::TimestampWritten>(msg)) {
 | 
							if (mr->all_of<Message::Components::TimestampWritten>(msg)) {
 | 
				
			||||||
			msg_ts = mr->get<Message::Components::TimestampWritten>(msg).ts;
 | 
								msg_ts = mr->get<Message::Components::TimestampWritten>(msg).ts;
 | 
				
			||||||
@@ -155,12 +176,17 @@ bool ToxFriendFauxOfflineMessaging::doFriendMessageCheck(const Contact3 c, const
 | 
				
			|||||||
		} // else error
 | 
							} // else error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// we sent our message, no point further iterating
 | 
							// we sent our message, no point further iterating
 | 
				
			||||||
		return true;
 | 
							return dfmc_Ret::SENT_THIS_TICK;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// TODO: somehow cleanup lsa
 | 
						if (!valid_unsent) {
 | 
				
			||||||
 | 
							// somehow cleanup lsa
 | 
				
			||||||
 | 
							mr->storage<Message::Components::LastSendAttempt>().clear();
 | 
				
			||||||
 | 
							//std::cout << "TFFOM: all sent, deleting lsa\n";
 | 
				
			||||||
 | 
							return dfmc_Ret::NO_MSG;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return false;
 | 
						return dfmc_Ret::TOO_SOON;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool ToxFriendFauxOfflineMessaging::onToxEvent(const Tox_Event_Friend_Connection_Status* e) {
 | 
					bool ToxFriendFauxOfflineMessaging::onToxEvent(const Tox_Event_Friend_Connection_Status* e) {
 | 
				
			||||||
@@ -180,8 +206,7 @@ bool ToxFriendFauxOfflineMessaging::onToxEvent(const Tox_Event_Friend_Connection
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	_cr.emplace_or_replace<Contact::Components::NextSendAttempt>(c, Message::getTimeMS() + uint64_t(_delay_after_cc*1000)); // wait before first message is sent
 | 
						_cr.emplace_or_replace<Contact::Components::NextSendAttempt>(c, Message::getTimeMS() + uint64_t(_delay_after_cc*1000)); // wait before first message is sent
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// TODO: ugly magic
 | 
						_interval_timer = 0.f;
 | 
				
			||||||
	_interval_timer = 60.f - 0.1f;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return false;
 | 
						return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -39,10 +39,15 @@ class ToxFriendFauxOfflineMessaging : public ToxEventI {
 | 
				
			|||||||
		float tick(float time_delta);
 | 
							float tick(float time_delta);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private:
 | 
						private:
 | 
				
			||||||
 | 
							enum class dfmc_Ret {
 | 
				
			||||||
 | 
								TOO_SOON,
 | 
				
			||||||
 | 
								SENT_THIS_TICK,
 | 
				
			||||||
 | 
								NO_MSG,
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
		// only called for online friends
 | 
							// only called for online friends
 | 
				
			||||||
		// returns true if a message was sent
 | 
							// returns true if a message was sent
 | 
				
			||||||
		// dont call this too often
 | 
							// dont call this too often
 | 
				
			||||||
		bool doFriendMessageCheck(const Contact3 c, const Contact::Components::ToxFriendEphemeral& tfe);
 | 
							dfmc_Ret doFriendMessageCheck(const Contact3 c, const Contact::Components::ToxFriendEphemeral& tfe);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	protected:
 | 
						protected:
 | 
				
			||||||
		bool onToxEvent(const Tox_Event_Friend_Connection_Status* e) override;
 | 
							bool onToxEvent(const Tox_Event_Friend_Connection_Status* e) override;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user