mirror of
https://github.com/block/buzz.git
synced 2026-11-03 16:01:35 +00:00
fix(desktop): populate last_message_at in channel browser (#951)
Signed-off-by: Will Pfleger <wpfleger@squareup.com> Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@sprout-oss.stage.blox.sqprod.co>
This commit is contained in:
@@ -156,6 +156,51 @@ pub async fn get_channels(state: State<'_, AppState>) -> Result<Vec<ChannelInfo>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Populate last_message_at by fetching the most recent human message per
|
||||||
|
// channel. Uses per-channel filters (single #h value each) so the relay can
|
||||||
|
// push the query to its indexed channel_id column. Multi-value #h is NOT
|
||||||
|
// SQL-pushed and would silently drop quieter channels under the global limit.
|
||||||
|
let channel_ids: Vec<String> = channels.iter().map(|c| c.id.clone()).collect();
|
||||||
|
if !channel_ids.is_empty() {
|
||||||
|
let filters: Vec<serde_json::Value> = channel_ids
|
||||||
|
.iter()
|
||||||
|
.map(|id| {
|
||||||
|
serde_json::json!({
|
||||||
|
"kinds": [9, 40002],
|
||||||
|
"#h": [id],
|
||||||
|
"limit": 1
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let message_events = query_relay(&state, &filters).await.unwrap_or_default();
|
||||||
|
|
||||||
|
let mut last_message_by_channel: std::collections::HashMap<String, u64> =
|
||||||
|
std::collections::HashMap::new();
|
||||||
|
for ev in &message_events {
|
||||||
|
if let Some(ch_id) = ev.tags.iter().find_map(|t| {
|
||||||
|
let s = t.as_slice();
|
||||||
|
(s.len() >= 2 && s[0] == "h").then(|| s[1].clone())
|
||||||
|
}) {
|
||||||
|
let ts = ev.created_at.as_secs();
|
||||||
|
last_message_by_channel
|
||||||
|
.entry(ch_id)
|
||||||
|
.and_modify(|existing| {
|
||||||
|
if ts > *existing {
|
||||||
|
*existing = ts;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.or_insert(ts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for channel in &mut channels {
|
||||||
|
if let Some(&ts) = last_message_by_channel.get(&channel.id) {
|
||||||
|
channel.last_message_at = Some(nostr_convert::timestamp_to_iso(ts));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NIP-DV: drop DMs the viewer has hidden. The relay maintains a per-viewer
|
// NIP-DV: drop DMs the viewer has hidden. The relay maintains a per-viewer
|
||||||
// parameterized-replaceable snapshot (kind:30622, d=my pubkey) whose `h`
|
// parameterized-replaceable snapshot (kind:30622, d=my pubkey) whose `h`
|
||||||
// tags list currently-hidden DM channel ids. The snapshot also carries
|
// tags list currently-hidden DM channel ids. The snapshot also carries
|
||||||
|
|||||||
@@ -533,7 +533,7 @@ pub fn relay_members_from_event(event: &Event) -> Value {
|
|||||||
// ── Time helpers ────────────────────────────────────────────────────────────
|
// ── Time helpers ────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
/// Convert a unix-seconds timestamp to a UTC RFC-3339 string.
|
/// Convert a unix-seconds timestamp to a UTC RFC-3339 string.
|
||||||
fn timestamp_to_iso(secs: u64) -> String {
|
pub(crate) fn timestamp_to_iso(secs: u64) -> String {
|
||||||
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||||||
let dt = UNIX_EPOCH + Duration::from_secs(secs);
|
let dt = UNIX_EPOCH + Duration::from_secs(secs);
|
||||||
// Format manually as RFC-3339 — the `time` crate is already a transitive
|
// Format manually as RFC-3339 — the `time` crate is already a transitive
|
||||||
|
|||||||
Reference in New Issue
Block a user