This commit is contained in:
2026-09-22 20:15:15 +07:00
parent 1c5ef58049
commit 706cc72c1f
14 changed files with 1021 additions and 104 deletions
+33 -41
View File
@@ -1,4 +1,4 @@
use std::collections::{HashMap, HashSet};
use std::collections::HashMap;
use std::fmt;
use anyhow::Result;
@@ -502,32 +502,7 @@ impl CommunityPanel {
return;
}
let mut index: HashMap<EventId, usize> = self
.rows
.iter()
.enumerate()
.map(|(ix, message)| (message.id, ix))
.collect();
let mut added = Vec::new();
for message in messages {
match index.get(&message.id).copied() {
Some(ix) => self.rows[ix] = message,
None => {
index.insert(message.id, self.rows.len() + added.len());
added.push(message);
}
}
}
if !added.is_empty() {
let at = self.item_count();
let count = added.len();
self.rows.extend(added);
self.list_state.splice(at..at, count);
}
self.merge(messages);
cx.notify();
}
@@ -537,22 +512,42 @@ impl CommunityPanel {
return;
}
let known: HashSet<EventId> = self.rows.iter().map(|message| message.id).collect();
let added: Vec<ChatMessage> = timeline
.messages
.into_iter()
.filter(|message| !known.contains(&message.id))
self.has_more = timeline.has_more;
self.merge(timeline.messages);
cx.notify();
}
/// Fold read rows into what is on screen, keeping the list in time order.
fn merge(&mut self, messages: Vec<ChatMessage>) {
let mut shown: HashMap<EventId, usize> = self
.rows
.iter()
.enumerate()
.map(|(ix, message)| (message.id, ix))
.collect();
self.has_more = timeline.has_more;
let mut fresh = Vec::new();
if !added.is_empty() {
let count = added.len();
self.rows.splice(0..0, added);
self.list_state.splice(1..1, count);
for message in messages {
match shown.get(&message.id).copied() {
Some(ix) => self.rows[ix] = message,
None => fresh.push(message),
}
}
cx.notify();
for message in fresh {
if shown.contains_key(&message.id) {
continue;
}
let at = self
.rows
.partition_point(|row| (row.at_ms, row.id) <= (message.at_ms, message.id));
shown.insert(message.id, at);
self.rows.insert(at, message);
self.list_state.splice(at + 1..at + 1, 1);
}
}
fn send(&mut self, window: &mut Window, cx: &mut Context<Self>) {
@@ -567,9 +562,6 @@ impl CommunityPanel {
return;
};
// A rotation that excluded us moved the write plane out of reach, and the
// community refuses to seal a message nobody could read. The notice above
// the list is what says why.
if let Some(notice) = self.notice(cx).filter(|notice| !notice.writable()) {
window.push_notification(Notification::error(notice.to_string()).autohide(false), cx);
return;