From 408393a547f05eb95e19c8f6065e2238fa511483 Mon Sep 17 00:00:00 2001 From: DanS Date: Sun, 18 Oct 2026 09:44:33 -0500 Subject: [PATCH] feat(chat): add a "Copy my chat address" button The conversation header only copies a PEER's address, so a user had no way to hand out their own chat address for others to message them. Add a "Copy my chat address" link in the left pane (public App::chatMyAddress() forwards the stable seed-derived reply z-address; copied on click only, with an "address copied" toast and a warning if none exists yet). Co-Authored-By: Claude Opus 4.8 --- src/app.h | 3 +++ src/ui/windows/chat_tab.cpp | 18 ++++++++++++++++++ src/util/i18n.cpp | 3 +++ 3 files changed, 24 insertions(+) diff --git a/src/app.h b/src/app.h index 745b482..34ee04f 100644 --- a/src/app.h +++ b/src/app.h @@ -302,6 +302,9 @@ public: wallet::LiteWalletController* liteWallet() { return lite_wallet_.get(); } // HushChat service (identity + in-memory message store); the Chat tab reads its store. chat::ChatService& chatService() { return chat_service_; } + // Public forwarder for the UI: the wallet z-address others use to reach this user in chat. Call on + // click (not per-frame) — the underlying chatReplyZaddr() may persist a freshly chosen address. + std::string chatMyAddress() { return chatReplyZaddr(); } // Why the Chat tab has no identity yet, so it can show the right prompt instead of always // "unlock your wallet". Locked = encrypted & locked (seed unreadable); Preparing = unlocked and // deriving the identity (fetch in flight, or waiting on the node / address list); Unavailable = diff --git a/src/ui/windows/chat_tab.cpp b/src/ui/windows/chat_tab.cpp index b9314b3..7b05e24 100644 --- a/src/ui/windows/chat_tab.cpp +++ b/src/ui/windows/chat_tab.cpp @@ -916,6 +916,24 @@ void RenderChatTab(App* app) if (ImGui::SmallButton(bl.c_str())) s_show_blocked = true; ImGui::PopStyleColor(); } + // "Copy my chat address" — the address others use to reach this user. The conversation header + // only copies a PEER's address, so without this there's no way to hand out your own. Copies on + // click only (chatMyAddress may persist a freshly chosen address). + { + ImGui::PushStyleColor(ImGuiCol_Text, material::OnSurfaceMedium()); + // Text-only: SmallButton uses the body font, which has no Material icon glyph (would show "?"). + if (ImGui::SmallButton(TR("chat_copy_my_address"))) { + std::string myAddr = app->chatMyAddress(); + if (myAddr.empty()) { + Notifications::instance().warning(TR("chat_no_my_address")); + } else { + ImGui::SetClipboardText(myAddr.c_str()); + Notifications::instance().info(TR("address_copied")); + } + } + ImGui::PopStyleColor(); + if (ImGui::IsItemHovered()) material::Tooltip("%s", TR("chat_my_address_tip")); + } const std::string search = s_search; ImGui::Separator(); if (convs.empty()) { diff --git a/src/util/i18n.cpp b/src/util/i18n.cpp index 30fb009..2c9b4ac 100644 --- a/src/util/i18n.cpp +++ b/src/util/i18n.cpp @@ -263,6 +263,9 @@ void I18n::loadBuiltinEnglish() strings_["chat_jump_latest"] = "Latest"; strings_["chat_empty_title"] = "No conversations yet"; strings_["chat_empty_start"] = "Start one with \"New conversation\"."; + strings_["chat_copy_my_address"] = "Copy my chat address"; + strings_["chat_my_address_tip"] = "Share this address so others can message you"; + strings_["chat_no_my_address"] = "No chat address yet"; strings_["chat_search"] = "Search conversations"; strings_["chat_no_matches"] = "No conversations match your search."; strings_["chat_export"] = "Export chat\xE2\x80\xA6";