/** * UIManager 모듈 * UI 컴포넌트 및 상태 관리 */ class UIManager { constructor() { console.log('🎨 UIManager 초기화 시작'); // UI 상태 this.showNotesPanel = false; this.showBookmarksPanel = false; this.showBacklinks = false; this.activePanel = 'notes'; // 모달 상태 this.showNoteModal = false; this.showBookmarkModal = false; this.showLinkModal = false; this.showNotesModal = false; this.showBookmarksModal = false; this.showLinksModal = false; this.showBacklinksModal = false; // 기능 메뉴 상태 this.activeFeatureMenu = null; // 검색 상태 this.searchQuery = ''; this.noteSearchQuery = ''; this.filteredNotes = []; // 텍스트 선택 모드 this.textSelectorUISetup = false; console.log('✅ UIManager 초기화 완료'); } /** * 기능 메뉴 토글 */ toggleFeatureMenu(feature) { if (this.activeFeatureMenu === feature) { this.activeFeatureMenu = null; } else { this.activeFeatureMenu = feature; // 해당 기능의 모달 표시 switch(feature) { case 'link': this.showLinksModal = true; break; case 'memo': this.showNotesModal = true; break; case 'bookmark': this.showBookmarksModal = true; break; case 'backlink': this.showBacklinksModal = true; break; } } } /** * 노트 모달 열기 */ openNoteModal(highlight = null) { console.log('📝 노트 모달 열기'); if (highlight) { console.log('🔍 하이라이트와 연결된 노트 모달:', highlight); } this.showNoteModal = true; } /** * 노트 모달 닫기 */ closeNoteModal() { this.showNoteModal = false; } /** * 링크 모달 열기 */ openLinkModal() { console.log('🔗 링크 모달 열기'); console.log('🔗 showLinksModal 설정 전:', this.showLinksModal); this.showLinksModal = true; this.showLinkModal = true; // 기존 호환성 console.log('🔗 showLinksModal 설정 후:', this.showLinksModal); } /** * 링크 모달 닫기 */ closeLinkModal() { this.showLinksModal = false; this.showLinkModal = false; } /** * 북마크 모달 닫기 */ closeBookmarkModal() { this.showBookmarkModal = false; } /** * 검색 결과 하이라이트 */ highlightSearchResults(element, searchText) { if (!searchText.trim()) return; // 기존 검색 하이라이트 제거 const existingHighlights = element.querySelectorAll('.search-highlight'); existingHighlights.forEach(highlight => { const parent = highlight.parentNode; parent.replaceChild(document.createTextNode(highlight.textContent), highlight); parent.normalize(); }); if (!searchText) return; // 새로운 검색 하이라이트 적용 const walker = document.createTreeWalker( element, NodeFilter.SHOW_TEXT, null, false ); const textNodes = []; let node; while (node = walker.nextNode()) { textNodes.push(node); } const searchRegex = new RegExp(`(${searchText.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi'); textNodes.forEach(textNode => { const text = textNode.textContent; if (searchRegex.test(text)) { const highlightedHTML = text.replace(searchRegex, '$1'); const wrapper = document.createElement('div'); wrapper.innerHTML = highlightedHTML; const fragment = document.createDocumentFragment(); while (wrapper.firstChild) { fragment.appendChild(wrapper.firstChild); } textNode.parentNode.replaceChild(fragment, textNode); } }); } /** * 노트 검색 필터링 */ filterNotes(notes) { if (!this.noteSearchQuery.trim()) { this.filteredNotes = notes; return notes; } const query = this.noteSearchQuery.toLowerCase(); this.filteredNotes = notes.filter(note => note.content.toLowerCase().includes(query) || (note.tags && note.tags.some(tag => tag.toLowerCase().includes(query))) ); return this.filteredNotes; } /** * 텍스트 선택 모드 UI 설정 */ setupTextSelectorUI() { console.log('🔧 setupTextSelectorUI 함수 실행됨'); // 중복 실행 방지 if (this.textSelectorUISetup) { console.log('⚠️ 텍스트 선택 모드 UI가 이미 설정됨 - 중복 실행 방지'); return; } // 헤더 숨기기 const header = document.querySelector('header'); if (header) { header.style.display = 'none'; } // 안내 메시지 표시 const messageDiv = document.createElement('div'); messageDiv.id = 'text-selection-message'; messageDiv.className = 'fixed top-4 left-1/2 transform -translate-x-1/2 bg-blue-500 text-white px-6 py-3 rounded-lg shadow-lg z-50'; messageDiv.innerHTML = `
"${selectedText}"