extract group discovery into a discovery entity
This commit is contained in:
@@ -6,7 +6,7 @@ use gpui::{
|
||||
IntoElement, ParentElement, Render, SharedString, Styled, Subscription, WeakEntity, Window,
|
||||
div, uniform_list,
|
||||
};
|
||||
use nip29::{GroupCandidate, GroupKey, GroupsEvent, GroupsRegistry};
|
||||
use nip29::{Discovery, GroupCandidate, GroupKey, GroupsEvent, GroupsRegistry};
|
||||
use nostr_sdk::prelude::RelayUrl;
|
||||
use settings::AppSettings;
|
||||
use smallvec::{SmallVec, smallvec};
|
||||
@@ -35,19 +35,18 @@ pub struct BrowsePanel {
|
||||
relay: Option<RelayUrl>,
|
||||
/// The groups the relay has announced so far
|
||||
candidates: Vec<GroupCandidate>,
|
||||
/// The communities of the user's contacts
|
||||
contacts: Vec<GroupCandidate>,
|
||||
/// Whether the contacts' communities are still resolving
|
||||
contacts_loading: bool,
|
||||
/// The groups discovered from the cache and the relays
|
||||
discovery: Entity<Discovery>,
|
||||
/// Whether the relay is still answering
|
||||
loading: bool,
|
||||
_subscriptions: SmallVec<[Subscription; 2]>,
|
||||
_subscriptions: SmallVec<[Subscription; 3]>,
|
||||
}
|
||||
|
||||
impl BrowsePanel {
|
||||
fn new(dock: WeakEntity<DockArea>, window: &mut Window, cx: &mut Context<Self>) -> Self {
|
||||
let input = cx.new(|cx| InputState::new(window, cx).placeholder(INPUT_PLACEHOLDER));
|
||||
let registry = GroupsRegistry::global(cx);
|
||||
let discovery = registry.read(cx).discovery();
|
||||
|
||||
let mut subscriptions = smallvec![];
|
||||
|
||||
@@ -59,6 +58,10 @@ impl BrowsePanel {
|
||||
}),
|
||||
);
|
||||
|
||||
subscriptions.push(cx.observe(&discovery, |_, _, cx| {
|
||||
cx.notify();
|
||||
}));
|
||||
|
||||
subscriptions.push(
|
||||
cx.subscribe(®istry, |this, _registry, event, cx| match event {
|
||||
GroupsEvent::Browsed(candidate) => {
|
||||
@@ -67,19 +70,15 @@ impl BrowsePanel {
|
||||
GroupsEvent::BrowseSettled(relay) => {
|
||||
this.settle(relay.clone(), cx);
|
||||
}
|
||||
GroupsEvent::Suggested(candidate) => {
|
||||
this.push_contact(candidate.as_ref().clone(), cx);
|
||||
}
|
||||
GroupsEvent::SuggestSettled => {
|
||||
this.settle_contacts(cx);
|
||||
}
|
||||
_ => {}
|
||||
}),
|
||||
);
|
||||
|
||||
// Wait for the panel to leave the stack before kicking off the sync.
|
||||
cx.defer_in(window, |this, _window, cx| {
|
||||
this.load_contacts(cx);
|
||||
// Wait for the panel to leave the stack before kicking off the sweep.
|
||||
cx.defer_in(window, |_this, _window, cx| {
|
||||
GroupsRegistry::global(cx).update(cx, |registry, cx| {
|
||||
registry.discover(cx);
|
||||
});
|
||||
});
|
||||
|
||||
Self {
|
||||
@@ -88,50 +87,12 @@ impl BrowsePanel {
|
||||
input,
|
||||
relay: None,
|
||||
candidates: Vec::new(),
|
||||
contacts: Vec::new(),
|
||||
contacts_loading: true,
|
||||
discovery,
|
||||
loading: false,
|
||||
_subscriptions: subscriptions,
|
||||
}
|
||||
}
|
||||
|
||||
/// Pull the resolved contacts' communities and start the contacts sync.
|
||||
fn load_contacts(&mut self, cx: &mut Context<Self>) {
|
||||
let registry = GroupsRegistry::global(cx);
|
||||
|
||||
let (candidates, loading) = registry.update(cx, |registry, cx| {
|
||||
registry.load_contacts_groups(cx);
|
||||
(
|
||||
registry.contacts_candidates().to_vec(),
|
||||
registry.contacts_loading(),
|
||||
)
|
||||
});
|
||||
|
||||
self.contacts = candidates;
|
||||
self.contacts_loading = loading;
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn push_contact(&mut self, candidate: GroupCandidate, cx: &mut Context<Self>) {
|
||||
match self.contacts.iter_mut().find(|c| c.key == candidate.key) {
|
||||
Some(existing) => *existing = candidate,
|
||||
None => self.contacts.push(candidate),
|
||||
}
|
||||
|
||||
self.contacts.sort_by(|a, b| {
|
||||
a.display_name()
|
||||
.to_lowercase()
|
||||
.cmp(&b.display_name().to_lowercase())
|
||||
});
|
||||
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn settle_contacts(&mut self, cx: &mut Context<Self>) {
|
||||
self.contacts_loading = false;
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
/// Browse the relay in the input.
|
||||
fn browse(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
let registry = GroupsRegistry::global(cx);
|
||||
@@ -211,10 +172,10 @@ impl BrowsePanel {
|
||||
range: Range<usize>,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Vec<AnyElement> {
|
||||
let registry = GroupsRegistry::global(cx);
|
||||
let hide_avatar = AppSettings::get_hide_avatar(cx);
|
||||
let panel = cx.entity().downgrade();
|
||||
|
||||
let registry = GroupsRegistry::global(cx);
|
||||
let joined: Vec<GroupKey> = registry
|
||||
.read(cx)
|
||||
.groups()
|
||||
@@ -229,16 +190,19 @@ impl BrowsePanel {
|
||||
.map(|candidate| {
|
||||
let key = candidate.key.clone();
|
||||
let name = SharedString::from(candidate.display_name().to_owned());
|
||||
|
||||
let seed = key.cache_tag();
|
||||
let is_joined = joined.contains(&key);
|
||||
|
||||
let picture = candidate
|
||||
.display_image()
|
||||
.map(|picture| SharedString::from(picture.to_owned()));
|
||||
let seed = key.cache_tag();
|
||||
|
||||
let detail = if relay_detail {
|
||||
key.relay().domain().unwrap_or_else(|| key.relay().as_str())
|
||||
} else {
|
||||
key.id().as_str()
|
||||
};
|
||||
let is_joined = joined.contains(&key);
|
||||
|
||||
let action = if is_joined {
|
||||
Button::new(format!("browse-joined-{seed}"))
|
||||
@@ -335,9 +299,9 @@ impl Focusable for BrowsePanel {
|
||||
impl Render for BrowsePanel {
|
||||
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let count = self.candidates.len();
|
||||
let from_contacts = self.relay.is_none();
|
||||
let discover = self.relay.is_none();
|
||||
|
||||
let (contacts, contact_count) = if from_contacts {
|
||||
let (discovered, discovered_count, discovering) = if discover {
|
||||
let registry = GroupsRegistry::global(cx);
|
||||
let joined: Vec<GroupKey> = registry
|
||||
.read(cx)
|
||||
@@ -346,34 +310,37 @@ impl Render for BrowsePanel {
|
||||
.map(|group| group.read(cx).key().clone())
|
||||
.collect();
|
||||
|
||||
let contacts: Vec<GroupCandidate> = self
|
||||
.contacts
|
||||
let discovery = self.discovery.read(cx);
|
||||
let discovering = discovery.loading();
|
||||
|
||||
let discovered: Vec<GroupCandidate> = discovery
|
||||
.discovered()
|
||||
.iter()
|
||||
.filter(|candidate| !joined.contains(&candidate.key))
|
||||
.cloned()
|
||||
.collect();
|
||||
|
||||
let count = contacts.len();
|
||||
(contacts, count)
|
||||
let count = discovered.len();
|
||||
(discovered, count, discovering)
|
||||
} else {
|
||||
(Vec::new(), 0)
|
||||
(Vec::new(), 0, false)
|
||||
};
|
||||
|
||||
let body = if from_contacts {
|
||||
if contact_count > 0 {
|
||||
let body = if discover {
|
||||
if discovered_count > 0 {
|
||||
uniform_list(
|
||||
"browse-contacts",
|
||||
contact_count,
|
||||
"browse-discovered",
|
||||
discovered_count,
|
||||
cx.processor(move |this, range, _window, cx| {
|
||||
this.render_rows(&contacts, true, range, cx)
|
||||
this.render_rows(&discovered, true, range, cx)
|
||||
}),
|
||||
)
|
||||
.h_full()
|
||||
.into_any_element()
|
||||
} else if self.contacts_loading {
|
||||
notice("Loading communities from your contacts…", cx)
|
||||
} else if discovering {
|
||||
notice("Discovering groups…", cx)
|
||||
} else {
|
||||
notice("No communities from your contacts.", cx)
|
||||
notice("No groups found.", cx)
|
||||
}
|
||||
} else if count > 0 {
|
||||
uniform_list(
|
||||
@@ -407,19 +374,18 @@ impl Render for BrowsePanel {
|
||||
this.browse(window, cx);
|
||||
})),
|
||||
)
|
||||
.when(
|
||||
self.loading || (from_contacts && self.contacts_loading),
|
||||
|this| this.child(Indicator::new().small().color(cx.theme().icon_accent)),
|
||||
),
|
||||
.when(self.loading || (discover && discovering), |this| {
|
||||
this.child(Indicator::new().small().color(cx.theme().icon_accent))
|
||||
}),
|
||||
)
|
||||
.when(from_contacts && contact_count > 0, |this| {
|
||||
.when(discover && discovered_count > 0, |this| {
|
||||
this.child(
|
||||
div()
|
||||
.px_3()
|
||||
.pb_1()
|
||||
.text_xs()
|
||||
.text_color(cx.theme().text_muted)
|
||||
.child("From your contacts"),
|
||||
.child("Discovered groups"),
|
||||
)
|
||||
})
|
||||
.child(div().flex_1().min_h_0().child(body))
|
||||
|
||||
Reference in New Issue
Block a user