feat: separate draft pull requests into their own tab

This commit is contained in:
Valdemar Lorenzen
2026-10-21 10:25:08 +02:00
parent cce3b1e469
commit 6a359cc351
9 changed files with 179 additions and 22 deletions
+34 -15
View File
@@ -24,6 +24,7 @@ pub enum Category {
Tags,
Open,
Closed,
Drafts,
All,
}
impl Category {
@@ -36,6 +37,7 @@ impl Category {
Self::Tags => "Tags",
Self::Open => "Open",
Self::Closed => "Closed",
Self::Drafts => "Drafts",
Self::All => "All",
}
}
@@ -814,7 +816,12 @@ impl DiffState {
pub fn categories(&self) -> &'static [Category] {
if self.pull_request_remote.is_some() {
&[Category::Open, Category::Closed, Category::All]
&[
Category::Open,
Category::Closed,
Category::Drafts,
Category::All,
]
} else {
self.catalog
.as_ref()
@@ -1207,26 +1214,34 @@ impl DiffState {
.collect();
}
fn pull_request_streams(&self) -> std::ops::Range<usize> {
match self.categories().get(self.category) {
Some(Category::All) => 0..2,
Some(Category::Closed) => 1..2,
_ => 0..1,
}
}
pub(crate) fn pull_request_partial(&self) -> bool {
self.pull_request_remote.is_some()
&& self
.pull_request_categories
.iter()
.enumerate()
.any(|(index, status)| {
(self.category == 2 || self.category == index) && !status.complete
})
.pull_request_streams()
.any(|index| !self.pull_request_categories[index].complete)
}
pub(crate) fn pull_request_notice(&self) -> Option<String> {
self.pull_request_remote.as_ref()?;
let active = self.categories()[self.category];
let statuses: Vec<_> = self
.pull_request_categories
.categories()
.iter()
.enumerate()
.filter(|(index, _)| self.category == 2 || self.category == *index)
.map(|(index, status)| {
let category = [Category::Open, Category::Closed][index];
.copied()
.filter(|category| {
*category != Category::All && (active == Category::All || *category == active)
})
.map(|category| {
let status =
&self.pull_request_categories[usize::from(category == Category::Closed)];
let count = self.catalog.as_ref().map_or(0, |catalog| {
catalog
.entries
@@ -1254,8 +1269,9 @@ impl DiffState {
}
fn retry_pull_requests(&mut self) {
for (index, status) in self.pull_request_categories.iter_mut().enumerate() {
if (self.category == 2 || self.category == index) && status.error.take().is_some() {
for index in self.pull_request_streams() {
let status = &mut self.pull_request_categories[index];
if status.error.take().is_some() {
self.pull_request_retries[index] += 1;
self.loading = true;
}
@@ -1284,7 +1300,10 @@ impl DiffState {
if entry.target == RevisionTarget::Working
|| (entry.category != category
&& !(category == Category::All
&& matches!(entry.category, Category::Open | Category::Closed)))
&& matches!(
entry.category,
Category::Open | Category::Closed | Category::Drafts
)))
{
continue;
}
+10
View File
@@ -13,6 +13,7 @@ pub(crate) struct PullRequestSummary {
pub title: String,
pub description: String,
pub closed: bool,
pub draft: bool,
pub created_at: String,
}
@@ -694,11 +695,19 @@ fn summary(
) -> Result<PullRequestSummary, String> {
let gitlab = provider == Provider::Gitlab;
let (closed, merged) = status(provider, value)?;
let draft = match value.get("draft") {
None => false,
Some(value) => value
.as_bool()
.ok_or("Forge API returned invalid draft flag")?,
};
let author = author(provider, value)?;
let state = if merged {
"merged"
} else if closed {
"closed"
} else if draft {
"draft"
} else {
"open"
};
@@ -733,6 +742,7 @@ fn summary(
_ => format!("{author} · {state} · {size}"),
},
closed,
draft,
created_at: created_at(value)?,
})
}
+1 -1
View File
@@ -105,7 +105,7 @@ Local reviews: :diff.comment anchors exact Visual text, Visual Line rows, or the
:diff.review.save PATH exports JSON; :diff.review.open [ID|PATH] selects/imports; :diff.review.new
Normal Esc or :pane.close discards unsaved text and dismisses the floating editor
Snapshot anchors stay immutable; stale comments lose gutter markers; no publishing
Pull requests: :pull_requests [REMOTE]; GitHub/GitLab/Gitea Open/Closed/All tabs, type to search
Pull requests: :pull_requests [REMOTE]; GitHub/GitLab/Gitea Open/Closed/Drafts/All tabs, type to search
Enter opens the immutable PR head against its merge base; API auth uses provider tokens or gh/glab
Resolve jj conflicts: :resolve opens the current working-copy conflicts in a dedicated workspace
Editable marker-free Draft vs readonly Alternative; :resolve.history shows inputs/base
+2
View File
@@ -1635,6 +1635,8 @@ impl Repository {
description: pull.description,
category: if pull.closed {
Category::Closed
} else if pull.draft {
Category::Drafts
} else {
Category::Open
},