From 7ebc5f6c9dfc7c5a09e74994c09dc71ea60e7b2b Mon Sep 17 00:00:00 2001 From: byGalax Date: Sat, 16 May 2026 22:22:04 +0200 Subject: [PATCH] feat(P5C.T2): per-conv 'mentions only' toggle + notification gate --- .../src/components/ConversationRowMenu.tsx | 31 +++++++++++++++++-- .../src/context/ConversationsContext.tsx | 7 ++++- apps/desktop/src/pages/ChatsPage.tsx | 1 + packages/db-types/src/index.ts | 3 ++ packages/shared/src/chat/conversations.ts | 30 ++++++++++++++++-- packages/shared/src/chat/types.ts | 4 +++ 6 files changed, 71 insertions(+), 5 deletions(-) diff --git a/apps/desktop/src/components/ConversationRowMenu.tsx b/apps/desktop/src/components/ConversationRowMenu.tsx index a06e924..ef6cec6 100644 --- a/apps/desktop/src/components/ConversationRowMenu.tsx +++ b/apps/desktop/src/components/ConversationRowMenu.tsx @@ -1,6 +1,7 @@ import { muteDurationToIso, setConversationArchived, + setConversationMentionsOnly, setConversationMutedUntil, } from '@chat-app/shared/chat'; import { forwardRef, useCallback, useEffect, useRef, useState } from 'react'; @@ -8,12 +9,13 @@ import { createPortal } from 'react-dom'; import { useTranslation } from 'react-i18next'; import { supabase } from '../lib/supabase'; -import { ArchiveIcon, BellIcon, BellOffIcon, MoreVerticalIcon } from './icons'; +import { ArchiveIcon, AtIcon, BellIcon, BellOffIcon, MoreVerticalIcon } from './icons'; interface Props { conversationId: string; archived: boolean; mutedUntil: string | null; + mentionsOnly: boolean; } interface MuteOption { @@ -50,7 +52,7 @@ interface MenuPos { // escape the sidebar's `overflow-y-auto` clipping context. Position is // computed from the trigger's bounding rect — menu anchors right-aligned // under the trigger so it doesn't push off-screen on narrow windows. -export function ConversationRowMenu({ conversationId, archived, mutedUntil }: Props) { +export function ConversationRowMenu({ conversationId, archived, mutedUntil, mentionsOnly }: Props) { const { t } = useTranslation(['app']); const [open, setOpen] = useState(false); const [submenuOpen, setSubmenuOpen] = useState<'mute' | null>(null); @@ -145,6 +147,21 @@ export function ConversationRowMenu({ conversationId, archived, mutedUntil }: Pr [conversationId], ); + const handleMentionsOnly = useCallback( + async (next: boolean) => { + setOpen(false); + try { + await setConversationMentionsOnly(supabase, { + conversationId, + mentionsOnly: next, + }); + } catch (err: unknown) { + console.warn('mentions-only toggle failed', err); + } + }, + [conversationId], + ); + return ( <>