diff --git a/frontend/src/App.svelte b/frontend/src/App.svelte index efb3a5a..5e43b31 100644 --- a/frontend/src/App.svelte +++ b/frontend/src/App.svelte @@ -168,7 +168,7 @@ {:else if view !== 'login' && view !== 'signup' && view !== 'recovery'} diff --git a/frontend/src/components/ActivityRow.svelte b/frontend/src/components/ActivityRow.svelte index 3bae7e8..81673fe 100644 --- a/frontend/src/components/ActivityRow.svelte +++ b/frontend/src/components/ActivityRow.svelte @@ -211,7 +211,7 @@ {@render locationLine(activity.loc_label, activity.loc_lat, activity.loc_lng)} {/if} {#if activity.scheduled_at}

🕒 {formatDate(activity.scheduled_at)}

{/if} - {#if activity.visibility === 'public'} + {#if activity.visibility === 'public' && activity.owner_display}

Lagt til av {#if activity.owner_username} diff --git a/frontend/src/components/Home.svelte b/frontend/src/components/Home.svelte index fe75953..7d0b4e2 100644 --- a/frontend/src/components/Home.svelte +++ b/frontend/src/components/Home.svelte @@ -117,8 +117,11 @@

{:else if session.user}

- Velkommen, {session.user.display_name?.trim() || session.user.email}. - Her er aktivitetene dine for vinteren. + {#if session.user.display_name?.trim()} + Velkommen, {session.user.display_name}. Her er aktivitetene dine for vinteren. + {:else} + Her er aktivitetene dine for vinteren. + {/if}

{#if !showForm && !editing} diff --git a/server/activities.ts b/server/activities.ts index a9bac9b..2dc5a3b 100644 --- a/server/activities.ts +++ b/server/activities.ts @@ -66,16 +66,29 @@ function heartsFor(activityId: string, viewerId: string | null): { count: number return { count, hearted }; } -function ownerAttribution(ownerId: string): { display: string; username: string | null } { +/** + * Build the public-facing attribution for an owner. Prefer the user's chosen + * `display_name`; fall back to their `username` slug if set (also user-chosen); + * otherwise return null so the client hides attribution entirely. We + * deliberately do NOT fall back to the email or any prefix of it — that's a + * contact identifier the user didn't elect to surface. + * + * `username` (the link target) is returned independently and is only non-null + * when the owner has opted into a public list — drives whether the + * attribution renders as a link to //list. + */ +function ownerAttribution(ownerId: string): { display: string | null; username: string | null } { const row = getDb() - .prepare('SELECT display_name, email, username, public_list_enabled FROM users WHERE id = ?') + .prepare('SELECT display_name, username, public_list_enabled FROM users WHERE id = ?') .get(ownerId) as - | { display_name: string | null; email: string; username: string | null; public_list_enabled: number | null } + | { display_name: string | null; username: string | null; public_list_enabled: number | null } | null; - if (!row) return { display: 'ukjent', username: null }; + if (!row) return { display: null, username: null }; const display = (row.display_name && row.display_name.trim()) ? row.display_name - : (row.email.indexOf('@') > 0 ? row.email.slice(0, row.email.indexOf('@')) : row.email); + : (row.username && row.username.trim()) + ? row.username + : null; const username = row.public_list_enabled === 1 ? row.username : null; return { display, username }; } diff --git a/server/users.ts b/server/users.ts index d2f8e2b..0e31cf0 100644 --- a/server/users.ts +++ b/server/users.ts @@ -57,7 +57,9 @@ usersRoutes.get('/:username/list', (c) => { id: r.id, visibility: 'public', owner_id: r.owner_id, - owner_display: user.display_name?.trim() || username, + // Prefer the display name; fall back to the username slug (which is + // what the URL already shows). Never falls through to email/id. + owner_display: (user.display_name && user.display_name.trim()) || username, // The list itself is at //list, so we already know the slug. // Surfacing it on each row keeps ActivityRow's rendering uniform. owner_username: username, diff --git a/shared/types.ts b/shared/types.ts index bec887e..546b371 100644 --- a/shared/types.ts +++ b/shared/types.ts @@ -173,7 +173,13 @@ export interface ActivityPublic { id: string; visibility: 'public'; owner_id: string; // serialized for public - owner_display: string; // display_name OR derived handle (email prefix) + /** + * Public-facing handle: display_name OR (when only the slug is set) the + * username. NULL when the owner has set neither — in that case the client + * hides attribution entirely rather than falling back to the email or to + * an identifier the user didn't choose. + */ + owner_display: string | null; // Owner's URL slug, if they've opted into a public list. When non-null, the // client renders the owner attribution as a link to //list. owner_username: string | null;