Commit graph

69 commits

Author SHA1 Message Date
1d45f75f12
PWA icons: use the Tchatou brand mark, not the Orbit logo
Regenerate the install/notification icons from tchatou.fr's own favicon
(France-blue tile + speech bubbles). Bump the SW cache version so clients
fetch the new icons; push handler unchanged.
2026-06-27 10:29:54 +00:00
f8635d3256
Revert "Push notifications: keep them on screen until dismissed"
This reverts commit 3864c71aff.
2026-06-27 03:04:24 +00:00
3864c71aff
Push notifications: keep them on screen until dismissed
Backgrounded mentions fired the notification (hence the sound) but it was
easy to miss — auto-dismissed / silent in the shade. Add requireInteraction
+ a short vibrate so it stays visible, and bump the SW cache so clients pick
up the change.
2026-06-27 02:52:08 +00:00
9ca8d8c072
ux: styled alert card for content-policy rejections
Replace the plain ⚠ sysline with a prominent amber alert card (SVG
warning icon, left-accent border, stands out from normal system lines)
when an upload is blocked by content policy. The message now reads as
a clear consequence — 'blocked' rather than 'refused' — and tells the
user that operators have been notified. Malware rejections also get the
alert treatment.
2026-06-23 15:05:47 +00:00
3c96b2e6b0
filehost: friendly message for violence-rejected images 2026-06-23 02:38:45 +00:00
d64e912cba
filehost: friendly message for NSFW-rejected images
Images are now moderated by a local NudeNet service; explicit uploads
get 422 nsfw_image. Map that to a clear 'image rejected: explicit
content' notice instead of a raw error code.
2026-06-23 02:19:59 +00:00
acbc6d774f
filehost: clear message when AV scanner is down (503)
Server now fails closed when ClamAV can't scan (refuses with 503
scanner_unavailable instead of storing an unverified file). Map that to
a friendly 'virus scanning temporarily unavailable' notice instead of a
raw error code.
2026-06-23 02:03:12 +00:00
3702ade9e1
filehost: precise not-identified match (don't reject the success lines)
The module sends the token line first, then 'No need to log in again' —
which the previous heuristic matched as not-identified. Match the real
guest line ('must be logged in to use file hosting') instead, and also
swallow it (it lacks the FILEHOST prefix).
2026-06-22 22:49:40 +00:00
32a42a6cdc
filehost: always hide FILEHOST service notices
The automatic /FILEHOST command behind image/voice uploads emitted help
notices that leaked into chat once the token line resolved. Suppress all
FILEHOST notices unconditionally (still extract the token when an upload
is pending), and tighten not-identified detection so it no longer matches
the 'Your logged in account: …' success line.
2026-06-22 22:47:06 +00:00
3cd60c844f
composer: voice messages (record + inline player)
Record a voice message in the composer (MediaRecorder → opus/webm) and
share it through the same /FILEHOST upload flow as images; received audio
URLs render as an inline player. Works in channels and PMs.
2026-06-22 22:00:58 +00:00
199c8100fb
games: per-game-type stats and ladders
Each game (chess / Connect 4 / tic-tac-toe) now has its own rank, points
and record. The panel shows a rank row per game played, the leaderboard
gains a per-game tab, and the profile chip shows a player's strongest
game. Reads the per-type GS$ / GS$TOP lines GameServ now sends.
2026-06-22 14:18:47 +00:00
18d6d2df5a
games: read GameServ state from invisible client-only tag
GameServ now pushes board/stats state in a +tchatou.fr/gs tag on a
bodiless TAGMSG instead of a GS# NOTICE, so plain IRC clients never see
the machine lines and only get the human-readable NOTICE. The web client
reads the tag to drive the UI and hides GameServ's NOTICEs from chat.
2026-06-22 13:56:56 +00:00
695641f29a
games: board games refereed by GameServ + ranked ladder
chess, tic-tac-toe and Connect Four played against the GameServ services
referee (it validates moves + keeps the account-keyed Bronze→Master
ladder); the client only sends commands and renders the pushed state.
adds a generic plugin message-filter so a service's machine lines stay
out of chat.
2026-06-22 12:12:39 +00:00
704bd473b7
report: route ReportServ command + replies to the Status window
filing a report echoed our REPORT command into a ReportServ PM buffer
and ReportServ's confirmation landed in the active channel. route both
(by sender/recipient = report.service) to Status instead, and put the
optimistic confirmation there too.
2026-06-22 12:12:07 +00:00
94b5fabc84
report: file abuse reports through ReportServ via a window
the report action opened a hardcoded PRIVMSG to #staff, which a +n
staff channel silently drops for non-members. now it opens a report
window (target + reason) and sends REPORT to the ReportServ service,
which queues it for staff and isn't blocked by +n. config gains
report.service (default ReportServ); empty falls back to the channel.
2026-06-22 12:12:07 +00:00
093df67757
sidebar: show the server name under the Status row
the Home list's Status row now shows where you're connected (the ircd
hostname) instead of the generic "System", falling back to System
until 004 arrives.
2026-06-22 12:12:07 +00:00
a48a5ad66c
topbar: mIRC-style Status title on the server buffer
rename the server/console window to Status everywhere and render its
title as "Status: <nick> [+<umodes>] on <servername>". track the ircd
hostname from RPL_MYINFO (004) and query our user modes on register so
the line is populated.
2026-06-22 12:12:07 +00:00
698bff268f
connect: auto-connect from the site entry-form handoff
The Tchatou entry form now sends visitors to /app/?nick=&channel= and parks
any SASL password in same-origin sessionStorage (kept out of the URL). On
boot we consume that one-shot marker and connect right away, so a visitor who
already chose a pseudo on the site never sees the join form a second time.

A new autoConnecting flag shows a small splash while the handoff connects;
any failure clears it and falls back to the join form with the nick and
channel still prefilled from the URL.
2026-06-21 01:13:46 +00:00
reverse
23d8979ae7
main: static-import the error boundary so recovery code is in the core bundle 2026-06-20 18:18:11 +00:00
reverse
9f9a3e530a
Add a top-level error boundary (crash recovery instead of white screen)
A render error anywhere previously unmounted the whole tree into a blank
page. AppErrorBoundary now wraps the app and shows a localized recovery
screen with a reload button, logging the error. Mirrors the proven
PluginBoundary pattern.
2026-06-20 18:16:10 +00:00
reverse
11343270e8
MemberList: browser-native virtualization for large channels
Off-screen member rows now skip layout & paint via content-visibility,
with contain-intrinsic-size for correct scrollbar sizing (yomirc gets a
smaller estimate). A 2k-member panel only renders the visible rows; small
channels are unchanged. Together with the earlier per-message re-render
fixes, this closes the large-channel lag (layout/paint + re-render cost).
2026-06-20 18:01:25 +00:00
reverse
85f1458145
Topbar: narrow store selects so it doesn't re-render per message
Was subscribing to the whole active buffer (new object on every message)
and recounting members each time. Now selects name/isChannel/topic/modes/
members individually — re-renders only when those change, not on each line.
Audited the rest: MessageList must track messages (capped 500, virtualise
later); Sidebar is bounded; the typing indicator is trivial and benefits
from frequent renders; modal selectors only run while open.
2026-06-20 17:51:01 +00:00
reverse
39c68105f0
MemberList: stop re-rendering/re-sorting on every message
Subscribe to buffer.members by reference (updated immutably) instead of
the whole active buffer, and memoise the role grouping + name sort. The
list now recomputes only when membership/mode/filter actually changes —
not on each incoming line, which was O(members) work per message in big
channels.
2026-06-20 16:53:11 +00:00
reverse
5d5b54cfc4
config: optional defaults.lang to pin a default UI language
When set (and the user hasn't explicitly chosen one), it overrides
browser detection after the runtime config loads. Omitted = auto-detect
as before.
2026-06-20 16:28:25 +00:00
reverse
e444daf4d6
Plugins: hand decorators/actions formatting-stripped text (+ raw)
MessageInfo.text is now the human-readable text with mIRC formatting/
colour codes stripped, so orbit-copy copies clean text instead of raw
control codes; the original is available as MessageInfo.raw.
2026-06-20 09:12:58 +00:00
reverse
9cde837da6
Add message_action plugin slot; move orbit-copy into the action toolbar
New addMessageAction() puts a plugin button in each message's hover
toolbar next to reply/react (inherits its styling), distinct from the
inline addMessageDecorator. orbit-copy now lives there with its green
check-on-copy feedback — tidier than a copy icon on every line.
2026-06-20 09:05:20 +00:00
reverse
4036ce527d
orbit-copy: flip the copy button to a green check on copy 2026-06-20 08:56:25 +00:00
reverse
f12ac0a627
Plugin SRI support + documented deployment CSP
Plugin entries may now be { url, integrity, crossorigin } so off-origin
plugins can be pinned with Subresource Integrity (crossorigin defaults to
anonymous when a hash is set). Documents a sample CSP header and SRI hash
generation in SECURITY.md; the policy is a header (deployment-specific
origins) rather than a baked meta tag.
2026-06-20 08:37:17 +00:00
reverse
d51e18f0f7
Accessibility pass: focus ring, skip link, landmarks, labels
Adds a clear :focus-visible keyboard ring for buttons/links/menu items,
a skip-to-messages link, landmark labels on the message log (role=log),
conversation sidebar and member list, and aria-labels on the emoji-only
message action buttons. New a11y i18n namespace across all locales.
2026-06-20 08:33:41 +00:00
reverse
641fd0de84
Plugin maturity: more UI slots, message decorators, two examples
Adds topbar_item and sidebar_item slots, plus addMessageDecorator() —
a per-message hook handed a stable read-only view {id,nick,text,kind,
ts,mine}, each rendered inside its own error boundary. Ships orbit-clock
(topbar) and orbit-copy (decorator) examples and documents both.
2026-06-20 08:30:27 +00:00
reverse
36339e2a03
Per-channel notification level (All / Mentions / Mute)
Replaces the binary mute with a three-way level stored per channel
(legacy muted channels migrate to Mute). The topbar bell opens an
accessible popover; the notify decision honours the level — All alerts
on every line, Mentions only on your nick/highlights, Mute never.
2026-06-20 08:24:07 +00:00
reverse
2dc06f3388
Add keyboard shortcuts, a ? help sheet, and mark-all-read
Global hotkeys (chat view): Ctrl/Cmd-K switcher, Alt+Up/Down to cycle
conversations, Shift+Esc to mark everything read, ? for the help sheet.
Composer arrow handler now ignores Alt so buffer-nav passes through.
2026-06-20 08:18:13 +00:00
reverse
ae50b59b4c
feat: Ctrl/⌘-K quick switcher — fuzzy-jump to any channel, DM or person, or join a channel by name (keyboard-navigable command palette); pure result builder with tests, i18n in 10 languages 2026-06-20 08:05:33 +00:00
reverse
92a135cb96
feat: text-size control (Appearance), Orbit.apiVersion for plugins, and remove dangling privacy/advanced settings labels 2026-06-20 07:51:03 +00:00
reverse
772dfacb39
chore: project credibility bundle — CONTRIBUTING/CODE_OF_CONDUCT/SECURITY/issue+PR templates, .editorconfig, CHANGELOG; add plugin-bus & mode-parsing tests; replace ineffective try/catch plugin slots with a real error boundary (fixes lint, actually isolates plugin render errors) 2026-06-20 07:31:04 +00:00
reverse
71473bd478
feat(plugins): compiled-plugin support — expose React/ReactDOM/jsx-runtime/Fragment as externalization targets, add settings_section slot (addSettingsSection) wired into Settings, + plugin-template/ (Vite build with React externalized) and docs 2026-06-20 05:42:02 +00:00
reverse
0032471faf
config: disable demo plugin in production (system ships, example stays available) 2026-06-20 05:10:39 +00:00
reverse
1b497704e1
fix(plugins): composer plugin-button selector returned a new array each render (zustand v5 infinite loop crashed the chat view) — select stable ref, filter in body 2026-06-20 05:05:41 +00:00
reverse
8e5be83d20
feat(plugins): KiwiIRC-style operator-controlled plugin system — window.Orbit (plugin/on/emit/state/irc/themes/storage/addUi), config plugins[], HTM render, composer_button slot, demo plugin + docs/PLUGINS.md 2026-06-20 05:01:20 +00:00
reverse
af252a8193
add orbit-avatar.png (1024px raster of the project icon) to public for download 2026-06-20 03:52:55 +00:00
reverse
6a1020ac4c
app: use the Orbit project icon as the favicon / apple-touch-icon / PWA manifest icon 2026-06-20 03:41:30 +00:00
reverse
a4e42c0c30
settings: inline IRCv3 chat-bubble v3 mark for the section icon (no official IRCv3 glyph exists) 2026-06-20 03:33:15 +00:00
reverse
47b11ed43e
settings: use a plug icon for the IRCv3 section (capabilities/plugins) instead of a satellite 2026-06-20 03:18:08 +00:00
reverse
21ef4c40d4
settings: About hero uses the Orbit project icon, not the deployment/server icon 2026-06-20 03:03:53 +00:00
reverse
808bf08b60
settings: add About section (app version/build/commit injected at build, AGPL source/project links); bump version to 1.0.0 2026-06-20 02:58:33 +00:00
reverse
b36db60573
settings: Server section gains max-channels row + collapsible raw ISUPPORT (005) viewer 2026-06-20 02:50:29 +00:00
reverse
ae008ae5a6
settings: move Server info into its own section (separate from IRCv3 capabilities) 2026-06-20 02:44:54 +00:00
reverse
86d21fb4ba
settings: add Server info card to IRCv3 panel (network, software/version, TLS, users online, casemapping, channel types, roles, limits) 2026-06-20 02:38:31 +00:00
reverse
a54cc18aa9
settings: fix scroll on mobile — cards no longer shrink/clip inside the scroll area (IRCv3 list now fully reachable) 2026-06-20 02:29:47 +00:00
reverse
60e85a8257
settings: 2-column responsive grid for IRCv3 capabilities so the full set is visible 2026-06-20 02:22:49 +00:00