Skip to content

feat(header): optional per-server subtitle so several instances can be told apart - #96

Open
maxlamagna wants to merge 1 commit into
bcurts:mainfrom
maxlamagna:feat/optional-room-subtitle
Open

feat(header): optional per-server subtitle so several instances can be told apart#96
maxlamagna wants to merge 1 commit into
bcurts:mainfrom
maxlamagna:feat/optional-room-subtitle

Conversation

@maxlamagna

Copy link
Copy Markdown
Contributor

The per-project isolation section in the README explains how to run one install as several isolated instances. Once you do, every one of them has the same header and the same tab title, and there is no way to tell which server a tab belongs to.

What this adds

static/index.html already has <span class="subtitle" id="room-subtitle"> in the header, and a .subtitle rule in static/style.css, but nothing has ever put anything into that span. This fills it in.

A new This server field in Settings sets the value. It renders beside the title, and it is appended to the browser tab title as agentchattr - name. Empty by default, which is exactly today's appearance, so nothing changes for anyone who ignores it.

Handling of the value

It is rendered with textContent, never innerHTML.

Internal whitespace is collapsed, so a pasted newline cannot break the header across two lines, and it is capped at 40 characters so a long name cannot crowd out the rest of the header.

That normalisation also runs on the settings-file read path, not just the live update path. data/settings.json is hand-editable, so a value written straight into the file would otherwise bypass every check.

One change to an existing rule of yours, easy to decline

The .subtitle rule is yours and pre-existing: 12px, normal weight, var(--text-dim), which is #6a6a80 against a dark header. Because nothing ever populated the span, that styling has never actually been rendered, and it is hard to read once there is text in it.

This raises it to weight 500 and var(--text). It stays clearly secondary to the title, which is 16px at weight 600. static/index.html:22 is the only element carrying the class, so nothing else in the UI moves.

If you would rather keep your own styling, drop that one hunk in static/style.css and the rest of the PR is unaffected.

Tests

12 new in tests/test_room_name.py, covering normalisation, the 40-character cap, the settings-file read path, and the default-empty behaviour.

Full suite on this branch: 93 tests, 0 failures, 1 skipped.

One declared gap: the single line wiring the subtitle into the websocket update_settings handler is not covered. Testing it needs either a live websocket or extracting that inline settings block, and neither felt like it belonged in this change. The normalisation that line delegates to is covered directly.

README

One paragraph added to the Per-project isolation section, since the setting is currently undocumented.

One thing to know if you merge this second

A companion PR fixes one-shot scheduling. Both PRs bump style.css?v= and chat.js?v= in static/index.html, and both bump them to the same values. They merge cleanly, but the second merge then leaves the stamps unchanged from the first, so a browser that loaded after the first merge would keep those assets. Please bump both stamps once more when you take the second of the two.

…e told apart

Running one agentchattr install across several projects, as the
per-project isolation section describes, leaves you with identical tabs
and identical headers. There is no way to tell which server a tab belongs
to.

This fills in the #room-subtitle span that already exists in the header
but has never had anything put into it. A new "This server" field in
Settings sets it, it renders beside the title, and it is appended to the
browser tab title as "agentchattr - name". Empty by default, which is
today's appearance exactly, so nothing changes for anyone who ignores it.

The value is normalised on the way in: internal whitespace is collapsed so
a pasted newline cannot break the header across two lines, and it is capped
at 40 characters so a long name cannot crowd out the rest of the header.
Normalisation also runs on the settings-file read path, because
data/settings.json is hand-editable and would otherwise bypass every check
the live update path applies. It is rendered with textContent, not innerHTML.

This commit also changes an existing rule of yours, and it is easy to drop
if you would rather it stayed as it is. The .subtitle rule is 12px, normal
weight, in --text-dim, which is #6a6a80 against a dark header. Because
nothing ever populated the span, that styling had never actually been
rendered, and it is hard to read once there is text in it. This raises it
to weight 500 and --text. It stays clearly secondary to the title, which is
16px at weight 600. static/index.html:22 is the only element carrying the
class, so nothing else in the UI moves.

Tests: 12 new in tests/test_room_name.py, covering normalisation, the cap,
the settings-file read path, and the default-empty behaviour.

One declared gap: the single line wiring the subtitle into the websocket
update_settings handler is not covered. Testing it needs either a live
websocket or extracting that inline settings block, and neither belongs in
this change. The normalisation it delegates to is covered directly.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant