feat: unread indicator (*) for rooms with new messages

Rooms that receive a message while not active show a * prefix in the
sidebar. The marker clears when you tab to that room.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Fredrik Johansson
2026-06-26 22:30:10 +02:00
parent 340735f992
commit 95fd29ae8d

View File

@@ -107,6 +107,7 @@ type model struct {
rooms []string // "general" always first; DM rooms appended
activeRoom int
messages map[string][]entry
unread map[string]bool // rooms with messages since last viewed
peers map[proto.PeerID]string // connected peers: id → alias
peerOrder []proto.PeerID
@@ -131,6 +132,7 @@ func newModel(ipcPort int, network string) model {
networkName: network,
rooms: []string{"general"},
messages: make(map[string][]entry),
unread: make(map[string]bool),
peers: make(map[proto.PeerID]string),
input: ti,
status: "connecting…",
@@ -215,9 +217,11 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m, cmds = m.doSend(cmds)
case msg.Type == tea.KeyTab:
m.activeRoom = (m.activeRoom + 1) % len(m.rooms)
delete(m.unread, m.activeRoomName())
m = m.refreshViewport()
case msg.Type == tea.KeyShiftTab:
m.activeRoom = (m.activeRoom - 1 + len(m.rooms)) % len(m.rooms)
delete(m.unread, m.activeRoomName())
m = m.refreshViewport()
default:
var tiCmd tea.Cmd
@@ -303,6 +307,9 @@ func (m model) applyEvent(evt proto.IpcMessage) model {
}
m.messages[msg.Room] = append(m.messages[msg.Room], e)
m = m.addRoom(msg.Room)
if msg.Room != m.activeRoomName() {
m.unread[msg.Room] = true
}
m = m.refreshViewport()
}
}
@@ -483,7 +490,11 @@ func (m model) renderRooms(boxH int) string {
if i == m.activeRoom {
lines = append(lines, styleActive.Width(innerW).Render("▶ "+label))
} else {
lines = append(lines, styleRoom.Width(innerW).Render(" "+label))
prefix := " "
if m.unread[room] {
prefix = "* "
}
lines = append(lines, styleRoom.Width(innerW).Render(prefix+label))
}
}
for len(lines) < contentH {