diff --git a/manifest.json b/manifest.json index 48ec7a2e..0049280e 100644 --- a/manifest.json +++ b/manifest.json @@ -17,7 +17,7 @@ "64": "src/resources/icons/icon-64.png" } }, - "permissions": ["tabs", "notifications", "storage"], + "permissions": ["tabs", "notifications", "storage", "scripting"], "host_permissions": ["https://newsapi.org/", "*://*/*"], "background": { "service_worker": "src/background.ts" diff --git a/src/SEQTA.ts b/src/SEQTA.ts index f7f0254a..ac9c6e1b 100644 --- a/src/SEQTA.ts +++ b/src/SEQTA.ts @@ -28,6 +28,7 @@ import { updateBgDurations } from './seqta/ui/Animation' import { SettingsResizer } from "./seqta/ui/SettingsResizer"; import documentLoadCSS from './css/documentload.scss?inline' import injectedCSS from './css/injected.scss?inline' +import { injectYouTubeVideo } from './seqta/ui/VideoLoader' declare global { interface Window { @@ -135,17 +136,10 @@ export function OpenWhatsNewPopup() { let imagecont = document.createElement('div') imagecont.classList.add('whatsnewImgContainer') - let video = document.createElement('video') - let source = document.createElement('source') - // Perhaps we host this on a server and then grab it instead of having it locally? - source.setAttribute('src', browser.runtime.getURL(updateVideo)) - source.setAttribute('type', 'video/mp4') - video.autoplay = true - video.muted = true - video.loop = true - video.appendChild(source) - video.classList.add('whatsnewImg') - imagecont.appendChild(video) + + let div = document.createElement('div') + div.classList.add('whatsnewImg') + imagecont.appendChild(div) let textcontainer = document.createElement('div') textcontainer.classList.add('whatsnewTextContainer') @@ -274,6 +268,10 @@ export function OpenWhatsNewPopup() { let bkelement = document.getElementById('whatsnewbk') let popup = document.getElementsByClassName('whatsnewContainer')[0] + injectYouTubeVideo( + '5nM6T3KCVfM', 'PLSlFV-9e6dvyRNVacLwJwQZ3sWJYZ_PFb', document.querySelector('.whatsnewImg')!, true, true, '100%', '100%' + ) + animate( [popup, bkelement as HTMLElement], { scale: [0, 1], opacity: [0, 1] }, diff --git a/src/background.ts b/src/background.ts index 7e597081..ae5e7434 100644 --- a/src/background.ts +++ b/src/background.ts @@ -1,6 +1,7 @@ import browser from 'webextension-polyfill' import { onError } from './seqta/utils/onError'; import { SettingsState } from "./types/storage"; +import { applyYoutubeStyles } from './seqta/ui/VideoLoader'; export const openDB = () => { return new Promise((resolve, reject) => { @@ -118,6 +119,16 @@ browser.runtime.onMessage.addListener((request: any, _sender: any, sendResponse: GetNews(sendResponse, url); return true; + + case 'youtubeIframe': + const { hideControls } = request; + + browser.scripting.executeScript({ + target: { tabId: _sender.tab.id, allFrames: true }, + func: applyYoutubeStyles, + args: [hideControls] + }); + break; default: console.log('Unknown request type'); diff --git a/src/css/injected.scss b/src/css/injected.scss index 70d15402..304cf566 100644 --- a/src/css/injected.scss +++ b/src/css/injected.scss @@ -2902,10 +2902,31 @@ body:has(.outside-container:not(.hide)) #AddedSettings.tooltip:hover > .tooltipt padding-bottom: 16px; } .whatsnewImg { + background-color: black; + pointer-events: none !important; margin: 8px auto; width: 90%; border-radius: 16px; box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.3); + +} +.whatsnewImg > iframe { + aspect-ratio: 16/9; + width: 100%; + height: 100%; + border-radius: 16px; + opacity: 0; + + animation-delay: 0.8s !important; + animation: fade-in 0.5s forwards; +} +@keyframes fade-in { + 0% { + opacity: 0; + } + 100% { + opacity: 1; + } } .whatsnewTextContainer { display: flex; diff --git a/src/seqta/ui/VideoLoader.ts b/src/seqta/ui/VideoLoader.ts new file mode 100644 index 00000000..61209fcd --- /dev/null +++ b/src/seqta/ui/VideoLoader.ts @@ -0,0 +1,80 @@ +import Browser from "webextension-polyfill"; + +/** + * Injects a YouTube iframe into the specified element. + * + * @param videoId - The YouTube video ID to embed. + * @param playlistId - The YouTube playlist ID to allow embed to loop. + * @param mountElement - The element to mount the iframe to. + * @param hideControls - Whether to hide the YouTube player controls. + * @param mute - Whether to mute the video. + * @param width - The width of the iframe. + * @param height - The height of the iframe. + */ +export function injectYouTubeVideo(videoId: string, playlistId: string, mountElement: HTMLElement, hideControls: boolean, mute: boolean, width: string, height: string): void { + const controlsParam = hideControls ? 'controls=0' : 'controls=1'; + const autoplayParam = 'autoplay=1'; + const muteParam = mute ? 'mute=1' : 'mute=0'; + const listParams = playlistId ? `list=${playlistId}&` : ''; + + const iframeSrc = `https://www.youtube.com/embed/${videoId}?${listParams}${autoplayParam}&${controlsParam}&${muteParam}&loop=1`; + const iframe = document.createElement('iframe'); + + iframe.width = width; + iframe.height = height; + iframe.src = iframeSrc; + iframe.frameBorder = '0'; + iframe.allow = 'accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture'; + iframe.allowFullscreen = true; + + iframe.onload = () => { + Browser.runtime.sendMessage({ type: 'youtubeIframe', hideControls }); + }; + + mountElement.innerHTML = ''; // Clear any existing content + mountElement.appendChild(iframe); + + /* if (hideControls) { + applyCustomStylesToIframe(iframe); + } */ +} + +/** + * Function to inject CSS styles into the iframe. + * + * @param hideControls - Whether to hide the YouTube player controls. + */ +export function applyYoutubeStyles(hideControls: boolean) { + if (window.location == window.parent.location) return; + if (!window.location.href.includes('youtube.com/embed/')) return; + + if (hideControls) { + const hideControlsCss = ` + .ytp-gradient-top, + .ytp-chrome-bottom, + .ytp-chrome-top, + .ytp-chrome-top-buttons, + .ytp-pause-overlay, + .ytp-watermark { + display: none !important; + } + `; + const hideControlsStyle = document.createElement('style'); + hideControlsStyle.textContent = hideControlsCss; + document.head.appendChild(hideControlsStyle); + + const f =() => { + const btn = document.querySelector('.ytp-ad-skip-button') as HTMLButtonElement | null; + const adText = document.querySelector('.ytp-ad-text'); + const v = document.querySelector('video')!; + if(adText){ + v.currentTime = v.duration + } + if(btn){ + v.currentTime = v.duration + btn.click(); + } + } + setInterval(f, 100); + } +}