diff --git a/docs/core-checklist-status.md b/docs/core-checklist-status.md index 364ae8e..186ed55 100644 --- a/docs/core-checklist-status.md +++ b/docs/core-checklist-status.md @@ -9,7 +9,7 @@ Legend: 1. Account - `DONE` (email auth, JWT, refresh, logout, reset, sessions; web handles `/verify-email?token=...` links with auth-page feedback; integration tests cover resend-verification replacement, password-reset login flow, and `check-email` status transitions) 2. User Profile - `DONE` (username, name, avatar, bio, update) -3. User Status - `PARTIAL` (online/last seen/offline; web now formats `just now/today/yesterday/recently`, backend-side presence heuristics still limited) +3. User Status - `PARTIAL` (online/last seen/offline; web now formats `just now/today/yesterday/recently` and uses Telegram-like fallback `last seen recently` when precise last-seen is unavailable; backend-side presence heuristics still limited) 4. Contacts - `PARTIAL` (list/search/add/remove/block/unblock; `add by email` flow covered by integration tests including `success/not found/blocked conflict`; web now surfaces specific add-by-email errors (`not found` vs `blocked`); UX moved to menu; Contacts panel now includes inline `Block/Unblock` actions per user) 5. Chat List - `DONE` (all/pinned/archive/sort/unread; saved-messages delete behavior covered: clear history without deleting chat; regression test covers `GET /chats/{saved_id}` detail response) 6. Chat Types - `DONE` (private/group/channel) diff --git a/web/src/components/ChatInfoPanel.tsx b/web/src/components/ChatInfoPanel.tsx index e7c5cf0..aebb4a9 100644 --- a/web/src/components/ChatInfoPanel.tsx +++ b/web/src/components/ChatInfoPanel.tsx @@ -645,7 +645,7 @@ export function ChatInfoPanel({ chatId, open, onClose }: Props) { ? "User is online" : chat.counterpart_last_seen_at ? `Last seen ${formatLastSeen(chat.counterpart_last_seen_at)}` - : "User is offline"} + : "Last seen recently"}
) : (No extra information.
@@ -1304,7 +1304,7 @@ function privateChatStatusLabel(chat: { counterpart_is_online?: boolean | null; if (chat.counterpart_last_seen_at) { return `last seen ${formatLastSeen(chat.counterpart_last_seen_at)}`; } - return "offline"; + return "last seen recently"; } function initialsFromName(value: string): string { diff --git a/web/src/components/ChatList.tsx b/web/src/components/ChatList.tsx index 4752e83..c54ccf8 100644 --- a/web/src/components/ChatList.tsx +++ b/web/src/components/ChatList.tsx @@ -873,7 +873,7 @@ function chatMetaLabel(chat: { if (chat.counterpart_last_seen_at) { return `last seen ${formatLastSeen(chat.counterpart_last_seen_at)}`; } - return "offline"; + return "last seen recently"; } if (chat.type === "group") { const members = chat.members_count ?? 0; diff --git a/web/src/pages/ChatsPage.tsx b/web/src/pages/ChatsPage.tsx index a269b15..da5fbd7 100644 --- a/web/src/pages/ChatsPage.tsx +++ b/web/src/pages/ChatsPage.tsx @@ -301,7 +301,7 @@ function headerMetaLabel(chat: { if (chat.counterpart_last_seen_at) { return `last seen ${formatLastSeen(chat.counterpart_last_seen_at)}`; } - return "offline"; + return "last seen recently"; } if (chat.type === "group") { const members = chat.members_count ?? 0;