Public landing, owner-list links, owner-conditional semi, PWA + mobile
Four related UX/privacy/install changes.
1. **Logged-out lands on the public list.** The root route now shows the
same Home view as a logged-in user, minus their own private rows and
the "Ny aktivitet" button. The nav exposes a "Logg inn" button when
no session is present. Login becomes one click away, not the forced
landing — anyone can browse the public + semi list anonymously.
2. **Public activities link to /<owner_username>/list.** When a public
activity's owner has opted into a public list, the "Lagt til av X"
line renders X as a link to /<username>/list. Server populates
`owner_username` on every public-row serialisation (null when the
owner hasn't opted in, so the client just renders plain text).
3. **Conditional owner_id on semi rows.** The server now serialises
`owner_id` on a semi row ONLY when the viewer IS the owner. The
wire type's `ActivitySemi.owner_id` is therefore optional. This
solves the semi-delete UX without leaking attribution: owners see
Edit/Delete buttons on their own semi rows; non-owners get the same
bare row they got before. The privacy property is enforced at the
API boundary, not in client-side render logic.
4. **Mobile-friendly + installable PWA.**
- `manifest.webmanifest` with name, theme color, standalone display,
and a maskable SVG icon (icon.svg).
- Service worker (sw.js): cache-first for the bundled shell;
network-only for /api/* (we never cache session-dependent or
ciphertext data — see the comment in sw.js for the rationale).
Falls back to the SPA shell for navigation requests when offline.
- SW registered in main.ts only in production builds (import.meta.env.PROD).
- viewport-fit=cover + env(safe-area-inset-*) padding so content
doesn't slip under iOS notches when installed.
- WCAG 2.5.5 touch-target sizing: min-height: 44px on buttons,
with an explicit opt-out for tag-close buttons (24×24 still meets
the 2.5.8 minimum).
- 16px font on form inputs below 480px so iOS doesn't auto-zoom.
Server-side: server/index.ts now serves manifest, icon, and sw.js
from frontend/dist alongside /assets/*. The catch-all still serves
index.html so the SPA's /<username>/list path routing keeps working.
Smoke-tested with a production-mode server: manifest returns the
correct application/manifest+json MIME, SVG renders, sw.js is
loadable, and unknown paths fall through to index.html as expected.
26 tests still pass; both tsconfigs typecheck (frontend now pulls
vite/client types for import.meta.env.PROD); Vite build succeeds.
This commit is contained in:
parent
6f4c11c7a6
commit
f0b4d735b5
15 changed files with 317 additions and 54 deletions
17
README.md
17
README.md
|
|
@ -126,6 +126,23 @@ podman run --replace --name vinterliste \
|
|||
The container exposes `/api/health` for healthchecks and bakes the build date /
|
||||
git revision into both OCI labels and `/etc/build-info`.
|
||||
|
||||
## Installable (PWA) + mobile
|
||||
|
||||
The SPA ships with a web app manifest (`/manifest.webmanifest`), an SVG icon
|
||||
(`/icon.svg`), and a small service worker (`/sw.js`) that caches the bundled
|
||||
shell for offline reads. The API itself is **never** cached — sessions and
|
||||
ciphertexts must come fresh from the server. On supported browsers
|
||||
(Chrome/Edge on Android and desktop, Firefox with the flag) you'll see an
|
||||
"Install" prompt; on iOS you can Add to Home Screen but iOS doesn't render
|
||||
SVG icons, so the home-screen icon will fall back to the page screenshot.
|
||||
|
||||
Layout adapts to small screens via:
|
||||
|
||||
- `viewport` set to `width=device-width, initial-scale=1, viewport-fit=cover`
|
||||
- safe-area insets in `padding` so content doesn't slip under iOS notches
|
||||
- `min-height: 44px` on buttons (WCAG 2.5.5 enhanced touch target)
|
||||
- `font-size: 16px` on inputs below 480px so iOS doesn't auto-zoom
|
||||
|
||||
## Promoting a moderator
|
||||
|
||||
Moderators can delete any `semi` or `public` activity (not `private` — those
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue