// 설정 페이지 JavaScript class SettingsManager { constructor() { this.config = null; this.userInfo = null; this.currentSettings = {}; this.timeAlarmSettings = {}; // 회원등급별 사용 가능한 엔진 정의 this.availableEngines = { 'basic': ['google', 'mymemory'], 'premium': ['google', 'mymemory', 'deepl'], 'vip': ['google', 'mymemory', 'deepl', 'openai'] }; // 엔진별 상세 정보 this.engineInfo = { 'google': { name: 'Google 번역', description: '빠른 속도와 다양한 언어 지원을 제공하는 구글의 무료 번역 서비스', level: 'basic' }, 'mymemory': { name: 'MyMemory 번역', description: '번역 메모리 기반으로 높은 품질의 번역을 제공하는 무료 서비스', level: 'basic' }, 'deepl': { name: 'DeepL 번역', description: '높은 번역 품질로 유명한 AI 번역 서비스', level: 'premium' }, 'openai': { name: 'OpenAI ChatGPT', description: '문맥을 이해하는 고품질 AI 번역, 의역 및 설명 포함', level: 'vip' }, 'gemini': { name: 'Google Gemini', description: '구글의 최신 AI 모델, 자연스러운 번역과 의역 제공', level: 'vip' } }; this.init(); } async init() { try { console.log('설정 페이지 초기화 시작'); // 탭 기능 초기화 this.initTabs(); await this.loadConfig(); await this.loadUserInfo(); await this.loadCurrentSettings(); await this.loadTimeAlarmSettings(); // UI 초기화 this.initializeUI(); this.initializeTimeAlarmUI(); this.setupEventListeners(); this.updateUI(); console.log('설정 페이지 초기화 완료'); } catch (error) { console.error('설정 페이지 초기화 실패:', error); this.showMessage('설정 페이지를 초기화하는 중 오류가 발생했습니다.', 'error'); } } // 탭 기능 초기화 initTabs() { const tabButtons = document.querySelectorAll('.tab-button'); const tabContents = document.querySelectorAll('.tab-content'); tabButtons.forEach(button => { button.addEventListener('click', () => { const targetTab = button.dataset.tab; // 모든 탭 버튼과 컨텐츠 비활성화 tabButtons.forEach(btn => btn.classList.remove('active')); tabContents.forEach(content => content.classList.remove('active')); // 선택된 탭 활성화 button.classList.add('active'); const targetContent = document.getElementById(`${targetTab}-tab`); if (targetContent) { targetContent.classList.add('active'); } console.log(`탭 전환: ${targetTab}`); }); }); } async loadConfig() { try { const result = await chrome.storage.local.get('settings_config'); this.config = result.settings_config || {}; console.log('설정을 settings_config에서 로드함:', this.config); } catch (error) { console.error('설정 로드 실패:', error); this.config = {}; } } async loadUserInfo() { try { console.log('사용자 정보 로드 시작...'); if (!this.config || !this.config.ACCESS_TOKEN) { console.warn('액세스 토큰이 없습니다. 기본 회원으로 설정합니다.'); this.userInfo = { membership_level: 'basic' }; return; } const SUPABASE_URL = this.config.SUPABASE_URL || "http://146.56.101.199:8000"; const SUPABASE_ANON_KEY = this.config.SUPABASE_ANON_KEY || "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.ey AgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE"; console.log('Supabase URL:', SUPABASE_URL); console.log('토큰 존재 여부:', !!this.config.ACCESS_TOKEN); // 사용자 기본 정보 가져오기 const authUrl = `${SUPABASE_URL}/auth/v1/user`; console.log('사용자 인증 요청:', authUrl); const authRes = await fetch(authUrl, { headers: { Authorization: `Bearer ${this.config.ACCESS_TOKEN}`, apikey: SUPABASE_ANON_KEY, 'Content-Type': 'application/json' } }); console.log('인증 응답 상태:', authRes.status, authRes.statusText); if (!authRes.ok) { const errorText = await authRes.text(); console.error('사용자 인증 실패:', errorText); throw new Error(`사용자 인증 실패: ${authRes.status}`); } const authUser = await authRes.json(); console.log('인증된 사용자:', authUser); if (!authUser || !authUser.email) { throw new Error('사용자 이메일 정보가 없습니다.'); } // 사용자 상세 정보 가져오기 const detailsUrl = `${SUPABASE_URL}/rest/v1/users?select=*&email=eq.${encodeURIComponent(authUser.email)}&limit=1`; console.log('사용자 상세 정보 요청:', detailsUrl); const detailsRes = await fetch(detailsUrl, { headers: { Authorization: `Bearer ${this.config.ACCESS_TOKEN}`, apikey: SUPABASE_ANON_KEY, 'Content-Type': 'application/json' } }); console.log('상세 정보 응답 상태:', detailsRes.status, detailsRes.statusText); if (!detailsRes.ok) { const errorText = await detailsRes.text(); console.error('사용자 정보 조회 실패:', errorText); throw new Error(`사용자 정보 조회 실패: ${detailsRes.status}`); } const detailsData = await detailsRes.json(); console.log('사용자 상세 정보:', detailsData); if (!detailsData || !Array.isArray(detailsData) || detailsData.length === 0) { console.warn('사용자 상세 정보가 없습니다. 기본 회원으로 설정합니다.'); this.userInfo = { email: authUser.email, membership_level: 'basic' }; } else { this.userInfo = detailsData[0]; // membership_level이 없으면 기본값 설정 if (!this.userInfo.membership_level) { this.userInfo.membership_level = 'basic'; } } console.log('사용자 정보 로드 완료:', this.userInfo); } catch (error) { console.error('사용자 정보 로드 실패:', error); this.userInfo = { membership_level: 'basic' }; console.log('기본 회원으로 설정됨'); } } async loadCurrentSettings() { try { const result = await chrome.storage.local.get('translation_engine_settings'); this.currentSettings = result.translation_engine_settings || {}; // 기본값 설정 (구글만 활성화, 나머지는 비활성화) const defaultSettings = { google: true, // 구글만 기본 활성화 mymemory: false, // MyMemory 비활성화 deepl: false, // DeepL 비활성화 openai: false, // OpenAI 비활성화 gemini: false // Gemini 비활성화 }; // 기존 설정이 없으면 기본값 사용 Object.keys(defaultSettings).forEach(engine => { if (this.currentSettings[engine] === undefined) { this.currentSettings[engine] = defaultSettings[engine]; } }); console.log('현재 설정 로드:', this.currentSettings); } catch (error) { console.error('현재 설정 로드 실패:', error); // 기본값으로 구글만 활성화 this.currentSettings = { google: true, mymemory: false, deepl: false, openai: false, gemini: false }; } } async loadTimeAlarmSettings() { try { const result = await chrome.storage.local.get('time_alarm_settings'); this.timeAlarmSettings = result.time_alarm_settings || { enabled: true, workTime: 60, // 분 restTime: 5, // 분 autoZzim: false }; console.log('시간 알람 설정 로드 완료:', this.timeAlarmSettings); } catch (error) { console.error('시간 알람 설정 로드 실패:', error); this.timeAlarmSettings = { enabled: true, workTime: 60, restTime: 5, autoZzim: false }; } } initializeUI() { // 회원등급 정보 표시 const membershipElement = document.getElementById('current-membership'); const membershipInfoElement = document.getElementById('membership-engines-info'); if (membershipElement && this.userInfo) { const level = this.userInfo.membership_level || 'basic'; const levelNames = { 'basic': '기본 회원', 'premium': '프리미엄 회원', 'vip': 'VIP 회원' }; membershipElement.textContent = levelNames[level.toLowerCase()] || '기본 회원'; const availableEngines = this.availableEngines[level.toLowerCase()] || this.availableEngines.basic; const engineNames = availableEngines.map(engine => this.engineInfo[engine].name); membershipInfoElement.innerHTML = ` 사용 가능한 번역 엔진:
${engineNames.join(', ')}

등급별 혜택:
• 기본: Google, MyMemory (무료 엔진)
• 프리미엄: + DeepL (고품질 엔진)
• VIP: + ChatGPT `; console.log('회원등급 UI 업데이트 완료:', level); } else { console.error('회원등급 표시 요소를 찾을 수 없습니다.'); } } // 시간 알람 UI 초기화 initializeTimeAlarmUI() { this.updateTimeAlarmUI(); } setupEventListeners() { // 토글 스위치 이벤트 const toggleSwitches = document.querySelectorAll('.toggle-switch'); toggleSwitches.forEach(toggle => { toggle.addEventListener('click', (e) => { const engine = e.target.dataset.engine; if (engine && !e.target.classList.contains('disabled')) { this.toggleEngine(engine); } else if (e.target.id === 'timeAlarmToggle') { // 시간 알람 토글 this.timeAlarmSettings.enabled = !this.timeAlarmSettings.enabled; this.updateTimeAlarmUI(); console.log('시간 알람 토글:', this.timeAlarmSettings.enabled); } }); }); // 저장 버튼 const saveButton = document.getElementById('save-settings'); if (saveButton) { saveButton.addEventListener('click', () => this.saveSettings()); } // 기본값 복원 버튼 const resetButton = document.getElementById('reset-settings'); if (resetButton) { resetButton.addEventListener('click', () => this.resetToDefaults()); } // 시간 입력 필드 이벤트 const workTimeInput = document.getElementById('workTimeInput'); const restTimeInput = document.getElementById('restTimeInput'); const autoZzimCheckbox = document.getElementById('autoZzimCheckbox'); if (workTimeInput) { workTimeInput.addEventListener('change', (e) => { this.timeAlarmSettings.workTime = parseInt(e.target.value) || 60; }); } if (restTimeInput) { restTimeInput.addEventListener('change', (e) => { this.timeAlarmSettings.restTime = parseInt(e.target.value) || 5; }); } if (autoZzimCheckbox) { autoZzimCheckbox.addEventListener('change', (e) => { this.timeAlarmSettings.autoZzim = e.target.checked; }); } } updateUI() { const userLevel = (this.userInfo?.membership_level || 'basic').toLowerCase(); const availableEngines = this.availableEngines[userLevel] || this.availableEngines.basic; // 각 엔진 아이템 업데이트 const engineItems = document.querySelectorAll('.engine-item'); engineItems.forEach(item => { const engine = item.dataset.engine; const toggle = item.querySelector('.toggle-switch'); if (availableEngines.includes(engine)) { // 사용 가능한 엔진 item.classList.remove('disabled'); toggle.classList.remove('disabled'); // 현재 설정에 따라 토글 상태 설정 if (this.currentSettings[engine]) { toggle.classList.add('active'); } else { toggle.classList.remove('active'); } } else { // 사용 불가능한 엔진 item.classList.add('disabled'); toggle.classList.add('disabled'); toggle.classList.remove('active'); } }); // 시간 알람 UI 업데이트 this.updateTimeAlarmUI(); } updateTimeAlarmUI() { const timeAlarmToggle = document.getElementById('timeAlarmToggle'); const workTimeInput = document.getElementById('workTimeInput'); const restTimeInput = document.getElementById('restTimeInput'); const autoZzimCheckbox = document.getElementById('autoZzimCheckbox'); if (timeAlarmToggle) { if (this.timeAlarmSettings.enabled) { timeAlarmToggle.classList.add('active'); } else { timeAlarmToggle.classList.remove('active'); } } if (workTimeInput) { workTimeInput.value = this.timeAlarmSettings.workTime; } if (restTimeInput) { restTimeInput.value = this.timeAlarmSettings.restTime; } if (autoZzimCheckbox) { autoZzimCheckbox.checked = this.timeAlarmSettings.autoZzim; } } toggleEngine(engine) { this.currentSettings[engine] = !this.currentSettings[engine]; this.updateUI(); console.log(`${engine} 엔진 토글:`, this.currentSettings[engine]); } async saveSettings() { try { this.showLoading(true); // 시간 알람 설정 업데이트 const workTimeInput = document.getElementById('workTimeInput'); const restTimeInput = document.getElementById('restTimeInput'); const autoZzimCheckbox = document.getElementById('autoZzimCheckbox'); if (workTimeInput) { this.timeAlarmSettings.workTime = parseInt(workTimeInput.value) || 60; } if (restTimeInput) { this.timeAlarmSettings.restTime = parseInt(restTimeInput.value) || 5; } if (autoZzimCheckbox) { this.timeAlarmSettings.autoZzim = autoZzimCheckbox.checked; } // 번역 엔진 설정 저장 await chrome.storage.local.set({ 'translation_engine_settings': this.currentSettings }); // 시간 알람 설정 저장 await chrome.storage.local.set({ 'time_alarm_settings': this.timeAlarmSettings }); // Background script에 시간 알람 설정 변경 알림 chrome.runtime.sendMessage({ action: 'updateTimeAlarmSettings', settings: this.timeAlarmSettings }); console.log('설정 저장 완료:', { translation: this.currentSettings, timeAlarm: this.timeAlarmSettings }); this.showMessage('설정이 성공적으로 저장되었습니다.', 'success'); } catch (error) { console.error('설정 저장 실패:', error); this.showMessage('설정 저장 중 오류가 발생했습니다.', 'error'); } finally { this.showLoading(false); } } async resetToDefaults() { if (!confirm('모든 설정을 기본값으로 복원하시겠습니까?')) { return; } try { this.showLoading(true); // 기본값으로 재설정 (구글만 활성화) this.currentSettings = { google: true, mymemory: false, deepl: false, openai: false, gemini: false }; // 저장 await chrome.storage.local.set({ 'translation_engine_settings': this.currentSettings }); // UI 업데이트 this.updateUI(); // 시간 알람 설정 초기화 this.timeAlarmSettings = { enabled: false, workTime: 60, restTime: 5, autoZzim: false }; // 저장소에서 시간 알람 설정 제거 await chrome.storage.local.remove('time_alarm_settings'); // Background script에 알림 chrome.runtime.sendMessage({ action: 'updateTimeAlarmSettings', settings: this.timeAlarmSettings }); console.log('기본값 복원 완료'); this.showMessage('설정이 기본값으로 복원되었습니다.', 'success'); } catch (error) { console.error('기본값 복원 실패:', error); this.showMessage('기본값 복원 중 오류가 발생했습니다.', 'error'); } finally { this.showLoading(false); } } showMessage(text, type = 'info') { const messageElement = document.getElementById('message'); if (messageElement) { messageElement.textContent = text; messageElement.className = `message ${type}`; messageElement.style.display = 'block'; // 3초 후 자동 숨김 setTimeout(() => { messageElement.style.display = 'none'; }, 3000); } } showLoading(show) { const loadingElement = document.getElementById('loading'); if (loadingElement) { loadingElement.style.display = show ? 'block' : 'none'; } } } // 페이지 로드 시 초기화 document.addEventListener('DOMContentLoaded', () => { console.log('설정 페이지 DOM 로드 완료'); new SettingsManager(); }); // 창 닫기 전 확인 window.addEventListener('beforeunload', (e) => { // 설정이 변경되었는지 확인하는 로직을 추가할 수 있음 // 현재는 단순히 로그만 출력 console.log('설정 페이지 종료'); });