diff --git a/build/javascript/package.json b/build/javascript/package.json index 91f75d9ec..41b8d58ae 100644 --- a/build/javascript/package.json +++ b/build/javascript/package.json @@ -5,7 +5,6 @@ "main": "index.js", "dependencies": { "@joeattardi/emoji-button": "^4.6.0", - "@justinribeiro/lite-youtube": "^0.9.1", "@videojs/http-streaming": "2.8.2", "@videojs/themes": "^1.0.1", "htm": "^3.0.4", @@ -26,7 +25,6 @@ "@videojs/http-streaming/dist/videojs-http-streaming.min.js", "video.js/dist/video-js.min.css", "@joeattardi/emoji-button", - "@justinribeiro/lite-youtube", "htm", "preact", "mark.js/dist/mark.es6.min.js", diff --git a/webroot/index.html b/webroot/index.html index ea35a7b88..af0015382 100644 --- a/webroot/index.html +++ b/webroot/index.html @@ -63,7 +63,6 @@ - diff --git a/webroot/js/components/chat/chat-message-view.js b/webroot/js/components/chat/chat-message-view.js index be0fbcc3f..8d4d03866 100644 --- a/webroot/js/components/chat/chat-message-view.js +++ b/webroot/js/components/chat/chat-message-view.js @@ -122,10 +122,7 @@ function getMessageWithEmbeds(message) { var anchors = container.getElementsByTagName('a'); for (var i = 0; i < anchors.length; i++) { const url = anchors[i].href; - if (getYoutubeIdFromURL(url)) { - const youtubeID = getYoutubeIdFromURL(url); - embedText += getYoutubeEmbedFromID(youtubeID); - } else if (url.indexOf('instagram.com/p/') > -1) { + if (url.indexOf('instagram.com/p/') > -1) { embedText += getInstagramEmbedFromURL(url); } } @@ -142,26 +139,6 @@ function getMessageWithEmbeds(message) { return message + embedText; } -function getYoutubeIdFromURL(url) { - try { - var regExp = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/; - var match = url.match(regExp); - - if (match && match[2].length == 11) { - return match[2]; - } else { - return null; - } - } catch (e) { - console.log(e); - return null; - } -} - -function getYoutubeEmbedFromID(id) { - return `
`; -} - function getInstagramEmbedFromURL(url) { const urlObject = new URL(url.replace(/\/$/, '')); urlObject.pathname += '/embed'; diff --git a/webroot/js/web_modules/@justinribeiro/lite-youtube.js b/webroot/js/web_modules/@justinribeiro/lite-youtube.js deleted file mode 100644 index 281152c04..000000000 --- a/webroot/js/web_modules/@justinribeiro/lite-youtube.js +++ /dev/null @@ -1,302 +0,0 @@ -/** - * - * The shadowDom / Intersection Observer version of Paul's concept: - * https://github.com/paulirish/lite-youtube-embed - * - * A lightweight YouTube embed. Still should feel the same to the user, just - * MUCH faster to initialize and paint. - * - * Thx to these as the inspiration - * https://storage.googleapis.com/amp-vs-non-amp/youtube-lazy.html - * https://autoplay-youtube-player.glitch.me/ - * - * Once built it, I also found these (👍👍): - * https://github.com/ampproject/amphtml/blob/master/extensions/amp-youtube - * https://github.com/Daugilas/lazyYT https://github.com/vb/lazyframe - */ -class LiteYTEmbed extends HTMLElement { - constructor() { - super(); - this.iframeLoaded = false; - this.setupDom(); - } - static get observedAttributes() { - return ['videoid']; - } - connectedCallback() { - this.addEventListener('pointerover', LiteYTEmbed.warmConnections, { - once: true, - }); - this.addEventListener('click', () => this.addIframe()); - } - get videoId() { - return encodeURIComponent(this.getAttribute('videoid') || ''); - } - set videoId(id) { - this.setAttribute('videoid', id); - } - get videoTitle() { - return this.getAttribute('videotitle') || 'Video'; - } - set videoTitle(title) { - this.setAttribute('videotitle', title); - } - get videoPlay() { - return this.getAttribute('videoPlay') || 'Play'; - } - set videoPlay(name) { - this.setAttribute('videoPlay', name); - } - get videoStartAt() { - return Number(this.getAttribute('videoStartAt') || '0'); - } - set videoStartAt(time) { - this.setAttribute('videoStartAt', String(time)); - } - get autoLoad() { - return this.hasAttribute('autoload'); - } - set autoLoad(value) { - if (value) { - this.setAttribute('autoload', ''); - } - else { - this.removeAttribute('autoload'); - } - } - get params() { - return `start=${this.videoStartAt}&${this.getAttribute('params')}`; - } - /** - * Define our shadowDOM for the component - */ - setupDom() { - const shadowDom = this.attachShadow({ mode: 'open' }); - shadowDom.innerHTML = ` - -
- - - - - - -
- `; - this.domRefFrame = this.shadowRoot.querySelector('#frame'); - this.domRefImg = { - fallback: this.shadowRoot.querySelector('#fallbackPlaceholder'), - webp: this.shadowRoot.querySelector('#webpPlaceholder'), - jpeg: this.shadowRoot.querySelector('#jpegPlaceholder'), - }; - this.domRefPlayButton = this.shadowRoot.querySelector('.lty-playbtn'); - } - /** - * Parse our attributes and fire up some placeholders - */ - setupComponent() { - this.initImagePlaceholder(); - this.domRefPlayButton.setAttribute('aria-label', `${this.videoPlay}: ${this.videoTitle}`); - this.setAttribute('title', `${this.videoPlay}: ${this.videoTitle}`); - if (this.autoLoad) { - this.initIntersectionObserver(); - } - } - /** - * Lifecycle method that we use to listen for attribute changes to period - * @param {*} name - * @param {*} oldVal - * @param {*} newVal - */ - attributeChangedCallback(name, oldVal, newVal) { - switch (name) { - case 'videoid': { - if (oldVal !== newVal) { - this.setupComponent(); - // if we have a previous iframe, remove it and the activated class - if (this.domRefFrame.classList.contains('lyt-activated')) { - this.domRefFrame.classList.remove('lyt-activated'); - this.shadowRoot.querySelector('iframe').remove(); - this.iframeLoaded = false; - } - } - break; - } - } - } - /** - * Inject the iframe into the component body - */ - addIframe() { - if (!this.iframeLoaded) { - const iframeHTML = ` -`; - this.domRefFrame.insertAdjacentHTML('beforeend', iframeHTML); - this.domRefFrame.classList.add('lyt-activated'); - this.iframeLoaded = true; - } - } - /** - * Setup the placeholder image for the component - */ - initImagePlaceholder() { - // we don't know which image type to preload, so warm the connection - LiteYTEmbed.addPrefetch('preconnect', 'https://i.ytimg.com/'); - const posterUrlWebp = `https://i.ytimg.com/vi_webp/${this.videoId}/hqdefault.webp`; - const posterUrlJpeg = `https://i.ytimg.com/vi/${this.videoId}/hqdefault.jpg`; - this.domRefImg.webp.srcset = posterUrlWebp; - this.domRefImg.jpeg.srcset = posterUrlJpeg; - this.domRefImg.fallback.src = posterUrlJpeg; - this.domRefImg.fallback.setAttribute('aria-label', `${this.videoPlay}: ${this.videoTitle}`); - this.domRefImg.fallback.setAttribute('alt', `${this.videoPlay}: ${this.videoTitle}`); - } - /** - * Setup the Intersection Observer to load the iframe when scrolled into view - */ - initIntersectionObserver() { - if ('IntersectionObserver' in window && - 'IntersectionObserverEntry' in window) { - const options = { - root: null, - rootMargin: '0px', - threshold: 0, - }; - const observer = new IntersectionObserver((entries, observer) => { - entries.forEach(entry => { - if (entry.isIntersecting && !this.iframeLoaded) { - LiteYTEmbed.warmConnections(); - this.addIframe(); - observer.unobserve(this); - } - }); - }, options); - observer.observe(this); - } - } - /** - * Add a to the head - * @param {*} kind - * @param {*} url - * @param {*} as - */ - static addPrefetch(kind, url, as) { - const linkElem = document.createElement('link'); - linkElem.rel = kind; - linkElem.href = url; - if (as) { - linkElem.as = as; - } - linkElem.crossOrigin = 'true'; - document.head.append(linkElem); - } - /** - * Begin preconnecting to warm up the iframe load Since the embed's netwok - * requests load within its iframe, preload/prefetch'ing them outside the - * iframe will only cause double-downloads. So, the best we can do is warm up - * a few connections to origins that are in the critical path. - * - * Maybe `` would work, but it's unsupported: - * http://crbug.com/593267 But TBH, I don't think it'll happen soon with Site - * Isolation and split caches adding serious complexity. - */ - static warmConnections() { - if (LiteYTEmbed.preconnected) - return; - // Host that YT uses to serve JS needed by player, per amp-youtube - LiteYTEmbed.addPrefetch('preconnect', 'https://s.ytimg.com'); - // The iframe document and most of its subresources come right off - // youtube.com - LiteYTEmbed.addPrefetch('preconnect', 'https://www.youtube.com'); - // The botguard script is fetched off from google.com - LiteYTEmbed.addPrefetch('preconnect', 'https://www.google.com'); - // TODO: Not certain if these ad related domains are in the critical path. - // Could verify with domain-specific throttling. - LiteYTEmbed.addPrefetch('preconnect', 'https://googleads.g.doubleclick.net'); - LiteYTEmbed.addPrefetch('preconnect', 'https://static.doubleclick.net'); - LiteYTEmbed.preconnected = true; - } -} -LiteYTEmbed.preconnected = false; -// Register custom element -customElements.define('lite-youtube', LiteYTEmbed); - -export { LiteYTEmbed }; diff --git a/webroot/styles/chat.css b/webroot/styles/chat.css index fbacc6003..4d72e8d5b 100644 --- a/webroot/styles/chat.css +++ b/webroot/styles/chat.css @@ -179,11 +179,6 @@ /* height: 15rem; */ } -.message-text .youtube-embed { - width: 90%; - height: auto; -} - /* MESSAGE TEXT CONTENT */ /* MESSAGE TEXT CONTENT */ /* MESSAGE TEXT CONTENT */ diff --git a/webroot/styles/standalone-chat.css b/webroot/styles/standalone-chat.css index 83db75b66..711de5acf 100644 --- a/webroot/styles/standalone-chat.css +++ b/webroot/styles/standalone-chat.css @@ -45,7 +45,6 @@ The styles in this file mostly ovveride those coming from chat.css #messages-only .message-text .chat-embed, #messages-only .message-text .instagram-embed, -#messages-only .message-text .embedded-image, -#messages-only .message-text .youtube-embed { +#messages-only .message-text .embedded-image { max-width: 350px; }