481 lines
26 KiB
JavaScript
481 lines
26 KiB
JavaScript
/**
|
||
* @file js/index.js
|
||
* @description
|
||
* 主 UI 初始化和模块管理脚本。
|
||
* 该文件负责:
|
||
* - 初始化全局 `window.ui`命名空间,用于挂载各个 UI 模块的功能。
|
||
* - 定义 UI 模块的注册机制 (`window.ui.registerModule`)。
|
||
* - 管理模块加载状态 (`window.ui.moduleStatus`, `EXPECTED_UI_MODULES`, `_allModulesReady`)。
|
||
* - 提供一个就绪回调队列 (`window.ui.onReady`, `_pendingInitializations`),确保在所有模块加载完毕且 DOM 就绪后执行初始化代码。
|
||
* - 包含核心的 UI 初始化逻辑 (`initializeAllUI_internal`),用于绑定全局事件监听器、初始化特定 UI 组件等。
|
||
* - 处理特定 UI 元素的动态显隐和交互,如翻译模型选择相关的 UI (`updateTranslationUIVisibility`, `handleCustomModelSelection`)。
|
||
* - 监听 `DOMContentLoaded` 事件以启动整个 UI 初始化流程。
|
||
*/
|
||
|
||
if (typeof window.ui === 'undefined') {
|
||
console.log('DEBUG index.js: Initializing window.ui object');
|
||
window.ui = {};
|
||
} else {
|
||
console.log('DEBUG index.js: window.ui object already exists.');
|
||
}
|
||
|
||
if (typeof window.ui.moduleStatus === 'undefined') {
|
||
console.log('DEBUG index.js: Initializing window.ui.moduleStatus');
|
||
window.ui.moduleStatus = {};
|
||
} else {
|
||
console.log('DEBUG index.js: window.ui.moduleStatus already exists.');
|
||
}
|
||
|
||
// Placeholders for core methods - ensures they exist if called early by other scripts
|
||
window.ui.registerModule = window.ui.registerModule || function(name, funcs) {
|
||
console.warn(`UI: Placeholder registerModule called for ${name}. Functions will not be registered globally yet.`);
|
||
// Basic status update
|
||
if (window.ui && window.ui.moduleStatus) {
|
||
window.ui.moduleStatus[name] = true; // Mark as loaded for _allModulesReady check
|
||
console.log(`UI模块 (via placeholder) 已记录: ${name}`);
|
||
}
|
||
// Try to execute pending initializations if this was the last expected module according to a basic check
|
||
if (typeof _allModulesReady === 'function' && _allModulesReady() && typeof _executePendingInitializations === 'function') {
|
||
console.warn("Placeholder registerModule: All modules might be ready, attempting to execute initializations.");
|
||
_executePendingInitializations();
|
||
}
|
||
};
|
||
window.ui.onReady = window.ui.onReady || function(cb) {
|
||
console.warn(`UI: Placeholder onReady called. Executing callback.`);
|
||
if (document.readyState === "complete" || document.readyState === "interactive") {
|
||
setTimeout(cb, 0); // Execute async if DOM is somewhat ready
|
||
} else {
|
||
document.addEventListener('DOMContentLoaded', () => setTimeout(cb, 0)); // Otherwise wait for DOM
|
||
}
|
||
};
|
||
// END OF VERY TOP INITIALIZATION
|
||
|
||
const EXPECTED_UI_MODULES = ['helpers', 'form', 'fileList', 'progress', 'notification', 'sourceSite', 'keyHandlers', 'keyManager'];
|
||
// Initialize moduleStatus for expected modules if not already set by placeholders or previous runs
|
||
EXPECTED_UI_MODULES.forEach(name => {
|
||
if (typeof window.ui.moduleStatus[name] === 'undefined' || window.ui.moduleStatus[name] === false) { // Check if false to allow re-init logic
|
||
window.ui.moduleStatus[name] = false;
|
||
}
|
||
});
|
||
|
||
/**
|
||
* 根据是否选择自定义翻译模型,更新相关 UI 元素的可见性和状态。
|
||
* 当用户在翻译模型下拉菜单中选择 "custom" 或从 "custom" 切换到其他模型时,此函数被调用。
|
||
*
|
||
* 主要操作:
|
||
* - 显示或隐藏自定义源站点容器 (`customSourceSiteContainer`)。
|
||
* - 启用或禁用自定义源站点选择下拉框 (`customSourceSiteSelect`),并在隐藏时清空其选择。
|
||
* - 显示或隐藏自定义源站点信息区域 (`customSourceSiteInfo`),并在隐藏时清空其内容。
|
||
*
|
||
* @param {boolean} showCustomUI - 如果为 `true`,则显示自定义模型相关的 UI 部分;否则隐藏它们。
|
||
*/
|
||
function updateTranslationUIVisibility(showCustomUI) {
|
||
// console.log(`UI::updateTranslationUIVisibility, showCustom: ${showCustomUI}`); // Original log
|
||
console.log(`DEBUG index.js: updateTranslationUIVisibility CALLED with showCustom: ${showCustomUI}`);
|
||
if (typeof window.updateTranslationUIVisibility === 'function' && window.updateTranslationUIVisibility !== updateTranslationUIVisibility) {
|
||
window.updateTranslationUIVisibility(showCustomUI);
|
||
return;
|
||
}
|
||
const customSourceSiteContainer = document.getElementById('customSourceSiteContainer');
|
||
const customSourceSiteSelect = document.getElementById('customSourceSiteSelect');
|
||
const customSourceSiteInfo = document.getElementById('customSourceSiteInfo');
|
||
|
||
if (customSourceSiteContainer) {
|
||
customSourceSiteContainer.classList.toggle('hidden', !showCustomUI);
|
||
}
|
||
|
||
if (customSourceSiteSelect) {
|
||
customSourceSiteSelect.disabled = !showCustomUI;
|
||
if (!showCustomUI) {
|
||
customSourceSiteSelect.value = ''; // Clear selection when hiding
|
||
}
|
||
}
|
||
|
||
if (customSourceSiteInfo) {
|
||
customSourceSiteInfo.classList.toggle('hidden', !showCustomUI);
|
||
if (!showCustomUI) {
|
||
customSourceSiteInfo.innerHTML = ''; // Clear info when hiding
|
||
}
|
||
}
|
||
}
|
||
// CORRECTED SPELLING HERE
|
||
window.ui.updateTranslationUIVisibility = updateTranslationUIVisibility;
|
||
console.log('DEBUG index.js: Assigned window.ui.updateTranslationUIVisibility. Type is now:', typeof window.ui.updateTranslationUIVisibility);
|
||
if (typeof window.ui.updateTranslationUIVisibility !== 'function') {
|
||
console.error('CRITICAL DEBUG index.js: updateTranslationUIVisibility IS NOT A FUNCTION immediately after assignment!');
|
||
}
|
||
|
||
let _pendingInitializations = [];
|
||
let _modulesReadyStatus = {}; // This will be populated by the actual registerModule
|
||
let _domReady = false;
|
||
let _initializationExecuted = false; // Flag to prevent multiple executions
|
||
|
||
|
||
/**
|
||
* 检查所有在 `EXPECTED_UI_MODULES` 中定义的预期 UI 模块是否都已注册并标记为就绪。
|
||
* 它遍历 `EXPECTED_UI_MODULES` 数组,并检查 `window.ui.moduleStatus` 中对应模块的状态。
|
||
*
|
||
* @returns {boolean} 如果所有预期模块都已就绪,则返回 `true`;否则返回 `false`。
|
||
* @private
|
||
*/
|
||
function _allModulesReady() {
|
||
for (const moduleName of EXPECTED_UI_MODULES) {
|
||
if (!window.ui.moduleStatus[moduleName]) {
|
||
// console.log(`DEBUG index.js: _allModulesReady - Module not ready: ${moduleName}`);
|
||
return false;
|
||
}
|
||
}
|
||
console.log("DEBUG index.js: _allModulesReady - All expected UI modules are ready.");
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* (全局 `window.ui` 接口)
|
||
* 注册一个 UI 模块及其提供的功能函数到全局 `window.ui` 对象上。
|
||
* 每个模块通过调用此函数来声明自身已加载,并将其公开的接口挂载到 `window.ui`。
|
||
*
|
||
* 主要步骤:
|
||
* 1. 参数校验:确保 `moduleName` 和 `functions` 对象有效。
|
||
* 2. 函数挂载:遍历 `functions` 对象中的每个函数,将其赋值给 `window.ui[funcName]`。
|
||
* 如果发生命名冲突(覆盖已有的非核心 `window.ui` 属性),会打印警告。
|
||
* 3. 状态更新:将 `window.ui.moduleStatus[moduleName]` 设置为 `true`,标记该模块已加载。
|
||
* 4. 触发初始化:调用 `_executePendingInitializations` 尝试执行待处理的初始化任务,
|
||
* 因为一个新模块的加载可能满足了所有初始化条件。
|
||
*
|
||
* @param {string} moduleName - 要注册的模块的名称 (应与 `EXPECTED_UI_MODULES` 中的条目对应)。
|
||
* @param {Object} functions -一个对象,其键是函数名,值是函数本身。这些函数将被添加到 `window.ui`。
|
||
*/
|
||
window.ui.registerModule = function(moduleName, functions) {
|
||
console.log('DEBUG index.js: registerModule - START. Module:', moduleName, 'Functions:', Object.keys(functions));
|
||
if (!moduleName || typeof moduleName !== 'string') {
|
||
console.error('UI: registerModule - moduleName is invalid.', moduleName);
|
||
return;
|
||
}
|
||
if (!functions || typeof functions !== 'object') {
|
||
console.error(`UI: registerModule - functions for module '${moduleName}' is invalid.`, functions);
|
||
return;
|
||
}
|
||
|
||
Object.keys(functions).forEach(funcName => {
|
||
if (window.ui.hasOwnProperty(funcName) &&
|
||
funcName !== 'registerModule' &&
|
||
funcName !== 'onReady' &&
|
||
funcName !== 'moduleStatus' &&
|
||
funcName !== 'updateTranslationUIVisibility' &&
|
||
funcName !== 'handleCustomModelSelection' &&
|
||
funcName !== 'showNotification' &&
|
||
!EXPECTED_UI_MODULES.includes(funcName)
|
||
) {
|
||
// console.warn(`UI: Module '${moduleName}' is overwriting existing ui function '${funcName}'.`);
|
||
}
|
||
window.ui[funcName] = functions[funcName];
|
||
});
|
||
|
||
window.ui.moduleStatus[moduleName] = true;
|
||
console.log(`UI模块已注册: ${moduleName}`);
|
||
|
||
// 检查是否所有模块都已加载完成,并且DOM已准备好
|
||
if (typeof _executePendingInitializations === 'function') {
|
||
_executePendingInitializations();
|
||
} else {
|
||
console.error("DEBUG index.js: registerModule - _executePendingInitializations is not defined when trying to call it after module registration.");
|
||
}
|
||
};
|
||
|
||
/**
|
||
* 执行所有通过 `window.ui.onReady` 排队的待处理初始化回调函数。
|
||
* 此函数仅在以下所有条件都满足时才会实际执行回调:
|
||
* - DOM 已加载完成 (`_domReady` 为 `true`)。
|
||
* - 所有预期的 UI 模块都已注册 (`_allModulesReady()` 返回 `true`)。
|
||
* - 初始化流程尚未执行过 (`_initializationExecuted` 为 `false`)。
|
||
*
|
||
* 执行时,它会:
|
||
* 1. 设置 `_initializationExecuted = true` 防止重入。
|
||
* 2. 依次执行 `_pendingInitializations` 队列中的所有回调函数。
|
||
* 3. 调用核心的 `initializeAllUI_internal()` 函数来完成最终的 UI 设置。
|
||
* @private
|
||
*/
|
||
function _executePendingInitializations() {
|
||
console.log(`DEBUG index.js: _executePendingInitializations called. DOM Ready: ${_domReady}, All Modules Ready: ${typeof _allModulesReady === 'function' ? _allModulesReady() : 'unknown'}, Executed: ${_initializationExecuted}`);
|
||
if (_initializationExecuted) {
|
||
console.log("DEBUG index.js: _executePendingInitializations - Already executed, skipping.");
|
||
return;
|
||
}
|
||
|
||
if (_domReady && typeof _allModulesReady === 'function' && _allModulesReady()) {
|
||
console.log('DEBUG index.js: All conditions met, executing pending initializations...');
|
||
_initializationExecuted = true; // Set flag
|
||
while (_pendingInitializations.length > 0) {
|
||
const cb = _pendingInitializations.shift();
|
||
try {
|
||
console.log("DEBUG index.js: Executing a pending initialization callback.");
|
||
cb();
|
||
} catch (e) {
|
||
console.error("Error executing pending initialization:", e);
|
||
}
|
||
}
|
||
console.log("DEBUG index.js: All pending initializations executed.");
|
||
|
||
// 确保核心的 initializeAllUI_internal 被调用
|
||
if (typeof initializeAllUI_internal === 'function') {
|
||
console.log("DEBUG index.js: Calling initializeAllUI_internal from _executePendingInitializations.");
|
||
initializeAllUI_internal();
|
||
} else {
|
||
console.error("DEBUG index.js: initializeAllUI_internal is not defined when trying to call from _executePendingInitializations.");
|
||
}
|
||
|
||
} else {
|
||
console.log("DEBUG index.js: _executePendingInitializations - Conditions not yet met (or _allModulesReady not defined).");
|
||
}
|
||
}
|
||
|
||
/**
|
||
* (全局 `window.ui` 接口)
|
||
* 注册一个回调函数,该函数将在整个 UI(包括所有模块和 DOM)完全准备就绪后执行。
|
||
* 如果调用此函数时 UI 已经就绪,则回调会几乎立即异步执行。
|
||
* 否则,回调会被添加到一个队列 (`_pendingInitializations`) 中,等待所有条件满足后由 `_executePendingInitializations` 统一执行。
|
||
*
|
||
* @param {function} callback - 当 UI 完全就绪时要执行的回调函数。
|
||
*/
|
||
window.ui.onReady = function(callback) {
|
||
console.log("DEBUG index.js: window.ui.onReady called with a callback.");
|
||
if (typeof callback !== 'function') {
|
||
console.error('UI: onReady callback is not a function.');
|
||
return;
|
||
}
|
||
if (_domReady && typeof _allModulesReady === 'function' && _allModulesReady() && _initializationExecuted) {
|
||
console.log("DEBUG index.js: onReady - UI already fully initialized, executing callback immediately.");
|
||
setTimeout(callback, 0); // 执行回调,异步以避免栈溢出
|
||
} else {
|
||
console.log("DEBUG index.js: onReady - UI not yet fully initialized or initializations not run, queueing callback.");
|
||
_pendingInitializations.push(callback);
|
||
// 如果DOM已就绪但初始化尚未运行(可能模块仍在加载),尝试运行一次
|
||
if (_domReady && typeof _executePendingInitializations === 'function' && !_initializationExecuted) {
|
||
console.log("DEBUG index.js: onReady - DOM ready, trying to execute pending initializations.");
|
||
_executePendingInitializations();
|
||
}
|
||
}
|
||
};
|
||
|
||
/**
|
||
* 处理当翻译模型下拉框选择发生变化时的逻辑,特别是针对"自定义模型"选项。
|
||
* 当用户选择或取消选择 "custom" 模型时,此函数负责:
|
||
* 1. 调用 `window.ui.updateTranslationUIVisibility` 来切换相关 UI 元素的显隐。
|
||
* 2. 如果选择了 "custom" 模型:
|
||
* - 尝试调用 `window.ui.tryPopulateCustomSourceSitesDropdown` 来填充自定义源站点下拉列表。
|
||
* - 自动展开自定义源站点设置区域(如果该区域存在且当前是折叠状态)。
|
||
* @private
|
||
*/
|
||
function handleCustomModelSelection() {
|
||
console.log("DEBUG index.js: handleCustomModelSelection: 处理自定义模式选择");
|
||
const isCustomModel = document.getElementById('translationModel').value === 'custom';
|
||
|
||
if (typeof window.ui.updateTranslationUIVisibility === 'function') {
|
||
window.ui.updateTranslationUIVisibility(isCustomModel);
|
||
} else {
|
||
console.warn("DEBUG index.js: handleCustomModelSelection - updateTranslationUIVisibility is not available on window.ui.");
|
||
}
|
||
|
||
if (isCustomModel) {
|
||
console.log("DEBUG index.js: Custom model selected. Attempting to populate dropdown and expand section.");
|
||
if (typeof window.ui.tryPopulateCustomSourceSitesDropdown === 'function') {
|
||
console.log("DEBUG index.js: Calling window.ui.tryPopulateCustomSourceSitesDropdown...");
|
||
window.ui.tryPopulateCustomSourceSitesDropdown();
|
||
} else {
|
||
console.warn("DEBUG index.js: window.ui.tryPopulateCustomSourceSitesDropdown is not available.");
|
||
}
|
||
// 自动展开自定义源站点设置区域
|
||
const customSourceSiteDiv = document.getElementById('customSourceSite');
|
||
const customSourceSiteToggleIconEl = document.getElementById('customSourceSiteToggleIcon');
|
||
if (customSourceSiteDiv && customSourceSiteDiv.classList.contains('hidden')) {
|
||
customSourceSiteDiv.classList.remove('hidden');
|
||
if (customSourceSiteToggleIconEl) {
|
||
customSourceSiteToggleIconEl.setAttribute('icon', 'carbon:chevron-up');
|
||
}
|
||
console.log("DEBUG index.js: Custom source site section expanded.");
|
||
}
|
||
}
|
||
}
|
||
window.ui.handleCustomModelSelection = handleCustomModelSelection;
|
||
|
||
|
||
/**
|
||
* 核心的内部 UI 初始化函数。
|
||
* 此函数在所有模块加载完毕且 DOM 就绪后,由 `_executePendingInitializations` 调用。
|
||
* 主要职责包括:
|
||
* - 调用 `window.ui.registerGlobalUIEventListeners` (如果由模块提供) 来注册全局性的事件监听器 (如键盘快捷键)。
|
||
* - 调用 `window.ui.registerSourceSiteListeners` (如果由模块提供) 来注册与自定义源站点相关的事件监听器。
|
||
* - 调用 `window.ui.initKeyManagerDisplay` (如果由模块提供) 来初始化 API Key 管理器的显示。
|
||
* - 检查初始的翻译模型选择状态,并调用 `updateTranslationUIVisibility` 和/或 `handleCustomModelSelection` 以确保 UI 正确显示。
|
||
* @private
|
||
*/
|
||
function initializeAllUI_internal() {
|
||
console.log("DEBUG index.js: Executing initializeAllUI_internal (event listeners, etc.)...");
|
||
|
||
// 全局UI事件 (例如键盘快捷键、弹窗关闭等)
|
||
if (typeof window.ui.registerGlobalUIEventListeners === 'function') {
|
||
window.ui.registerGlobalUIEventListeners();
|
||
console.log("DEBUG index.js: Registered global UI event listeners (from window.ui).");
|
||
} else if (typeof registerGlobalUIEventListeners_internal === 'function') {
|
||
// Fallback to a locally defined one if modules didn't provide it (e.g. if helpers.js moved it here)
|
||
// registerGlobalUIEventListeners_internal(); // This function is no longer defined in index.js
|
||
console.warn("DEBUG index.js: window.ui.registerGlobalUIEventListeners not found. Global listeners might not be set up by helpers.js.");
|
||
}
|
||
|
||
|
||
// 源站点特定的事件 (例如选择自定义源站点时的行为)
|
||
if (typeof window.ui.registerSourceSiteListeners === 'function') {
|
||
window.ui.registerSourceSiteListeners();
|
||
console.log("DEBUG index.js: Registered source site specific event listeners.");
|
||
} else {
|
||
console.warn("DEBUG index.js: window.ui.registerSourceSiteListeners is not available. Custom source site interactions might be limited.");
|
||
}
|
||
|
||
// 初始化Key管理器UI(如果它作为一个模块提供了初始化函数)
|
||
if (typeof window.ui.initKeyManagerDisplay === 'function') {
|
||
window.ui.initKeyManagerDisplay();
|
||
console.log("DEBUG index.js: Initialized Key Manager UI display.");
|
||
} else {
|
||
console.warn("DEBUG index.js: window.ui.initKeyManagerDisplay is not available. Key manager UI might not initialize correctly.");
|
||
}
|
||
|
||
// 检查初始翻译模型选择,并相应地更新UI
|
||
const initialTranslationModel = document.getElementById('translationModel');
|
||
if (initialTranslationModel) {
|
||
console.log(`DEBUG index.js: Initial translation model value: ${initialTranslationModel.value}`);
|
||
if (typeof window.ui.updateTranslationUIVisibility === 'function') {
|
||
window.ui.updateTranslationUIVisibility(initialTranslationModel.value === 'custom');
|
||
console.log("DEBUG index.js: Initial call to updateTranslationUIVisibility in initializeAllUI_internal done.");
|
||
} else {
|
||
console.warn("DEBUG index.js: updateTranslationUIVisibility function not available in initializeAllUI_internal for initial UI setup.");
|
||
}
|
||
// 如果初始模型是 'custom',确保自定义源站点下拉列表已填充
|
||
if (initialTranslationModel.value === 'custom') {
|
||
if (typeof window.ui.handleCustomModelSelection === 'function') {
|
||
// window.ui.handleCustomModelSelection(); // This will also call updateTranslationUIVisibility
|
||
console.log("DEBUG index.js: Initial model is custom, handleCustomModelSelection should have run or will run via onReady.");
|
||
} else {
|
||
console.warn("DEBUG index.js: window.ui.handleCustomModelSelection not available for initial custom model check.");
|
||
}
|
||
}
|
||
} else {
|
||
console.warn("DEBUG index.js: Translation model select element not found during initializeAllUI_internal.");
|
||
}
|
||
|
||
// 后端模式:隐藏/禁用模型与Key设置相关的前端编辑入口,仅保留“选择使用哪个模型”
|
||
try {
|
||
const isBackendMode = (typeof window !== 'undefined' && window.storageAdapter && window.storageAdapter.isFrontendMode === false);
|
||
if (isBackendMode) {
|
||
const hide = (el) => { try { if (el) { el.classList.add('hidden'); el.setAttribute('aria-hidden', 'true'); } } catch {} };
|
||
const disable = (el) => { try { if (el) { el.setAttribute('disabled', 'true'); el.classList.add('opacity-50','cursor-not-allowed'); } } catch {} };
|
||
|
||
// 1) API Key 文本域与其标签
|
||
hide(document.querySelector('label[for="mistralApiKeys"]'));
|
||
hide(document.getElementById('mistralApiKeys'));
|
||
hide(document.querySelector('label[for="translationApiKeys"]'));
|
||
hide(document.getElementById('translationApiKeys'));
|
||
hide(document.getElementById('rememberMistralKey'));
|
||
hide(document.getElementById('rememberTranslationKey'));
|
||
|
||
// 2) Key 管理器按钮与弹窗
|
||
const keyBtn = document.getElementById('modelKeyManagerBtn');
|
||
if (keyBtn) { disable(keyBtn); keyBtn.title = '后端模式:模型与Key管理已禁用'; }
|
||
hide(document.getElementById('modelKeyManagerModal'));
|
||
|
||
// 3) 自定义源站点相关(仅保留选择模型,不提供站点/Key管理)
|
||
hide(document.getElementById('customSourceSiteContainer'));
|
||
hide(document.getElementById('customSourceSite'));
|
||
hide(document.getElementById('customSourceSiteInfo'));
|
||
hide(document.getElementById('manageSourceSiteKeyBtn'));
|
||
hide(document.getElementById('detectModelsBtn'));
|
||
|
||
// 4) 提示
|
||
if (typeof window.showNotification === 'function') {
|
||
window.showNotification('后端模式:已禁用前端的模型与Key设置;可直接选择要使用的模型。', 'info');
|
||
}
|
||
}
|
||
} catch (e) {
|
||
console.warn('[Index] Backend-mode gating failed (ignored):', e?.message || e);
|
||
}
|
||
console.log("DEBUG index.js: initializeAllUI_internal finished.");
|
||
}
|
||
|
||
|
||
/**
|
||
* DOMContentLoaded 事件的监听器回调。
|
||
* 当 HTML 文档完全加载并解析完成后(不等待样式表、图像和子框架),此函数被触发。
|
||
*
|
||
* 主要操作:
|
||
* 1. 设置全局标志 `_domReady = true`。
|
||
* 2. 调用 `_executePendingInitializations()` 尝试启动待处理的初始化任务。
|
||
* (如果此时模块尚未全部加载,`_executePendingInitializations` 内部逻辑会等待)。
|
||
* 3. 为翻译模型选择器 (`#translationModel`) 绑定 `change` 事件监听器:
|
||
* - 当选择变化时,调用 `window.ui.handleCustomModelSelection` 更新相关 UI。
|
||
* - (注释中提及) `saveCurrentSettings` 应由 `app.js` 处理,以避免逻辑冲突。
|
||
* 4. (注释中提及) 初始的自定义模型检查和 UI 更新会由 `initializeAllUI_internal` 通过 `onReady` 流程处理,
|
||
* 此处不再直接触发 `handleCustomModelSelection`。
|
||
*/
|
||
document.addEventListener('DOMContentLoaded', () => {
|
||
console.log('DEBUG index.js: DOMContentLoaded event fired.');
|
||
_domReady = true;
|
||
// 尝试执行初始化。如果模块尚未全部注册,_executePendingInitializations 内部会等待。
|
||
if (typeof _executePendingInitializations === 'function') {
|
||
_executePendingInitializations();
|
||
} else {
|
||
console.error('DEBUG index.js: _executePendingInitializations is not defined at DOMContentLoaded!');
|
||
}
|
||
|
||
// 为翻译模型选择器绑定事件 (如果存在)
|
||
const translationModelSelect = document.getElementById('translationModel');
|
||
if (translationModelSelect) {
|
||
console.log("DEBUG index.js: Found translation model selector, adding change event listener.");
|
||
translationModelSelect.addEventListener('change', function() {
|
||
const selectedValue = this.value;
|
||
console.log(`DEBUG index.js: Translation model changed to: ${selectedValue}`);
|
||
|
||
// 先保存设置
|
||
if (typeof saveCurrentSettings === 'function') {
|
||
saveCurrentSettings();
|
||
console.log("DEBUG index.js: Settings saved after translation model change.");
|
||
} else {
|
||
console.warn("DEBUG index.js: saveCurrentSettings function not found.");
|
||
}
|
||
|
||
// 调用 handleCustomModelSelection 来处理UI联动,它内部会调用 updateTranslationUIVisibility
|
||
if (typeof window.ui.handleCustomModelSelection === 'function') {
|
||
window.ui.handleCustomModelSelection();
|
||
} else {
|
||
console.warn('DEBUG index.js: window.ui.handleCustomModelSelection function not available during translation model change.');
|
||
// Fallback: direct call if handleCustomModelSelection is missing
|
||
if (typeof window.ui.updateTranslationUIVisibility === 'function') {
|
||
window.ui.updateTranslationUIVisibility(selectedValue === 'custom');
|
||
} else {
|
||
console.warn('DEBUG index.js: updateTranslationUIVisibility function also not available on window.ui during translation model change (fallback).');
|
||
}
|
||
}
|
||
|
||
// 触发验证状态更新(在设置保存后)- 直接调用全局刷新函数
|
||
if (typeof window.refreshValidationState === 'function') {
|
||
setTimeout(() => {
|
||
console.log('[DEBUG] Triggering refreshValidationState after settings save');
|
||
window.refreshValidationState();
|
||
}, 100);
|
||
} else {
|
||
console.warn('[DEBUG] window.refreshValidationState not available');
|
||
}
|
||
});
|
||
|
||
// 触发一次初始检查,以防页面加载时已选择了 "custom"
|
||
// 这将由 initializeAllUI_internal -> onReady -> _executePendingInitializations -> initializeAllUI_internal 处理
|
||
// if (typeof window.ui.handleCustomModelSelection === 'function') {
|
||
// console.log("DEBUG index.js: Triggering initial handleCustomModelSelection check post DOMContentLoaded and listener setup.");
|
||
// // window.ui.handleCustomModelSelection(); // Avoid direct call, let initialization flow handle it.
|
||
// }
|
||
|
||
} else {
|
||
console.warn("DEBUG index.js: Translation model select element not found after DOMContentLoaded.");
|
||
}
|
||
});
|
||
|
||
console.log("DEBUG index.js: End of script. Waiting for module registrations and DOMContentLoaded.");
|