Initial commit

This commit is contained in:
weishaupt
2026-10-04 17:34:29 -04:00
commit 197214ae25
30 changed files with 2868 additions and 0 deletions
+125
View File
@@ -0,0 +1,125 @@
# 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
This project lives at `C:\wallpapers\wIRC`. Since you're picking this up
with Claude Code the same way as Cart & Dagger: it needs the Android SDK
command-line tools + Gradle, same setup you've already got at
`C:\Users\admin\AppData\Local\Android\Sdk`.
From PowerShell, in `C:\wallpapers\wIRC`:
```powershell
cd C:\wallpapers\wIRC
# One-time: point Gradle at your existing SDK install
$env:ANDROID_HOME = "C:\Users\admin\AppData\Local\Android\Sdk"
"sdk.dir=C:\\Users\\admin\\AppData\\Local\\Android\\Sdk" | 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 `C:\wallpapers\wIRC\app\build\outputs\apk\debug\app-debug.apk`.
From there, install it the same way you've been doing for Cart & Dagger —
`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.