| 80 |
80 |
|
if (saved) { var t = parseFloat(saved); if (!isNaN(t) && t < media.duration - 5) media.currentTime = t; }
|
| 81 |
81 |
|
});
|
| 82 |
82 |
|
|
| 83 |
|
- |
// Keyboard shortcuts
|
| 84 |
|
- |
setupKeyboard(media, null);
|
|
83 |
+ |
// Keyboard shortcuts (no virtual timeline in simple mode)
|
|
84 |
+ |
setupKeyboard(media, null, null, null, 0);
|
| 85 |
85 |
|
return;
|
| 86 |
86 |
|
}
|
| 87 |
87 |
|
|
| 286 |
286 |
|
}
|
| 287 |
287 |
|
});
|
| 288 |
288 |
|
|
| 289 |
|
- |
// Seek on progress bar (virtual timeline)
|
| 290 |
|
- |
progressBar.addEventListener('click', function(e) {
|
| 291 |
|
- |
var rect = progressBar.getBoundingClientRect();
|
| 292 |
|
- |
var pct = (e.clientX - rect.left) / rect.width;
|
| 293 |
|
- |
var targetMs = pct * totalDurationMs;
|
|
289 |
+ |
// Seek to a virtual time in milliseconds (shared by progress bar + keyboard)
|
|
290 |
+ |
function seekToVirtualMs(targetMs) {
|
|
291 |
+ |
targetMs = Math.max(0, Math.min(targetMs, totalDurationMs));
|
| 294 |
292 |
|
|
| 295 |
293 |
|
var targetIdx = 0;
|
| 296 |
294 |
|
for (var k = 0; k < segments.length; k++) {
|
| 331 |
329 |
|
}
|
| 332 |
330 |
|
|
| 333 |
331 |
|
updateInsertionUI();
|
|
332 |
+ |
}
|
|
333 |
+ |
|
|
334 |
+ |
// Seek on progress bar (virtual timeline)
|
|
335 |
+ |
progressBar.addEventListener('click', function(e) {
|
|
336 |
+ |
var rect = progressBar.getBoundingClientRect();
|
|
337 |
+ |
var pct = (e.clientX - rect.left) / rect.width;
|
|
338 |
+ |
seekToVirtualMs(pct * totalDurationMs);
|
| 334 |
339 |
|
});
|
| 335 |
340 |
|
|
| 336 |
341 |
|
// Volume
|
| 469 |
474 |
|
});
|
| 470 |
475 |
|
|
| 471 |
476 |
|
// Keyboard shortcuts for segment mode
|
| 472 |
|
- |
setupKeyboard(activeEl, function() { return activeEl; });
|
|
477 |
+ |
setupKeyboard(activeEl, function() { return activeEl; }, seekToVirtualMs, getVirtualTime, totalDurationMs);
|
| 473 |
478 |
|
|
| 474 |
479 |
|
// ── Keyboard shortcuts (Phase 5) ──
|
| 475 |
480 |
|
|
| 476 |
|
- |
function setupKeyboard(defaultEl, getActiveEl) {
|
|
481 |
+ |
function setupKeyboard(defaultEl, getActiveEl, virtualSeek, getVTime, totalMs) {
|
| 477 |
482 |
|
document.addEventListener('keydown', function(e) {
|
| 478 |
483 |
|
// Don't handle in form inputs
|
| 479 |
484 |
|
if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA' || e.target.tagName === 'SELECT') return;
|
| 487 |
492 |
|
break;
|
| 488 |
493 |
|
case 'ArrowLeft':
|
| 489 |
494 |
|
e.preventDefault();
|
| 490 |
|
- |
if (el.currentTime !== undefined) el.currentTime = Math.max(0, el.currentTime - 10);
|
|
495 |
+ |
if (virtualSeek) {
|
|
496 |
+ |
virtualSeek(getVTime() * 1000 - 10000);
|
|
497 |
+ |
} else if (el.currentTime !== undefined) {
|
|
498 |
+ |
el.currentTime = Math.max(0, el.currentTime - 10);
|
|
499 |
+ |
}
|
| 491 |
500 |
|
break;
|
| 492 |
501 |
|
case 'ArrowRight':
|
| 493 |
502 |
|
e.preventDefault();
|
| 494 |
|
- |
if (el.currentTime !== undefined) el.currentTime = Math.min(el.duration || 0, el.currentTime + 10);
|
|
503 |
+ |
if (virtualSeek) {
|
|
504 |
+ |
virtualSeek(getVTime() * 1000 + 10000);
|
|
505 |
+ |
} else if (el.currentTime !== undefined) {
|
|
506 |
+ |
el.currentTime = Math.min(el.duration || 0, el.currentTime + 10);
|
|
507 |
+ |
}
|
| 495 |
508 |
|
break;
|
| 496 |
509 |
|
case 'ArrowUp':
|
| 497 |
510 |
|
e.preventDefault();
|