diff options
| author | akbash <akbash@herdr.dev> | 2026-07-06 23:59:59 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-07-06 23:59:59 +0300 |
| commit | 4f22e9a73ba4d9029468e078235c5f5ce629d179 (patch) | |
| tree | 49b56a29305192c8270aa43e87bb5f1d86d00233 /src/server/headless.rs | |
| parent | 56edcbcba83b8ff7f6f69ee4231f163e97df3346 (diff) | |
fix: preserve wrapped pane links (#1099)
refs #1098
Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
Co-authored-by: Can Celik <ogulcancelik@gmail.com>
Diffstat (limited to 'src/server/headless.rs')
| -rw-r--r-- | src/server/headless.rs | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/src/server/headless.rs b/src/server/headless.rs index e84dfc59..04320ff2 100644 --- a/src/server/headless.rs +++ b/src/server/headless.rs @@ -163,6 +163,13 @@ fn dirty_patch_intersects_hyperlinks( false } +fn dirty_patch_contains_plain_url_candidate(patch: &crate::pane::TerminalDirtyPatch) -> bool { + patch.rows.iter().any(|(_, row_cells)| { + let row: String = row_cells.iter().map(|cell| cell.symbol.as_str()).collect(); + !crate::app::actions::visible_url_spans(&row).is_empty() + }) +} + // --------------------------------------------------------------------------- // Constants // --------------------------------------------------------------------------- @@ -3196,6 +3203,9 @@ impl HeadlessServer { if dirty_patch_intersects_hyperlinks(&frame, info.inner_rect, &patch) { retained_fallback!("hyperlink_intersection"); } + if dirty_patch_contains_plain_url_candidate(&patch) { + retained_fallback!("plain_url_candidate"); + } if !apply_terminal_dirty_patch(&mut frame, info.inner_rect, patch) { retained_fallback!("patch_apply_failed"); } @@ -3372,6 +3382,7 @@ impl HeadlessServer { let hyperlinks = crate::server::render_stream::visible_hyperlinks( &self.app.state, &self.app.terminal_runtimes, + Some(&buffer), ); crate::render_prof::duration_since( "full_render.visible_hyperlinks", @@ -7513,6 +7524,38 @@ next_tab = "" } #[tokio::test] + async fn retained_pty_update_declines_when_dirty_row_creates_plain_url() { + let (mut server, client_rx, pane_id) = retained_test_server(b"plain"); + server.render_and_stream(); + let _ = client_rx + .recv_timeout(Duration::from_millis(100)) + .expect("initial frame"); + + let runtime = server + .app + .state + .runtime_for_pane_in_workspace(&server.app.terminal_runtimes, 0, pane_id) + .expect("runtime"); + runtime.test_process_pty_bytes(b"\rhttps://example.com/new"); + + assert!(!server.render_retained_pty_update_and_stream()); + assert!(client_rx.recv_timeout(Duration::from_millis(50)).is_err()); + + server.render_and_stream(); + let full = read_server_frame( + client_rx + .recv_timeout(Duration::from_millis(100)) + .expect("full frame after plain URL"), + ); + assert!( + full.hyperlinks + .iter() + .any(|uri| uri == "https://example.com/new"), + "full render should synthesize plain URL hyperlink metadata" + ); + } + + #[tokio::test] async fn retained_pty_update_allows_kitty_enabled_empty_graphics_cache() { let (mut server, client_rx, pane_id) = retained_test_server(b"aaaa"); server.app.state.kitty_graphics_enabled = true; |
