add issue detail
This commit is contained in:
@@ -11,8 +11,9 @@ use crate::backend::{Backend, BackendEvent};
|
||||
/// events (e.g. per-event `NostrUpdate`s) collapse into one query.
|
||||
const REFRESH_DEBOUNCE: Duration = Duration::from_millis(300);
|
||||
|
||||
/// Per-repository store: announcement, state, issues, patches, PRs and
|
||||
/// their resolved statuses. Always derived from the local database.
|
||||
/// Per-repository store: announcement, state, issues, patches, PRs,
|
||||
/// comments and their resolved statuses. Always derived from the local
|
||||
/// database.
|
||||
pub struct RepoStore {
|
||||
addr: RepoAddr,
|
||||
pub announcement: Option<Announcement>,
|
||||
@@ -23,6 +24,8 @@ pub struct RepoStore {
|
||||
pub issues: Vec<Event>,
|
||||
pub patches: Vec<Event>,
|
||||
pub pull_requests: Vec<Event>,
|
||||
/// Comments on issues / PRs, oldest first.
|
||||
pub comments: Vec<Event>,
|
||||
statuses: Vec<Event>,
|
||||
/// Error of the last action initiated from this store, if any.
|
||||
pub last_error: Option<String>,
|
||||
@@ -73,6 +76,7 @@ impl RepoStore {
|
||||
issues: Vec::new(),
|
||||
patches: Vec::new(),
|
||||
pull_requests: Vec::new(),
|
||||
comments: Vec::new(),
|
||||
statuses: Vec::new(),
|
||||
last_error: None,
|
||||
refreshing: false,
|
||||
@@ -172,8 +176,8 @@ impl RepoStore {
|
||||
let all_states = states.into_iter().filter(|e| !deletions.is_deleted(e));
|
||||
let state = latest(all_states).map(|state| parse_state(&state));
|
||||
|
||||
let (mut issues, mut patches, mut pull_requests, mut statuses) =
|
||||
(Vec::new(), Vec::new(), Vec::new(), Vec::new());
|
||||
let (mut issues, mut patches, mut pull_requests, mut statuses, mut comments) =
|
||||
(Vec::new(), Vec::new(), Vec::new(), Vec::new(), Vec::new());
|
||||
|
||||
for event in activity {
|
||||
if deletions.is_deleted(&event) {
|
||||
@@ -183,6 +187,7 @@ impl RepoStore {
|
||||
Kind::GitIssue => issues.push(event),
|
||||
Kind::GitPatch => patches.push(event),
|
||||
Kind::GitPullRequest | Kind::GitPullRequestUpdate => pull_requests.push(event),
|
||||
Kind::Comment => comments.push(event),
|
||||
kind if RepoStatus::from_kind(kind).is_some() => statuses.push(event),
|
||||
_ => {}
|
||||
}
|
||||
@@ -191,6 +196,7 @@ impl RepoStore {
|
||||
sort_newest_first(&mut issues);
|
||||
sort_newest_first(&mut patches);
|
||||
sort_newest_first(&mut pull_requests);
|
||||
sort_oldest_first(&mut comments);
|
||||
|
||||
Ok::<_, Error>((
|
||||
announcement,
|
||||
@@ -199,21 +205,23 @@ impl RepoStore {
|
||||
patches,
|
||||
pull_requests,
|
||||
statuses,
|
||||
comments,
|
||||
))
|
||||
});
|
||||
|
||||
self.tasks.retain(|task| !task.is_ready());
|
||||
self.tasks.push(cx.spawn(async move |this, cx| {
|
||||
let (announcement, state, issues, patches, pull_requests, statuses) = match work.await {
|
||||
Ok(data) => data,
|
||||
Err(e) => {
|
||||
return this.update(cx, |this, cx| {
|
||||
this.refreshing = false;
|
||||
this.last_error = Some(e.to_string());
|
||||
cx.notify();
|
||||
});
|
||||
}
|
||||
};
|
||||
let (announcement, state, issues, patches, pull_requests, statuses, comments) =
|
||||
match work.await {
|
||||
Ok(data) => data,
|
||||
Err(e) => {
|
||||
return this.update(cx, |this, cx| {
|
||||
this.refreshing = false;
|
||||
this.last_error = Some(e.to_string());
|
||||
cx.notify();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
let again = this.update(cx, |this, cx| {
|
||||
this.announcement = announcement;
|
||||
@@ -226,6 +234,7 @@ impl RepoStore {
|
||||
this.issues = issues;
|
||||
this.patches = patches;
|
||||
this.pull_requests = pull_requests;
|
||||
this.comments = comments;
|
||||
this.statuses = statuses;
|
||||
|
||||
cx.notify();
|
||||
@@ -297,6 +306,28 @@ impl RepoStore {
|
||||
self.send(builder, cx);
|
||||
}
|
||||
|
||||
/// Comments on a root event (issue / PR), oldest first.
|
||||
pub fn comments_of(&self, root: &EventId) -> impl Iterator<Item = &Event> {
|
||||
self.comments
|
||||
.iter()
|
||||
.filter(move |e| signed_core::references_root(e, root))
|
||||
}
|
||||
|
||||
/// Comment on a root event (issue / PR) per NIP-34 (kind 1111).
|
||||
pub fn comment(&mut self, root: &Event, content: String, cx: &mut Context<Self>) {
|
||||
let Ok(root_ref) = Tag::parse(["e", &root.id.to_hex(), "", "root"]) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let builder = EventBuilder::new(Kind::Comment, content).tags([
|
||||
root_ref,
|
||||
Tag::public_key(root.pubkey),
|
||||
Tag::coordinate(self.addr.clone(), None),
|
||||
]);
|
||||
|
||||
self.send(builder, cx);
|
||||
}
|
||||
|
||||
/// Open a pull request on this repository: a root PR event whose content
|
||||
/// is the `git format-patch` output of the proposed changes.
|
||||
///
|
||||
@@ -390,6 +421,10 @@ fn sort_newest_first(events: &mut [Event]) {
|
||||
events.sort_by_key(|e| std::cmp::Reverse(e.created_at));
|
||||
}
|
||||
|
||||
fn sort_oldest_first(events: &mut [Event]) {
|
||||
events.sort_by_key(|e| e.created_at);
|
||||
}
|
||||
|
||||
/// The proposed commit of a `git format-patch` output: the `From <commit>`
|
||||
/// header on its first line.
|
||||
fn patch_current_commit(patch: &str) -> Option<&str> {
|
||||
|
||||
Reference in New Issue
Block a user