diff --git a/README.md b/README.md index ed5fdad..da51801 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,22 @@ -# Threema UX v2 — QR available on demand +# Threema UX v3 — three real fixes -Replaces the previous attempt that had the QR rendering inline above -the channel help text. That placement didn't work for you in practice -because it wasn't visible when you actually wanted it. +## What this fixes vs v2 -## What this does instead - -1. **"Show QR" link** next to the channel title in the threema card — - visible at all times, clickable any time you want the QR. - -2. **Auto-opens the modal** the first time you focus the add-ID input - on the page (so a new user adding their first ID sees it without - needing to click "Show QR" themselves). Doesn't re-pop after - dismissal — the link covers re-opens. - -3. **Modal** with QR + 3-step instructions + "AIAGENT" label. Plain - `` (no next/image), closes on ESC / overlay click / × button. - -The earlier `threema-setup.tsx` component file is removed — replaced by -`threema-qr-modal.tsx`. +| # | Issue | Fix | +|---|-------|-----| +| 1 | QR image 404'd as `GET /en/threema/qr_code_AIAGENT.png` | Middleware matcher now excludes paths with file extensions, so static files in `public/` are not locale-prefixed | +| 2 | Displayed gateway name as `AIAGENT` (without asterisk) | `displayName` is now `*AIAGENT` (with asterisk) — what users actually see in their Threema contacts | +| 3 | "Show QR" hyperlink — too small, unclear what it does | Replaced with a proper accent-bordered info banner: icon + title + body explaining what to do + prominent "Show QR code" button | ## Files ``` -src/lib/threema-gateway-config.ts # unchanged from before — central gateway constants -src/components/channel-users/threema-qr-modal.tsx # NEW — the modal -src/components/channel-users/channel-users.tsx # MODIFIED — Show QR button + focus auto-open + modal mount -deploy/patch-i18n-threema.mjs # adds threemaSetup.showQr label in 4 langs -public/threema/qr_code_AIAGENT.png # unchanged +src/middleware.ts # MODIFIED — matcher excludes dot-paths (static files) +src/lib/threema-gateway-config.ts # MODIFIED — displayName: "*AIAGENT" +src/components/channel-users/channel-users.tsx # MODIFIED — banner replaces inline hyperlink +src/components/channel-users/threema-qr-modal.tsx # UNCHANGED from v2 (label now reads "*AIAGENT" automatically via config) +deploy/patch-i18n-threema.mjs # MODIFIED — new bannerTitle/bannerBody/bannerButton keys, showQr dropped +public/threema/qr_code_AIAGENT.png # UNCHANGED ``` ## Apply @@ -35,32 +24,54 @@ public/threema/qr_code_AIAGENT.png # unchanged ```bash cd /path/to/pieced-portal -# Remove the old inline component if you applied the previous archive -rm -f src/components/channel-users/threema-setup.tsx - -# Drop new + modified files -unzip -o /path/to/threema-ux-v2.zip - -# Update messages +unzip -o /path/to/threema-ux-v3.zip node deploy/patch-i18n-threema.mjs - -# TS check npx tsc --noEmit - git add -A -git commit -m "Threema QR: on-demand modal + auto-open on first add" +git status # eyeball +git commit -m "Threema UX: middleware static fix, *AIAGENT display, info banner" git push ``` -After redeploy, the threema card under Authorized Users shows: +## Layout after redeploy ``` -threema [Show QR] 0 users - ──────────────────── - - ──────────────────── - [ input: A8K2P3X7 ] [ Add ] - ^^^ focusing this opens the QR modal the first time +┌─────────────────────────────────────────────────────────┐ +│ threema 2 users │ +├─────────────────────────────────────────────────────────┤ +│ ╔═══════════════════════════════════════════════════════╗│ +│ ║ [icon] Set up Threema [ Show QR code ] ║│ ← prominent banner, accent border +│ ║ Open Threema on your phone and scan our ║│ +│ ║ QR code to add the assistant as a contact. ║│ +│ ║ Then add your own Threema ID below. ║│ +│ ╚═══════════════════════════════════════════════════════╝│ +├─────────────────────────────────────────────────────────┤ +│ │ +│ ┌───────┐ ┌───────┐ │ +│ │USER01 ✕│ │USER02 ✕│ │ +│ └───────┘ └───────┘ │ +│ [ A8K2P3X7 ] [ Add ] │ +└─────────────────────────────────────────────────────────┘ ``` -Clicking "Show QR" or focusing the input → modal with QR + steps. +The banner is always visible whenever the threema channel is enabled. +Clicking "Show QR code" opens the modal with the QR and 3-step +instructions. ESC, overlay click, or × button closes. + +Auto-open on first focus of the add-ID input is preserved from v2 — +the modal pops once when a customer clicks into the input to add their +first ID, so a brand-new customer who skipped the banner still gets +the QR right when they need it. + +## Verification + +After redeploy: + +1. Open `https://app.pieced.ch/en/tenants/acme-gmbh-2acf4612` in the browser. +2. Scroll to the **Authorized Users → threema** card. +3. Visible banner with icon, title "Set up Threema", body text, and a + clearly clickable "Show QR code" button on the right. +4. Click the button → modal with the QR shows. +5. The label under the QR reads `*AIAGENT` (with asterisk). +6. Browser DevTools → Network → `GET /threema/qr_code_AIAGENT.png` is + `200`, not `404`, and not redirected to `/en/threema/...`. diff --git a/deploy/patch-i18n-threema.mjs b/deploy/patch-i18n-threema.mjs index decdcc5..f1dcddb 100644 --- a/deploy/patch-i18n-threema.mjs +++ b/deploy/patch-i18n-threema.mjs @@ -37,7 +37,9 @@ const i18n = { 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", }, }, de: { @@ -57,7 +59,9 @@ const i18n = { 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", }, }, fr: { @@ -77,7 +81,9 @@ const i18n = { 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", }, }, it: { @@ -97,7 +103,9 @@ const i18n = { 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", }, }, }; diff --git a/src/components/channel-users/channel-users.tsx b/src/components/channel-users/channel-users.tsx index 02a2edf..e9b9781 100644 --- a/src/components/channel-users/channel-users.tsx +++ b/src/components/channel-users/channel-users.tsx @@ -225,24 +225,47 @@ export function ChannelUsers({ className="bg-surface-2 border border-border rounded-lg p-4" >
-
-

- {channel} -

- {channel === "threema" && ( - - )} -
+

+ {channel} +

{users.length} {t("users")}
+ {channel === "threema" && ( +
+
+ +
+

+ {t("threemaSetup.bannerTitle")} +

+

{t("threemaSetup.bannerBody")}

+
+
+ +
+ )} + {helpKey && (

{t(helpKey)} diff --git a/src/lib/threema-gateway-config.ts b/src/lib/threema-gateway-config.ts index 414d17f..27df94d 100644 --- a/src/lib/threema-gateway-config.ts +++ b/src/lib/threema-gateway-config.ts @@ -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; diff --git a/src/messages/de.json b/src/messages/de.json index 1b6988d..c744564 100644 --- a/src/messages/de.json +++ b/src/messages/de.json @@ -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": { diff --git a/src/messages/en.json b/src/messages/en.json index 63cd2a5..0a69aae 100644 --- a/src/messages/en.json +++ b/src/messages/en.json @@ -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": { diff --git a/src/messages/fr.json b/src/messages/fr.json index 490e77b..d582663 100644 --- a/src/messages/fr.json +++ b/src/messages/fr.json @@ -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": { diff --git a/src/messages/it.json b/src/messages/it.json index 5050e06..215d5b4 100644 --- a/src/messages/it.json +++ b/src/messages/it.json @@ -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": { diff --git a/src/middleware.ts b/src/middleware.ts index 2c1447d..902cec5 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -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|.*\\..*).*)"], };