M1 step 5: IRC App

- Chat: header (Buffer n/N, unread elsewhere, topic or connection
  state), wrapped hh:mm <nick> lines (own in accent, Mentions green,
  info grey), input line; Tab cycles Buffers, Fn+Up/Down scrolls back,
  Enter sends, Back leaves while the IRC Service keeps running
- /settings: server form (host, port, TLS, self-signed pinning, nick,
  SASL, NickServ, auto-join); Save & reconnect restarts the session
- Opening the App starts the IRC Service; viewing a Buffer clears its
  unread count; IrcSession gains a revision counter for redraws

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
This commit is contained in:
2026-10-02 15:14:59 +02:00
co-authored by Claude Opus 5.5
parent 74a341418e
commit 076baa77d1
8 changed files with 397 additions and 3 deletions
+17 -2
View File
@@ -50,11 +50,14 @@ int IrcService::totalUnread() {
std::string IrcService::saveConfig() {
std::string error = config_.save();
if (error.empty() && !wanted_) {
if (!error.empty()) return error;
if (wanted_) {
restart_ = true; // the task reconnects with a fresh session
} else {
Lock l(lock_);
session_.reset(new IrcSession(config_)); // a new server or nick starts a fresh session
}
return error;
return "";
}
void IrcService::taskEntry(void* self) { static_cast<IrcService*>(self)->loop(); }
@@ -178,6 +181,18 @@ void IrcService::loop() {
bool wifiUp = wifi_.state() == WifiController::State::Connected;
bool monitoring = wifi_.state() == WifiController::State::Monitoring;
if (restart_) {
restart_ = false;
if (open_) {
conn_->print("QUIT :reconfiguring\r\n");
vTaskDelay(pdMS_TO_TICKS(300));
close("");
}
Lock l(lock_);
session_.reset(new IrcSession(config_));
retryAtMs_ = now;
backoff_.reset();
}
if (!wanted_) {
if (open_) close("disconnected");
status_ = Status::Stopped;