Commit Graph
11 Commits
Author SHA1 Message Date
SalastilandClaude Sonnet 5.5 48fb1a97f3 Telegram: Settings page, poll composer, ARCHITECTURE entry; nobilis pointer
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-16 00:23:50 -04:00
SalastilandClaude Sonnet 5.5 a6fd981b6f Twitch: no third-party emote services; channel emotes greyed in the picker
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-14 19:52:54 -04:00
SalastilandClaude Sonnet 5.5 9ef8a67ac4 Every service notification is drawn as a card; the rule is in ARCHITECTURE.md
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-14 15:11:23 -04:00
SalastilandClaude Sonnet 5.5 d99ad2ba68 Documentation brought up to date: the settings pages, how a conversation opens, presence and the tray, link cards and Kick events, Discord mutes set on the account, the tests and the tidy step, and the daemon described as it is rather than as it was meant to be
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-11 00:30:08 -04:00
SalastilandClaude Opus 5.5 26f84b475b Not-connected conversations in italics, with a spinner and a banner
A conversation whose account is not connected, or whose own link is
down, is drawn in italics in the channel list - with a spinner while
something is retrying, a broken-link mark when nothing is - and opening
it shows a Service interruption banner saying why: the account's own
progress, an IRC refusal, or Sneedchat's diagnosis of Tor, the forum or
the chat.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-02 17:39:42 -04:00
SalastilandClaude Opus 5.5 ae8947a9b4 Settings: storage, cleared by group; missing pictures fetched again
General gains a Storage section: chat history, pictures and video,
avatars and server icons, emotes/stickers/sounds, and the web cache,
each with its size and a Clear button, history asked about inline first.
Chromium's HTTP cache, found at 1.2 GB, is capped at 256 MB.

A cached picture that fails to load is handed to the daemon to fetch
again (restoreMedia), held back from its own error handler until the
answer, and let through to fail as before if it cannot come back. Rows
carry their buffer so a Discord thumbnail can be found from its message.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-02 13:54:52 -04:00
SalastilandClaude Opus 5.5 9e67ca6bfb Pick up the cache caps; every media cache is swept now #243
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-02 12:37:16 -04:00
SalastilandClaude Opus 5.5 8d0eb09702 README and ARCHITECTURE: the client as it is now
Discord calls, streams and the no-captcha decision; Kick's player; Matrix
cross-signing and forwarding; Sneedchat on the open internet; the right
socket and cache paths; XMPP and Slack out. #238

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-02 00:14:13 -04:00
SalastilandClaude Opus 5 f965642a55 A camera that can be turned on in a call already running
The missing half of #189. A call placed as a video call already opened a
camera; a call placed as a voice call could never grow one, and the
button was hidden unless the call was on a media server - so on the two
shapes of Matrix call that do not use one, there was no camera at all.

Added and removed rather than enabled and disabled. A disabled track
keeps sending - a black rectangle at whatever frame rate the encoder
feels like - so the far end sees a dark square where a face was and
cannot tell that from a camera that has frozen. Removing the track ends
it properly, and every other client then draws the person's name. The
loopback harness below measures exactly this difference: with the old
enabled=false the far end still counts one live video track after the
camera is switched off, and with the track removed it counts none.

One gesture for all three shapes of call - a media server, a mesh
between several people, a single connection between two - because the
button is one button and the person pressing it is asking one thing.
Which shape this is belongs to the call, not to the control. On a mesh
the camera is still opened once and lent to every leg, since five
connections asking the machine for the same camera get one capture and
four refusals.

Renegotiations are now serialised. Turning a camera on and sharing a
screen a second later are two changes to one connection, and starting
the second offer while the first is unanswered leaves a peer connection
neither end can recover from. A remote track that is taken away is
dropped from the stream it arrived on, so a tile stops drawing the last
frame it received - Chromium reports that as a mute before it reports it
as an end, and on a removed track the mute is often all there is.

cameraOn is asked of the call rather than assumed, in both branches:
that block runs on every phase change, and a fixed answer put the button
back to "off" the moment a call connected.

The call UI is unchanged in shape and deliberately not Matrix-shaped -
Discord's camera (#180) and screen share (#14) get the same row of
buttons when they arrive.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-13 18:35:29 -04:00
SalastilandClaude Opus 5 d06770972b Say that the client does not execute code, and will not
Scripting came up as the one place moho falls short of the clients it is
measured against - HexChat has Perl and Python, WeeChat four languages,
mIRC its own - and the answer is that it is a decision rather than a gap.

Written into the security notes rather than anywhere else, because it is
the same decision as the rest of that section. The fixed preload surface,
the tag and attribute whitelist and the media scheme all exist to stop
attacker-controlled message content from becoming something that runs. A
plugin API hands that back in one step, and with more privilege than the
renderer has.

Recorded so the next feature comparison reads it as answered instead of
filing it, and so somebody asking for it gets the reasoning rather than a
maybe.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-11 23:04:21 -04:00
SalastilandClaude Opus 5 c0ff53e833 A front page that reads like an invitation
The README opened with "a unified desktop chat client" and a paragraph about
the UI only ever seeing a service-agnostic account/buffer/message model. That
is a true and useful sentence to a maintainer and the wrong first sentence for
somebody deciding whether to download this: 223 lines in, the wire protocol
and the on-disk layout came before anything about what it is like to use.

So the README is now a page: what moho is, what it does, where to get it, and
the four commands to build and run it. Everything else moved to
ARCHITECTURE.md rather than being deleted - the daemon split, the JSON-RPC
surface, what each backend actually implements, where state lives - because
none of it was wrong, it was only in the wrong place.

Three of the old build instructions were wrong, which is the other reason to
rewrite rather than trim. `npm run pack:appimage` is not a script. There is no
pacman target, so `pacman -U dist/moho-0.1.0.pacman` installs nothing; the
PKGBUILD is the Arch path. And builds have been named after their commit since
the AppImages started accumulating, so `moho-0.1.0.AppImage` is a filename
that no longer occurs. Every command the new page names is checked against
package.json.

The prerequisites are named now, too: cmake, pkg-config and the ALSA headers.
Nobody knew to write those down until CI met a machine that did not already
have them.

Carried forward with a correction: the IRC section claimed twelve
capabilities. It negotiates twenty-four, four of them drafts, plus WHOX - the
ticket work landed after that paragraph was last touched.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-11 21:14:52 -04:00