per-channel message logs with shared ChannelLog type
Move ChannelLog to src/thalamus/channel_log.rs — shared by all channel daemon implementations. Each channel/PM gets its own log with consumed/unread tracking. IRC daemon: channels tracked via BTreeMap<String, ChannelLog>. list() returns all channels (joined + PMs) with per-channel unread counts. Sent messages stored in logs too. Co-Developed-By: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
8e66f0a66c
commit
e604659e3a
3 changed files with 102 additions and 65 deletions
76
src/thalamus/channel_log.rs
Normal file
76
src/thalamus/channel_log.rs
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
// channel_log.rs — Per-channel message history
|
||||
//
|
||||
// Shared by all channel daemon implementations. Tracks messages
|
||||
// with consumed/unread semantics for the recv protocol.
|
||||
|
||||
use std::collections::VecDeque;
|
||||
|
||||
const DEFAULT_CAPACITY: usize = 200;
|
||||
|
||||
/// Per-channel message history with consumed/unread tracking.
|
||||
pub struct ChannelLog {
|
||||
messages: VecDeque<String>,
|
||||
consumed: usize,
|
||||
total: usize,
|
||||
}
|
||||
|
||||
impl ChannelLog {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
messages: VecDeque::with_capacity(DEFAULT_CAPACITY),
|
||||
consumed: 0,
|
||||
total: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn push(&mut self, line: String) {
|
||||
if self.messages.len() >= DEFAULT_CAPACITY {
|
||||
self.messages.pop_front();
|
||||
if self.consumed > 0 {
|
||||
self.consumed -= 1;
|
||||
}
|
||||
}
|
||||
self.messages.push_back(line);
|
||||
self.total += 1;
|
||||
}
|
||||
|
||||
pub fn unread(&self) -> u32 {
|
||||
(self.total - self.consumed) as u32
|
||||
}
|
||||
|
||||
/// Return all unconsumed messages (marks consumed), plus scrollback
|
||||
/// to reach at least min_count total.
|
||||
pub fn recv_new(&mut self, min_count: usize) -> String {
|
||||
let buf_len = self.messages.len();
|
||||
let unconsumed_start = buf_len.saturating_sub(self.total - self.consumed);
|
||||
|
||||
let new_msgs: Vec<&str> = self.messages.iter()
|
||||
.skip(unconsumed_start)
|
||||
.map(|s| s.as_str())
|
||||
.collect();
|
||||
|
||||
let need_extra = min_count.saturating_sub(new_msgs.len());
|
||||
let scroll_start = unconsumed_start.saturating_sub(need_extra);
|
||||
let scrollback: Vec<&str> = self.messages.iter()
|
||||
.skip(scroll_start)
|
||||
.take(unconsumed_start - scroll_start)
|
||||
.map(|s| s.as_str())
|
||||
.collect();
|
||||
|
||||
self.consumed = self.total;
|
||||
|
||||
let mut result = scrollback;
|
||||
result.extend(new_msgs);
|
||||
result.join("\n")
|
||||
}
|
||||
|
||||
/// Return last N lines without consuming.
|
||||
pub fn recv_history(&self, count: usize) -> String {
|
||||
self.messages.iter()
|
||||
.rev().take(count)
|
||||
.collect::<Vec<_>>().into_iter().rev()
|
||||
.map(|s| s.as_str())
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n")
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue