Commit graph

471 commits

Author SHA1 Message Date
1a215ff912 Update dependency @types/node to v24.13.3 2026-07-11 02:02:05 +00:00
4f95f0ea66
Theme the games panel instead of hardcoded dark colours
The panel referenced its own token names (--bg2/--tx/--tx-dim/--ac/--card)
that don't exist in the app, so it always fell back to hardcoded dark
values — mismatched on the light and Night-orange/green themes. Alias
those tokens to the app's theme tokens (--bg / --ink / --muted / --accent
/ --bg-soft-2) at the panel root, fix the active white-overlay fills that
vanished on light backgrounds (rows, input, toast), map the accept action
to --online, and soften the shadows. The panel now follows the active
theme; the game-piece colours (X/O, chess, Connect-4) stay as-is.
2026-07-11 01:59:55 +00:00
a6769d3a54
Move Games from the topbar into the footer nav
Games is now a "Jeux" tab in the footer alongside Accueil / Salons / Amis
— icon over label, accent when its panel is open, an alert dot when it's
your move or a challenge is pending — a native bottom-nav home for it. The
panel still opens from the persistent 'overlay' slot, and the new-game /
challenge ("invite to game") flow lives inside it (plus the profile Défier
action). Drops the now-unused topbar-plugin-in-overflow machinery; the
clock stays in the desktop header.
2026-07-11 01:48:18 +00:00
c28a28645f
Hide the clock from the mobile overflow menu
The clock is a passive HH:MM display (a sandboxed .sbx-slot), so it doesn't
belong in the action menu — and it's redundant on phones, where the OS
status bar already shows the time. Drop sandboxed topbar plugins from the
⋮ overflow; the bar copy is already hidden on mobile, so the clock is now
gone on phones while staying in the desktop header.
2026-07-11 01:07:13 +00:00
231be23f0d
Add an 'overlay' plugin slot; move Games into the mobile ⋮ menu
A topbar plugin's popover was rendered as a child of its launcher button,
so the button had to stay mounted for the popover to survive — which is
why the games button couldn't move off the crowded mobile header. Add a
persistent 'overlay' UI slot at the app root and render the games panel
there, decoupling it from the button. The launcher is now stateless, so
on mobile it drops into the ⋮ overflow as a labelled "Jeux" row (freeing
the header for the channel name + topic) while its panel stays anchored.
Desktop keeps the icon in the bar.
2026-07-11 00:54:36 +00:00
e36d3a1d34
Keep the games button in the mobile topbar
The games panel is a fixed overlay rendered as a child of its button, so
the button has to stay mounted for the panel to survive — it can't move
into the ephemeral overflow menu, where it would unmount (and the panel
vanish) the moment the menu closes. Now that search / manage / leave live
in the overflow, the bar has room, so show the games plugin button inline
on mobile instead of hiding it. Reachable again, and the title and topic
still fit.
2026-07-11 00:28:18 +00:00
7c074d7a8b
Rework the mobile topbar into a native header
On phones the channel header crammed every button into one row: the title
sat behind the games-plugin button and the topic was pushed off screen.
Collapse the one-shot actions (search, manage, leave) into a "⋮" overflow
menu, hide topbar plugin items on mobile, and keep only the stateful notify
and pin toggles, the member count and the overflow inline. The channel
glyph, name and topic now have room to show as a proper two-line header.
2026-07-11 00:11:56 +00:00
d817db9255
Theme the topbar toolbar icons to match the footer set
The channel header's search, notify, pin, manage and close buttons — plus
the app-wide search-field magnifiers and the menu toggle — used OS emoji
glyphs. Extend the shared Icon component with search, close, menu, bell,
bell-off, pin and sliders, and use it across the topbar, the notify and
pin menus, and the explore / switcher / side-search fields. The icons
inherit each button's colour and get the same press and focus states as
the footer, so the whole chrome now reads as one icon family.
2026-07-10 23:51:15 +00:00
e82b4b7f01
Replace footer emoji glyphs with a themed icon set
The account bar's tabs and settings button used OS emoji (home, compass,
people, gear), which render off-theme and differ across platforms. Add a
shared stroke-icon component — 24×24, currentColor, the same 1.9 stroke as
the composer glyphs — and use it for Accueil, Salons, Amis and Settings.
The icons inherit each button's colour, so the active tab now reads as a
soft accent pill, and the buttons gain a press dip and focus ring so the
bar feels native on desktop, not just touch.
2026-07-10 22:57:37 +00:00
dbb45e4d17
Load only the active UI locale on first paint
All ten translations (~400 KB of JSON) were bundled into the entry
chunk, nearly all of it never used in a session. Ship only French — the
default and fallback — and fetch the other nine as separate chunks on
demand (language switch or a config-pinned default). The entry chunk
drops from 653 KB to 361 KB (200 KB to 118 KB gzipped), cutting the
parse/execute work that was delaying the largest paint.
2026-07-10 22:26:24 +00:00
d5ddbbff4f
Coalesce inbound messages into batched renders
Each IRC line arrives as its own WebSocket frame (text.ircv3.net), so
the store rendered once per line. Joining several busy channels at once
— NAMES plus a WHO reply per member — fired a render for every line and
stalled the main thread, which also inflated LCP. Buffer messages onto a
0ms timer so a whole burst drains in one render; under load the timers
back up and each drain swallows more lines. A timer rather than rAF keeps
unread counts and mention notifications live in a backgrounded tab.
2026-07-10 22:14:24 +00:00
14cf38afa8
Fix Turnstile ref write during render and the gtag lint error
Turnstile refreshed its callback ref in the render body; move it to an
effect. The gtag shim legitimately pushes the live arguments object, so
scope a disable to that line with a reason. Lint is now error-clean.
2026-07-10 21:49:55 +00:00
9b21adb9cc
Derive prop-synced state during render, not in effects
The nick field, channel +k/+l inputs and avatar hook re-synced from
props by calling setState inside an effect, which triggers an extra
render pass each time. Track the previous prop and adjust during
render instead — one pass, and the avatar now resets on account switch.
2026-07-10 21:48:08 +00:00
7ea1fd3e87
Add @/ path alias, replace deep relative imports
Set up an @/* -> src/* alias (tsconfig paths + vite resolve) and
convert every ../../-and-deeper import to it. Same-dir ./ and
one-level ../ stay relative. Build-time only, so the bundle is
unchanged; the deep imports were just hard to read and broke on
file moves.
2026-07-10 21:30:32 +00:00
96ff3bef78
Image/voice shares: bold + italic so they stand out in the log 2026-07-10 21:09:36 +00:00
b1b628bdc9
Fix CTCP ACTION: wrap in \x01 so /me + image shares render as '* nick …' in every client (mIRC etc.) 2026-07-10 21:09:36 +00:00
4f8d10c8a5
yomirc: float the hover toolbar above the log line so it no longer overlaps the next line (fixes hover jump) 2026-07-10 20:04:46 +00:00
f90aca5252
Sidebar rows: div[role=button] + a real close button — valid HTML, keyboard-reachable close 2026-07-10 19:54:40 +00:00
5d6de5a357
Sidebar: memoize each room row (subscribes to its own buffer) so a message updates only that row 2026-07-10 19:50:37 +00:00
b7265b5706
Composer: mark fire-and-forget image uploads with void (intent; store already catches) 2026-07-10 19:45:06 +00:00
d3300d4a4e
Images: decode avatars + link previews off-thread (decoding=async), pin preview img size 2026-07-10 19:43:33 +00:00
bbd8b81ea6
Modals: trap Tab inside the dialog and return focus to the trigger on close (a11y) 2026-07-10 19:41:51 +00:00
77d8a0a669
Message rows use content-visibility to skip off-screen layout/paint (faster channel switch) 2026-07-10 19:17:13 +00:00
c3b96c5b16
Memoize message rows: a new message re-renders only the new row, not the whole list 2026-07-10 19:07:11 +00:00
67e6493b71
Native tactile press feedback: controls dip+dim on touch, no tap delay/callout 2026-07-10 18:54:21 +00:00
8bc88557b3
Mobile native-feel: kill iOS input-zoom (16px), overscroll-contain, no tap-flash, safe-area top, non-selectable chrome 2026-07-10 18:37:30 +00:00
c0ec75d6dd
iOS keyboard: native easing curve + 60px threshold to stop suggestion-bar jitter 2026-07-10 18:21:24 +00:00
d5af169c73
Self-heal the iOS pre-resize when no keyboard opens (hardware keyboard / programmatic focus) 2026-07-10 17:54:51 +00:00
88e689fc82
Smooth iOS keyboard open: pre-resize on focus + CSS height glide, corrected by the resize event 2026-07-10 17:53:14 +00:00
9a4757e839
Track mobile keyboard via VisualViewport directly; drop the pre-resize guess that broke the first open 2026-07-10 17:41:50 +00:00
db1ba1420f
Analytics consent: grant only analytics_storage in the app (ad signals stay denied, ad-free) 2026-07-10 16:26:02 +00:00
e2ecd093a6
Make the console/status window follow the theme accent (drop hardcoded terminal green) 2026-07-10 15:43:30 +00:00
df3f9d4b92
Reflect own away state in the member list (patch self entry) + orange away name 2026-07-10 15:04:23 +00:00
04f229053a
Fix avatar click crash: capture rect before the state updater runs 2026-07-10 14:48:22 +00:00
b94b9f8994
Open a presence menu (Available/Away + reason) from the account avatar 2026-07-10 14:45:28 +00:00
cf51efe339
Rework theme presets: rename, orange Night-orange accent, theme-aware console 2026-07-10 14:25:26 +00:00
8894974479
Drop the app's consent banner; consent is handled on the site (same origin) 2026-07-10 14:01:44 +00:00
6f9df54864
Switch analytics to Google Consent Mode v2 (advanced) 2026-07-10 13:29:01 +00:00
8fd1af78bb
Fix stale app-update comment to match no-auto-reload behavior 2026-07-10 10:30:47 +00:00
726ce7b609
Strip IRC formatting codes from WebMCP read_messages output 2026-07-10 10:27:21 +00:00
7f6fb14b19
Expose the chat as WebMCP tools for AI agents (list/read/send/join/switch/members) 2026-07-10 10:21:10 +00:00
6ad0d2bbd9
Fix mobile drawer footer: give the nav tabs their own full-width row 2026-07-10 09:25:46 +00:00
c18604c426
Stop the app from auto-reloading on new builds; update on next manual refresh instead 2026-07-10 09:04:31 +00:00
ad05f3e470
Fix mobile topbar overflow: drop the redundant channel avatar and tighten spacing 2026-07-10 08:13:30 +00:00
937a9dc38c
Fix mobile: wrap the extban composer and full-screen the channel panel 2026-07-10 08:06:22 +00:00
4a0b6b51e0
Fix mobile layout: constrain the app to the viewport height when a navbar shell wraps it 2026-07-10 08:00:46 +00:00
27cfae944a
Support extban stacking: nest a matching extban inside an acting one (mute:account:...) 2026-07-10 07:42:11 +00:00
a390078876
List +e ban-exceptions and +I invite-exceptions in the channel panel, removable per mode 2026-07-10 07:27:02 +00:00
a141742868
Gate the extban +e/+I modes on the server's CHANMODES list modes 2026-07-10 07:17:41 +00:00
2bae979b30
Let extbans be set as +b, +e or +I from the channel panel, with the example following the mode 2026-07-10 07:11:33 +00:00