Commit Graph
9 Commits
Author SHA1 Message Date
SalastilandClaude Sonnet 5 20389e7396 Add Matrix verification/backup, per-protocol join pages, Discord friends, and expired-media/auth-failure recovery
- Matrix: interactive device verification (SAS emoji flow), recovery-key
  backup/restore, membership announcement moderation, member/room avatars,
  power-level-aware moderation menu, and an encryption lock indicator on
  the composer - verified live with two independent devices.
- Replace the single combined join panel with a dedicated page per
  protocol (IrcJoinPanel/MatrixJoinPanel/DiscordJoinPanel), routed by
  whichever account the "+" button was clicked for rather than listing
  every account in one expandable page.
- Discord: friends list (Online/All, click-to-DM, add-friend, matches
  READY's relationships + live PRESENCE_UPDATE), create-a-server, and
  join-by-invite alongside the existing DM-by-ID flow.
- Discord: an expired attachment-link fallback ("Open in Discord") for
  scrollback media whose signed cdn.discordapp.com URL has lapsed -
  Discord's own /attachments/refresh-urls re-sign endpoint hard-rejects
  this backend's user-token requests, confirmed live, so this opens the
  real message instead of showing a broken embed.
- Discord: detect gateway close code 4004 (revoked token) as a distinct
  ConnState::AuthFailed instead of retrying a dead credential forever;
  the Accounts pane shows a clear "needs login" state that routes
  straight to a fresh QR login, which upserts the same account id in
  place (no lost buffers/scrollback).
- Fix the unread-DM pinned-buffer flash never reliably triggering: an
  implicit property binding computed via nested closures over two
  separate properties wasn't consistently re-evaluated by QML's
  dependency tracker; replaced with an explicit recompute function called
  at every actual mutation point.
- Fix ChatBarWidget.qml's pill double-padding against BasePill's own
  padding.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-21 12:30:46 -04:00
SalastilandClaude Sonnet 5 0ad9b7b719 Add Matrix backend with full end-to-end encryption
- New chatd-rs backend/matrix module: m.login.password auth, /sync-based
  multi-room connect loop, and full E2EE via matrix-sdk-crypto (device key
  upload, Megolm session establishment, encrypt/decrypt) - verified live
  against real homeservers with two independent devices exchanging an
  encrypted message neither one decrypted itself.
- Reactions, edits, redactions, replies, and media upload/download, mapped
  onto the existing Reaction/Embed/ReplyPreview model.
- Frontend wiring: MatrixConnectForm.qml, AccountsPanel/ChatView hookup,
  and the real addMatrixAccount RPC handler (replacing the stub).
- Fix messages doubling in the UI: the Matrix backend never called
  Runtime::set_own_identity, so every message - including the account's
  own - was stored with is_own=false, defeating the frontend's optimistic-
  send reconciliation.
- Fix accounts getting stuck showing "connecting" forever: the Connected
  state transition was gated on this being the account's very first-ever
  sync (next_batch.is_none()), which is never true again once a cursor is
  persisted across a restart - a real account could sync successfully
  forever and never have its state announced as connected.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-12 22:57:54 -04:00
SalastilandClaude Sonnet 5 73ff641e6a Bundle Sneedchat smilies client-side; add Discord reactions and reaction/reply UI polish
- Bundle Sneedchat's 175 site smilies as local assets instead of fetching
  live over Tor; render them full-size in the chat buffer and emoji picker,
  with animated (gif/webp) smilies looping via a separate AnimatedImage row
  since Qt rich-text <img> can only render a static first frame.
- Add Discord message reactions: toggleReaction RPC, per-message reaction
  pills sized to match Discord's own client, a shared reaction/emoji-picker
  popup anchored and edge-clamped to the message row, and a row-wide hover
  toolbar (reactions/reply/more) gated to Discord only.
- Extend the row hover highlight to every protocol, not just Discord, since
  it's generic UX polish with nothing protocol-specific about it.
- Restyle the message context menu with per-item icons and Discord-style
  colored entries (e.g. red Delete), using anchored icon+text layout instead
  of RowLayout/MenuItem auto-sizing for reliable alignment across items.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-12 18:41:39 -04:00
SalastilandClaude Sonnet 5 71b1419b37 Switch Sneedchat attachment uploads from qu.ax to postimg.cc
qu.ax stopped reliably serving uploaded images back out. postimg.cc has
no documented API, so its anonymous upload flow was reverse-engineered
from a real browser session (HAR capture): the upload POST 403s as
"automated" without Origin/Referer headers, and the response only
returns the result page URL, not a direct image link, so the page is
fetched and scraped for the real (server-normalized) filename.

- http.rs: thread optional extra headers through the request path, add
  post_multipart for a multi-field body (postimg.cc needs gallery/
  optsize/expire/numfiles/upload_session alongside the file - the old
  post_multipart_file only ever sent a bare file)
- mod.rs: new postimg.cc upload/scrape implementation, wraps as
  [url=page][img]direct[/img][/url] matching its own "Thumbnail for
  forums" BBCode preset; images only (png/jpg/gif/webp/bmp), since
  postimg.cc doesn't host video the way qu.ax did
- form.rs: expose attr() for reuse when scraping the result page
- Fixed a live bug where the result page's outer wrapper div repeats
  data-image= without the filename attributes, before the real one

Live-verified end-to-end in #fishtank (test messages since deleted).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-12 15:23:17 -04:00
SalastilandClaude Sonnet 5 eeed38da6e Sneedchat reconnect/attachments, optimistic sends, scroll/video fixes, plugin status indicator
- Sneedchat: detect a reconnect that silently lands as a guest (server's
  own can_send permission flag) and force a session refresh + relogin;
  add an idle-read timeout so a dead websocket is actually noticed
- Sneedchat: multipart file upload support in http.rs, wired into
  sendMessage's attachment path (qu.ax-hosted images/video)
- Discord-style optimistic message sends: dim pending messages, resolve
  to the real server echo, turn red and offer Retry on failure/timeout
- MessageList: fix scroll-to-end/New-divider landing, anchored-scroll
  reliability during scrollbar drags, and BBCode [img][/img] tags
  merging into one URL when posted back-to-back
- MediaEmbed: real audio output device, working scrub-bar seek/pan,
  restart-from-start on a finished video
- DaemonStatusSettings: chatd connection indicator + build (git branch)
  badge for DMS's plugin manager pane
- BufferList: scope the "+" join-channel affordance to IRC accounts only
- DisplaySettingsPanel: new toggle for content-sniffing unrecognized
  media links

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-12 14:58:35 -04:00
SalastilandClaude Sonnet 5 9ea5f85b69 Persist UI state, fix Sneedchat media embedding, fix a send race
- Persist the last-viewed channel and collapsed sidebar groups (accounts,
  Discord guilds/DMs, pinned) across closing and reopening the chat
  window, which recreates these views from scratch rather than just
  hiding them.
- Add one line of breathing room between the last message and the
  composer bar.
- Fix BBCode-wrapped image links (Sneedchat's own "[url=X][img]X[/img]
  [/url]" convention) not embedding: the wrapper wasn't being collapsed
  before extraction, so the bare-URL scan swallowed the trailing [/url]
  into the "URL" and broke the extension check. Also harden that scan
  against any other bracket-adjacent markup, and recognize known
  extensionless image hosts (e.g. ShareX-style upload hosts).
- Resolve Kiwi Farms attachment links (which encode their extension in
  the slug, not as a real URL suffix) by fetching them through the
  account's Tor transport - using the onion address specifically, since
  kiwifarms.st's clearnet edge is both unstable and tends to mishandle
  Tor exit traffic - caching to /tmp, and patching the message body with
  the local path once ready. Required teaching the frontend's URL
  detection about file:// links and giving message-body rewrites a way
  to update in place without showing a spurious "(edited)" label.
- Fix Sneedchat messages failing to send (while still receiving fine) on
  a room whose connection had recently been re-established: the old
  connection's delayed cleanup could remove a newer, live sender for the
  same room out from under it. Sender removal now checks it's still the
  same channel before removing it.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-10 00:44:17 -04:00
SalastilandClaude Sonnet 5 7f3a1d36cd Restructure QML into views/settings/forms, add popout IPC command
- Move the ~17 top-level QML files into views/, settings/, and forms/
  subdirectories, grouped so cross-directory type references stay minimal
  (only 3 files need an added `import` line). Root now only holds the
  four surfaces plugin.json points at directly.
- Add a `dms ipc call dankChat popout` IPC target to open the floating
  window directly, alongside the existing `toggle`, and document both in
  the README along with the new directory layout.
- Add one line of breathing room between the last message and the
  composer bar via the message ListView's bottomMargin (measured with
  FontMetrics rather than a guessed pixel value).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-09 23:41:07 -04:00
SalastilandClaude Sonnet 5 b0158c3985 Sneedchat BBCode rendering, memory safeguards, and Tor settings overhaul
- Render Sneedchat's BBCode (bold/italic/underline/strike/color/quote/
  spoiler/code/img/video/list) into the same conventions MessageList's
  formatter already understands, and fix multi-line messages collapsing
  onto one line under Text.StyledText (raw \n isn't a line break there).
- Bound unbounded memory growth: periodic avatar-cache eviction by size,
  periodic scrollback pruning + incremental vacuum, and a per-buffer
  in-memory message cap in the frontend.
- Add a Sneedchat settings panel with per-channel enable/disable toggles.
- Make Tor its own settings category instead of a Sneedchat subsection,
  since there's a single daemon-wide embedded Tor client, not one per
  account. TorManager is now resettable (RwLock instead of OnceCell),
  with "regenerate circuit" (fast, reuses cached consensus) and "restart
  from scratch" (wipes cache, cold bootstrap) actions.
- Add a per-IRC-account "tunnel through Tor" toggle, off by default,
  routing through an external SOCKS5 proxy via the irc crate's native
  proxy support (the embedded Arti client has no public hook the irc
  crate can use directly, so this needs a real Tor daemon/Tor Browser).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-09 23:11:58 -04:00
SalastilandClaude Sonnet 5 12008621ee Initial commit: Dank Chat unified multi-protocol chat plugin for DankMaterialShell
Rust daemon (chatd-rs) speaking IRC, Discord, and Sneedchat (SockChat over
Tor) behind a shared Unix-socket JSON-RPC/event protocol, plus the QML
frontend (accounts, buffers, messages, settings) that drives it. The
earlier libpurple-based C daemon and its vendored/submoduled protocol
plugins have been fully superseded and are not carried into this history.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-09 02:50:53 -04:00