Files
vexplor_dev/frontend/contexts/MessengerContext.tsx
syc0123 403e5cae40 [RAPID] 메신저 기능 구현 및 UI/UX 개선
- 사용자 온라인 상태 표시 (온라인/자리비움/오프라인) 디스코드 스타일
- 채팅방별 알림 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>
2026-04-01 12:20:43 +09:00

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;
}