One line under the handle in the user profile popover, from the presence the
SDK already receives (currently_active + last_active_ago): 'Active now',
'Active just now', 'Last active 12 min ago / 3 hours ago / yesterday / 5 days
ago / over a month ago'. Nothing is shown without presence data or for an
offline user with no timestamp (Hide Online Status users), so nothing new is
exposed; re-renders on the existing presence events, no polling. Wording
unit-tested; verified headless ('Active now' for an online member).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
25 lines
1.0 KiB
TypeScript
25 lines
1.0 KiB
TypeScript
/**
|
|
* [Gitea #150] "Active now" / "Last active 12 min ago" from presence.
|
|
* Returns null when there is nothing honest to say: no presence data, an
|
|
* offline user with no timestamp (e.g. someone hiding their online status).
|
|
*/
|
|
export const describeLastActive = (
|
|
presence: { presence: string; active: boolean; lastActiveTs?: number } | undefined,
|
|
now = Date.now(),
|
|
): string | null => {
|
|
if (!presence) return null;
|
|
if (presence.presence === 'online' && presence.active) return 'Active now';
|
|
const ts = presence.lastActiveTs;
|
|
if (!ts || ts <= 0) return null;
|
|
const ago = Math.max(0, now - ts);
|
|
const min = Math.round(ago / 60_000);
|
|
if (min < 1) return 'Active just now';
|
|
if (min < 60) return `Last active ${min} min ago`;
|
|
const hours = Math.round(min / 60);
|
|
if (hours < 24) return `Last active ${hours} ${hours === 1 ? 'hour' : 'hours'} ago`;
|
|
const days = Math.round(hours / 24);
|
|
if (days === 1) return 'Last active yesterday';
|
|
if (days < 30) return `Last active ${days} days ago`;
|
|
return 'Last active over a month ago';
|
|
};
|