mirror of
https://github.com/Minidoracat/mcp-feedback-enhanced.git
synced 2025-07-27 10:42:25 +08:00
✨ 新增輸入框高度保存
This commit is contained in:
parent
39102a92c3
commit
17eb95f9e5
@ -207,19 +207,22 @@
|
||||
// 11. 初始化自動提交管理器
|
||||
self.initializeAutoSubmitManager();
|
||||
|
||||
// 11. 應用設定到 UI
|
||||
// 12. 初始化 Textarea 高度管理器
|
||||
self.initializeTextareaHeightManager();
|
||||
|
||||
// 13. 應用設定到 UI
|
||||
self.settingsManager.applyToUI();
|
||||
|
||||
// 12. 初始化各個管理器
|
||||
// 14. 初始化各個管理器
|
||||
self.uiManager.initTabs();
|
||||
self.imageHandler.init();
|
||||
|
||||
// 13. 檢查並啟動自動提交(如果條件滿足)
|
||||
// 15. 檢查並啟動自動提交(如果條件滿足)
|
||||
setTimeout(function() {
|
||||
self.checkAndStartAutoSubmit();
|
||||
}, 500); // 延遲 500ms 確保所有初始化完成
|
||||
|
||||
// 14. 建立 WebSocket 連接
|
||||
// 16. 建立 WebSocket 連接
|
||||
self.webSocketManager.connect();
|
||||
|
||||
resolve();
|
||||
@ -473,6 +476,47 @@
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 初始化 Textarea 高度管理器
|
||||
*/
|
||||
FeedbackApp.prototype.initializeTextareaHeightManager = function() {
|
||||
console.log('📏 初始化 Textarea 高度管理器...');
|
||||
|
||||
try {
|
||||
// 檢查 TextareaHeightManager 模組是否已載入
|
||||
if (!window.MCPFeedback.TextareaHeightManager) {
|
||||
console.warn('⚠️ TextareaHeightManager 模組未載入,跳過初始化');
|
||||
return;
|
||||
}
|
||||
|
||||
// 建立 TextareaHeightManager 實例
|
||||
this.textareaHeightManager = new window.MCPFeedback.TextareaHeightManager({
|
||||
settingsManager: this.settingsManager,
|
||||
debounceDelay: 500 // 500ms 防抖延遲
|
||||
});
|
||||
|
||||
// 初始化管理器
|
||||
this.textareaHeightManager.initialize();
|
||||
|
||||
// 註冊 combinedFeedbackText textarea
|
||||
const success = this.textareaHeightManager.registerTextarea(
|
||||
'combinedFeedbackText',
|
||||
'combinedFeedbackTextHeight'
|
||||
);
|
||||
|
||||
if (success) {
|
||||
console.log('✅ combinedFeedbackText 高度管理已啟用');
|
||||
} else {
|
||||
console.warn('⚠️ combinedFeedbackText 註冊失敗');
|
||||
}
|
||||
|
||||
console.log('✅ Textarea 高度管理器初始化完成');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Textarea 高度管理器初始化失敗:', error);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 處理 WebSocket 開啟
|
||||
*/
|
||||
@ -1451,7 +1495,9 @@
|
||||
this.imageHandler.cleanup();
|
||||
}
|
||||
|
||||
|
||||
if (this.textareaHeightManager) {
|
||||
this.textareaHeightManager.destroy();
|
||||
}
|
||||
|
||||
console.log('✅ 應用程式資源清理完成');
|
||||
};
|
||||
|
@ -40,7 +40,9 @@
|
||||
sessionHistoryRetentionHours: 72,
|
||||
// 用戶訊息記錄設定
|
||||
userMessageRecordingEnabled: true,
|
||||
userMessagePrivacyLevel: 'full' // 'full', 'basic', 'disabled'
|
||||
userMessagePrivacyLevel: 'full', // 'full', 'basic', 'disabled'
|
||||
// UI 元素尺寸設定
|
||||
combinedFeedbackTextHeight: 150 // combinedFeedbackText textarea 的高度(px)
|
||||
};
|
||||
|
||||
// 當前設定
|
||||
|
@ -0,0 +1,267 @@
|
||||
/**
|
||||
* Textarea 高度管理器
|
||||
* 負責監聽 textarea 高度變化並持久化設定
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
// 確保命名空間存在
|
||||
window.MCPFeedback = window.MCPFeedback || {};
|
||||
const Utils = window.MCPFeedback.Utils;
|
||||
|
||||
/**
|
||||
* TextareaHeightManager 建構函數
|
||||
*/
|
||||
function TextareaHeightManager(options) {
|
||||
options = options || {};
|
||||
|
||||
// 設定管理器實例
|
||||
this.settingsManager = options.settingsManager || null;
|
||||
|
||||
// 已註冊的 textarea 元素
|
||||
this.registeredTextareas = new Map();
|
||||
|
||||
// ResizeObserver 實例
|
||||
this.resizeObserver = null;
|
||||
|
||||
// 防抖計時器
|
||||
this.debounceTimers = new Map();
|
||||
|
||||
// 防抖延遲(毫秒)
|
||||
this.debounceDelay = options.debounceDelay || 500;
|
||||
|
||||
console.log('📏 TextareaHeightManager 建構函數初始化完成');
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化高度管理器
|
||||
*/
|
||||
TextareaHeightManager.prototype.initialize = function() {
|
||||
console.log('📏 開始初始化 TextareaHeightManager...');
|
||||
|
||||
// 檢查 ResizeObserver 支援
|
||||
if (!window.ResizeObserver) {
|
||||
console.warn('📏 瀏覽器不支援 ResizeObserver,將使用備用方案');
|
||||
this.initializeFallback();
|
||||
return;
|
||||
}
|
||||
|
||||
// 建立 ResizeObserver
|
||||
this.createResizeObserver();
|
||||
|
||||
console.log('✅ TextareaHeightManager 初始化完成');
|
||||
};
|
||||
|
||||
/**
|
||||
* 建立 ResizeObserver
|
||||
*/
|
||||
TextareaHeightManager.prototype.createResizeObserver = function() {
|
||||
const self = this;
|
||||
|
||||
this.resizeObserver = new ResizeObserver(function(entries) {
|
||||
entries.forEach(function(entry) {
|
||||
const element = entry.target;
|
||||
const config = self.registeredTextareas.get(element);
|
||||
|
||||
if (config) {
|
||||
self.handleResize(element, config);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
console.log('📏 ResizeObserver 建立完成');
|
||||
};
|
||||
|
||||
/**
|
||||
* 處理 textarea 尺寸變化
|
||||
*/
|
||||
TextareaHeightManager.prototype.handleResize = function(element, config) {
|
||||
const self = this;
|
||||
const settingKey = config.settingKey;
|
||||
|
||||
// 清除之前的防抖計時器
|
||||
if (this.debounceTimers.has(settingKey)) {
|
||||
clearTimeout(this.debounceTimers.get(settingKey));
|
||||
}
|
||||
|
||||
// 設定新的防抖計時器
|
||||
const timer = setTimeout(function() {
|
||||
const currentHeight = element.offsetHeight;
|
||||
|
||||
// 檢查高度是否有變化
|
||||
if (currentHeight !== config.lastHeight) {
|
||||
console.log('📏 偵測到 ' + settingKey + ' 高度變化:', config.lastHeight + 'px → ' + currentHeight + 'px');
|
||||
|
||||
// 更新記錄的高度
|
||||
config.lastHeight = currentHeight;
|
||||
|
||||
// 保存到設定
|
||||
if (self.settingsManager) {
|
||||
self.settingsManager.set(settingKey, currentHeight);
|
||||
}
|
||||
}
|
||||
|
||||
// 清除計時器記錄
|
||||
self.debounceTimers.delete(settingKey);
|
||||
}, this.debounceDelay);
|
||||
|
||||
this.debounceTimers.set(settingKey, timer);
|
||||
};
|
||||
|
||||
/**
|
||||
* 註冊 textarea 元素
|
||||
*/
|
||||
TextareaHeightManager.prototype.registerTextarea = function(elementId, settingKey) {
|
||||
const element = Utils.safeQuerySelector('#' + elementId);
|
||||
|
||||
if (!element) {
|
||||
console.warn('📏 找不到元素:', elementId);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (element.tagName.toLowerCase() !== 'textarea') {
|
||||
console.warn('📏 元素不是 textarea:', elementId);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 載入並應用保存的高度
|
||||
this.loadAndApplyHeight(element, settingKey);
|
||||
|
||||
// 建立配置物件
|
||||
const config = {
|
||||
elementId: elementId,
|
||||
settingKey: settingKey,
|
||||
lastHeight: element.offsetHeight
|
||||
};
|
||||
|
||||
// 註冊到 Map
|
||||
this.registeredTextareas.set(element, config);
|
||||
|
||||
// 開始監聽
|
||||
if (this.resizeObserver) {
|
||||
this.resizeObserver.observe(element);
|
||||
}
|
||||
|
||||
console.log('📏 已註冊 textarea:', elementId, '設定鍵:', settingKey);
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* 載入並應用保存的高度
|
||||
*/
|
||||
TextareaHeightManager.prototype.loadAndApplyHeight = function(element, settingKey) {
|
||||
if (!this.settingsManager) {
|
||||
console.warn('📏 沒有設定管理器,無法載入高度設定');
|
||||
return;
|
||||
}
|
||||
|
||||
const savedHeight = this.settingsManager.get(settingKey);
|
||||
|
||||
if (savedHeight && typeof savedHeight === 'number' && savedHeight > 0) {
|
||||
// 確保不小於最小高度
|
||||
const minHeight = this.getMinHeight(element);
|
||||
const finalHeight = Math.max(savedHeight, minHeight);
|
||||
|
||||
// 應用高度
|
||||
element.style.height = finalHeight + 'px';
|
||||
|
||||
console.log('📏 已恢復 ' + settingKey + ' 高度:', finalHeight + 'px');
|
||||
} else {
|
||||
console.log('📏 沒有找到 ' + settingKey + ' 的保存高度,使用預設值');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 獲取元素的最小高度
|
||||
*/
|
||||
TextareaHeightManager.prototype.getMinHeight = function(element) {
|
||||
const computedStyle = window.getComputedStyle(element);
|
||||
const minHeight = computedStyle.minHeight;
|
||||
|
||||
if (minHeight && minHeight !== 'none') {
|
||||
const value = parseInt(minHeight);
|
||||
if (!isNaN(value)) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
// 預設最小高度
|
||||
return 150;
|
||||
};
|
||||
|
||||
/**
|
||||
* 取消註冊 textarea 元素
|
||||
*/
|
||||
TextareaHeightManager.prototype.unregisterTextarea = function(elementId) {
|
||||
const element = Utils.safeQuerySelector('#' + elementId);
|
||||
|
||||
if (!element) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const config = this.registeredTextareas.get(element);
|
||||
|
||||
if (config) {
|
||||
// 停止監聽
|
||||
if (this.resizeObserver) {
|
||||
this.resizeObserver.unobserve(element);
|
||||
}
|
||||
|
||||
// 清除防抖計時器
|
||||
if (this.debounceTimers.has(config.settingKey)) {
|
||||
clearTimeout(this.debounceTimers.get(config.settingKey));
|
||||
this.debounceTimers.delete(config.settingKey);
|
||||
}
|
||||
|
||||
// 從 Map 中移除
|
||||
this.registeredTextareas.delete(element);
|
||||
|
||||
console.log('📏 已取消註冊 textarea:', elementId);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* 備用方案初始化(當不支援 ResizeObserver 時)
|
||||
*/
|
||||
TextareaHeightManager.prototype.initializeFallback = function() {
|
||||
console.log('📏 使用備用方案初始化...');
|
||||
|
||||
// 備用方案可以使用 MutationObserver 或定期檢查
|
||||
// 這裡先實作基本功能,主要是載入保存的高度
|
||||
console.log('📏 備用方案初始化完成(僅支援載入功能)');
|
||||
};
|
||||
|
||||
/**
|
||||
* 銷毀管理器
|
||||
*/
|
||||
TextareaHeightManager.prototype.destroy = function() {
|
||||
console.log('📏 開始銷毀 TextareaHeightManager...');
|
||||
|
||||
// 清除所有防抖計時器
|
||||
this.debounceTimers.forEach(function(timer) {
|
||||
clearTimeout(timer);
|
||||
});
|
||||
this.debounceTimers.clear();
|
||||
|
||||
// 停止所有監聽
|
||||
if (this.resizeObserver) {
|
||||
this.resizeObserver.disconnect();
|
||||
this.resizeObserver = null;
|
||||
}
|
||||
|
||||
// 清除註冊記錄
|
||||
this.registeredTextareas.clear();
|
||||
|
||||
console.log('✅ TextareaHeightManager 銷毀完成');
|
||||
};
|
||||
|
||||
// 將 TextareaHeightManager 加入命名空間
|
||||
window.MCPFeedback.TextareaHeightManager = TextareaHeightManager;
|
||||
|
||||
console.log('✅ TextareaHeightManager 模組載入完成');
|
||||
|
||||
})();
|
@ -1153,6 +1153,7 @@
|
||||
<script src="/static/js/modules/image-handler.js?v=2025010510"></script>
|
||||
<script src="/static/js/modules/settings-manager.js?v=2025010510"></script>
|
||||
<script src="/static/js/modules/ui-manager.js?v=2025010510"></script>
|
||||
<script src="/static/js/modules/textarea-height-manager.js?v=2025010510"></script>
|
||||
|
||||
<!-- 主應用程式 -->
|
||||
<script src="/static/js/app.js?v=2025010510"></script>
|
||||
|
Loading…
x
Reference in New Issue
Block a user