add support deletion
This commit is contained in:
@@ -3,7 +3,7 @@ use std::time::Duration;
|
||||
use anyhow::Error;
|
||||
use gpui::{AppContext, Context, Subscription, Task};
|
||||
use nostr_sdk::prelude::*;
|
||||
use signed_core::{Announcement, RepoAddr, RepoStatus, filters, parse_state};
|
||||
use signed_core::{Announcement, Deletions, RepoAddr, RepoStatus, filters, parse_state};
|
||||
|
||||
use crate::backend::{Backend, BackendEvent};
|
||||
|
||||
@@ -41,11 +41,14 @@ impl RepoStore {
|
||||
let subscription = cx.subscribe(&backend, |this, _backend, event, cx| {
|
||||
let relevant = match event {
|
||||
BackendEvent::NostrUpdate(update) => {
|
||||
// Deletions may target any event of this repository.
|
||||
let deletion =
|
||||
update.kind == Kind::EventDeletion || update.kind == Kind::RequestToVanish;
|
||||
let coordinate = update.coordinate.as_ref() == Some(&this.addr);
|
||||
let author = update.author == this.addr.public_key;
|
||||
let kind = update.kind == Kind::GitRepoAnnouncement;
|
||||
|
||||
coordinate || (author && kind)
|
||||
deletion || coordinate || (author && kind)
|
||||
}
|
||||
BackendEvent::Published(event) => {
|
||||
let kind = event.kind == Kind::GitRepoAnnouncement;
|
||||
@@ -94,14 +97,15 @@ impl RepoStore {
|
||||
let addr = self.addr.clone();
|
||||
|
||||
Backend::global(cx).update(cx, |backend, cx| {
|
||||
backend.subscribe_bootstrap(
|
||||
vec![
|
||||
filters::announcement(&addr),
|
||||
filters::state(&addr),
|
||||
filters::activity(&addr),
|
||||
],
|
||||
cx,
|
||||
);
|
||||
let mut repo_filters = vec![
|
||||
filters::announcement(&addr),
|
||||
filters::state(&addr),
|
||||
filters::activity(&addr),
|
||||
];
|
||||
// Deletion requests (NIP-09/62) must be known before any
|
||||
// event of this repository can be shown.
|
||||
repo_filters.extend(filters::deletions_for_repo(&addr));
|
||||
backend.subscribe_bootstrap(repo_filters, cx);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -141,31 +145,38 @@ impl RepoStore {
|
||||
let addr = self.addr.clone();
|
||||
|
||||
let work = cx.background_spawn(async move {
|
||||
let queries = async {
|
||||
let (announcements, states, activity, deletion_events) = async {
|
||||
let db = client.database();
|
||||
|
||||
let announcements = db.query(filters::announcement(&addr)).await?;
|
||||
let states = db.query(filters::state(&addr)).await?;
|
||||
let activity = db.query(filters::activity(&addr)).await?;
|
||||
let deletion_events = db.query(filters::deletions()).await?;
|
||||
|
||||
Ok::<_, Error>((announcements, states, activity))
|
||||
Ok::<_, Error>((announcements, states, activity, deletion_events))
|
||||
}
|
||||
.await?;
|
||||
|
||||
let (announcements, states, activity) = queries;
|
||||
let deletions = Deletions::from_events(deletion_events);
|
||||
|
||||
// Parse and sort off the main thread; only plain data
|
||||
// crosses back into the entity.
|
||||
let announcement = latest(announcements)
|
||||
let all_announcements = announcements
|
||||
.into_iter()
|
||||
.filter(|e| !deletions.is_deleted(e));
|
||||
let announcement = latest(all_announcements)
|
||||
.as_ref()
|
||||
.and_then(Announcement::from_event);
|
||||
|
||||
let state = latest(states).map(|state| parse_state(&state));
|
||||
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());
|
||||
|
||||
for event in activity {
|
||||
if deletions.is_deleted(&event) {
|
||||
continue;
|
||||
}
|
||||
match event.kind {
|
||||
Kind::GitIssue => issues.push(event),
|
||||
Kind::GitPatch => patches.push(event),
|
||||
|
||||
@@ -5,7 +5,7 @@ use std::time::Duration;
|
||||
use anyhow::Error;
|
||||
use gpui::{AppContext, Context, Subscription, Task};
|
||||
use nostr_sdk::prelude::*;
|
||||
use signed_core::{Announcement, RepoAddr, filters, repo_addr};
|
||||
use signed_core::{Announcement, Deletions, RepoAddr, filters, repo_addr};
|
||||
|
||||
use crate::backend::{Backend, BackendEvent};
|
||||
|
||||
@@ -40,9 +40,12 @@ impl RepoListStore {
|
||||
let subscription = cx.subscribe(&backend, |this, _backend, event, cx| {
|
||||
let relevant = match event {
|
||||
BackendEvent::NostrUpdate(update) => {
|
||||
// Activity (patches, issues, ...) is addressed to repos via
|
||||
// `a` tags, so its author isn't the repo owner; always refresh.
|
||||
if filters::ACTIVITY_KINDS.contains(&update.kind) {
|
||||
// Deletions may target anything we list; always refresh.
|
||||
if update.kind == Kind::EventDeletion || update.kind == Kind::RequestToVanish {
|
||||
true
|
||||
} else if filters::ACTIVITY_KINDS.contains(&update.kind) {
|
||||
// Activity (patches, issues, ...) is addressed to repos via
|
||||
// `a` tags, so its author isn't the repo owner; always refresh.
|
||||
true
|
||||
} else {
|
||||
let is_announcement = update.kind == Kind::GitRepoAnnouncement;
|
||||
@@ -98,6 +101,9 @@ impl RepoListStore {
|
||||
None => filters::all_announcements(),
|
||||
};
|
||||
backend.sync_bootstrap(filter, cx);
|
||||
// Deletion requests (NIP-09/62) must be known before any
|
||||
// announcement can be shown.
|
||||
backend.sync_bootstrap(filters::deletions(), cx);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -143,12 +149,18 @@ impl RepoListStore {
|
||||
};
|
||||
|
||||
let events = client.database().query(filter).await?;
|
||||
let deletion_events = client.database().query(filters::deletions()).await?;
|
||||
let deletions = Deletions::from_events(deletion_events);
|
||||
|
||||
// Dedup and sort off the main thread; only the final list
|
||||
// crosses back into the entity.
|
||||
let mut by_repo: HashMap<RepoAddr, Announcement> = HashMap::new();
|
||||
|
||||
for event in events {
|
||||
if deletions.is_deleted(&event) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let Some(announcement) = Announcement::from_event(&event) else {
|
||||
continue;
|
||||
};
|
||||
@@ -175,6 +187,9 @@ impl RepoListStore {
|
||||
|
||||
let state_filter = Filter::new().kind(Kind::RepoState);
|
||||
for event in client.database().query(state_filter).await? {
|
||||
if deletions.is_deleted(&event) {
|
||||
continue;
|
||||
}
|
||||
let Some(id) = event.tags.identifier() else {
|
||||
continue;
|
||||
};
|
||||
@@ -191,16 +206,10 @@ impl RepoListStore {
|
||||
.kinds(filters::ACTIVITY_KINDS)
|
||||
.since(Timestamp::now() - ACTIVITY_WINDOW);
|
||||
for event in client.database().query(activity_filter).await? {
|
||||
for tag in event.tags.iter() {
|
||||
if tag.kind() != "a" {
|
||||
continue;
|
||||
}
|
||||
let Some(content) = tag.content() else {
|
||||
continue;
|
||||
};
|
||||
let Ok(addr) = Coordinate::parse(content) else {
|
||||
continue;
|
||||
};
|
||||
if deletions.is_deleted(&event) {
|
||||
continue;
|
||||
}
|
||||
for addr in event.tags.coordinates() {
|
||||
if addr.kind != Kind::GitRepoAnnouncement {
|
||||
continue;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user