Expand description
heatsync-core — the brain. protocol types, heat ramp, emote resolution, ws parsing, mock feed, and the editing model. no terminal, no async, no i/o (clocks and keystrokes are passed in). every client is a thin face over this.
The editing half (key, edit, vi, slash, clip) lived in the tui
until a second face needed it. None of it ever touched the terminal except
for crossterm’s key type, which key now replaces — a face maps its own
keystrokes into key::KeyEvent and gets the same editor.
Modules§
- clip
- yank target. tries the system clipboard first, then falls back to OSC 52 so a yank still lands over ssh, where there is no local clipboard daemon to talk to. returns a short label naming which path worked, for the status line.
- edit
- a vi line editor for the composer. insert and normal sub-modes, motions, operators, registers and history — the same muscle memory as everywhere else, rather than a handful of emacs control chords.
- emote
- emote resolution. mirrors the server: /api/channel/:c/emotes returns a
precedence-ordered (7tv > bttv > ffz > twitch > kick) deduped list, so we
insert first-wins into a name→emote map and word-match message text against
it. modifiers (BTTV
w!-style prefixes / FFZffzX-style effect words) are parsed here into per-stackEffectlists; the pixel work happens at render. - heat
- the heat ramp — one decaying scalar → a stepped temperature color. mirrors client/config/colors.js (the ONE source of truth). terminal-native: we return the xterm-256 index, not css. the tui maps that to a cell color.
- key
- Face-independent key events.
- mock
- deterministic mock feed — proves the aesthetic before the relay WS exists. no rand crate, no real clock: a seeded xorshift + a synthetic ms clock advanced each tick. heat emerges from the same decaying-counter model the live feed uses, so the mock and the real thing behave identically.
- proto
- HeatSync
/wsrelay protocol — parse inbound frames, build outbound ones. anon read is allowed, so no auth is required to consume chat. content and usernames are sanitized HERE, at the trust boundary, before anything else touches them (terminal-injection defense). - sanitize
- terminal-injection defense. chat text is UNTRUSTED — a raw escape sequence in a message could retitle the terminal, poke the clipboard, or worse on some emulators. we render into a terminal, so we strip every control byte before a message is ever handed to the tui. this is the one risk chatterino never has.
- slash
- slash commands typed in the composer, the way every chat client does it.
- vi
- vi navigation over the chat ring: a cursor, a linewise visual selection, counts, and search. no rendering and no I/O — main.rs owns the keymap and the drawing, this owns the model, which is what makes the motions testable.
Structs§
- Channel
- live state for a single channel. bounded ring buffer — a raid can flood
forever and we never grow past
cap(mele is 8GB; resource-conscious). heat is a decaying counter driven by message arrivals. - Message
- one chat line.
heatis the channel’s heat snapshotted at arrival, so a message sent during a spike stays warm in scrollback.coloris the user’s chat color (hex) if the platform sent one.
Enums§
- Platform
- where a channel’s chat comes from.