Update local plugin changes

This commit is contained in:
henrryyes
2026-01-18 01:48:30 +08:00
parent b9b02d48ae
commit 0bd3cc57c5
7 changed files with 2272 additions and 1409 deletions

View File

@@ -8,7 +8,16 @@ import { TtsStorage } from "../../core/server-storage.js";
import { extractSpeakText, parseTtsSegments, DEFAULT_SKIP_TAGS, normalizeEmotion, splitTtsSegmentsForFree } from "./tts-text.js";
import { TtsPlayer } from "./tts-player.js";
import { synthesizeV3, FREE_DEFAULT_VOICE } from "./tts-api.js";
import { ensureTtsPanel, updateTtsPanel, removeAllTtsPanels, initTtsPanelStyles, setPanelConfigHandlers } from "./tts-panel.js";
import {
ensureTtsPanel,
updateTtsPanel,
removeAllTtsPanels,
initTtsPanelStyles,
setPanelConfigHandlers,
updateAutoSpeakAll,
updateSpeedAll,
updateVoiceAll
} from "./tts-panel.js";
import { getCacheEntry, setCacheEntry, getCacheStats, clearExpiredCache, clearAllCache, pruneCache } from './tts-cache.js';
import { speakMessageFree, clearAllFreeQueues, clearFreeQueueForMessage } from './tts-free-provider.js';
import {
@@ -1034,6 +1043,9 @@ async function handleIframeMessage(ev) {
if (ok) {
const cacheStats = await getCacheStatsSafe();
postToIframe(iframe, { type: 'xb-tts:config-saved', payload: { ...config, cacheStats } });
updateAutoSpeakAll();
updateSpeedAll();
updateVoiceAll();
} else {
postToIframe(iframe, { type: 'xb-tts:config-save-error', payload: { message: '保存失败' } });
}
@@ -1138,11 +1150,9 @@ export async function initTts() {
saveConfig: saveConfig,
openSettings: openSettings,
clearQueue: (messageId) => {
// 清理该消息的所有队列
clearMessageFromQueue(messageId);
clearFreeQueueForMessage(messageId);
// 重置面板状态
const state = ensureMessageState(messageId);
state.status = 'idle';
state.currentSegment = 0;
@@ -1162,34 +1172,74 @@ export async function initTts() {
case 'metadata':
msgState.duration = info?.duration || msgState.duration || 0;
break;
case 'progress':
msgState.progress = info?.currentTime || 0;
msgState.duration = info?.duration || msgState.duration || 0;
break;
case 'playing':
msgState.status = 'playing';
if (typeof item?.segmentIndex === 'number') {
msgState.currentSegment = item.segmentIndex + 1;
}
break;
case 'paused':
msgState.status = 'paused';
break;
case 'ended':
msgState.status = 'ended';
msgState.progress = msgState.duration;
case 'ended': {
// 检查是否是最后一个段落
const segIdx = typeof item?.segmentIndex === 'number' ? item.segmentIndex : -1;
const total = msgState.totalSegments || 1;
// 判断是否为最后一个段落
// segIdx 是 0-basedtotal 是总数
// 如果 segIdx >= total - 1说明是最后一个
const isLastSegment = total <= 1 || segIdx >= total - 1;
if (isLastSegment) {
// 真正播放完成
msgState.status = 'ended';
msgState.progress = msgState.duration;
} else {
// 还有后续段落
// 检查队列中是否有该消息的待播放项
const prefix = `msg-${messageId}-`;
const hasQueued = player.queue.some(q => q.id?.startsWith(prefix));
if (hasQueued) {
// 后续段落已在队列中,等待播放
msgState.status = 'queued';
} else {
// 后续段落还在请求中
msgState.status = 'sending';
}
}
break;
}
case 'blocked':
msgState.status = 'blocked';
break;
case 'error':
msgState.status = 'error';
break;
case 'enqueued':
// 只在非播放/暂停状态时更新
if (msgState.status !== 'playing' && msgState.status !== 'paused') {
msgState.status = 'queued';
}
break;
case 'idle':
case 'cleared':
// 播放器空闲,但可能还有段落在请求
// 不主动改变状态,让请求完成后的逻辑处理
break;
}
updateTtsPanel(messageId, msgState);
};