| 
									
										
										
										
											2022-06-09 12:51:19 +02:00
										 |  |  | /* | 
					
						
							|  |  |  | 	GoToSocial | 
					
						
							| 
									
										
										
										
											2023-03-12 18:49:06 +01:00
										 |  |  | 	Copyright (C) GoToSocial Authors admin@gotosocial.org | 
					
						
							|  |  |  | 	SPDX-License-Identifier: AGPL-3.0-or-later | 
					
						
							| 
									
										
										
										
											2022-06-09 12:51:19 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	This program is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  | 	it under the terms of the GNU Affero General Public License as published by | 
					
						
							|  |  |  | 	the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | 	(at your option) any later version. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  | 	but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  | 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  | 	GNU Affero General Public License for more details. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	You should have received a copy of the GNU Affero General Public License | 
					
						
							|  |  |  | 	along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-07 17:58:01 +02:00
										 |  |  | const Photoswipe = require("photoswipe/dist/umd/photoswipe.umd.min.js"); | 
					
						
							|  |  |  | const PhotoswipeLightbox = require("photoswipe/dist/umd/photoswipe-lightbox.umd.min.js"); | 
					
						
							|  |  |  | const PhotoswipeCaptionPlugin = require("photoswipe-dynamic-caption-plugin").default; | 
					
						
							| 
									
										
										
										
											2023-05-11 17:46:32 +02:00
										 |  |  | const Plyr = require("plyr"); | 
					
						
							| 
									
										
										
										
											2023-12-27 11:23:52 +01:00
										 |  |  | const Prism = require("./prism.js"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Prism.manual = true; | 
					
						
							|  |  |  | Prism.highlightAll(); | 
					
						
							| 
									
										
										
										
											2022-08-07 17:58:01 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-08 10:12:16 +02:00
										 |  |  | const reduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-03 20:35:43 +02:00
										 |  |  | let [_, _user, type, id] = window.location.pathname.split("/"); | 
					
						
							|  |  |  | if (type == "statuses") { | 
					
						
							|  |  |  | 	let firstStatus = document.getElementsByClassName("thread")[0].children[0]; | 
					
						
							|  |  |  | 	if (firstStatus.id != id) { | 
					
						
							|  |  |  | 		document.getElementById(id).scrollIntoView(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-07 17:58:01 +02:00
										 |  |  | const lightbox = new PhotoswipeLightbox({ | 
					
						
							|  |  |  | 	gallery: '.photoswipe-gallery', | 
					
						
							| 
									
										
										
										
											2023-05-11 17:46:32 +02:00
										 |  |  | 	children: '.photoswipe-slide', | 
					
						
							| 
									
										
										
										
											2022-08-07 17:58:01 +02:00
										 |  |  | 	pswpModule: Photoswipe, | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | new PhotoswipeCaptionPlugin(lightbox, { | 
					
						
							|  |  |  | 	type: 'auto', | 
					
						
							| 
									
										
										
										
											2023-05-11 17:46:32 +02:00
										 |  |  | 	captionContent(slide) { | 
					
						
							|  |  |  | 		return slide.data.alt; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | lightbox.addFilter('itemData', (item) => { | 
					
						
							|  |  |  | 	const el = item.element; | 
					
						
							| 
									
										
										
										
											2024-08-08 10:12:16 +02:00
										 |  |  | 	if ( | 
					
						
							|  |  |  | 		el && | 
					
						
							|  |  |  | 		el.classList.contains("plyr-video") && | 
					
						
							|  |  |  | 		el._plyrContainer !== undefined | 
					
						
							|  |  |  | 	) { | 
					
						
							| 
									
										
										
										
											2023-05-11 17:46:32 +02:00
										 |  |  | 		const parentNode = el._plyrContainer.parentNode; | 
					
						
							|  |  |  | 		return { | 
					
						
							|  |  |  | 			alt: el.getAttribute("alt"), | 
					
						
							|  |  |  | 			_video: { | 
					
						
							|  |  |  | 				open(c) { | 
					
						
							|  |  |  | 					c.appendChild(el._plyrContainer); | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 				close() { | 
					
						
							|  |  |  | 					parentNode.appendChild(el._plyrContainer); | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 				pause() { | 
					
						
							|  |  |  | 					el._player.pause(); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			width: parseInt(el.dataset.pswpWidth), | 
					
						
							|  |  |  | 			height: parseInt(el.dataset.pswpHeight) | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return item; | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | lightbox.on("contentActivate", (e) => { | 
					
						
							|  |  |  | 	const { content } = e; | 
					
						
							|  |  |  | 	if (content.data._video != undefined) { | 
					
						
							|  |  |  | 		content.data._video.open(content.element); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | lightbox.on("contentDeactivate", (e) => { | 
					
						
							|  |  |  | 	const { content } = e; | 
					
						
							|  |  |  | 	if (content.data._video != undefined) { | 
					
						
							|  |  |  | 		content.data._video.pause(); | 
					
						
							|  |  |  | 		content.data._video.close(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | lightbox.on("close", function () { | 
					
						
							|  |  |  | 	if (lightbox.pswp.currSlide.data._video != undefined) { | 
					
						
							|  |  |  | 		lightbox.pswp.currSlide.data._video.close(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-08-07 17:58:01 +02:00
										 |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | lightbox.init(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-11 17:46:32 +02:00
										 |  |  | function dynamicSpoiler(className, updateFunc) { | 
					
						
							|  |  |  | 	Array.from(document.getElementsByClassName(className)).forEach((spoiler) => { | 
					
						
							|  |  |  | 		const update = updateFunc(spoiler); | 
					
						
							|  |  |  | 		if (update) { | 
					
						
							|  |  |  | 			update(); | 
					
						
							|  |  |  | 			spoiler.addEventListener("toggle", update); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | dynamicSpoiler("text-spoiler", (spoiler) => { | 
					
						
							| 
									
										
										
										
											2023-05-12 13:50:37 +02:00
										 |  |  | 	const button = spoiler.querySelector(".button"); | 
					
						
							| 
									
										
										
										
											2023-05-11 17:46:32 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-12 13:50:37 +02:00
										 |  |  | 	return () => { | 
					
						
							|  |  |  | 		button.textContent = spoiler.open | 
					
						
							|  |  |  | 			? "Show less" | 
					
						
							|  |  |  | 			: "Show more"; | 
					
						
							|  |  |  | 	}; | 
					
						
							| 
									
										
										
										
											2023-05-11 17:46:32 +02:00
										 |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-12 13:50:37 +02:00
										 |  |  | dynamicSpoiler("media-spoiler", (spoiler) => { | 
					
						
							| 
									
										
										
										
											2023-05-11 17:46:32 +02:00
										 |  |  | 	const eye = spoiler.querySelector(".eye.button"); | 
					
						
							| 
									
										
										
										
											2023-05-12 13:50:37 +02:00
										 |  |  | 	const video = spoiler.querySelector(".plyr-video"); | 
					
						
							| 
									
										
										
										
											2024-08-08 10:12:16 +02:00
										 |  |  | 	const loopingAuto = !reduceMotion.matches && video != null && video.classList.contains("gifv"); | 
					
						
							| 
									
										
										
										
											2023-05-11 17:46:32 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-12 13:50:37 +02:00
										 |  |  | 	return () => { | 
					
						
							|  |  |  | 		if (spoiler.open) { | 
					
						
							|  |  |  | 			eye.setAttribute("aria-label", "Hide media"); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			eye.setAttribute("aria-label", "Show media"); | 
					
						
							| 
									
										
										
										
											2024-08-08 10:12:16 +02:00
										 |  |  | 			if (video && !loopingAuto) { | 
					
						
							| 
									
										
										
										
											2023-05-11 17:46:32 +02:00
										 |  |  | 				video.pause(); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2023-05-12 13:50:37 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	}; | 
					
						
							| 
									
										
										
										
											2023-05-11 17:46:32 +02:00
										 |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Array.from(document.getElementsByClassName("plyr-video")).forEach((video) => { | 
					
						
							| 
									
										
										
										
											2024-08-08 10:12:16 +02:00
										 |  |  | 	const loopingAuto = !reduceMotion.matches && video.classList.contains("gifv"); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if (loopingAuto) { | 
					
						
							|  |  |  | 		// If we're able to play this as a
 | 
					
						
							|  |  |  | 		// looping gifv, then do so, else fall
 | 
					
						
							|  |  |  | 		// back to user-controllable video player.
 | 
					
						
							|  |  |  | 		video.draggable = false; | 
					
						
							|  |  |  | 		video.autoplay = true; | 
					
						
							|  |  |  | 		video.loop = true; | 
					
						
							|  |  |  | 		video.classList.remove("photoswipe-slide"); | 
					
						
							|  |  |  | 		video.classList.remove("plry-video"); | 
					
						
							|  |  |  | 		video.load(); | 
					
						
							|  |  |  | 		video.play(); | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2023-05-11 17:46:32 +02:00
										 |  |  | 	let player = new Plyr(video, { | 
					
						
							|  |  |  | 		title: video.title, | 
					
						
							|  |  |  | 		settings: ["loop"], | 
					
						
							|  |  |  | 		disableContextMenu: false, | 
					
						
							|  |  |  | 		hideControls: false, | 
					
						
							|  |  |  | 		tooltips: { contrors: true, seek: true }, | 
					
						
							|  |  |  | 		iconUrl: "/assets/plyr.svg", | 
					
						
							|  |  |  | 		listeners: { | 
					
						
							|  |  |  | 			fullscreen: () => { | 
					
						
							|  |  |  | 				if (player.playing) { | 
					
						
							|  |  |  | 					setTimeout(() => { | 
					
						
							|  |  |  | 						player.play(); | 
					
						
							|  |  |  | 					}, 1); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				lightbox.loadAndOpen(parseInt(video.dataset.pswpIndex), { | 
					
						
							|  |  |  | 					gallery: video.closest(".photoswipe-gallery") | 
					
						
							|  |  |  | 				}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				return false; | 
					
						
							| 
									
										
										
										
											2022-06-09 12:51:19 +02:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2023-05-11 17:46:32 +02:00
										 |  |  | 	}); | 
					
						
							| 
									
										
										
										
											2022-12-17 05:38:56 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-11 17:46:32 +02:00
										 |  |  | 	player.elements.container.title = video.title; | 
					
						
							|  |  |  | 	video._player = player; | 
					
						
							|  |  |  | 	video._plyrContainer = player.elements.container; | 
					
						
							| 
									
										
										
										
											2022-06-09 12:51:19 +02:00
										 |  |  | }); | 
					
						
							| 
									
										
										
										
											2025-03-01 18:41:32 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-02 11:27:30 +01:00
										 |  |  | Array.from(document.getElementsByTagName('time')).forEach(timeTag => { | 
					
						
							|  |  |  | 	const datetime = timeTag.getAttribute('datetime'); | 
					
						
							|  |  |  | 	const currentText = timeTag.textContent.trim(); | 
					
						
							|  |  |  | 	// Only format if current text contains precise time.
 | 
					
						
							|  |  |  | 	if (currentText.match(/\d{2}:\d{2}/)) { | 
					
						
							|  |  |  | 		const date = new Date(datetime); | 
					
						
							|  |  |  | 		timeTag.textContent = date.toLocaleString( | 
					
						
							|  |  |  | 			undefined, | 
					
						
							|  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2025-03-01 18:41:32 +08:00
										 |  |  | 				year: 'numeric', | 
					
						
							|  |  |  | 				month: 'short', | 
					
						
							|  |  |  | 				day: '2-digit', | 
					
						
							|  |  |  | 				hour: '2-digit', | 
					
						
							|  |  |  | 				minute: '2-digit', | 
					
						
							|  |  |  | 				hour12: false | 
					
						
							| 
									
										
										
										
											2025-03-02 11:27:30 +01:00
										 |  |  | 			}, | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-03-01 18:41:32 +08:00
										 |  |  | }); |