From 91bde912384300688df485a95e905c066619cf3b Mon Sep 17 00:00:00 2001 From: dijunkun Date: Tue, 10 Mar 2026 17:46:44 +0800 Subject: [PATCH] [feat] probe presence before connect and show warning if offline --- src/gui/panels/remote_peer_panel.cpp | 18 ++++--- src/gui/render.cpp | 79 ++++++++++++++++++++++++++++ src/gui/render.h | 12 ++++- src/gui/render_callback.cpp | 24 +++++++-- 4 files changed, 123 insertions(+), 10 deletions(-) diff --git a/src/gui/panels/remote_peer_panel.cpp b/src/gui/panels/remote_peer_panel.cpp index 9923e08..bdd8b48 100644 --- a/src/gui/panels/remote_peer_panel.cpp +++ b/src/gui/panels/remote_peer_panel.cpp @@ -165,12 +165,18 @@ static int InputTextCallback(ImGuiInputTextCallbackData* data) { } int Render::ConnectTo(const std::string& remote_id, const char* password, - bool remember_password) { - if (!device_presence_.IsOnline(remote_id)) { - offline_warning_text_ = - localization::device_offline[localization_language_index_]; - show_offline_warning_window_ = true; - LOG_WARN("Skip connect to [{}]: device is offline", remote_id); + bool remember_password, bool bypass_presence_check) { + if (!bypass_presence_check && !device_presence_.IsOnline(remote_id)) { + int ret = + RequestSingleDevicePresence(remote_id, password, remember_password); + if (ret != 0) { + offline_warning_text_ = + localization::device_offline[localization_language_index_]; + show_offline_warning_window_ = true; + LOG_WARN("Presence probe failed for [{}], ret={}", remote_id, ret); + } else { + LOG_INFO("Presence probe requested for [{}] before connect", remote_id); + } return -1; } diff --git a/src/gui/render.cpp b/src/gui/render.cpp index 81fbbb0..0be5042 100644 --- a/src/gui/render.cpp +++ b/src/gui/render.cpp @@ -1605,6 +1605,7 @@ void Render::MainLoop() { UpdateLabels(); HandleRecentConnections(); HandleConnectionStatusChange(); + HandlePendingPresenceProbe(); HandleStreamWindow(); HandleServerWindow(); @@ -1684,6 +1685,84 @@ void Render::HandleConnectionStatusChange() { need_to_send_recent_connections_ = false; } +void Render::HandlePendingPresenceProbe() { + bool has_action = false; + bool should_connect = false; + bool remember_password = false; + std::string remote_id; + std::string password; + + { + std::lock_guard lock(pending_presence_probe_mutex_); + if (!pending_presence_probe_ || !pending_presence_result_ready_) { + return; + } + + has_action = true; + should_connect = pending_presence_online_; + remote_id = pending_presence_remote_id_; + password = pending_presence_password_; + remember_password = pending_presence_remember_password_; + + pending_presence_probe_ = false; + pending_presence_result_ready_ = false; + pending_presence_online_ = false; + pending_presence_remote_id_.clear(); + pending_presence_password_.clear(); + pending_presence_remember_password_ = false; + } + + if (!has_action) { + return; + } + + if (should_connect) { + ConnectTo(remote_id, password.c_str(), remember_password, true); + return; + } + + offline_warning_text_ = + localization::device_offline[localization_language_index_]; + show_offline_warning_window_ = true; +} + +int Render::RequestSingleDevicePresence(const std::string& remote_id, + const char* password, + bool remember_password) { + if (!signal_connected_ || !peer_) { + return -1; + } + + { + std::lock_guard lock(pending_presence_probe_mutex_); + pending_presence_probe_ = true; + pending_presence_result_ready_ = false; + pending_presence_online_ = false; + pending_presence_remote_id_ = remote_id; + pending_presence_password_ = password ? password : ""; + pending_presence_remember_password_ = remember_password; + } + + nlohmann::json j; + j["type"] = "recent_connections_presence"; + j["user_id"] = client_id_; + j["devices"] = nlohmann::json::array({remote_id}); + auto s = j.dump(); + + int ret = SendSignalMessage(peer_, s.data(), s.size()); + if (ret != 0) { + std::lock_guard lock(pending_presence_probe_mutex_); + pending_presence_probe_ = false; + pending_presence_result_ready_ = false; + pending_presence_online_ = false; + pending_presence_remote_id_.clear(); + pending_presence_password_.clear(); + pending_presence_remember_password_ = false; + } + + return ret; +} + void Render::HandleStreamWindow() { if (need_to_create_stream_window_) { CreateStreamWindow(); diff --git a/src/gui/render.h b/src/gui/render.h index 4ab11f1..d3701e8 100644 --- a/src/gui/render.h +++ b/src/gui/render.h @@ -194,6 +194,7 @@ class Render { void UpdateInteractions(); void HandleRecentConnections(); void HandleConnectionStatusChange(); + void HandlePendingPresenceProbe(); void HandleStreamWindow(); void HandleServerWindow(); void Cleanup(); @@ -243,7 +244,9 @@ class Render { private: int ConnectTo(const std::string& remote_id, const char* password, - bool remember_password); + bool remember_password, bool bypass_presence_check = false); + int RequestSingleDevicePresence(const std::string& remote_id, + const char* password, bool remember_password); int CreateMainWindow(); int DestroyMainWindow(); int CreateStreamWindow(); @@ -690,6 +693,13 @@ class Render { std::unordered_map connection_host_names_; std::string selected_server_remote_id_ = ""; std::string selected_server_remote_hostname_ = ""; + std::mutex pending_presence_probe_mutex_; + bool pending_presence_probe_ = false; + bool pending_presence_result_ready_ = false; + bool pending_presence_online_ = false; + std::string pending_presence_remote_id_ = ""; + std::string pending_presence_password_ = ""; + bool pending_presence_remember_password_ = false; FileTransferState file_transfer_; }; } // namespace crossdesk diff --git a/src/gui/render_callback.cpp b/src/gui/render_callback.cpp index 1047cd8..ff4e200 100644 --- a/src/gui/render_callback.cpp +++ b/src/gui/render_callback.cpp @@ -48,6 +48,15 @@ void Render::OnSignalMessageCb(const char* message, size_t size, std::string id = dev["id"].get(); bool online = dev["online"].get(); render->device_presence_.SetOnline(id, online); + { + std::lock_guard lock( + render->pending_presence_probe_mutex_); + if (render->pending_presence_probe_ && + render->pending_presence_remote_id_ == id) { + render->pending_presence_result_ready_ = true; + render->pending_presence_online_ = online; + } + } } } } else if (type == "presence_update") { @@ -57,6 +66,15 @@ void Render::OnSignalMessageCb(const char* message, size_t size, bool online = j["online"].get(); if (!id.empty()) { render->device_presence_.SetOnline(id, online); + { + std::lock_guard lock( + render->pending_presence_probe_mutex_); + if (render->pending_presence_probe_ && + render->pending_presence_remote_id_ == id) { + render->pending_presence_result_ready_ = true; + render->pending_presence_online_ = online; + } + } } } } @@ -498,9 +516,9 @@ void Render::OnReceiveDataBufferCb(const char* data, size_t size, const double bps = (static_cast(delta_bytes) * 8.0) / delta_seconds; if (bps > 0.0) { - const double capped = (std::min)( - bps, - static_cast((std::numeric_limits::max)())); + const double capped = + (std::min)(bps, static_cast( + (std::numeric_limits::max)())); estimated_rate_bps = static_cast(capped); } }