fix: date repository cards from state events, not announcements

The explore list fell back to the announcement created_at because kind 30618 state events were only fetched per repository, on open. Sync them globally and refresh the list on published state events, so a card shows the last push without the user cloning first.

Open repository panels now also react to state events from relays and to locally published state events.
This commit is contained in:
2026-09-25 17:36:35 +07:00
parent 1d44338037
commit 42c1229a90
4 changed files with 39 additions and 17 deletions
+5
View File
@@ -184,6 +184,11 @@ pub fn all_announcements() -> Filter {
Filter::new().kind(Kind::GitRepoAnnouncement)
}
/// All repository state events, carrying each repository's refs and last push time.
pub fn all_states() -> Filter {
Filter::new().kind(Kind::RepoState)
}
/// How far back deletion requests are fetched and stored.
const DELETIONS_LOOKBACK: Duration = Duration::from_secs(3 * 365 * 86_400);
+12 -4
View File
@@ -207,7 +207,11 @@ impl RepoStore {
update.kind == Kind::EventDeletion || update.kind == Kind::RequestToVanish;
let coordinate = update.coordinate.as_ref() == Some(addr);
let author = update.author == addr.public_key;
let kind = update.kind == Kind::GitRepoAnnouncement;
// Announcements and state share the owner and identifier.
// State events carry `d`, not `a`, so `coordinate` misses them.
let authored = (update.kind == Kind::GitRepoAnnouncement
|| update.kind == Kind::RepoState)
&& author;
// NIP-22 comments carry no `a` tag.
// Coordinate matching fails for them.
// Any comment may reference this repository's roots.
@@ -216,18 +220,22 @@ impl RepoStore {
// Any status event may reference a root of this repository.
let status = RepoStatus::from_kind(update.kind).is_some();
deletion || coordinate || (author && kind) || comment || status
deletion || coordinate || authored || comment || status
}),
BackendEvent::Published(event) => {
let kind = event.kind == Kind::GitRepoAnnouncement;
let announcement = event.kind == Kind::GitRepoAnnouncement;
let author = event.pubkey == addr.public_key;
let coordinate = event.tags.coordinates().into_iter().any(|c| c == *addr);
// State events carry their repository id in the `d` tag.
let state = event.kind == Kind::RepoState
&& author
&& event.tags.identifier().as_deref() == Some(addr.identifier.as_str());
// Locally published deletions may target any event of this repository.
// Refresh so they take effect immediately, like relay deletions.
let deletion =
event.kind == Kind::EventDeletion || event.kind == Kind::RequestToVanish;
coordinate || (kind && author) || deletion
coordinate || (announcement && author) || state || deletion
}
_ => false,
};
+8 -1
View File
@@ -83,12 +83,16 @@ impl RepoListStore {
BackendEvent::Published(event) => {
let announcement = event.kind == Kind::GitRepoAnnouncement;
// Locally published state events advance last activity.
// Refresh so a push made in this session dates the card immediately.
let state = event.kind == Kind::RepoState;
// Locally published deletions are already in the local database.
// Refresh so they take effect immediately, like relay deletions.
let deletion =
event.kind == Kind::EventDeletion || event.kind == Kind::RequestToVanish;
announcement || deletion
announcement || state || deletion
}
// Only a completed sync refreshes the list.
// Progress ticks would re-scan the whole database several times
@@ -133,6 +137,9 @@ impl RepoListStore {
backend.update(cx, |backend, cx| {
backend.sync_bootstrap(filters::all_announcements(), cx);
// State events carry the last push time, so syncing them globally
// lets the list date every repository without the user opening it.
backend.sync_bootstrap(filters::all_states(), cx);
// Deletion requests, NIP-09/62, must be known before any announcement is shown.
backend.sync_bootstrap(filters::deletions(), cx);
});