+ {t('crop.result', { + width: out.width, + height: out.height, + sourceWidth: image.width, + sourceHeight: image.height, + })} +
+{t('layout.sidebar.placeholder')}
) : ( diff --git a/apps/web/src/layout/TopBar.tsx b/apps/web/src/layout/TopBar.tsx index 558103d..214805b 100644 --- a/apps/web/src/layout/TopBar.tsx +++ b/apps/web/src/layout/TopBar.tsx @@ -6,6 +6,7 @@ import { useTranslation } from 'react-i18next'; import { Link, useNavigate } from 'react-router-dom'; import { useAuth } from '../auth/auth-context'; +import { useBranding } from '../branding/use-branding'; import { IconButton, IconLink } from '../components/IconButton'; import { apiGet } from '../lib/api'; import { isTypingTarget } from '../lib/keyboard'; @@ -67,6 +68,9 @@ export function TopBar({ sidebarCollapsed, onToggleSidebar }: TopBarProps): Reac enabled: Boolean(user && pondSlug), }); const isPondOwner = Boolean(user && pond.data && user.id === pond.data.ownerId); + // Instance identity (issue #306) — shared query, also read by the sidebar + // logo and reachable without a session (the login screen carries it). + const branding = useBranding(); async function handleLogout(): Promise{t('admin.intro')}
+ {/* An operator may not expect their logo to be readable by anyone who + opens the login page — so say it, rather than let them find out. */} +{t('admin.publicNote')}
+ ++ + {t('admin.darkMissing')} +
+ )} + +{t(`admin.logo.${variant}Hint`)}
+{t('admin.logo.current', { width: asset.width, height: asset.height })}
+ +{t('admin.logo.none')}
+ )} + +{upload.isPending ? t('admin.uploading') : ''}
+{t('admin.favicon.hint')}
+{present ? t('admin.favicon.present') : t('admin.favicon.default')}
+ {present && ( + + )} +{upload.isPending ? t('admin.uploading') : ''}
+