feat: flag vendored clones and make the repo filter navigable

Two Repos-tab quality-of-life changes:

- External/vendored clones (repos with zero of your own commits — e.g. an
  upstream cloned for reference and never pushed to) are measured on
  refresh, cached in stats_cache (RepoStatsEntry.authored), shown with a
  dim ⧉ marker prefixed to the name, and hidden by the persistent
  hide_external_clones config toggle (key `x`, the `S` menu, or
  `vulp list --external|--no-external`). A fork you do commit to stays
  yours, so only true reference clones are flagged.

- Inside the `/` filter box, ↑↓ now move through the live-filtered
  results and Enter opens the highlighted repo/project directly, instead
  of the filter only "locking" on Enter with no way to scroll or select.
This commit is contained in:
dualfroz committed 2026-07-08 16:15:02 +02:00
1 parent 2ccf69f64c
commit 212c55d138
16 files changed
+120 -10

No files matched your search

+20 -1
View File
@@ -231,7 +231,26 @@ pub fn tui_phase(state: &mut HubState, existing_term: Option<crate::tui::Tty>) -
state.filter_text.clear();
state.rebuild_display();
}
KeyCode::Enter => { state.filtering = false; }
// Live navigation while the search box is open: arrows move
// the highlight through the filtered results so you can pick
// one without first "locking" the filter (j/k stay literal
// filter input). Enter opens whatever is highlighted.
KeyCode::Down => state.scroll_down(),
KeyCode::Up => state.scroll_up(),
KeyCode::Enter => match state.tab {
Tab::Repos | Tab::Projects
if state.cur_repo_idx().is_some() || state.cur_proj_idx().is_some() =>
{
// Open the highlighted repo/project directly, keeping
// the filter text applied for when we come back.
state.filtering = false;
state.open_detail = true;
return Ok(PhaseResult::OpenDetail);
}
// Nothing openable under the cursor: just lock the filter
// (exit typing, keep the text) so the full keymap works.
_ => state.filtering = false,
},
KeyCode::Backspace => {
state.filter_text.pop();
state.rebuild_display();