feat: swipe gestures, pin/mute, last seen, emoji fix, push/rename fixes
- Add swipe-to-reveal in mobile chat list (right=pin, left=mute/leave) - Pin/mute API endpoints with is_pinned DB column migration - Show pin icon on pinned chats, mute icon on muted chats - Pinned chats sort to top of list - Fix push notifications sent to message sender (filter uid) - Remove debug console.log from WS handler - Fix chat rename not updating in sidebar without reload - Fix emoji picker z-index and positioning on mobile (z-50, bottom-full) - Add last seen time in chat header for private chats Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -16,7 +16,7 @@ export default async function chatRoutes(app: FastifyInstance) {
|
||||
const { rows } = await pool.query(`
|
||||
SELECT
|
||||
c.id, c.type, c.title, c.description, c.avatar_color, c.avatar, c.is_public, c.created_at,
|
||||
cm.role, cm.last_read_at,
|
||||
cm.role, cm.last_read_at, cm.is_pinned, cm.is_muted,
|
||||
(SELECT content FROM messages WHERE chat_id = c.id AND is_deleted = FALSE ORDER BY created_at DESC LIMIT 1) AS last_message,
|
||||
(SELECT created_at FROM messages WHERE chat_id = c.id AND is_deleted = FALSE ORDER BY created_at DESC LIMIT 1) AS last_message_at,
|
||||
(SELECT COUNT(*) FROM messages WHERE chat_id = c.id AND is_deleted = FALSE AND created_at > cm.last_read_at) AS unread_count,
|
||||
@@ -44,7 +44,7 @@ export default async function chatRoutes(app: FastifyInstance) {
|
||||
) END AS private_user_id
|
||||
FROM chats c
|
||||
JOIN chat_members cm ON cm.chat_id = c.id AND cm.user_id = $1
|
||||
ORDER BY COALESCE(
|
||||
ORDER BY cm.is_pinned DESC, COALESCE(
|
||||
(SELECT created_at FROM messages WHERE chat_id = c.id AND is_deleted = FALSE ORDER BY created_at DESC LIMIT 1),
|
||||
c.created_at
|
||||
) DESC
|
||||
@@ -65,6 +65,8 @@ export default async function chatRoutes(app: FastifyInstance) {
|
||||
memberCount: parseInt(r.member_count),
|
||||
privateUserId: r.private_user_id,
|
||||
createdAt: r.created_at,
|
||||
isPinned: r.is_pinned,
|
||||
isMuted: r.is_muted,
|
||||
}));
|
||||
});
|
||||
|
||||
@@ -308,6 +310,24 @@ export default async function chatRoutes(app: FastifyInstance) {
|
||||
return { ok: true };
|
||||
});
|
||||
|
||||
// Pin/unpin chat for current user
|
||||
app.put('/:id/pin', async (req) => {
|
||||
const { id: userId } = req.user as { id: string };
|
||||
const { id } = req.params as { id: string };
|
||||
const { pinned } = req.body as { pinned: boolean };
|
||||
await pool.query('UPDATE chat_members SET is_pinned = $1 WHERE chat_id = $2 AND user_id = $3', [pinned, id, userId]);
|
||||
return { ok: true };
|
||||
});
|
||||
|
||||
// Mute/unmute chat for current user
|
||||
app.put('/:id/mute', async (req) => {
|
||||
const { id: userId } = req.user as { id: string };
|
||||
const { id } = req.params as { id: string };
|
||||
const { muted } = req.body as { muted: boolean };
|
||||
await pool.query('UPDATE chat_members SET is_muted = $1 WHERE chat_id = $2 AND user_id = $3', [muted, id, userId]);
|
||||
return { ok: true };
|
||||
});
|
||||
|
||||
// Leave chat
|
||||
app.delete('/:id/leave', async (req, reply) => {
|
||||
const { id: userId } = req.user as { id: string };
|
||||
|
||||
Reference in New Issue
Block a user