diff --git a/src/mcp_feedback_enhanced/web/locales/en/translation.json b/src/mcp_feedback_enhanced/web/locales/en/translation.json index ba9e854..eea72ef 100644 --- a/src/mcp_feedback_enhanced/web/locales/en/translation.json +++ b/src/mcp_feedback_enhanced/web/locales/en/translation.json @@ -471,5 +471,42 @@ "testPlaying": "Playing test audio", "audioNotFound": "Selected audio not found" } + }, + "notification": { + "title": "Browser Notifications", + "settingLabel": "Browser Notifications", + "description": "Get notified when new sessions are created (only when in background)", + "enabled": "Notifications enabled ✅", + "disabled": "Notifications disabled", + "permissionRequired": "Notification permission required to enable this feature", + "permissionDenied": "Browser has blocked notifications, please allow in browser settings", + "permissionGranted": "Granted", + "permissionDeniedStatus": "Denied (please modify in browser settings)", + "permissionDefault": "Not set", + "notSupported": "Your browser does not support notifications", + "enableFailed": "Failed to enable notifications", + "test": "Send test notification", + "testTitle": "Test Notification", + "testDescription": "Send a test notification to confirm it's working", + "autoplayBlocked": "Browser blocked autoplay, please click the page to enable audio notifications", + "triggerTitle": "Notification Trigger Context", + "triggerDescription": "Choose when to receive notifications", + "triggerModeUpdated": "Notification trigger mode updated", + "trigger": { + "focusLost": "When window loses focus (switching to other apps)", + "tabSwitch": "When switching to other browser tabs", + "background": "When window is minimized or hidden", + "always": "Always notify (including foreground)" + }, + "browser": { + "title": "MCP Feedback - New Session", + "ready": "Ready", + "unknownProject": "Unknown Project", + "testTitle": "Test Notification", + "testBody": "This is a test notification, it will close automatically in 5 seconds", + "notSupported": "Your browser does not support notifications", + "permissionRequired": "Please grant notification permission first", + "criticalTitle": "MCP Feedback - Warning" + } } } diff --git a/src/mcp_feedback_enhanced/web/locales/zh-CN/translation.json b/src/mcp_feedback_enhanced/web/locales/zh-CN/translation.json index 0578ec8..29f0830 100644 --- a/src/mcp_feedback_enhanced/web/locales/zh-CN/translation.json +++ b/src/mcp_feedback_enhanced/web/locales/zh-CN/translation.json @@ -470,5 +470,42 @@ }, "stats": { "detailedStats": "详细统计信息" + }, + "notification": { + "title": "浏览器通知", + "settingLabel": "浏览器通知", + "description": "新会话建立时通知(仅在后台运行时)", + "enabled": "通知已启用 ✅", + "disabled": "通知已关闭", + "permissionRequired": "需要通知权限才能启用此功能", + "permissionDenied": "浏览器已封锁通知,请在浏览器设置中允许", + "permissionGranted": "已授权", + "permissionDeniedStatus": "已拒绝(请在浏览器设置中修改)", + "permissionDefault": "尚未设置", + "notSupported": "您的浏览器不支持通知功能", + "enableFailed": "启用通知失败", + "test": "发送测试通知", + "testTitle": "测试通知", + "testDescription": "发送测试通知以确认功能正常", + "autoplayBlocked": "浏览器阻止音效自动播放,请点击页面以启用音效通知", + "triggerTitle": "通知触发场景", + "triggerDescription": "选择何时接收通知", + "triggerModeUpdated": "通知触发模式已更新", + "trigger": { + "focusLost": "窗口失去焦点时(切换到其他应用程序)", + "tabSwitch": "切换到其他标签页时", + "background": "窗口最小化或隐藏时", + "always": "总是通知(包括前景)" + }, + "browser": { + "title": "MCP Feedback - 新会话", + "ready": "准备就绪", + "unknownProject": "未知项目", + "testTitle": "测试通知", + "testBody": "这是一个测试通知,5秒后将自动关闭", + "notSupported": "您的浏览器不支持通知功能", + "permissionRequired": "请先授权通知权限", + "criticalTitle": "MCP Feedback - 警告" + } } } diff --git a/src/mcp_feedback_enhanced/web/locales/zh-TW/translation.json b/src/mcp_feedback_enhanced/web/locales/zh-TW/translation.json index 2e8e147..57dbc8c 100644 --- a/src/mcp_feedback_enhanced/web/locales/zh-TW/translation.json +++ b/src/mcp_feedback_enhanced/web/locales/zh-TW/translation.json @@ -475,5 +475,42 @@ }, "stats": { "detailedStats": "詳細統計資訊" + }, + "notification": { + "title": "瀏覽器通知", + "settingLabel": "瀏覽器通知", + "description": "新會話建立時通知(僅在背景執行時)", + "enabled": "通知已啟用 ✅", + "disabled": "通知已關閉", + "permissionRequired": "需要通知權限才能啟用此功能", + "permissionDenied": "瀏覽器已封鎖通知,請在瀏覽器設定中允許", + "permissionGranted": "已授權", + "permissionDeniedStatus": "已拒絕(請在瀏覽器設定中修改)", + "permissionDefault": "尚未設定", + "notSupported": "您的瀏覽器不支援通知功能", + "enableFailed": "啟用通知失敗", + "test": "發送測試通知", + "testTitle": "測試通知", + "testDescription": "發送測試通知以確認功能正常", + "autoplayBlocked": "瀏覽器阻止音效自動播放,請點擊頁面以啟用音效通知", + "triggerTitle": "通知觸發情境", + "triggerDescription": "選擇何時接收通知", + "triggerModeUpdated": "通知觸發模式已更新", + "trigger": { + "focusLost": "視窗失去焦點時(切換到其他應用程式)", + "tabSwitch": "切換到其他標籤頁時", + "background": "視窗最小化或隱藏時", + "always": "總是通知(包括前景)" + }, + "browser": { + "title": "MCP Feedback - 新會話", + "ready": "準備就緒", + "unknownProject": "未知專案", + "testTitle": "測試通知", + "testBody": "這是一個測試通知,5秒後將自動關閉", + "notSupported": "您的瀏覽器不支援通知功能", + "permissionRequired": "請先授權通知權限", + "criticalTitle": "MCP Feedback - 警告" + } } } diff --git a/src/mcp_feedback_enhanced/web/static/css/audio-management.css b/src/mcp_feedback_enhanced/web/static/css/audio-management.css index c10ec86..1629327 100644 --- a/src/mcp_feedback_enhanced/web/static/css/audio-management.css +++ b/src/mcp_feedback_enhanced/web/static/css/audio-management.css @@ -8,44 +8,15 @@ /* ===== 音效管理區塊樣式 ===== */ -.audio-management-section { - background: var(--bg-tertiary); - border: 1px solid var(--border-color); - border-radius: 12px; - padding: 20px; - margin-bottom: 20px; - transition: all 0.3s ease; -} - -.audio-management-section:hover { - border-color: var(--accent-color); - box-shadow: 0 2px 8px rgba(0, 122, 204, 0.1); -} - -.audio-management-header { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 12px; - padding-bottom: 12px; - border-bottom: 1px solid var(--border-color); -} - -.audio-management-title { - color: var(--text-primary); - font-size: 16px; - font-weight: 600; - margin: 0; - display: flex; - align-items: center; - gap: 8px; -} +/* 音效描述文字 */ .audio-management-description { color: var(--text-secondary); font-size: 14px; margin-bottom: 20px; line-height: 1.4; + padding-bottom: 16px; + border-bottom: 1px solid var(--border-color); } /* ===== 音效設定控制項樣式 ===== */ diff --git a/src/mcp_feedback_enhanced/web/static/css/notification-settings.css b/src/mcp_feedback_enhanced/web/static/css/notification-settings.css new file mode 100644 index 0000000..6cef93d --- /dev/null +++ b/src/mcp_feedback_enhanced/web/static/css/notification-settings.css @@ -0,0 +1,152 @@ +/** + * MCP Feedback Enhanced - 瀏覽器通知設定樣式 + * ======================================== + */ + +/* 權限狀態顯示 */ +.permission-status { + font-size: 12px; + margin-top: 8px; + display: block; /* 使用 block 讓內容自然流動 */ +} + +.permission-status span { + display: inline-block; /* 確保內容在同一行 */ + white-space: nowrap; /* 防止文字換行 */ + line-height: 1.2; /* 適當的行高 */ +} + +/* 權限狀態樣式 */ +.status-granted { + color: #059669; +} + +.status-denied { + color: #dc2626; +} + +.status-default { + color: #6366f1; +} + +.status-unsupported { + color: #d97706; +} + +/* 觸發情境選項 */ +.notification-trigger { + margin-top: 12px; + padding-top: 12px; + border-top: 1px solid rgba(0, 0, 0, 0.1); +} + +.trigger-options { + margin-top: 12px; + display: flex; + flex-direction: column; + gap: 10px; +} + +.radio-option { + display: flex; + align-items: center; + padding: 8px 12px; + background-color: var(--bg-secondary, #f9fafb); + border-radius: 6px; + cursor: pointer; + transition: background-color 0.2s ease; +} + +.radio-option:hover { + background-color: var(--bg-hover, #f3f4f6); +} + +.radio-option input[type="radio"] { + margin-right: 10px; + cursor: pointer; +} + +.radio-option span { + font-size: 14px; + color: var(--text-primary, #1f2937); + line-height: 1.4; +} + +/* 測試按鈕區塊 */ +.notification-actions { + margin-top: 16px; +} + +.notification-actions .btn-primary { + padding: 8px 16px; + font-size: 14px; + background-color: var(--primary-color, #007acc); + color: white; + border: none; + border-radius: 6px; + cursor: pointer; + transition: background-color 0.2s ease; +} + +.notification-actions .btn-primary:hover { + background-color: var(--primary-hover, #0066b3); +} + +/* 通知設定專用的 setting-info 調整 */ +#notificationSettings .setting-info { + max-width: calc(100% - 100px); /* 為開關預留空間 */ +} + +/* 響應式設計 */ +@media (max-width: 768px) { + .permission-status { + font-size: 11px; + } + + #notificationSettings .setting-info { + max-width: calc(100% - 80px); /* 小螢幕上調整空間 */ + } + + .radio-option { + padding: 6px 10px; + } + + .radio-option span { + font-size: 13px; + } +} + +/* 深色模式支援 */ +@media (prefers-color-scheme: dark) { + .status-granted { + color: #34d399; + } + + .status-denied { + color: #f87171; + } + + .status-default { + color: #a5b4fc; + } + + .status-unsupported { + color: #fbbf24; + } + + .notification-trigger { + border-top-color: rgba(255, 255, 255, 0.1); + } + + .radio-option { + background-color: rgba(255, 255, 255, 0.05); + } + + .radio-option:hover { + background-color: rgba(255, 255, 255, 0.1); + } + + .radio-option span { + color: #e5e7eb; + } +} \ No newline at end of file diff --git a/src/mcp_feedback_enhanced/web/static/js/app.js b/src/mcp_feedback_enhanced/web/static/js/app.js index 8c848c4..7b23812 100644 --- a/src/mcp_feedback_enhanced/web/static/js/app.js +++ b/src/mcp_feedback_enhanced/web/static/js/app.js @@ -42,6 +42,10 @@ this.audioManager = null; this.audioSettingsUI = null; + // 通知管理器 + this.notificationManager = null; + this.notificationSettings = null; + // 自動提交管理器 this.autoSubmitManager = null; @@ -239,25 +243,28 @@ // 10. 初始化音效管理器 self.initializeAudioManagers(); - // 11. 初始化自動提交管理器 + // 11. 初始化通知管理器 + self.initializeNotificationManager(); + + // 12. 初始化自動提交管理器 self.initializeAutoSubmitManager(); - // 12. 初始化 Textarea 高度管理器 + // 13. 初始化 Textarea 高度管理器 self.initializeTextareaHeightManager(); - // 13. 應用設定到 UI + // 14. 應用設定到 UI self.settingsManager.applyToUI(); - // 14. 初始化各個管理器 + // 15. 初始化各個管理器 self.uiManager.initTabs(); self.imageHandler.init(); - // 15. 檢查並啟動自動提交(如果條件滿足) + // 16. 檢查並啟動自動提交(如果條件滿足) setTimeout(function() { self.checkAndStartAutoSubmit(); }, 500); // 延遲 500ms 確保所有初始化完成 - // 16. 播放啟動音效(如果音效已啟用) + // 17. 播放啟動音效(如果音效已啟用) setTimeout(function() { if (self.audioManager) { self.audioManager.playStartupNotification(); @@ -523,6 +530,52 @@ } }; + /** + * 初始化通知管理器 + */ + FeedbackApp.prototype.initializeNotificationManager = function() { + console.log('🔔 初始化通知管理器...'); + + try { + // 檢查通知模組是否已載入 + if (!window.MCPFeedback.NotificationManager) { + console.warn('⚠️ 通知模組未載入,跳過初始化'); + return; + } + + // 1. 初始化通知管理器 + this.notificationManager = new window.MCPFeedback.NotificationManager({ + t: window.i18nManager ? window.i18nManager.t.bind(window.i18nManager) : function(key, defaultValue) { return defaultValue || key; } + }); + this.notificationManager.initialize(); + + // 2. 初始化通知設定 UI + if (window.MCPFeedback.NotificationSettings) { + const notificationContainer = document.querySelector('#notificationSettingsContainer'); + console.log('🔍 通知設定容器:', notificationContainer); + + if (notificationContainer) { + this.notificationSettings = new window.MCPFeedback.NotificationSettings({ + container: notificationContainer, + notificationManager: this.notificationManager, + t: window.i18nManager ? window.i18nManager.t.bind(window.i18nManager) : function(key, defaultValue) { return defaultValue || key; } + }); + this.notificationSettings.initialize(); + console.log('✅ 通知設定 UI 初始化完成'); + } else { + console.error('❌ 找不到通知設定容器元素 notificationSettingsContainer'); + } + } else { + console.warn('⚠️ NotificationSettings 模組未載入'); + } + + console.log('✅ 通知管理器初始化完成'); + + } catch (error) { + console.error('❌ 通知管理器初始化失敗:', error); + } + }; + /** * 初始化 Textarea 高度管理器 */ @@ -720,6 +773,14 @@ this.audioManager.playNotification(); } + // 發送瀏覽器通知 + if (this.notificationManager && data.session_info) { + this.notificationManager.notifyNewSession( + data.session_info.session_id, + data.session_info.project_directory || data.project_directory || '未知專案' + ); + } + // 顯示新會話通知 window.MCPFeedback.Utils.showMessage( data.message || '新的 MCP 會話已創建,正在更新內容...', diff --git a/src/mcp_feedback_enhanced/web/static/js/modules/audio/audio-settings-ui.js b/src/mcp_feedback_enhanced/web/static/js/modules/audio/audio-settings-ui.js index 19d197e..587a95d 100644 --- a/src/mcp_feedback_enhanced/web/static/js/modules/audio/audio-settings-ui.js +++ b/src/mcp_feedback_enhanced/web/static/js/modules/audio/audio-settings-ui.js @@ -70,17 +70,18 @@ */ AudioSettingsUI.prototype.createUI = function() { const html = ` -