Spaces:
Sleeping
Sleeping
Add new session button
Browse files
app.py
CHANGED
|
@@ -643,9 +643,14 @@ INDEX_HTML = r"""<!DOCTYPE html>
|
|
| 643 |
.job-actions { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
|
| 644 |
.job-action-btn { padding: 8px 12px; background: var(--surface); border: 1px solid var(--border); border-radius: 8px; color: var(--ink); font-family: 'DM Sans', sans-serif; font-size: 0.78rem; cursor: pointer; }
|
| 645 |
.job-action-btn:hover { background: var(--champagne); }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 646 |
.log-panel { display:none; margin-top:24px; background:var(--ink); color:var(--cream); border-radius:12px; padding:14px; font:12px/1.45 ui-monospace, SFMono-Regular, Consolas, monospace; white-space:pre-wrap; max-height:240px; overflow:auto; text-align:left; }
|
| 647 |
.log-panel.open { display:block; }
|
| 648 |
-
@media (max-width: 600px) { nav { padding: 16px 20px; } .input-card { padding: 24px 20px; } #screen-processing { padding: 32px 16px 60px; } .pipeline { padding: 20px 16px; } .job-status-card { flex-direction: column; align-items: stretch; } .job-actions { justify-content: flex-start; } .clips-grid { grid-template-columns: repeat(2, 1fr); gap: 10px; } .regen-section { padding: 22px 18px; } .regen-btn { width: 100%; margin-left: 0; } .regen-row { flex-direction: column; align-items: flex-start; } }
|
| 649 |
.thumb-1 { background: linear-gradient(135deg, #D4A96A 0%, #8B5E3C 100%); } .thumb-2 { background: linear-gradient(135deg, #7A9E8A 0%, #3D6650 100%); }
|
| 650 |
.thumb-3 { background: linear-gradient(135deg, #9E8A7A 0%, #5C3E2E 100%); } .thumb-4 { background: linear-gradient(135deg, #8A7A9E 0%, #4A3866 100%); }
|
| 651 |
.thumb-5 { background: linear-gradient(135deg, #9E9A7A 0%, #5C5820 100%); } .thumb-6 { background: linear-gradient(135deg, #C4856A 0%, #7A3020 100%); }
|
|
@@ -658,7 +663,10 @@ INDEX_HTML = r"""<!DOCTYPE html>
|
|
| 658 |
<body>
|
| 659 |
<nav>
|
| 660 |
<div class="logo">Clip<span>Forge</span></div>
|
| 661 |
-
<div
|
|
|
|
|
|
|
|
|
|
| 662 |
</nav>
|
| 663 |
<div class="screen active" id="screen-input">
|
| 664 |
<div style="display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:calc(100vh - 65px);padding:40px 20px;text-align:center;">
|
|
@@ -764,6 +772,53 @@ INDEX_HTML = r"""<!DOCTYPE html>
|
|
| 764 |
document.getElementById('nav-status').style.display = 'block';
|
| 765 |
}
|
| 766 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 767 |
function setPollStatus(text) {
|
| 768 |
document.getElementById('poll-status-label').textContent = text;
|
| 769 |
}
|
|
@@ -857,6 +912,7 @@ INDEX_HTML = r"""<!DOCTYPE html>
|
|
| 857 |
}
|
| 858 |
btn.disabled = true;
|
| 859 |
btn.textContent = 'Starting...';
|
|
|
|
| 860 |
const job = await createJob();
|
| 861 |
rememberJob(job.id);
|
| 862 |
renderedClips = [];
|
|
@@ -911,6 +967,7 @@ INDEX_HTML = r"""<!DOCTYPE html>
|
|
| 911 |
if (!job || !job.id) return;
|
| 912 |
document.getElementById('job-id-label').textContent = `Job ${job.id}`;
|
| 913 |
document.getElementById('nav-status').textContent = job.nav_status || 'Processing...';
|
|
|
|
| 914 |
document.getElementById('processing-sub').textContent = job.error ? job.error : job.status;
|
| 915 |
document.getElementById('log-panel').textContent = job.logs || '';
|
| 916 |
(job.steps || []).forEach((step, i) => {
|
|
@@ -1055,6 +1112,7 @@ INDEX_HTML = r"""<!DOCTYPE html>
|
|
| 1055 |
document.getElementById('clips-section').style.display = 'none';
|
| 1056 |
document.getElementById('regen-section').style.display = 'none';
|
| 1057 |
document.getElementById('nav-status').textContent = 'Regenerating...';
|
|
|
|
| 1058 |
document.querySelectorAll('.pipeline-step').forEach((s, i) => {
|
| 1059 |
s.classList.remove('active', 'done');
|
| 1060 |
s.querySelector('.step-icon').innerHTML = iconLabels[i];
|
|
|
|
| 643 |
.job-actions { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
|
| 644 |
.job-action-btn { padding: 8px 12px; background: var(--surface); border: 1px solid var(--border); border-radius: 8px; color: var(--ink); font-family: 'DM Sans', sans-serif; font-size: 0.78rem; cursor: pointer; }
|
| 645 |
.job-action-btn:hover { background: var(--champagne); }
|
| 646 |
+
.nav-right { display:flex; flex-direction:column; align-items:flex-end; gap:6px; }
|
| 647 |
+
.nav-status { font-size:0.8rem; color:var(--ink-muted); font-weight:300; display:none; }
|
| 648 |
+
.nav-new-session { display:none; padding:7px 12px; background:var(--surface); border:1px solid var(--border); border-radius:8px; color:var(--ink); font-family:'DM Sans', sans-serif; font-size:0.76rem; cursor:pointer; transition:all 0.15s; }
|
| 649 |
+
.nav-new-session:hover { background:var(--champagne); border-color:var(--gold); }
|
| 650 |
+
.nav-new-session.show { display:inline-flex; }
|
| 651 |
.log-panel { display:none; margin-top:24px; background:var(--ink); color:var(--cream); border-radius:12px; padding:14px; font:12px/1.45 ui-monospace, SFMono-Regular, Consolas, monospace; white-space:pre-wrap; max-height:240px; overflow:auto; text-align:left; }
|
| 652 |
.log-panel.open { display:block; }
|
| 653 |
+
@media (max-width: 600px) { nav { padding: 16px 20px; } .input-card { padding: 24px 20px; } #screen-processing { padding: 32px 16px 60px; } .pipeline { padding: 20px 16px; } .job-status-card { flex-direction: column; align-items: stretch; } .job-actions { justify-content: flex-start; } .clips-grid { grid-template-columns: repeat(2, 1fr); gap: 10px; } .regen-section { padding: 22px 18px; } .regen-btn { width: 100%; margin-left: 0; } .regen-row { flex-direction: column; align-items: flex-start; } .nav-new-session { padding:7px 10px; } }
|
| 654 |
.thumb-1 { background: linear-gradient(135deg, #D4A96A 0%, #8B5E3C 100%); } .thumb-2 { background: linear-gradient(135deg, #7A9E8A 0%, #3D6650 100%); }
|
| 655 |
.thumb-3 { background: linear-gradient(135deg, #9E8A7A 0%, #5C3E2E 100%); } .thumb-4 { background: linear-gradient(135deg, #8A7A9E 0%, #4A3866 100%); }
|
| 656 |
.thumb-5 { background: linear-gradient(135deg, #9E9A7A 0%, #5C5820 100%); } .thumb-6 { background: linear-gradient(135deg, #C4856A 0%, #7A3020 100%); }
|
|
|
|
| 663 |
<body>
|
| 664 |
<nav>
|
| 665 |
<div class="logo">Clip<span>Forge</span></div>
|
| 666 |
+
<div class="nav-right">
|
| 667 |
+
<div class="nav-status" id="nav-status">Processing...</div>
|
| 668 |
+
<button class="nav-new-session" id="new-session-btn" type="button" onclick="startNewSession()">New session</button>
|
| 669 |
+
</div>
|
| 670 |
</nav>
|
| 671 |
<div class="screen active" id="screen-input">
|
| 672 |
<div style="display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:calc(100vh - 65px);padding:40px 20px;text-align:center;">
|
|
|
|
| 772 |
document.getElementById('nav-status').style.display = 'block';
|
| 773 |
}
|
| 774 |
|
| 775 |
+
function resetPipelineUi() {
|
| 776 |
+
document.querySelectorAll('.pipeline-step').forEach((s, i) => {
|
| 777 |
+
s.classList.remove('active', 'done');
|
| 778 |
+
s.querySelector('.step-icon').innerHTML = iconLabels[i];
|
| 779 |
+
document.getElementById(`fill-${i}`).style.width = '0%';
|
| 780 |
+
document.getElementById(`pct-${i}`).textContent = i === 0 ? '0%' : '';
|
| 781 |
+
});
|
| 782 |
+
}
|
| 783 |
+
|
| 784 |
+
function resetUploadUi() {
|
| 785 |
+
document.getElementById('upload-zone').innerHTML = '<div class="upload-icon">File</div><div class="upload-text">Click to browse or drag & drop</div><div class="upload-sub">MP4, MOV, AVI - up to your Space limit</div>';
|
| 786 |
+
}
|
| 787 |
+
|
| 788 |
+
function startNewSession() {
|
| 789 |
+
pollToken += 1;
|
| 790 |
+
currentJobId = null;
|
| 791 |
+
renderedClips = [];
|
| 792 |
+
selectedFile = null;
|
| 793 |
+
autoStartAfterFilePick = false;
|
| 794 |
+
pollFailures = 0;
|
| 795 |
+
lastJobSnapshot = null;
|
| 796 |
+
try { localStorage.removeItem(JOB_STORAGE_KEY); } catch (_) {}
|
| 797 |
+
|
| 798 |
+
document.getElementById('screen-processing').classList.remove('active');
|
| 799 |
+
document.getElementById('screen-input').classList.add('active');
|
| 800 |
+
document.getElementById('nav-status').textContent = 'Processing...';
|
| 801 |
+
document.getElementById('nav-status').style.display = 'none';
|
| 802 |
+
document.getElementById('new-session-btn').classList.remove('show');
|
| 803 |
+
document.getElementById('job-id-label').textContent = 'Job pending';
|
| 804 |
+
setPollStatus('Waiting for updates');
|
| 805 |
+
document.getElementById('processing-sub').textContent = 'Sit back - long videos can take a little while';
|
| 806 |
+
document.getElementById('log-panel').textContent = '';
|
| 807 |
+
document.getElementById('log-panel').classList.remove('open');
|
| 808 |
+
document.getElementById('clips-grid').innerHTML = '';
|
| 809 |
+
document.getElementById('clips-section').style.display = 'none';
|
| 810 |
+
document.getElementById('clips-sub-text').textContent = 'Tap any clip to preview';
|
| 811 |
+
document.getElementById('regen-section').style.display = 'none';
|
| 812 |
+
document.getElementById('regen-prompt').value = '';
|
| 813 |
+
document.getElementById('file-input').value = '';
|
| 814 |
+
document.getElementById('yt-url').value = '';
|
| 815 |
+
document.getElementById('convert-btn').disabled = false;
|
| 816 |
+
document.getElementById('convert-btn').textContent = 'Convert to Clips ->';
|
| 817 |
+
resetUploadUi();
|
| 818 |
+
resetPipelineUi();
|
| 819 |
+
window.scrollTo({ top: 0, behavior: 'smooth' });
|
| 820 |
+
}
|
| 821 |
+
|
| 822 |
function setPollStatus(text) {
|
| 823 |
document.getElementById('poll-status-label').textContent = text;
|
| 824 |
}
|
|
|
|
| 912 |
}
|
| 913 |
btn.disabled = true;
|
| 914 |
btn.textContent = 'Starting...';
|
| 915 |
+
document.getElementById('new-session-btn').classList.remove('show');
|
| 916 |
const job = await createJob();
|
| 917 |
rememberJob(job.id);
|
| 918 |
renderedClips = [];
|
|
|
|
| 967 |
if (!job || !job.id) return;
|
| 968 |
document.getElementById('job-id-label').textContent = `Job ${job.id}`;
|
| 969 |
document.getElementById('nav-status').textContent = job.nav_status || 'Processing...';
|
| 970 |
+
document.getElementById('new-session-btn').classList.toggle('show', Boolean(job.done));
|
| 971 |
document.getElementById('processing-sub').textContent = job.error ? job.error : job.status;
|
| 972 |
document.getElementById('log-panel').textContent = job.logs || '';
|
| 973 |
(job.steps || []).forEach((step, i) => {
|
|
|
|
| 1112 |
document.getElementById('clips-section').style.display = 'none';
|
| 1113 |
document.getElementById('regen-section').style.display = 'none';
|
| 1114 |
document.getElementById('nav-status').textContent = 'Regenerating...';
|
| 1115 |
+
document.getElementById('new-session-btn').classList.remove('show');
|
| 1116 |
document.querySelectorAll('.pipeline-step').forEach((s, i) => {
|
| 1117 |
s.classList.remove('active', 'done');
|
| 1118 |
s.querySelector('.step-icon').innerHTML = iconLabels[i];
|