refactor 2
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::Error;
|
||||
use gpui::{AppContext, Context, Subscription, Task};
|
||||
@@ -7,12 +9,19 @@ use signed_core::{Announcement, RepoAddr, filters};
|
||||
|
||||
use crate::backend::{Backend, BackendEvent};
|
||||
|
||||
/// Delay between a refresh request and the actual re-query, so bursts of
|
||||
/// events (e.g. sync progress ticks) collapse into one query.
|
||||
const REFRESH_DEBOUNCE: Duration = Duration::from_millis(300);
|
||||
|
||||
/// Store listing repository announcements (global discovery or per-author).
|
||||
pub struct RepoListStore {
|
||||
pub announcements: Vec<Announcement>,
|
||||
/// Shared so views can clone the list per frame without a deep copy.
|
||||
pub announcements: Arc<Vec<Announcement>>,
|
||||
author: Option<PublicKey>,
|
||||
refreshing: bool,
|
||||
refresh_dirty: bool,
|
||||
/// A refresh is waiting out [`REFRESH_DEBOUNCE`].
|
||||
debouncing: bool,
|
||||
tasks: Vec<Task<Result<(), Error>>>,
|
||||
_subscription: Subscription,
|
||||
}
|
||||
@@ -42,10 +51,11 @@ impl RepoListStore {
|
||||
});
|
||||
|
||||
let mut store = Self {
|
||||
announcements: Vec::new(),
|
||||
announcements: Arc::new(Vec::new()),
|
||||
author,
|
||||
refreshing: false,
|
||||
refresh_dirty: false,
|
||||
debouncing: false,
|
||||
_subscription: subscription,
|
||||
tasks: Vec::new(),
|
||||
};
|
||||
@@ -78,14 +88,34 @@ 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. The query and processing run on a
|
||||
/// background thread; only the results are applied on the main thread.
|
||||
/// Debounced: a short delay collapses bursts of requests (e.g. sync
|
||||
/// progress ticks), and requests that arrive while a query is running
|
||||
/// are folded into one follow-up query. The query and processing run on
|
||||
/// a background thread; only the results are applied on the main thread.
|
||||
pub fn refresh(&mut self, cx: &mut Context<Self>) {
|
||||
if self.refreshing {
|
||||
self.refresh_dirty = true;
|
||||
return;
|
||||
}
|
||||
if self.debouncing {
|
||||
return;
|
||||
}
|
||||
self.debouncing = true;
|
||||
|
||||
let task = cx.spawn(async move |this, cx| {
|
||||
cx.background_executor().timer(REFRESH_DEBOUNCE).await;
|
||||
|
||||
this.update(cx, |this, cx| {
|
||||
this.debouncing = false;
|
||||
this.run_refresh(cx);
|
||||
})
|
||||
});
|
||||
|
||||
self.tasks.push(task);
|
||||
}
|
||||
|
||||
/// One query + apply cycle (debounced entry point).
|
||||
fn run_refresh(&mut self, cx: &mut Context<Self>) {
|
||||
self.refreshing = true;
|
||||
|
||||
let client = Backend::global(cx).read(cx).client();
|
||||
@@ -136,7 +166,7 @@ impl RepoListStore {
|
||||
};
|
||||
|
||||
let again = this.update(cx, |this, cx| {
|
||||
this.announcements = announcements;
|
||||
this.announcements = Arc::new(announcements);
|
||||
cx.notify();
|
||||
|
||||
this.refreshing = false;
|
||||
|
||||
Reference in New Issue
Block a user