Skip to content

Commit

Permalink
update: enable to unblock YouTube videos
Browse files Browse the repository at this point in the history
  • Loading branch information
michael-freling committed Jun 30, 2024
1 parent 3d85de5 commit 3155936
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 50 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ There are a few features supported to block spoilers
1. Keep the history of the last episode of a season for each anime you watched
2. Block spoilers on YouTube videos according to your watch history

[![Watch the video](https://img.youtube.com/vi/4mhkCjqaki8/hqdefault.jpg)](https://www.youtube.com/embed/4mhkCjqaki8)

## Supported services

Currently, spoilers are blocked on YouTube only.
Expand Down
1 change: 0 additions & 1 deletion manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
"content_scripts": [
{
"matches": ["https://www.youtube.com/*"],
"world": "MAIN",
"js": ["js/content_scripts/youtube.js"]
},
{
Expand Down
27 changes: 9 additions & 18 deletions src/background/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,6 @@ import { Config, UserHistory } from "../blocker";

const storage = chrome.storage.sync;

// sendResponse doesn't work within an async function
// https://developer.chrome.com/docs/extensions/develop/concepts/messaging#simple
// Use onMessageExternal from webpages like a main world
// https://developer.chrome.com/docs/extensions/develop/concepts/messaging#external-webpage
chrome.runtime.onMessageExternal.addListener(
(message, sender, sendResponse) => {
// const extensionID = chrome.runtime.id;
// sender.id is undefined
if (sender.origin != "https://www.youtube.com") {
return;
}

storage.get(["config", "userHistory"]).then(sendResponse);
return true;
}
);

// https://developer.chrome.com/docs/extensions/reference/api/runtime#event-onInstalled
chrome.runtime.onInstalled.addListener(async (details) => {
if (details.reason === "install") {
Expand All @@ -35,11 +18,19 @@ interface UpdateWatchHistoryMessage {
episode: number;
}

interface Message extends UpdateWatchHistoryMessage {}
interface GetConfigMessage {
type: "getConfig";
}

type Message = UpdateWatchHistoryMessage | GetConfigMessage;

chrome.runtime.onMessage.addListener(
(message: Message, sender, sendResponse) => {
switch (message.type) {
case "getConfig":
storage.get(["config", "userHistory"]).then(sendResponse);
return true;

case "updateWatchHistory":
// no support other than tv shows
if (message.mediaType != "tv") {
Expand Down
43 changes: 29 additions & 14 deletions src/content_scripts/content.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,30 @@
import { useState } from "react";
import { useEffect, useState } from "react";
import { Spoiler } from "../blocker";

interface BlockedContentProps {
spoiler: Spoiler;
originalContent: HTMLElement;
originalContentDisplayStyle: string;
}

export function BlockedContent({
spoiler,
originalContent,
originalContentDisplayStyle,
}: BlockedContentProps) {
const [isBlocked, setBlocked] = useState(true);

useEffect(() => {
if (isBlocked) {
originalContent.style.display = "none";
} else {
originalContent.style.display = originalContentDisplayStyle;
}
}, [isBlocked]);

if (!isBlocked) {
// Workaround to insert an HTMLElement, but it doesn't work at all
// https://stackoverflow.com/questions/49297334/react-how-to-add-htmlelement
return (
<div
key="non blocked"
dangerouslySetInnerHTML={{ __html: originalContent.innerHTML }}
/>
);
// Hide the react content but show the original content
return <></>;
}

let details = spoiler.title;
Expand All @@ -40,15 +44,26 @@ export function BlockedContent({
justifyContent: "center",
height: "100%",
fontSize: "1.5rem",
padding: "8px",

color: "#fff",
backgroundColor: "#cc4400",
}}
>
<div>Blocked by an Anime Spoiler Blocker</div>
<div>This is a content for a {details}</div>
{/*
<button onClick={() => setBlocked(false)} disabled={true}>
Show the original content. (Doesn't work)
<div>This is the video for {details}</div>
<button
onClick={() => setBlocked(false)}
style={{
margin: "8px",
padding: "8px",
backgroundColor: "#cccc00",
color: "#222",
borderRadius: "8px",
}}
>
Unblock
</button>
*/}
</div>
);
}
31 changes: 14 additions & 17 deletions src/content_scripts/youtube.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,18 +66,13 @@ class VideoSpoilerFilter {
// Listen for messages from the main world
window.addEventListener("load", async (event) => {
try {
// Sends a message to the service worker and receives a tip in response
const { config, userHistory } = await chrome.runtime.sendMessage(
// chrome.runtime.id,
process.env.EXTENSION_ID,
{
event: event,
}
);
console.debug({
config,
userHistory,
const { config, userHistory } = await chrome.runtime.sendMessage({
type: "getConfig",
});
// console.debug({
// config,
// userHistory,
// });

const blocker = new VideoSpoilerFilter(
new TextSpoilerAnalyzer(config, userHistory)
Expand Down Expand Up @@ -105,16 +100,18 @@ window.addEventListener("load", async (event) => {
// do not mount a react component if it's already mounted
return;
}
const root = document.createElement("div");
contentHTMLElement.parentElement!.appendChild(root);

const originalContent = contentHTMLElement.cloneNode(
true
) as HTMLElement;
caches[cacheKey] = originalContent;
ReactDOM.createRoot(contentHTMLElement).render(
caches[cacheKey] = contentHTMLElement;
ReactDOM.createRoot(root).render(
<StrictMode>
<BlockedContent
spoiler={spoiler}
originalContent={originalContent}
originalContent={contentHTMLElement as HTMLElement}
originalContentDisplayStyle={
(contentHTMLElement as HTMLElement).style.display
}
/>
</StrictMode>
);
Expand Down

0 comments on commit 3155936

Please sign in to comment.