Merge branch 'feat/video-audio-player' into 'master'
Feat/video audio player See merge request idotj/mastodon-embed-feed-timeline!24
This commit is contained in:
		
						commit
						7be552b956
					
				| @ -1,3 +1,8 @@ | |||||||
|  | v3.13.1 - 12/01/2024 | ||||||
|  | - Add support for audio player | ||||||
|  | - Add support for video player | ||||||
|  | - Load video player when user clicks on video preview | ||||||
|  | 
 | ||||||
| v3.12.0 - 11/12/2023 | v3.12.0 - 11/12/2023 | ||||||
| - Fix link preview event on click | - Fix link preview event on click | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -77,6 +77,9 @@ hide_reblog: false, | |||||||
| // Hide replies toots. Default: don't hide | // Hide replies toots. Default: don't hide | ||||||
| hide_replies: false, | hide_replies: false, | ||||||
| 
 | 
 | ||||||
|  | // Hide video image preview and load video player instead. Default: don't hide | ||||||
|  | hide_video_preview: false, | ||||||
|  | 
 | ||||||
| // Hide preview for links. Default: don't hide | // Hide preview for links. Default: don't hide | ||||||
| hide_preview_link: false, | hide_preview_link: false, | ||||||
| 
 | 
 | ||||||
|  | |||||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 260 KiB After Width: | Height: | Size: 260 KiB | 
| @ -7,24 +7,25 @@ | |||||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0" /> |     <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||||||
|     <meta name="keywords" content="mastodon, embed timeline" /> |     <meta name="keywords" content="mastodon, embed timeline" /> | ||||||
|     <meta name="description" content="Mastodon embed timeline" /> |     <meta name="description" content="Mastodon embed timeline" /> | ||||||
|     <link rel="stylesheet" href="mastodon-timeline.css" /> |     <link rel="stylesheet" href="mastodon-timeline.min.css" /> | ||||||
|     <style> |     <style> | ||||||
|       html { |       html { | ||||||
|         height: 100%; |         height: 100%; | ||||||
|       } |       } | ||||||
| 
 |  | ||||||
|       body { |       body { | ||||||
|  |         display: flex; | ||||||
|         height: 100%; |         height: 100%; | ||||||
|  |         justify-content: center; | ||||||
|  |         align-items: center; | ||||||
|         background: lightslategray; |         background: lightslategray; | ||||||
|         font-size: 16px; |  | ||||||
|         font-family: Arial, Helvetica, sans-serif; |         font-family: Arial, Helvetica, sans-serif; | ||||||
|  |         font-size: 16px; | ||||||
|  |         margin: 0; | ||||||
|       } |       } | ||||||
| 
 |  | ||||||
|       .dummy-wrapper { |       .dummy-wrapper { | ||||||
|         width: 100%; |         width: calc(100% - 1rem); | ||||||
|         max-width: 26rem; |         max-width: 26rem; | ||||||
|         height: calc(100% - 4rem); |         height: calc(100% - 3rem); | ||||||
|         margin: 2rem auto; |  | ||||||
|       } |       } | ||||||
|     </style> |     </style> | ||||||
|   </head> |   </head> | ||||||
| @ -38,6 +39,6 @@ | |||||||
|       </div> |       </div> | ||||||
|     </div> |     </div> | ||||||
| 
 | 
 | ||||||
|     <script src="mastodon-timeline.js"></script> |     <script src="mastodon-timeline.min.js"></script> | ||||||
|   </body> |   </body> | ||||||
| </html> | </html> | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| /* Mastodon embed feed timeline v3.12.0 */ | /* Mastodon embed feed timeline v3.13.1 */ | ||||||
| /* More info at: */ | /* More info at: */ | ||||||
| /* https://gitlab.com/idotj/mastodon-embed-feed-timeline */ | /* https://gitlab.com/idotj/mastodon-embed-feed-timeline */ | ||||||
| 
 | 
 | ||||||
| @ -223,6 +223,7 @@ html[data-theme="dark"] { | |||||||
| 
 | 
 | ||||||
| /* Medias */ | /* Medias */ | ||||||
| .mt-toot-media { | .mt-toot-media { | ||||||
|  |   position: relative; | ||||||
|   overflow: hidden; |   overflow: hidden; | ||||||
|   margin-bottom: 1rem; |   margin-bottom: 1rem; | ||||||
| } | } | ||||||
| @ -233,15 +234,26 @@ html[data-theme="dark"] { | |||||||
|   z-index: 1; |   z-index: 1; | ||||||
|   transform: translate(-50%, -50%); |   transform: translate(-50%, -50%); | ||||||
| } | } | ||||||
| .mt-toot-media-spoiler > img { | .mt-toot-media-spoiler > img, | ||||||
|  | .mt-toot-media-spoiler > audio, | ||||||
|  | .mt-toot-media-spoiler > video, | ||||||
|  | .mt-toot-media-spoiler > .mt-toot-media-play-icon { | ||||||
|   filter: blur(2rem); |   filter: blur(2rem); | ||||||
|  |   pointer-events: none; | ||||||
| } | } | ||||||
| .img-ratio14_7 { | .mt-toot-media.img-ratio14_7, | ||||||
|   position: relative; | .mt-toot-media.video-ratio14_7 { | ||||||
|   padding-top: 56.95%; |   padding-top: 56.95%; | ||||||
|   width: 100%; |   width: 100%; | ||||||
| } | } | ||||||
| .img-ratio14_7 > img { | .mt-toot-media > audio { | ||||||
|  |   width: 100%; | ||||||
|  |   position: relative; | ||||||
|  |   z-index: 1; | ||||||
|  | } | ||||||
|  | .img-ratio14_7 > img, | ||||||
|  | .video-ratio14_7 > img, | ||||||
|  | .video-ratio14_7 > video { | ||||||
|   width: 100%; |   width: 100%; | ||||||
|   height: auto; |   height: auto; | ||||||
|   position: absolute; |   position: absolute; | ||||||
| @ -251,6 +263,29 @@ html[data-theme="dark"] { | |||||||
|   text-align: center; |   text-align: center; | ||||||
|   color: var(--content-text); |   color: var(--content-text); | ||||||
| } | } | ||||||
|  | .mt-toot-media.loading-spinner .mt-toot-media-play-icon { | ||||||
|  |   display: none; | ||||||
|  | } | ||||||
|  | .mt-toot-media-play-icon { | ||||||
|  |   display: flex; | ||||||
|  |   position: absolute; | ||||||
|  |   width: 3rem; | ||||||
|  |   height: 3rem; | ||||||
|  |   top: calc(50% - 1.5rem); | ||||||
|  |   left: calc(50% - 1.5rem); | ||||||
|  |   justify-content: center; | ||||||
|  |   align-items: center; | ||||||
|  |   background-color: transparent; | ||||||
|  |   border: none; | ||||||
|  |   cursor: pointer; | ||||||
|  | } | ||||||
|  | .mt-toot-media-play-icon > svg { | ||||||
|  |   width: 2.5rem; | ||||||
|  |   height: 2.5rem; | ||||||
|  |   fill: var(--bg-color); | ||||||
|  |   stroke:var(--content-text); | ||||||
|  |   stroke-width: 1px; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| /* Preview link */ | /* Preview link */ | ||||||
| .mt-toot-preview { | .mt-toot-preview { | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| /** | /** | ||||||
|  * Mastodon embed feed timeline v3.12.0 |  * Mastodon embed feed timeline v3.13.1 | ||||||
|  * More info at: |  * More info at: | ||||||
|  * https://gitlab.com/idotj/mastodon-embed-feed-timeline
 |  * https://gitlab.com/idotj/mastodon-embed-feed-timeline
 | ||||||
|  */ |  */ | ||||||
| @ -46,6 +46,9 @@ window.addEventListener("load", () => { | |||||||
|     // Hide replies toots. Default: don't hide
 |     // Hide replies toots. Default: don't hide
 | ||||||
|     hide_replies: false, |     hide_replies: false, | ||||||
| 
 | 
 | ||||||
|  |     // Hide video image preview and load video player instead. Default: don't hide
 | ||||||
|  |     hide_video_preview: false, | ||||||
|  | 
 | ||||||
|     // Hide preview card if toot contains a link, photo or video from a URL. Default: don't hide
 |     // Hide preview card if toot contains a link, photo or video from a URL. Default: don't hide
 | ||||||
|     hide_preview_link: false, |     hide_preview_link: false, | ||||||
| 
 | 
 | ||||||
| @ -89,6 +92,10 @@ const MastodonApi = function (params_) { | |||||||
|     typeof params_.hide_reblog !== "undefined" ? params_.hide_reblog : false; |     typeof params_.hide_reblog !== "undefined" ? params_.hide_reblog : false; | ||||||
|   this.HIDE_REPLIES = |   this.HIDE_REPLIES = | ||||||
|     typeof params_.hide_replies !== "undefined" ? params_.hide_replies : false; |     typeof params_.hide_replies !== "undefined" ? params_.hide_replies : false; | ||||||
|  |   this.HIDE_VIDEO_PREVIEW = | ||||||
|  |     typeof params_.hide_video_preview !== "undefined" | ||||||
|  |       ? params_.hide_video_preview | ||||||
|  |       : false; | ||||||
|   this.HIDE_PREVIEW_LINK = |   this.HIDE_PREVIEW_LINK = | ||||||
|     typeof params_.hide_preview_link !== "undefined" |     typeof params_.hide_preview_link !== "undefined" | ||||||
|       ? params_.hide_preview_link |       ? params_.hide_preview_link | ||||||
| @ -185,7 +192,8 @@ MastodonApi.prototype.buildTimeline = async function () { | |||||||
|     if ( |     if ( | ||||||
|       e.target.localName == "article" || |       e.target.localName == "article" || | ||||||
|       e.target.offsetParent?.localName == "article" || |       e.target.offsetParent?.localName == "article" || | ||||||
|       e.target.localName == "img" |       (e.target.localName == "img" && | ||||||
|  |         !e.target.parentNode.classList.contains("video-ratio14_7")) | ||||||
|     ) { |     ) { | ||||||
|       openTootURL(e); |       openTootURL(e); | ||||||
|     } |     } | ||||||
| @ -193,6 +201,19 @@ MastodonApi.prototype.buildTimeline = async function () { | |||||||
|     if (e.target.localName == "button" && e.target.className == "spoiler-btn") { |     if (e.target.localName == "button" && e.target.className == "spoiler-btn") { | ||||||
|       toogleSpoiler(e); |       toogleSpoiler(e); | ||||||
|     } |     } | ||||||
|  |     // Check if video preview image or play icon/button was clicked
 | ||||||
|  |     if ( | ||||||
|  |       e.target.className == "mt-toot-media-play-icon" || | ||||||
|  |       (e.target.localName == "svg" && | ||||||
|  |         e.target.parentNode.className == "mt-toot-media-play-icon") || | ||||||
|  |       (e.target.localName == "path" && | ||||||
|  |         e.target.parentNode.parentNode.className == | ||||||
|  |           "mt-toot-media-play-icon") || | ||||||
|  |       (e.target.localName == "img" && | ||||||
|  |         e.target.parentNode.classList.contains("video-ratio14_7")) | ||||||
|  |     ) { | ||||||
|  |       loadTootVideo(e); | ||||||
|  |     } | ||||||
|   }); |   }); | ||||||
|   this.mtBodyContainer.addEventListener("keydown", function (e) { |   this.mtBodyContainer.addEventListener("keydown", function (e) { | ||||||
|     // Check if Enter key was pressed with focus in an article
 |     // Check if Enter key was pressed with focus in an article
 | ||||||
| @ -229,7 +250,11 @@ MastodonApi.prototype.buildTimeline = async function () { | |||||||
|    */ |    */ | ||||||
|   const toogleSpoiler = function (e) { |   const toogleSpoiler = function (e) { | ||||||
|     const nextSibling = e.target.nextSibling; |     const nextSibling = e.target.nextSibling; | ||||||
|     if (nextSibling.localName === "img") { |     if ( | ||||||
|  |       nextSibling.localName === "img" || | ||||||
|  |       nextSibling.localName === "audio" || | ||||||
|  |       nextSibling.localName === "video" | ||||||
|  |     ) { | ||||||
|       e.target.parentNode.classList.remove("mt-toot-media-spoiler"); |       e.target.parentNode.classList.remove("mt-toot-media-spoiler"); | ||||||
|       e.target.style.display = "none"; |       e.target.style.display = "none"; | ||||||
|     } else if ( |     } else if ( | ||||||
| @ -249,6 +274,18 @@ MastodonApi.prototype.buildTimeline = async function () { | |||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   }; |   }; | ||||||
|  | 
 | ||||||
|  |   /** | ||||||
|  |    * Replace the video preview image by the video player | ||||||
|  |    * @param {event} e User interaction trigger | ||||||
|  |    */ | ||||||
|  |   const loadTootVideo = function (e) { | ||||||
|  |     const parentNode = e.target.closest("[data-video-url]"); | ||||||
|  |     const videoURL = parentNode.dataset.videoUrl; | ||||||
|  |     parentNode.replaceChildren(); | ||||||
|  |     parentNode.innerHTML = | ||||||
|  |       '<video controls src="' + videoURL + '" autoplay></video>'; | ||||||
|  |   }; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
| @ -541,14 +578,14 @@ MastodonApi.prototype.assambleToot = function (c, i) { | |||||||
|   // Media attachments
 |   // Media attachments
 | ||||||
|   let media = []; |   let media = []; | ||||||
|   if (c.media_attachments.length > 0) { |   if (c.media_attachments.length > 0) { | ||||||
|     for (let picid in c.media_attachments) { |     for (let i in c.media_attachments) { | ||||||
|       media.push(this.placeMedias(c.media_attachments[picid], c.sensitive)); |       media.push(this.placeMedias(c.media_attachments[i], c.sensitive)); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   if (c.reblog && c.reblog.media_attachments.length > 0) { |   if (c.reblog && c.reblog.media_attachments.length > 0) { | ||||||
|     for (let picid in c.reblog.media_attachments) { |     for (let i in c.reblog.media_attachments) { | ||||||
|       media.push( |       media.push( | ||||||
|         this.placeMedias(c.reblog.media_attachments[picid], c.reblog.sensitive) |         this.placeMedias(c.reblog.media_attachments[i], c.reblog.sensitive) | ||||||
|       ); |       ); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| @ -729,20 +766,85 @@ MastodonApi.prototype.replaceHTMLtag = function ( | |||||||
|  */ |  */ | ||||||
| MastodonApi.prototype.placeMedias = function (m, s) { | MastodonApi.prototype.placeMedias = function (m, s) { | ||||||
|   const spoiler = s || false; |   const spoiler = s || false; | ||||||
|   const pic = |   const type = m.type; | ||||||
|     '<div class="mt-toot-media img-ratio14_7 ' + |   let media = ""; | ||||||
|     (spoiler ? "mt-toot-media-spoiler " : "") + |  | ||||||
|     this.SPINNER_CLASS + |  | ||||||
|     '">' + |  | ||||||
|     (spoiler ? '<button class="spoiler-btn">Show content</button>' : "") + |  | ||||||
|     '<img src="' + |  | ||||||
|     m.preview_url + |  | ||||||
|     '" alt="' + |  | ||||||
|     (m.description ? this.escapeHtml(m.description) : "") + |  | ||||||
|     '" loading="lazy" />' + |  | ||||||
|     "</div>"; |  | ||||||
| 
 | 
 | ||||||
|   return pic; |   if (type === "image") { | ||||||
|  |     media = | ||||||
|  |       '<div class="mt-toot-media img-ratio14_7 ' + | ||||||
|  |       (spoiler ? "mt-toot-media-spoiler " : "") + | ||||||
|  |       this.SPINNER_CLASS + | ||||||
|  |       '">' + | ||||||
|  |       (spoiler ? '<button class="spoiler-btn">Show content</button>' : "") + | ||||||
|  |       '<img src="' + | ||||||
|  |       m.preview_url + | ||||||
|  |       '" alt="' + | ||||||
|  |       (m.description ? this.escapeHtml(m.description) : "") + | ||||||
|  |       '" loading="lazy" />' + | ||||||
|  |       "</div>"; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if (type === "audio") { | ||||||
|  |     if (m.preview_url) { | ||||||
|  |       media = | ||||||
|  |         '<div class="mt-toot-media img-ratio14_7 ' + | ||||||
|  |         (spoiler ? "mt-toot-media-spoiler " : "") + | ||||||
|  |         this.SPINNER_CLASS + | ||||||
|  |         '">' + | ||||||
|  |         (spoiler ? '<button class="spoiler-btn">Show content</button>' : "") + | ||||||
|  |         '<audio controls src="' + | ||||||
|  |         m.url + | ||||||
|  |         '"></audio>' + | ||||||
|  |         '<img src="' + | ||||||
|  |         m.preview_url + | ||||||
|  |         '" alt="' + | ||||||
|  |         (m.description ? this.escapeHtml(m.description) : "") + | ||||||
|  |         '" loading="lazy" />' + | ||||||
|  |         "</div>"; | ||||||
|  |     } else { | ||||||
|  |       media = | ||||||
|  |         '<div class="mt-toot-media ' + | ||||||
|  |         (spoiler ? "mt-toot-media-spoiler " : "") + | ||||||
|  |         '">' + | ||||||
|  |         (spoiler ? '<button class="spoiler-btn">Show content</button>' : "") + | ||||||
|  |         '<audio controls src="' + | ||||||
|  |         m.url + | ||||||
|  |         '"></audio>' + | ||||||
|  |         "</div>"; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if (type === "video") { | ||||||
|  |     if (!this.HIDE_VIDEO_PREVIEW) { | ||||||
|  |       media = | ||||||
|  |         '<div class="mt-toot-media video-ratio14_7 ' + | ||||||
|  |         (spoiler ? "mt-toot-media-spoiler " : "") + | ||||||
|  |         this.SPINNER_CLASS + | ||||||
|  |         '" data-video-url="' + | ||||||
|  |         m.url + | ||||||
|  |         '">' + | ||||||
|  |         (spoiler ? '<button class="spoiler-btn">Show content</button>' : "") + | ||||||
|  |         '<img src="' + | ||||||
|  |         m.preview_url + | ||||||
|  |         '" alt="' + | ||||||
|  |         (m.description ? this.escapeHtml(m.description) : "") + | ||||||
|  |         '" loading="lazy" />' + | ||||||
|  |         '<button class="mt-toot-media-play-icon" title="Load video"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 14"><path d="M9.5 7l-9 6.3V.7z"/></svg></button>' + | ||||||
|  |         "</div>"; | ||||||
|  |     } else { | ||||||
|  |       media = | ||||||
|  |         '<div class="mt-toot-media video-ratio14_7 ' + | ||||||
|  |         (spoiler ? "mt-toot-media-spoiler " : "") + | ||||||
|  |         '">' + | ||||||
|  |         (spoiler ? '<button class="spoiler-btn">Show content</button>' : "") + | ||||||
|  |         '<video controls src="' + | ||||||
|  |         m.url + | ||||||
|  |         '"></video>' + | ||||||
|  |         "</div>"; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return media; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  | |||||||
							
								
								
									
										2
									
								
								src/mastodon-timeline.min.css
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								src/mastodon-timeline.min.css
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										2
									
								
								src/mastodon-timeline.min.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								src/mastodon-timeline.min.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 i.j
						i.j