apolinario commited on
Commit
21ee9d9
·
1 Parent(s): 889687b

more UI change

Browse files
Files changed (1) hide show
  1. index.html +97 -9
index.html CHANGED
@@ -305,6 +305,20 @@
305
  color: #78716c;
306
  }
307
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
308
  .status-bar {
309
  display: flex;
310
  justify-content: space-between;
@@ -332,6 +346,11 @@
332
  color: #991b1b;
333
  }
334
 
 
 
 
 
 
335
  .mode-toggle {
336
  display: flex;
337
  gap: 10px;
@@ -719,6 +738,7 @@
719
  <h2>Generated Video</h2>
720
  <div class="video-container">
721
  <canvas id="outputCanvas"></canvas>
 
722
  <div id="placeholder" class="placeholder">
723
  <p>Configure settings and click Start</p>
724
  </div>
@@ -728,6 +748,12 @@
728
  <div>
729
  <span id="statusPill" class="status-pill status-disconnected">Disconnected</span>
730
  <span style="margin-left: 15px;">Frames: <strong id="frameCount">0</strong> / <strong id="maxFrames">234</strong></span>
 
 
 
 
 
 
731
  </div>
732
  <div>
733
  <label style="display: inline; margin: 0;">Playback:</label>
@@ -756,7 +782,6 @@
756
  <button id="startStopBtn" class="btn btn-primary" onclick="app.toggleGeneration()" style="flex: 1;">
757
  Start Generation
758
  </button>
759
- <button class="btn btn-secondary" onclick="app.downloadVideo()">Download</button>
760
  </div>
761
 
762
  <!-- Advanced Settings Accordion -->
@@ -1165,6 +1190,7 @@
1165
  maxFrames: 234,
1166
  ws: null,
1167
  frameBuffer: [],
 
1168
  playbackInterval: null,
1169
  frameExtractionInterval: null,
1170
  webcamStream: null,
@@ -1174,6 +1200,7 @@
1174
  recordedChunks: [],
1175
  promptUpdateTimer: null,
1176
  pendingPromptUpdate: null,
 
1177
 
1178
  init() {
1179
  this.setupEventListeners();
@@ -1383,10 +1410,18 @@
1383
 
1384
  this.isGenerating = true;
1385
  this.frameCount = 0;
 
1386
  document.getElementById('frameCount').textContent = '0';
1387
  this.frameBuffer = [];
 
1388
  this.updateUI();
1389
 
 
 
 
 
 
 
1390
  // Start recording
1391
  this.startRecording();
1392
 
@@ -1462,11 +1497,14 @@
1462
  btn.disabled = !auth.canStart;
1463
  }
1464
 
1465
- // Update status
1466
- const statusPill = document.getElementById('statusPill');
1467
- if (statusPill) {
1468
- statusPill.className = 'status-pill status-disconnected';
1469
- statusPill.textContent = 'Disconnected';
 
 
 
1470
  }
1471
 
1472
  // Re-enable mode buttons
@@ -1474,8 +1512,6 @@
1474
  const btn = document.getElementById(id);
1475
  if (btn) btn.disabled = false;
1476
  });
1477
-
1478
- this.showInfo(`Disconnected: ${event.reason || 'Generation complete'}`);
1479
  };
1480
 
1481
  } catch (error) {
@@ -1554,11 +1590,12 @@
1554
  const bitmap = await createImageBitmap(blob);
1555
 
1556
  this.frameBuffer.push(bitmap);
 
1557
  this.frameCount++;
1558
  document.getElementById('frameCount').textContent = this.frameCount;
1559
 
1560
  if (this.frameCount === 1) {
1561
- document.getElementById('placeholder').style.display = 'none';
1562
  this.startPlaybackLoop();
1563
  }
1564
 
@@ -1569,9 +1606,22 @@
1569
  // Check if generation is complete
1570
  if (this.frameCount >= this.maxFrames) {
1571
  this.isGenerating = false;
 
1572
  this.stopFrameExtraction();
1573
  this.stopRecording();
1574
  this.updateUI();
 
 
 
 
 
 
 
 
 
 
 
 
1575
  this.showInfo('Generation complete!');
1576
  }
1577
  },
@@ -1867,9 +1917,47 @@
1867
  this.stopFrameExtraction();
1868
  this.stopRecording();
1869
  this.isGenerating = false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1870
  this.updateUI();
1871
  },
1872
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1873
  downloadVideo() {
1874
  if (this.recordedChunks.length === 0) {
1875
  this.showError('No video data to download');
 
305
  color: #78716c;
306
  }
307
 
308
+ .spinner {
309
+ width: 50px;
310
+ height: 50px;
311
+ border: 4px solid #e7e5e4;
312
+ border-top: 4px solid #f59e0b;
313
+ border-radius: 50%;
314
+ animation: spin 1s linear infinite;
315
+ }
316
+
317
+ @keyframes spin {
318
+ 0% { transform: rotate(0deg); }
319
+ 100% { transform: rotate(360deg); }
320
+ }
321
+
322
  .status-bar {
323
  display: flex;
324
  justify-content: space-between;
 
346
  color: #991b1b;
347
  }
348
 
349
+ .status-finished {
350
+ background: #dbeafe;
351
+ color: #1e40af;
352
+ }
353
+
354
  .mode-toggle {
355
  display: flex;
356
  gap: 10px;
 
738
  <h2>Generated Video</h2>
739
  <div class="video-container">
740
  <canvas id="outputCanvas"></canvas>
741
+ <div id="spinner" class="spinner hidden"></div>
742
  <div id="placeholder" class="placeholder">
743
  <p>Configure settings and click Start</p>
744
  </div>
 
748
  <div>
749
  <span id="statusPill" class="status-pill status-disconnected">Disconnected</span>
750
  <span style="margin-left: 15px;">Frames: <strong id="frameCount">0</strong> / <strong id="maxFrames">234</strong></span>
751
+ <button id="replayBtn" class="btn btn-secondary hidden" onclick="app.replayVideo()" style="margin-left: 15px; padding: 4px 12px; font-size: 0.75rem;">
752
+ Replay
753
+ </button>
754
+ <button id="downloadBtn" class="btn btn-secondary hidden" onclick="app.downloadVideo()" style="margin-left: 10px; padding: 4px 12px; font-size: 0.75rem;">
755
+ Download
756
+ </button>
757
  </div>
758
  <div>
759
  <label style="display: inline; margin: 0;">Playback:</label>
 
782
  <button id="startStopBtn" class="btn btn-primary" onclick="app.toggleGeneration()" style="flex: 1;">
783
  Start Generation
784
  </button>
 
785
  </div>
786
 
787
  <!-- Advanced Settings Accordion -->
 
1190
  maxFrames: 234,
1191
  ws: null,
1192
  frameBuffer: [],
1193
+ allFrames: [], // Store all frames for replay
1194
  playbackInterval: null,
1195
  frameExtractionInterval: null,
1196
  webcamStream: null,
 
1200
  recordedChunks: [],
1201
  promptUpdateTimer: null,
1202
  pendingPromptUpdate: null,
1203
+ generationFinished: false,
1204
 
1205
  init() {
1206
  this.setupEventListeners();
 
1410
 
1411
  this.isGenerating = true;
1412
  this.frameCount = 0;
1413
+ this.generationFinished = false;
1414
  document.getElementById('frameCount').textContent = '0';
1415
  this.frameBuffer = [];
1416
+ this.allFrames = [];
1417
  this.updateUI();
1418
 
1419
+ // Show spinner, hide placeholder, replay and download buttons
1420
+ document.getElementById('spinner').classList.remove('hidden');
1421
+ document.getElementById('placeholder').style.display = 'none';
1422
+ document.getElementById('replayBtn').classList.add('hidden');
1423
+ document.getElementById('downloadBtn').classList.add('hidden');
1424
+
1425
  // Start recording
1426
  this.startRecording();
1427
 
 
1497
  btn.disabled = !auth.canStart;
1498
  }
1499
 
1500
+ // Update status - only if not already finished
1501
+ if (!this.generationFinished) {
1502
+ const statusPill = document.getElementById('statusPill');
1503
+ if (statusPill) {
1504
+ statusPill.className = 'status-pill status-disconnected';
1505
+ statusPill.textContent = 'Disconnected';
1506
+ }
1507
+ this.showInfo(`Disconnected: ${event.reason || 'Connection closed'}`);
1508
  }
1509
 
1510
  // Re-enable mode buttons
 
1512
  const btn = document.getElementById(id);
1513
  if (btn) btn.disabled = false;
1514
  });
 
 
1515
  };
1516
 
1517
  } catch (error) {
 
1590
  const bitmap = await createImageBitmap(blob);
1591
 
1592
  this.frameBuffer.push(bitmap);
1593
+ this.allFrames.push(imageData); // Store raw data for replay
1594
  this.frameCount++;
1595
  document.getElementById('frameCount').textContent = this.frameCount;
1596
 
1597
  if (this.frameCount === 1) {
1598
+ document.getElementById('spinner').classList.add('hidden');
1599
  this.startPlaybackLoop();
1600
  }
1601
 
 
1606
  // Check if generation is complete
1607
  if (this.frameCount >= this.maxFrames) {
1608
  this.isGenerating = false;
1609
+ this.generationFinished = true;
1610
  this.stopFrameExtraction();
1611
  this.stopRecording();
1612
  this.updateUI();
1613
+
1614
+ // Update status to Finished
1615
+ const statusPill = document.getElementById('statusPill');
1616
+ statusPill.className = 'status-pill status-finished';
1617
+ statusPill.textContent = 'Finished';
1618
+
1619
+ // Show replay and download buttons
1620
+ document.getElementById('replayBtn').classList.remove('hidden');
1621
+ if (this.recordedChunks.length > 0) {
1622
+ document.getElementById('downloadBtn').classList.remove('hidden');
1623
+ }
1624
+
1625
  this.showInfo('Generation complete!');
1626
  }
1627
  },
 
1917
  this.stopFrameExtraction();
1918
  this.stopRecording();
1919
  this.isGenerating = false;
1920
+
1921
+ // Hide spinner, show placeholder if no frames
1922
+ document.getElementById('spinner').classList.add('hidden');
1923
+ if (this.frameCount === 0) {
1924
+ document.getElementById('placeholder').style.display = 'flex';
1925
+ }
1926
+
1927
+ // Update status pill - only show "Disconnected" if manually stopped or error
1928
+ if (!this.generationFinished) {
1929
+ const statusPill = document.getElementById('statusPill');
1930
+ if (statusPill) {
1931
+ statusPill.className = 'status-pill status-disconnected';
1932
+ statusPill.textContent = 'Disconnected';
1933
+ }
1934
+ }
1935
+
1936
  this.updateUI();
1937
  },
1938
 
1939
+ async replayVideo() {
1940
+ if (this.allFrames.length === 0) {
1941
+ this.showError('No frames to replay');
1942
+ return;
1943
+ }
1944
+
1945
+ // Stop current playback
1946
+ this.stopPlaybackLoop();
1947
+
1948
+ // Recreate frameBuffer from stored frames
1949
+ this.frameBuffer = [];
1950
+ for (const imageData of this.allFrames) {
1951
+ const blob = new Blob([imageData], { type: 'image/jpeg' });
1952
+ const bitmap = await createImageBitmap(blob);
1953
+ this.frameBuffer.push(bitmap);
1954
+ }
1955
+
1956
+ // Restart playback
1957
+ this.startPlaybackLoop();
1958
+ this.showInfo('Replaying video');
1959
+ },
1960
+
1961
  downloadVideo() {
1962
  if (this.recordedChunks.length === 0) {
1963
  this.showError('No video data to download');