diff --git a/templates/_layout.html b/templates/_layout.html
index ed68412..7408d84 100644
--- a/templates/_layout.html
+++ b/templates/_layout.html
@@ -8,7 +8,7 @@
-
+
@@ -31,6 +31,7 @@
+
diff --git a/website/main.js b/website/main.js
index 90b7e19..9f603ea 100644
--- a/website/main.js
+++ b/website/main.js
@@ -36,6 +36,9 @@ function getPostItColorByDate(dateString) {
return postItColors[colorIndex];
}
+// Global variable to track last user-set volume (default to 1)
+let lastMediaVolume = 1;
+
function createPost(t) {
const post = document.createElement("div");
post.className = "post";
@@ -60,15 +63,38 @@ function createPost(t) {
link.target = "_blank";
link.style.textDecoration = "none";
- const embedHtml = t.embed.length > 0
- ? t.embed.map(img =>
- `
-
-
-
- `
- ).join("")
- : "";
+ // --- EMBED HTML (images and videos) ---
+ let embedHtml = "";
+ if (t.embed && t.embed.length > 0) {
+ embedHtml = t.embed.map((embed, idx) => {
+ if (embed.type === "image") {
+ // Image embed
+ return `
+
+
+
+ `;
+ } else if (embed.type === "video") {
+ // Video embed
+ // Use a data attribute for m3u8 playlist, set src only if not m3u8
+ const isM3u8 = embed.playlist && embed.playlist.endsWith('.m3u8');
+ return `
+
+ `;
+ }
+ // ...other embed types can be handled here...
+ return "";
+ }).join("");
+ }
const textHtml = t.text.replace(/\n/g, "
");
@@ -102,12 +128,57 @@ function createPost(t) {
createShadowbox(post, img);
});
});
+
+ // --- HLS.js video support for .m3u8 ---
+ const videos = post.querySelectorAll('video[data-hls-src],video.video-embed');
+ videos.forEach(video => {
+ // Set initial volume to lastMediaVolume
+ video.volume = lastMediaVolume;
+
+ // Prevent drag-selection when interacting with video controls (esp. volume)
+ video.addEventListener('mousedown', function (e) {
+ // Only prevent drag if the event is on the controls bar (not the video area)
+ // This is a best-effort: always prevent drag for any mousedown on video controls
+ e.stopPropagation();
+ });
+
+ // Listen for volume changes and sync to all players
+ video.addEventListener('volumechange', function () {
+ if (!isNaN(video.volume)) {
+ lastMediaVolume = video.volume;
+ // Sync all other videos on the page
+ document.querySelectorAll('video.video-embed').forEach(v => {
+ if (v !== video && Math.abs(v.volume - lastMediaVolume) > 0.01) {
+ v.volume = lastMediaVolume;
+ }
+ });
+ }
+ });
+ });
+
+ // HLS.js setup for m3u8
+ const hlsVideos = post.querySelectorAll('video[data-hls-src]');
+ if (hlsVideos.length > 0 && window.Hls) {
+ hlsVideos.forEach(video => {
+ const src = video.getAttribute('data-hls-src');
+ if (video.canPlayType('application/vnd.apple.mpegurl')) {
+ video.src = src;
+ } else if (window.Hls.isSupported()) {
+ const hls = new window.Hls();
+ hls.loadSource(src);
+ hls.attachMedia(video);
+ } else {
+ video.outerHTML = '