Changeset cca2e89 in Klonkt


Ignore:
Timestamp:
06/28/2026 01:15:39 PM (2 months ago)
Author:
Robin Genis <roboburr@…>
Branches:
main
Children:
9910ba1
Parents:
931b4cb
Message:

feat(identity): one image — the site photo is the only avatar input

Removed the separate account-avatar upload. A user's avatar everywhere (nav, account, profile
header, fediverse) is now their SITE photo, set in one place (site settings). The account page
shows it read-only with a link.

  • middleware/render.js — nav avatar = site photo always; drop the account-avatar cross-fallback
  • views/pages/account.ejs — remove the avatar upload; read-only site photo + hint to site settings
  • services/i18n.js — acct.photo_site_hint (nl/en/de)
Location:
src
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • src/middleware/render.js

    r931b4cb rcca2e89  
    7171  // avatar change or role switch) heals itself without a new login.
    7272  if (_u && _u.id) {
    73     const _fresh = db.prepare('SELECT avatar_url, role, lang FROM users WHERE id = ?').get(_u.id);
    74     if (_fresh) _u = { ..._u, avatar_url: _fresh.avatar_url, role: _fresh.role, lang: _fresh.lang };
    75     // One identity: no own account avatar → fall back to the user's site photo,
    76     // so the same picture shows everywhere (nav, account, comments).
    77     if (_u && !_u.avatar_url) {
    78       const _sp = db.prepare("SELECT profile_photo FROM sites WHERE owner_id = ? AND profile_photo IS NOT NULL ORDER BY is_primary DESC, created_at ASC LIMIT 1").get(_u.id);
    79       if (_sp && _sp.profile_photo) _u = { ..._u, avatar_url: _sp.profile_photo };
    80     }
     73    const _fresh = db.prepare('SELECT role, lang FROM users WHERE id = ?').get(_u.id);
     74    if (_fresh) _u = { ..._u, role: _fresh.role, lang: _fresh.lang };
     75    // ONE image: a user's avatar everywhere (nav, account, comments) is simply their SITE
     76    // photo — there is no separate account avatar. Falls back to the initial-letter
     77    // placeholder when the site has no photo yet.
     78    const _sp = db.prepare("SELECT profile_photo FROM sites WHERE owner_id = ? AND profile_photo IS NOT NULL ORDER BY is_primary DESC, created_at ASC LIMIT 1").get(_u.id);
     79    _u = { ..._u, avatar_url: (_sp && _sp.profile_photo) || null };
    8180  }
    8281  const userOwnsSite = !!(_u && _u.role !== 'god' &&
    8382    db.prepare('SELECT 1 FROM sites WHERE owner_id = ? LIMIT 1').get(_u.id));
    8483
    85   // The avatar of the SITE OWNER (not the viewer!) — for the Klonkt site header,
    86   // so the artist can use their own account photo as the site photo.
    8784  const _site = data.site || res.locals.site || null;
    88   const siteOwnerAvatar = (_site && _site.owner_id)
    89     ? (db.prepare('SELECT avatar_url FROM users WHERE id = ?').get(_site.owner_id)?.avatar_url || null)
    90     : null;
     85  // The site header uses the SITE photo (site.profile_photo) — the one and only image,
     86  // set in site settings. (No separate account-avatar fallback anymore.)
     87  const siteOwnerAvatar = null;
    9188
    9289  // Viewer mode: may view everything, change nothing. Views use canMutate
  • src/services/i18n.js

    r931b4cb rcca2e89  
    733733    'acct.profile': 'Profiel',
    734734    'acct.avatar_change': 'Klik om je foto te wijzigen',
    735     'acct.member_since': 'Lid sinds',
     735    'acct.member_since': 'Lid sinds', 'acct.photo_site_hint': 'Je profielfoto stel je in bij je <a href="/admin">site-instellingen</a> — één foto, overal gebruikt.',
    736736    'acct.avatar_remove': 'Foto verwijderen',
    737737    'acct.username': 'Gebruikersnaam',
     
    16431643    'acct.profile': 'Profile',
    16441644    'acct.avatar_change': 'Click to change your photo',
    1645     'acct.member_since': 'Member since',
     1645    'acct.member_since': 'Member since', 'acct.photo_site_hint': 'Your profile photo is set in your <a href="/admin">site settings</a> — one photo, used everywhere.',
    16461646    'acct.avatar_remove': 'Remove photo',
    16471647    'acct.username': 'Username',
     
    25532553    'acct.profile': 'Profil',
    25542554    'acct.avatar_change': 'Zum Ändern deines Fotos klicken',
    2555     'acct.member_since': 'Mitglied seit',
     2555    'acct.member_since': 'Mitglied seit', 'acct.photo_site_hint': 'Dein Profilbild legst du in den <a href="/admin">Site-Einstellungen</a> fest — ein Bild für überall.',
    25562556    'acct.avatar_remove': 'Foto entfernen',
    25572557    'acct.username': 'Benutzername',
  • src/views/pages/account.ejs

    r931b4cb rcca2e89  
    2727
    2828    <div class="ax-profile-id">
    29       <% if (canMutate) { %>
    30         <form action="/account/avatar" method="post" enctype="multipart/form-data" class="ax-avatar-form">
    31           <label class="ax-avatar-wrap" title="<%= t('acct.avatar_change') %>">
    32             <span class="ax-profile-avatar">
    33               <% var _av = account.avatar_url || (typeof siteAvatar !== 'undefined' ? siteAvatar : null); %>
    34               <% if (_av) { %>
    35                 <img src="<%= _av %>" alt="">
    36               <% } else { %>
    37                 <span><%= account.username.charAt(0).toUpperCase() %></span>
    38               <% } %>
    39             </span>
    40             <span class="ax-avatar-edit" aria-hidden="true">
    41               <svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"/><circle cx="12" cy="13" r="4"/></svg>
    42             </span>
    43             <input type="file" name="avatar" accept="image/jpeg,image/png,image/webp,image/gif" onchange="this.form.submit()" hidden>
    44           </label>
    45         </form>
    46       <% } else { %>
    47         <span class="ax-profile-avatar ax-profile-avatar-static">
    48           <% var _av2 = account.avatar_url || (typeof siteAvatar !== 'undefined' ? siteAvatar : null); %>
    49           <% if (_av2) { %>
    50             <img src="<%= _av2 %>" alt="">
    51           <% } else { %>
    52             <span><%= account.username.charAt(0).toUpperCase() %></span>
    53           <% } %>
    54         </span>
    55       <% } %>
     29      <span class="ax-profile-avatar ax-profile-avatar-static">
     30        <% var _av = (typeof siteAvatar !== 'undefined' ? siteAvatar : null); %>
     31        <% if (_av) { %>
     32          <img src="<%= _av %>" alt="">
     33        <% } else { %>
     34          <span><%= account.username.charAt(0).toUpperCase() %></span>
     35        <% } %>
     36      </span>
    5637      <div class="ax-profile-meta">
    5738        <div class="ax-profile-name"><%= account.username %></div>
     
    6041          <div class="ax-profile-joined"><%= t('acct.member_since') %> <%= formatDate(account.created_at) %></div>
    6142        <% } %>
    62         <% if (account.avatar_url && canMutate) { %>
    63           <form action="/account/avatar/remove" method="post" class="ax-avatar-remove">
    64             <button type="submit" class="ax-linkbtn"><%= t('acct.avatar_remove') %></button>
    65           </form>
     43        <% if (canMutate) { %>
     44          <div class="ax-profile-joined"><%- t('acct.photo_site_hint') %></div>
    6645        <% } %>
    6746      </div>
Note: See TracChangeset for help on using the changeset viewer.