From e96498645a8204b6a5150b04cffec55db42f5d40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sedat=20=C3=96zt=C3=BCrk?= Date: Sat, 4 Jul 2026 22:36:50 +0300 Subject: [PATCH] =?UTF-8?q?Messenger=20Widget=20g=C3=BCncellemesi?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ui/src/components/layouts/ClassicLayout.tsx | 2 + ui/src/components/layouts/DeckedLayout.tsx | 2 + ui/src/components/layouts/Layouts.tsx | 2 - ui/src/components/layouts/ModernLayout.tsx | 2 + ui/src/components/layouts/SimpleLayout.tsx | 2 + .../components/layouts/StackedSideLayout.tsx | 2 + .../components/template/MessengerWidget.tsx | 116 +++++++++--------- .../ThemeConfigurator/StyleSwitcher.tsx | 2 +- .../ThemeConfigurator/ThemeConfigurator.tsx | 8 +- .../ThemeConfigurator/ThemeSwitcher.tsx | 2 + 10 files changed, 75 insertions(+), 65 deletions(-) diff --git a/ui/src/components/layouts/ClassicLayout.tsx b/ui/src/components/layouts/ClassicLayout.tsx index 63a19c0..7fcadb2 100644 --- a/ui/src/components/layouts/ClassicLayout.tsx +++ b/ui/src/components/layouts/ClassicLayout.tsx @@ -7,6 +7,7 @@ import SidePanel from '@/components/template/SidePanel' import UserDropdown from '@/components/template/UserDropdown' import { useStoreState } from '@/store' import LanguageSelector from '../template/LanguageSelector' +import MessengerWidget from '../template/MessengerWidget' import Search from '../template/Search' import StackedSideNav from '../template/StackedSideNav' import AiAssistant from '../template/AiAssistant' @@ -27,6 +28,7 @@ const HeaderActionsEnd = () => { <> + diff --git a/ui/src/components/layouts/DeckedLayout.tsx b/ui/src/components/layouts/DeckedLayout.tsx index dec4617..e9845cb 100644 --- a/ui/src/components/layouts/DeckedLayout.tsx +++ b/ui/src/components/layouts/DeckedLayout.tsx @@ -8,6 +8,7 @@ import MobileNav from '@/components/template/MobileNav' import View from '@/views/Views' import Search from '@/components/template/Search' import LanguageSelector from '../template/LanguageSelector' +import MessengerWidget from '../template/MessengerWidget' import AiAssistant from '../template/AiAssistant' const HeaderActionsStart = () => { @@ -25,6 +26,7 @@ const HeaderActionsEnd = () => { + diff --git a/ui/src/components/layouts/Layouts.tsx b/ui/src/components/layouts/Layouts.tsx index f5d70ae..136a511 100644 --- a/ui/src/components/layouts/Layouts.tsx +++ b/ui/src/components/layouts/Layouts.tsx @@ -15,7 +15,6 @@ import useLocale from '@/utils/hooks/useLocale' import { useDynamicRoutes } from '@/routes/dynamicRoutesContext' import { useLocation } from 'react-router-dom' import { hasSubdomain } from '@/utils/subdomain' -import MessengerWidget from '../template/MessengerWidget' export type LayoutType = | typeof LAYOUT_TYPE_CLASSIC @@ -103,7 +102,6 @@ const Layout = () => { } > - {authenticated && currentPath.includes('/admin') && } ) } diff --git a/ui/src/components/layouts/ModernLayout.tsx b/ui/src/components/layouts/ModernLayout.tsx index 244c774..2c49c87 100644 --- a/ui/src/components/layouts/ModernLayout.tsx +++ b/ui/src/components/layouts/ModernLayout.tsx @@ -8,6 +8,7 @@ import SidePanel from '@/components/template/SidePanel' import UserDropdown from '@/components/template/UserDropdown' import View from '@/views/Views' import LanguageSelector from '../template/LanguageSelector' +import MessengerWidget from '../template/MessengerWidget' import { useStoreState } from '@/store' import StackedSideNav from '../template/StackedSideNav' import AiAssistant from '../template/AiAssistant' @@ -27,6 +28,7 @@ const HeaderActionsEnd = () => { <> + diff --git a/ui/src/components/layouts/SimpleLayout.tsx b/ui/src/components/layouts/SimpleLayout.tsx index 83e87b4..f83b4e0 100644 --- a/ui/src/components/layouts/SimpleLayout.tsx +++ b/ui/src/components/layouts/SimpleLayout.tsx @@ -8,6 +8,7 @@ import View from '@/views/Views' import Notification from '@/components/template/Notification' import Search from '@/components/template/Search' import LanguageSelector from '../template/LanguageSelector' +import MessengerWidget from '../template/MessengerWidget' import AiAssistant from '../template/AiAssistant' const HeaderActionsStart = () => { @@ -25,6 +26,7 @@ const HeaderActionsEnd = () => { + diff --git a/ui/src/components/layouts/StackedSideLayout.tsx b/ui/src/components/layouts/StackedSideLayout.tsx index 971bc17..a5dd5de 100644 --- a/ui/src/components/layouts/StackedSideLayout.tsx +++ b/ui/src/components/layouts/StackedSideLayout.tsx @@ -7,6 +7,7 @@ import View from '@/views/Views' import Search from '@/components/template/Search' import Notification from '@/components/template/Notification' import LanguageSelector from '../template/LanguageSelector' +import MessengerWidget from '../template/MessengerWidget' import AiAssistant from '../template/AiAssistant' const HeaderActionsStart = () => { @@ -23,6 +24,7 @@ const HeaderActionsEnd = () => { <> + diff --git a/ui/src/components/template/MessengerWidget.tsx b/ui/src/components/template/MessengerWidget.tsx index bd1fc06..9e0cbec 100644 --- a/ui/src/components/template/MessengerWidget.tsx +++ b/ui/src/components/template/MessengerWidget.tsx @@ -17,13 +17,13 @@ import { } from '@/services/messenger.service' import { messengerSignalR } from '@/services/messenger.signalr' import { useStoreState } from '@/store' +import withHeaderItem from '@/utils/hoc/withHeaderItem' import dayjs from 'dayjs' import EmojiPicker, { EmojiClickData } from 'emoji-picker-react' -import { useEffect, useMemo, useRef, useState } from 'react' +import classNames from 'classnames' +import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { FaArrowLeft, - FaCompress, - FaExpand, FaPaperclip, FaRegSmile, FaSearch, @@ -33,6 +33,8 @@ import { } from 'react-icons/fa' import { IoCheckmarkDone, IoChatbubbleEllipsesOutline, IoSend } from 'react-icons/io5' import { useLocalization } from '@/utils/hooks/useLocalization' +import useThemeClass from '@/utils/hooks/useThemeClass' +import { useLocation } from 'react-router-dom' const MAX_UPLOAD_SIZE = 10 * 1024 * 1024 const CONTACT_REFRESH_INTERVAL = 30000 @@ -64,13 +66,15 @@ const mergeMessages = ( ) } -const MessengerWidget = () => { +const MessengerWidgetContent = ({ className }: { className?: string }) => { + const location = useLocation() const auth = useStoreState((state) => state.auth) const tenantId = auth.user.tenantId || auth.tenant?.tenantId const fileInputRef = useRef(null) const messageInputRef = useRef(null) const messagesEndRef = useRef(null) const { translate } = useLocalization() + const { textTheme } = useThemeClass() const [open, setOpen] = useState(false) const [contacts, setContacts] = useState([]) @@ -83,7 +87,6 @@ const MessengerWidget = () => { const [uploading, setUploading] = useState(false) const [showEmoji, setShowEmoji] = useState(false) const [multiSelect, setMultiSelect] = useState(false) - const [maximized, setMaximized] = useState(false) const [unreadByContact, setUnreadByContact] = useState>({}) const [reachableContactIds, setReachableContactIds] = useState([]) @@ -250,14 +253,24 @@ const MessengerWidget = () => { }) } - const closeWidget = () => { + const closeWidget = useCallback(() => { setOpen(false) - setMaximized(false) setSelectedIds([]) setText('') setAttachments([]) setShowEmoji(false) - } + }, []) + + useEffect(() => { + if (!open) return + + const handleKeyDown = (event: KeyboardEvent) => { + if (event.key === 'Escape') closeWidget() + } + + window.addEventListener('keydown', handleKeyDown) + return () => window.removeEventListener('keydown', handleKeyDown) + }, [closeWidget, open]) const handleFiles = async (files: FileList | null) => { if (!files?.length) return @@ -349,11 +362,10 @@ const MessengerWidget = () => { setText((current) => `${current}${emoji.emoji}`) } - if (!auth.session.signedIn) return null + if (!auth.session.signedIn || !location.pathname.startsWith('/admin')) return null - const panelClassName = maximized - ? 'pointer-events-auto fixed inset-2 z-[51] overflow-hidden rounded-xl border border-gray-200 bg-white/80 shadow-[0_24px_80px_rgba(15,23,42,0.35)] backdrop-blur-xl dark:border-gray-700 dark:bg-gray-900/85 sm:inset-4' - : 'pointer-events-auto fixed inset-x-2 bottom-20 top-3 z-[51] overflow-hidden rounded-xl border border-gray-200 bg-white/80 shadow-[0_24px_80px_rgba(15,23,42,0.35)] backdrop-blur-xl dark:border-gray-700 dark:bg-gray-900/85 sm:inset-auto sm:bottom-20 sm:right-5 sm:h-[min(75vh,680px)] sm:w-[min(78vw,800px)]' + const panelClassName = + 'pointer-events-auto fixed inset-2 z-[51] overflow-hidden rounded-xl border border-gray-200 bg-white/80 shadow-[0_24px_80px_rgba(15,23,42,0.35)] backdrop-blur-xl dark:border-gray-700 dark:bg-gray-900/85 sm:inset-4' const headerActionClassName = 'text-gray-600 hover:bg-gray-900/10 hover:text-gray-900 active:bg-gray-900/15 dark:text-gray-200 dark:hover:bg-white/10 dark:hover:text-white dark:active:bg-white/15' @@ -405,21 +417,6 @@ const MessengerWidget = () => {
- -
-
+ +
(open ? closeWidget() : setOpen(true))} + onKeyDown={(event) => { + if (event.key === 'Enter' || event.key === ' ') { + event.preventDefault() + if (open) { + closeWidget() + } else { + setOpen(true) + } + } + }} + > + + {unread > 0 && ( + + {unread > 99 ? '99+' : unread} + + )} +
+
) } +const MessengerWidgetHeaderItem = withHeaderItem(MessengerWidgetContent) + +const MessengerWidget = () => + export default MessengerWidget diff --git a/ui/src/components/template/ThemeConfigurator/StyleSwitcher.tsx b/ui/src/components/template/ThemeConfigurator/StyleSwitcher.tsx index 22dcbce..14d84f5 100644 --- a/ui/src/components/template/ThemeConfigurator/StyleSwitcher.tsx +++ b/ui/src/components/template/ThemeConfigurator/StyleSwitcher.tsx @@ -111,12 +111,12 @@ const StyleSwitcher = ({ onStyleChange }: { onStyleChange?: () => void }) => { return (