mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-22 15:25:46 +00:00
4dc46e176a
* refactor(user-mgmt): extract formatLastSeen helper Move the relative-time formatter (with the Navidrome '0001-01-01T00:00:00Z' epoch guard) into utils/userMgmtHelpers.ts. UserManagementSection.tsx: 515 → 499 LOC. * refactor(user-mgmt): extract useUserMgmtData hook Pull users + libraries state, sequential admin-API fetch, and the nginx-friendly error normalisation into hooks/useUserMgmtData.ts. UserManagementSection.tsx: 499 → 464 LOC. * refactor(user-mgmt): extract useUserMgmtActions hook Bundle handleSave (covers create + edit + library assignment), handleSaveAndGetMagic (new non-admin user → encoded magic string on clipboard), and performDelete into hooks/useUserMgmtActions.ts. The delete confirmation modal now closes inline in the parent before delegating to performDelete so the hook stays agnostic of UI state. UserManagementSection.tsx: 464 → 343 LOC. * refactor(user-mgmt): extract UserMgmtRow subcomponent Move the per-user list row (user/admin badges, lib-names blob, magic- string + delete actions, keyboard activation) into components/settings/userMgmt/UserMgmtRow.tsx. UserManagementSection.tsx: 343 → 272 LOC. * refactor(user-mgmt): extract MagicStringModal subcomponent Move the per-user magic-string portal modal (password re-set + clipboard copy of the encoded server-magic-string) into components/settings/userMgmt/MagicStringModal.tsx. Internal password and submitting state move into the modal; the parent only owns which user is targeted. UserManagementSection.tsx: 272 → 153 LOC.
24 lines
1.3 KiB
TypeScript
24 lines
1.3 KiB
TypeScript
/**
|
|
* Render a relative time string like "3 hours ago" / "in 2 weeks" with
|
|
* the supplied locale. Navidrome returns `"0001-01-01T00:00:00Z"` for
|
|
* never-accessed users — that round-trips to year 1, which `Date.parse`
|
|
* turns into a wildly-negative epoch. We guard with a "is this after the
|
|
* year 2001-ish" sanity check and fall back to the `neverLabel` so the
|
|
* UI doesn't claim "2024 years ago".
|
|
*/
|
|
export function formatLastSeen(iso: string | null | undefined, locale: string, neverLabel: string): string {
|
|
if (!iso) return neverLabel;
|
|
const t = new Date(iso).getTime();
|
|
if (!Number.isFinite(t) || t < 1_000_000_000_000) return neverLabel;
|
|
const diffSec = (t - Date.now()) / 1000;
|
|
const abs = Math.abs(diffSec);
|
|
const rtf = new Intl.RelativeTimeFormat(locale, { numeric: 'auto' });
|
|
if (abs < 60) return rtf.format(Math.round(diffSec), 'second');
|
|
if (abs < 3600) return rtf.format(Math.round(diffSec / 60), 'minute');
|
|
if (abs < 86400) return rtf.format(Math.round(diffSec / 3600), 'hour');
|
|
if (abs < 604800) return rtf.format(Math.round(diffSec / 86400), 'day');
|
|
if (abs < 2592000) return rtf.format(Math.round(diffSec / 604800), 'week');
|
|
if (abs < 31536000) return rtf.format(Math.round(diffSec / 2592000), 'month');
|
|
return rtf.format(Math.round(diffSec / 31536000), 'year');
|
|
}
|