perf(send): poll the clipboard for the paste hint only when it helps
The send tab read the OS clipboard every frame the paste button was hovered, to preview a pasted address. SDL's clipboard read is a synchronous round-trip that can stall, and the preview can only ever latch when the recipient field is empty, so most of those reads were wasted work. - The clipboard is now read only while the button is hovered and the recipient field is empty, polled once on hover entry and then at most twice a second. - Trimming the clipboard text moves to a shared helper that also bounds the copy so a pathological multi-megabyte clipboard is ignored. Tests: the trim helper handles null, surrounding whitespace, an all-whitespace string, and the length bound. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+14
-15
@@ -1416,21 +1416,20 @@ void RenderSendTab(App* app)
|
||||
paste_hovered = material::IsRectHovered(pasteBtnPos,
|
||||
ImVec2(pasteBtnPos.x + pasteBtnSize.x, pasteBtnPos.y + pasteBtnSize.y));
|
||||
|
||||
// Handle preview state — don't modify s_to_address, just store preview text
|
||||
if (paste_hovered && !s_paste_previewing) {
|
||||
const char* clip = ImGui::GetClipboardText();
|
||||
if (clip && clip[0] != '\0') {
|
||||
std::string trimmed(clip);
|
||||
while (!trimmed.empty() && (trimmed.front() == ' ' || trimmed.front() == '\n' || trimmed.front() == '\r' || trimmed.front() == '\t'))
|
||||
trimmed.erase(trimmed.begin());
|
||||
while (!trimmed.empty() && (trimmed.back() == ' ' || trimmed.back() == '\n' || trimmed.back() == '\r' || trimmed.back() == '\t'))
|
||||
trimmed.pop_back();
|
||||
// Preview any address, a mining one too: once pasted, the field explains why it can't be paid.
|
||||
bool looksValid = dragonx::util::isDragonXAddress(trimmed);
|
||||
if (looksValid && s_to_address[0] == '\0') {
|
||||
s_preview_text = trimmed;
|
||||
s_paste_previewing = true;
|
||||
}
|
||||
// Handle preview state — don't modify s_to_address, just store preview text.
|
||||
// The OS clipboard is only worth reading when the result can latch (field empty), polled on hover entry
|
||||
// and then at most every 0.5 s (SDL's clipboard is a synchronous round-trip: 1-5 ms on X11, can stall).
|
||||
static double s_nextClipPoll = 0.0;
|
||||
if (!paste_hovered) s_nextClipPoll = 0.0; // poll immediately on the next hover entry
|
||||
if (paste_hovered && !s_paste_previewing && s_to_address[0] == '\0' &&
|
||||
ImGui::GetTime() >= s_nextClipPoll) {
|
||||
s_nextClipPoll = ImGui::GetTime() + 0.5;
|
||||
// Copy immediately: the backend frees the previous clipboard buffer on the next call.
|
||||
const std::string trimmed = dragonx::util::trimmedClipboardText(ImGui::GetClipboardText());
|
||||
// Preview any address, a mining one too: once pasted, the field explains why it can't be paid.
|
||||
if (!trimmed.empty() && dragonx::util::isDragonXAddress(trimmed)) {
|
||||
s_preview_text = trimmed;
|
||||
s_paste_previewing = true;
|
||||
}
|
||||
} else if (!paste_hovered && s_paste_previewing) {
|
||||
s_paste_previewing = false;
|
||||
|
||||
Reference in New Issue
Block a user