feat: add community ui #52

Merged
reya merged 48 commits from feat/community-ui into master 2026-09-23 01:12:53 +00:00
4 changed files with 8 additions and 1549 deletions
Showing only changes of commit 33ee06f559 - Show all commits
+8 -10
View File
@@ -46,11 +46,11 @@ pub enum Intent {
/// What one round saw, for the caller to report and act on.
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct Progress {
pub fetched: usize,
pub opened: usize,
/// Wraps the round reached that no key this client holds can open.
pub unreadable: usize,
pub exhausted: bool,
/// A relay refused or never answered a page.
pub failed: bool,
/// How many relays failed the round.
pub errors: usize,
}
@@ -920,11 +920,12 @@ impl Community {
self.members = snapshot.members;
self.load_images(cx);
// A fold reads every plane, so its count is the truth for every
// channel rather than a sample of the region one round read.
// Replacing it is what lets the count fall again once a key is
// adopted; a partial round only ever raises it.
let reported = !snapshot.unreadable.is_empty();
for (channel, count) in snapshot.unreadable {
self.record_unreadable(channel, count);
}
self.unreadable = snapshot.unreadable;
if reported {
cx.emit(CommunityEvent::Unreadable(self.state.id));
@@ -1147,10 +1148,7 @@ async fn sync_round(
}
fn absorb(progress: &mut Progress, page: &WrapPage) {
progress.fetched += page.raw;
progress.opened += page.opened.len();
progress.unreadable += page.unreadable;
progress.exhausted |= page.exhausted;
progress.failed |= page.failed;
progress.errors += page.errors;
}
-16
View File
@@ -708,22 +708,6 @@ mod tests {
}
}
#[test]
fn only_the_list_and_a_community_id_have_a_route() {
let id = CommunityId::from_bytes([0x42; 32]);
assert_eq!(route_of(&sync::list_subscription_id()), Some(Route::List));
assert_eq!(
route_of(&sync::subscription_id(&id)),
Some(Route::Community(id))
);
assert_eq!(route_of(&SubscriptionId::new("concord-history-3")), None);
assert_eq!(
route_of(&SubscriptionId::new("some/other/subscription")),
None
);
}
/// A burst within one window folds each community once, and the list once,
/// however many events arrived.
#[test]
-35
View File
@@ -1087,32 +1087,6 @@ mod tests {
});
}
/// The List discovering a root moves the community on without dropping the
/// one held: only the current root is exchanged for the material's.
#[test]
fn a_list_material_at_a_newer_epoch_keeps_the_root_it_superseded() {
let held_state = held(
CommunityId::from_bytes([0x42; 32]),
Keys::generate().public_key(),
);
let mut fresh = held_state.clone();
fresh.root_epoch = Epoch(3);
fresh.community_root = [0x55; 32];
let merged = refresh(held_state.clone(), fresh);
assert_eq!(merged.root_epoch, Epoch(3));
assert_eq!(merged.community_root, [0x55; 32]);
assert_eq!(
merged
.held_roots
.iter()
.map(|root| (root.epoch, root.key))
.collect::<Vec<_>>(),
vec![(held_state.root_epoch, held_state.community_root)]
);
}
/// What `CommunityRegistry` needs from a created community: a state document
/// `load` finds, a control plane the subscription filter actually addresses,
/// and a fold that survives an inbound control edit.
@@ -1454,15 +1428,6 @@ mod tests {
assert_eq!(community_of(&subscription_id(&id)), Some(id));
}
/// A relay answers a longer REQ with `invalid subscription id length` but
/// `subscribe` still reports success, so an over-long id fails silently.
#[test]
fn a_community_subscription_id_fits_the_nip01_cap() {
let id = CommunityId::from_bytes([0x42; 32]);
assert!(subscription_id(&id).as_str().len() <= 64);
}
fn event_at(at_ms: u64) -> Event {
EventBuilder::new(Kind::TextNote, "wrap")
.custom_created_at(Timestamp::from_secs(at_ms / 1000))
File diff suppressed because it is too large Load Diff