Files
wIRC-android/README.md
T
2026-10-04 17:38:11 -04:00

6.4 KiB

wIRC

A native Android IRC client: mIRC colors, timestamps, OP powers (kick/ban/op), Ctrl+K/B/I formatting shortcuts, saved servers with on-connect identify commands, and every channel and private message opening as its own independently-styled window (1px black border, adjustable background transparency, black/white text toggle).

What's built so far (MVP)

  • Raw socket IRC connection (irc/IrcConnection.kt) with auto-reconnect/backoff, optional TLS, auto-join on connect.
  • Full mIRC control-code parser (irc/MircColorParser.kt) — colors, bold, underline, reverse, reset — rendered as a Compose AnnotatedString.
  • Protocol line parser (irc/IrcLineParser.kt) for PRIVMSG/JOIN/PART/KICK/MODE/ TOPIC/NOTICE/QUIT/NAMES.
  • ConnectionManager — app-wide singleton so every open window reads from the same shared state (messages, user list) regardless of which window is active.
  • IrcConnectionService — foreground service that keeps the socket(s) alive when the app is backgrounded (Android kills background network connections aggressively without this).
  • ChannelScreen — the actual window UI: scrollback with mIRC colors + per-line timestamps, input bar, long-press a nick for a Kick/Ban/Op/De-op menu, and a settings panel (gear icon) with the transparency slider and text color toggle.
  • ChannelWindowActivity — one instance per channel. Uses documentLaunchMode="always" + resizeableActivity="true" in the manifest and FLAG_ACTIVITY_NEW_DOCUMENT on launch, which is the standard way an app can offer real independent, draggable/resizable OS-level windows on devices that support freeform multi-window (large tablets, Samsung DeX, etc).
  • MainActivity / MainScreen — the main window. Lists saved servers as cards (Connect / Edit / Delete), and per-connected-server a box to join + open a channel window. "+ Add Server" opens ServerEditDialog with host, port, TLS, nick, auto-join channels, and a multi-line "on-connect / identify commands" field — e.g. PRIVMSG NickServ :IDENTIFY hunter2 — sent automatically right after registration on every connect, before auto-join.
  • ServerRepository — persists the saved server list (including on-connect commands) to servers.json in app-private storage, so it survives app restarts. This is the "file that saves that information" you asked for.
  • Private messages: ConnectionManager now keys PMs by the other person's nick (not our own), and emits a newQueryBuffers event the first time a PM from someone new arrives. IrcConnectionService listens for that and auto-launches a ChannelWindowActivity for it — so a PM pops its own window the same way tapping a channel does, no different from every other window in the app.
  • Ctrl+K / Ctrl+B / Ctrl+I: hardware-keyboard shortcuts wired into the input field in ChannelScreen.kt. Ctrl+B/I insert the raw bold (\u0002) / italic (\u001D) toggle control chars at the cursor. Ctrl+K opens a 16-swatch mIRC color picker dialog (foreground, then optional background) and inserts the real \u0003FG,BG wire code — same bytes mIRC/HexChat send.

Known limitations / what's still rough

  • "Minimize" isn't an app feature — on devices with freeform multi-window (large tablets, Samsung DeX, etc.) the OS itself draws minimize/maximize/ close chrome around any resizeableActivity="true" window. Both MainActivity and ChannelWindowActivity are marked resizable so they get that treatment automatically; there's no button to build on the app side.
  • No SASL handshake yet — ServerConfig has saslUser/saslPass fields but IrcConnection only sends CAP REQ :sasl and stops there. The "on-connect commands" field is the current way to identify (it just sends a plain PRIVMSG NickServ :IDENTIFY ... after registration, which works fine on Rizon/most networks even without real SASL).
  • Multi-window is best-effort, same as before — genuinely dependent on device/OEM support for freeform windowing. This is a platform limitation, not something the app can force.
  • No notifications for mentions when a window isn't focused yet.
  • Channel list per server isn't persisted — only the server configs (including identify commands) are saved; which channels you had open resets each app restart. Worth adding to ServerRepository next if it bugs you.

Building — Claude Code / PowerShell, no Android Studio

It needs the Android SDK command-line tools + Gradle.

From PowerShell, in the project directory:

# One-time: point Gradle at your existing SDK install
$env:ANDROID_HOME = "<path-to-Android-Sdk>"
"sdk.dir=<path-to-Android-Sdk, backslashes doubled>" | Out-File -Encoding ascii local.properties

# Generate the Gradle wrapper jar (not shipped in this zip — it's a binary)
# Requires a local Gradle install once, just to bootstrap the wrapper:
gradle wrapper --gradle-version 8.9

# Build
.\gradlew.bat assembleDebug

The debug APK lands at app\build\outputs\apk\debug\app-debug.apk. From there, install it with adb install, or transfer it over your own hosting and install directly on the tablet/phone.

If Claude Code hits a missing gradle command for that one-time wrapper bootstrap, the SDK's cmdline-tools don't include Gradle itself — grab it separately (choco install gradle if you use Chocolatey, or download the binary distribution and add it to PATH) just for that first gradle wrapper call; every build after that uses .\gradlew.bat and doesn't need a system Gradle install anymore.

Transferring to tablet/phone

Once you've got an APK (built on the laptop in Android Studio, or later directly on-device via Claude Code in Termux/proot once that's sorted out):

  • Simplest: adb install app-debug.apk if the device is plugged in / on the same network with ADB over Wi-Fi enabled.
  • Or just copy the APK over via your own file transfer (your hosting, a shared folder, whatever you'd normally use) and install it directly on the device — you'll need "install unknown apps" allowed for whichever app you use to open the APK file.

Suggested next steps

  1. Wire up persistence for server/channel lists (Room or DataStore) so MainActivity remembers your setup between launches.
  2. Finish SASL PLAIN auth in IrcConnection.
  3. Add a notification path for mentions when a channel window isn't focused.
  4. Decide on nick auto-complete / tab-complete in the input bar.