Make "Show original" in the headers dialog the action, not a description

The hint at the foot of Message headers named an action and left you to go
find it. Requested in #236, and the reporter is right that it is the shape of
the thing rather than the size: telling somebody a feature exists is half a
job when the other half is one element away.

Clicking it now closes the headers dialog and opens the original, so it reads
as going deeper rather than as opening a second window.

`tNode` rather than a sentence chopped either side of a button: the sentence
stays whole for whoever translates it, and a language that puts the verb
somewhere else can move the hole rather than being handed two fragments.

The link style needed unscoping to work, which turned out to be a bug of its
own. `.link-btn` was written for the composer's To and Cc labels and scoped to
`.composer-field label`, so the two callers outside it -- the trusted-domain
list in Privacy settings, and now this -- rendered as default button chrome in
the middle of a sentence. The rule is now unscoped and Privacy is fixed by the
same change.

Checked in a browser: the hint reads as a sentence with a dotted-underlined
link in it, clicking swaps one dialog for the other, and the raw message is
there.

Closes #236.
This commit is contained in:
2026-09-02 13:17:10 -07:00
parent 45f1309d06
commit b10ce2f9dd
11 changed files with 40 additions and 13 deletions
+22 -1
View File
@@ -436,7 +436,28 @@ export const MessageView = memo(function MessageView({ email: e, expanded, wasUn
{e.inReplyTo?.length ? <><dt>{translate("In-Reply-To")}</dt><dd className="mono small">{e.inReplyTo.join(" ")}</dd></> : null}
{e.references?.length ? <><dt>{translate("References")}</dt><dd className="mono small">{e.references.join(" ")}</dd></> : null}
</dl>
<p className="hint">{translate("Use “Show original” for the complete raw message.")}</p>
{/*
* The action, not a description of where to find it. Telling somebody
* an action exists and leaving them to hunt for it is half a job
* (#236) -- and one dialog replaces the other, so it reads as going
* deeper rather than as opening a second window.
*
* `tNode` rather than two `translate` calls around a button: the
* sentence stays whole for whoever translates it, and languages that
* put the verb elsewhere can move the hole.
*/}
<p className="hint">
{tNode("Use {action} for the complete raw message.", {
action: (
<button
className="link-btn"
onClick={() => { setShowHeaders(false); void openSource(); }}
>
{translate("Show original")}
</button>
),
})}
</p>
</Dialog>
</article>
);