UNPKG

@restnfeel/agentc-starter-kit

Version:

한국어 기업용 CMS 모듈 - Task Master AI와 함께 빠르게 웹사이트를 구현할 수 있는 재사용 가능한 컴포넌트 시스템

388 lines (385 loc) 14.4 kB
"use client"; import { jsx } from 'react/jsx-runtime'; import { useReducer, useCallback, useEffect, createContext, useContext } from 'react'; const initialModalState = { isOpen: false, isMinimized: false, position: { x: 0, y: 0 }, size: { width: "800px", height: "600px" }, zIndex: 1000, }; const initialState = { modalState: initialModalState, currentSession: null, sessions: [], nextZIndex: 1000, }; const STORAGE_KEY = "desktop-chat-modal-state"; const SESSIONS_STORAGE_KEY = "desktop-chat-sessions"; function modalStateReducer(state, action) { var _a, _b; switch (action.type) { case "OPEN_MODAL": return { ...state, modalState: { ...state.modalState, isOpen: true, zIndex: state.nextZIndex, }, nextZIndex: state.nextZIndex + 1, }; case "CLOSE_MODAL": return { ...state, modalState: { ...state.modalState, isOpen: false, isMinimized: false, }, }; case "MINIMIZE_MODAL": return { ...state, modalState: { ...state.modalState, isMinimized: true, }, }; case "MAXIMIZE_MODAL": return { ...state, modalState: { ...state.modalState, isMinimized: false, }, }; case "SET_POSITION": return { ...state, modalState: { ...state.modalState, position: action.payload, }, }; case "SET_SIZE": return { ...state, modalState: { ...state.modalState, size: action.payload, }, }; case "BRING_TO_FRONT": return { ...state, modalState: { ...state.modalState, zIndex: state.nextZIndex, }, nextZIndex: state.nextZIndex + 1, }; case "CREATE_SESSION": { const newSession = { id: action.payload.id, title: action.payload.title || `Chat ${state.sessions.length + 1}`, messages: [], createdAt: new Date(), lastActivity: new Date(), }; return { ...state, sessions: [...state.sessions, newSession], currentSession: newSession, }; } case "SWITCH_SESSION": { const session = state.sessions.find((s) => s.id === action.payload); return { ...state, currentSession: session || null, }; } case "DELETE_SESSION": { const filteredSessions = state.sessions.filter((s) => s.id !== action.payload); const wasCurrentSession = ((_a = state.currentSession) === null || _a === void 0 ? void 0 : _a.id) === action.payload; return { ...state, sessions: filteredSessions, currentSession: wasCurrentSession ? filteredSessions[0] || null : state.currentSession, }; } case "ADD_MESSAGE": { if (!state.currentSession) return state; const updatedSessions = state.sessions.map((session) => session.id === state.currentSession.id ? { ...session, messages: [...session.messages, action.payload], lastActivity: new Date(), } : session); const updatedCurrentSession = { ...state.currentSession, messages: [...state.currentSession.messages, action.payload], lastActivity: new Date(), }; return { ...state, sessions: updatedSessions, currentSession: updatedCurrentSession, }; } case "CLEAR_CURRENT_SESSION": { if (!state.currentSession) return state; const updatedSessions = state.sessions.map((session) => session.id === state.currentSession.id ? { ...session, messages: [], lastActivity: new Date(), } : session); const updatedCurrentSession = { ...state.currentSession, messages: [], lastActivity: new Date(), }; return { ...state, sessions: updatedSessions, currentSession: updatedCurrentSession, }; } case "SET_SESSIONS": return { ...state, sessions: action.payload, currentSession: action.payload[0] || null, }; case "UPDATE_SESSION_ACTIVITY": { const updatedSessions = state.sessions.map((session) => session.id === action.payload ? { ...session, lastActivity: new Date() } : session); const updatedCurrentSession = ((_b = state.currentSession) === null || _b === void 0 ? void 0 : _b.id) === action.payload ? { ...state.currentSession, lastActivity: new Date() } : state.currentSession; return { ...state, sessions: updatedSessions, currentSession: updatedCurrentSession, }; } default: return state; } } const ModalStateContext = createContext(undefined); function useModalState() { const context = useContext(ModalStateContext); if (!context) { throw new Error("useModalState must be used within a ModalStateProvider"); } return context; } function ModalStateProvider({ children, persistToStorage = true, maxSessions = 10, sessionTimeout = 24 * 60 * 60 * 1000, // 24 hours }) { const [state, dispatch] = useReducer(modalStateReducer, initialState); // Generate unique session ID const generateSessionId = useCallback(() => { return `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; }, []); // Generate unique message ID const generateMessageId = useCallback(() => { return `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; }, []); // Modal actions const openModal = useCallback(() => { dispatch({ type: "OPEN_MODAL" }); }, []); const closeModal = useCallback(() => { dispatch({ type: "CLOSE_MODAL" }); }, []); const minimizeModal = useCallback(() => { dispatch({ type: "MINIMIZE_MODAL" }); }, []); const maximizeModal = useCallback(() => { dispatch({ type: "MAXIMIZE_MODAL" }); }, []); const setModalPosition = useCallback((x, y) => { dispatch({ type: "SET_POSITION", payload: { x, y } }); }, []); const setModalSize = useCallback((width, height) => { dispatch({ type: "SET_SIZE", payload: { width, height } }); }, []); const bringToFront = useCallback(() => { dispatch({ type: "BRING_TO_FRONT" }); }, []); // Chat session actions const createSession = useCallback((title) => { const sessionId = generateSessionId(); dispatch({ type: "CREATE_SESSION", payload: { id: sessionId, title } }); return sessionId; }, [generateSessionId]); const switchSession = useCallback((sessionId) => { dispatch({ type: "SWITCH_SESSION", payload: sessionId }); dispatch({ type: "UPDATE_SESSION_ACTIVITY", payload: sessionId }); }, []); const deleteSession = useCallback((sessionId) => { dispatch({ type: "DELETE_SESSION", payload: sessionId }); }, []); const addMessage = useCallback((messageData) => { const message = { ...messageData, id: generateMessageId(), timestamp: new Date(), }; dispatch({ type: "ADD_MESSAGE", payload: message }); }, [generateMessageId]); const clearCurrentSession = useCallback(() => { dispatch({ type: "CLEAR_CURRENT_SESSION" }); }, []); // Storage functions const saveToStorage = useCallback(() => { if (!persistToStorage || typeof window === "undefined") return; try { // Save modal state const modalStateToSave = { position: state.modalState.position, size: state.modalState.size, isMinimized: state.modalState.isMinimized, }; localStorage.setItem(STORAGE_KEY, JSON.stringify(modalStateToSave)); // Save sessions (with date serialization) const sessionsToSave = state.sessions.map((session) => ({ ...session, createdAt: session.createdAt.toISOString(), lastActivity: session.lastActivity.toISOString(), messages: session.messages.map((msg) => ({ ...msg, timestamp: msg.timestamp.toISOString(), })), })); localStorage.setItem(SESSIONS_STORAGE_KEY, JSON.stringify(sessionsToSave)); } catch (error) { console.warn("Failed to save modal state to storage:", error); } }, [state, persistToStorage]); const loadFromStorage = useCallback(() => { if (!persistToStorage || typeof window === "undefined") return; try { // Load modal state const savedModalState = localStorage.getItem(STORAGE_KEY); if (savedModalState) { const parsed = JSON.parse(savedModalState); if (parsed.position) { dispatch({ type: "SET_POSITION", payload: parsed.position }); } if (parsed.size) { dispatch({ type: "SET_SIZE", payload: parsed.size }); } if (parsed.isMinimized) { dispatch({ type: "MINIMIZE_MODAL" }); } } // Load sessions const savedSessions = localStorage.getItem(SESSIONS_STORAGE_KEY); if (savedSessions) { const parsed = JSON.parse(savedSessions); const now = new Date(); // Filter out expired sessions and restore dates const validSessions = parsed .map((session) => ({ ...session, createdAt: new Date(session.createdAt), lastActivity: new Date(session.lastActivity), messages: session.messages.map((msg) => ({ ...msg, timestamp: new Date(msg.timestamp), })), })) .filter((session) => { const timeSinceActivity = now.getTime() - session.lastActivity.getTime(); return timeSinceActivity < sessionTimeout; }) .slice(-maxSessions); // Keep only the most recent sessions if (validSessions.length > 0) { dispatch({ type: "SET_SESSIONS", payload: validSessions }); } } } catch (error) { console.warn("Failed to load modal state from storage:", error); } }, [persistToStorage, sessionTimeout, maxSessions]); const clearStorage = useCallback(() => { if (typeof window === "undefined") return; try { localStorage.removeItem(STORAGE_KEY); localStorage.removeItem(SESSIONS_STORAGE_KEY); } catch (error) { console.warn("Failed to clear modal state storage:", error); } }, []); // Auto-save to storage when state changes useEffect(() => { if (persistToStorage) { const timeoutId = setTimeout(saveToStorage, 500); // Debounce saves return () => clearTimeout(timeoutId); } }, [state, saveToStorage, persistToStorage]); // Load from storage on mount useEffect(() => { loadFromStorage(); }, [loadFromStorage]); // Create initial session if none exists useEffect(() => { if (state.sessions.length === 0 && !state.currentSession) { createSession("Welcome Chat"); } }, [state.sessions.length, state.currentSession, createSession]); // Cleanup expired sessions periodically useEffect(() => { const cleanupInterval = setInterval(() => { const now = new Date(); const validSessions = state.sessions.filter((session) => { const timeSinceActivity = now.getTime() - session.lastActivity.getTime(); return timeSinceActivity < sessionTimeout; }); if (validSessions.length !== state.sessions.length) { dispatch({ type: "SET_SESSIONS", payload: validSessions }); } }, 60000); // Check every minute return () => clearInterval(cleanupInterval); }, [state.sessions, sessionTimeout]); const contextValue = { modalState: state.modalState, openModal, closeModal, minimizeModal, maximizeModal, setModalPosition, setModalSize, bringToFront, currentSession: state.currentSession, sessions: state.sessions, createSession, switchSession, deleteSession, addMessage, clearCurrentSession, saveToStorage, loadFromStorage, clearStorage, }; return (jsx(ModalStateContext.Provider, { value: contextValue, children: children })); } export { ModalStateProvider, ModalStateProvider as default, useModalState }; //# sourceMappingURL=modal-state-context.js.map