fix: stubtitle
This commit is contained in:
@@ -101,8 +101,6 @@ background-color: rgba(0, 0, 0, 0.5);
|
||||
color: white;
|
||||
line-height: 1.3;
|
||||
text-shadow: 1px 1px 2px black;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease-in-out;
|
||||
display: inline-block`;
|
||||
|
||||
const SUBTITLE_ORIGIN_STYLE = `font-size: clamp(1.5rem, 3cqw, 3rem);`;
|
||||
|
||||
@@ -10,9 +10,11 @@ export class BilingualSubtitleManager {
|
||||
#formattedSubtitles = [];
|
||||
#translationService;
|
||||
#captionWindowEl = null;
|
||||
#paperEl = null;
|
||||
#currentSubtitleIndex = -1;
|
||||
#preTranslateSeconds = 100;
|
||||
#setting = {};
|
||||
#isAdPlaying = false;
|
||||
|
||||
/**
|
||||
* @param {object} options
|
||||
@@ -56,6 +58,14 @@ export class BilingualSubtitleManager {
|
||||
this.#formattedSubtitles = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新广告播放状态。
|
||||
*/
|
||||
setIsAdPlaying(isPlaying) {
|
||||
this.#isAdPlaying = isPlaying;
|
||||
this.onTimeUpdate();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建并配置用于显示字幕的 DOM 元素。
|
||||
*/
|
||||
@@ -68,6 +78,7 @@ export class BilingualSubtitleManager {
|
||||
height: "100%",
|
||||
left: "0",
|
||||
top: "0",
|
||||
pointerEvents: "none",
|
||||
});
|
||||
|
||||
const paper = document.createElement("div");
|
||||
@@ -81,16 +92,20 @@ export class BilingualSubtitleManager {
|
||||
textAlign: "center",
|
||||
containerType: "inline-size",
|
||||
zIndex: "2147483647",
|
||||
pointerEvents: "auto",
|
||||
display: "none",
|
||||
});
|
||||
this.#paperEl = paper;
|
||||
|
||||
this.#captionWindowEl = document.createElement("div");
|
||||
this.#captionWindowEl.className = `kiss-caption-window`;
|
||||
this.#captionWindowEl.style.cssText = this.#setting.windowStyle;
|
||||
this.#captionWindowEl.style.pointerEvents = "auto";
|
||||
this.#captionWindowEl.style.cursor = "grab";
|
||||
this.#captionWindowEl.style.opacity = "1";
|
||||
|
||||
paper.appendChild(this.#captionWindowEl);
|
||||
container.appendChild(paper);
|
||||
this.#paperEl.appendChild(this.#captionWindowEl);
|
||||
container.appendChild(this.#paperEl);
|
||||
|
||||
const videoContainer = this.#videoEl.parentElement?.parentElement;
|
||||
if (!videoContainer) {
|
||||
@@ -101,7 +116,7 @@ export class BilingualSubtitleManager {
|
||||
videoContainer.style.position = "relative";
|
||||
videoContainer.appendChild(container);
|
||||
|
||||
this.#enableDragging(paper, container, this.#captionWindowEl);
|
||||
this.#enableDragging(this.#paperEl, container, this.#captionWindowEl);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -230,7 +245,12 @@ export class BilingualSubtitleManager {
|
||||
* @param {object | null} subtitle - 字幕对象,或 null 用于清空。
|
||||
*/
|
||||
#updateCaptionDisplay(subtitle) {
|
||||
if (!this.#captionWindowEl) return;
|
||||
if (!this.#paperEl || !this.#captionWindowEl) return;
|
||||
|
||||
if (this.#isAdPlaying) {
|
||||
this.#paperEl.style.display = "none";
|
||||
return;
|
||||
}
|
||||
|
||||
if (subtitle) {
|
||||
const p1 = document.createElement("p");
|
||||
@@ -247,9 +267,9 @@ export class BilingualSubtitleManager {
|
||||
this.#captionWindowEl.replaceChildren(p2);
|
||||
}
|
||||
|
||||
this.#captionWindowEl.style.opacity = "1";
|
||||
this.#paperEl.style.display = "block";
|
||||
} else {
|
||||
this.#captionWindowEl.style.opacity = "0";
|
||||
this.#paperEl.style.display = "none";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import { i18n } from "../config";
|
||||
const VIDEO_SELECT = "#container video";
|
||||
const CONTORLS_SELECT = ".ytp-right-controls";
|
||||
const YT_CAPTION_SELECT = "#ytp-caption-window-container";
|
||||
const YT_AD_SELECT = ".video-ads";
|
||||
|
||||
class YouTubeCaptionProvider {
|
||||
#setting = {};
|
||||
@@ -45,6 +46,7 @@ class YouTubeCaptionProvider {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener("yt-navigate-finish", () => {
|
||||
setTimeout(() => {
|
||||
if (this.#toggleButton) {
|
||||
@@ -54,9 +56,46 @@ class YouTubeCaptionProvider {
|
||||
this.#doubleClick();
|
||||
}, 1000);
|
||||
});
|
||||
|
||||
this.#waitForElement(CONTORLS_SELECT, (ytControls) =>
|
||||
this.#injectToggleButton(ytControls)
|
||||
);
|
||||
|
||||
this.#waitForElement(YT_AD_SELECT, (adContainer) => {
|
||||
this.#moAds(adContainer);
|
||||
});
|
||||
}
|
||||
|
||||
#moAds(adContainer) {
|
||||
const adSlector = ".ytp-ad-player-overlay-layout";
|
||||
const observer = new MutationObserver((mutations) => {
|
||||
for (const mutation of mutations) {
|
||||
if (mutation.type === "childList") {
|
||||
mutation.addedNodes.forEach((node) => {
|
||||
if (node.nodeType === 1 && node.matches(adSlector)) {
|
||||
logger.debug("Youtube Provider: AD start playing!", node);
|
||||
// todo: 顺带把广告快速跳过
|
||||
if (this.#managerInstance) {
|
||||
this.#managerInstance.setIsAdPlaying(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
mutation.removedNodes.forEach((node) => {
|
||||
if (node.nodeType === 1 && node.matches(adSlector)) {
|
||||
logger.debug("Youtube Provider: Ad ends!");
|
||||
if (this.#managerInstance) {
|
||||
this.#managerInstance.setIsAdPlaying(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
observer.observe(adContainer, {
|
||||
childList: true,
|
||||
subtree: true,
|
||||
});
|
||||
}
|
||||
|
||||
#waitForElement(selector, callback) {
|
||||
@@ -517,6 +556,7 @@ class YouTubeCaptionProvider {
|
||||
|
||||
let subtitles = this.#processSubtitles({ flatEvents });
|
||||
const isPoor = this.#isQualityPoor(subtitles);
|
||||
logger.debug("Youtube Provider: isQualityPoor", { isPoor, subtitles });
|
||||
if (isPoor) {
|
||||
subtitles = this.#processSubtitles({ flatEvents, usePause: true });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user