From 58208787e74559c746c1763a592ee59ba0bab416 Mon Sep 17 00:00:00 2001 From: benya Date: Sun, 8 Mar 2026 12:55:55 +0300 Subject: [PATCH] feat(web): refresh audio card UI and enforce outside-click menu close --- web/src/components/ChatList.tsx | 150 +++++++++++++++++------------ web/src/components/MessageList.tsx | 50 ++++++---- 2 files changed, 117 insertions(+), 83 deletions(-) diff --git a/web/src/components/ChatList.tsx b/web/src/components/ChatList.tsx index dab8c61..ef8b08e 100644 --- a/web/src/components/ChatList.tsx +++ b/web/src/components/ChatList.tsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from "react"; +import { useEffect, useRef, useState } from "react"; import { createPortal } from "react-dom"; import { archiveChat, clearChat, createPrivateChat, deleteChat, getChats, getSavedMessagesChat, joinChat, leaveChat, pinChat, unarchiveChat, unpinChat } from "../api/chats"; import { globalSearch } from "../api/search"; @@ -46,6 +46,9 @@ export function ChatList() { const [profileAllowPrivateMessages, setProfileAllowPrivateMessages] = useState(true); const [profileError, setProfileError] = useState(null); const [profileSaving, setProfileSaving] = useState(false); + const sidebarRef = useRef(null); + const burgerMenuRef = useRef(null); + const burgerButtonRef = useRef(null); const deleteModalChat = chats.find((chat) => chat.id === deleteModalChatId) ?? null; const canDeleteForEveryone = Boolean( deleteModalChat && @@ -168,6 +171,25 @@ export function ChatList() { return () => window.removeEventListener("keydown", onKeyDown); }, []); + useEffect(() => { + const onPointerDown = (event: MouseEvent) => { + const target = event.target as Node | null; + if (ctxChatId) { + setCtxChatId(null); + setCtxPos(null); + } + if (menuOpen) { + const inMenu = burgerMenuRef.current?.contains(target ?? null) ?? false; + const inButton = burgerButtonRef.current?.contains(target ?? null) ?? false; + if (!inMenu && !inButton) { + setMenuOpen(false); + } + } + }; + document.addEventListener("mousedown", onPointerDown); + return () => document.removeEventListener("mousedown", onPointerDown); + }, [ctxChatId, menuOpen]); + useEffect(() => { applyAppearancePreferences(getAppPreferences()); }, []); @@ -271,10 +293,11 @@ export function ChatList() { } return ( -