'use client'; import '@/app/(main)/chat/style.scss'; import '@/app/styles/chat-dock.scss'; import { useCallback, useEffect, useState } from 'react'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faComments, faAnglesRight, faXmark } from '@fortawesome/free-solid-svg-icons'; import dynamic from 'next/dynamic'; // 채팅 본체는 하이드레이션 임계경로에서 빼기 위해 client-only 지연 로드(ssr:false). // (main)/Layout 에 상시 마운트되는 단일 인스턴스라 최초 로드 후 유지 → 'main' 룸 단일 참가자 불변식 보존. const MainChat = dynamic(() => import('@/app/(main)/chat/MainChat'), { ssr: false, loading: () => null }); const STORAGE_KEY = 'az-chat-collapsed'; const WIDTH_EXPANDED = '340px'; const WIDTH_COLLAPSED = '52px'; // 우측 고정 채팅 도크 — (main)/Layout 에 단일 인스턴스로 상시 마운트되어 페이지 전환에도 유지된다(App Router layout 은 자식 라우트 이동에 언마운트 안 됨). // MainChat 은 접힘(desktop 레일)/모바일 닫힘 상태에서도 언마운트하지 않고 CSS 로만 숨겨 SignalR 참가(JoinRoom 'main')·메시지·스크롤을 보존한다. // → 이 도크가 'main' 룸의 유일한 참가자여야 이중 JoinRoom/LeaveRoom 충돌이 없다 (그래서 /chat 페이지는 별도 MainChat 을 마운트하지 않는다). export default function ChatDock() { // 데스크톱 접힘(레일) — localStorage 영속. 기본 펼침. const [collapsed, setCollapsed] = useState(false); // 모바일 드로어 열림 — 비영속, 기본 닫힘. const [drawerOpen, setDrawerOpen] = useState(false); // 최초 mount 시 localStorage 에서 collapsed 복원 useEffect(() => { try { const saved = window.localStorage.getItem(STORAGE_KEY); if (saved === 'true') { setCollapsed(true); } } catch {} }, []); // collapsed 변경 시 html 루트 CSS 변수 동기화 — desktop grid 의 chat 컬럼 폭(모바일은 fixed 라 무영향) useEffect(() => { const root = document.documentElement; root.style.setProperty('--antooza-chat-width', collapsed ? WIDTH_COLLAPSED : WIDTH_EXPANDED); try { window.localStorage.setItem(STORAGE_KEY, String(collapsed)); } catch {} return () => { root.style.removeProperty('--antooza-chat-width'); }; }, [collapsed]); const collapse = useCallback(() => setCollapsed(true), []); const expand = useCallback(() => setCollapsed(false), []); const openDrawer = useCallback(() => setDrawerOpen(true), []); const closeDrawer = useCallback(() => setDrawerOpen(false), []); // MainChat 헤더(.chat-room__meta)에 주입할 컨트롤 — desktop=접기, mobile=드로어 닫기 (CSS 로 상호 배타 노출) const headerControls = ( <> > ); return ( <> {/* 모바일 플로팅 토글 */} {/* 모바일 오버레이 */}
> ); }