Files
multica/server/migrations/148_chat_session_pinned.up.sql
Jiayuan Zhang db84ff57c8 feat(chat): pin a chat to the top of the Chat list (MUL-4240)
Builds on Chat V2 (#5076). Adds a per-conversation pin so a user can
keep important chats at the top of the IM-style thread list, above the
activity-sorted rest.

Backend:
- migration 148: chat_session.pinned_at (nullable) + partial index; the
  timestamp doubles as the pinned-group sort key and the boolean flag.
- list queries order pinned-first, then by most-recent activity.
- SetChatSessionPinned query + PATCH /api/chat/sessions/{id}/pin handler;
  pinning never bumps updated_at, so an unpinned chat won't jump the list.
- ChatSessionResponse.pinned + chat:session_updated carries the new state.

Frontend:
- ChatSession.pinned; setChatSessionPinned API + useSetChatSessionPinned
  with optimistic re-sort; shared sortChatSessions comparator.
- thread list: pin indicator on pinned rows + pin/unpin hover action;
  list sorted pinned-first so it stays ordered after cache patches.
- realtime patch re-sorts on pin change; en/ja/ko/zh-Hans strings.

Tests: SetChatSessionPinned handler test, sortChatSessions unit tests.
2026-07-08 16:09:56 +08:00

13 lines
714 B
SQL

-- Per-conversation pin for the Chat list: a user can pin a chat so it stays
-- at the top of their conversation list, above the activity-sorted rest.
-- `pinned_at` doubles as the sort key within the pinned group (most-recently
-- pinned first) and as the boolean flag (NULL = not pinned). Sessions are
-- already per-creator, so no extra user dimension is needed.
ALTER TABLE chat_session ADD COLUMN pinned_at TIMESTAMPTZ;
-- Partial index over pinned rows only — the pinned group is small, and the
-- list query orders by pinned_at within a single (workspace, creator) scan.
CREATE INDEX idx_chat_session_pinned
ON chat_session (creator_id, workspace_id, pinned_at DESC)
WHERE pinned_at IS NOT NULL;