contact messages: visitor identity, relative timestamps, alternating headers
- The first message of a thread must carry name + email introducing the visitor; the panel shows the two fields until the thread has an identity (send stays disabled while they look empty, so the draft is never lost), prefilled from and saved to localStorage. The identity is stored on ContactThread (msgspec defaults — old databases decode unchanged) and fixed afterwards; it labels the visitor's messages instead of 'you', and the admin inbox lists threads by name with the email as a mailto in the thread header. - Timestamps use the analytics relative formatter (formatWhen), with the full date on hover. - Message headers alternate alignment (own messages right, theirs left) as the visual side cue; the sent-from page link is dropped from the display (kept as stored metadata). - Composer gains a sendDisabled prop for the intro gate.
This commit is contained in:
1 parent
e810c5f664
commit
67c19230b4
7 files changed
+173
-57
No files matched your search
+16
-14
@@ -49,12 +49,14 @@ no extra connection). Frames **to** the server:
|
||||
`pagerite.js` re-sends this on every socket (re)connect, which is the
|
||||
resync mechanism (the socket idle-closes after 5 min and reconnects on
|
||||
activity).
|
||||
- `{token, msg, pow, fr}` — append a message; `msg` is the Markdown-subset
|
||||
source, `pow` the solved proof-of-work (below), `fr` the page path it
|
||||
was sent from (stored for context).
|
||||
- `{token, msg, pow, fr, name?, email?}` — append a message; `msg` is the
|
||||
Markdown-subset source, `pow` the solved proof-of-work (below), `fr` the
|
||||
page path it was sent from (stored for context). The **first** message
|
||||
of a thread must carry `name` and `email` introducing the visitor; the
|
||||
identity is stored on the thread and fixed from then on.
|
||||
|
||||
Frames **from** the server: `{type: "thread", id, created, unread,
|
||||
messages: [{id, t, admin, html, page}]}` — a full thread snapshot
|
||||
Frames **from** the server: `{type: "thread", id, created, unread, name,
|
||||
email, messages: [{id, t, admin, html, page}]}` — a full thread snapshot
|
||||
(replace/upsert by `id`); `{type: "pow", challenge, required}` — a fresh
|
||||
single-use PoW challenge (`required` means the last message was rejected
|
||||
for a missing/stale solution and should be re-sent once solved); or
|
||||
@@ -142,18 +144,18 @@ server restart (the pending set is RAM-only) still linger — no GC.
|
||||
|
||||
`Data.contact: dict[bytes, ContactThread]` in the kanta database, keyed by
|
||||
the 12-byte blake3 hash of the session token (never the token itself). A
|
||||
thread is `created`, `admin_read`, and `messages: dict[str,
|
||||
ContactMessage]` keyed by a sortable timestamp-random id (dict-keyed, so a
|
||||
save's database diff touches only the appended message). Each message
|
||||
stores `t`, the Markdown source `md`, its strict rendering `html`, `admin`
|
||||
("" = visitor, else the SSO name) and `page`. Appends are single
|
||||
transactions (`contact` / `contact:reply` / `contact:read`).
|
||||
thread is `created`, `admin_read`, the visitor's self-entered
|
||||
`name`/`email` (required with the first message, fixed afterwards) and
|
||||
`messages: dict[str, ContactMessage]` keyed by a sortable timestamp-random
|
||||
id (dict-keyed, so a save's database diff touches only the appended
|
||||
message). Each message stores `t`, the Markdown source `md`, its strict
|
||||
rendering `html`, `admin` ("" = visitor, else the SSO name) and `page`.
|
||||
Appends are single transactions (`contact` / `contact:reply` /
|
||||
`contact:read`).
|
||||
|
||||
## Limits and deliberate gaps (MVP)
|
||||
|
||||
- Message source ≤ 8000 chars; uploads ≤ 20 MB and ≤ 10 pending per
|
||||
session; payloads cap at 100 threads × last 200 messages.
|
||||
- No thread moderation (delete/block), no orphan-upload GC for files
|
||||
orphaned by a server restart, panel strings are English-only, and the
|
||||
admin inbox lists threads by token-hash prefix rather than enriched
|
||||
visitor identity.
|
||||
orphaned by a server restart, and panel strings are English-only.
|
||||
Reference in new issue
Block a user