This commit is contained in:
2026-09-04 08:16:05 +07:00
parent 212f35d6bb
commit 17de4f6376
43 changed files with 376 additions and 721 deletions
@@ -26,8 +26,7 @@ use super::pull_request_detail::PullRequestDetailView;
use super::send_patch::open_send_patch_panel;
/// Height of one pull request row in the virtual list.
/// Same layout as an issue row.
const PR_ROW_HEIGHT: f32 = 73.;
const ROW_HEIGHT: f32 = 73.;
/// Status filter of the pull request list, chosen via the header's filter buttons.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -70,17 +69,10 @@ pub struct PullRequestsView {
/// Per-row heights of the virtual list.
item_sizes: Rc<Vec<Size<Pixels>>>,
/// The filtered pull request count [`Self::item_sizes`] was built for.
/// Rebuilt on change.
pr_len: usize,
/// Indices into the store's `pull_requests` matching [`Self::filter`].
/// Root PR events only, updates are revisions of the root.
/// The virtual list renders this slice.
/// Rebuilt only when the store version or the filter changes.
/// Keyed by [`Self::cache_key`].
visible_prs: Vec<usize>,
/// Header counts `(total, open, closed, draft, merged)`.
/// Root pull requests only, revisions are not separate PRs.
/// Rebuilt with [`Self::visible_prs`].
counts: (usize, usize, usize, usize, usize),
/// Store version and filter the cached rows/counts were built from.
cache_key: Option<(u64, PullRequestFilter)>,
@@ -139,6 +131,7 @@ impl PullRequestsView {
}
/// Render one row of the pull request list.
///
/// `ix` is the row index, `pr_ix` the index in the store's `pull_requests`.
fn render_row(&self, ix: usize, pr_ix: usize, cx: &mut Context<Self>) -> AnyElement {
let pr = &self.store.read(cx).pull_requests[pr_ix];
@@ -205,7 +198,6 @@ impl PullRequestsView {
fn render_header(&self, cx: &mut Context<Self>) -> AnyElement {
// Counts of the last list rebuild.
// `render` rebuilds first when the store version or filter changed, so never stale.
let (total, open, closed, draft, merged) = self.counts;
h_flex()
@@ -341,8 +333,8 @@ impl Render for PullRequestsView {
let filter = self.filter;
// Rows and counts are rebuilt only when the store refreshed or filter changed.
// Other renders reuse the cache.
let version = self.store.read(cx).version();
if self.cache_key != Some((version, filter)) {
let store = self.store.read(cx);
let mut counts = (0usize, 0usize, 0usize, 0usize, 0usize);
@@ -351,24 +343,24 @@ impl Render for PullRequestsView {
.iter()
.enumerate()
.filter_map(|(ix, pr)| {
// Kind-30620 patches are revisions of a root PR, NIP-34.
// They are not separate pull requests.
// Count root events only, or the counts inflate with every revision.
// Revisions also default to `Open` in `status_of`.
if pr.kind != Kind::GitPullRequest {
return None;
}
let status = store.status_of(pr);
counts.0 += 1;
match status {
RepoStatus::Open => counts.1 += 1,
RepoStatus::Closed => counts.2 += 1,
RepoStatus::Draft => counts.3 += 1,
RepoStatus::Applied => counts.4 += 1,
}
filter.matches(status).then_some(ix)
})
.collect();
self.counts = counts;
self.cache_key = Some((version, filter));
}
@@ -379,7 +371,7 @@ impl Render for PullRequestsView {
// Rebuild it whenever the filtered pull request count changes.
if count != self.pr_len {
self.pr_len = count;
self.item_sizes = Rc::new(vec![size(px(0.), px(PR_ROW_HEIGHT)); count]);
self.item_sizes = Rc::new(vec![size(px(0.), px(ROW_HEIGHT)); count]);
}
let sizes = self.item_sizes.clone();