Threema UX: static file middleware fix, *AIAGENT display, info banner
All checks were successful
Build and Push / build (push) Successful in 1m26s
All checks were successful
Build and Push / build (push) Successful in 1m26s
This commit is contained in:
@@ -225,24 +225,47 @@ export function ChannelUsers({
|
||||
className="bg-surface-2 border border-border rounded-lg p-4"
|
||||
>
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<h4 className="text-sm font-medium text-text-primary capitalize">
|
||||
{channel}
|
||||
</h4>
|
||||
{channel === "threema" && (
|
||||
<button
|
||||
onClick={() => setShowQrFor("threema")}
|
||||
className="text-xs font-medium text-accent hover:text-accent-dim cursor-pointer underline underline-offset-2"
|
||||
>
|
||||
{t("threemaSetup.showQr")}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
<h4 className="text-sm font-medium text-text-primary capitalize">
|
||||
{channel}
|
||||
</h4>
|
||||
<span className="text-xs text-text-muted tabular-nums">
|
||||
{users.length} {t("users")}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{channel === "threema" && (
|
||||
<div className="mb-3 flex flex-col sm:flex-row gap-3 items-start sm:items-center justify-between bg-accent/5 border border-accent/30 rounded-lg p-3">
|
||||
<div className="flex items-start gap-2 flex-1">
|
||||
<svg
|
||||
className="w-4 h-4 mt-0.5 text-accent flex-shrink-0"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M3 4a1 1 0 011-1h4a1 1 0 011 1v4a1 1 0 01-1 1H4a1 1 0 01-1-1V4zM15 4a1 1 0 011-1h4a1 1 0 011 1v4a1 1 0 01-1 1h-4a1 1 0 01-1-1V4zM3 16a1 1 0 011-1h4a1 1 0 011 1v4a1 1 0 01-1 1H4a1 1 0 01-1-1v-4zM13 13h3v3h-3zM18 13h3v3h-3zM13 18h3v3h-3zM18 18h3v3h-3z"
|
||||
/>
|
||||
</svg>
|
||||
<div className="text-xs text-text-secondary leading-relaxed">
|
||||
<p className="font-medium text-text-primary mb-0.5">
|
||||
{t("threemaSetup.bannerTitle")}
|
||||
</p>
|
||||
<p>{t("threemaSetup.bannerBody")}</p>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => setShowQrFor("threema")}
|
||||
className="self-stretch sm:self-auto px-3 py-2 text-xs font-medium bg-accent text-surface-0 rounded-lg hover:bg-accent-dim transition-colors whitespace-nowrap cursor-pointer shadow-lg shadow-accent/20"
|
||||
>
|
||||
{t("threemaSetup.bannerButton")}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{helpKey && (
|
||||
<p className="text-xs text-text-secondary bg-surface-1 border border-border rounded-lg p-3 mb-3 whitespace-pre-line">
|
||||
{t(helpKey)}
|
||||
|
||||
@@ -13,21 +13,19 @@
|
||||
* env var that lists the active account.
|
||||
* 2. Move the QR PNG into a server-rendered route that takes a
|
||||
* gateway ID query param.
|
||||
* 3. Update consumers (today only ThreemaSetup) to accept the
|
||||
* gateway info as a prop and pass it from a server component.
|
||||
*
|
||||
* In display contexts we strip the leading asterisk from the Threema
|
||||
* ID — customers don't understand the `*X` prefix convention used for
|
||||
* Gateway accounts, and the QR code carries the real value anyway. We
|
||||
* keep the asterisk only for places where the technical value matters
|
||||
* (server-side message routing, debug logs).
|
||||
* 3. Update consumers to accept the gateway info as a prop and pass
|
||||
* it from a server component.
|
||||
*/
|
||||
|
||||
export const THREEMA_GATEWAY = {
|
||||
/** Technical Threema Gateway ID, with leading asterisk. */
|
||||
id: "*AIAGENT",
|
||||
/** Display name shown to customers (no asterisk). */
|
||||
displayName: "AIAGENT",
|
||||
/**
|
||||
* Display name shown to customers. INCLUDES the leading asterisk —
|
||||
* customers need to recognise this exact string in their Threema
|
||||
* contacts after scanning the QR, so we don't strip it.
|
||||
*/
|
||||
displayName: "*AIAGENT",
|
||||
/** Public path to the QR code PNG served from `public/`. */
|
||||
qrCodePath: "/threema/qr_code_AIAGENT.png",
|
||||
} as const;
|
||||
|
||||
@@ -403,7 +403,9 @@
|
||||
"step2": "Tippen Sie auf das Scan-Symbol und scannen Sie diesen QR-Code, um den Assistenten als Kontakt hinzuzufügen.",
|
||||
"step3": "Fügen Sie anschliessend unten Ihre eigene Threema-ID hinzu.",
|
||||
"qrAlt": "QR-Code, um {gateway} als Threema-Kontakt hinzuzufügen",
|
||||
"showQr": "QR anzeigen"
|
||||
"bannerTitle": "Threema einrichten",
|
||||
"bannerBody": "Öffnen Sie Threema auf Ihrem Telefon und scannen Sie unseren QR-Code, um den Assistenten als Kontakt hinzuzufügen. Geben Sie anschliessend unten Ihre eigene Threema-ID ein.",
|
||||
"bannerButton": "QR-Code anzeigen"
|
||||
}
|
||||
},
|
||||
"team": {
|
||||
|
||||
@@ -403,7 +403,9 @@
|
||||
"step2": "Tap the scan icon and scan this QR code to add the assistant as a contact.",
|
||||
"step3": "Then add your own Threema ID below.",
|
||||
"qrAlt": "QR code to add {gateway} as a Threema contact",
|
||||
"showQr": "Show QR"
|
||||
"bannerTitle": "Set up Threema",
|
||||
"bannerBody": "Open Threema on your phone and scan our QR code to add the assistant as a contact. Then add your own Threema ID below.",
|
||||
"bannerButton": "Show QR code"
|
||||
}
|
||||
},
|
||||
"team": {
|
||||
|
||||
@@ -403,7 +403,9 @@
|
||||
"step2": "Appuyez sur l'icône de scan et scannez ce QR code pour ajouter l'assistant comme contact.",
|
||||
"step3": "Puis ajoutez votre propre identifiant Threema ci-dessous.",
|
||||
"qrAlt": "QR code pour ajouter {gateway} comme contact Threema",
|
||||
"showQr": "Afficher le QR"
|
||||
"bannerTitle": "Configurer Threema",
|
||||
"bannerBody": "Ouvrez Threema sur votre téléphone et scannez notre QR code pour ajouter l'assistant comme contact. Saisissez ensuite votre propre identifiant Threema ci-dessous.",
|
||||
"bannerButton": "Afficher le QR code"
|
||||
}
|
||||
},
|
||||
"team": {
|
||||
|
||||
@@ -403,7 +403,9 @@
|
||||
"step2": "Tocca l'icona di scansione e scansiona questo QR code per aggiungere l'assistente ai contatti.",
|
||||
"step3": "Quindi aggiungi il tuo ID Threema qui sotto.",
|
||||
"qrAlt": "QR code per aggiungere {gateway} come contatto Threema",
|
||||
"showQr": "Mostra QR"
|
||||
"bannerTitle": "Configura Threema",
|
||||
"bannerBody": "Apri Threema sul tuo telefono e scansiona il nostro QR code per aggiungere l'assistente ai contatti. Inserisci poi il tuo ID Threema qui sotto.",
|
||||
"bannerButton": "Mostra QR code"
|
||||
}
|
||||
},
|
||||
"team": {
|
||||
|
||||
@@ -40,5 +40,10 @@ export default async function middleware(request: NextRequest) {
|
||||
}
|
||||
|
||||
export const config = {
|
||||
matcher: ["/((?!_next|favicon.ico|api).*)"],
|
||||
// Excludes _next/* internal routes, the favicon, api routes, AND any
|
||||
// path containing a dot (covers all static files served from public/,
|
||||
// e.g. /threema/qr_code_AIAGENT.png). Without the dot exclusion, the
|
||||
// i18n middleware prepends the locale ("/en/threema/qr_code_AIAGENT.png")
|
||||
// and the file is not found.
|
||||
matcher: ["/((?!_next|favicon.ico|api|.*\\..*).*)"],
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user