fix(peer): serve full browse listings + harden the listener; TUI transfer/UX work
Peer layer: - Stream peer messages with a partial-write queue instead of write_all, so a large SharedFileListResponse over the non-blocking socket is no longer truncated (third-party clients like SoulseekQt can now browse our shares). - Bound the peer-init handshake with a read timeout and handle each accepted connection on its own thread, so one stalled peer can't wedge the listener. - e2e: third-party direct/brokered/large-share browse + stalled-peer coverage. TUI: - Uploads share the downloads table columns (real Speed) and the info pane now renders details for a selected upload. - Download progress bar counts only in-progress transfers and hides when idle. - Always-visible unread badge (private messages + rooms) in the shortcuts bar, self-drawn blink so it works under tmux. - Persist the unread private-message count across restarts.
This commit is contained in:
@@ -181,12 +181,20 @@ fn render_messages(
|
||||
let start = lines.len().saturating_sub(height.max(1));
|
||||
let rendered: Vec<Line> = lines[start..]
|
||||
.iter()
|
||||
.map(|l| match &l.username {
|
||||
Some(user) => Line::from(vec![
|
||||
Span::styled(format!("<{user}> "), info_style()),
|
||||
Span::styled(l.text.clone(), primary_style()),
|
||||
]),
|
||||
None => Line::from(Span::styled(l.text.clone(), dimmed_style())),
|
||||
.map(|l| {
|
||||
let time =
|
||||
Span::styled(l.at.format("%H:%M ").to_string(), dimmed_style());
|
||||
match &l.username {
|
||||
Some(user) => Line::from(vec![
|
||||
time,
|
||||
Span::styled(format!("<{user}> "), info_style()),
|
||||
Span::styled(l.text.clone(), primary_style()),
|
||||
]),
|
||||
None => Line::from(vec![
|
||||
time,
|
||||
Span::styled(l.text.clone(), dimmed_style()),
|
||||
]),
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
frame.render_widget(Paragraph::new(rendered), area);
|
||||
|
||||
Reference in New Issue
Block a user