06eca4a6f93e0b26202ed8beeb968485537ed577

Author
TheEdgeOfClaw <openclaw@theedgeofrage.com>
Committer
GitHub <noreply@github.com>
Date

Message

Fix iOS PWA video downloads (#2)

Diff

This diff is truncated to protect this page.

  1diff --git a/assets/index.js b/assets/index.js
  2index c62e9896555855b717a39aa1fe7ee2f1f0de6099..aed890cdaf123fb44a475a9614133521bd10639e 100644
  3--- a/assets/index.js
  4+++ b/assets/index.js
  5@@ -2,6 +2,14 @@ document.addEventListener("DOMContentLoaded", function() {
  6 	const searchInput = document.getElementById("video-search");
  7 	if (!searchInput) return;
  8 
  9+	document.querySelectorAll('button[data-url]').forEach(function(btn) {
 10+		btn.addEventListener('click', function() {
 11+			const url = this.dataset.url;
 12+			const filename = this.dataset.filename;
 13+			downloadVideo(url, filename);
 14+		});
 15+	});
 16+
 17 	function performSearch() {
 18 		const videoCards = Array.from(document.querySelectorAll(".video-card"));
 19 		const query = searchInput.value.trim();
 20@@ -73,3 +81,20 @@ if ("serviceWorker" in navigator) {
 21 		console.log("Service Worker registration failed:", error);
 22 	});
 23 }
 24+
 25+function downloadVideo(url, filename) {
 26+	const xhr = new XMLHttpRequest();
 27+	xhr.open("GET", url, true);
 28+	xhr.responseType = "blob";
 29+	xhr.onload = function () {
 30+		if (this.status === 200) {
 31+			const blob = this.response;
 32+			const link = document.createElement("a");
 33+			link.href = window.URL.createObjectURL(blob);
 34+			link.download = filename;
 35+			link.click();
 36+			window.URL.revokeObjectURL(link.href);
 37+		}
 38+	};
 39+	xhr.send();
 40+}
 41diff --git a/pages/new_videos.templ b/pages/new_videos.templ
 42index 3b29b1d7500f5dd533edbe1ee472f3778232183a..438644480aba067f868b5fa721d7dd3a99816831 100644
 43--- a/pages/new_videos.templ
 44+++ b/pages/new_videos.templ
 45@@ -89,13 +89,14 @@ templ VideoCard(video models.Video) {
 46 					</form>
 47 					<div class="d-flex gap-2">
 48 						if video.IsDownloaded() {
 49-							<a
 50-								href={ templ.SafeURL(fmt.Sprintf("/videos/%s/file", video.ID)) }
 51+							<button
 52+								type="button"
 53 								class="btn btn-success"
 54-								download
 55+								data-url={ templ.SafeURL(fmt.Sprintf("/videos/%s/file", video.ID)) }
 56+								data-filename={ templ.SafeURL(video.Title + ".mp4") }
 57 							>
 58 								<i class="bi bi-download"></i>
 59-							</a>
 60+							</button>
 61 						} else if video.IsDownloading() {
 62 							<button
 63 								class="btn btn-primary"
 64diff --git a/pages/new_videos_templ.go b/pages/new_videos_templ.go
 65index a9bb2c5a258fe5ea3301032915cd667a178c98de..9877f02faa5663c91cacb52285cf3e90e2347f9f 100644
 66--- a/pages/new_videos_templ.go
 67+++ b/pages/new_videos_templ.go
 68@@ -363,105 +363,118 @@ func VideoCard(video models.Video) templ.Component {
 69 			return templ_7745c5c3_Err
 70 		}
 71 		if video.IsDownloaded() {
 72-			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "<a href=\"")
 73+			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "<button type=\"button\" class=\"btn btn-success\" data-url=\"")
 74 			if templ_7745c5c3_Err != nil {
 75 				return templ_7745c5c3_Err
 76 			}
 77-			var templ_7745c5c3_Var21 templ.SafeURL
 78-			templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("/videos/%s/file", video.ID)))
 79+			var templ_7745c5c3_Var21 string
 80+			templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(templ.SafeURL(fmt.Sprintf("/videos/%s/file", video.ID)))
 81 			if templ_7745c5c3_Err != nil {
 82-				return templ.Error{Err: templ_7745c5c3_Err, FileName: `pages/new_videos.templ`, Line: 93, Col: 70}
 83+				return templ.Error{Err: templ_7745c5c3_Err, FileName: `pages/new_videos.templ`, Line: 95, Col: 74}
 84 			}
 85 			_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21))
 86 			if templ_7745c5c3_Err != nil {
 87 				return templ_7745c5c3_Err
 88 			}
 89-			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "\" class=\"btn btn-success\" download><i class=\"bi bi-download\"></i></a> ")
 90-			if templ_7745c5c3_Err != nil {
 91-				return templ_7745c5c3_Err
 92-			}
 93-		} else if video.IsDownloading() {
 94-			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "<button class=\"btn btn-primary\" disabled hx-get=\"")
 95+			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "\" data-filename=\"")
 96 			if templ_7745c5c3_Err != nil {
 97 				return templ_7745c5c3_Err
 98 			}
 99 			var templ_7745c5c3_Var22 string
100-			templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("/videos/%s/card", video.ID))
101+			templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(templ.SafeURL(video.Title + ".mp4"))
102 			if templ_7745c5c3_Err != nil {
103-				return templ.Error{Err: templ_7745c5c3_Err, FileName: `pages/new_videos.templ`, Line: 103, Col: 57}
104+				return templ.Error{Err: templ_7745c5c3_Err, FileName: `pages/new_videos.templ`, Line: 96, Col: 59}
105 			}
106 			_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22))
107 			if templ_7745c5c3_Err != nil {
108 				return templ_7745c5c3_Err
109 			}