diff --git a/script.html b/script.html index bf9c0c8..4fb89d8 100644 --- a/script.html +++ b/script.html @@ -1194,4 +1194,199 @@ function bindShare() { var sl = document.getElementById("sharelink"); if (sl) sl.onclick = async function () { var title = (DATA && DATA.script && DATA.script.title) || "A video"; - \ No newline at end of file + // The native sheet is the shortest path into a text message on a phone. + if (navigator.share) { + try { await navigator.share({ title: title, text: msg, url: link }); return; } + catch (e) { if (e && e.name === "AbortError") return; } + } + try { + await navigator.clipboard.writeText(link); + sl.textContent = "Link copied"; + setTimeout(function () { sl.textContent = "Share the video"; }, 1600); + } catch (e) { showMsg("msg", "Copy this: " + link); } + }; + var c = document.getElementById("sharecopy"); + if (c) c.onclick = function () { + var t = document.getElementById("sharemsg"); + t.select(); + navigator.clipboard.writeText(t.value).then(function () { + c.textContent = "Copied"; + setTimeout(function () { c.textContent = "Copy the message"; }, 1600); + }).catch(function () { c.textContent = "Select it and copy"; }); + }; + } + + b.onclick = async function () { + hideMsg("msg"); + b.disabled = true; b.textContent = "Choosing a frame…"; + var r = await api("share_image", { email: email, project_id: pid, refresh: true }); + if (r.ok && r.pending) { + var waited = 0; + r = await new Promise(function (done) { + var t = setInterval(async function () { + waited += 4; + var g = await api("share_image", { email: email, project_id: pid }); + if (g.ok && !g.pending) { clearInterval(t); done(g); return; } + if (waited > 180) { clearInterval(t); done({ ok: false, error: "That is taking unusually long." }); } + }, 4000); + }); + } + b.disabled = false; b.textContent = "Pick another frame"; + if (!r.ok) { showMsg("msg", r.error || "Could not make that picture."); return; } + if (r.note) { showMsg("msg", r.note); return; } + note.textContent = r.status_text || ""; + paint(r); + }; + + api("share_image", { email: email, project_id: pid }).then(function (r) { + if (r && r.ok && !r.pending && r.image) { + b.textContent = "Pick another frame"; + note.textContent = r.status_text || ""; + paint(r); + } + }); +} + +function bindPost() { + loadTakes(); + bindShare(); + // The editing bay is opt-in. Most people want to watch the thing and leave. + var eo = document.getElementById("edlopen"); + if (eo) eo.onclick = function () { + var w = document.getElementById("edlwrap"); + var open = w.style.display === "none"; + w.style.display = open ? "" : "none"; + this.textContent = open ? "Close the video editor" : "Open the video editor"; + if (open) { + if (!EDL) loadEdl((DATA && DATA.project) || {}); + else tlDraw(); + w.scrollIntoView({ behavior: "smooth", block: "start" }); + } + }; + var sb = document.getElementById("seams"); + function paintSeams(r) { + var el = document.getElementById("seamout"); + if (!el) return; + el.innerHTML = '

' + esc(r.status_text || "") + '

' + + (r.seams || []).map(function (x) { + var col = x.verdict === "smooth" ? "var(--good)" + : (x.verdict === "visible" ? "var(--accent2)" : "var(--bad)"); + return '
' + + 'shot ' + x.after_shot + ' → ' + x.before_shot + ' at ' + x.at_seconds + 's · ' + + 'shift ' + x.shift_x + ',' + x.shift_y + ' · drift ' + x.drift + ' · ' + + '' + esc(x.verdict) + '' + + (x.recommend_broll ? ' · worth a cutaway' : '') + + '
'; + }).join(""); + } + + if (sb) sb.onclick = async function () { + sb.disabled = true; sb.textContent = "Measuring…"; + var el = document.getElementById("seamout"); + var r = await api("seam_report", { email: email, project_id: pid }); + if (!r.ok) { + sb.disabled = false; sb.textContent = "Measure the joins"; + showMsg("msg", r.error || "Could not measure."); + return; + } + // Measuring downloads every shot and searches each join for the best + // alignment, which is far too slow to answer inside one request. + if (r.pending) { + el.innerHTML = '

' + esc(r.status_text || "Measuring…") + '

'; + var waited = 0; + var t = setInterval(async function () { + waited += 4; + var g = await api("seam_report", { email: email, project_id: pid }); + if (g.ok && !g.pending) { + clearInterval(t); + sb.disabled = false; sb.textContent = "Measure the joins"; + paintSeams(g); + return; + } + if (waited > 180) { + clearInterval(t); + sb.disabled = false; sb.textContent = "Measure the joins"; + showMsg("msg", "Measuring is taking unusually long."); + } + }, 4000); + return; + } + sb.disabled = false; sb.textContent = "Measure the joins"; + if (!r.seams || !r.seams.length) { + el.innerHTML = '

' + esc(r.status_text || "Nothing to measure.") + '

'; + return; + } + el.innerHTML = '

' + esc(r.status_text || "") + '

' + + r.seams.map(function (x) { + var col = x.verdict === "smooth" ? "var(--good)" + : (x.verdict === "visible" ? "var(--accent2)" : "var(--bad)"); + return '
' + + 'shot ' + x.after_shot + ' → ' + x.before_shot + ' at ' + x.at_seconds + 's · ' + + 'shift ' + x.shift_x + ',' + x.shift_y + ' · drift ' + x.drift + ' · ' + + '' + esc(x.verdict) + '' + + (x.recommend_broll ? ' · worth a cutaway' : '') + + '
'; + }).join(""); + }; + + var cb = document.getElementById("cut"); + if (cb) cb.onclick = async function () { + hideMsg("msg"); + cb.disabled = true; cb.textContent = "Cutting…"; + var r = await api("render_cut", { email: email, project_id: pid }); + if (!r.ok) { cb.disabled = false; cb.textContent = "Cut the B-roll in"; showMsg("msg", r.error || "Could not cut."); return; } + var waited = 0; + var t = setInterval(async function () { + waited += 5; + var g = await api("get_project", { email: email, project_id: pid }); + if (g.ok && g.project && g.project.cut_url) { clearInterval(t); load(); return; } + if (waited > 300) { + clearInterval(t); + cb.disabled = false; cb.textContent = "Cut the B-roll in"; + showMsg("msg", "That is taking unusually long. Try again shortly."); + } + }, 5000); + }; +} + +function bindBottom() { + var rv = document.getElementById("revise"); + if (rv) rv.onclick = async function () { + hideMsg("msg"); + var fb = document.getElementById("fb").value.trim(); + if (fb.length < 5) { showMsg("msg", "Tell us what you would like changed."); return; } + rv.disabled = true; rv.textContent = "Sending…"; + var res = await api("revise_script", { email: email, project_id: pid, feedback: fb }); + if (!res.ok) { rv.disabled = false; rv.textContent = "Rewrite the words"; showMsg("msg", res.error || "That did not go through."); return; } + showMsg("msg", "Rewriting now…", "ok"); + load(); + }; + var ap = document.getElementById("approve"); + if (ap) ap.onclick = async function () { + hideMsg("msg"); + ap.disabled = true; ap.textContent = "Approving…"; + var res = await api("approve_script", { email: email, project_id: pid }); + if (!res.ok) { ap.disabled = false; ap.textContent = "Approve and lock it"; showMsg("msg", res.error || "That did not go through."); return; } + showMsg("msg", res.status_text || "Approved.", "ok"); + load(); + }; +} + +async function load() { + if (!pid || !email) return; + if (!PRESETS.length) { + var c = await api("camera_presets", {}); + if (c.ok) { PRESETS = c.presets || []; MODELS = c.models || []; } + } + var r = await api("get_project", { email: email, project_id: pid }); + if (!r.ok) { showMsg("msg", r.error || "Could not load that script."); return; } + if (!PHOTOS.length && r.project && r.project.pet_id) { + var ph = await api("list_photos", { email: email, pet_id: r.project.pet_id }); + if (ph.ok) PHOTOS = ph.photos || []; + } + render(r); +} +load(); + + +