Files
ST-Amily2-Chat-Optimisation/ui/drawer.js
2025-08-05 07:13:07 +08:00

222 lines
9.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { getSlideToggleOptions } from '/script.js';
import { slideToggle } from '/lib.js';
import { extension_settings, renderExtensionTemplateAsync } from "/scripts/extensions.js";
import { extensionName, defaultSettings } from "../utils/settings.js";
import {
checkAuthorization,
displayExpiryInfo,
pluginAuthStatus,
} from "../utils/auth.js";
import {
updateUI,
setAvailableModels,
populateModelDropdown,
applyUpdateIndicator,
} from "./state.js";
import { bindModalEvents } from "./bindings.js";
import { fetchSupportedModels } from "../core/api.js";
import { bindHistoriographyEvents } from "./historiography-bindings.js";
import { bindHanlinyuanEvents } from "./hanlinyuan-bindings.js";
import { showContentModal } from "./page-window.js";
const extensionFolderPath = `scripts/extensions/third-party/${extensionName}`;
async function loadSettings() {
extension_settings[extensionName] = {
...defaultSettings,
...(extension_settings[extensionName] || {}),
};
checkAuthorization();
const autoLogin = localStorage.getItem("plugin_auto_login") === "true";
console.log(
`[Amily2-调试] 授权状态: ${pluginAuthStatus.authorized}, 自动登录标志: ${autoLogin}`,
);
if (autoLogin && pluginAuthStatus.authorized) {
console.log("[Amily2号] 检测到有效授权将执行自动UI更新。");
}
$("#expiry_info").html(displayExpiryInfo());
updateUI();
if (pluginAuthStatus.authorized && extension_settings[extensionName].apiUrl) {
const cachedModels = localStorage.getItem("cached_models_amily2");
if (cachedModels) {
const models = JSON.parse(cachedModels);
console.log(`[Amily2号] 从缓存加载模型列表 (${models.length}个)`);
setAvailableModels(models);
populateModelDropdown();
} else {
toastr.info("正在自动加载模型列表...", "Amily2号");
setTimeout(async () => {
const models = await fetchSupportedModels();
if (models.length > 0) {
setAvailableModels(models);
localStorage.setItem("cached_models_amily2", JSON.stringify(models));
populateModelDropdown();
}
}, 500);
}
}
}
async function initializePanel(contentPanel, errorContainer) {
if (contentPanel.data("initialized")) return;
try {
const modalContent = await $.get(`${extensionFolderPath}/assets/amily2-modal.html`);
contentPanel.html(modalContent);
const mainContainer = contentPanel.find('#amily2_chat_optimiser');
if (mainContainer.length) {
const additionalFeaturesContent = await $.get(`${extensionFolderPath}/assets/Amily2-AdditionalFeatures.html`);
const additionalPanelHtml = `<div id="amily2_additional_features_panel" style="display: none;">${additionalFeaturesContent}</div>`;
mainContainer.append(additionalPanelHtml);
const hanlinyuanContent = await $.get(`${extensionFolderPath}/assets/hanlinyuan.html`);
const hanlinyuanPanelHtml = `<div id="amily2_hanlinyuan_panel" style="display: none;">${hanlinyuanContent}</div>`;
mainContainer.append(hanlinyuanPanelHtml);
}
await loadSettings();
bindModalEvents();
bindHistoriographyEvents();
bindHanlinyuanEvents();
contentPanel.data("initialized", true);
console.log("[Amily-重构] 宫殿模块已按蓝图竣工。");
applyUpdateIndicator();
} catch (error) {
console.error("[Amily-建设部] 紧急报告:加载模块化蓝图时发生意外:", error);
const errorMessage = errorContainer
? '<p style="color:red; padding:10px; border:1px solid red; border-radius:5px;">紧急报告在扩展区域建造Amily2号府邸时发生意外。</p>'
: '<p style="color:red; padding: 20px;">紧急报告无法加载Amily2号府邸内饰。</p>';
if (errorContainer) {
errorContainer.append(errorMessage);
} else {
contentPanel.html(errorMessage);
}
}
}
/**
* 【兼容性核心】为旧版SillyTavern提供的抽屉切换后备方案。
* 这个函数综合了我们之前所有调试的经验,确保了稳定和兼容。
*/
function toggleDrawerFallback() {
const drawerIcon = $('#amily2_drawer_icon');
const contentPanel = $('#amily2_drawer_content');
// 状态同步:如果图标和面板状态不一致(被外部关闭),先强制同步
if (drawerIcon.hasClass('openIcon') && !contentPanel.is(':visible')) {
drawerIcon.removeClass('openIcon').addClass('closedIcon');
}
// 核心逻辑:基于图标的 class 来判断
if (drawerIcon.hasClass('closedIcon')) {
// 打开抽屉
// 1. 关闭其他所有打开的抽屉(使用正确的 toggleClass确保非破坏性
$('.openDrawer').not(contentPanel).not('.pinnedOpen').addClass('resizing').each((_, el) => {
slideToggle(el, {
...getSlideToggleOptions(),
onAnimationEnd: function (el) {
el.closest('.drawer-content').classList.remove('resizing');
},
});
});
$('.openIcon').not(drawerIcon).not('.drawerPinnedOpen').toggleClass('closedIcon openIcon');
$('.openDrawer').not(contentPanel).not('.pinnedOpen').toggleClass('closedDrawer openDrawer');
// 2. 打开当前抽屉
drawerIcon.toggleClass('closedIcon openIcon');
contentPanel.toggleClass('closedDrawer openDrawer');
contentPanel.addClass('resizing').each((_, el) => {
slideToggle(el, {
...getSlideToggleOptions(),
onAnimationEnd: function (el) {
el.closest('.drawer-content').classList.remove('resizing');
},
});
});
} else {
// 关闭当前抽屉
drawerIcon.toggleClass('openIcon closedIcon');
contentPanel.toggleClass('openDrawer closedDrawer');
contentPanel.addClass('resizing').each((_, el) => {
slideToggle(el, {
...getSlideToggleOptions(),
onAnimationEnd: function (el) {
el.closest('.drawer-content').classList.remove('resizing');
},
});
});
}
}
export async function createDrawer() {
const settings = extension_settings[extensionName];
const location = settings.iconLocation || 'topbar';
if (location === 'topbar') {
if ($("#amily2_main_drawer").length > 0) return;
// 使用与st-memory-enhancement完全一致的HTML结构确保兼容性
const amily2DrawerHtml = `
<div id="amily2_main_drawer" class="drawer">
<div class="drawer-toggle" data-drawer="amily2_drawer_content">
<div id="amily2_drawer_icon" class="drawer-icon fa-solid fa-magic fa-fw closedIcon interactable" title="Amily2号优化助手" tabindex="0"></div>
</div>
<div id="amily2_drawer_content" class="drawer-content closedDrawer">
</div>
</div>
`;
$("#sys-settings-button").after(amily2DrawerHtml);
const contentPanel = $("#amily2_drawer_content");
await initializePanel(contentPanel);
// 【兼容性核心】使用动态导入来判断环境并绑定点击事件
try {
const { doNavbarIconClick } = await import('/script.js');
if (typeof doNavbarIconClick === 'function') {
// 新版SillyTavern使用官方函数
$('#amily2_main_drawer .drawer-toggle').on('click', doNavbarIconClick);
console.log('[Amily2-兼容性] 检测到新版环境,已绑定官方点击事件。');
} else {
// 理论上不存在的导出项会直接抛出错误,但作为双重保险
throw new Error('doNavbarIconClick is not a function');
}
} catch (error) {
// 旧版SillyTavern动态导入失败使用我们的后备方案
$('#amily2_main_drawer .drawer-toggle').on('click', toggleDrawerFallback);
console.log('[Amily2-兼容性] 检测到旧版环境 (无法导入 doNavbarIconClick),已绑定后备点击事件。');
}
} else if (location === 'extensions') {
if ($("#extensions_settings2 #amily2_chat_optimiser").length > 0) return;
const amilyFrameHtml = `
<div id="amily2_extension_frame">
<div class="inline-drawer">
<div class="inline-drawer-toggle inline-drawer-header">
<b><i class="fas fa-crown" style="color: #ffc107;"></i> Amily2号 优化中枢</b>
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
</div>
<div class="inline-drawer-content" style="display: none;">
</div>
</div>
</div>
`;
const frame = $(amilyFrameHtml);
$('#extensions_settings2').append(frame);
const contentPanel = frame.find('.inline-drawer-content');
initializePanel(contentPanel, frame);
}
}