-
-
+
+
+
+
+
+
+
-
- 📝 Edit napise (kliknite vrstico za popravek)
-
- ${segments.filter(s => s.start < endInit && s.end > startInit).map((s, i) => `
-
- [${s.start.toFixed(1)}s]
-
-
- `).join("")}
-
-
+
+
+
+
+
+
+
+
0:00
+
${formatTime(videoDuration)}
+
+
+
+ Začetek: ${formatTime(startInit)}
+ Konec: ${formatTime(endInit)}
+ Trajanje: ${(endInit-startInit).toFixed(1)}s
+
+
+
+
+
+
+
+
+ 📝 Edit napise (kliknite vrstico za popravek)
+
+ ${segments.filter(s => s.start < endInit && s.end > startInit).map((s, i) => `
+
+ [${s.start.toFixed(1)}s]
+
+
+ `).join("")}
+
+
+
@@ -1068,48 +1091,125 @@
document.addEventListener("keydown", escHandler);
overlay.querySelector(".modal-close").addEventListener("click", closeModal);
- // Slider handlers
+ // ─── iPhone-style trim bar logic ───
const video = document.getElementById("edit-video");
- const startSlider = document.getElementById("edit-start");
- const endSlider = document.getElementById("edit-end");
+ const trimBar = document.getElementById("trim-bar");
+ const trimRegion = document.getElementById("trim-region");
+ const handleL = document.getElementById("trim-handle-left");
+ const handleR = document.getElementById("trim-handle-right");
+ const playhead = document.getElementById("trim-playhead");
const startVal = document.getElementById("edit-start-val");
const endVal = document.getElementById("edit-end-val");
const durVal = document.getElementById("edit-duration");
- function updateUI() {
- const s = parseFloat(startSlider.value);
- const e = parseFloat(endSlider.value);
- startVal.textContent = s.toFixed(1) + "s";
- endVal.textContent = e.toFixed(1) + "s";
- durVal.textContent = (e - s).toFixed(1) + "s";
+ // State
+ let trimStart = startInit;
+ let trimEnd = endInit;
+ let dragging = null; // 'left' / 'right' / null
+
+ function pctOf(t) {
+ return (t / videoDuration) * 100;
}
- startSlider.addEventListener("input", () => {
- if (parseFloat(startSlider.value) >= parseFloat(endSlider.value)) {
- startSlider.value = parseFloat(endSlider.value) - 0.5;
+ function timeFromPx(px) {
+ const rect = trimBar.getBoundingClientRect();
+ const pct = Math.max(0, Math.min(1, (px - rect.left) / rect.width));
+ return pct * videoDuration;
+ }
+
+ function renderTrim() {
+ const lPct = pctOf(trimStart);
+ const rPct = pctOf(trimEnd);
+ trimRegion.style.left = lPct + '%';
+ trimRegion.style.right = (100 - rPct) + '%';
+ handleL.style.left = `calc(${lPct}% - 9px)`;
+ handleR.style.left = `calc(${rPct}% - 9px)`;
+ startVal.textContent = formatTime(trimStart);
+ endVal.textContent = formatTime(trimEnd);
+ durVal.textContent = (trimEnd - trimStart).toFixed(1) + "s";
+ }
+
+ function renderPlayhead() {
+ if (!video) return;
+ const t = video.currentTime || 0;
+ playhead.style.left = `calc(${pctOf(t)}% - 1px)`;
+ }
+
+ // Mouse + touch start
+ function onPointerDown(which, e) {
+ e.preventDefault();
+ dragging = which;
+ document.body.style.cursor = 'ew-resize';
+ }
+
+ // Mouse + touch move
+ function onPointerMove(e) {
+ if (!dragging) return;
+ const x = e.touches ? e.touches[0].clientX : e.clientX;
+ let t = timeFromPx(x);
+ // Constraints
+ if (dragging === 'left') {
+ t = Math.max(0, Math.min(t, trimEnd - 1));
+ trimStart = t;
+ if (video) video.currentTime = t;
+ } else if (dragging === 'right') {
+ t = Math.max(trimStart + 1, Math.min(t, videoDuration));
+ trimEnd = t;
+ if (video) video.currentTime = t;
}
- updateUI();
- if (video) video.currentTime = parseFloat(startSlider.value);
- });
- endSlider.addEventListener("input", () => {
- if (parseFloat(endSlider.value) <= parseFloat(startSlider.value)) {
- endSlider.value = parseFloat(startSlider.value) + 0.5;
- }
- updateUI();
- if (video) video.currentTime = parseFloat(endSlider.value);
+ renderTrim();
+ }
+
+ function onPointerUp() {
+ dragging = null;
+ document.body.style.cursor = '';
+ }
+
+ handleL.addEventListener("mousedown", (e) => onPointerDown('left', e));
+ handleR.addEventListener("mousedown", (e) => onPointerDown('right', e));
+ handleL.addEventListener("touchstart", (e) => onPointerDown('left', e));
+ handleR.addEventListener("touchstart", (e) => onPointerDown('right', e));
+
+ document.addEventListener("mousemove", onPointerMove);
+ document.addEventListener("touchmove", onPointerMove);
+ document.addEventListener("mouseup", onPointerUp);
+ document.addEventListener("touchend", onPointerUp);
+
+ // Click anywhere on trim bar = seek video
+ trimBar.addEventListener("click", (e) => {
+ if (e.target === handleL || e.target === handleR || handleL.contains(e.target) || handleR.contains(e.target)) return;
+ const t = timeFromPx(e.clientX);
+ if (video) video.currentTime = t;
});
+ // Update playhead during playback
+ if (video) {
+ video.addEventListener("timeupdate", renderPlayhead);
+ video.addEventListener("loadedmetadata", () => {
+ // Če videoDuration ni bilo podanih, vzemi iz videa
+ if (!data.video_duration && video.duration) {
+ // Recalculate render
+ renderTrim();
+ renderPlayhead();
+ }
+ });
+ }
+
window.seekEditVideo = function(which) {
if (!video) return;
- const t = which === "start" ? parseFloat(startSlider.value) : parseFloat(endSlider.value);
+ const t = which === "start" ? trimStart : trimEnd;
video.currentTime = t;
if (which === "start") video.play();
};
+ // Initial render
+ renderTrim();
+ renderPlayhead();
+
// Save button
document.getElementById("edit-save-btn").addEventListener("click", async () => {
- const start = parseFloat(startSlider.value);
- const end = parseFloat(endSlider.value);
+ const start = trimStart;
+ const end = trimEnd;
if (end - start < 5) {
alert("Trajanje mora biti vsaj 5s");
return;