diff --git a/trailer.html b/trailer.html index 1fa4c3a..380abb5 100644 --- a/trailer.html +++ b/trailer.html @@ -1084,7 +1084,7 @@ + fold("views", "Master pictures for each set-up", "", viewsHtml(draft)) + fold("cast", "The cast", cast.length + " characters - faces, looks, voices", castHtml) + fold("props", "Things that must look the same in every shot", ((PKG.props || []).length || "no") + " tracked", propsHtml()) - + body; + + rangeHtml() + body; } // FOLDS. The cast, the props, the story notes and the master pictures are @@ -1746,6 +1746,26 @@ + ''; } + // A link of many clips can take longer than the proxy's 5 s; it is made + // anyway, and asking again returns the same link at once. + async function shareRetry(payload) { + var r1 = await api("share_clips", payload); + if (!r1.ok && /timed out/i.test(r1.error || "")) r1 = await api("share_clips", payload); + if (!r1.ok) { showMsg("msg", r1.error || "That did not work."); return null; } + hideMsg("msg"); + return r1; + } + var RANGE = { from: "", to: "" }; + document.addEventListener("input", function (e) { + if (e.target && e.target.id === "rgfrom") RANGE.from = e.target.value; + if (e.target && e.target.id === "rgto") RANGE.to = e.target.value; + }); + function rangeHtml() { + return '
Watch a run of shots from shot ' + + ' to ' + + ' ' + + '
'; + } async function act(name, payload) { var r = await api(name, payload); if (!r.ok) { showMsg("msg", r.error || "That did not work."); return null; } @@ -1821,10 +1841,27 @@ else el.disabled = false; return; } + if ((el = hit("data-rangeplay"))) { + // A RUN OF SHOTS: every filmed shot from one number to another, off + // the cutting room floor, as one link that plays them in order. + var rf = String((document.getElementById("rgfrom") || {}).value || "").trim(), rt = String((document.getElementById("rgto") || {}).value || "").trim(); + var pad = function (x) { return /^\d+$/.test(x) ? ("000" + x).slice(-3) : x; }; + rf = pad(rf); rt = pad(rt); + var run = (PKG.shots || []).slice().sort(function (a, b) { return String(a.id).localeCompare(String(b.id)); }) + .filter(function (x) { var id = String(x.id); return x.clip_url && !x.floor && (!rf || id >= rf) && (!rt || id <= rt || id.indexOf(rt) === 0); }) + .map(function (x) { return x.id; }); + if (run.length < 2) { showMsg("msg", "There are fewer than two filmed shots in that range."); return; } + if (run.length > 80) { showMsg("msg", "That is " + run.length + " shots; a link holds at most 80. Choose a shorter range."); return; } + el.disabled = true; + r = await shareRetry({ draft_id: CUR, shot_ids: run, label: "Shots " + run[0] + " to " + run[run.length - 1] }); + el.disabled = false; + if (r) { var lk = document.getElementById("rglink"); if (lk) lk.innerHTML = '' + esc(r.url) + ''; showMsg("msg", r.clips + " shots, played in order: " + r.url, "ok"); } + return; + } if ((el = hit("data-sharescene"))) { var sids = el.getAttribute("data-sharescene").split(","); el.disabled = true; - r = await act("share_clips", { draft_id: CUR, shot_ids: sids, label: el.getAttribute("data-scenelabel") }); + r = await shareRetry({ draft_id: CUR, shot_ids: sids, label: el.getAttribute("data-scenelabel") }); if (r) { SHARES["scene:" + sids.join(",")] = r.url; showMsg("msg", r.clips + " clips, played in order: " + r.url, "ok"); openTab(CUR); } else el.disabled = false; return;