37 Commits
Author SHA1 Message Date
Amnibro d5d2f12350 Resizing fixes: DM and thread pop-outs stay on screen; no gap under Braid's DM list (#5798) 2026-10-16 00:40:16 -04:00
ancsemi fe5ed5b8a0 Replace em dashes in client code comments and styles 2026-10-10 16:08:55 -04:00
ancsemi 0b8c04e708 Replace em dashes in the English UI text and messages 2026-10-10 16:08:54 -04:00
ancsemi 4d2960de38 Channel Tabs: translate the labels Haven has words for, log failures (#5749)
Channels, Close and Create now use Haven's existing translations through
window.t (English when a key is missing). The two empty catch blocks log
a warning instead of swallowing the error.
2026-10-10 16:01:17 -04:00
ancsemi 4316a00c60 Channel Tabs: keep Create Temp Channel and never show a blank tab (#5749)
The layout hid Haven's Create Temp Channel row and listened for a button
that does not exist, so people allowed only temporary channels lost the
way to make one. The row stays and opens the Join or create window with
Temporary ticked. The DMs tab now shows its pane even before the first
DM (Haven hides it then), and guests, who have no DMs, get no DMs tab.
2026-10-10 16:01:17 -04:00
ancsemi 80acb6e825 Channel Tabs: keep the unread dots in step with Haven's counts (#5749)
The dots now refresh from _updateTabTitle, which every unread change goes
through (including reading a DM in PiP and coming back to the window),
skip muted channels like the tab title does, and retry until the app is
ready. Turning the layout off removes the wrappers from the app instead
of leaving copies of Haven's methods on it.
2026-10-10 16:01:17 -04:00
ancsemi a92f26e55f Channel Tabs: remember the open tab in the plugin's own data (#5749)
The tab was saved under a bare 'activeChannelTab' localStorage key that
looked like one of Haven's own. It now lives with the layout's other
setting in HavenApi.Data, and an existing value is moved over once.
2026-10-10 16:01:17 -04:00
ancsemi 402239ffe0 Channel Tabs: put Join and Create back without undoing Haven's changes (#5749)
Turning the layout off used to restore the class and style the Join and
Create sections had when it was turned on. Haven shows or hides Create as
permissions arrive, so an admin could lose Create (or a member gain it)
until a reload. Only the position is restored now, the panes lose the
pane-hidden class, and the sections go home before the modal is removed.
2026-10-10 16:01:17 -04:00
birdcrazy 7b911be08e Create channelTabsLayout plugin (#5749) 2026-10-10 15:42:21 -04:00
ancsemi f8b1b2fd3f Chrome layout: the row mic sits after the channel options button, so it no longer slides away when the row is hovered 2026-10-09 20:33:23 -04:00
ancsemi ffb27a6463 Chrome layout: show menu labels in the user's language where Haven has them (#5681)
The + menu, the home server menu, the DM dock button, the row voice buttons
and the temporary channel prompt now use Haven's existing translations, and
build their buttons with text instead of HTML. Labels Haven has no string
for yet stay in English.
2026-10-05 18:17:01 -04:00
ancsemi bbf3065e9e Chrome layout: People button uses Haven's panel toggle, drop a retired event (#5681)
The People dock button called a function Haven does not have and fell back
to collapsing the panel directly, which Haven did not remember and which
switching layouts never undid. It now presses Haven's own panel toggle and
its pressed state follows the panel however it is toggled. The listener for
haven:layout-effect is removed: nothing sends that event any more, the
Layout picker calls _engage and _disengage directly.
2026-10-05 18:17:01 -04:00
ancsemi 4ab441c671 Chrome layout: open the Join and Create sections without leaving inline styles (#5681)
The + menu wrote inline styles on the Join and Create sections and on the
create form's container, and none of them were undone when switching
layouts. It now opens a collapsed section through Haven's own section
toggle and leaves the create form's visibility to Haven, which already
shows it to everyone allowed to create channels.
2026-10-05 18:17:01 -04:00
ancsemi 9b35ad0f0a Chrome layout: leave the saved DM list collapse alone (#5681)
Opening and closing the DM drawer wrote Haven's own DM collapse setting, and
a click on the DM header also ran Haven's collapse, so the DM list could
stay collapsed after switching back to Original. The drawer now shows the
list with a style rule, the header click only closes the drawer, and the
layout saves nothing about the DM list. Also replaces the empty catches
there and around saving the layout choice with a logged warning.
2026-10-05 18:17:01 -04:00
ancsemi 00256443bb Chrome layout: stop hiding the update banner (#5681)
The layout hid the banner that tells admins a new Haven version is out.
2026-10-05 18:17:01 -04:00
ancsemi 4fcdcbc288 Chrome layout: show the real DM unread badge on the dock button (#5681)
The layout added a second element with the DM badge's id, but Haven keeps
the first one up to date, and that one sits in the DM header the layout
hides, so the dock never showed unread DMs. The layout now moves Haven's
own badge onto the dock button and puts it back when switching layouts.
2026-10-05 18:17:01 -04:00
ancsemi a0e1309d2d Chrome layout: keep the Settings button and make the home menu open Settings (#5681)
The layout hid the panel holding the only Settings button on desktop, and
its home server menu called a Settings function Haven does not have, so
Settings could not be opened at all. The Settings button stays visible,
the menu opens Settings through that button, Server Settings then switches
to the Admin tab, and that item only shows for people who can use it.
2026-10-05 18:17:01 -04:00
ancsemi 134c4d3814 Chrome layout: the mic on a channel row joins voice in that channel (#5681)
Haven's voice join takes no channel and joins the one being viewed, so the
mic on another channel's row joined voice where you already were. The
button now opens that channel first and then joins, the same way
double-clicking a channel row does.
2026-10-05 18:17:01 -04:00
ancsemi c6eb65d77c Chrome layout: find channel rows by data-code so the voice buttons appear (#5681)
Haven tags each channel row with data-code, but the layout looked for
data-channel-code, so no row ever got its join voice button.
2026-10-05 18:17:01 -04:00
ancsemi de70950745 Chrome layout: stop redrawing the channel voice buttons on every frame (#5681)
Each pass rewrote every voice button inside the channel list, which the
layout's own observer saw as a change and answered with another pass, so
the buttons were redrawn on every animation frame while the layout was on.
A button is now only rewritten when its join or leave state flips.
2026-10-05 18:17:01 -04:00
Amnibro a388655e12 feat(layout): ship Chrome Layout as standalone layout plugin (#5681)
- Package sidebar condensation into plugins/ChromeLayout.plugin.js
- Promotes channel creation, joining, and temp channels to prominent header action menu
- Docks DMs and People in footer with unread badges and sliding drawer
- Equips channel rows with voice controls (join/leave)
- Adds quick settings menu to home server icon
- Full height channel section with category group dividers
- Conforms to the Layout picker contract in docs/theme-authoring.md
- Adds test suite in test/chromeLayout.test.js and entry in GUIDE.md
2026-10-05 17:59:08 -04:00
ancsemi a3af38f915 The last empty catches: background polls, webhook retries and relay calls log, plugins and the installer say why
The server pass covered try/catch blocks; these were promise .catch(() => {})
calls it did not look at. Presence polls (Steam, Spotify, Last.fm), webhook
redelivery, the emoji data refresh and relay viewer changes now log a warning
when they fail. The two queue chains that swallow on purpose (Ferry sends,
relay restarts) say so, since the caller already sees the error. In the bundled
plugins and the installer each catch now gives its reason or logs, and three
try blocks around calls that cannot throw are gone. Test cleanup is unchanged.
2026-10-02 10:31:55 -04:00
Bernardo Costa 60f7f76670 Haven Glyphs: an optional plugin that draws interface icons with a bundled Font Awesome font (#5673) 2026-09-16 23:50:50 -04:00
ancsemi 39c8f41f04 Leaving the Braid layout no longer brings back banners the user had closed (#5671) 2026-09-16 21:24:52 -04:00
Amnibro e87c36249f Braid and Compact file themes no longer stack on Matrix (#5628)
File themes that set the page background (Braid, Braid Light, Compact) are treated as full palettes: turning one on in Settings selects it in the picker instead of layering its colours on top of Matrix or another built-in theme. The theme popup gains a Layout section with Braid and Compact switches so the chrome can be changed without touching the picker colours. Picking a built-in theme now saves first and then reapplies only the real CSS tweaks, so the Settings toggles and the picker agree.
2026-09-10 22:56:05 -04:00
birdcrazy 8c81828944 Settings sections follow the nav order on both panels (#5596)
Settings sections now sit in the same order as the nav on both the user and admin panels, so clicking down the nav scrolls in one direction instead of jumping around. Admin settings get the same scroll spy the user settings had, a Terms of Service nav entry, and icons and names that match their sections. Fixes #5576.
2026-09-08 13:17:12 -04:00
birdcrazy 5a5f2130fd Channel Scrolling setting: separate or combined sidebar scrollbars (#5582)
Layout settings gain a Channel Scrolling choice: separate scrollbars for channels and DMs, or one for the whole sidebar. Short windows fall back to the combined layout so the channel controls stay reachable. The Layout section is split into Density and Channel Scrolling subsections, and the picker setup code is shared. Thanks to @birdcrazy.
2026-09-07 12:55:23 -04:00
Bernardo Costa 14116a4540 Add the Compact Layout plugin and shared layout ownership for structural plugins (#5552)
* Add reversible Compact Layout plugin

* Keep structural layouts stable through Mod Mode
2026-09-02 23:30:35 -04:00
Amnibroandancsemi c931320a3c Braid: three spacing levels, and dark ink on the Android badge (#5494)
Braid shipped one spacing. Settings → Braid spacing (and Menu → Braid
spacing, which cycles without closing the menu) now offers Compact, Cozy
and Spacious. Cozy is exactly what shipped, so the two new levels go in
both directions: the same eight messages measure 417 / 513 / 617 px.

The scale is tokens on html[data-braid-density], read by both the form
and layout sheets, so message runs and channel rows tighten together
along with the sidebar width. Corner radii are deliberately left out of
the scale — this is a density control, not a shape one, and the cards
measure an identical 14px (12px for channel rows) at all three levels.

--braid-gutter is now derived as inset + avatar + row gap rather than
hardcoded. A continuation indents by exactly its leader's gutter, so a
level that shrinks the avatar can no longer drift a run out of line with
its own first message. Measured 0px drift at all three levels.

The Android App badge kept a hardcoded white label. It cannot follow
--accent-text because it paints itself a fixed Android-green gradient in
every theme, so white sat at 1.78:1 at the light end of that gradient.
It and its dismiss button now use an ink that measures 9.65:1 there and
6.46:1 at the dark end.

Co-authored-by: ancsemi <ancsemi@gmail.com>
2026-09-01 22:00:08 -04:00
Amnibro b729a7aad1 fix(braid): keep main channels out of sub-channel cards (#5507)
* fix(braid): keep main channels out of sub-channel cards

_markRuns marked a channel card run from "is my neighbour also a
.channel-item", with no notion of parentage, so any unbroken run of rows
became one card. The first main channel after another channel's
sub-channels continued their card, and read as belonging to a tag it has
no relation to. Reported on both the web client and the Android app.

A card is now a family: siblings under one parent, or a parent followed
by its own subs. famOf() keys a sub row by dataset.parentId and a main
row by "main". joinsRun() continues a run only inside one key, or from a
parent into its own subs, so sub -> main always breaks the card. The
sub-tag-label row carries the same parentId, so a tag stays with the
subs it labels.

Version 1.7 -> 1.8.

* fix(braid): a main channel always starts its own card

Follow-up to review: the first rule still let two adjacent main channels
share a card. A main channel now always begins a new group, so it can
never sit inside a run that reads as a sub-channel family. A card is a
main channel plus its own subs, or a run of sibling subs, or the DM list.

joinsRun() continues a run only into a sub row: from that sub's parent,
or from a sibling sub with the same parentId. Anything into a main row
breaks. DM rows keep grouping among themselves.

* fix(braid): a tag header takes over the grouping, so its channels read flat

Matches the Android app. When sub-channels are re-grouped under their own
tag header, the header already carries the grouping, so indenting the rows
under it as well claims the sub arrow for channels that only look nested
because of where they sit.

Rows the core marks with data-sub-tag (exactly those under a tag label)
get data-braid-flat, and the arrow is painted over with # in Braid form.
Private subs keep their lock, since only a literal arrow is replaced, and
a sub shown directly beneath its parent with no header still keeps it.
Purely cosmetic and scoped to data-braid-form, so toggling the form off
restores the original glyph with no DOM left behind.
2026-09-01 00:59:34 -04:00
Amnibro e735ac80e5 Braid Layout: restore Join / Create a Channel, and fix the dead Encryption entry (#5497)
Reported by birdycrazy: the layout "seems to completely remove the ability
to join or create channels", and the Encryption menu entry does nothing.

Both are real. Join and Create were not merely collapsed — they could not
be reopened at all.

_collapseJoinCreate() added its own `braid-collapsed` class to the section
alongside the stock `.collapsed` class on the body, and the stylesheet hid
`.braid-collapsed .collapsible-section-body` with !important. Nothing ever
removed that class, so the stock toggle went on flipping `.collapsed`
underneath while the body stayed hidden. Traced live: clicking the header
moves the stock class exactly as it should, computed display stays `none`,
and dropping `braid-collapsed` by hand returns it to `block`. That left an
admin unable to create a channel and everyone unable to join one for as
long as the layout was on.

Visibility now comes only from the stock class, which the collapse helper
still sets, so the sections keep opening collapsed and the header reopens
them.

The Encryption entry proxied a click to #e2e-menu-btn, whose handler only
toggles #e2e-dropdown. That dropdown lives inside #e2e-menu-wrapper, which
the app sets to display:none outside a DM — so in a normal channel the
entry appeared and did nothing whatsoever. Inside a DM it fared no better:
this layout hides the header chrome the dropdown anchors to, and the click
that opened it kept bubbling to the document handler that closes it again.

Proxy the three actions instead — Verify encryption, Recover keys, Reset
keys — each of which opens its own modal and does not depend on the
dropdown. The menu is built once, so they are marked and resolved when it
opens: shown where encryption applies, hidden everywhere else.
2026-08-15 09:51:09 -04:00
Amnibro 4aeb770869 Braid Layout v1.6: respect every theme; contain the server logo image (#5479)
Theme respect (reported: 'braid layout is not properly respecting the
other themes'):
- --braid-bub (message-card / channel-card surface) was derived from
  --bg-hover. On themes where hover is a full-contrast selection color
  (win95's navy), every card painted as a permanent highlight and text
  went illegible. Now mixed from text-primary over bg-secondary (5%),
  which reads as a subtle card on every palette; hover states follow the
  same recipe instead of --bg-active.
- All cosmetic shape rules (radii, decorative borders/shadows on
  messages, buttons, modals, menus, toasts, reactions, code, inputs)
  moved to :where() with no !important: they still override the base
  stylesheet, but any [data-theme=...] rule now wins — win95 keeps its
  square corners, themes keep their identity.
- Server strip: glyphs sitting on an accent tile (home, hover) use
  --bg-primary so they stay visible on themes where accent equals
  text-primary (matrix/fallout/crt terminal-glow palettes).

Server logo (reported: 'the server logo is becoming the background of
the server select tiles'):
- The admin-set icon is injected into #home-server as a bare classless
  <img> with no CSS anywhere, so it rendered at natural size and
  sprawled behind the neighboring tiles. style.css now constrains any
  direct img child of .server-icon (100%/cover/inherit radius) — fixes
  the stock vertical rail too — and the Braid strip carries the same
  rule.

Verified live under the Braid layout across matrix (canary for
accent==text themes), win95, daylight, ffx: cards readable, square
corners preserved on win95, home glyph visible on matrix; a 512x512
injected logo renders contained at tile size with strip height
unchanged.
2026-08-08 14:28:11 -04:00
ancsemi d46c90b339 Drop a Braid comment referencing the order-CSS helper v1.5 removed (#5477) 2026-08-05 00:27:31 -04:00
Amnibro 6670655e91 Braid Layout v1.5: multi-server strip, in-sidebar voice dock, layout toggle (#5477)
* Braid Layout v1.5: multi-server strip fix, voice dock with streaming options, one-click layout toggle

- Server strip: #server-list flexed inline so multiple servers keep one row;
  vertical separator, compact utility buttons, hidden scrollbar
- Voice dock: relocate #voice-panel + #voice-settings-panel (screen share
  resolution/fps pickers included) bottom-left with both mute/deafen pairs
  and a People toggle; LIFO restore on suspend/disengage
- Layout toggle: engage/disengage split with persisted preference; Braid
  hexagon switch lives IN the classic bottom bar next to themes; themes +
  classic buttons beside the Menu under Braid; Ctrl+Shift+B (and Ctrl+Alt+B)
- Mod Mode: floating 'Done editing layout' exit, drag-handle leak fixed,
  return switch hidden while editing
- Feedback round: join/create back on top, roomier message cards, contrast
  tokens for buttons in light AND dark palettes, icon menu with short labels,
  sidebar resize unlocked (stock inline width wins again)

* Braid Layout v1.5: calmer message-input focus ring
2026-08-05 00:24:18 -04:00
Amnibro f233849c08 Fix silent crash on launch (swallowed bind errors), allow Node 24, and add opt-in Braid themes + layout plugin (#5471)
* Fail loudly when the server port cannot be bound, and stop refusing Node 24

A failed bind (EADDRINUSE/EACCES/EADDRNOTAVAIL) surfaces as an async
'error' event on the HTTP server. With no listener there, it fell
through to the global uncaughtException keep-alive, which logged it to
crash.log and kept a process alive that never got its socket: no
banner, no exit code, and Start Haven.bat's netstat readiness probe
was satisfied by the stale port-holder — so launches died silently.
Reproduced on 3.39.0 by double-launching; %APPDATA%\Haven\crash.log
shows the same swallowed EADDRINUSE in the wild.

- server.js: bind failures on the main listener are now fatal and
  explain themselves (which port, why, what to do) before exit 1.
  Other server errors keep the existing keep-alive behaviour.
- server.js: the HTTP->HTTPS redirect listener (port+1) warns and
  continues instead of feeding the same silent uncaught path.
- Start Haven.bat: the hard Node >=24 refusal is gone — Node 24 is
  current LTS and better-sqlite3 12.10.0 ships prebuilds for it
  (verified working). The honest gate is a functional
  require('better-sqlite3') check after npm install; >=25 warns.
- package.json/lock: engines widened to >=18 <25 (lock version also
  synced from stale 3.31.2).

* Add Braid themes (dark/light) and the Braid Layout plugin

Ports the Braid look from the Amni-Haven mobile app to the web and
desktop clients, as pure opt-ins riding the existing rails — no core
file changes:

- themes/braid.theme.css / braid-light.theme.css: the mobile BRAID /
  BRAID_LIGHT palettes (mint on slate / deep green on white) with the
  1.6x-rounder shape language. Unpublished by default; admins opt in
  via Settings -> Custom Themes, exactly like any file theme.
- plugins/BraidLayout.plugin.js: the 'vastly simplified' two-edge
  layout — folds the server rail (including manage/sync) into a strip
  atop the sidebar, tucks header extras into a kebab menu, and uses
  the full width for messages. Every stock feature stays reachable:
  the kebab proxies search/pins/gallery/channel code/encryption/
  settings and adds People, Soundboard, Status bar, and app-download
  entries for the chrome it hides. A separate variable-driven shape
  layer applies the Braid format (radii, blur, focus rings) on top of
  ANY active theme, so all built-in themes reskin the Braid layout
  with their own palette. start()/stop() fully applies and fully
  restores (DOM, styles, listeners, localStorage); the
  MutationObserver is childList-only and only mutates
  styles/attributes, so it cannot observe its own writes.

All sizes are rem so the interface Zoom slider scales Braid chrome
together with the rest of the UI. prefers-reduced-motion disables the
motion layer outright.

* Braid Layout: mobile-parity chat cards and condensed chrome

Feedback round: the flat message list didn't carry the mobile Braid
shape language, and leftover strips still read as four-edge chrome.

- Merged run cards (desktop twin of Haven-Mobile's braidForm): a run of
  same-author posts becomes one bordered card on .message-body, dashed
  seams between posts, avatar and hover-timestamp in the gutter, own
  messages tinted with the accent. Run position comes from O(n)
  data-braid-run marking in the existing observer batch — NOT
  :has(+ .message-compact), which makes Chromium re-run invalidation
  per sibling insert and sent a 600-message channel load quadratic.
  Channel list runs are carded the same way.
- Condensed chrome: the topic bar folds into the header band as a
  quiet subtitle (no second border strip), header drops to 3rem,
  sidebar footer and composer tighten, media buttons shrink to 2rem.
- All gutter math is rem (.625 pad + 2.25 avatar + .75 gap = 3.625rem)
  so cards and compacts stay aligned under interface zoom.

* Braid Layout v1.2: Mod Mode interop, themed icons, modern settings, subtler seams

- Mod Mode (the layout editor) is now fully functional with Braid on:
  the layer suspends itself while body.mod-mode-on is set — gates come
  off and the server rail unfolds so every draggable section and panel
  handle is real — and re-applies when editing ends. A saved custom
  section order wins over Braid's default join/create-at-bottom
  ordering (the order rules load only when no haven-layout is stored).
  'Edit layout' joins the kebab menu.
- The bottom-left emoji buttons (theme/activities/members/settings/
  donate/mute/deafen) become currentColor line icons so they follow the
  palette like the rest of the chrome; originals restore on disable.
- Modern settings: nav rail becomes grouped pills with an accent-tinted
  active state, each settings section becomes a rounded card (the
  inline border-top hairlines between sections retire), header gets the
  blur band + pill tabs treatment.
- The seam between same-author posts shrinks to a centered dotted
  hairline (min(7rem,45%)) instead of a full-width dashed rule.

* Braid Layout v1.3: true author-run merging, hamburger menu, text sliders, hex loader, logo glow

- Message merging now chains on AUTHOR: consecutive posts by the same
  user merge into one card even when the app rendered them as separate
  full .message elements (persona changes, break_chain, and system
  notices still split). Continuing messages hide their avatar/header
  and surface their own timestamp in the gutter on hover
  (data-time-short). The visible full-width divider is gone — bodies
  inside a run no longer draw internal horizontal borders, so the only
  separator is the small centered dotted seam.
- One animated hamburger (morphs to an X) replaces both the header
  kebab and the bottom-left icon bar: grouped Channel / View / App menu
  with staggered item animation. The menu mounts on <body> — the
  blurred header is a containing block with overflow:hidden that clips
  even position:fixed descendants. Every absorbed feature keeps its
  door (themes, activities, members, settings, donate, apps, Mod Mode).
- Braid text size: two continuous sliders in Settings (chat text
  80-160%, interface text 85-140%) layered over rem zoom, live-applied
  via CSS vars and persisted per user.
- The brand hexagon gets an accent glow that breathes (and a slow spin
  on hover); a hexagonal loading indicator appears on channel switches
  and reskins the setup wizard's circular spinner. All animations
  respect prefers-reduced-motion.
- Braid / Braid Light themes: type & color enforcement pass — the font
  stack and palette land over style.css's per-element declarations
  (fonts on all controls, selection/placeholder/link/timestamp colors),
  and the own-message tint calms from 12% to 8% accent.

* Braid Layout v1.4: hamburger moves home to the bottom-left, settings nav gets real pills and themed icons

- The hamburger relocates to the bottom-left corner where the icon bar
  it absorbed used to live — the popups it opens (themes, activities)
  anchor down there, so the menu and its children now share a corner
  instead of spawning across the screen from the button. It is styled
  as a Haven tile (bordered, bg-tertiary, accent hover) with a Menu
  label, and the grouped menu rises from the bottom-left with the same
  morph-to-X and stagger.
- Settings nav highlights now encompass their rows: stock uses a
  hanging-indent hack (padding-left 1.625rem + text-indent -16px) so
  wrapped labels clear the leading emoji, which pulled the first line
  left out of the highlight pill. Items are now full-width flex pills
  with text-indent reset — and every leading emoji (nav rows and the
  User/Admin tabs) becomes a currentColor line glyph keyed by
  data-target, same treatment as the old bottom-left buttons, with a
  Haven hexagon fallback for unmapped rows. Originals restore on
  disable.
2026-08-02 20:56:15 -04:00
ancsemi 0f74fd6ec3 v2.3.5: externalize donor list, fix password redirect loop, fix plugin loader scope 2026-02-26 20:24:02 -05:00
ancsemi 42e6fc6259 v2.3.0 Webcam video, plugin/theme system, font size, channel invites, admin members panel, desktop app beta, session invalidation, security fixes 2026-02-24 18:54:00 -05:00