refacotr
This commit is contained in:
@@ -42,6 +42,19 @@ impl InboxItem {
|
||||
pub fn is_unread(&self) -> bool {
|
||||
!self.archived && !self.unread_ids.is_empty()
|
||||
}
|
||||
|
||||
/// Recompute the unread and archived flags from `state`.
|
||||
pub fn apply_state(&mut self, state: &InboxReadState) {
|
||||
self.unread_ids = self
|
||||
.events
|
||||
.iter()
|
||||
.rev()
|
||||
.filter(|event| !state.is_read(event))
|
||||
.map(|event| event.id)
|
||||
.collect();
|
||||
|
||||
self.archived = self.events.iter().all(|event| state.is_archived(event));
|
||||
}
|
||||
}
|
||||
|
||||
/// Root issue, patch or pull request of a notification event.
|
||||
@@ -112,25 +125,18 @@ where
|
||||
|
||||
let root_event = lookup(root);
|
||||
|
||||
let unread_ids = events
|
||||
.iter()
|
||||
.rev()
|
||||
.filter(|event| !state.is_read(event))
|
||||
.map(|event| event.id)
|
||||
.collect();
|
||||
|
||||
let archived = events.iter().all(|event| state.is_archived(event));
|
||||
|
||||
InboxItem {
|
||||
let mut item = InboxItem {
|
||||
root,
|
||||
root_kind: root_event.as_ref().map(|event| event.kind),
|
||||
address: root_event
|
||||
.as_ref()
|
||||
.and_then(|event| event.tags.coordinates().next()),
|
||||
events,
|
||||
unread_ids,
|
||||
archived,
|
||||
}
|
||||
unread_ids: Vec::new(),
|
||||
archived: false,
|
||||
};
|
||||
item.apply_state(state);
|
||||
item
|
||||
})
|
||||
.collect();
|
||||
|
||||
@@ -174,6 +180,13 @@ impl InboxReadState {
|
||||
}
|
||||
}
|
||||
|
||||
/// Mark one event archived. Events at or before the cutoff are already archived.
|
||||
pub fn mark_archived(&mut self, event: &Event) {
|
||||
if event.created_at > self.archived_before {
|
||||
self.archived_ids.insert(event.id);
|
||||
}
|
||||
}
|
||||
|
||||
/// Mark every non-self event read, anchoring the cutoff ten days back.
|
||||
pub fn mark_all_read(&mut self, all: &[Event], me: PublicKey, now: Timestamp) {
|
||||
let cutoff = now - MARK_ALL_WINDOW;
|
||||
@@ -626,6 +639,47 @@ mod tests {
|
||||
assert_eq!(state.read_ids, HashSet::from([fresh.id]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mark_archived_skips_events_at_or_before_the_cutoff() {
|
||||
let now = Timestamp::from_secs(1_000_000_000);
|
||||
let event = issue(&keys(2), now.as_secs() - 1000);
|
||||
|
||||
let mut state = InboxReadState {
|
||||
archived_before: now,
|
||||
..Default::default()
|
||||
};
|
||||
state.mark_archived(&event);
|
||||
assert!(state.archived_ids.is_empty());
|
||||
|
||||
let mut state = InboxReadState::default();
|
||||
state.mark_archived(&event);
|
||||
assert_eq!(state.archived_ids, HashSet::from([event.id]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn apply_state_recomputes_unread_and_archived() {
|
||||
let now = Timestamp::from_secs(1_000_000_000);
|
||||
let first = issue(&keys(2), now.as_secs() - 2000);
|
||||
let second = issue(&keys(2), now.as_secs() - 1000);
|
||||
let mut item = InboxItem {
|
||||
root: first.id,
|
||||
root_kind: None,
|
||||
address: None,
|
||||
events: vec![second.clone(), first.clone()],
|
||||
unread_ids: Vec::new(),
|
||||
archived: false,
|
||||
};
|
||||
|
||||
let state = InboxReadState {
|
||||
read_before: first.created_at,
|
||||
..Default::default()
|
||||
};
|
||||
item.apply_state(&state);
|
||||
|
||||
assert_eq!(item.unread_ids, vec![second.id]);
|
||||
assert!(!item.archived);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn serde_round_trip_preserves_state() {
|
||||
let first = issue(&keys(1), 100);
|
||||
|
||||
Reference in New Issue
Block a user