fix(copy): five texts that told guests the wrong thing
None of these are cosmetic — each one either misdescribes the UI or omits
something a guest needs to get back into their account.
JOIN. "Willkommen bei" + "<Event>" read as "Willkommen bei Hochzeit von …".
Adds the article. This deliberately couples the lead-in to EVENT_NAME's
grammatical gender and is wrong for "Willkommen bei der Sommerfest" — noted in
the markup, with the article-free alternative, for whoever reuses this. The
no-name fallback moves from "dem Event" to "Feier", or it would now render
"Willkommen bei der dem Event".
GUIDE / post actions. Named only the long-press, which is invisible: a guest has
to already know it exists to find it. Now names the three-dot button that is on
every card in list view — described as "die drei Punkte (⋯)" rather than a
glyph, because the icon renders HORIZONTALLY (three circles at cy=12) despite
the code comment calling it a kebab. Long-press stays in the text, because the
button exists ONLY in the list view: the grid tiles have `use:longpress` and no
button at all, so a menu-only instruction would strand anyone browsing in grid
mode. "anzeigen und speichern", not "herunterladen" — the action opens the
original inline in a new tab (Content-Disposition: inline, deliberate, it is the
only playable video source), so the guest saves it from there.
GUIDE / recovery. Said "Deinen PIN merken!", but `POST /recover` takes
{display_name, pin} — a guest who memorised four digits and forgot whether they
typed "Anna" or "Anna M." still cannot get in. Now names both. It also claimed
the PIN is "immer unter Mein Konto zu finden", which is false in the only case
that matters: /account renders it from local storage and falls back to "PIN
nicht gespeichert", so it is NOT on the new device you are trying to reach.
UPLOAD / photo-task game. Adds a persistent helper line under the caption box
rather than a second placeholder line: a `placeholder` attribute may not contain
line breaks (Safari collapses them), and a placeholder disappears exactly when
the guest starts typing and needs it. The hashtag is written plain on purpose —
`#fotoaufgabe3` is a DIFFERENT tag from `#fotoaufgabe`, so putting the number
inside it would turn twelve tasks into twelve unfilterable tags.
UPLOAD SHEET. "Öffne den Link in Safari oder Chrome" named a link that is not on
screen — the guest is already inside the app. Now names the situation (the
WhatsApp in-app browser the join link opens in) and the menu entry that escapes
it. Kept rather than removed: in that webview the camera and file picker can
silently do nothing, with no error and no operator to ask.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -41,8 +41,19 @@
|
||||
{
|
||||
kind: 'text',
|
||||
icon: '👆',
|
||||
title: 'Lange tippen für mehr',
|
||||
body: 'Tippe lange auf ein Bild im Feed, um zusätzliche Aktionen zu öffnen — zum Beispiel das Original anzeigen oder eigene Beiträge löschen.'
|
||||
title: 'Mehr zu einem Foto',
|
||||
// Names the VISIBLE control first. Long-press was the only affordance mentioned here,
|
||||
// and it is invisible — a guest has to already know it exists. The three-dot button
|
||||
// is on every card in list view and is what most people will find.
|
||||
//
|
||||
// Both views are named on purpose: the button exists only in the LIST view
|
||||
// (FeedListCard). The grid tiles have no button at all, only `use:longpress`, so a
|
||||
// guest browsing in grid mode would be stranded by a menu-only instruction.
|
||||
//
|
||||
// "anzeigen und speichern", not "herunterladen": the action opens the original in a
|
||||
// new tab (`Content-Disposition: inline`, deliberate — it is the only playable video
|
||||
// source), so the guest saves it from there rather than getting a download.
|
||||
body: 'Tippe oben rechts am Beitrag auf die drei Punkte (⋯), um weitere Aktionen zu öffnen: das Original in voller Auflösung anzeigen und speichern oder eigene Beiträge löschen. In der Kachel-Ansicht tippst du stattdessen lange auf ein Bild.'
|
||||
},
|
||||
{
|
||||
kind: 'theme',
|
||||
@@ -52,9 +63,18 @@
|
||||
{
|
||||
kind: 'text',
|
||||
icon: '🔑',
|
||||
title: 'Deinen PIN merken!',
|
||||
title: 'Name und PIN merken!',
|
||||
// Recovery needs BOTH the display name and the PIN (`POST /recover` takes
|
||||
// {display_name, pin}), but this step only ever mentioned the PIN — so a guest who
|
||||
// memorised four digits and forgot whether they typed "Anna" or "Anna M." still
|
||||
// could not get back in.
|
||||
//
|
||||
// "solange du auf diesem Gerät angemeldet bleibst" replaces "ist immer … zu finden",
|
||||
// which was false in exactly the case that matters: /account renders the PIN from
|
||||
// local storage and falls back to "PIN nicht gespeichert", so it is NOT there on a
|
||||
// new device — which is the only reason anyone needs it.
|
||||
body:
|
||||
'Du hast beim Registrieren einen 4-stelligen PIN erhalten. Speichere ihn — du brauchst ihn, um dein Konto auf einem anderen Gerät wiederherzustellen. Er ist immer unter „Mein Konto“ zu finden.' +
|
||||
'Beim Registrieren hast du einen 4-stelligen PIN bekommen. Für die Anmeldung auf einem anderen Gerät brauchst du beides: genau den Namen, den du hier eingegeben hast, und diesen PIN. Notiere dir am besten beides — solange du auf diesem Gerät angemeldet bleibst, findest du sie unter „Mein Konto“.' +
|
||||
(hasPrivacyNote ? ' Den Datenschutzhinweis findest du ebenfalls unter „Mein Konto“.' : '')
|
||||
}
|
||||
]);
|
||||
|
||||
@@ -305,8 +305,14 @@
|
||||
line of text and is never wrong. It lives here rather than in the root layout
|
||||
because both layout banners are gated on `$showBottomNav`, which `/upload` turns
|
||||
off — a banner there would never render on the composer. -->
|
||||
<!-- "diese Seite", not "den Link": the guest is already inside the app when they read
|
||||
this, so there is no link on screen for "den Link" to refer to. Naming the app
|
||||
they most likely arrived from, and the menu entry that gets them out, turns a
|
||||
hint they cannot act on into an instruction they can. -->
|
||||
<p class="px-1 pt-1 text-center text-xs text-gray-500 dark:text-gray-400">
|
||||
Nichts passiert beim Tippen? Öffne den Link in Safari oder Chrome.
|
||||
Nichts passiert beim Tippen? Dann bist du wahrscheinlich im Browser von WhatsApp o. Ä.
|
||||
Öffne diese Seite in Safari oder Chrome — dort funktionieren Kamera und Galerie. (Im Menü
|
||||
des In-App-Browsers: „In Safari öffnen“ bzw. „Im Browser öffnen“.)
|
||||
</p>
|
||||
{/if}
|
||||
|
||||
|
||||
@@ -309,8 +309,15 @@
|
||||
{/if}
|
||||
{:else}
|
||||
<!-- Normal join form -->
|
||||
<!-- The article is HARDCODED to match this event's name ("Hochzeit von …"), so the
|
||||
lead-in and the <h1> below read as one sentence: "Willkommen bei der Hochzeit
|
||||
von …". That couples this string to EVENT_NAME's grammatical gender — it is
|
||||
wrong for "Willkommen bei der Sommerfest". Deliberate for a single event; if
|
||||
this app is reused, either make the article configurable alongside EVENT_NAME
|
||||
or drop back to an article-free lead-in ("Herzlich willkommen!"), which works
|
||||
with any name. The fallback below must keep agreeing with whatever is chosen. -->
|
||||
<p class="mb-1 text-center text-sm font-medium text-gray-500 dark:text-gray-400">
|
||||
Willkommen bei
|
||||
Willkommen bei der
|
||||
</p>
|
||||
{#if eventName}
|
||||
<h1
|
||||
@@ -320,8 +327,10 @@
|
||||
{eventName}
|
||||
</h1>
|
||||
{:else}
|
||||
<!-- "Feier", not "dem Event": the lead-in above now carries the article, so the
|
||||
old fallback would render "Willkommen bei der dem Event". -->
|
||||
<h1 class="mb-3 text-center text-3xl font-semibold text-gray-900 dark:text-gray-100">
|
||||
dem Event
|
||||
Feier
|
||||
</h1>
|
||||
{/if}
|
||||
<p class="mb-6 text-center text-gray-600 dark:text-gray-400">
|
||||
|
||||
@@ -308,6 +308,18 @@
|
||||
rows="4"
|
||||
class="input resize-none text-sm"
|
||||
></textarea>
|
||||
<!-- Persistent helper, NOT a second placeholder line. Two reasons: a `placeholder`
|
||||
attribute may not contain line breaks (Safari collapses them outright), and a
|
||||
placeholder disappears the moment the guest starts typing — which is exactly when
|
||||
they need to read what to write. This stays visible while they type.
|
||||
The hashtag is written plain on purpose: `#fotoaufgabe3` would be a DIFFERENT tag
|
||||
from `#fotoaufgabe`, so twelve tasks would produce twelve unfilterable tags. The
|
||||
number belongs in the prose, the hashtag stays one word. -->
|
||||
<p class="mt-1.5 text-xs leading-snug text-gray-500 dark:text-gray-400">
|
||||
<span class="font-semibold text-gray-600 dark:text-gray-300">Fotoaufgabe?</span> Schreib
|
||||
die Aufgabe dazu — die Nummer steht unten rechts auf dem Kärtchen am Tisch — und setze den
|
||||
Hashtag #fotoaufgabe.
|
||||
</p>
|
||||
<div class="mt-1 text-xs text-gray-500 text-right dark:text-gray-400">
|
||||
{caption.length} / {MAX_CAPTION_LENGTH}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user