Skip to content

Commit

Permalink
Fix youtube video issue (#47)
Browse files Browse the repository at this point in the history
* 🎨 Create a circle.

* 🚧 Add new files.

* 🚧 Inject script and css to content script.

* 🚧 Show phrase floating icon.

* 🚧 Exclude node_modules.

* 🎨 Move the phrase floating icon.

* 🚧 Show home view correctly.

* 💄 Update phrase floating panel styles.

* 🚧 Update phrase floating panel

* 🚧 Change show/hide logic.

* 🚧 Complete phrase panel component part.

* 🚧 Add axios support.

* 🚧 Get current page's url.

* 🚧 Add default group when open new page.

* 🚧 Change get word list logic.

* 🚧 Update phrase floating panel logic.

* 🚧 Remove log.

* 🚧 Bump version.

* 🚧 Fix youtube video issue.

* 🚧 Add new logic.

* 🚧 Add langman and cambridge dictionary link.

* 🚧 Change z-index.

* 🚧 Fix cros issue.

* 🚧 Fix get word transltaion cors issue.

* 🚧 Save infinite loop issue.

* 🚧 Add google translator.

* 🚧 Fix mount twice issue.

* ⚡️ Bump version.

* 🚧 Switch Chinese and English automatically.

* 🚧 Fix #50 bug.

* 🚧 Fix word not hightlight.

* 🔇 Remove log.

* 🚧 Remove code.

---------

Co-authored-by: Toly <[email protected]>
  • Loading branch information
tolerious and Toly authored Sep 26, 2024
1 parent 6ffe0c6 commit 51e88d2
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 58 deletions.
8 changes: 2 additions & 6 deletions src/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"name": "Stylish Reader",
"description": "Help you learn English better and easier.",
"developer": { "name": "Toly Feng", "url": "https://stylishreader.com" },
"version": "0.0.8",
"version": "0.0.9",
"icons": {
"48": "icons/stylish-reader-48.png"
},
Expand All @@ -13,11 +13,7 @@
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": [
"content_script.js",
"assets/js/plyr.js",
"assets/js/youtube-transport.js"
],
"js": ["content_script.js", "assets/js/plyr.js"],
"css": ["assets/css/plyr.css"],
"run_at": "document_end"
}
Expand Down
8 changes: 4 additions & 4 deletions src/plugins/entryPoint/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,19 +150,19 @@ function processResponse(details) {
let data = [];

filter.ondata = (event) => {
let str = decoder.decode(event.data, { stream: true });
let str = decoder.decode(event.data);
data.push(str);
filter.write(encoder.encode(event.data));
};

filter.onstop = (event) => {
let responseBody = data.join("");
try {
let json = JSON.parse(responseBody);
console.log("Response JSON data: ", json);
console.log(details.url);
notifyContentScript({ type: "youtube", url: details.url, data: json });
// 在这里处理 JSON 数据
data.forEach((d) => {
filter.write(encoder.encode(d));
});
} catch (e) {
alert("视频处理失败,请刷新页面重试");
}
Expand Down
4 changes: 3 additions & 1 deletion src/plugins/general/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,9 @@ function removeUnMarkedWord(word) {

function convertCurrentTextNodeContent(textNode, targetWordList) {
// 判断并找出当前文本节点中包含的目标单词
const textContent = textNode.textContent;
const textContent = textNode.textContent
.replaceAll("\n", " ")
.replaceAll("\t", " ");
const targetWordSet = new Set(targetWordList);
const splittedTextContentStringList = textContent.split(" ");
// 存放的是目标单词在splittedTextContentStringList中的索引
Expand Down
164 changes: 121 additions & 43 deletions src/plugins/youtube/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,37 +29,34 @@ export function createYoutubeStylishReaderIcon() {
const toolBar = document.querySelector(".ytp-right-controls");
if (toolBar) {
const element = createYoutubeStylishIconElement();
element.addEventListener("click", onClickStylishReaderIcon);
logger("add icon...");
// element.addEventListener("click", onClickStylishReaderIcon);
toolBar.appendChild(element);
}
}

async function onClickStylishReaderIcon(e) {
logger(currentYoutubeTranslationUrl);
logger(currentYoutubeZhTranslationUrl);
if (
currentYoutubeTranslationUrl.trim() === "" ||
currentYoutubeZhTranslationUrl.trim() === ""
) {
logger("No translation found");
alert("请切换中英双语字母后再保存");
} else {
console.log("en", currentYoutubeTranslationUrl);
console.log("zh", currentYoutubeZhTranslationUrl);
const token = await getLoginToken();
console.log({
type: "subtitle",
data: {
enUrl: currentYoutubeTranslationUrl,
enData: currentYoutubeTranslationData,
zhUrl: currentYoutubeZhTranslationUrl,
zhData: currentYoutubeZhTranslationData,
videoId: getVideoId(),
token,
link: window.location.href,
title: document.title,
},
});
// console.log({
// type: "subtitle",
// data: {
// enUrl: currentYoutubeTranslationUrl,
// enData: currentYoutubeTranslationData,
// zhUrl: currentYoutubeZhTranslationUrl,
// zhData: currentYoutubeZhTranslationData,
// videoId: getVideoId(),
// token,
// link: window.location.href,
// title: document.title,
// },
// });
sendMessageToYoutubeVideoPage({
type: "subtitle",
data: {
Expand Down Expand Up @@ -134,18 +131,31 @@ export function parseSubtitles(url, data) {
if (isCurrentSubtitleEnglish(url)) {
currentYoutubeTranslationUrl = url;
currentYoutubeTranslationData = data;
logger("English subtitle gotcha.");
setEnglishTranscriptStatus(true);
if (!url) {
logger(`English url is empty`);
} else if (!data) {
logger(`English data is empty`);
} else {
logger("English subtitle gotcha.");
setEnglishTranscriptStatus(true);
}
}
if (isCurrentSubtitleChinese(url)) {
currentYoutubeZhTranslationUrl = url;
currentYoutubeZhTranslationData = data;
logger("Chinese subtitle gotcha.");
setChineseTranscriptStatus(true);
if (!url) {
logger(`Chinese url is empty`);
} else if (!data) {
logger(`Chinese data is empty`);
} else {
logger("Chinese subtitle gotcha.");
setChineseTranscriptStatus(true);
}
}
}

function sendMessageToYoutubeVideoPage(message) {
logger("sendMessageToYoutubeVideoPage");
const event = new CustomEvent("fromYoutubeVideoContentScript", {
detail: JSON.stringify(message),
bubbles: true,
Expand Down Expand Up @@ -201,6 +211,7 @@ function injectJsToShadowDom(jsFileUrl) {
}

async function createYoutubeMiddlewareToShadowDom() {
logger("createYoutubeMiddlewareToShadowDom");
const shadowRoot = document.createElement("div");
shadowRoot.id = youtubeShadowRootId;
shadowRoot.style.display = "none";
Expand Down Expand Up @@ -243,17 +254,16 @@ async function createYoutubeMiddlewareToShadowDom() {

// 添加到页面上
document.body.appendChild(shadowRoot);

eval(vueScript.textContent);
}

async function selectChineseTranscriptAutomatically() {
logger("Get transcript automatically.");
async function autoSelectChineseSubtitle() {
const chromeBottom = document.querySelector(".ytp-chrome-bottom");
const settingsButton = document.querySelector(
"[data-tooltip-target-id='ytp-settings-button']"
);
const controlPanelOuter = document.getElementById("ytp-id-18");
const controlPanelOuter = document.querySelector(
".ytp-popup.ytp-settings-menu"
);

// 让控制栏显示
chromeBottom.style.opacity = 1;
Expand Down Expand Up @@ -299,6 +309,71 @@ async function selectChineseTranscriptAutomatically() {
});
}

async function autoSelectEnglishSubtitle() {
const chromeBottom = document.querySelector(".ytp-chrome-bottom");
const settingsButton = document.querySelector(
"[data-tooltip-target-id='ytp-settings-button']"
);
const controlPanelOuter = document.querySelector(
".ytp-popup.ytp-settings-menu"
);

// 让控制栏显示
chromeBottom.style.opacity = 1;
// 点击设置图标,弹出Panel
await waitForSeconds(500);
settingsButton.click();
await waitForSeconds(500);
let controlPanelInner = controlPanelOuter.querySelector(".ytp-panel-menu");
await waitForSeconds(500);
controlPanelInner.childNodes.forEach((child) => {
if (
child.textContent.includes("字幕") ||
child.textContent.includes("Subtitles")
) {
child.click();
}
});
await waitForSeconds(500);
controlPanelInner = controlPanelOuter.querySelector(".ytp-panel-menu");
await waitForSeconds(500);
// 所有带有“英语”或者english字眼的项目集合
const englishElements = [];
controlPanelInner.childNodes.forEach((child) => {
const childTextContent = child.textContent.toLowerCase();
if (
(childTextContent.includes("english") ||
childTextContent.includes("英语")) &&
!childTextContent.includes(">>")
) {
englishElements.push(child);
}
});

// 集合里面可能不止有一个选项,选择字数最短的那个一般是“英语”或者“english”
if (englishElements.length === 0) {
logger("没有英文字幕");
} else {
let e = englishElements[0];
englishElements.forEach((element) => {
if (element.textContent.length < e.textContent.length) {
e = element;
}
});
e.click();
}
}

async function selectChineseTranscriptAutomatically() {
logger("Get transcript automatically.");
if (isChineseTranscriptExist) {
await autoSelectEnglishSubtitle();
}
if (isEnglishTranscriptExist) {
await autoSelectChineseSubtitle();
}
}

export function toggleSubtitleBtn() {
const subtitleBtn = document.querySelector("[aria-keyshortcuts='c']");
const value = subtitleBtn.getAttribute("aria-pressed");
Expand All @@ -322,7 +397,6 @@ export function addTranscriptStatusElementIfNotExist() {

export function setEnglishTranscriptStatus(active) {
isEnglishTranscriptExist = active;
console.log("set english background color", active);
const element = document.getElementById(transcriptStatusEnglishElementId);
element.style.backgroundColor = active
? activeStatusBackgroundColor
Expand All @@ -331,7 +405,6 @@ export function setEnglishTranscriptStatus(active) {

export function setChineseTranscriptStatus(active) {
isChineseTranscriptExist = active;
console.log("set Chinese background color", active);
const element = document.getElementById(transcriptStatusChineseElementId);
element.style.backgroundColor = active
? activeStatusBackgroundColor
Expand All @@ -346,11 +419,11 @@ function createTranscriptStatusElement() {
const container = document.createElement("div");
container.id = transcriptStatusElementId;
container.style.height = height;
container.style.width = "150px";
container.style.width = "200px";
container.style.backgroundColor = "white";
container.style.border = "1px solid #94a3b8";
container.style.display = "grid";
container.style.gridTemplateColumns = "1fr 1fr 1fr";
container.style.gridTemplateColumns = "1fr 1fr 1fr 1fr";
container.style.gridTemplateRows = "1fr";
container.style.alignItems = "center";
container.style.textAlign = "center";
Expand All @@ -363,42 +436,47 @@ function createTranscriptStatusElement() {
englishDiv.textContent = "English";
englishDiv.style.lineHeight = height;
englishDiv.style.height = "100%";
englishDiv.style.cursor = "not-allowed";
// englishDiv.style.backgroundColor = inActiveStatusBackgroundColor;
englishDiv.style.borderRight = "1px solid #64748b";
englishDiv.style.cursor = "not-allowed";

// 创建第二个子 div
const chineseDiv = document.createElement("div");
chineseDiv.id = transcriptStatusChineseElementId;
chineseDiv.textContent = "中文";
chineseDiv.style.lineHeight = height;
chineseDiv.style.height = "100%";
chineseDiv.style.cursor = "not-allowed";
chineseDiv.style.borderRight = "1px solid #64748b";
// chineseDiv.style.backgroundColor = inActiveStatusBackgroundColor;

// 创建第三个 div
const automationDiv = document.createElement("div");
automationDiv.textContent = "Auto";
automationDiv.style.lineHeight = height;
automationDiv.style.height = "100%";
automationDiv.style.borderRight = "1px solid #64748b";
automationDiv.style.cursor = "pointer";

// 创建第四个 div
const addVideoDiv = document.createElement("div");
addVideoDiv.textContent = "Add";
addVideoDiv.style.lineHeight = height;
addVideoDiv.style.height = "100%";
addVideoDiv.style.cursor = "pointer";
addVideoDiv.addEventListener("click", onClickStylishReaderIcon);

// 将子 div 添加到父容器
container.appendChild(englishDiv);
container.appendChild(chineseDiv);
container.appendChild(automationDiv);
container.appendChild(addVideoDiv);

automationDiv.addEventListener("click", selectChineseTranscriptAutomatically);

// 将容器添加到parent中
parentNode.appendChild(container);
console.log("isEnglishTranscriptExist", isEnglishTranscriptExist);
console.log("isChineseTranscriptExist", isChineseTranscriptExist);
if (!isEnglishTranscriptExist) {
setEnglishTranscriptStatus(false);
} else {
setEnglishTranscriptStatus(true);
}
if (!isChineseTranscriptExist) {
setChineseTranscriptStatus(false);
} else {
setEnglishTranscriptStatus(true);
}
setChineseTranscriptStatus(isChineseTranscriptExist);
setEnglishTranscriptStatus(isEnglishTranscriptExist);
}
4 changes: 0 additions & 4 deletions src/webPage/youtubeTransport/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,11 @@ const serverUrl = import.meta.env.VITE_SERVER
function registerEventListenerFromContentScript() {
document.addEventListener('fromYoutubeVideoContentScript', async (event: any) => {
const detail = JSON.parse(event.detail)
console.log(detail.data)
const d = detail.data
if (await checkIfVideoExist(d.videoId, d.token)) {
console.log('video exist')
alert('视频已经添加过')
return
}
console.log(d)
const a = await saveArticle(d)
if (a.data.code === 200) {
alert('视频添加成功')
Expand Down Expand Up @@ -46,7 +43,6 @@ async function checkIfVideoExist(videoId: string, token: string) {
{ videoId },
{ headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` } }
)
console.log(r.data)
if (r.data.code === 200 && r.data.data.length === 0) {
return false
}
Expand Down

0 comments on commit 51e88d2

Please sign in to comment.