saq1b commited on
Commit
9341db6
·
verified ·
1 Parent(s): 219b88e

Upload index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +82 -19
templates/index.html CHANGED
@@ -111,19 +111,20 @@
111
  availableVideos.forEach((video) => {
112
  const card = document.createElement("div");
113
  card.className = "bg-white p-4 rounded shadow flex flex-col justify-between";
114
-
115
- // Create a container that enforces a 9:16 aspect ratio
116
  const videoContainer = document.createElement("div");
117
  videoContainer.className = "relative w-full rounded overflow-hidden";
118
  videoContainer.style.aspectRatio = "9 / 16";
119
-
120
- // Create the video element for preview
121
  const previewVideo = document.createElement("video");
122
  previewVideo.className = "absolute top-0 left-0 w-full h-full object-cover";
123
  previewVideo.muted = true;
124
  previewVideo.loop = true;
125
  previewVideo.playsInline = true;
126
  previewVideo.autoplay = true;
 
127
  if (video.preview_video) {
128
  previewVideo.src = video.preview_video;
129
  } else {
@@ -132,19 +133,27 @@
132
  }
133
  videoContainer.appendChild(previewVideo);
134
  card.appendChild(videoContainer);
135
-
136
  // Title
137
  const title = document.createElement("h3");
138
  title.className = "mt-2 font-semibold";
139
  title.textContent = video.title;
140
  card.appendChild(title);
141
-
142
- // Info
143
  const info = document.createElement("p");
144
  info.className = "text-sm text-gray-600";
145
  info.textContent = `Subreddit: ${video.subreddit} | Upvotes: ${video.ups}`;
146
  card.appendChild(info);
147
-
 
 
 
 
 
 
 
 
148
  // Checkbox for selection
149
  const checkbox = document.createElement("input");
150
  checkbox.type = "checkbox";
@@ -178,14 +187,28 @@
178
  });
179
  const data = await res.json();
180
  console.log(data);
 
 
181
  });
182
 
183
- // Poll for processing results every 5 seconds
184
- setInterval(async () => {
185
- const res = await fetch("/api/results");
186
- const results = await res.json();
187
- renderResults(results);
188
- }, 5000);
 
 
 
 
 
 
 
 
 
 
 
 
189
 
190
  function renderResults(results) {
191
  resultsList.innerHTML = "";
@@ -193,15 +216,28 @@
193
  const result = results[id];
194
  const container = document.createElement("div");
195
  container.className = "bg-white p-4 rounded shadow";
 
196
  const header = document.createElement("div");
197
  header.className = "flex justify-between items-center";
198
  const title = document.createElement("h3");
199
  title.className = "font-semibold text-lg";
200
  title.textContent = result.generated_title || "Processing...";
201
  header.appendChild(title);
 
 
 
 
 
 
 
 
 
 
 
202
  container.appendChild(header);
 
203
  if (result.status === "completed") {
204
- // Limit the display size of the processed video.
205
  const videoContainer = document.createElement("div");
206
  videoContainer.className = "max-w-md mx-auto mt-2";
207
  const videoElem = document.createElement("video");
@@ -209,9 +245,15 @@
209
  videoElem.controls = true;
210
  videoElem.className = "w-full";
211
  videoElem.style.maxHeight = "500px";
 
 
 
 
 
 
212
  videoContainer.appendChild(videoElem);
213
  container.appendChild(videoContainer);
214
-
215
  // Caption with a copy button
216
  const captionDiv = document.createElement("div");
217
  captionDiv.className = "mt-2 flex items-center";
@@ -238,11 +280,32 @@
238
  pendingMsg.className = "text-gray-600 mt-2";
239
  container.appendChild(pendingMsg);
240
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
241
  resultsList.appendChild(container);
242
  }
243
  }
244
 
245
- // Settings Modal
246
  openSettings.addEventListener("click", async () => {
247
  const res = await fetch("/api/settings");
248
  const settings = await res.json();
@@ -270,9 +333,9 @@
270
  });
271
 
272
  // Connect to the logs WebSocket for live console output
273
- const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
274
  const logsSocket = new WebSocket(`${protocol}//${location.host}/ws/logs`);
275
- logsSocket.onmessage = function(event) {
276
  const newLog = document.createElement("div");
277
  newLog.textContent = event.data;
278
  consoleOutput.appendChild(newLog);
 
111
  availableVideos.forEach((video) => {
112
  const card = document.createElement("div");
113
  card.className = "bg-white p-4 rounded shadow flex flex-col justify-between";
114
+
115
+ // Container with enforced 9:16 aspect ratio
116
  const videoContainer = document.createElement("div");
117
  videoContainer.className = "relative w-full rounded overflow-hidden";
118
  videoContainer.style.aspectRatio = "9 / 16";
119
+
120
+ // Video element for preview (with controls)
121
  const previewVideo = document.createElement("video");
122
  previewVideo.className = "absolute top-0 left-0 w-full h-full object-cover";
123
  previewVideo.muted = true;
124
  previewVideo.loop = true;
125
  previewVideo.playsInline = true;
126
  previewVideo.autoplay = true;
127
+ previewVideo.controls = true; // <-- now shows native video controls
128
  if (video.preview_video) {
129
  previewVideo.src = video.preview_video;
130
  } else {
 
133
  }
134
  videoContainer.appendChild(previewVideo);
135
  card.appendChild(videoContainer);
136
+
137
  // Title
138
  const title = document.createElement("h3");
139
  title.className = "mt-2 font-semibold";
140
  title.textContent = video.title;
141
  card.appendChild(title);
142
+
143
+ // Info (Subreddit and Upvotes)
144
  const info = document.createElement("p");
145
  info.className = "text-sm text-gray-600";
146
  info.textContent = `Subreddit: ${video.subreddit} | Upvotes: ${video.ups}`;
147
  card.appendChild(info);
148
+
149
+ // Display Duration if available
150
+ if (video.duration) {
151
+ const durationText = document.createElement("p");
152
+ durationText.className = "text-sm text-gray-600";
153
+ durationText.textContent = `Duration: ${video.duration} sec`;
154
+ card.appendChild(durationText);
155
+ }
156
+
157
  // Checkbox for selection
158
  const checkbox = document.createElement("input");
159
  checkbox.type = "checkbox";
 
187
  });
188
  const data = await res.json();
189
  console.log(data);
190
+ // Restart polling for processing results whenever processing begins.
191
+ startResultsPolling();
192
  });
193
 
194
+ // Function to poll for processing results
195
+ let pollingInterval;
196
+ function startResultsPolling() {
197
+ // Clear any previous interval if exists
198
+ if (pollingInterval) clearInterval(pollingInterval);
199
+ pollingInterval = setInterval(async () => {
200
+ const res = await fetch("/api/results");
201
+ const results = await res.json();
202
+ renderResults(results);
203
+ // TASK 1: Stop polling if there are no pending videos
204
+ const pendingExists = Object.values(results).some(
205
+ (r) => r.status === "pending"
206
+ );
207
+ if (!pendingExists && Object.keys(results).length > 0) {
208
+ clearInterval(pollingInterval);
209
+ }
210
+ }, 5000);
211
+ }
212
 
213
  function renderResults(results) {
214
  resultsList.innerHTML = "";
 
216
  const result = results[id];
217
  const container = document.createElement("div");
218
  container.className = "bg-white p-4 rounded shadow";
219
+
220
  const header = document.createElement("div");
221
  header.className = "flex justify-between items-center";
222
  const title = document.createElement("h3");
223
  title.className = "font-semibold text-lg";
224
  title.textContent = result.generated_title || "Processing...";
225
  header.appendChild(title);
226
+
227
+ // TASK 5: Add a "Copy Title" button
228
+ if (result.generated_title) {
229
+ const titleCopyBtn = document.createElement("button");
230
+ titleCopyBtn.textContent = "Copy Title";
231
+ titleCopyBtn.className = "bg-blue-500 text-white px-2 py-1 rounded ml-2";
232
+ titleCopyBtn.addEventListener("click", () => {
233
+ navigator.clipboard.writeText(result.generated_title);
234
+ });
235
+ header.appendChild(titleCopyBtn);
236
+ }
237
  container.appendChild(header);
238
+
239
  if (result.status === "completed") {
240
+ // Processed video display
241
  const videoContainer = document.createElement("div");
242
  videoContainer.className = "max-w-md mx-auto mt-2";
243
  const videoElem = document.createElement("video");
 
245
  videoElem.controls = true;
246
  videoElem.className = "w-full";
247
  videoElem.style.maxHeight = "500px";
248
+
249
+ // TASK 6: Make the video element draggable.
250
+ videoElem.setAttribute("draggable", "true");
251
+ videoElem.addEventListener("dragstart", (e) => {
252
+ e.dataTransfer.setData("text/uri-list", result.video_url);
253
+ });
254
  videoContainer.appendChild(videoElem);
255
  container.appendChild(videoContainer);
256
+
257
  // Caption with a copy button
258
  const captionDiv = document.createElement("div");
259
  captionDiv.className = "mt-2 flex items-center";
 
280
  pendingMsg.className = "text-gray-600 mt-2";
281
  container.appendChild(pendingMsg);
282
  }
283
+
284
+ // TASK 2: Add a "Delete Video" button to allow removal of processed videos.
285
+ if (result.status === "completed") {
286
+ const deleteBtn = document.createElement("button");
287
+ deleteBtn.textContent = "Delete Video";
288
+ deleteBtn.className = "bg-red-500 text-white px-2 py-1 rounded mt-2";
289
+ deleteBtn.addEventListener("click", async () => {
290
+ if (confirm("Are you sure you want to delete this video?")) {
291
+ const res = await fetch(`/api/video/${id}`, {
292
+ method: "DELETE",
293
+ });
294
+ if (res.ok) {
295
+ container.remove();
296
+ } else {
297
+ alert("Failed to delete video.");
298
+ }
299
+ }
300
+ });
301
+ container.appendChild(deleteBtn);
302
+ }
303
+
304
  resultsList.appendChild(container);
305
  }
306
  }
307
 
308
+ // Settings Modal handlers
309
  openSettings.addEventListener("click", async () => {
310
  const res = await fetch("/api/settings");
311
  const settings = await res.json();
 
333
  });
334
 
335
  // Connect to the logs WebSocket for live console output
336
+ const protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
337
  const logsSocket = new WebSocket(`${protocol}//${location.host}/ws/logs`);
338
+ logsSocket.onmessage = function (event) {
339
  const newLog = document.createElement("div");
340
  newLog.textContent = event.data;
341
  consoleOutput.appendChild(newLog);