add trash panel and re-tag stale cached rooms
This commit is contained in:
+57
-10
@@ -397,6 +397,7 @@ impl ChatRegistry {
|
||||
|
||||
if !errors.is_empty() {
|
||||
let mut newly_trashed = 0;
|
||||
|
||||
trash.update(cx, |trash, cx| {
|
||||
newly_trashed = errors
|
||||
.iter()
|
||||
@@ -405,16 +406,9 @@ impl ChatRegistry {
|
||||
cx.notify();
|
||||
})?;
|
||||
|
||||
// Only newly trashed messages emit an error event so repeated
|
||||
// reprocess attempts of the same message don't re-alert the user
|
||||
if newly_trashed > 0 {
|
||||
let reason = if newly_trashed == 1 {
|
||||
"A message could not be decrypted".to_string()
|
||||
} else {
|
||||
format!("{newly_trashed} messages could not be decrypted")
|
||||
};
|
||||
this.update(cx, |_, cx| {
|
||||
cx.emit(ChatEvent::Error(reason));
|
||||
cx.emit(ChatEvent::Ping);
|
||||
})?;
|
||||
}
|
||||
}
|
||||
@@ -556,7 +550,7 @@ impl ChatRegistry {
|
||||
}
|
||||
|
||||
/// Retry unwrapping trashed gift wraps with the newly available encryption key.
|
||||
fn reprocess_trash(&mut self, cx: &mut Context<Self>) {
|
||||
pub fn reprocess_trash(&mut self, cx: &mut Context<Self>) {
|
||||
let nostr = NostrRegistry::global(cx);
|
||||
let client = nostr.read(cx).client();
|
||||
let signer = nostr.read(cx).signer();
|
||||
@@ -632,6 +626,32 @@ impl ChatRegistry {
|
||||
.count()
|
||||
}
|
||||
|
||||
/// How many messages are waiting in the trash.
|
||||
pub fn trashed_count(&self, cx: &App) -> usize {
|
||||
self.trash.read(cx).len()
|
||||
}
|
||||
|
||||
/// The messages that could not be decrypted, newest first.
|
||||
pub fn trashed(&self, cx: &App) -> Vec<TrashedMessage> {
|
||||
let mut messages: Vec<TrashedMessage> = self
|
||||
.trash
|
||||
.read(cx)
|
||||
.iter()
|
||||
.filter_map(|message| {
|
||||
let event = Event::from_json(message.raw_event.as_str()).ok()?;
|
||||
|
||||
Some(TrashedMessage {
|
||||
id: event.id,
|
||||
created_at: event.created_at,
|
||||
reason: message.reason.clone(),
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
|
||||
messages.sort_by_key(|message| std::cmp::Reverse(message.created_at));
|
||||
messages
|
||||
}
|
||||
|
||||
/// Get the relays that have seen a given rumor id.
|
||||
pub fn rumor_seen_on(&self, id: &EventId) -> Option<HashSet<RelayUrl>> {
|
||||
self.event_map
|
||||
@@ -854,8 +874,9 @@ impl ChatRegistry {
|
||||
.custom_tags(SingleLetterTag::LOWERCASE_K, ["7", "14", "15"]);
|
||||
|
||||
let events = client.database().query(filter).await?;
|
||||
let mut grouped: HashMap<u64, Vec<UnsignedEvent>> = HashMap::new();
|
||||
|
||||
let mut grouped: HashMap<u64, Vec<UnsignedEvent>> = HashMap::new();
|
||||
let mut stale: Vec<(EventId, UnsignedEvent)> = Vec::new();
|
||||
// Keep the single-threaded web event loop responsive during large rescans
|
||||
let mut last_yield = Instant::now();
|
||||
|
||||
@@ -869,15 +890,41 @@ impl ChatRegistry {
|
||||
&& rumor.tags.public_keys().next().is_some()
|
||||
{
|
||||
search.write().unwrap().insert(&rumor);
|
||||
|
||||
if rumor.pubkey != public_key
|
||||
&& !rumor.tags.public_keys().any(|k| k == public_key)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
let room_id = rumor.uniq_id().to_string();
|
||||
let stored_room = raw
|
||||
.tags
|
||||
.iter()
|
||||
.find(|tag| tag.kind() == "r")
|
||||
.and_then(|tag| tag.content());
|
||||
|
||||
if stored_room.is_none_or(|stored| stored != room_id)
|
||||
&& let Some(gift_wrap) = raw
|
||||
.tags
|
||||
.iter()
|
||||
.find(|tag| tag.kind() == "d")
|
||||
.and_then(|tag| tag.content())
|
||||
.and_then(|value| EventId::from_hex(value).ok())
|
||||
{
|
||||
stale.push((gift_wrap, rumor.clone()));
|
||||
}
|
||||
|
||||
grouped.entry(rumor.uniq_id()).or_default().push(rumor);
|
||||
}
|
||||
}
|
||||
|
||||
for (gift_wrap, rumor) in stale {
|
||||
if let Err(error) = set_rumor(&client, gift_wrap, &rumor).await {
|
||||
log::warn!("Failed to re-tag a cached message: {error:#}");
|
||||
}
|
||||
}
|
||||
|
||||
let mut rooms = HashSet::with_capacity(grouped.len());
|
||||
|
||||
for (_id, messages) in grouped.into_iter() {
|
||||
|
||||
@@ -219,6 +219,17 @@ impl FailedMessage {
|
||||
}
|
||||
}
|
||||
|
||||
/// A message that could not be decrypted, as surfaced to the UI.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TrashedMessage {
|
||||
/// The undecryptable gift wrap's id, stable across renders
|
||||
pub id: EventId,
|
||||
/// When the gift wrap was received
|
||||
pub created_at: Timestamp,
|
||||
/// Why it could not be decrypted
|
||||
pub reason: SharedString,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Mention {
|
||||
pub public_key: PublicKey,
|
||||
|
||||
Reference in New Issue
Block a user