Files
ihasmail/web/src/lib/brand.ts
T
jcoffey 07b39eb9b6 Call the app by its name in every sentence that names it (#406)
APP_NAME renames an instance, but only the sign-in page, the title bar and
a few headings used it. Two dozen sentences wrote "ihasmail" into
themselves, so a renamed instance still told people to keep an ihasmail
tab open and offered to open mail links "in ihasmail".

Those sentences now take the name as {app}, which also lets a translator
put it where their language wants it. brand.ts grew useAppName() for
components and currentAppName() for the few places that build strings
outside React.

Left as they are: the Files folder "ihasmail", the Sieve script
"ihasmail" and ihasmail.org. Those name things a person can go and look
at, and renaming them would rename real data.

All nine catalogues keep their translations: the name inside each one
became the placeholder. Three of the strings had no translation before
and still fall back to English.

A test walks the sources and the catalogues so a new sentence can't
hard-code the name again.
2026-09-19 14:27:34 -07:00

38 lines
1.5 KiB
TypeScript

import { useSession } from "@/store/session";
/**
* What this instance calls itself, when nothing has said otherwise yet.
*
* `APP_NAME` is a runtime environment variable, so the real answer arrives
* from the server -- on `/api/config` before anybody signs in, and on the
* session afterwards. This is what stands in until it does, and what stands
* for good if the request fails: a sign-in form with no name on it would be
* worse than one with the wrong name.
*
* One constant rather than the string written out at each of them, because
* three copies of a default is how two of them end up stale.
*/
export const DEFAULT_APP_NAME = "ihasmail";
/**
* What this instance calls itself, right now.
*
* Text that names the app reads it from here rather than writing "ihasmail"
* into the sentence, so an instance renamed with `APP_NAME` is called by its
* name everywhere, not only on the sign-in page and in the title bar. The
* name goes into the sentence as the `{app}` placeholder, which also lets a
* translator put it where their language wants it.
*
* Two shapes for the same fact: the hook for components, and the plain
* function for the few places that build strings outside React (the service
* worker's facts, for one). Both fall back to the default until the session
* arrives.
*/
export function useAppName(): string {
return useSession((s) => s.session?.ihasmail?.appName)?.trim() || DEFAULT_APP_NAME;
}
export function currentAppName(): string {
return useSession.getState().session?.ihasmail?.appName?.trim() || DEFAULT_APP_NAME;
}