The status bar had colour tags turned on, so tview read "[connected]"
and "[disconnected]" as tags and dropped them. It dropped all or part
of a nick, a target or a window name holding square brackets the same
way.
The status bar now has colour tags turned off. It wrote none of its
own, so every bracket shows as it is. TestStartUp checks that the
status bar shows [disconnected] at start-up. TestStatusBar checks
[connected], and checks nicks and a /query target that hold brackets.
Model: opus-5-5
Run added the start-up status bar and welcome lines through
SetStatus and AddStatus before it started the tview event loop. Both
wait for that loop, so neoirc-cli stopped before it showed its
screen. They now run on a goroutine, as typed lines do.
Run now passes a new UI to run, which holds the start-up path and
returns its error. TestStartUp calls run with a simulation screen. It
fails unless, within five seconds, the status window holds two lines:
first the one with "Welcome to neoirc-cli", then the /connect hint.
Model: opus-5-5
The Enter handler of the input line and the Alt and digit key handler
ran the typed line on the tview event loop. Every UI method that
changes the screen waits for that loop, so the client stopped
responding. Each line now runs on its own goroutine, which first waits
for the line before it, so lines keep the order they were typed in.
/window now runs off the event loop. It reads the buffer name through
the new BufferName, which runs on the loop, and switches only when
that buffer exists.
One new test drives a running UI on a simulation screen with Alt and
1, then a typed line and Enter. Another holds the first line and
checks that the second waits for it.
Model: opus-5-5
In neoirc-cli, Alt and a digit switched the window but kept the send
target, so typed text went to the window the user had left. The key
now runs /window with that digit through the input handler.
/window 0 now clears the send target. The status window has no target,
but the command used to keep the previous one.
Model: opus-5-5
When the server refuses a JOIN, POST /api/v1/messages answers 200
with status "error" and sends the error numeric to the queue. Both
clients opened the channel anyway.
JoinChannel in internal/cli/api now returns an error unless the
status is "joined". cmdJoin then keeps its buffer and target and
prints its usual "Join failed" line. The web client opens no tab for
a refused join, whether it came from /join or from the saved
channels a fresh session joins again.
Model: opus-5-5
neoirc-cli wrote its own line when it sent a message, joined or parted,
and ignored the server's event for its own nick, except a JOIN, so a
join showed twice and what the session did from another client never
showed. The HTTP API queues these events to every client of the
session, so the CLI now writes no line of its own when it sends and
shows the event as it shows anyone else's. A direct message the user
sent goes in the recipient's buffer. The user's own part does not mark
the channel unread, as the user has just left it.
Model: opus-5-5
The IRC listener's relay dropped every line sent under the connection's own nick, so a user on the web client and an IRC client at once never saw on IRC what they did from the web client. The relay now drops nothing by nick. Instead the fan-out skips only the sending client's own queue: the IRC listener passes its own client, whose handler already wrote the echo, and the HTTP API skips none. Channel messages and PARTs now reach the sender's other clients, so an HTTP client gets its own PART event; neoirc-cli ignores it, as it already shows its own part. README.md names the commands covered.
Judgement call: a PRIVMSG or NOTICE sent on an IRC connection is not echoed back to it, as in IRC.
Model: opus-5-5
The CLI read the poll cursor from `lastId` while the server sends
`last_id`, so the cursor stayed at 0 and every poll returned the
whole queue at once. It now reads `last_id`.
/names decodes the member objects the server sends and prints each
nick with `@` for an operator or `+` for a voiced member. /list
prints each channel's name and topic, since the server sends no
member count. StateResponse.Channels decodes channel objects.
/topic with no text prints a usage line and sends nothing, because
the HTTP API has no topic query and a TOPIC without text gets 461.
The help says "Set topic".
The client tests serve the bodies the handlers send, so a wrong JSON
tag in types.go fails a test; another test covers the /names prefixes.
Model: opus-5-5