From 2d3be10c8f6c8feb0daa3d54c010526aa7a19baa Mon Sep 17 00:00:00 2001 From: Psychotoxical Date: Mon, 20 Apr 2026 22:26:58 +0200 Subject: [PATCH] feat(users): show last-access timestamp per user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Maps Navidrome's lastAccessAt onto NdUser and renders it in the User Management row as a localized relative time (Intl.RelativeTimeFormat with the current i18n language). Tooltip carries the absolute timestamp. Navidrome returns 0001-01-01 for never-accessed users — detected and shown as the localized "Never" label. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/api/navidromeAdmin.ts | 2 ++ src/locales/de.ts | 1 + src/locales/en.ts | 1 + src/locales/es.ts | 1 + src/locales/fr.ts | 1 + src/locales/nb.ts | 1 + src/locales/nl.ts | 1 + src/locales/ru.ts | 1 + src/locales/zh.ts | 1 + src/pages/Settings.tsx | 31 +++++++++++++++++++++++++++++-- 10 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/api/navidromeAdmin.ts b/src/api/navidromeAdmin.ts index 3383b061..91ddd2d8 100644 --- a/src/api/navidromeAdmin.ts +++ b/src/api/navidromeAdmin.ts @@ -13,6 +13,7 @@ export interface NdUser { isAdmin: boolean; libraryIds: number[]; lastLoginAt?: string | null; + lastAccessAt?: string | null; createdAt?: string; updatedAt?: string; } @@ -56,6 +57,7 @@ export async function ndListUsers(serverUrl: string, token: string): Promise([]); const [libraries, setLibraries] = useState([]); const [loading, setLoading] = useState(true); @@ -607,6 +624,10 @@ function UserManagementSection({ : u.libraryIds.length === 0 ? t('settings.userMgmtNoLibraries') : libraries.filter(l => u.libraryIds.includes(l.id)).map(l => l.name).join(', '); + const lastSeen = formatLastSeen(u.lastAccessAt, i18n.language, t('settings.userMgmtNeverSeen')); + const lastSeenAbsolute = u.lastAccessAt + ? new Date(u.lastAccessAt).toLocaleString(i18n.language) + : ''; return (
)} + + {lastSeen} +