- 사용자 온라인 상태 표시 (온라인/자리비움/오프라인) 디스코드 스타일 - 채팅방별 알림 ON/OFF 토글 (Bell 아이콘, localStorage 저장) - 파일 업로드 실시간 소켓 브로드캐스트 및 한글 파일명 깨짐 수정 - FAB 읽지않음 배지 버그 수정 (메신저 닫혀있을 때 markAsRead 차단) - 타이핑 도트 애니메이션, 날짜 오늘/어제 표시 - 입력창 bordered box, DM 편집 버튼 숨김 - 메신저 설정 버튼 제거, 새 대화 시작하기 Empty state CTA - useMessengerSocket 소켓 중복 생성 방지 (MessengerModal로 이동) Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com> [RAPID-micro] 추적 파일 정리 및 메신저 소소한 변경 - .omc/state/ 파일 git 추적 제거 (.gitignore 이미 설정됨) - db/checkpoints/ gitignore 추가 - globals.css: 메신저 메시지 시간 폰트 스타일 추가 - useMessenger.ts: fileMimeType 필드 및 API_BASE_URL import 추가 Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
94 lines
2.7 KiB
TypeScript
94 lines
2.7 KiB
TypeScript
"use client";
|
|
|
|
import React, { createContext, useContext, useState, useCallback, useEffect } from "react";
|
|
|
|
interface MessengerContextValue {
|
|
isOpen: boolean;
|
|
selectedRoomId: string | null;
|
|
unreadCount: number;
|
|
notificationEnabled: boolean;
|
|
mutedRooms: Set<string>;
|
|
openMessenger: (roomId?: string) => void;
|
|
closeMessenger: () => void;
|
|
selectRoom: (roomId: string) => void;
|
|
setUnreadCount: (count: number) => void;
|
|
toggleNotification: () => void;
|
|
toggleRoomMute: (roomId: string) => void;
|
|
}
|
|
|
|
const MessengerContext = createContext<MessengerContextValue | undefined>(undefined);
|
|
|
|
export function MessengerProvider({ children }: { children: React.ReactNode }) {
|
|
const [isOpen, setIsOpen] = useState(false);
|
|
const [selectedRoomId, setSelectedRoomId] = useState<string | null>(null);
|
|
const [unreadCount, setUnreadCount] = useState(0);
|
|
const [notificationEnabled, setNotificationEnabled] = useState(true);
|
|
const [mutedRooms, setMutedRooms] = useState<Set<string>>(new Set());
|
|
|
|
useEffect(() => {
|
|
const stored = localStorage.getItem("messenger_notification");
|
|
if (stored !== null) setNotificationEnabled(stored === "true");
|
|
try {
|
|
const muted = JSON.parse(localStorage.getItem("messenger_muted_rooms") || "[]");
|
|
setMutedRooms(new Set(muted));
|
|
} catch {}
|
|
}, []);
|
|
|
|
const openMessenger = useCallback((roomId?: string) => {
|
|
setIsOpen(true);
|
|
if (roomId) setSelectedRoomId(roomId);
|
|
}, []);
|
|
|
|
const closeMessenger = useCallback(() => {
|
|
setIsOpen(false);
|
|
}, []);
|
|
|
|
const selectRoom = useCallback((roomId: string) => {
|
|
setSelectedRoomId(roomId);
|
|
}, []);
|
|
|
|
const toggleNotification = useCallback(() => {
|
|
setNotificationEnabled((prev) => {
|
|
const next = !prev;
|
|
localStorage.setItem("messenger_notification", String(next));
|
|
return next;
|
|
});
|
|
}, []);
|
|
|
|
const toggleRoomMute = useCallback((roomId: string) => {
|
|
setMutedRooms((prev) => {
|
|
const next = new Set(prev);
|
|
if (next.has(roomId)) next.delete(roomId);
|
|
else next.add(roomId);
|
|
localStorage.setItem("messenger_muted_rooms", JSON.stringify([...next]));
|
|
return next;
|
|
});
|
|
}, []);
|
|
|
|
return (
|
|
<MessengerContext.Provider
|
|
value={{
|
|
isOpen,
|
|
selectedRoomId,
|
|
unreadCount,
|
|
notificationEnabled,
|
|
mutedRooms,
|
|
openMessenger,
|
|
closeMessenger,
|
|
selectRoom,
|
|
setUnreadCount,
|
|
toggleNotification,
|
|
toggleRoomMute,
|
|
}}
|
|
>
|
|
{children}
|
|
</MessengerContext.Provider>
|
|
);
|
|
}
|
|
|
|
export function useMessengerContext() {
|
|
const ctx = useContext(MessengerContext);
|
|
if (!ctx) throw new Error("useMessengerContext must be used within MessengerProvider");
|
|
return ctx;
|
|
}
|