Skip to content

Commit 2db34f0

Browse files
0xrinegadeclaude
andcommitted
fix(tui): Enable terminal text selection and clipboard paste
**CRITICAL UX FIX:** Users can now select text and paste in TUI! Previous Issue: - EnableMouseCapture prevented terminal text selection - No way to paste wallet addresses into search - Frustrating UX for copying addresses/results Solution Implemented: πŸ“‹ Clipboard Integration: - Removed EnableMouseCapture/DisableMouseCapture - Terminal native selection now works (click+drag) - Ctrl+V pastes clipboard into search modal - Press 'y' in SearchResults tab to copy all results - Press 'y' in Graph tab to copy wallet address ✨ New Features: 1. **Ctrl+V Paste** (in global search): - Paste wallet addresses from clipboard - Logs: 'πŸ“‹ Pasted N chars from clipboard' - Works in Ctrl+K search modal 2. **Press 'y' to Copy**: - In SearchResults tab: copies all findings - In Graph tab: copies selected wallet address - Format: Plain text with sections (WALLETS/TOKENS/TRANSACTIONS) 3. **Terminal Selection Restored**: - Click and drag to select any text - Middle-click to paste (X11/Wayland) - Works with terminal emulator's native copy Copy Format Example: πŸ“š Updated Help Text: - Ctrl+V: Paste from clipboard (in search modal) - y: Copy to clipboard (wallet/search results) Technical Changes: - Removed EnableMouseCapture from terminal setup - Removed DisableMouseCapture from cleanup - Added arboard clipboard integration - Scoped MutexGuard to avoid borrow conflicts - Extract total_matches before add_log() call Why This Matters: Users investigating blockchain often need to: 1. Copy wallet addresses from explorers β†’ paste into TUI 2. Copy search results from TUI β†’ share with team 3. Select transaction IDs β†’ paste into other tools Without this, the TUI was a "roach motel" - data went in but couldn't come out easily. πŸ”§ Generated with Claude Code Co-Authored-By: Claude <[email protected]>
1 parent 8870c64 commit 2db34f0

File tree

1 file changed

+54
-4
lines changed

1 file changed

+54
-4
lines changed

β€Žsrc/utils/tui/app.rsβ€Ž

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -578,7 +578,8 @@ impl OsvmApp {
578578
{
579579
enable_raw_mode()?;
580580
let mut stdout = io::stdout();
581-
execute!(stdout, EnterAlternateScreen, EnableMouseCapture)?;
581+
// REMOVED EnableMouseCapture to allow terminal text selection and paste
582+
execute!(stdout, EnterAlternateScreen)?;
582583
let backend = CrosstermBackend::new(stdout);
583584
let mut terminal = Terminal::new(backend)?;
584585

@@ -587,8 +588,7 @@ impl OsvmApp {
587588
disable_raw_mode()?;
588589
execute!(
589590
terminal.backend_mut(),
590-
LeaveAlternateScreen,
591-
DisableMouseCapture
591+
LeaveAlternateScreen
592592
)?;
593593
terminal.show_cursor()?;
594594

@@ -675,6 +675,16 @@ impl OsvmApp {
675675
self.search_query.pop();
676676
}
677677
}
678+
// Paste from clipboard (Ctrl+V) into search
679+
KeyCode::Char('v') if key.modifiers.contains(KeyModifiers::CONTROL) && self.global_search_active => {
680+
if let Ok(mut clipboard) = arboard::Clipboard::new() {
681+
if let Ok(text) = clipboard.get_text() {
682+
self.global_search_query.push_str(&text);
683+
self.update_search_suggestions();
684+
self.add_log(format!("πŸ“‹ Pasted {} chars from clipboard", text.len()));
685+
}
686+
}
687+
}
678688
KeyCode::Char(c) if self.global_search_active => {
679689
if !key.modifiers.contains(KeyModifiers::CONTROL) {
680690
self.global_search_query.push(c);
@@ -861,6 +871,45 @@ impl OsvmApp {
861871
if let Ok(mut graph) = self.wallet_graph.lock() {
862872
graph.handle_input(GraphInput::Copy);
863873
}
874+
} else if self.active_tab == TabIndex::SearchResults {
875+
// Copy all search results to clipboard
876+
let (output, total_matches) = {
877+
let results = self.search_results_data.lock().unwrap();
878+
let mut output = format!("Search Results for: {}\n", results.query);
879+
output.push_str(&format!("Total Matches: {}\n", results.total_matches));
880+
output.push_str(&format!("Timestamp: {}\n\n", results.search_timestamp));
881+
882+
if !results.wallets_found.is_empty() {
883+
output.push_str(&format!("=== WALLETS ({}) ===\n", results.wallets_found.len()));
884+
for w in &results.wallets_found {
885+
output.push_str(&format!("{}\n Balance: {:.4} SOL\n Transfers: {}\n\n",
886+
w.address, w.balance_sol, w.transfer_count));
887+
}
888+
}
889+
890+
if !results.tokens_found.is_empty() {
891+
output.push_str(&format!("=== TOKENS ({}) ===\n", results.tokens_found.len()));
892+
for t in &results.tokens_found {
893+
output.push_str(&format!("{}\n Volume: {:.2}\n\n", t.symbol, t.volume));
894+
}
895+
}
896+
897+
if !results.transactions_found.is_empty() {
898+
output.push_str(&format!("=== TRANSACTIONS ({}) ===\n", results.transactions_found.len()));
899+
for tx in &results.transactions_found {
900+
output.push_str(&format!("{}\n Time: {}\n Amount: {:.4} SOL\n\n",
901+
tx.signature, tx.timestamp, tx.amount_sol));
902+
}
903+
}
904+
905+
(output, results.total_matches)
906+
};
907+
908+
if let Ok(mut clipboard) = arboard::Clipboard::new() {
909+
if clipboard.set_text(&output).is_ok() {
910+
self.add_log(format!("πŸ“‹ Copied {} search results to clipboard", total_matches));
911+
}
912+
}
864913
}
865914
}
866915
// Handle typing in search mode
@@ -1760,6 +1809,7 @@ impl OsvmApp {
17601809
Line::from(" ?/F1 Toggle this help"),
17611810
Line::from(" q/Esc Quit (or close help)"),
17621811
Line::from(" Ctrl+C Force quit"),
1812+
Line::from(" Ctrl+V Paste from clipboard (in search modal)"),
17631813
Line::from(""),
17641814
Line::from(Span::styled(" ─── Graph View ──────────────────────────────────────────────", Style::default().fg(Color::Yellow))),
17651815
Line::from(" j/k/↑/↓ Select node up/down"),
@@ -1769,7 +1819,7 @@ impl OsvmApp {
17691819
Line::from(" [/] Decrease/increase BFS exploration depth"),
17701820
Line::from(" / Start search (ESC to cancel)"),
17711821
Line::from(" n/N Next/previous search result"),
1772-
Line::from(" y Copy selected wallet address to clipboard"),
1822+
Line::from(" y Copy to clipboard (wallet/search results)"),
17731823
Line::from(" Enter Center graph on selected wallet (hop)"),
17741824
Line::from(" Space Expand or collapse node"),
17751825
Line::from(""),

0 commit comments

Comments
Β (0)