Skip to content

feat: add dynamic channel management (/join, /part) - #8

Merged
KinseyD merged 3 commits into
mainfrom
feat/dynamic-channels
Sep 29, 2026
Merged

KinseyD merged 3 commits into
mainfrom
feat/dynamic-channels

Conversation

@KinseyD

@KinseyD KinseyD commented Sep 29, 2026

Copy link
Copy Markdown
Owner

Summary

Channels are no longer config-only. This PR adds runtime channel management — /join and /part — with per-channel server confirmation, while the channels config key becomes the startup join intent.

Commands

Command Behavior
/join #channel Join or focus a channel on the current registered server; a new JOIN waits for server confirmation.
/part [#channel] [reason] Leave the named channel, or the current channel when omitted; the buffer and its history are retained.

Both are online-only: the server must have completed registration. Channel names follow the configuration rule — a single # or & prefix with at least one character; whitespace, control characters, commas and colons are rejected. No channel keys or multi-target entries.

Behavior

  • Each JOIN and PART has its own 30-second confirmation timeout; the status dot reflects the result (blinking grey while unconfirmed, red when not joined or membership is uncertain after a timeout).
  • Runtime membership is memory-only: the config file is never rewritten and runtime changes disappear on exit.
  • Reconnection rejoins the current join intent once (including runtime /joins, excluding parted channels).
  • KICK keeps join intent without auto-retrying; an unsolicited own PART clears it.
  • Channel chat is gated on the confirmed JOIN; a prioritized PART prevents queued channel chat from leaking to the wire.
  • Raw console JOIN/PART lines go through the same managed state — they cannot bypass runtime intent and produce no console echoes.
  • Opening a configured channel's buffer does not join it by itself.
  • PART never deletes history: the buffer, draft and reading position survive.

Implementation

  • src/connection/channels.rs (new) — per-channel confirmation state machine in the worker; deadlines and errors scoped to the operation.
  • src/application/channels.rs + channel_tests.rs (new) — session join/part intent, buffer lifecycle and status queries.
  • src/command.rs — /join / /part parsing (reason preserved, invalid names rejected with the draft retained).
  • src/protocol.rs — structured channel errors (code, target, reason).
  • src/tui/render.rs — extended status-dot semantics.
  • src/config.rs — validate configured channel names at load time.
  • Drops the channel-lists feature from the irc dependency; channel state is now managed locally. No new dependencies.

Tests

  • New tests/dynamic_channels.rs: 16 integration tests over a mock IRC server on 127.0.0.1 — join waits for own confirmation, independent JOIN/PART deadlines, late confirmations, kick vs. unsolicited PART, reconnect intent, raw-command bypass prevention, offline rejection, and buffer/draft survival.
  • Existing suites updated where semantics changed.
  • Full suite: 329 passed / 0 failed on Windows; cargo fmt --check and cargo clippy --all-targets -- -D warnings clean.
  • Includes the follow-up fix restoring blocking mode on accepted mock sockets — on Windows an accepted socket inherits the listener's non-blocking mode, which made read_line return WouldBlock instead of honoring the read timeout.

Docs

  • README: new "Dynamic channels" section, command-table entries, config semantics for channels, and the extended status-dot legend.
  • config.example.toml: documents channels as startup join intent.

pengchanghao and others added 3 commits September 22, 2026 17:18
Accepted sockets inherit the listener's non-blocking mode on Windows,
so read_line returned WouldBlock instead of waiting for the read
timeout; all dynamic_channels integration tests panicked.
fix: restore blocking mode on accepted mock sockets on Windows
@KinseyD
KinseyD merged commit f81d96e into main Sep 29, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant