This commit is contained in:
2026-08-04 15:22:18 +07:00
parent 5c005e281d
commit 8707e71b53
7 changed files with 214 additions and 121 deletions
+58 -25
View File
@@ -11,9 +11,10 @@ use crate::backend::{Backend, BackendEvent};
pub struct RepoListStore {
pub announcements: Vec<Announcement>,
author: Option<PublicKey>,
_subscription: Subscription,
refreshing: bool,
refresh_dirty: bool,
tasks: Vec<Task<Result<(), Error>>>,
_subscription: Subscription,
}
impl RepoListStore {
@@ -40,6 +41,8 @@ impl RepoListStore {
let mut store = Self {
announcements: Vec::new(),
author,
refreshing: false,
refresh_dirty: false,
_subscription: subscription,
tasks: Vec::new(),
};
@@ -69,42 +72,72 @@ impl RepoListStore {
}
/// Re-query the local database. Latest announcement per repository wins.
///
/// Debounced: concurrent requests are coalesced into a single re-query
/// after the running one finishes.
pub fn refresh(&mut self, cx: &mut Context<Self>) {
if self.refreshing {
self.refresh_dirty = true;
return;
}
self.refreshing = true;
let client = Backend::global(cx).read(cx).client();
let author = self.author;
let task = cx.spawn(async move |this, cx| {
let filter = match author {
Some(a) => filters::announcements_by(a),
None => filters::all_announcements(500),
};
loop {
let filter = match author {
Some(a) => filters::announcements_by(a),
None => filters::all_announcements(500),
};
let events = client.database().query(filter).await?;
let events = match client.database().query(filter).await {
Ok(events) => events,
Err(_) => {
return this.update(cx, |this, _cx| {
this.refreshing = false;
});
}
};
this.update(cx, |this, cx| {
let mut by_repo: HashMap<(String, String), Announcement> = HashMap::new();
let again = this.update(cx, |this, cx| {
let mut by_repo: HashMap<(String, String), Announcement> = HashMap::new();
for event in events {
let Some(announcement) = Announcement::from_event(&event) else {
continue;
};
for event in events {
let Some(announcement) = Announcement::from_event(&event) else {
continue;
};
let key = (announcement.owner.to_hex(), announcement.id.clone());
let key = (announcement.owner.to_hex(), announcement.id.clone());
match by_repo.get(&key) {
Some(existing) if existing.created_at >= announcement.created_at => {}
_ => {
by_repo.insert(key, announcement);
match by_repo.get(&key) {
Some(existing) if existing.created_at >= announcement.created_at => {}
_ => {
by_repo.insert(key, announcement);
}
}
}
let mut announcements: Vec<Announcement> = by_repo.into_values().collect();
announcements.sort_by_key(|a| std::cmp::Reverse(a.created_at));
this.announcements = announcements;
cx.notify();
if this.refresh_dirty {
this.refresh_dirty = false;
true
} else {
this.refreshing = false;
false
}
})?;
if !again {
break;
}
let mut announcements: Vec<Announcement> = by_repo.into_values().collect();
announcements.sort_by_key(|a| std::cmp::Reverse(a.created_at));
this.announcements = announcements;
cx.notify();
})?;
}
Ok(())
});