From 997598188dc6c684627dc4ee2fe53d8707108459 Mon Sep 17 00:00:00 2001 From: benya Date: Sun, 8 Mar 2026 01:03:04 +0300 Subject: [PATCH] fix(web): improve context menu positioning and forward UX - render chat/message context menus via portal to document.body - clamp menu coordinates to viewport while keeping near-cursor placement - remove visible chat id fallbacks from chat/discover UI - hide 'delete for everyone' checkbox for channels; show channel-specific hint - replace forward-by-chat-id prompt with searchable chat picker modal --- web/src/components/ChatList.tsx | 52 +++++++---- web/src/components/MessageList.tsx | 134 +++++++++++++++++++++------- web/src/components/NewChatPanel.tsx | 2 +- 3 files changed, 139 insertions(+), 49 deletions(-) diff --git a/web/src/components/ChatList.tsx b/web/src/components/ChatList.tsx index 506bed5..ba4d53e 100644 --- a/web/src/components/ChatList.tsx +++ b/web/src/components/ChatList.tsx @@ -1,4 +1,5 @@ import { useEffect, useState } from "react"; +import { createPortal } from "react-dom"; import { deleteChat } from "../api/chats"; import { updateMyProfile } from "../api/users"; import { useAuthStore } from "../store/authStore"; @@ -26,7 +27,7 @@ export function ChatList() { const [profileError, setProfileError] = useState(null); const [profileSaving, setProfileSaving] = useState(false); const deleteModalChat = chats.find((chat) => chat.id === deleteModalChatId) ?? null; - const canDeleteForEveryone = Boolean(deleteModalChat && !deleteModalChat.is_saved && deleteModalChat.type !== "private"); + const canDeleteForEveryone = Boolean(deleteModalChat && !deleteModalChat.is_saved && deleteModalChat.type === "group"); useEffect(() => { const timer = setTimeout(() => { @@ -115,7 +116,7 @@ export function ChatList() {
-

{chat.display_title || chat.title || `${chat.type} #${chat.id}`}

+

{chatLabel(chat)}

{messagesByChat[chat.id]?.length ? "now" : ""} @@ -128,26 +129,32 @@ export function ChatList() {
- {ctxChatId && ctxPos ? ( -
e.stopPropagation()}> - -
- ) : null} + {ctxChatId && ctxPos + ? createPortal( +
e.stopPropagation()}> + +
, + document.body + ) + : null} {deleteModalChatId ? (
-

Delete chat #{deleteModalChatId}

+

Delete chat: {deleteModalChat ? chatLabel(deleteModalChat) : "selected chat"}

+ {deleteModalChat?.type === "channel" ? ( +

Channels are removed for all subscribers.

+ ) : null} {canDeleteForEveryone ? (