Spaces:
Running
Running
Luigi
commited on
Update index.html
Browse files- index.html +282 -430
index.html
CHANGED
@@ -2,276 +2,130 @@
|
|
2 |
<html lang="en">
|
3 |
<head>
|
4 |
<meta charset="UTF-8">
|
5 |
-
<meta name="viewport" content="width=device-width, initial-scale=1.0,
|
6 |
-
<title>Autotutorial.ai -
|
7 |
-
<link rel="manifest" href="manifest.json">
|
8 |
-
<meta name="apple-mobile-web-app-capable" content="yes">
|
9 |
-
<meta name="apple-mobile-web-app-status-bar-style" content="
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
<!-- Font Awesome CDN -->
|
15 |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" integrity="sha512-9usAa10IRO0HhonpyAIVpjrylPvoDwiPUiKdWk5t3PyolY1cOd4DSE0Ga+ri4AuTroPR5aQvXU9xC6qOPnzFeg==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
16 |
-
|
|
|
17 |
<link rel="preconnect" href="https://fonts.googleapis.com">
|
18 |
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
19 |
-
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&
|
20 |
|
21 |
<style>
|
22 |
-
|
23 |
-
|
24 |
-
font-family: 'Inter', sans-serif; /* Default to Inter, fallback if SF Pro Display doesn't load perfectly */
|
25 |
-
-webkit-font-smoothing: antialiased;
|
26 |
-
-moz-osx-font-smoothing: grayscale;
|
27 |
-
background-color: var(--gray-100); /* Lighter iOS-like background */
|
28 |
-
color: var(--gray-900);
|
29 |
-
margin: 0; /* Reset margins */
|
30 |
-
padding-bottom: 50px; /* Padding for bottom tab bar */
|
31 |
}
|
32 |
-
|
33 |
-
|
34 |
-
@font-face {
|
35 |
-
font-family: 'SF Pro Display'; /* Name to use in CSS */
|
36 |
-
src: url('https://cdn.jsdelivr.net/gh/fontsource/fontsource-sf-pro-display@latest/files/sf-pro-display-latin-400-normal.woff2') format('woff2'), /* Example CDN - consider hosting or local */
|
37 |
-
url('https://cdn.jsdelivr.net/gh/fontsource/fontsource-sf-pro-display@latest/files/sf-pro-display-latin-400-normal.woff') format('woff');
|
38 |
-
/* Add other weights as needed */
|
39 |
-
font-weight: 400;
|
40 |
-
font-style: normal;
|
41 |
-
font-display: swap; /* or optional */
|
42 |
}
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
.app-container {
|
48 |
-
max-width: 768px; /* Mobile-first max width */
|
49 |
-
margin: 0 auto; /* Center on larger screens */
|
50 |
-
background-color: var(--gray-50); /* Even lighter background, closer to iOS */
|
51 |
-
border-radius: 0px; /* No border radius for full-screen app feel */
|
52 |
overflow: hidden;
|
53 |
-
box-shadow:
|
54 |
-
|
55 |
-
display: flex;
|
56 |
-
flex-direction: column; /* Vertical flex layout */
|
57 |
-
}
|
58 |
-
|
59 |
-
header {
|
60 |
-
background-color: var(--gray-50); /* White header background */
|
61 |
-
padding: 2rem 1.5rem 1rem 1.5rem; /* Adjusted header padding - less top, more bottom */
|
62 |
-
color: var(--gray-900);
|
63 |
-
border-bottom: 1px solid var(--gray-200); /* iOS-style separator */
|
64 |
-
}
|
65 |
-
|
66 |
-
header h1 {
|
67 |
-
font-size: 2.25rem; /* Large iOS title size */
|
68 |
-
font-weight: 700;
|
69 |
-
letter-spacing: -0.02em;
|
70 |
-
margin-bottom: 0.25rem; /* Reduced bottom margin */
|
71 |
-
text-align: left; /* Left-align iOS style */
|
72 |
-
}
|
73 |
-
|
74 |
-
header p {
|
75 |
-
font-size: 1.1rem; /* Slightly smaller subtitle */
|
76 |
-
color: var(--gray-600); /* Muted subtitle color */
|
77 |
-
font-weight: 400;
|
78 |
}
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
section {
|
86 |
-
margin-bottom: 2rem; /* Reduced section margin */
|
87 |
-
}
|
88 |
-
|
89 |
-
section h2 {
|
90 |
-
font-size: 1.7rem; /* Section title size */
|
91 |
font-weight: 600;
|
92 |
-
|
93 |
-
margin-bottom: 1.25rem; /* Reduced section title margin */
|
94 |
-
letter-spacing: -0.015em;
|
95 |
-
text-align: left; /* Left-align section titles */
|
96 |
-
}
|
97 |
-
|
98 |
-
section h3 {
|
99 |
-
font-size: 1.3rem; /* Subtitle size */
|
100 |
-
font-weight: 500;
|
101 |
-
color: var(--gray-700);
|
102 |
-
margin-bottom: 0.8rem; /* Reduced subtitle margin */
|
103 |
-
letter-spacing: -0.01em;
|
104 |
-
text-align: left; /* Left-align subtitles */
|
105 |
-
}
|
106 |
-
|
107 |
-
.input-label { @apply block text-gray-700 text-sm font-semibold mb-1; } /* Smaller label margin */
|
108 |
-
.status-box { @apply border rounded-md p-4 mb-3 bg-gray-50 border-gray-200 relative overflow-hidden; } /* Reduced status box margin */
|
109 |
-
.error-text { @apply text-red-500 mt-1 text-sm; } /* Smaller error text margin */
|
110 |
-
.video-player-container { @apply rounded-md overflow-hidden shadow-md; } /* Keep shadow for video player */
|
111 |
-
.video-overlay-title { position: absolute; bottom: 15px; left: 15px; color: white; font-size: 1.5rem; font-weight: 600; text-shadow: 1px 1px 2px rgba(0,0,0,0.6); } /* Smaller video overlay title */
|
112 |
-
|
113 |
-
footer {
|
114 |
-
background-color: var(--gray-50); /* White footer */
|
115 |
-
border-top: 1px solid var(--gray-200); /* iOS footer separator */
|
116 |
-
padding: 1.25rem 1.5rem; /* Reduced footer padding */
|
117 |
-
text-center text-gray-500 text-sm;
|
118 |
}
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
.tutorial-item p { @apply text-gray-600 text-sm; }
|
126 |
-
.tutorial-list-section { display: flex; flex-direction: column; gap: 0.75rem; } /* Vertical tutorial list */
|
127 |
-
.settings-grid { display: grid; grid-template-columns: 1fr; gap: 1.75rem; } /* Single column settings on mobile */
|
128 |
-
@media (min-width: 768px) { /* Medium screens and up */
|
129 |
-
.settings-grid { grid-template-columns: 1fr 1fr; } /* Two-column settings on larger screens */
|
130 |
-
}
|
131 |
-
.help-section p { line-height: 1.6; margin-bottom: 1rem; }
|
132 |
-
|
133 |
-
/* Radix UI Button Styling - iOS Style Refinements */
|
134 |
-
.radix-button {
|
135 |
-
@apply inline-flex items-center justify-center rounded-md px-4 py-2 font-semibold text-sm focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 transition-colors duration-200; /* Reduced button padding */
|
136 |
-
-webkit-tap-highlight-color: transparent; /* Remove tap highlight on iOS */
|
137 |
-
}
|
138 |
-
.radix-button-primary { @apply radix-button bg-indigo-600 hover:bg-indigo-700 active:bg-indigo-800 text-white shadow-sm hover:shadow-md; }
|
139 |
-
.radix-button-primary:disabled { @apply bg-indigo-300 cursor-not-allowed hover:bg-indigo-300 focus:ring-0 shadow-none; }
|
140 |
-
.radix-button-secondary { @apply radix-button bg-gray-200 hover:bg-gray-300 active:bg-gray-400 text-gray-700 shadow-sm hover:shadow-md; }
|
141 |
-
.radix-button-apply { @apply radix-button bg-green-500 hover:bg-green-600 active:bg-green-700 text-white shadow-sm hover:shadow-md; }
|
142 |
-
|
143 |
-
/* Radix UI Input Styling - iOS Style Refinements */
|
144 |
-
.radix-input {
|
145 |
-
@apply appearance-none border rounded-md w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:ring-2 focus:ring-indigo-500 transition-shadow duration-200; /* Reduced input padding */
|
146 |
-
border-color: var(--gray-300);
|
147 |
-
background-color: var(--gray-50); /* Light gray input background */
|
148 |
-
color: var(--gray-900);
|
149 |
-
box-shadow: inset 0 0 0 1px var(--gray-300); /* iOS-like border shadow */
|
150 |
-
}
|
151 |
-
.radix-input:focus { @apply shadow-none border-indigo-500; box-shadow: inset 0 0 0 2px var(--indigo-500); } /* iOS-like focus */
|
152 |
-
|
153 |
-
/* Radix UI Select Styling - iOS Style - Needs more JS for true iOS Picker */
|
154 |
-
.radix-select-trigger {
|
155 |
-
@apply radix-button radix-button-secondary w-full justify-between;
|
156 |
-
border-radius: 8px; /* More rounded select */
|
157 |
-
padding-left: 1rem; padding-right: 1rem; /* Adjust select padding */
|
158 |
}
|
159 |
-
.
|
160 |
-
|
161 |
}
|
162 |
-
.radix-select-item {
|
163 |
-
@apply px-3.5 py-2 text-sm text-gray-700 cursor-pointer hover:bg-gray-100 focus:outline-none focus:bg-gray-100;
|
164 |
-
}
|
165 |
-
.radix-select-item[data-highlighted] { @apply bg-indigo-50 text-indigo-900; }
|
166 |
-
|
167 |
-
/* Progress Bar - iOS Style - Thinner */
|
168 |
-
.status-progress-bar { position: absolute; bottom: 0; left: 0; right: 0; height: 3px; background-color: var(--indigo-500); transform-origin: 0% 0%; transform: scaleX(0); transition: transform 0.4s ease-out; }
|
169 |
-
.status-progress-bar.active { transform: scaleX(1); }
|
170 |
-
|
171 |
-
/* Transitions */
|
172 |
-
.transition-opacity { transition-property: opacity; transition-timing-function: ease-out; transition-duration: 200ms; }
|
173 |
-
|
174 |
-
/* Bottom Tab Bar Navigation - iOS Style */
|
175 |
-
.bottom-tab-bar {
|
176 |
-
position: fixed; bottom: 0; left: 0; right: 0;
|
177 |
-
background-color: var(--gray-50); /* White tab bar background */
|
178 |
-
border-top: 1px solid var(--gray-200); /* iOS tab bar border */
|
179 |
-
padding-top: 0.5rem; padding-bottom: calc(env(safe-area-inset-bottom) + 0.5rem); /* Safe area padding for iOS */
|
180 |
-
display: flex; justify-content: space-around;
|
181 |
-
z-index: 100; /* Ensure it's on top */
|
182 |
-
}
|
183 |
-
|
184 |
-
.bottom-tab-button {
|
185 |
-
display: flex; flex-direction: column; align-items: center;
|
186 |
-
color: var(--gray-500); /* Inactive tab color */
|
187 |
-
text-decoration: none;
|
188 |
-
font-size: 0.85rem; /* Smaller tab label */
|
189 |
-
padding: 0.5rem 1rem; border-radius: 8px; /* Tab button padding and rounded corners */
|
190 |
-
-webkit-tap-highlight-color: transparent; /* Remove tap highlight on iOS */
|
191 |
-
}
|
192 |
-
|
193 |
-
.bottom-tab-button.active, .bottom-tab-button:active, .bottom-tab-button:hover {
|
194 |
-
color: var(--indigo-600); /* Active/tapped tab color */
|
195 |
-
background-color: var(--gray-100); /* Slightly highlight active tab */
|
196 |
-
}
|
197 |
-
|
198 |
-
.bottom-tab-icon {
|
199 |
-
font-size: 1.3rem; /* Tab icon size */
|
200 |
-
margin-bottom: 0.25rem;
|
201 |
-
}
|
202 |
-
|
203 |
-
/* Scrollbar - minimal for mobile */
|
204 |
-
::-webkit-scrollbar { width: 4px; height: 4px; }
|
205 |
-
::-webkit-scrollbar-track { background: transparent; } /* Transparent track */
|
206 |
-
::-webkit-scrollbar-thumb { background: var(--gray-400); border-radius: 2px; } /* Thinner, lighter thumb */
|
207 |
-
::-webkit-scrollbar-thumb:hover { background: var(--gray-500); }
|
208 |
-
* { scrollbar-width: thin; scrollbar-color: var(--gray-400) transparent; } /* Firefox scrollbar */
|
209 |
-
|
210 |
-
|
211 |
</style>
|
212 |
</head>
|
213 |
-
<body
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
<
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
<
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
<
|
234 |
-
<
|
235 |
-
|
236 |
-
<
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
255 |
</div>
|
256 |
-
<p class="text-sm text-gray-500 mt-2">For enhanced AI features.</p>
|
257 |
-
</section>
|
258 |
|
259 |
-
|
260 |
-
|
261 |
-
<button id="resetButton" class="radix-button-secondary hidden"><i class="fas fa-redo mr-2"></i> Reset</button>
|
262 |
-
</section>
|
263 |
|
264 |
-
|
265 |
-
|
|
|
|
|
|
|
266 |
<div id="statusMessages">
|
267 |
-
<p class="text-
|
268 |
</div>
|
269 |
-
<p id="errorMessage" class="
|
270 |
-
<
|
271 |
-
</
|
272 |
-
|
273 |
-
|
274 |
-
|
|
|
|
|
|
|
|
|
275 |
<div class="video-player-container">
|
276 |
<video id="tutorialVideo" controls width="100%">
|
277 |
<source src="https://joy.videvo.net/videvo_files/video/free/2016-06/small_watermarked/Drone_Flying_Above_City_Skyline_preview.mp4" type="video/mp4">
|
@@ -279,160 +133,175 @@
|
|
279 |
</video>
|
280 |
<div id="videoTitleOverlay" class="video-overlay-title"></div>
|
281 |
</div>
|
282 |
-
<div
|
283 |
<div>
|
284 |
-
<p
|
|
|
285 |
</div>
|
286 |
-
<
|
287 |
-
<a href="#" id="downloadButton" class="radix-button-primary" download="tutorial.mp4"><i class="fas fa-download mr-2"></i> Download</a>
|
288 |
-
</div>
|
289 |
-
</div>
|
290 |
-
</section>
|
291 |
-
</section>
|
292 |
-
|
293 |
-
<!-- Tutorial History Section -->
|
294 |
-
<section id="history-section" class="hidden">
|
295 |
-
<h2 class="text-xl">History</h2>
|
296 |
-
<p class="text-gray-700 mb-6">Past tutorials.</p>
|
297 |
-
|
298 |
-
<div class="tutorial-list-section">
|
299 |
-
<div class="tutorial-item history-item" data-video-title="Mastering JavaScript Promises">
|
300 |
-
<h3>JavaScript Promises</h3>
|
301 |
-
<p>Oct 26, 2023</p>
|
302 |
-
</div>
|
303 |
-
<div class="tutorial-item history-item" data-video-title="Introduction to Python for Data Science">
|
304 |
-
<h3>Python for Data Science</h3>
|
305 |
-
<p>Oct 25, 2023</p>
|
306 |
</div>
|
307 |
-
|
308 |
-
|
309 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
310 |
</div>
|
311 |
-
|
312 |
-
|
313 |
-
</
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
<
|
321 |
-
<
|
322 |
-
<label for="defaultDurationSetting" class="input-label">Default Duration</label>
|
323 |
-
<select id="defaultDurationSetting" class="radix-select-trigger">
|
324 |
-
<option value="5" class="radix-select-item">5 Minutes</option>
|
325 |
-
<option value="10" selected class="radix-select-item">10 Minutes</option>
|
326 |
-
<option value="15" class="radix-select-item">15 Minutes</option>
|
327 |
-
</select>
|
328 |
-
</div>
|
329 |
-
<div>
|
330 |
-
<label for="videoQualitySetting" class="input-label">Video Quality</label>
|
331 |
-
<select id="videoQualitySetting" class="radix-select-trigger">
|
332 |
-
<option value="720p" selected class="radix-select-item">720p HD</option>
|
333 |
-
<option value="1080p" class="radix-select-item">1080p Full HD</option>
|
334 |
-
<option value="4k" class="radix-select-item">4K Ultra HD (Premium)</option>
|
335 |
-
</select>
|
336 |
-
</div>
|
337 |
-
<div>
|
338 |
-
<label for="voiceoverLanguage" class="input-label">Voiceover Language</label>
|
339 |
-
<select id="voiceoverLanguage" class="radix-select-trigger">
|
340 |
-
<option value="en-US" selected class="radix-select-item">English (US)</option>
|
341 |
-
<option value="en-GB" class="radix-select-item">English (UK)</option>
|
342 |
-
<option value="es-ES" class="radix-select-item">Spanish</option>
|
343 |
-
<option value="fr-FR" class="radix-select-item">French</option>
|
344 |
-
</select>
|
345 |
-
</div>
|
346 |
-
<div>
|
347 |
-
<label for="outputFormat" class="input-label">Output Format</label>
|
348 |
-
<select id="outputFormat" class="radix-select-trigger">
|
349 |
-
<option value="mp4" selected class="radix-select-item">MP4 (Recommended)</option>
|
350 |
-
<option value="mov" class="radix-select-item">MOV</option>
|
351 |
-
<option value="webm" class="radix-select-item">WebM</option>
|
352 |
-
</select>
|
353 |
-
</div>
|
354 |
-
</div>
|
355 |
-
<div class="mt-4 flex justify-start">
|
356 |
-
<button id="applySettingsButton" class="radix-button-apply"><i class="fas fa-check mr-2"></i> Apply</button>
|
357 |
-
</div>
|
358 |
-
<p class="mt-3 text-sm text-gray-500">Demo settings.</p>
|
359 |
-
</section>
|
360 |
-
|
361 |
-
<!-- Help Section -->
|
362 |
-
<section id="help-section" class="hidden">
|
363 |
-
<h2 class="text-xl">Help</h2>
|
364 |
-
<p class="text-gray-700 mb-6">App guidance.</p>
|
365 |
-
|
366 |
-
<div class="help-section">
|
367 |
-
<p>Welcome to Autotutorial.ai! Generate videos easily.</p>
|
368 |
<p><strong>Getting Started:</strong></p>
|
369 |
-
<ol
|
370 |
-
<li>Go to "Generate" tab.</li>
|
371 |
-
<li>Enter tutorial topic.</li>
|
372 |
-
<li>Select duration.</li>
|
373 |
-
<li>(Optional) Add API keys.</li>
|
374 |
-
<li>Tap "Generate".</li>
|
375 |
-
<li>
|
376 |
-
<li>Preview in "Preview" section.</li>
|
377 |
</ol>
|
378 |
-
<p><strong>History:</strong></p>
|
379 |
-
<p>Access past tutorials in "History" (demo).</p>
|
380 |
<p><strong>Settings:</strong></p>
|
381 |
-
<p>Customize preferences in "Settings" (demo).</p>
|
382 |
-
<p>For
|
383 |
-
</
|
384 |
-
</
|
385 |
-
|
386 |
-
</
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
|
|
|
|
|
|
|
|
|
|
409 |
|
410 |
<script>
|
411 |
document.addEventListener('DOMContentLoaded', () => {
|
412 |
-
//
|
413 |
-
const tabButtons = document.querySelectorAll('.
|
414 |
-
const sections =
|
415 |
|
416 |
tabButtons.forEach(button => {
|
417 |
button.addEventListener('click', function(event) {
|
418 |
event.preventDefault();
|
419 |
-
const sectionId = this.getAttribute('data-section');
|
420 |
|
421 |
tabButtons.forEach(btn => btn.classList.remove('active'));
|
422 |
-
sections.forEach(sec => sec.classList.add('
|
423 |
|
424 |
this.classList.add('active');
|
425 |
-
document.getElementById(
|
426 |
-
if (sectionId === 'generate') {
|
427 |
-
document.getElementById('videoOutputSection').classList.add('
|
428 |
document.getElementById('videoOutputSection').classList.remove('opacity-0');
|
429 |
}
|
430 |
});
|
431 |
});
|
432 |
-
document.querySelector('.
|
433 |
-
|
434 |
|
435 |
-
|
|
|
436 |
const historyItems = document.querySelectorAll('.history-item');
|
437 |
const videoTitleSpan = document.getElementById('videoTitle');
|
438 |
const videoTitleOverlay = document.getElementById('videoTitleOverlay');
|
@@ -442,25 +311,24 @@
|
|
442 |
const title = this.getAttribute('data-video-title');
|
443 |
videoTitleSpan.textContent = title + " (Preview)";
|
444 |
videoTitleOverlay.textContent = title;
|
445 |
-
videoOutputSection.classList.remove('
|
446 |
videoOutputSection.classList.remove('opacity-0');
|
447 |
const statusMessagesDiv = document.getElementById('statusMessages');
|
448 |
-
statusMessagesDiv.innerHTML = `<p class="text-
|
449 |
statusMessagesDiv.scrollTop = statusMessagesDiv.scrollHeight;
|
450 |
});
|
451 |
});
|
452 |
|
453 |
-
// Apply Settings Button Simulation
|
454 |
document.getElementById('applySettingsButton').addEventListener('click', function() {
|
455 |
const statusMessagesDiv = document.getElementById('statusMessages');
|
456 |
-
statusMessagesDiv.innerHTML = `<p class="text-
|
457 |
statusMessagesDiv.scrollTop = statusMessagesDiv.scrollHeight;
|
458 |
});
|
459 |
});
|
460 |
|
461 |
|
462 |
document.getElementById('generateButton').addEventListener('click', function() {
|
463 |
-
// ... (same generateButton event listener logic as before) ...
|
464 |
const topic = document.getElementById('tutorialTopic').value;
|
465 |
const duration = document.getElementById('desiredDuration').value;
|
466 |
const openaiKey = document.getElementById('openaiApiKey').value;
|
@@ -477,16 +345,13 @@
|
|
477 |
|
478 |
// Reset status and hide video output
|
479 |
statusMessagesDiv.innerHTML = '';
|
480 |
-
errorMessageDiv.classList.add('
|
481 |
-
videoOutputSection.classList.add('
|
482 |
videoOutputSection.classList.remove('opacity-0');
|
483 |
-
resetButton.classList.
|
484 |
-
generateButton.
|
485 |
-
|
486 |
-
|
487 |
-
statusSection.querySelector('h3').innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i> Status';
|
488 |
-
progressBar.style.transform = 'scaleX(0)';
|
489 |
-
progressBar.classList.add('active');
|
490 |
|
491 |
|
492 |
const steps = [
|
@@ -504,24 +369,21 @@
|
|
504 |
function processStep() {
|
505 |
if (currentStepIndex < steps.length) {
|
506 |
simulateStep(statusMessagesDiv, steps[currentStepIndex].message, steps[currentStepIndex].delay, () => {
|
507 |
-
progressBar.
|
508 |
currentStepIndex++;
|
509 |
processStep();
|
510 |
}, true);
|
511 |
} else {
|
512 |
-
progressBar.
|
513 |
-
statusMessagesDiv.innerHTML = '<p class="text-
|
514 |
-
statusSection.querySelector('h3 i').classList.remove('fa-spinner', 'fa-spin', 'mr-2');
|
515 |
-
statusSection.querySelector('h3 i').classList.add('fa-check-circle', 'text-green-500', 'mr-2');
|
516 |
-
statusSection.querySelector('h3').innerHTML = '<i class="fas fa-check-circle text-green-500 mr-2"></i> Status';
|
517 |
|
518 |
videoTitleSpan.textContent = topic + " (" + duration + "min Preview)";
|
519 |
videoTitleOverlay.textContent = topic;
|
520 |
-
videoOutputSection.classList.remove('
|
521 |
setTimeout(() => videoOutputSection.classList.remove('opacity-0'), 50);
|
522 |
-
generateButton.
|
523 |
-
generateButton.classList.add('
|
524 |
-
resetButton.classList.remove('
|
525 |
}
|
526 |
}
|
527 |
processStep();
|
@@ -530,28 +392,21 @@
|
|
530 |
});
|
531 |
|
532 |
document.getElementById('resetButton').addEventListener('click', function() {
|
533 |
-
// ... (same resetButton event listener logic as before) ...
|
534 |
const statusMessagesDiv = document.getElementById('statusMessages');
|
535 |
const errorMessageDiv = document.getElementById('errorMessage');
|
536 |
const generateButton = document.getElementById('generateButton');
|
537 |
const resetButton = document.getElementById('resetButton');
|
538 |
-
const statusSection = document.getElementById('statusSection');
|
539 |
const videoOutputSection = document.getElementById('videoOutputSection');
|
540 |
const progressBar = document.getElementById('progressBar');
|
541 |
|
542 |
-
statusMessagesDiv.innerHTML = '<p class="text-
|
543 |
-
errorMessageDiv.classList.add('
|
544 |
-
videoOutputSection.classList.add('
|
545 |
videoOutputSection.classList.remove('opacity-0');
|
546 |
-
generateButton.
|
547 |
-
generateButton.classList.remove('
|
548 |
-
resetButton.classList.add('
|
549 |
-
|
550 |
-
statusSection.querySelector('h3 i').classList.add('fa-check-circle', 'text-green-500', 'mr-2');
|
551 |
-
statusSection.querySelector('h3').innerHTML = '<i class="fas fa-check-circle text-green-500 mr-2"></i> Status';
|
552 |
-
progressBar.classList.remove('active');
|
553 |
-
progressBar.style.transform = 'scaleX(0)';
|
554 |
-
|
555 |
});
|
556 |
|
557 |
|
@@ -559,20 +414,17 @@
|
|
559 |
setTimeout(function() {
|
560 |
const messageElement = document.createElement('p');
|
561 |
if (isSuccess) {
|
562 |
-
messageElement.classList.add('text-
|
563 |
-
messageElement.innerHTML = `<
|
564 |
} else {
|
565 |
-
messageElement.classList.add('text-
|
566 |
-
messageElement.innerHTML = `<
|
567 |
document.getElementById('errorMessage').textContent = "Error generating tutorial. Check API keys.";
|
568 |
-
document.getElementById('errorMessage').classList.remove('
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
document.getElementById('
|
573 |
-
document.getElementById('generateButton').classList.add('hidden');
|
574 |
-
document.getElementById('resetButton').classList.remove('hidden');
|
575 |
-
document.getElementById('progressBar').classList.remove('active');
|
576 |
}
|
577 |
statusDiv.appendChild(messageElement);
|
578 |
statusDiv.scrollTop = statusDiv.scrollHeight;
|
|
|
2 |
<html lang="en">
|
3 |
<head>
|
4 |
<meta charset="UTF-8">
|
5 |
+
<meta name="viewport" content="viewport-fit=cover, width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
6 |
+
<title>Autotutorial.ai - Ionic Demo</title>
|
7 |
+
<link rel="manifest" href="manifest.json">
|
8 |
+
<meta name="apple-mobile-web-app-capable" content="yes">
|
9 |
+
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
10 |
+
|
11 |
+
<!-- Ionic CSS -->
|
12 |
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ionic/core@latest/css/ionic.bundle.css">
|
13 |
+
|
14 |
<!-- Font Awesome CDN -->
|
15 |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" integrity="sha512-9usAa10IRO0HhonpyAIVpjrylPvoDwiPUiKdWk5t3PyolY1cOd4DSE0Ga+ri4AuTroPR5aQvXU9xC6qOPnzFeg==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
16 |
+
|
17 |
+
<!-- Inter Font from Google Fonts -->
|
18 |
<link rel="preconnect" href="https://fonts.googleapis.com">
|
19 |
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
20 |
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
21 |
|
22 |
<style>
|
23 |
+
:root {
|
24 |
+
--ion-font-family: 'Inter', sans-serif;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
}
|
26 |
+
body {
|
27 |
+
font-family: var(--ion-font-family);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
}
|
29 |
+
.video-player-container {
|
30 |
+
border-radius: 8px;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
31 |
overflow: hidden;
|
32 |
+
box-shadow: 0 2px 8px rgba(0,0,0,0.15);
|
33 |
+
position: relative; /* For video overlay */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
}
|
35 |
+
.video-overlay-title {
|
36 |
+
position: absolute;
|
37 |
+
bottom: 16px;
|
38 |
+
left: 16px;
|
39 |
+
color: white;
|
40 |
+
font-size: 1.5em;
|
|
|
|
|
|
|
|
|
|
|
|
|
41 |
font-weight: 600;
|
42 |
+
text-shadow: 1px 1px 2px rgba(0,0,0,0.8);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
43 |
}
|
44 |
+
.status-box {
|
45 |
+
border-radius: 8px;
|
46 |
+
border: 1px solid var(--ion-color-light);
|
47 |
+
background-color: var(--ion-color-light-contrast);
|
48 |
+
padding: 16px;
|
49 |
+
margin-bottom: 16px;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
}
|
51 |
+
.status-progress-bar {
|
52 |
+
margin-top: 8px;
|
53 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
54 |
</style>
|
55 |
</head>
|
56 |
+
<body>
|
57 |
+
|
58 |
+
<ion-app>
|
59 |
+
|
60 |
+
<ion-header translucent="true">
|
61 |
+
<ion-toolbar>
|
62 |
+
<ion-title>Autotutorial.ai</ion-title>
|
63 |
+
</ion-toolbar>
|
64 |
+
</ion-header>
|
65 |
+
|
66 |
+
<ion-content fullscreen="true">
|
67 |
+
|
68 |
+
<ion-card>
|
69 |
+
<ion-card-header>
|
70 |
+
<ion-card-title>Generate Tutorial</ion-card-title>
|
71 |
+
<ion-card-subtitle>Create a new video tutorial</ion-card-subtitle>
|
72 |
+
</ion-card-header>
|
73 |
+
|
74 |
+
<ion-card-content>
|
75 |
+
|
76 |
+
<ion-list lines="full">
|
77 |
+
<ion-item>
|
78 |
+
<ion-label position="floating">Tutorial Topic</ion-label>
|
79 |
+
<ion-input type="text" id="tutorialTopic" value="React State Management Best Practices"></ion-input>
|
80 |
+
</ion-item>
|
81 |
+
|
82 |
+
<ion-item>
|
83 |
+
<ion-label>Desired Duration</ion-label>
|
84 |
+
<ion-select value="10" id="desiredDuration">
|
85 |
+
<ion-select-option value="5">5 Minutes</ion-select-option>
|
86 |
+
<ion-select-option value="10">10 Minutes</ion-select-option>
|
87 |
+
<ion-select-option value="15">15 Minutes</ion-select-option>
|
88 |
+
<ion-select-option value="20">20 Minutes</ion-select-option>
|
89 |
+
</ion-select>
|
90 |
+
</ion-item>
|
91 |
+
|
92 |
+
<ion-item>
|
93 |
+
<ion-label position="floating">OpenAI API Key (Optional)</ion-label>
|
94 |
+
<ion-input type="text" id="openaiApiKey" value="sk-DEMO_OPENAI_KEY" placeholder="For enhanced script generation"></ion-input>
|
95 |
+
</ion-item>
|
96 |
+
|
97 |
+
<ion-item>
|
98 |
+
<ion-label position="floating">Video Generation API Key (Optional)</ion-label>
|
99 |
+
<ion-input type="text" id="videoGenApiKey" value="vg-DEMO_VIDEO_GEN_KEY" placeholder="For advanced video synthesis"></ion-input>
|
100 |
+
</ion-item>
|
101 |
+
</ion-list>
|
102 |
+
|
103 |
+
<div style="margin-top: 20px; display: flex; gap: 10px;">
|
104 |
+
<ion-button id="generateButton" expand="block"><ion-icon slot="start" icon="magic"></ion-icon>Generate Tutorial</ion-button>
|
105 |
+
<ion-button id="resetButton" expand="block" color="secondary" class="ion-hide"><ion-icon slot="start" icon="refresh"></ion-icon>Reset</ion-button>
|
106 |
</div>
|
|
|
|
|
107 |
|
108 |
+
</ion-card-content>
|
109 |
+
</ion-card>
|
|
|
|
|
110 |
|
111 |
+
<ion-card id="statusSection" class="status-box">
|
112 |
+
<ion-card-header>
|
113 |
+
<ion-card-title><ion-icon icon="information-circle" style="margin-right: 8px;"></ion-icon>Status Updates</ion-card-title>
|
114 |
+
</ion-card-header>
|
115 |
+
<ion-card-content>
|
116 |
<div id="statusMessages">
|
117 |
+
<p class="ion-text-color-secondary"><ion-icon icon="checkmark-circle" color="success" style="margin-right: 4px;"></ion-icon>Ready to generate. Click "Generate Tutorial".</p>
|
118 |
</div>
|
119 |
+
<p id="errorMessage" class="ion-text-color-danger ion-hide" style="margin-top: 8px;"></p>
|
120 |
+
<ion-progress-bar value="0" buffer="0" reversed="false" class="status-progress-bar" id="progressBar"></ion-progress-bar>
|
121 |
+
</ion-card-content>
|
122 |
+
</ion-card>
|
123 |
+
|
124 |
+
<ion-card id="videoOutputSection" class="ion-hide">
|
125 |
+
<ion-card-header>
|
126 |
+
<ion-card-title><ion-icon icon="film" style="margin-right: 8px;"></ion-icon>Tutorial Preview</ion-card-title>
|
127 |
+
</ion-card-header>
|
128 |
+
<ion-card-content>
|
129 |
<div class="video-player-container">
|
130 |
<video id="tutorialVideo" controls width="100%">
|
131 |
<source src="https://joy.videvo.net/videvo_files/video/free/2016-06/small_watermarked/Drone_Flying_Above_City_Skyline_preview.mp4" type="video/mp4">
|
|
|
133 |
</video>
|
134 |
<div id="videoTitleOverlay" class="video-overlay-title"></div>
|
135 |
</div>
|
136 |
+
<div style="margin-top: 16px; display: flex; justify-content: space-between; align-items: center;">
|
137 |
<div>
|
138 |
+
<p><strong id="videoTitle"></strong></p>
|
139 |
+
<ion-text color="secondary"><p>Generated tutorial preview</p></ion-text>
|
140 |
</div>
|
141 |
+
<ion-button id="downloadButton" download="tutorial.mp4"><ion-icon slot="start" icon="download"></ion-icon>Download</ion-button>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
142 |
</div>
|
143 |
+
</ion-card-content>
|
144 |
+
</ion-card>
|
145 |
+
|
146 |
+
<ion-card id="history-section" class="ion-hide">
|
147 |
+
<ion-card-header>
|
148 |
+
<ion-card-title><ion-icon icon="time" style="margin-right: 8px;"></ion-icon>Tutorial History</ion-card-title>
|
149 |
+
<ion-card-subtitle>Access past tutorials</ion-card-subtitle>
|
150 |
+
</ion-card-header>
|
151 |
+
<ion-card-content>
|
152 |
+
<ion-list id="historyList">
|
153 |
+
<ion-item button class="history-item" data-video-title="Mastering JavaScript Promises">
|
154 |
+
<ion-label>
|
155 |
+
<h3>Mastering JavaScript Promises</h3>
|
156 |
+
<p>Generated: Oct 26, 2023</p>
|
157 |
+
</ion-label>
|
158 |
+
</ion-item>
|
159 |
+
<ion-item button class="history-item" data-video-title="Introduction to Python for Data Science">
|
160 |
+
<ion-label>
|
161 |
+
<h3>Introduction to Python for Data Science</h3>
|
162 |
+
<p>Generated: Oct 25, 2023</p>
|
163 |
+
</ion-label>
|
164 |
+
</ion-item>
|
165 |
+
<ion-item button class="history-item" data-video-title="Building a REST API with Express.js">
|
166 |
+
<ion-label>
|
167 |
+
<h3>Building a REST API with Express.js</h3>
|
168 |
+
<p>Generated: Oct 20, 2023</p>
|
169 |
+
</ion-label>
|
170 |
+
</ion-item>
|
171 |
+
</ion-list>
|
172 |
+
<ion-text color="secondary"><p style="margin-top: 16px;">Demo history is simulated.</p></ion-text>
|
173 |
+
</ion-card-content>
|
174 |
+
</ion-card>
|
175 |
+
|
176 |
+
<ion-card id="settings-section" class="ion-hide">
|
177 |
+
<ion-card-header>
|
178 |
+
<ion-card-title><ion-icon icon="settings" style="margin-right: 8px;"></ion-icon>Settings</ion-card-title>
|
179 |
+
<ion-card-subtitle>Customize preferences</ion-card-subtitle>
|
180 |
+
</ion-card-header>
|
181 |
+
<ion-card-content>
|
182 |
+
<ion-list lines="full">
|
183 |
+
<ion-item>
|
184 |
+
<ion-label>Default Duration</ion-label>
|
185 |
+
<ion-select value="10" id="defaultDurationSetting">
|
186 |
+
<ion-select-option value="5">5 Minutes</ion-select-option>
|
187 |
+
<ion-select-option value="10">10 Minutes</ion-select-option>
|
188 |
+
<ion-select-option value="15">15 Minutes</ion-select-option>
|
189 |
+
</ion-select>
|
190 |
+
</ion-item>
|
191 |
+
<ion-item>
|
192 |
+
<ion-label>Video Quality</ion-label>
|
193 |
+
<ion-select value="720p" id="videoQualitySetting">
|
194 |
+
<ion-select-option value="720p">720p HD</ion-select-option>
|
195 |
+
<ion-select-option value="1080p">1080p Full HD</ion-select-option>
|
196 |
+
<ion-select-option value="4k">4K Ultra HD (Premium)</ion-select-option>
|
197 |
+
</ion-select>
|
198 |
+
</ion-item>
|
199 |
+
<ion-item>
|
200 |
+
<ion-label>Voiceover Language</ion-label>
|
201 |
+
<ion-select value="en-US" id="voiceoverLanguage">
|
202 |
+
<ion-select-option value="en-US">English (US)</ion-select-option>
|
203 |
+
<ion-select-option value="en-GB">English (UK)</ion-select-option>
|
204 |
+
<ion-select-option value="es-ES">Spanish</ion-select-option>
|
205 |
+
<ion-select-option value="fr-FR">French</ion-select-option>
|
206 |
+
</ion-select>
|
207 |
+
</ion-item>
|
208 |
+
<ion-item>
|
209 |
+
<ion-label>Output Format</ion-label>
|
210 |
+
<ion-select value="mp4" id="outputFormat">
|
211 |
+
<ion-select-option value="mp4">MP4 (Recommended)</ion-select-option>
|
212 |
+
<ion-select-option value="mov">MOV</ion-select-option>
|
213 |
+
<ion-select-option value="webm">WebM</ion-select-option>
|
214 |
+
</ion-select>
|
215 |
+
</ion-item>
|
216 |
+
</ion-list>
|
217 |
+
<div style="margin-top: 20px;">
|
218 |
+
<ion-button id="applySettingsButton" expand="block" color="success"><ion-icon slot="start" icon="checkmark"></ion-icon>Apply Settings</ion-button>
|
219 |
</div>
|
220 |
+
<ion-text color="secondary"><p style="margin-top: 16px;">Demo settings only.</p></ion-text>
|
221 |
+
</ion-card-content>
|
222 |
+
</ion-card>
|
223 |
+
|
224 |
+
<ion-card id="help-section" class="ion-hide">
|
225 |
+
<ion-card-header>
|
226 |
+
<ion-card-title><ion-icon icon="help-circle" style="margin-right: 8px;"></ion-icon>Help & Support</ion-card-title>
|
227 |
+
<ion-card-subtitle>Guidance and resources</ion-card-subtitle>
|
228 |
+
</ion-card-header>
|
229 |
+
<ion-card-content>
|
230 |
+
<p>Welcome to Autotutorial.ai! Generate tutorials with ease.</p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
231 |
<p><strong>Getting Started:</strong></p>
|
232 |
+
<ol>
|
233 |
+
<li>Go to "Generate Tutorial" tab.</li>
|
234 |
+
<li>Enter your tutorial topic.</li>
|
235 |
+
<li>Select desired duration.</li>
|
236 |
+
<li>(Optional) Add API keys for enhanced features.</li>
|
237 |
+
<li>Tap "Generate Tutorial" to start.</li>
|
238 |
+
<li>Monitor "Status Updates" for progress.</li>
|
239 |
+
<li>Preview tutorial in "Tutorial Preview" section.</li>
|
240 |
</ol>
|
241 |
+
<p><strong>Tutorial History:</strong></p>
|
242 |
+
<p>Access and manage past tutorials in "Tutorial History" (demo feature).</p>
|
243 |
<p><strong>Settings:</strong></p>
|
244 |
+
<p>Customize default preferences in "Settings" (basic demo settings).</p>
|
245 |
+
<p>For further assistance, contact support at <a href="mailto:[email protected]">[email protected]</a>.</p>
|
246 |
+
</ion-card-content>
|
247 |
+
</ion-card>
|
248 |
+
|
249 |
+
</ion-content>
|
250 |
+
|
251 |
+
<ion-tabs>
|
252 |
+
<ion-tab-bar slot="bottom">
|
253 |
+
<ion-tab-button tab="generate" data-section="generate" class="tab-button-link active">
|
254 |
+
<ion-icon icon="magic"></ion-icon>
|
255 |
+
<ion-label>Generate</ion-label>
|
256 |
+
</ion-tab-button>
|
257 |
+
<ion-tab-button tab="history" data-section="history" class="tab-button-link">
|
258 |
+
<ion-icon icon="time"></ion-icon>
|
259 |
+
<ion-label>History</ion-label>
|
260 |
+
</ion-tab-button>
|
261 |
+
<ion-tab-button tab="settings" data-section="settings" class="tab-button-link">
|
262 |
+
<ion-icon icon="settings"></ion-icon>
|
263 |
+
<ion-label>Settings</ion-label>
|
264 |
+
</ion-tab-button>
|
265 |
+
<ion-tab-button tab="help" data-section="help" class="tab-button-link">
|
266 |
+
<ion-icon icon="help-circle"></ion-icon>
|
267 |
+
<ion-label>Help</ion-label>
|
268 |
+
</ion-tab-button>
|
269 |
+
</ion-tab-bar>
|
270 |
+
</ion-tabs>
|
271 |
+
|
272 |
+
</ion-app>
|
273 |
+
|
274 |
+
<!-- Ionic Scripts -->
|
275 |
+
<script type="module" src="https://cdn.jsdelivr.net/npm/@ionic/core@latest/dist/ionic/ionic.esm.js"></script>
|
276 |
+
<script nomodule src="https://cdn.jsdelivr.net/npm/@ionic/core@latest/dist/ionic/ionic.js"></script>
|
277 |
|
278 |
<script>
|
279 |
document.addEventListener('DOMContentLoaded', () => {
|
280 |
+
// Tab Navigation
|
281 |
+
const tabButtons = document.querySelectorAll('.tab-button-link');
|
282 |
+
const sections = ['generate-section', 'history-section', 'settings-section', 'help-section'];
|
283 |
|
284 |
tabButtons.forEach(button => {
|
285 |
button.addEventListener('click', function(event) {
|
286 |
event.preventDefault();
|
287 |
+
const sectionId = this.getAttribute('data-section') + '-section';
|
288 |
|
289 |
tabButtons.forEach(btn => btn.classList.remove('active'));
|
290 |
+
sections.forEach(sec => document.getElementById(sec).classList.add('ion-hide'));
|
291 |
|
292 |
this.classList.add('active');
|
293 |
+
document.getElementById(sectionId).classList.remove('ion-hide');
|
294 |
+
if (sectionId === 'generate-section') {
|
295 |
+
document.getElementById('videoOutputSection').classList.add('ion-hide');
|
296 |
document.getElementById('videoOutputSection').classList.remove('opacity-0');
|
297 |
}
|
298 |
});
|
299 |
});
|
300 |
+
document.querySelector('.tab-button-link[data-section="generate"]').classList.add('active');
|
301 |
+
sections.filter(sec => sec !== 'generate-section').forEach(sec => document.getElementById(sec).classList.add('ion-hide'));
|
302 |
|
303 |
+
|
304 |
+
// Tutorial History Item Click Simulation
|
305 |
const historyItems = document.querySelectorAll('.history-item');
|
306 |
const videoTitleSpan = document.getElementById('videoTitle');
|
307 |
const videoTitleOverlay = document.getElementById('videoTitleOverlay');
|
|
|
311 |
const title = this.getAttribute('data-video-title');
|
312 |
videoTitleSpan.textContent = title + " (Preview)";
|
313 |
videoTitleOverlay.textContent = title;
|
314 |
+
videoOutputSection.classList.remove('ion-hide');
|
315 |
videoOutputSection.classList.remove('opacity-0');
|
316 |
const statusMessagesDiv = document.getElementById('statusMessages');
|
317 |
+
statusMessagesDiv.innerHTML = `<p class="ion-text-color-secondary"><ion-icon icon="video" color="primary" style="margin-right: 4px;"></ion-icon>Loading: ${title}</p>`;
|
318 |
statusMessagesDiv.scrollTop = statusMessagesDiv.scrollHeight;
|
319 |
});
|
320 |
});
|
321 |
|
322 |
+
// Apply Settings Button Simulation
|
323 |
document.getElementById('applySettingsButton').addEventListener('click', function() {
|
324 |
const statusMessagesDiv = document.getElementById('statusMessages');
|
325 |
+
statusMessagesDiv.innerHTML = `<p class="ion-text-color-success"><ion-icon icon="checkmark-circle" color="success" style="margin-right: 4px;"></ion-icon>Settings Applied.</p>`;
|
326 |
statusMessagesDiv.scrollTop = statusMessagesDiv.scrollHeight;
|
327 |
});
|
328 |
});
|
329 |
|
330 |
|
331 |
document.getElementById('generateButton').addEventListener('click', function() {
|
|
|
332 |
const topic = document.getElementById('tutorialTopic').value;
|
333 |
const duration = document.getElementById('desiredDuration').value;
|
334 |
const openaiKey = document.getElementById('openaiApiKey').value;
|
|
|
345 |
|
346 |
// Reset status and hide video output
|
347 |
statusMessagesDiv.innerHTML = '';
|
348 |
+
errorMessageDiv.classList.add('ion-hide');
|
349 |
+
videoOutputSection.classList.add('ion-hide');
|
350 |
videoOutputSection.classList.remove('opacity-0');
|
351 |
+
resetButton.classList.remove('ion-hide');
|
352 |
+
generateButton.classList.add('ion-hide'); // Hide generate, show reset
|
353 |
+
resetButton.classList.remove('ion-hide');
|
354 |
+
progressBar.value = 0;
|
|
|
|
|
|
|
355 |
|
356 |
|
357 |
const steps = [
|
|
|
369 |
function processStep() {
|
370 |
if (currentStepIndex < steps.length) {
|
371 |
simulateStep(statusMessagesDiv, steps[currentStepIndex].message, steps[currentStepIndex].delay, () => {
|
372 |
+
progressBar.value = ((currentStepIndex + 1) / steps.length);
|
373 |
currentStepIndex++;
|
374 |
processStep();
|
375 |
}, true);
|
376 |
} else {
|
377 |
+
progressBar.value = 1;
|
378 |
+
statusMessagesDiv.innerHTML = '<p class="ion-text-color-success"><ion-icon icon="checkmark-circle" color="success" style="margin-right: 4px;"></ion-icon>Generation Complete!</p>';
|
|
|
|
|
|
|
379 |
|
380 |
videoTitleSpan.textContent = topic + " (" + duration + "min Preview)";
|
381 |
videoTitleOverlay.textContent = topic;
|
382 |
+
videoOutputSection.classList.remove('ion-hide');
|
383 |
setTimeout(() => videoOutputSection.classList.remove('opacity-0'), 50);
|
384 |
+
generateButton.classList.remove('ion-hide'); // Show generate, hide reset
|
385 |
+
generateButton.classList.add('ion-hide');
|
386 |
+
resetButton.classList.remove('ion-hide');
|
387 |
}
|
388 |
}
|
389 |
processStep();
|
|
|
392 |
});
|
393 |
|
394 |
document.getElementById('resetButton').addEventListener('click', function() {
|
|
|
395 |
const statusMessagesDiv = document.getElementById('statusMessages');
|
396 |
const errorMessageDiv = document.getElementById('errorMessage');
|
397 |
const generateButton = document.getElementById('generateButton');
|
398 |
const resetButton = document.getElementById('resetButton');
|
|
|
399 |
const videoOutputSection = document.getElementById('videoOutputSection');
|
400 |
const progressBar = document.getElementById('progressBar');
|
401 |
|
402 |
+
statusMessagesDiv.innerHTML = '<p class="ion-text-color-secondary"><ion-icon icon="checkmark-circle" color="success" style="margin-right: 4px;"></ion-icon>Ready to generate. Click "Generate Tutorial".</p>';
|
403 |
+
errorMessageDiv.classList.add('ion-hide');
|
404 |
+
videoOutputSection.classList.add('ion-hide');
|
405 |
videoOutputSection.classList.remove('opacity-0');
|
406 |
+
generateButton.classList.remove('ion-hide'); // Show generate, hide reset
|
407 |
+
generateButton.classList.remove('ion-hide');
|
408 |
+
resetButton.classList.add('ion-hide');
|
409 |
+
progressBar.value = 0;
|
|
|
|
|
|
|
|
|
|
|
410 |
});
|
411 |
|
412 |
|
|
|
414 |
setTimeout(function() {
|
415 |
const messageElement = document.createElement('p');
|
416 |
if (isSuccess) {
|
417 |
+
messageElement.classList.add('ion-text-color-secondary');
|
418 |
+
messageElement.innerHTML = `<ion-icon icon="radio-button-on" color="primary" style="margin-right: 4px;"></ion-icon> ${message}`;
|
419 |
} else {
|
420 |
+
messageElement.classList.add('ion-text-color-danger');
|
421 |
+
messageElement.innerHTML = `<ion-icon icon="close-circle" color="danger" style="margin-right: 4px;"></ion-icon> ${message}`;
|
422 |
document.getElementById('errorMessage').textContent = "Error generating tutorial. Check API keys.";
|
423 |
+
document.getElementById('errorMessage').classList.remove('ion-hide');
|
424 |
+
generateButton.classList.remove('ion-hide'); // Show generate, hide reset
|
425 |
+
generateButton.classList.add('ion-hide');
|
426 |
+
resetButton.classList.remove('ion-hide');
|
427 |
+
document.getElementById('progressBar').value = 0;
|
|
|
|
|
|
|
428 |
}
|
429 |
statusDiv.appendChild(messageElement);
|
430 |
statusDiv.scrollTop = statusDiv.scrollHeight;
|