@kanyun-ai-infra/band-cli 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundled/kernel/fixture.js +1 -1
- package/bundled/kernel/index.js +1 -1
- package/bundled/official/activity/package.json +1 -1
- package/bundled/official/approval/package.json +1 -1
- package/bundled/official/artifacts/package.json +1 -1
- package/bundled/official/chat/package.json +1 -1
- package/bundled/official/chunks/chunk-SB74RUTN.js +1 -0
- package/bundled/official/comment/dist/index.js +1 -1
- package/bundled/official/comment/package.json +2 -2
- package/bundled/official/header/package.json +1 -1
- package/bundled/official/home/package.json +1 -1
- package/bundled/official/layouts/package.json +1 -1
- package/bundled/official/library/package.json +1 -1
- package/bundled/official/members/dist/index.js +1 -1
- package/bundled/official/members/package.json +2 -2
- package/bundled/official/memory/dist/index.js +2 -2
- package/bundled/official/memory/package.json +2 -2
- package/bundled/official/native/package.json +1 -1
- package/bundled/official/params-form/package.json +1 -1
- package/bundled/official/plugins/package.json +1 -1
- package/bundled/official/project/dist/index.js +1 -1
- package/bundled/official/project/package.json +2 -2
- package/bundled/official/queue/package.json +1 -1
- package/bundled/official/settings/dist/index.js +1 -1
- package/bundled/official/settings/package.json +2 -2
- package/bundled/official/settings/plugin.yaml +7 -0
- package/bundled/official/shell/dist/index.js +1 -1
- package/bundled/official/shell/package.json +2 -2
- package/bundled/official/stages/package.json +1 -1
- package/bundled/official/threads/package.json +1 -1
- package/bundled/official/turn-bar/package.json +1 -1
- package/bundled/official/turn-trace/package.json +1 -1
- package/bundled/official/version-switch/dist/index.js +1 -1
- package/bundled/official/version-switch/package.json +1 -1
- package/bundled/official/viewer-entity/package.json +1 -1
- package/bundled/official/viewer-external/package.json +1 -1
- package/bundled/official/viewer-image/package.json +1 -1
- package/bundled/official/viewer-media/index.js +2 -2
- package/bundled/official/viewer-media/package.json +2 -2
- package/bundled/official/viewer-storyboard/index.js +2 -2
- package/bundled/official/viewer-storyboard/package.json +2 -2
- package/bundled/official/viewer-text/dist/index.js +2 -2
- package/bundled/official/viewer-text/package.json +2 -2
- package/bundled/official/viewer-tool/package.json +1 -1
- package/bundled/official/viewer-web/package.json +1 -1
- package/bundled/official/viewer-web-app/package.json +1 -1
- package/bundled/official/workshops/dist/index.js +2 -2
- package/bundled/official/workshops/package.json +2 -2
- package/bundled/skills/band-plugin/SKILL.md +20 -273
- package/bundled/skills/band-plugin/references/code.md +58 -0
- package/bundled/skills/band-plugin/references/dev.md +37 -0
- package/bundled/skills/band-plugin/references/execution.md +26 -0
- package/bundled/skills/band-plugin/references/manifest.md +65 -0
- package/bundled/skills/band-plugin/references/placement.md +34 -0
- package/bundled/skills/band-plugin/references/reuse.md +38 -0
- package/bundled/skills/band-plugin/references/rules.md +12 -0
- package/bundled/skills/band-plugin/references/shape.md +17 -0
- package/bundled/skills/band-plugin/references/testing-publish.md +35 -0
- package/bundled/skills/band-plugin/references/viewer-comments.md +25 -0
- package/bundled/skills/band-plugin/templates/dev/fixture.ts +15 -0
- package/bundled/skills/band-plugin/templates/dev/resources.ts +6 -0
- package/bundled/skills/band-plugin/templates/panel/index.ts +24 -0
- package/bundled/skills/band-plugin/templates/panel/package.json +12 -0
- package/bundled/skills/band-plugin/templates/panel/plugin.yaml +5 -0
- package/bundled/skills/band-plugin/templates/toolbar-dock/plugin.yaml +11 -0
- package/dev-host/Inspector.tsx +28 -10
- package/dev-host/app.tsx +2 -1
- package/dev-host/host.css +11 -0
- package/dev-host/main.tsx +5 -0
- package/dist/bin.js +3 -3
- package/dist/build-plugin.d.ts +1 -1
- package/dist/build-plugin.js +1 -1
- package/dist/{chunk-RAD6MMSL.js → chunk-JWZU3NOD.js} +1 -1
- package/dist/{chunk-TN7Z3OF6.js → chunk-TQHHHXXU.js} +1 -1
- package/dist/{chunk-VVJNG5GV.js → chunk-VTAJX7NN.js} +10 -10
- package/dist/{dev-server-RAZQ32W7.js → dev-server-SB5FMSVP.js} +101 -11
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3 -3
- package/dist/vite.d.ts +1 -1
- package/dist/vite.js +2 -2
- package/dist/{workshop-repo-CO6YMDee.d.ts → workshop-repo-Uq6blxyt.d.ts} +10 -10
- package/package.json +5 -4
- package/src/inspector-plugins.ts +18 -0
- package/bundled/official/chunks/chunk-JI6ZNGOE.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{activePair}from"../../chunks/chunk-
|
|
1
|
+
import{activePair}from"../../chunks/chunk-SB74RUTN.js";import"../../chunks/chunk-N6N56MWF.js";import"../../chunks/chunk-TWQQ2CCT.js";import"../../chunks/chunk-JFPQMFKF.js";import{ErrorNote,ExternalImportPanel,Mount,importConnector,importFrom,reactMount,shortTime,useCtxData,useSlotEntries,versionLabel}from"@kanyun-ai-infra/band-plugin-react";import{definePlugin}from"@kanyun-ai-infra/band-plugin-sdk";import{useEffect,useMemo,useState,useSyncExternalStore}from"react";import{jsx,jsxs}from"react/jsx-runtime";if(typeof document!=="undefined"&&document.head){const css="/* src/version-switch.css */\n.band-version-switch {\n display: flex;\n align-items: center;\n gap: 8px;\n flex-wrap: wrap;\n padding: 10px 14px 4px;\n}\n:where([data-band-page=review]) .band-version-switch {\n padding: 0;\n}\n.band-version-switch:where(.compact) {\n padding: 0;\n flex-wrap: nowrap;\n}\n@media (max-width: 860px) {\n .band-version-switch:where(.compact) {\n flex-wrap: wrap;\n min-width: 0;\n max-width: 100%;\n }\n .band-version-switch:where(.compact) .band-version-switch-picker {\n max-width: 100%;\n }\n .band-version-switch:where(.compact) .band-version-switch-select.select {\n max-width: 100%;\n }\n}\n.band-version-switch-name {\n font-weight: 600;\n}\n.band-version-switch-select.select {\n max-width: min(100%, 420px);\n min-height: 32px;\n border-radius: 8px;\n}\n.band-version-switch-old {\n font-size: var(--fs-dense);\n color: var(--warn);\n background: var(--warn-soft);\n padding: 5px 8px;\n border-radius: 7px;\n}\n.band-version-switch-spacer {\n flex: 1;\n}\n.band-version-switch-actions {\n display: flex;\n align-items: center;\n}\n.band-version-switch-picker {\n position: relative;\n min-width: 0;\n}\n.band-version-switch-import {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: 20;\n width: min(340px, calc(100vw - 32px));\n padding: 14px;\n background: var(--panel);\n border-radius: var(--r-xl);\n box-shadow: var(--shadow-pop);\n}\n.band-version-switch:where(:has(.band-version-switch-notice)) {\n flex-wrap: wrap;\n}\n.band-version-switch-notice {\n flex-basis: 100%;\n max-width: 340px;\n color: var(--muted);\n font-size: var(--fs-ui);\n}\n.band-version-switch > :where(.btn) {\n min-height: 32px;\n border-radius: 8px;\n}\n";let el=document.head.querySelector('style[data-band-style="@kanyun-ai-infra/band-version-switch"]');if(!el){el=document.createElement("style");el.setAttribute("data-band-style","@kanyun-ai-infra/band-version-switch");document.head.prepend(el)}el.textContent=css}var noSubscribe=()=>()=>{};var ACTIONS_SLOT="@kanyun-ai-infra/band-version-switch/actions";var src_default=definePlugin({surfaces:{"version-switch":reactMount((ctx,props)=>jsx(VersionBar,{ctx,artifactId:props.owner.artifactId,artifactName:props.owner.artifactName,compare:props.owner.compare,onVersionChange:props.owner.onVersionChange,compact:props.config.compact===true},props.owner.artifactId))}});function ActionsSlot({ctx,artifactId}){const entries=useSlotEntries(ctx,ACTIONS_SLOT);if(entries.length===0)return null;return jsx("span",{className:"band-version-switch-actions","data-band-slot":ACTIONS_SLOT,children:entries.map(e=>jsx(Mount,{mount:el=>ctx.slots.mount(el,ACTIONS_SLOT,{key:e.key,owner:{projectId:ctx.project.id,artifactId}}),deps:[ctx,artifactId,e.key]},e.key))})}function VersionBar({ctx,artifactId,artifactName,compare,compact=false,onVersionChange}){const versions=useCtxData(ctx,()=>ctx.version.list(artifactId),[artifactId],"version.*");const[current,setCurrent]=useState(ctx.version.current());useEffect(()=>ctx.version.subscribe(setCurrent),[ctx]);const[imported,setImported]=useState(null);const[notice,setNotice]=useState("");const persisted=versions.data??[];const list=imported&&!persisted.some(v=>v.id===imported.id)?[...persisted,imported]:persisted;const latest=list.at(-1);const shown=current?list.find(v=>v.id===current.id)??current:latest??null;const old=!!shown&&!!latest&&shown.id!==latest.id;const artifacts=useCtxData(ctx,()=>ctx.artifacts.list(),[],"version.*");const artifact=artifacts.data?.find(a=>a.id===artifactId);const[importOpen,setImportOpen]=useState(false);const[importBusy,setImportBusy]=useState(false);const read=ctx.attachments.importExternal;const connections=ctx.app.data.write?.personalConnections;const canImport=artifact?.storage==="external"&&(artifact.key??"main")==="main"&&ctx.project.access==="member"&&ctx.member.can("submit-change");const via=importConnector(artifact?.source);const source=useMemo(()=>{if(!canImport||!read||!connections&&!via.exchange||!artifact?.runId||!artifact.stage)return void 0;const target={runId:artifact.runId,stage:artifact.stage,type:artifact.artifactType};return{label:via.label,connected:async()=>via.exchange||connections!==void 0&&(await connections.list()).some(c=>c.connector===via.connector&&c.status==="active"),manage:()=>ctx.app.navigate({page:"@kanyun-ai-infra/band-settings/connections"}),read:async ref=>{const result=await read({connector:via.connector,ref,target});if(result.kind==="versions"&&result.versions.length===0)return null;const version=result.kind==="versions"?result.versions.find(v=>v.artifactId===artifactId):void 0;if(!version)throw new Error("\u5BFC\u5165\u6CA1\u6709\u8FD4\u56DE\u5F53\u524D\u4EA7\u7269\u7684\u7248\u672C\uFF0C\u8BF7\u68C0\u67E5\u94FE\u63A5\u540E\u91CD\u65B0\u5BFC\u5165");return version}}},[ctx,canImport,read,connections,artifact?.runId,artifact?.stage,artifact?.artifactType,artifactId,via.connector,via.label,via.exchange]);const prev=shown?list[list.findIndex(v=>v.id===shown.id)-1]:void 0;const pair=useSyncExternalStore(compare?.subscribe??noSubscribe,()=>compare?.get()??null,()=>null);const comparing=!!compare&&activePair(pair,shown)!==null;return jsxs("div",{className:compact?"band-version-switch compact":"band-version-switch",children:[artifactName&&jsx("b",{className:"band-version-switch-name",children:artifactName}),(list.length>0||source)&&jsxs("span",{className:"band-version-switch-picker",children:[jsxs("select",{"aria-label":"\u7248\u672C",className:"select band-version-switch-select","data-band-guide":"versions",disabled:importBusy,value:shown?.id??"",onChange:e=>{if(e.target.value==="import-external"){setNotice("");setImportOpen(true);return}const v=list.find(x=>x.id===e.target.value)??null;ctx.collab.showVersion(v&&v.id===latest?.id?null:v);if(v)onVersionChange?.(v.id)},children:[!shown&&jsx("option",{value:"",children:"\u8FD8\u6CA1\u6709\u7248\u672C"}),[...list].reverse().map(v=>jsxs("option",{value:v.id,children:[versionLabel(v),typeof v.meta?.note==="string"?` \xB7 ${v.meta.note}`:""," \xB7"," ",shortTime(v.createdAt),v.id===latest?.id?" \xB7 \u6700\u65B0":""]},v.id)),source&&jsx("option",{value:"import-external",children:importFrom(via.label,"\u5BFC\u5165\u65B0\u7248\u672C")})]}),importOpen&&source&&jsx("div",{className:"band-version-switch-import",children:jsx(ExternalImportPanel,{source,onAdd:version=>{if(version===null){setNotice("\u5FEB\u7167\u4E0E\u5DF2\u6709\u7248\u672C\u5185\u5BB9\u76F8\u540C\uFF0C\u6CA1\u6709\u4EA7\u751F\u65B0\u7248\u672C");return}setImported({...version,meta:{...version.meta,label:version.meta?.label??"\u65B0\u7248\u672C"}});ctx.collab.showVersion(version);onVersionChange?.(version.id);versions.reload()},onClose:()=>setImportOpen(false),onBusy:setImportBusy})})]}),old&&shown&&jsx("span",{className:"band-version-switch-old",title:compact?`\u53EA\u8BFB\u67E5\u770B ${versionLabel(shown)}\uFF1B\u53EF\u5728\u8FD9\u4E00\u7248\u8BC4\u8BBA\uFF1B\u56DE\u5230\u6700\u65B0\u7248\u624D\u80FD\u7F16\u8F91`:void 0,children:compact?"\u53EA\u8BFB":`\u53EA\u8BFB\u67E5\u770B ${versionLabel(shown)}\uFF1B\u53EF\u5728\u8FD9\u4E00\u7248\u8BC4\u8BBA\uFF1B\u56DE\u5230\u6700\u65B0\u7248\u624D\u80FD\u7F16\u8F91`}),!compact&&jsx("span",{className:"band-version-switch-spacer"}),old&&jsx("button",{type:"button",className:"btn sm",onClick:()=>{ctx.collab.showVersion(null);if(latest)onVersionChange?.(latest.id)},children:"\u56DE\u5230\u6700\u65B0"}),compare&&(prev||comparing)&&jsx("button",{type:"button",className:comparing?"btn primary sm":"btn sm",title:comparing?"\u4E5F\u53EF\u4EE5\u6309 Esc":`\u548C\u4E0A\u4E00\u7248 ${prev?versionLabel(prev):""} \u5E76\u6392\u770B`,onClick:()=>compare.set(comparing||!prev||!shown?null:{against:prev,with:shown.id}),children:comparing?"\u9000\u51FA\u5BF9\u6BD4":`\u5BF9\u6BD4 ${prev?versionLabel(prev):""}`}),!comparing&&jsx(ActionsSlot,{ctx,artifactId}),notice&&jsx("output",{className:"band-version-switch-notice",children:notice}),jsx(ErrorNote,{retry:artifacts.reload,children:artifacts.error}),jsx(ErrorNote,{retry:versions.reload,children:versions.error})]})}export{ACTIONS_SLOT,VersionBar,src_default as default,versionLabel};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{CAPTIONS_FILE,END_BACKOFF_S,FILES_STYLE,ICONS,NARRATION_FILE,POSTER_FILE,SHOT_LIST_FILE,assetsOf,baseName,compareGroups,cueAt,deliverNote,endStillOf,folderOf,formatSize,historyOf,isNewest,localPathOf,mainVideoOf,mountFiles,parseCaptions,parseLocalPath,parseNarration,parseShotList,peaksOf,pendingPickOf,pickOfThread,playbackFor,posterOf,previewText,shotAt,shotChanges,shotFactsOf,shotNo,stillOf,takeIndex,takeLetter,takeName,trackBadges}from"../chunks/chunk-OBPNVP4S.js";import"../chunks/chunk-NUFRM6SI.js";import{relocateFileAnchor}from"../chunks/chunk-Z47EOZYW.js";import"../chunks/chunk-NUFRM6SI.js";import"../chunks/chunk-DK64JRQO.js";import{materialError,materialObjectUrl,materialViewer}from"../chunks/chunk-N6N56MWF.js";import{mountDockButtons}from"../chunks/chunk-TWQQ2CCT.js";import"../chunks/chunk-JFPQMFKF.js";import{shotAnchorOf}from"@kanyun-ai-infra/band-contracts";import{scrollIntoPanel}from"@kanyun-ai-infra/band-plugin-react/scroll";import{EVENT_GROUPS,definePlugin,defineSurface,withImeGuard}from"@kanyun-ai-infra/band-plugin-sdk";import{unitRectFrom}from"@kanyun-ai-infra/band-plugin-react/image-view";import{DRAG_PX,unitRectFrom as unitRectFrom2,unitRectOf}from"@kanyun-ai-infra/band-plugin-react/image-view";function kindOf(mime){if(mime.startsWith("video/"))return"video";if(mime.startsWith("audio/"))return"audio";return null}function mediaEntries(v){return(v?.entries??[]).flatMap(entry=>{const kind=kindOf(entry.mime);return kind?[{entry,kind}]:[]})}function formatTime(seconds){const s=Number.isFinite(seconds)&&seconds>0?Math.floor(seconds):0;const h=Math.floor(s/3600);const m=Math.floor(s%3600/60);const ss=String(s%60).padStart(2,"0");return h>0?`${h}:${String(m).padStart(2,"0")}:${ss}`:`${m}:${ss}`}function formatPrecise(seconds){const s=Number.isFinite(seconds)&&seconds>0?seconds:0;return`${formatTime(s)}.${Math.floor(s*10%10)}`}function timecodeOf(anchor){if(anchor.kind!=="timecode")return null;const{path,seconds,end,rect}=anchor.payload;if(typeof path!=="string"||typeof seconds!=="number"||seconds<0)return null;const box=unitRectFrom(rect);return{path,seconds,...typeof end==="number"&&end>seconds?{end}:{},...box?{rect:box}:{}}}function pointOf(payload){const{path,x,y}=payload;if(typeof path!=="string"||typeof x!=="number"||typeof y!=="number")return null;if(x<0||x>1||y<0||y>1)return null;return{path,x,y}}function placeTimecode(anchor,version,path,duration){const tc=timecodeOf(anchor);if(!tc||tc.path!==path)return null;const after=version.entries.find(e=>e.path===path)?.sha256??null;const at=relocateFileAnchor(tc,{before:null,after,...duration!==void 0?{duration}:{}});return at==="orphan"?null:tc}function containBox(element,natural){if(natural.width<=0||natural.height<=0||element.width<=0||element.height<=0){return element}const k=Math.min(element.width/natural.width,element.height/natural.height);const width=natural.width*k;const height=natural.height*k;return{left:element.left+(element.width-width)/2,top:element.top+(element.height-height)/2,width,height}}var DEFAULT_FRAME=1/30;function frameFrom(mediaTimes){let best=Number.POSITIVE_INFINITY;for(let i=1;i<mediaTimes.length;i++){const d=(mediaTimes[i]??0)-(mediaTimes[i-1]??0);if(d>0&&d<best)best=d}return best>=1/120&&best<=1/10?best:null}function stepFrame(now,frame,delta,duration){const index=Math.floor(now/frame+1e-6)+delta;const t=Math.max(0,(index+.5)*frame);return duration!==void 0?Math.min(t,Math.max(0,duration-frame/2)):t}var RATES=[.25,.5,1,1.5,2,4];function nextRate(rate,delta){let i=0;for(let j=0;j<RATES.length;j++){if(Math.abs((RATES[j]??1)-rate)<Math.abs((RATES[i]??1)-rate))i=j}return RATES[Math.min(RATES.length-1,Math.max(0,i+delta))]??1}var FRAME_NEAR_S=.25;var NARROW_PX=600;var SIDE_MIN_PX=280;var SIDE_GAP_PX=16;function fitFrame(room,aspect){const a=Number.isFinite(aspect)&&aspect>0?aspect:16/9;const W=Math.max(0,room.width);const H=Math.max(0,room.height);let h=H;let w=h*a;if(w>W){w=W;h=W/a}const side=a<1&&W-w-SIDE_GAP_PX>=SIDE_MIN_PX?"right":"below";return{width:w,height:h,side}}function mountMaterialMedia(ctx,root,source){let alive=true;let generation=0;const section=document.createElement("section");section.setAttribute("aria-label","\u7D20\u6750\u97F3\u89C6\u9891");section.style.cssText="display:flex;flex-direction:column;gap:12px;padding:16px;height:100%;box-sizing:border-box;overflow:auto";const kind=source?kindOf(source.attachment.mime):null;const player=document.createElement(kind==="audio"?"audio":"video");player.controls=true;player.preload="metadata";player.setAttribute("aria-label",source?.attachment.name??"\u7D20\u6750\u64AD\u653E\u5668");player.style.cssText="width:100%;max-height:100%;min-height:48px";const status=document.createElement("p");status.setAttribute("role","status");const retry=document.createElement("button");retry.type="button";retry.className="btn sm";retry.textContent="\u91CD\u8BD5";retry.hidden=true;const load=async()=>{const mine=++generation;status.textContent="\u6B63\u5728\u52A0\u8F7D\u7D20\u6750\u97F3\u89C6\u9891\u2026";retry.hidden=true;if(!source||!kind||materialViewer(source.attachment)!=="material-media"){status.textContent="\u7F3A\u5C11\u53EF\u67E5\u770B\u7684\u7D20\u6750\u97F3\u89C6\u9891\u6765\u6E90";return}try{const url=await materialObjectUrl(ctx,source);if(!alive||mine!==generation)return;player.onloadedmetadata=()=>{if(alive&&mine===generation)status.textContent=""};player.onerror=()=>{if(alive&&mine===generation){status.textContent="\u97F3\u89C6\u9891\u683C\u5F0F\u4E0D\u652F\u6301\u6216\u6587\u4EF6\u635F\u574F\uFF0C\u8BF7\u4E0B\u8F7D\u539F\u6587\u4EF6";retry.hidden=false}};player.src=url;player.load()}catch(error){if(alive&&mine===generation){status.textContent=materialError(error);retry.hidden=false}}};retry.onclick=()=>void load();section.append(player,status,retry);root.append(section);void load();return()=>{alive=false;generation++;player.pause();player.onloadedmetadata=null;player.onerror=null;player.removeAttribute("src");player.load();section.remove()}}var TOOLBAR_SLOT="@kanyun-ai-infra/band-viewer-media/toolbar";var STATUS_SLOT="@kanyun-ai-infra/band-viewer-media/status";var OVERLAY_SLOT="@kanyun-ai-infra/band-viewer-media/overlay";function mountSlotCells(ctx,el,slot,owner,cellClass){const cells=new Map;const draw=()=>{const entries=ctx.slots.entries(slot);const keep=new Set(entries.map(e=>e.key));for(const[key,c]of cells){if(keep.has(key))continue;c.dispose();c.cell.remove();cells.delete(key)}for(const e of entries){let c=cells.get(e.key);if(!c){const cell=el.ownerDocument.createElement("div");cell.className=cellClass;cell.dataset.bandSlotEntry=e.key;c={cell,dispose:ctx.slots.mount(cell,slot,{key:e.key,owner})};cells.set(e.key,c)}el.appendChild(c.cell)}el.hidden=cells.size===0};draw();const off=ctx.slots.subscribe(slot,draw);return()=>{off();for(const c of cells.values())c.dispose();cells.clear();el.replaceChildren();el.hidden=true}}var pct=n=>`${Math.max(0,Math.min(100,n*100))}%`;var px=n=>`${Math.round(n)}px`;var TAKES_STYLE=`
|
|
1
|
+
import{CAPTIONS_FILE,END_BACKOFF_S,FILES_STYLE,ICONS,NARRATION_FILE,POSTER_FILE,SHOT_LIST_FILE,assetsOf,baseName,compareGroups,cueAt,deliverNote,endStillOf,folderOf,formatSize,historyOf,isNewest,localPathOf,mainVideoOf,mountFiles,parseCaptions,parseLocalPath,parseNarration,parseShotList,peaksOf,pendingPickOf,pickOfThread,playbackFor,posterOf,previewText,shotAt,shotChanges,shotFactsOf,shotNo,stillOf,takeIndex,takeLetter,takeName,trackBadges}from"../chunks/chunk-OBPNVP4S.js";import"../chunks/chunk-NUFRM6SI.js";import{relocateFileAnchor}from"../chunks/chunk-Z47EOZYW.js";import"../chunks/chunk-NUFRM6SI.js";import"../chunks/chunk-DK64JRQO.js";import{materialError,materialObjectUrl,materialViewer}from"../chunks/chunk-N6N56MWF.js";import{mountDockButtons}from"../chunks/chunk-TWQQ2CCT.js";import"../chunks/chunk-JFPQMFKF.js";import{shotAnchorOf}from"@kanyun-ai-infra/band-contracts";import{scrollIntoPanel}from"@kanyun-ai-infra/band-plugin-react/scroll";import{EVENT_GROUPS,NARROW_QUERY,definePlugin,defineSurface,withImeGuard}from"@kanyun-ai-infra/band-plugin-sdk";import{unitRectFrom}from"@kanyun-ai-infra/band-plugin-react/image-view";import{DRAG_PX,unitRectFrom as unitRectFrom2,unitRectOf}from"@kanyun-ai-infra/band-plugin-react/image-view";function kindOf(mime){if(mime.startsWith("video/"))return"video";if(mime.startsWith("audio/"))return"audio";return null}function mediaEntries(v){return(v?.entries??[]).flatMap(entry=>{const kind=kindOf(entry.mime);return kind?[{entry,kind}]:[]})}function formatTime(seconds){const s=Number.isFinite(seconds)&&seconds>0?Math.floor(seconds):0;const h=Math.floor(s/3600);const m=Math.floor(s%3600/60);const ss=String(s%60).padStart(2,"0");return h>0?`${h}:${String(m).padStart(2,"0")}:${ss}`:`${m}:${ss}`}function formatPrecise(seconds){const s=Number.isFinite(seconds)&&seconds>0?seconds:0;return`${formatTime(s)}.${Math.floor(s*10%10)}`}function timecodeOf(anchor){if(anchor.kind!=="timecode")return null;const{path,seconds,end,rect}=anchor.payload;if(typeof path!=="string"||typeof seconds!=="number"||seconds<0)return null;const box=unitRectFrom(rect);return{path,seconds,...typeof end==="number"&&end>seconds?{end}:{},...box?{rect:box}:{}}}function pointOf(payload){const{path,x,y}=payload;if(typeof path!=="string"||typeof x!=="number"||typeof y!=="number")return null;if(x<0||x>1||y<0||y>1)return null;return{path,x,y}}function placeTimecode(anchor,version,path,duration){const tc=timecodeOf(anchor);if(!tc||tc.path!==path)return null;const after=version.entries.find(e=>e.path===path)?.sha256??null;const at=relocateFileAnchor(tc,{before:null,after,...duration!==void 0?{duration}:{}});return at==="orphan"?null:tc}function containBox(element,natural){if(natural.width<=0||natural.height<=0||element.width<=0||element.height<=0){return element}const k=Math.min(element.width/natural.width,element.height/natural.height);const width=natural.width*k;const height=natural.height*k;return{left:element.left+(element.width-width)/2,top:element.top+(element.height-height)/2,width,height}}var DEFAULT_FRAME=1/30;function frameFrom(mediaTimes){let best=Number.POSITIVE_INFINITY;for(let i=1;i<mediaTimes.length;i++){const d=(mediaTimes[i]??0)-(mediaTimes[i-1]??0);if(d>0&&d<best)best=d}return best>=1/120&&best<=1/10?best:null}function stepFrame(now,frame,delta,duration){const index=Math.floor(now/frame+1e-6)+delta;const t=Math.max(0,(index+.5)*frame);return duration!==void 0?Math.min(t,Math.max(0,duration-frame/2)):t}var RATES=[.25,.5,1,1.5,2,4];function nextRate(rate,delta){let i=0;for(let j=0;j<RATES.length;j++){if(Math.abs((RATES[j]??1)-rate)<Math.abs((RATES[i]??1)-rate))i=j}return RATES[Math.min(RATES.length-1,Math.max(0,i+delta))]??1}var FRAME_NEAR_S=.25;var NARROW_PX=600;var SIDE_MIN_PX=280;var SIDE_GAP_PX=16;function fitFrame(room,aspect){const a=Number.isFinite(aspect)&&aspect>0?aspect:16/9;const W=Math.max(0,room.width);const H=Math.max(0,room.height);let h=H;let w=h*a;if(w>W){w=W;h=W/a}const side=a<1&&W-w-SIDE_GAP_PX>=SIDE_MIN_PX?"right":"below";return{width:w,height:h,side}}function mountMaterialMedia(ctx,root,source){let alive=true;let generation=0;const section=document.createElement("section");section.setAttribute("aria-label","\u7D20\u6750\u97F3\u89C6\u9891");section.style.cssText="display:flex;flex-direction:column;gap:12px;padding:16px;height:100%;box-sizing:border-box;overflow:auto";const kind=source?kindOf(source.attachment.mime):null;const player=document.createElement(kind==="audio"?"audio":"video");player.controls=true;player.preload="metadata";player.setAttribute("aria-label",source?.attachment.name??"\u7D20\u6750\u64AD\u653E\u5668");player.style.cssText="width:100%;max-height:100%;min-height:48px";const status=document.createElement("p");status.setAttribute("role","status");const retry=document.createElement("button");retry.type="button";retry.className="btn sm";retry.textContent="\u91CD\u8BD5";retry.hidden=true;const load=async()=>{const mine=++generation;status.textContent="\u6B63\u5728\u52A0\u8F7D\u7D20\u6750\u97F3\u89C6\u9891\u2026";retry.hidden=true;if(!source||!kind||materialViewer(source.attachment)!=="material-media"){status.textContent="\u7F3A\u5C11\u53EF\u67E5\u770B\u7684\u7D20\u6750\u97F3\u89C6\u9891\u6765\u6E90";return}try{const url=await materialObjectUrl(ctx,source);if(!alive||mine!==generation)return;player.onloadedmetadata=()=>{if(alive&&mine===generation)status.textContent=""};player.onerror=()=>{if(alive&&mine===generation){status.textContent="\u97F3\u89C6\u9891\u683C\u5F0F\u4E0D\u652F\u6301\u6216\u6587\u4EF6\u635F\u574F\uFF0C\u8BF7\u4E0B\u8F7D\u539F\u6587\u4EF6";retry.hidden=false}};player.src=url;player.load()}catch(error){if(alive&&mine===generation){status.textContent=materialError(error);retry.hidden=false}}};retry.onclick=()=>void load();section.append(player,status,retry);root.append(section);void load();return()=>{alive=false;generation++;player.pause();player.onloadedmetadata=null;player.onerror=null;player.removeAttribute("src");player.load();section.remove()}}var TOOLBAR_SLOT="@kanyun-ai-infra/band-viewer-media/toolbar";var STATUS_SLOT="@kanyun-ai-infra/band-viewer-media/status";var OVERLAY_SLOT="@kanyun-ai-infra/band-viewer-media/overlay";function mountSlotCells(ctx,el,slot,owner,cellClass){const cells=new Map;const draw=()=>{const entries=ctx.slots.entries(slot);const keep=new Set(entries.map(e=>e.key));for(const[key,c]of cells){if(keep.has(key))continue;c.dispose();c.cell.remove();cells.delete(key)}for(const e of entries){let c=cells.get(e.key);if(!c){const cell=el.ownerDocument.createElement("div");cell.className=cellClass;cell.dataset.bandSlotEntry=e.key;c={cell,dispose:ctx.slots.mount(cell,slot,{key:e.key,owner})};cells.set(e.key,c)}el.appendChild(c.cell)}el.hidden=cells.size===0};draw();const off=ctx.slots.subscribe(slot,draw);return()=>{off();for(const c of cells.values())c.dispose();cells.clear();el.replaceChildren();el.hidden=true}}var pct=n=>`${Math.max(0,Math.min(100,n*100))}%`;var px=n=>`${Math.round(n)}px`;var TAKES_STYLE=`
|
|
2
2
|
.bm-takes { display: grid; gap: 10px; min-width: 0; container: bm-takes / inline-size; }
|
|
3
3
|
.bm-tk-bar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; min-width: 0; }
|
|
4
4
|
.bm-tk-bar h3 { margin: 0; font-size: var(--fs-row); font-weight: 600; color: var(--ink); }
|
|
@@ -118,7 +118,7 @@ import{CAPTIONS_FILE,END_BACKOFF_S,FILES_STYLE,ICONS,NARRATION_FILE,POSTER_FILE,
|
|
|
118
118
|
.bm-tk-mbar { display: flex; align-items: center; gap: 10px; }
|
|
119
119
|
.bm-tk-mbar .grow { flex: 1 1 auto; }
|
|
120
120
|
.bm-tk-mbar .btn { min-height: 44px; padding: 0 18px; }
|
|
121
|
-
`;var aspectOf=format=>{const[w,h]=(format??"").split("x").map(Number);return w&&h?`${w} / ${h}`:"16 / 9"};function mountTakes(o){const doc=o.doc;const shot=o.shot;const takes=shot.takes??[];const cutId=shot.take??takes[0]?.id??"";const cutDur=Math.max(.05,shot.end-shot.start);const beforeLen=()=>o.before?o.before.end-o.before.start:0;const afterLen=()=>o.after?o.after.end-o.after.start:0;const hasCtx=o.before!==void 0||o.after!==void 0;const cells=new Map;const el=doc.createElement("div");el.className="bm-takes";const style=doc.createElement("style");style.textContent=TAKES_STYLE;const bar=doc.createElement("div");bar.className="bm-tk-bar";const title=doc.createElement("h3");title.textContent=`\u955C\u5934 ${o.shotNo} \xB7 ${shot.title}`;const sub=doc.createElement("span");sub.className="bm-tk-sub";sub.textContent=`${takes.length} \u6761\u5019\u9009`;const grow=doc.createElement("span");grow.className="bm-tk-grow";const ctxBtn=doc.createElement("button");ctxBtn.type="button";ctxBtn.className="bm-tk-ctx";ctxBtn.textContent="\u5E26\u524D\u540E\u955C\u5934";ctxBtn.setAttribute("aria-pressed","false");ctxBtn.hidden=!hasCtx;const seg=doc.createElement("span");seg.className="bm-tk-switch";const sideBtn=doc.createElement("button");sideBtn.type="button";sideBtn.textContent="\u5E76\u6392";const abBtn=doc.createElement("button");abBtn.type="button";abBtn.textContent="A/B \u5207\u6362";abBtn.disabled=takes.length<2;seg.append(sideBtn,abBtn);const backBtn=doc.createElement("button");backBtn.type="button";backBtn.className="btn sm";backBtn.textContent="\u8FD4\u56DE\u6210\u7247";backBtn.addEventListener("click",()=>o.onClose());bar.append(title,sub,grow,ctxBtn,seg,backBtn);const grid=doc.createElement("div");grid.className="bm-tk-grid";grid.style.setProperty("--n",String(Math.min(4,Math.max(2,takes.length))));const ab=doc.createElement("div");ab.className="bm-tk-ab";ab.hidden=true;const abMain=doc.createElement("div");abMain.className="bm-tk-main";const abSide=doc.createElement("div");abSide.className="bm-tk-side";ab.append(abMain,abSide);const dots=doc.createElement("div");dots.className="bm-tk-dots";const ctl=doc.createElement("div");ctl.className="bm-tk-ctl";const playBtn=doc.createElement("button");playBtn.type="button";playBtn.className="ib";const timeLabel=doc.createElement("span");timeLabel.className="t";const nowLabel=doc.createElement("span");nowLabel.textContent="0:00.0";const totalLabel=doc.createElement("i");timeLabel.append(nowLabel,totalLabel);const gap=doc.createElement("span");gap.className="grow";const loopBtn=doc.createElement("button");loopBtn.type="button";loopBtn.className="ib";loopBtn.innerHTML=ICONS.loop;loopBtn.setAttribute("aria-label","\u5FAA\u73AF\u64AD\u653E\u8FD9\u4E00\u955C");loopBtn.title="\u5FAA\u73AF\u64AD\u653E\u8FD9\u4E00\u955C";loopBtn.setAttribute("aria-pressed","true");const muteBtn=doc.createElement("button");muteBtn.type="button";muteBtn.className="ib";ctl.append(playBtn,timeLabel,gap,loopBtn,muteBtn);const prog=doc.createElement("div");prog.className="bm-tk-prog";prog.setAttribute("role","slider");prog.setAttribute("aria-label","\u8FD9\u4E00\u955C\u7684\u8FDB\u5EA6");prog.setAttribute("aria-valuemin","0");const dimBefore=doc.createElement("span");dimBefore.className="dim";dimBefore.hidden=true;const dimAfter=doc.createElement("span");dimAfter.className="dim";dimAfter.hidden=true;const done=doc.createElement("span");done.className="done";const head=doc.createElement("span");head.className="head";prog.append(dimBefore,dimAfter,done,head);const hint=doc.createElement("p");hint.className="bm-tk-hint";const mbar=doc.createElement("div");mbar.className="bm-tk-mbar";mbar.hidden=true;const mCount=doc.createElement("span");mCount.className="pc bm-tk-sub";const mGrow=doc.createElement("span");mGrow.className="grow";const mPick=doc.createElement("button");mPick.type="button";mPick.className="btn primary";mPick.textContent="\u7528\u8FD9\u6761";mbar.append(mCount,mGrow);el.append(style,bar,grid,ab,dots,ctl,prog,hint,mbar);let mode="side";let context=false;let playing=false;let loop=true;let muted=false;let phase="take";let focusId=cutId;let dragging=null;let timer;let alive=true;const takeOf=id=>takes.find(t=>t.id===id);const clipOf=id=>takeOf(id)?.clip??null;const narrow=()=>(doc.defaultView?.innerWidth??NARROW_PX)<NARROW_PX;const phaseOf=()=>context?phase:"take";const videoOf=c=>phaseOf()==="take"?c.clip:c.cut;const allVideos=()=>[...cells.values()].flatMap(c=>[c.clip,c.cut].filter(Boolean));const lenOf=id=>takeOf(id)?.duration??cutDur;const localSeconds=()=>{const c=cells.get(focusId);const v=c?videoOf(c):null;const t=v&&Number.isFinite(v.currentTime)?v.currentTime:0;if(phaseOf()==="take")return Math.max(0,Math.min(t,lenOf(focusId)));const start=phaseOf()==="before"?o.before?.start??0:o.after?.start??0;return Math.max(0,t-start)};const span=()=>({before:context?beforeLen():0,take:cutDur,after:context?afterLen():0});const spanTotal=()=>{const s=span();return s.before+s.take+s.after};const progress=()=>{const s=span();const total=spanTotal();if(total<=0)return 0;const ph=phaseOf();if(ph==="take"){const ratio=Math.min(1,localSeconds()/Math.max(.01,lenOf(focusId)));return(s.before+ratio*s.take)/total}const base=ph==="before"?0:s.before+s.take;return Math.min(1,(base+localSeconds())/total)};const drawProgress=()=>{const s=span();const total=spanTotal();const on=context&&total>0;dimBefore.hidden=!on||s.before===0;dimAfter.hidden=!on||s.after===0;if(on){dimBefore.style.left="0";dimBefore.style.width=pct(s.before/total);dimAfter.style.left=pct((s.before+s.take)/total);dimAfter.style.width=pct(s.after/total)}const p=progress();done.style.width=pct(p);head.style.left=pct(p);prog.setAttribute("aria-valuenow",p.toFixed(3));nowLabel.textContent=formatPrecise(localSeconds());totalLabel.textContent=` / ${formatPrecise(phaseOf()==="take"?lenOf(focusId):cutDur)}`};const paintPlay=()=>{playBtn.innerHTML=playing?ICONS.pause:ICONS.play;playBtn.setAttribute("aria-label",playing?"\u6682\u505C":"\u64AD\u653E");playBtn.title=playing?"\u6682\u505C\uFF08\u7A7A\u683C / K\uFF09":"\u64AD\u653E\uFF08\u7A7A\u683C / K\uFF09"};const setSpeakers=()=>{for(const[id,c]of cells){const speak=id===focusId&&!muted;for(const v of[c.clip,c.cut])if(v)v.muted=!speak;c.spk.dataset.on=String(speak);c.spk.innerHTML=speak?ICONS.volume:ICONS.muted;c.spk.title=speak?"\u6B63\u5728\u51FA\u58F0":"\u9759\u97F3\uFF1B\u70B9\u753B\u9762\u6362\u6210\u8FD9\u6761\u51FA\u58F0"}};const paintPhase=()=>{const ph=phaseOf();for(const c of cells.values()){if(c.clip)c.clip.dataset.off=String(ph!=="take"||c.clip.readyState<2);if(c.cut)c.cut.dataset.off=String(ph==="take"||c.cut.readyState<2);const bar2=c.stage.querySelector(".bm-tk-ctxbar");if(bar2)bar2.hidden=!context}drawProgress()};const pauseAll=()=>{for(const v of allVideos())v.pause();playing=false;paintPlay()};const seekTo=at=>{const s=span();let ph="take";let t=at;if(context&&at<s.before){ph="before";t=(o.before?.start??0)+at}else if(context&&at>s.before+s.take){ph="after";t=(o.after?.start??0)+(at-s.before-s.take)}else{t=Math.max(0,at-s.before)}if(ph!==phase){phase=ph;paintPhase()}const ratio=ph==="take"?Math.min(1,Math.max(0,t/Math.max(.01,s.take))):0;for(const c of cells.values()){const v=videoOf(c);if(!v)continue;const want=ph==="take"?ratio*lenOf(c.takeId):t;try{v.currentTime=Math.max(0,Math.min(want,Math.max(.02,(v.duration||want+1)-.03)))}catch{}}drawProgress();o.onFocus()};const playFrom=ph=>{phase=ph;const s=span();if(ph==="before")seekTo(0);else if(ph==="after")seekTo(s.before+s.take);else seekTo(s.before);paintPhase();for(const c of cells.values()){const v=videoOf(c);if(!v||v.dataset.off==="true")continue;void v.play()?.catch(()=>{v.muted=true;void v.play()?.catch(()=>void 0)})}playing=true;paintPlay()};const play=()=>{const first=context&&o.before?"before":"take";playFrom(first)};const togglePlay=()=>{if(playing)pauseAll();else play()};const master=()=>{const c=cells.get(focusId)??[...cells.values()][0];return c?videoOf(c):null};const advance=()=>{const ph=phaseOf();if(ph==="before")return playFrom("take");if(ph==="take"){if(afterLen()>0)return playFrom("after");if(!loop)return pauseAll();return playFrom(o.before?"before":"take")}if(!loop)return pauseAll();return playFrom(o.before?"before":"take")};const tick=()=>{if(!alive)return;const m=master();if(!m)return;const ph=phaseOf();if(playing){const ratio=ph==="take"?Math.min(1,Math.max(0,m.currentTime/Math.max(.01,m.duration||cutDur))):0;for(const c of cells.values()){const v=videoOf(c);if(!v||v===m||v.dataset.off==="true"||v.paused)continue;const want=ph==="take"?ratio*lenOf(c.takeId):m.currentTime;if(Math.abs(v.currentTime-want)>.18){try{v.currentTime=want}catch{}}}const end=ph==="before"?o.before?.end??0:ph==="take"?Math.min(m.duration||cutDur,Number.POSITIVE_INFINITY):o.after?.end??0;if(m.currentTime>=end-.04||m.ended)return advance()}drawProgress();const at=Math.round(localSeconds()*10);if(at!==lastFocusTick){lastFocusTick=at;o.onFocus()}};let lastFocusTick=-1;const startTimer=()=>{if(timer!==void 0)return;timer=setInterval(tick,120)};const aspect=aspectOf(o.format);const buildCell=takeId=>{const take=takeOf(takeId);const i=takeIndex(shot,takeId);const item=doc.createElement("div");item.className="bm-tk-item";const stage=doc.createElement("div");stage.className="bm-tk-stage";stage.style.aspectRatio=aspect;stage.dataset.letter=takeLetter(i);const img=doc.createElement("img");img.alt="";const spk=doc.createElement("span");spk.className="bm-tk-spk";spk.dataset.on="false";spk.innerHTML=ICONS.muted;const ctxbar=doc.createElement("span");ctxbar.className="bm-tk-ctxbar";ctxbar.hidden=true;const bBefore=doc.createElement("i");const bTake=doc.createElement("b");const bAfter=doc.createElement("i");const total=beforeLen()+(take?.duration??cutDur)+afterLen();bBefore.style.width=total>0?pct(beforeLen()/total):"0";bAfter.style.width=total>0?pct(afterLen()/total):"0";ctxbar.append(bBefore,bTake,bAfter);const mark=doc.createElement("div");mark.className="bm-tk-mark";stage.append(img,spk,ctxbar,mark);item.append(stage);if(take?.image){void o.url(take.image).then(u=>{if(u&&alive)img.src=u})}let clip=null;if(take?.clip){clip=doc.createElement("video");clip.preload="auto";clip.playsInline=true;clip.muted=takeId!==focusId;clip.dataset.off="true";clip.addEventListener("loadeddata",paintPhase);clip.addEventListener("seeked",paintPhase);clip.addEventListener("loadedmetadata",()=>{if(clip&&clip.currentTime===0)clip.currentTime=.001;if(takeId===focusId)drawProgress()});void o.url(take.clip).then(u=>{if(!u||!alive||!clip)return;clip.src=u});stage.append(clip)}stage.addEventListener("click",()=>focusOn(takeId));let cut=null;if(hasCtx){cut=doc.createElement("video");cut.preload="auto";cut.playsInline=true;cut.muted=true;cut.dataset.off="true";cut.addEventListener("loadeddata",paintPhase);cut.addEventListener("seeked",paintPhase);void o.url(o.cutPath).then(u=>{if(u&&alive&&cut)cut.src=u});stage.append(cut)}const card=doc.createElement("div");card.className="bm-tk-card";item.append(card);cells.set(takeId,{takeId,stage,img,clip,cut,card,spk,item,mark});bindMark(mark,takeId);return item};const focusOn=takeId=>{focusId=takeId;setSpeakers();paintSel();if(abMode())layoutAB();paintMobilePick();paintDots();drawProgress();o.onFocus()};const bindMark=(layer,takeId)=>{let gesture=null;const draft=doc.createElement("div");draft.className="bm-tk-mark bm-tk-draft";layer.parentElement?.append(draft);const local=e=>{const r=layer.getBoundingClientRect();return{x:e.clientX-r.left,y:e.clientY-r.top}};layer.addEventListener("pointerdown",e=>{if(!o.marking()||takeId!==focusId)return;if(e.pointerType==="mouse"&&e.button!==0)return;if(clipOf(takeId)===null)return;pauseAll();layer.setPointerCapture?.(e.pointerId);gesture={id:e.pointerId,...local(e),moved:false}});layer.addEventListener("pointermove",e=>{if(!gesture||gesture.id!==e.pointerId)return;const at=local(e);if(!gesture.moved&&Math.hypot(at.x-gesture.x,at.y-gesture.y)<4)return;gesture.moved=true;const x0=Math.min(gesture.x,at.x);const y0=Math.min(gesture.y,at.y);draft.style.display="block";draft.style.left=px(x0);draft.style.top=px(y0);draft.style.width=px(Math.abs(at.x-gesture.x));draft.style.height=px(Math.abs(at.y-gesture.y))});const finish=(e,commit)=>{const g=gesture;if(!g||g.id!==e.pointerId)return;gesture=null;draft.style.display="none";if(!commit||takeId!==focusId)return;const r=layer.getBoundingClientRect();const at=local(e);const rect=g.moved?unitRectOf({left:r.left,top:r.top,width:r.width,height:r.height},{x:r.left+g.x,y:r.top+g.y},{x:e.clientX,y:e.clientY}):unitRectOf({left:r.left,top:r.top,width:r.width,height:r.height},{x:r.left+at.x,y:r.top+at.y});if(!rect)return;o.onMark(localSeconds(),rect)};layer.addEventListener("pointerup",e=>finish(e,true));layer.addEventListener("pointercancel",e=>finish(e,false))};const paintCards=()=>{const pending=o.pending();const canPick=o.canPick();for(const takeId of takes.map(t=>t.id)){const cell=cells.get(takeId);const take=takeOf(takeId);if(!cell||!take)continue;const inCut=takeId===cutId;const picked=pending?.takeId===takeId;const diff=take.duration-cutDur;cell.card.dataset.picked=String(picked);cell.card.replaceChildren();const l1=doc.createElement("div");l1.className="bm-tk-l1";const name=doc.createElement("b");name.textContent=takeName(shot,takeId);const d=doc.createElement("span");d.className="d";d.append(`${take.duration.toFixed(1)} \u79D2`);if(!inCut){if(Math.abs(diff)<.05)d.append("\uFF08\u4E00\u6837\u957F\uFF09");else{d.append("\uFF08");const em=doc.createElement("em");em.textContent=`${diff>0?"+":""}${diff.toFixed(1)}`;d.append(em,"\uFF09")}}l1.append(name);if(inCut){const tag=doc.createElement("span");tag.className="bm-tk-tag";tag.textContent="\u6210\u7247";l1.append(tag)}if(picked){const tag=doc.createElement("span");tag.className="bm-tk-tag";tag.dataset.kind="picked";tag.textContent="\u5DF2\u9009";l1.append(tag)}l1.append(d);cell.card.append(l1);if(take.note){const note=doc.createElement("p");note.className="bm-tk-note";note.textContent=take.note;cell.card.append(note)}const acts=doc.createElement("div");acts.className="bm-tk-acts";const pc=doc.createElement("span");pc.className="pc";pc.innerHTML=ICONS.comment;pc.append(String(o.comments(takeId)));const g=doc.createElement("span");g.className="grow";acts.append(pc,g);acts.append(moreMenu(takeId,take.clip??null));if(!inCut){if(picked&&pending?.undoable){const hand=doc.createElement("span");hand.className="bm-tk-hand";hand.append("\u5DF2\u4EA4\u7ED9 Rondo \xB7 ");const undo=doc.createElement("button");undo.type="button";undo.textContent="\u64A4\u9500";undo.addEventListener("click",()=>o.onUndo(pending.threadId));hand.append(undo);acts.append(hand)}else if(picked){const wait=doc.createElement("span");wait.className="bm-tk-wait";wait.textContent="\u5DF2\u9009 \xB7 Rondo \u5728\u6362";acts.append(wait)}else if(canPick){const use=doc.createElement("button");use.type="button";use.className="btn sm primary";use.textContent="\u7528\u8FD9\u6761";use.addEventListener("click",()=>o.onPick(takeId));acts.append(use)}}cell.card.append(acts)}paintMobilePick()};const moreMenu=(takeId,clip)=>{const more=doc.createElement("span");more.className="bm-tk-more";const btn=doc.createElement("button");btn.type="button";btn.className="ib sm";btn.setAttribute("aria-label","\u66F4\u591A\uFF1A\u5BF9\u8FD9\u6761\u8BC4\u8BBA\u3001\u4E0B\u8F7D\u7247\u6BB5");btn.title="\u5BF9\u8FD9\u6761\u8BC4\u8BBA \xB7 \u4E0B\u8F7D\u7247\u6BB5";btn.innerHTML=ICONS.more;btn.setAttribute("aria-haspopup","menu");btn.setAttribute("aria-expanded","false");const menu=doc.createElement("div");menu.className="bm-tk-menu";menu.setAttribute("role","menu");menu.hidden=true;const cmt=doc.createElement("button");cmt.type="button";cmt.setAttribute("role","menuitem");cmt.textContent="\u5BF9\u8FD9\u6761\u8BC4\u8BBA";cmt.addEventListener("click",()=>{menu.hidden=true;btn.setAttribute("aria-expanded","false");o.onComment(takeId)});menu.append(cmt);if(clip){const dl=doc.createElement("button");dl.type="button";dl.setAttribute("role","menuitem");dl.textContent="\u4E0B\u8F7D\u7247\u6BB5";dl.addEventListener("click",()=>{menu.hidden=true;btn.setAttribute("aria-expanded","false");void o.url(clip).then(u=>{if(!u)return;const a=doc.createElement("a");a.href=u;a.download=clip.split("/").pop()??"take.mp4";a.click()})});menu.append(dl)}btn.addEventListener("click",()=>{const open=menu.hidden;menu.hidden=!open;btn.setAttribute("aria-expanded",String(open))});more.append(btn,menu);return more};const paintMobilePick=()=>{if(!narrow()){mPick.remove();return}const pending=o.pending();const inCut=focusId===cutId;const picked=pending?.takeId===focusId;mCount.replaceChildren();mCount.innerHTML=ICONS.comment;mCount.append(` \u610F\u89C1 ${o.comments(focusId)}`);mPick.replaceChildren();if(inCut||!o.canPick()){mPick.remove();return}mbar.append(mPick);if(picked&&pending?.undoable){mPick.textContent="\u64A4\u9500";mPick.disabled=false;mPick.onclick=()=>o.onUndo(pending.threadId)}else if(picked){mPick.textContent="\u5DF2\u9009 \xB7 Rondo \u5728\u6362";mPick.disabled=true;mPick.onclick=null}else{mPick.textContent="\u7528\u8FD9\u6761";mPick.disabled=false;mPick.onclick=()=>o.onPick(focusId)}};const paintSel=()=>{const on=abMode();for(const[id,c]of cells)c.stage.dataset.sel=String(id===focusId&&on)};const layoutSide=()=>{for(const t of takes){const c=cells.get(t.id);if(!c)continue;if(c.stage.parentElement!==c.item)c.item.prepend(c.stage);if(c.card.parentElement!==c.item)c.item.append(c.card)}grid.replaceChildren(...takes.map(t=>cells.get(t.id)?.item).filter(Boolean));el.append(dots,ctl,prog,hint,mbar)};const layoutAB=()=>{const cell=cells.get(focusId);if(!cell)return;for(const c of cells.values())if(c!==cell)c.stage.remove();abMain.replaceChildren(cell.stage);const pick=doc.createElement("div");pick.className="bm-tk-pick";pick.setAttribute("role","group");pick.setAttribute("aria-label","\u5207\u6362\u5019\u9009");for(const t of takes){const b=doc.createElement("button");b.type="button";b.textContent=`${takeLetter(takeIndex(shot,t.id))}${t.id===cutId?" \xB7 \u6210\u7247":""}`;b.setAttribute("aria-pressed",String(t.id===focusId));b.addEventListener("click",()=>focusOn(t.id));pick.append(b)}const tip=doc.createElement("span");tip.className="bm-tk-hint";tip.textContent="\u6309\u5404\u81EA\u65F6\u957F\u7684\u6BD4\u4F8B\u5BF9\u4F4D\u7F6E";pick.append(tip);abMain.append(pick);abMain.append(dots,ctl,prog,hint);for(const t of takes){const c=cells.get(t.id);if(!c||c===cell)continue;if(c.stage.parentElement!==c.item)c.item.prepend(c.stage)}abSide.replaceChildren(...takes.map(t=>cells.get(t.id)?.card).filter(Boolean));paintSel()};const abMode=()=>{if(narrow()||mode==="ab")return true;const w=el.clientWidth||el.getBoundingClientRect().width||0;return!(w>0&&w/Math.max(1,takes.length)>=220)};const layout=()=>{const phone=narrow();el.dataset.narrow=String(phone);mbar.hidden=!phone;hint.hidden=phone;const w=el.clientWidth||el.getBoundingClientRect().width||0;const fits=w>0&&w/Math.max(1,takes.length)>=220;const useAB=abMode();grid.hidden=useAB;ab.hidden=!useAB;sideBtn.setAttribute("aria-pressed",String(!useAB));abBtn.setAttribute("aria-pressed",String(useAB));sideBtn.disabled=!fits||phone;sideBtn.title=sideBtn.disabled?"\u8FD9\u4E00\u5757\u653E\u4E0D\u4E0B\u51E0\u6761\u5E76\u6392\uFF0C\u7528 A/B \u5207\u6362\u770B":"\u51E0\u6761\u5019\u9009\u5E76\u6392";if(useAB)layoutAB();else layoutSide();paintSel();paintDots()};const paintDots=()=>{const i=takeIndex(shot,focusId);const phone=narrow();dots.hidden=!phone;if(!phone){dots.replaceChildren();return}dots.replaceChildren(...takes.map((t,k)=>{const d=doc.createElement("i");d.dataset.on=String(k===i);return d}));const label=doc.createElement("span");label.className="bm-tk-dotlabel";label.textContent=`${takeName(shot,focusId)} ${i+1}/${takes.length}`;dots.append(label);const swipe2=doc.createElement("span");swipe2.className="bm-tk-swipehint";swipe2.textContent="\u5DE6\u53F3\u6ED1\u52A8\u753B\u9762\u6362\u5019\u9009";dots.append(swipe2)};let swipe=null;el.addEventListener("pointerdown",e=>{if(!narrow()||o.marking())return;if(!e.target?.closest?.(".bm-tk-stage"))return;swipe={id:e.pointerId,x:e.clientX}});el.addEventListener("pointerup",e=>{if(!swipe||swipe.id!==e.pointerId)return;const dx=e.clientX-swipe.x;swipe=null;if(Math.abs(dx)<40)return;const next=takes[takeIndex(shot,focusId)+(dx<0?1:-1)];if(next)focusOn(next.id)});const paintMute=()=>{muteBtn.innerHTML=muted?ICONS.muted:ICONS.volume;muteBtn.setAttribute("aria-label",muted?"\u53D6\u6D88\u9759\u97F3":"\u9759\u97F3");muteBtn.title=muted?"\u53D6\u6D88\u9759\u97F3":"\u9759\u97F3";muteBtn.setAttribute("aria-pressed",String(muted))};for(const t of takes)buildCell(t.id);setSpeakers();paintCards();layout();paintPhase();paintPlay();drawProgress();paintMute();const ro=typeof ResizeObserver==="undefined"?null:new ResizeObserver(()=>{if(!alive)return;layout();drawProgress()});ro?.observe(el);startTimer();playBtn.addEventListener("click",()=>togglePlay());loopBtn.addEventListener("click",()=>{loop=!loop;loopBtn.setAttribute("aria-pressed",String(loop))});muteBtn.addEventListener("click",()=>{muted=!muted;setSpeakers();paintMute()});sideBtn.addEventListener("click",()=>{mode="side";layout()});abBtn.addEventListener("click",()=>{mode="ab";layout()});ctxBtn.addEventListener("click",()=>{context=!context;ctxBtn.setAttribute("aria-pressed",String(context));if(!context){phase="take";paintPhase()}else if(playing){playFrom(o.before?"before":"take")}else{paintPhase();seekTo(beforeLen())}});const seekAt=clientX=>{const r=prog.getBoundingClientRect();if(r.width===0)return;const p=Math.min(1,Math.max(0,(clientX-r.left)/r.width));seekTo(p*spanTotal())};prog.addEventListener("pointerdown",e=>{if(e.pointerType==="mouse"&&e.button!==0)return;dragging=e.pointerId;prog.setPointerCapture?.(e.pointerId);seekAt(e.clientX)});prog.addEventListener("pointermove",e=>{if(dragging===e.pointerId)seekAt(e.clientX)});prog.addEventListener("pointerup",()=>{dragging=null});prog.addEventListener("pointercancel",()=>{dragging=null});return{el,focus:()=>{const clip=clipOf(focusId);if(!clip)return null;return{takeId:focusId,seconds:localSeconds(),path:clip}},refresh:()=>{paintCards();drawProgress()},relayout:()=>{el.dataset.marking=String(o.marking());layout()},dispose:()=>{alive=false;if(timer!==void 0)clearInterval(timer);ro?.disconnect();for(const v of allVideos()){v.pause();v.removeAttribute("src")}el.remove()}}}function neighborsOf(shots,shotId){const i=shots.findIndex(s=>s.id===shotId);if(i<0)return{};const prev=shots[i-1];const next=shots[i+1];return{...prev?{before:{start:Math.max(prev.start,prev.end-1),end:prev.end}}:{},...next?{after:{start:next.start,end:Math.min(next.end,next.start+1)}}:{}}}var PLAY_WRITE_MS=250;var MENU_RATES=[.5,1,1.5,2];var MIN_FRAME_PX=240;var BAR_SHOW_MS=3e3;var COMMENT_DRAG_PX=6;var COMMENT_BOX_PX=144;var TIGHT_STAGE_PX=280;var BOX_ROOM_MIN_HEIGHT_PX=600;var BOX_NARROW_QUERY="(pointer: coarse), (max-width: 599px)";var LONG_PRESS_MS=500;var LONG_PRESS_SLOP_PX=10;var MIN_RANGE_S=.1;var FIRST_SCREEN_VAR="--band-review-first-screen";var STYLE=`
|
|
121
|
+
`;var aspectOf=format=>{const[w,h]=(format??"").split("x").map(Number);return w&&h?`${w} / ${h}`:"16 / 9"};function mountTakes(o){const doc=o.doc;const shot=o.shot;const takes=shot.takes??[];const cutId=shot.take??takes[0]?.id??"";const cutDur=Math.max(.05,shot.end-shot.start);const beforeLen=()=>o.before?o.before.end-o.before.start:0;const afterLen=()=>o.after?o.after.end-o.after.start:0;const hasCtx=o.before!==void 0||o.after!==void 0;const cells=new Map;const el=doc.createElement("div");el.className="bm-takes";const style=doc.createElement("style");style.textContent=TAKES_STYLE;const bar=doc.createElement("div");bar.className="bm-tk-bar";const title=doc.createElement("h3");title.textContent=`\u955C\u5934 ${o.shotNo} \xB7 ${shot.title}`;const sub=doc.createElement("span");sub.className="bm-tk-sub";sub.textContent=`${takes.length} \u6761\u5019\u9009`;const grow=doc.createElement("span");grow.className="bm-tk-grow";const ctxBtn=doc.createElement("button");ctxBtn.type="button";ctxBtn.className="bm-tk-ctx";ctxBtn.textContent="\u5E26\u524D\u540E\u955C\u5934";ctxBtn.setAttribute("aria-pressed","false");ctxBtn.hidden=!hasCtx;const seg=doc.createElement("span");seg.className="bm-tk-switch";const sideBtn=doc.createElement("button");sideBtn.type="button";sideBtn.textContent="\u5E76\u6392";const abBtn=doc.createElement("button");abBtn.type="button";abBtn.textContent="A/B \u5207\u6362";abBtn.disabled=takes.length<2;seg.append(sideBtn,abBtn);const backBtn=doc.createElement("button");backBtn.type="button";backBtn.className="btn sm";backBtn.textContent="\u8FD4\u56DE\u6210\u7247";backBtn.addEventListener("click",()=>o.onClose());bar.append(title,sub,grow,ctxBtn,seg,backBtn);const grid=doc.createElement("div");grid.className="bm-tk-grid";grid.style.setProperty("--n",String(Math.min(4,Math.max(2,takes.length))));const ab=doc.createElement("div");ab.className="bm-tk-ab";ab.hidden=true;const abMain=doc.createElement("div");abMain.className="bm-tk-main";const abSide=doc.createElement("div");abSide.className="bm-tk-side";ab.append(abMain,abSide);const dots=doc.createElement("div");dots.className="bm-tk-dots";const ctl=doc.createElement("div");ctl.className="bm-tk-ctl";const playBtn=doc.createElement("button");playBtn.type="button";playBtn.className="ib";const timeLabel=doc.createElement("span");timeLabel.className="t";const nowLabel=doc.createElement("span");nowLabel.textContent="0:00.0";const totalLabel=doc.createElement("i");timeLabel.append(nowLabel,totalLabel);const gap=doc.createElement("span");gap.className="grow";const loopBtn=doc.createElement("button");loopBtn.type="button";loopBtn.className="ib";loopBtn.innerHTML=ICONS.loop;loopBtn.setAttribute("aria-label","\u5FAA\u73AF\u64AD\u653E\u8FD9\u4E00\u955C");loopBtn.title="\u5FAA\u73AF\u64AD\u653E\u8FD9\u4E00\u955C";loopBtn.setAttribute("aria-pressed","true");const muteBtn=doc.createElement("button");muteBtn.type="button";muteBtn.className="ib";ctl.append(playBtn,timeLabel,gap,loopBtn,muteBtn);const prog=doc.createElement("div");prog.className="bm-tk-prog";prog.setAttribute("role","slider");prog.setAttribute("aria-label","\u8FD9\u4E00\u955C\u7684\u8FDB\u5EA6");prog.setAttribute("aria-valuemin","0");const dimBefore=doc.createElement("span");dimBefore.className="dim";dimBefore.hidden=true;const dimAfter=doc.createElement("span");dimAfter.className="dim";dimAfter.hidden=true;const done=doc.createElement("span");done.className="done";const head=doc.createElement("span");head.className="head";prog.append(dimBefore,dimAfter,done,head);const hint=doc.createElement("p");hint.className="bm-tk-hint";const mbar=doc.createElement("div");mbar.className="bm-tk-mbar";mbar.hidden=true;const mCount=doc.createElement("span");mCount.className="pc bm-tk-sub";const mGrow=doc.createElement("span");mGrow.className="grow";const mPick=doc.createElement("button");mPick.type="button";mPick.className="btn primary";mPick.textContent="\u7528\u8FD9\u6761";mbar.append(mCount,mGrow);el.append(style,bar,grid,ab,dots,ctl,prog,hint,mbar);let mode="side";let context=false;let playing=false;let loop=true;let muted=false;let phase="take";let focusId=cutId;let dragging=null;let timer;let alive=true;const takeOf=id=>takes.find(t=>t.id===id);const clipOf=id=>takeOf(id)?.clip??null;const narrow=()=>(doc.defaultView?.innerWidth??NARROW_PX)<NARROW_PX;const phaseOf=()=>context?phase:"take";const videoOf=c=>phaseOf()==="take"?c.clip:c.cut;const allVideos=()=>[...cells.values()].flatMap(c=>[c.clip,c.cut].filter(Boolean));const lenOf=id=>takeOf(id)?.duration??cutDur;const localSeconds=()=>{const c=cells.get(focusId);const v=c?videoOf(c):null;const t=v&&Number.isFinite(v.currentTime)?v.currentTime:0;if(phaseOf()==="take")return Math.max(0,Math.min(t,lenOf(focusId)));const start=phaseOf()==="before"?o.before?.start??0:o.after?.start??0;return Math.max(0,t-start)};const span=()=>({before:context?beforeLen():0,take:cutDur,after:context?afterLen():0});const spanTotal=()=>{const s=span();return s.before+s.take+s.after};const progress=()=>{const s=span();const total=spanTotal();if(total<=0)return 0;const ph=phaseOf();if(ph==="take"){const ratio=Math.min(1,localSeconds()/Math.max(.01,lenOf(focusId)));return(s.before+ratio*s.take)/total}const base=ph==="before"?0:s.before+s.take;return Math.min(1,(base+localSeconds())/total)};const drawProgress=()=>{const s=span();const total=spanTotal();const on=context&&total>0;dimBefore.hidden=!on||s.before===0;dimAfter.hidden=!on||s.after===0;if(on){dimBefore.style.left="0";dimBefore.style.width=pct(s.before/total);dimAfter.style.left=pct((s.before+s.take)/total);dimAfter.style.width=pct(s.after/total)}const p=progress();done.style.width=pct(p);head.style.left=pct(p);prog.setAttribute("aria-valuenow",p.toFixed(3));nowLabel.textContent=formatPrecise(localSeconds());totalLabel.textContent=` / ${formatPrecise(phaseOf()==="take"?lenOf(focusId):cutDur)}`};const paintPlay=()=>{playBtn.innerHTML=playing?ICONS.pause:ICONS.play;playBtn.setAttribute("aria-label",playing?"\u6682\u505C":"\u64AD\u653E");playBtn.title=playing?"\u6682\u505C\uFF08\u7A7A\u683C / K\uFF09":"\u64AD\u653E\uFF08\u7A7A\u683C / K\uFF09"};const setSpeakers=()=>{for(const[id,c]of cells){const speak=id===focusId&&!muted;for(const v of[c.clip,c.cut])if(v)v.muted=!speak;c.spk.dataset.on=String(speak);c.spk.innerHTML=speak?ICONS.volume:ICONS.muted;c.spk.title=speak?"\u6B63\u5728\u51FA\u58F0":"\u9759\u97F3\uFF1B\u70B9\u753B\u9762\u6362\u6210\u8FD9\u6761\u51FA\u58F0"}};const paintPhase=()=>{const ph=phaseOf();for(const c of cells.values()){if(c.clip)c.clip.dataset.off=String(ph!=="take"||c.clip.readyState<2);if(c.cut)c.cut.dataset.off=String(ph==="take"||c.cut.readyState<2);const bar2=c.stage.querySelector(".bm-tk-ctxbar");if(bar2)bar2.hidden=!context}drawProgress()};const pauseAll=()=>{for(const v of allVideos())v.pause();playing=false;paintPlay()};const seekTo=at=>{const s=span();let ph="take";let t=at;if(context&&at<s.before){ph="before";t=(o.before?.start??0)+at}else if(context&&at>s.before+s.take){ph="after";t=(o.after?.start??0)+(at-s.before-s.take)}else{t=Math.max(0,at-s.before)}if(ph!==phase){phase=ph;paintPhase()}const ratio=ph==="take"?Math.min(1,Math.max(0,t/Math.max(.01,s.take))):0;for(const c of cells.values()){const v=videoOf(c);if(!v)continue;const want=ph==="take"?ratio*lenOf(c.takeId):t;try{v.currentTime=Math.max(0,Math.min(want,Math.max(.02,(v.duration||want+1)-.03)))}catch{}}drawProgress();o.onFocus()};const playFrom=ph=>{phase=ph;const s=span();if(ph==="before")seekTo(0);else if(ph==="after")seekTo(s.before+s.take);else seekTo(s.before);paintPhase();for(const c of cells.values()){const v=videoOf(c);if(!v||v.dataset.off==="true")continue;void v.play()?.catch(()=>{v.muted=true;void v.play()?.catch(()=>void 0)})}playing=true;paintPlay()};const play=()=>{const first=context&&o.before?"before":"take";playFrom(first)};const togglePlay=()=>{if(playing)pauseAll();else play()};const master=()=>{const c=cells.get(focusId)??[...cells.values()][0];return c?videoOf(c):null};const advance=()=>{const ph=phaseOf();if(ph==="before")return playFrom("take");if(ph==="take"){if(afterLen()>0)return playFrom("after");if(!loop)return pauseAll();return playFrom(o.before?"before":"take")}if(!loop)return pauseAll();return playFrom(o.before?"before":"take")};const tick=()=>{if(!alive)return;const m=master();if(!m)return;const ph=phaseOf();if(playing){const ratio=ph==="take"?Math.min(1,Math.max(0,m.currentTime/Math.max(.01,m.duration||cutDur))):0;for(const c of cells.values()){const v=videoOf(c);if(!v||v===m||v.dataset.off==="true"||v.paused)continue;const want=ph==="take"?ratio*lenOf(c.takeId):m.currentTime;if(Math.abs(v.currentTime-want)>.18){try{v.currentTime=want}catch{}}}const end=ph==="before"?o.before?.end??0:ph==="take"?Math.min(m.duration||cutDur,Number.POSITIVE_INFINITY):o.after?.end??0;if(m.currentTime>=end-.04||m.ended)return advance()}drawProgress();const at=Math.round(localSeconds()*10);if(at!==lastFocusTick){lastFocusTick=at;o.onFocus()}};let lastFocusTick=-1;const startTimer=()=>{if(timer!==void 0)return;timer=setInterval(tick,120)};const aspect=aspectOf(o.format);const buildCell=takeId=>{const take=takeOf(takeId);const i=takeIndex(shot,takeId);const item=doc.createElement("div");item.className="bm-tk-item";const stage=doc.createElement("div");stage.className="bm-tk-stage";stage.style.aspectRatio=aspect;stage.dataset.letter=takeLetter(i);const img=doc.createElement("img");img.alt="";const spk=doc.createElement("span");spk.className="bm-tk-spk";spk.dataset.on="false";spk.innerHTML=ICONS.muted;const ctxbar=doc.createElement("span");ctxbar.className="bm-tk-ctxbar";ctxbar.hidden=true;const bBefore=doc.createElement("i");const bTake=doc.createElement("b");const bAfter=doc.createElement("i");const total=beforeLen()+(take?.duration??cutDur)+afterLen();bBefore.style.width=total>0?pct(beforeLen()/total):"0";bAfter.style.width=total>0?pct(afterLen()/total):"0";ctxbar.append(bBefore,bTake,bAfter);const mark=doc.createElement("div");mark.className="bm-tk-mark";stage.append(img,spk,ctxbar,mark);item.append(stage);if(take?.image){void o.url(take.image).then(u=>{if(u&&alive)img.src=u})}let clip=null;if(take?.clip){clip=doc.createElement("video");clip.preload="auto";clip.playsInline=true;clip.muted=takeId!==focusId;clip.dataset.off="true";clip.addEventListener("loadeddata",paintPhase);clip.addEventListener("seeked",paintPhase);clip.addEventListener("loadedmetadata",()=>{if(clip&&clip.currentTime===0)clip.currentTime=.001;if(takeId===focusId)drawProgress()});void o.url(take.clip).then(u=>{if(!u||!alive||!clip)return;clip.src=u});stage.append(clip)}stage.addEventListener("click",()=>focusOn(takeId));let cut=null;if(hasCtx){cut=doc.createElement("video");cut.preload="auto";cut.playsInline=true;cut.muted=true;cut.dataset.off="true";cut.addEventListener("loadeddata",paintPhase);cut.addEventListener("seeked",paintPhase);void o.url(o.cutPath).then(u=>{if(u&&alive&&cut)cut.src=u});stage.append(cut)}const card=doc.createElement("div");card.className="bm-tk-card";item.append(card);cells.set(takeId,{takeId,stage,img,clip,cut,card,spk,item,mark});bindMark(mark,takeId);return item};const focusOn=takeId=>{focusId=takeId;setSpeakers();paintSel();if(abMode())layoutAB();paintMobilePick();paintDots();drawProgress();o.onFocus()};const bindMark=(layer,takeId)=>{let gesture=null;const draft=doc.createElement("div");draft.className="bm-tk-mark bm-tk-draft";layer.parentElement?.append(draft);const local=e=>{const r=layer.getBoundingClientRect();return{x:e.clientX-r.left,y:e.clientY-r.top}};layer.addEventListener("pointerdown",e=>{if(!o.marking()||takeId!==focusId)return;if(e.pointerType==="mouse"&&e.button!==0)return;if(clipOf(takeId)===null)return;pauseAll();layer.setPointerCapture?.(e.pointerId);gesture={id:e.pointerId,...local(e),moved:false}});layer.addEventListener("pointermove",e=>{if(!gesture||gesture.id!==e.pointerId)return;const at=local(e);if(!gesture.moved&&Math.hypot(at.x-gesture.x,at.y-gesture.y)<4)return;gesture.moved=true;const x0=Math.min(gesture.x,at.x);const y0=Math.min(gesture.y,at.y);draft.style.display="block";draft.style.left=px(x0);draft.style.top=px(y0);draft.style.width=px(Math.abs(at.x-gesture.x));draft.style.height=px(Math.abs(at.y-gesture.y))});const finish=(e,commit)=>{const g=gesture;if(!g||g.id!==e.pointerId)return;gesture=null;draft.style.display="none";if(!commit||takeId!==focusId)return;const r=layer.getBoundingClientRect();const at=local(e);const rect=g.moved?unitRectOf({left:r.left,top:r.top,width:r.width,height:r.height},{x:r.left+g.x,y:r.top+g.y},{x:e.clientX,y:e.clientY}):unitRectOf({left:r.left,top:r.top,width:r.width,height:r.height},{x:r.left+at.x,y:r.top+at.y});if(!rect)return;o.onMark(localSeconds(),rect)};layer.addEventListener("pointerup",e=>finish(e,true));layer.addEventListener("pointercancel",e=>finish(e,false))};const paintCards=()=>{const pending=o.pending();const canPick=o.canPick();for(const takeId of takes.map(t=>t.id)){const cell=cells.get(takeId);const take=takeOf(takeId);if(!cell||!take)continue;const inCut=takeId===cutId;const picked=pending?.takeId===takeId;const diff=take.duration-cutDur;cell.card.dataset.picked=String(picked);cell.card.replaceChildren();const l1=doc.createElement("div");l1.className="bm-tk-l1";const name=doc.createElement("b");name.textContent=takeName(shot,takeId);const d=doc.createElement("span");d.className="d";d.append(`${take.duration.toFixed(1)} \u79D2`);if(!inCut){if(Math.abs(diff)<.05)d.append("\uFF08\u4E00\u6837\u957F\uFF09");else{d.append("\uFF08");const em=doc.createElement("em");em.textContent=`${diff>0?"+":""}${diff.toFixed(1)}`;d.append(em,"\uFF09")}}l1.append(name);if(inCut){const tag=doc.createElement("span");tag.className="bm-tk-tag";tag.textContent="\u6210\u7247";l1.append(tag)}if(picked){const tag=doc.createElement("span");tag.className="bm-tk-tag";tag.dataset.kind="picked";tag.textContent="\u5DF2\u9009";l1.append(tag)}l1.append(d);cell.card.append(l1);if(take.note){const note=doc.createElement("p");note.className="bm-tk-note";note.textContent=take.note;cell.card.append(note)}const acts=doc.createElement("div");acts.className="bm-tk-acts";const pc=doc.createElement("span");pc.className="pc";pc.innerHTML=ICONS.comment;pc.append(String(o.comments(takeId)));const g=doc.createElement("span");g.className="grow";acts.append(pc,g);acts.append(moreMenu(takeId,take.clip??null));if(!inCut){if(picked&&pending?.undoable){const hand=doc.createElement("span");hand.className="bm-tk-hand";hand.append("\u5DF2\u4EA4\u7ED9 Rondo \xB7 ");const undo=doc.createElement("button");undo.type="button";undo.textContent="\u64A4\u9500";undo.addEventListener("click",()=>o.onUndo(pending.threadId));hand.append(undo);acts.append(hand)}else if(picked){const wait=doc.createElement("span");wait.className="bm-tk-wait";wait.textContent="\u5DF2\u9009 \xB7 Rondo \u5728\u6362";acts.append(wait)}else if(canPick){const use=doc.createElement("button");use.type="button";use.className="btn sm primary";use.textContent="\u7528\u8FD9\u6761";use.addEventListener("click",()=>o.onPick(takeId));acts.append(use)}}cell.card.append(acts)}paintMobilePick()};const moreMenu=(takeId,clip)=>{const more=doc.createElement("span");more.className="bm-tk-more";const btn=doc.createElement("button");btn.type="button";btn.className="ib sm";btn.setAttribute("aria-label","\u66F4\u591A\uFF1A\u5BF9\u8FD9\u6761\u8BC4\u8BBA\u3001\u4E0B\u8F7D\u7247\u6BB5");btn.title="\u5BF9\u8FD9\u6761\u8BC4\u8BBA \xB7 \u4E0B\u8F7D\u7247\u6BB5";btn.innerHTML=ICONS.more;btn.setAttribute("aria-haspopup","menu");btn.setAttribute("aria-expanded","false");const menu=doc.createElement("div");menu.className="bm-tk-menu";menu.setAttribute("role","menu");menu.hidden=true;const cmt=doc.createElement("button");cmt.type="button";cmt.setAttribute("role","menuitem");cmt.textContent="\u5BF9\u8FD9\u6761\u8BC4\u8BBA";cmt.addEventListener("click",()=>{menu.hidden=true;btn.setAttribute("aria-expanded","false");o.onComment(takeId)});menu.append(cmt);if(clip){const dl=doc.createElement("button");dl.type="button";dl.setAttribute("role","menuitem");dl.textContent="\u4E0B\u8F7D\u7247\u6BB5";dl.addEventListener("click",()=>{menu.hidden=true;btn.setAttribute("aria-expanded","false");void o.url(clip).then(u=>{if(!u)return;const a=doc.createElement("a");a.href=u;a.download=clip.split("/").pop()??"take.mp4";a.click()})});menu.append(dl)}btn.addEventListener("click",()=>{const open=menu.hidden;menu.hidden=!open;btn.setAttribute("aria-expanded",String(open))});more.append(btn,menu);return more};const paintMobilePick=()=>{if(!narrow()){mPick.remove();return}const pending=o.pending();const inCut=focusId===cutId;const picked=pending?.takeId===focusId;mCount.replaceChildren();mCount.innerHTML=ICONS.comment;mCount.append(` \u610F\u89C1 ${o.comments(focusId)}`);mPick.replaceChildren();if(inCut||!o.canPick()){mPick.remove();return}mbar.append(mPick);if(picked&&pending?.undoable){mPick.textContent="\u64A4\u9500";mPick.disabled=false;mPick.onclick=()=>o.onUndo(pending.threadId)}else if(picked){mPick.textContent="\u5DF2\u9009 \xB7 Rondo \u5728\u6362";mPick.disabled=true;mPick.onclick=null}else{mPick.textContent="\u7528\u8FD9\u6761";mPick.disabled=false;mPick.onclick=()=>o.onPick(focusId)}};const paintSel=()=>{const on=abMode();for(const[id,c]of cells)c.stage.dataset.sel=String(id===focusId&&on)};const layoutSide=()=>{for(const t of takes){const c=cells.get(t.id);if(!c)continue;if(c.stage.parentElement!==c.item)c.item.prepend(c.stage);if(c.card.parentElement!==c.item)c.item.append(c.card)}grid.replaceChildren(...takes.map(t=>cells.get(t.id)?.item).filter(Boolean));el.append(dots,ctl,prog,hint,mbar)};const layoutAB=()=>{const cell=cells.get(focusId);if(!cell)return;for(const c of cells.values())if(c!==cell)c.stage.remove();abMain.replaceChildren(cell.stage);const pick=doc.createElement("div");pick.className="bm-tk-pick";pick.setAttribute("role","group");pick.setAttribute("aria-label","\u5207\u6362\u5019\u9009");for(const t of takes){const b=doc.createElement("button");b.type="button";b.textContent=`${takeLetter(takeIndex(shot,t.id))}${t.id===cutId?" \xB7 \u6210\u7247":""}`;b.setAttribute("aria-pressed",String(t.id===focusId));b.addEventListener("click",()=>focusOn(t.id));pick.append(b)}const tip=doc.createElement("span");tip.className="bm-tk-hint";tip.textContent="\u6309\u5404\u81EA\u65F6\u957F\u7684\u6BD4\u4F8B\u5BF9\u4F4D\u7F6E";pick.append(tip);abMain.append(pick);abMain.append(dots,ctl,prog,hint);for(const t of takes){const c=cells.get(t.id);if(!c||c===cell)continue;if(c.stage.parentElement!==c.item)c.item.prepend(c.stage)}abSide.replaceChildren(...takes.map(t=>cells.get(t.id)?.card).filter(Boolean));paintSel()};const abMode=()=>{if(narrow()||mode==="ab")return true;const w=el.clientWidth||el.getBoundingClientRect().width||0;return!(w>0&&w/Math.max(1,takes.length)>=220)};const layout=()=>{const phone=narrow();el.dataset.narrow=String(phone);mbar.hidden=!phone;hint.hidden=phone;const w=el.clientWidth||el.getBoundingClientRect().width||0;const fits=w>0&&w/Math.max(1,takes.length)>=220;const useAB=abMode();grid.hidden=useAB;ab.hidden=!useAB;sideBtn.setAttribute("aria-pressed",String(!useAB));abBtn.setAttribute("aria-pressed",String(useAB));sideBtn.disabled=!fits||phone;sideBtn.title=sideBtn.disabled?"\u8FD9\u4E00\u5757\u653E\u4E0D\u4E0B\u51E0\u6761\u5E76\u6392\uFF0C\u7528 A/B \u5207\u6362\u770B":"\u51E0\u6761\u5019\u9009\u5E76\u6392";if(useAB)layoutAB();else layoutSide();paintSel();paintDots()};const paintDots=()=>{const i=takeIndex(shot,focusId);const phone=narrow();dots.hidden=!phone;if(!phone){dots.replaceChildren();return}dots.replaceChildren(...takes.map((t,k)=>{const d=doc.createElement("i");d.dataset.on=String(k===i);return d}));const label=doc.createElement("span");label.className="bm-tk-dotlabel";label.textContent=`${takeName(shot,focusId)} ${i+1}/${takes.length}`;dots.append(label);const swipe2=doc.createElement("span");swipe2.className="bm-tk-swipehint";swipe2.textContent="\u5DE6\u53F3\u6ED1\u52A8\u753B\u9762\u6362\u5019\u9009";dots.append(swipe2)};let swipe=null;el.addEventListener("pointerdown",e=>{if(!narrow()||o.marking())return;if(!e.target?.closest?.(".bm-tk-stage"))return;swipe={id:e.pointerId,x:e.clientX}});el.addEventListener("pointerup",e=>{if(!swipe||swipe.id!==e.pointerId)return;const dx=e.clientX-swipe.x;swipe=null;if(Math.abs(dx)<40)return;const next=takes[takeIndex(shot,focusId)+(dx<0?1:-1)];if(next)focusOn(next.id)});const paintMute=()=>{muteBtn.innerHTML=muted?ICONS.muted:ICONS.volume;muteBtn.setAttribute("aria-label",muted?"\u53D6\u6D88\u9759\u97F3":"\u9759\u97F3");muteBtn.title=muted?"\u53D6\u6D88\u9759\u97F3":"\u9759\u97F3";muteBtn.setAttribute("aria-pressed",String(muted))};for(const t of takes)buildCell(t.id);setSpeakers();paintCards();layout();paintPhase();paintPlay();drawProgress();paintMute();const ro=typeof ResizeObserver==="undefined"?null:new ResizeObserver(()=>{if(!alive)return;layout();drawProgress()});ro?.observe(el);startTimer();playBtn.addEventListener("click",()=>togglePlay());loopBtn.addEventListener("click",()=>{loop=!loop;loopBtn.setAttribute("aria-pressed",String(loop))});muteBtn.addEventListener("click",()=>{muted=!muted;setSpeakers();paintMute()});sideBtn.addEventListener("click",()=>{mode="side";layout()});abBtn.addEventListener("click",()=>{mode="ab";layout()});ctxBtn.addEventListener("click",()=>{context=!context;ctxBtn.setAttribute("aria-pressed",String(context));if(!context){phase="take";paintPhase()}else if(playing){playFrom(o.before?"before":"take")}else{paintPhase();seekTo(beforeLen())}});const seekAt=clientX=>{const r=prog.getBoundingClientRect();if(r.width===0)return;const p=Math.min(1,Math.max(0,(clientX-r.left)/r.width));seekTo(p*spanTotal())};prog.addEventListener("pointerdown",e=>{if(e.pointerType==="mouse"&&e.button!==0)return;dragging=e.pointerId;prog.setPointerCapture?.(e.pointerId);seekAt(e.clientX)});prog.addEventListener("pointermove",e=>{if(dragging===e.pointerId)seekAt(e.clientX)});prog.addEventListener("pointerup",()=>{dragging=null});prog.addEventListener("pointercancel",()=>{dragging=null});return{el,focus:()=>{const clip=clipOf(focusId);if(!clip)return null;return{takeId:focusId,seconds:localSeconds(),path:clip}},refresh:()=>{paintCards();drawProgress()},relayout:()=>{el.dataset.marking=String(o.marking());layout()},dispose:()=>{alive=false;if(timer!==void 0)clearInterval(timer);ro?.disconnect();for(const v of allVideos()){v.pause();v.removeAttribute("src")}el.remove()}}}function neighborsOf(shots,shotId){const i=shots.findIndex(s=>s.id===shotId);if(i<0)return{};const prev=shots[i-1];const next=shots[i+1];return{...prev?{before:{start:Math.max(prev.start,prev.end-1),end:prev.end}}:{},...next?{after:{start:next.start,end:Math.min(next.end,next.start+1)}}:{}}}var PLAY_WRITE_MS=250;var MENU_RATES=[.5,1,1.5,2];var MIN_FRAME_PX=240;var BAR_SHOW_MS=3e3;var COMMENT_DRAG_PX=6;var COMMENT_BOX_PX=144;var TIGHT_STAGE_PX=280;var BOX_ROOM_MIN_HEIGHT_PX=600;var BOX_NARROW_QUERY=NARROW_QUERY;var LONG_PRESS_MS=500;var LONG_PRESS_SLOP_PX=10;var MIN_RANGE_S=.1;var FIRST_SCREEN_VAR="--band-review-first-screen";var STYLE=`
|
|
122
122
|
.bm-root { display: flex; flex-direction: column; gap: 8px; padding: 8px; min-width: 0; min-height: 0; overflow: auto; }
|
|
123
123
|
/* \u5BBF\u4E3B\u7ED9\u7684\u9996\u5C4F\u5269\u4F59\u9AD8\u5EA6\uFF08FIRST_SCREEN_VAR\uFF09\uFF1A\u91CF\u8FD9\u4E2A\u63A2\u9488\u7684\u9AD8\uFF0C\u53D8\u4E86 ResizeObserver \u91CD\u6392 */
|
|
124
124
|
.bm-firstscreen { position: absolute; width: 0; height: var(${FIRST_SCREEN_VAR}, 0px); visibility: hidden; pointer-events: none; }
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kanyun-ai-infra/band-viewer-media",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.8",
|
|
4
4
|
"description": "音频与视频,按时间点提意见,逐帧对齐",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
},
|
|
9
9
|
"peerDependencies": {
|
|
10
10
|
"@kanyun-ai-infra/band-native": "*",
|
|
11
|
-
"@kanyun-ai-infra/band-plugin-sdk": "^1.
|
|
11
|
+
"@kanyun-ai-infra/band-plugin-sdk": "^1.222.0",
|
|
12
12
|
"@kanyun-ai-infra/band-project": "*"
|
|
13
13
|
},
|
|
14
14
|
"peerDependenciesMeta": {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{relocateFileAnchor,relocateShot}from"../chunks/chunk-Z47EOZYW.js";import"../chunks/chunk-JFPQMFKF.js";import{SHOT_LIST_PATH,shotAnchorOf as shotAnchorOf2,shotFacts}from"@kanyun-ai-infra/band-contracts";import{isForbidden as isForbidden2}from"@kanyun-ai-infra/band-plugin-react/errors";import{scrollIntoPanel}from"@kanyun-ai-infra/band-plugin-react/scroll";import{EVENT_GROUPS,definePlugin,withImeGuard}from"@kanyun-ai-infra/band-plugin-sdk";import{parseShotList as parseContractShotList}from"@kanyun-ai-infra/band-contracts";var STORYBOARD_FILE="storyboard.json";var STORYBOARD_MD="storyboard.md";var NARRATION_FILE="narration.json";var isObj=v=>typeof v==="object"&&v!==null&&!Array.isArray(v);var str=v=>typeof v==="string"&&v.length>0;function parseShotList(text){return parseContractShotList(text)}async function readShotList(read){try{return parseShotList(new TextDecoder().decode(await read(STORYBOARD_FILE)))}catch{return null}}function narrationByShot(text){const out=new Map;let raw;try{raw=JSON.parse(text)}catch{return out}if(!isObj(raw)||!isObj(raw.frames))return out;for(const[id,cues]of Object.entries(raw.frames)){if(!Array.isArray(cues))continue;const lines=cues.flatMap(c=>isObj(c)&&str(c.text)?[c.text.trim()]:[]);if(lines.length===0)continue;out.set(id,lines.reduce((acc,line)=>acc===""?line:/[,。!?、,.!?;;::]$/.test(acc)?acc+line:`${acc}\uFF0C${line}`,""))}return out}function cells(line){const body=line.trim().replace(/^\|/,"").replace(/\|$/,"");return body.split(/(?<!\\)\|/).map(c=>c.trim().replace(/\\\|/g,"|"))}function summaryByShot(md){const out=new Map;const lines=md.split(/\r?\n/);for(let i=0;i<lines.length-1;i++){const head=lines[i]??"";if(!head.trim().startsWith("|")||!/^\s*\|?\s*:?-{3,}/.test(lines[i+1]??""))continue;const cols=cells(head);const shotCol=cols.indexOf("\u955C\u5934");const picCol=cols.indexOf("\u753B\u9762");if(shotCol===-1||picCol===-1)continue;for(const line of lines.slice(i+2)){if(!line.trim().startsWith("|"))break;const row=cells(line);const id=row[shotCol]?.split(/\s+/)[0];const pic=row[picCol];if(id&&pic)out.set(id,pic)}break}return out}var sec=n=>n.toFixed(1);function formatLabel(format){const m=format?/^(\d+)x(\d+)$/.exec(format):null;if(!m)return null;const w=Number(m[1]);const h=Number(m[2]);return`${w}\xD7${h} ${h>w?"\u7AD6\u5C4F":w>h?"\u6A2A\u5C4F":"\u65B9\u5F62"}`}function summaryLine(list){const fmt=formatLabel(list.format);return[`${list.shots.length} \u4E2A\u955C\u5934`,`${sec(list.duration)} \u79D2`,...fmt?[fmt]:[]].join(" \xB7 ")}function isPortrait(format){const m=format?/^(\d+)x(\d+)$/.exec(format):null;return m?Number(m[2])>=Number(m[1]):true}function diffShots(before,after){const prev=new Map(before.map(r=>[r.shot.id,r]));const next=new Set(after.map(r=>r.shot.id));const out=[];const removedAfter=new Map;let anchor=null;for(const r of before){if(next.has(r.shot.id))anchor=r.shot.id;else removedAfter.set(anchor,[...removedAfter.get(anchor)??[],r])}const pushRemoved=key=>{for(const r of removedAfter.get(key)??[]){out.push({id:r.shot.id,kind:"removed",changes:[],before:r})}};pushRemoved(null);for(const r of after){const old=prev.get(r.shot.id);if(!old){out.push({id:r.shot.id,kind:"added",changes:[],after:r});continue}const changes=[];if(old.shot.start!==r.shot.start||old.shot.end!==r.shot.end)changes.push("\u65F6\u957F");if(old.image!==r.image||(old.summary??r.shot.summary)!==(r.summary??r.shot.summary)){changes.push("\u753B\u9762")}if((old.narration??"")!==(r.narration??""))changes.push("\u65C1\u767D");out.push({id:r.shot.id,kind:changes.length>0?"changed":"same",changes,before:old,after:r});pushRemoved(r.shot.id)}return out}var hasShots=v=>v.entries.some(e=>e.path===STORYBOARD_FILE);function ownersOf(inputs){const owners=new Set;for(const id of inputs){const at=id.lastIndexOf("@");if(at<=0)return null;owners.add(id.slice(0,at))}return[...owners]}async function storyboardFor(ctx,current){if(!current)return null;const read=async v=>{const list=await readShotList(p=>ctx.version.readFile(p,{versionId:v.id}));return list?{version:v,list,shots:list.shots}:null};if(hasShots(current))return read(current);const inputs=[...current.provenance].reverse().flatMap(p=>p.inputs);if(inputs.length===0)return null;const owners=ownersOf(inputs)??(await ctx.artifacts.list()).map(a=>a.id);const lists=await Promise.all(owners.filter(id=>id!==current.artifactId).map(id=>ctx.version.list(id)));const found=new Map;for(const v of lists.flat()){if(inputs.includes(v.id)&&hasShots(v))found.set(v.id,v)}const hit=inputs.map(id=>found.get(id)).find(v=>v!==void 0);return hit?read(hit):null}function imageOf(shot,version){const images=version.entries.filter(e=>e.mime.startsWith("image/"));if(shot.image&&images.some(e=>e.path===shot.image))return shot.image;const base=p=>(p.split("/").pop()??p).replace(/\.[^.]+$/,"");return images.find(e=>base(e.path)===shot.id)?.path??null}function mediaPathOf(version){return version.entries.find(e=>e.mime.startsWith("video/")||e.mime.startsWith("audio/"))?.path??null}function shotLabel(shots,seconds){const shot=shotAt(shots,seconds);return shot?`${shots.indexOf(shot)+1} / ${shots.length} ${shot.title}`:""}function shotAt(shots,seconds){return shots.find(s=>seconds>=s.start&&seconds<s.end)}function shotOf(shots,sel){if(!sel)return null;if(sel.kind==="entity")return sel.entityType==="shot"?sel.id:null;if(sel.kind==="timecode")return shotAt(shots,sel.seconds)?.id??null;return null}function localTime(iso){const t=new Date(iso);if(Number.isNaN(t.getTime()))return"";const two=n=>String(n).padStart(2,"0");return`${two(t.getMonth()+1)}-${two(t.getDate())} ${two(t.getHours())}:${two(t.getMinutes())}`}var groups=new Map;function joinComparison(projectId,peer){const key=JSON.stringify([projectId,peer.version.artifactId]);const peers=groups.get(key)??new Set;groups.set(key,peers);peers.add(peer);const update=()=>{for(const self of peers){const other=[...peers].find(p=>p!==self&&p.version.id!==self.version.id);if(!other){self.draw(null,"after");continue}const newer=self.version.createdAt>other.version.createdAt;self.draw(diffShots(newer?other.rows:self.rows,newer?self.rows:other.rows),newer?"after":"before")}};update();return()=>{peers.delete(peer);if(!peers.size)groups.delete(key);update()}}import{shotAnchorOf}from"@kanyun-ai-infra/band-contracts";import{createImageLightbox}from"@kanyun-ai-infra/band-plugin-react/image-view";import{unitRectFrom}from"@kanyun-ai-infra/band-plugin-react/image-view";import{FIT,unitRectOf,LIGHTBOX_MAX_SCALE,LIGHTBOX_DRAG_PX,lightboxSize,lightboxClamp,lightboxZoom,focusRegion,nextImage}from"@kanyun-ai-infra/band-plugin-react/image-view";function regionShot(anchor,shots,version){const rect=unitRectFrom(anchor.payload.rect);const path=anchor.payload.path;if(!rect||anchor.kind!=="region"||typeof path!=="string")return null;const region={path,rect};if(anchor.snapshot&&anchor.snapshot.length<=4096&&anchor.snapshot.startsWith("{")){try{const hint=JSON.parse(anchor.snapshot);if(hint&&typeof hint==="object"&&"viewer"in hint&&hint.viewer==="storyboard"&&"shotId"in hint&&typeof hint.shotId==="string"){const index2=shots.findIndex(shot=>shot.id===hint.shotId&&imageOf(shot,version)===path);if(index2>=0)return{...region,index:index2}}}catch{}}const index=shots.findIndex(shot=>imageOf(shot,version)===region.path);return index<0?null:{...region,index}}import{reactMount}from"@kanyun-ai-infra/band-plugin-react";import{ErrorNote,InfoNote}from"@kanyun-ai-infra/band-plugin-react/components";import{failedBecause,isForbidden}from"@kanyun-ai-infra/band-plugin-react/errors";function threadReadError(host,error,retry){return reactMount(()=>isForbidden(error)?InfoNote({children:"\u6CA1\u6709\u6743\u9650\u67E5\u770B\u672C\u955C\u610F\u89C1\uFF0C\u8BF7\u8054\u7CFB\u9879\u76EE\u7BA1\u7406\u5458\u3002"}):ErrorNote({children:`\u610F\u89C1\u6CA1\u8BFB\u51FA\u6765\uFF1A${failedBecause(error,"\u70B9\u91CD\u8BD5")}`,retry}))(void 0,host,void 0)}import{LIGHTBOX_STYLE,lightboxIcon}from"@kanyun-ai-infra/band-plugin-react/image-view";function createShotLightbox(ctx,root,frame,options){const doc=root.ownerDocument;const el=(tag,cls,text)=>{const node=doc.createElement(tag);if(cls)node.className=cls;if(text!==void 0)node.textContent=text;return node};const narrow=()=>(doc.defaultView?.innerWidth??1440)<=600;const clock=seconds=>`${Math.floor(seconds/60)}:${sec(seconds%60).padStart(4,"0")}`;const duration=seconds=>String(Number(sec(seconds)));let threads=[];let threadError=null;let offThreadError;const clearThreadError=()=>{offThreadError?.();offThreadError=void 0;threadError=null};const drawSide=(side,index)=>{const b=options.board();const shot=options.board()?.shots[index];const row=options.rows()[index];if(!b||!shot)return;side.replaceChildren();const heading=el("h3",void 0,`\u955C\u5934 ${index+1}`);heading.append(el("span",void 0,`${duration(shot.end-shot.start)}s \xB7 ${clock(shot.start)}\u2013${clock(shot.end)}`));side.append(heading);const versionNote=options.versionNote();if(versionNote)side.append(el("p","bs-lb-hint",versionNote));const dl=el("dl");for(const[name,text]of[["\u6807\u9898",shot.title],["\u753B\u9762",row?.summary??"\u6CA1\u6709\u753B\u9762\u8BF4\u660E"],["\u65C1\u767D",row?.narration??"\u6CA1\u6709\u65C1\u767D"],["\u9759\u5E27",imageOf(shot,b.version)??"\u6CA1\u6709\u9759\u5E27"]]){dl.append(el("dt",void 0,name),el("dd",name==="\u9759\u5E27"?"bs-lb-path":void 0,text))}side.append(dl);const related=threads.filter(t=>regionShot(t.anchor,b.shots,b.version)?.index===index||shotAnchorOf(t.anchor)?.shotId===shot.id);side.append(el("div","bs-lb-cm-head",threadError?"\u672C\u955C\u610F\u89C1 \xB7 \u8BFB\u53D6\u5931\u8D25":`\u672C\u955C\u610F\u89C1 \xB7 ${related.length}`));if(threadError)side.append(threadError);for(const t of related){const button=el("button","bs-lb-cm");button.type="button";button.append(el("span",void 0,`#${t.mark}`),el("span","bs-lb-excerpt",`${t.anchor.kind==="region"?"\u9759\u5E27":"\u6574\u4E2A\u955C\u5934"} \xB7 ${t.excerpt}`));button.addEventListener("click",()=>{if(options.canComment())ctx.anchors.annotating.set(true);ctx.threads.open(t.id)});side.append(button)}side.append(el("p","bs-lb-hint",narrow()?"\u53EF\u53CC\u6307\u7F29\u653E\u3001\u62D6\u52A8\u67E5\u770B\u9759\u5E27\u3002\u624B\u673A\u6682\u4E0D\u652F\u6301\u5927\u56FE\u6807\u6CE8\u3002":options.canComment()?"\u6309 C \u6216\u70B9\u4EA7\u7269\u9876\u680F\u7684\u8BC4\u8BBA\u6C14\u6CE1\uFF0C\u5C31\u80FD\u5728\u5927\u56FE\u4E0A\u70B9\u4E00\u4E0B\u6216\u6846\u4E00\u5757\u5199\u610F\u89C1\u3002":"\u5F53\u524D\u53EA\u8BFB\uFF0C\u53EF\u67E5\u770B\u5DF2\u6709\u610F\u89C1\u3002"))};const lightbox=createImageLightbox(ctx,root,frame,{items:()=>{const b=options.board();return b?.shots.map((shot,i)=>({title:shot.title,alt:`\u955C\u5934 ${i+1} \xB7 ${shot.title}`,path:imageOf(shot,b.version)}))??[]},imageUrl:options.imageUrl,canComment:options.canComment,region:anchor=>{const b=options.board();return b?regionShot(anchor,b.shots,b.version):null},makeAnchor(index,rect){const b=options.board();const shot=b?.shots[index];const path=b&&shot?imageOf(shot,b.version):null;if(!path||!shot)return null;const note=options.versionNote();const label=`\u955C\u5934 ${index+1} \u9759\u5E27 \xB7 ${rect.w===0&&rect.h===0?"\u4E00\u70B9":"\u4E00\u5757"}${note?` \xB7 ${note}`:""}`;return ctx.anchors.make("region",{path,label,rect},JSON.stringify({viewer:"storyboard",shotId:shot.id}))},changed:options.changed,renderSide:drawSide,heading(index){const b=options.board();const shot=b?.shots[index];return{title:`\u955C\u5934 ${index+1} / ${b?.shots.length} \xB7 ${shot?.title}`,meta:`${duration((shot?.end??0)-(shot?.start??0))}s`}},labels:{layer:"\u5206\u955C\u5927\u56FE",back:"\u8FD4\u56DE\u5206\u955C",stage:"\u9759\u5E27\u821E\u53F0",side:"\u672C\u955C\u4FE1\u606F\u4E0E\u610F\u89C1",strip:"\u955C\u5934\u80F6\u7247\u6761",previous:"\u4E0A\u4E00\u955C",next:"\u4E0B\u4E00\u955C",item:i=>`\u5207\u5230\u955C\u5934 ${i+1}`,error:"\u9759\u5E27\u6CA1\u52A0\u8F7D\u51FA\u6765\uFF0C\u8FD4\u56DE\u5206\u955C\u540E\u91CD\u8BD5\u3002"},notify:options.notify,returned:options.returned});return{open:lightbox.open,locate:lightbox.locate,reveal:lightbox.reveal,setThreads(next){clearThreadError();threads=next;lightbox.setThreads(next)},setThreadsFailure(error,retry){clearThreadError();threadError=el("div");offThreadError=threadReadError(threadError,error,retry);lightbox.refresh()},dispose(){clearThreadError();lightbox.dispose()}}}var STYLE=`
|
|
1
|
+
import{relocateFileAnchor,relocateShot}from"../chunks/chunk-Z47EOZYW.js";import"../chunks/chunk-JFPQMFKF.js";import{SHOT_LIST_PATH,shotAnchorOf as shotAnchorOf2,shotFacts}from"@kanyun-ai-infra/band-contracts";import{isForbidden as isForbidden2}from"@kanyun-ai-infra/band-plugin-react/errors";import{scrollIntoPanel}from"@kanyun-ai-infra/band-plugin-react/scroll";import{EVENT_GROUPS,definePlugin,narrowMedia,withImeGuard}from"@kanyun-ai-infra/band-plugin-sdk";import{parseShotList as parseContractShotList}from"@kanyun-ai-infra/band-contracts";var STORYBOARD_FILE="storyboard.json";var STORYBOARD_MD="storyboard.md";var NARRATION_FILE="narration.json";var isObj=v=>typeof v==="object"&&v!==null&&!Array.isArray(v);var str=v=>typeof v==="string"&&v.length>0;function parseShotList(text){return parseContractShotList(text)}async function readShotList(read){try{return parseShotList(new TextDecoder().decode(await read(STORYBOARD_FILE)))}catch{return null}}function narrationByShot(text){const out=new Map;let raw;try{raw=JSON.parse(text)}catch{return out}if(!isObj(raw)||!isObj(raw.frames))return out;for(const[id,cues]of Object.entries(raw.frames)){if(!Array.isArray(cues))continue;const lines=cues.flatMap(c=>isObj(c)&&str(c.text)?[c.text.trim()]:[]);if(lines.length===0)continue;out.set(id,lines.reduce((acc,line)=>acc===""?line:/[,。!?、,.!?;;::]$/.test(acc)?acc+line:`${acc}\uFF0C${line}`,""))}return out}function cells(line){const body=line.trim().replace(/^\|/,"").replace(/\|$/,"");return body.split(/(?<!\\)\|/).map(c=>c.trim().replace(/\\\|/g,"|"))}function summaryByShot(md){const out=new Map;const lines=md.split(/\r?\n/);for(let i=0;i<lines.length-1;i++){const head=lines[i]??"";if(!head.trim().startsWith("|")||!/^\s*\|?\s*:?-{3,}/.test(lines[i+1]??""))continue;const cols=cells(head);const shotCol=cols.indexOf("\u955C\u5934");const picCol=cols.indexOf("\u753B\u9762");if(shotCol===-1||picCol===-1)continue;for(const line of lines.slice(i+2)){if(!line.trim().startsWith("|"))break;const row=cells(line);const id=row[shotCol]?.split(/\s+/)[0];const pic=row[picCol];if(id&&pic)out.set(id,pic)}break}return out}var sec=n=>n.toFixed(1);function formatLabel(format){const m=format?/^(\d+)x(\d+)$/.exec(format):null;if(!m)return null;const w=Number(m[1]);const h=Number(m[2]);return`${w}\xD7${h} ${h>w?"\u7AD6\u5C4F":w>h?"\u6A2A\u5C4F":"\u65B9\u5F62"}`}function summaryLine(list){const fmt=formatLabel(list.format);return[`${list.shots.length} \u4E2A\u955C\u5934`,`${sec(list.duration)} \u79D2`,...fmt?[fmt]:[]].join(" \xB7 ")}function isPortrait(format){const m=format?/^(\d+)x(\d+)$/.exec(format):null;return m?Number(m[2])>=Number(m[1]):true}function diffShots(before,after){const prev=new Map(before.map(r=>[r.shot.id,r]));const next=new Set(after.map(r=>r.shot.id));const out=[];const removedAfter=new Map;let anchor=null;for(const r of before){if(next.has(r.shot.id))anchor=r.shot.id;else removedAfter.set(anchor,[...removedAfter.get(anchor)??[],r])}const pushRemoved=key=>{for(const r of removedAfter.get(key)??[]){out.push({id:r.shot.id,kind:"removed",changes:[],before:r})}};pushRemoved(null);for(const r of after){const old=prev.get(r.shot.id);if(!old){out.push({id:r.shot.id,kind:"added",changes:[],after:r});continue}const changes=[];if(old.shot.start!==r.shot.start||old.shot.end!==r.shot.end)changes.push("\u65F6\u957F");if(old.image!==r.image||(old.summary??r.shot.summary)!==(r.summary??r.shot.summary)){changes.push("\u753B\u9762")}if((old.narration??"")!==(r.narration??""))changes.push("\u65C1\u767D");out.push({id:r.shot.id,kind:changes.length>0?"changed":"same",changes,before:old,after:r});pushRemoved(r.shot.id)}return out}var hasShots=v=>v.entries.some(e=>e.path===STORYBOARD_FILE);function ownersOf(inputs){const owners=new Set;for(const id of inputs){const at=id.lastIndexOf("@");if(at<=0)return null;owners.add(id.slice(0,at))}return[...owners]}async function storyboardFor(ctx,current){if(!current)return null;const read=async v=>{const list=await readShotList(p=>ctx.version.readFile(p,{versionId:v.id}));return list?{version:v,list,shots:list.shots}:null};if(hasShots(current))return read(current);const inputs=[...current.provenance].reverse().flatMap(p=>p.inputs);if(inputs.length===0)return null;const owners=ownersOf(inputs)??(await ctx.artifacts.list()).map(a=>a.id);const lists=await Promise.all(owners.filter(id=>id!==current.artifactId).map(id=>ctx.version.list(id)));const found=new Map;for(const v of lists.flat()){if(inputs.includes(v.id)&&hasShots(v))found.set(v.id,v)}const hit=inputs.map(id=>found.get(id)).find(v=>v!==void 0);return hit?read(hit):null}function imageOf(shot,version){const images=version.entries.filter(e=>e.mime.startsWith("image/"));if(shot.image&&images.some(e=>e.path===shot.image))return shot.image;const base=p=>(p.split("/").pop()??p).replace(/\.[^.]+$/,"");return images.find(e=>base(e.path)===shot.id)?.path??null}function mediaPathOf(version){return version.entries.find(e=>e.mime.startsWith("video/")||e.mime.startsWith("audio/"))?.path??null}function shotLabel(shots,seconds){const shot=shotAt(shots,seconds);return shot?`${shots.indexOf(shot)+1} / ${shots.length} ${shot.title}`:""}function shotAt(shots,seconds){return shots.find(s=>seconds>=s.start&&seconds<s.end)}function shotOf(shots,sel){if(!sel)return null;if(sel.kind==="entity")return sel.entityType==="shot"?sel.id:null;if(sel.kind==="timecode")return shotAt(shots,sel.seconds)?.id??null;return null}function localTime(iso){const t=new Date(iso);if(Number.isNaN(t.getTime()))return"";const two=n=>String(n).padStart(2,"0");return`${two(t.getMonth()+1)}-${two(t.getDate())} ${two(t.getHours())}:${two(t.getMinutes())}`}var groups=new Map;function joinComparison(projectId,peer){const key=JSON.stringify([projectId,peer.version.artifactId]);const peers=groups.get(key)??new Set;groups.set(key,peers);peers.add(peer);const update=()=>{for(const self of peers){const other=[...peers].find(p=>p!==self&&p.version.id!==self.version.id);if(!other){self.draw(null,"after");continue}const newer=self.version.createdAt>other.version.createdAt;self.draw(diffShots(newer?other.rows:self.rows,newer?self.rows:other.rows),newer?"after":"before")}};update();return()=>{peers.delete(peer);if(!peers.size)groups.delete(key);update()}}import{shotAnchorOf}from"@kanyun-ai-infra/band-contracts";import{createImageLightbox}from"@kanyun-ai-infra/band-plugin-react/image-view";import{unitRectFrom}from"@kanyun-ai-infra/band-plugin-react/image-view";import{FIT,unitRectOf,LIGHTBOX_MAX_SCALE,LIGHTBOX_DRAG_PX,lightboxSize,lightboxClamp,lightboxZoom,focusRegion,nextImage}from"@kanyun-ai-infra/band-plugin-react/image-view";function regionShot(anchor,shots,version){const rect=unitRectFrom(anchor.payload.rect);const path=anchor.payload.path;if(!rect||anchor.kind!=="region"||typeof path!=="string")return null;const region={path,rect};if(anchor.snapshot&&anchor.snapshot.length<=4096&&anchor.snapshot.startsWith("{")){try{const hint=JSON.parse(anchor.snapshot);if(hint&&typeof hint==="object"&&"viewer"in hint&&hint.viewer==="storyboard"&&"shotId"in hint&&typeof hint.shotId==="string"){const index2=shots.findIndex(shot=>shot.id===hint.shotId&&imageOf(shot,version)===path);if(index2>=0)return{...region,index:index2}}}catch{}}const index=shots.findIndex(shot=>imageOf(shot,version)===region.path);return index<0?null:{...region,index}}import{reactMount}from"@kanyun-ai-infra/band-plugin-react";import{ErrorNote,InfoNote}from"@kanyun-ai-infra/band-plugin-react/components";import{failedBecause,isForbidden}from"@kanyun-ai-infra/band-plugin-react/errors";function threadReadError(host,error,retry){return reactMount(()=>isForbidden(error)?InfoNote({children:"\u6CA1\u6709\u6743\u9650\u67E5\u770B\u672C\u955C\u610F\u89C1\uFF0C\u8BF7\u8054\u7CFB\u9879\u76EE\u7BA1\u7406\u5458\u3002"}):ErrorNote({children:`\u610F\u89C1\u6CA1\u8BFB\u51FA\u6765\uFF1A${failedBecause(error,"\u70B9\u91CD\u8BD5")}`,retry}))(void 0,host,void 0)}import{LIGHTBOX_STYLE,lightboxIcon}from"@kanyun-ai-infra/band-plugin-react/image-view";function createShotLightbox(ctx,root,frame,options){const doc=root.ownerDocument;const el=(tag,cls,text)=>{const node=doc.createElement(tag);if(cls)node.className=cls;if(text!==void 0)node.textContent=text;return node};const narrow=()=>(doc.defaultView?.innerWidth??1440)<=600;const clock=seconds=>`${Math.floor(seconds/60)}:${sec(seconds%60).padStart(4,"0")}`;const duration=seconds=>String(Number(sec(seconds)));let threads=[];let threadError=null;let offThreadError;const clearThreadError=()=>{offThreadError?.();offThreadError=void 0;threadError=null};const drawSide=(side,index)=>{const b=options.board();const shot=options.board()?.shots[index];const row=options.rows()[index];if(!b||!shot)return;side.replaceChildren();const heading=el("h3",void 0,`\u955C\u5934 ${index+1}`);heading.append(el("span",void 0,`${duration(shot.end-shot.start)}s \xB7 ${clock(shot.start)}\u2013${clock(shot.end)}`));side.append(heading);const versionNote=options.versionNote();if(versionNote)side.append(el("p","bs-lb-hint",versionNote));const dl=el("dl");for(const[name,text]of[["\u6807\u9898",shot.title],["\u753B\u9762",row?.summary??"\u6CA1\u6709\u753B\u9762\u8BF4\u660E"],["\u65C1\u767D",row?.narration??"\u6CA1\u6709\u65C1\u767D"],["\u9759\u5E27",imageOf(shot,b.version)??"\u6CA1\u6709\u9759\u5E27"]]){dl.append(el("dt",void 0,name),el("dd",name==="\u9759\u5E27"?"bs-lb-path":void 0,text))}side.append(dl);const related=threads.filter(t=>regionShot(t.anchor,b.shots,b.version)?.index===index||shotAnchorOf(t.anchor)?.shotId===shot.id);side.append(el("div","bs-lb-cm-head",threadError?"\u672C\u955C\u610F\u89C1 \xB7 \u8BFB\u53D6\u5931\u8D25":`\u672C\u955C\u610F\u89C1 \xB7 ${related.length}`));if(threadError)side.append(threadError);for(const t of related){const button=el("button","bs-lb-cm");button.type="button";button.append(el("span",void 0,`#${t.mark}`),el("span","bs-lb-excerpt",`${t.anchor.kind==="region"?"\u9759\u5E27":"\u6574\u4E2A\u955C\u5934"} \xB7 ${t.excerpt}`));button.addEventListener("click",()=>{if(options.canComment())ctx.anchors.annotating.set(true);ctx.threads.open(t.id)});side.append(button)}side.append(el("p","bs-lb-hint",narrow()?"\u53EF\u53CC\u6307\u7F29\u653E\u3001\u62D6\u52A8\u67E5\u770B\u9759\u5E27\u3002\u624B\u673A\u6682\u4E0D\u652F\u6301\u5927\u56FE\u6807\u6CE8\u3002":options.canComment()?"\u6309 C \u6216\u70B9\u4EA7\u7269\u9876\u680F\u7684\u8BC4\u8BBA\u6C14\u6CE1\uFF0C\u5C31\u80FD\u5728\u5927\u56FE\u4E0A\u70B9\u4E00\u4E0B\u6216\u6846\u4E00\u5757\u5199\u610F\u89C1\u3002":"\u5F53\u524D\u53EA\u8BFB\uFF0C\u53EF\u67E5\u770B\u5DF2\u6709\u610F\u89C1\u3002"))};const lightbox=createImageLightbox(ctx,root,frame,{items:()=>{const b=options.board();return b?.shots.map((shot,i)=>({title:shot.title,alt:`\u955C\u5934 ${i+1} \xB7 ${shot.title}`,path:imageOf(shot,b.version)}))??[]},imageUrl:options.imageUrl,canComment:options.canComment,region:anchor=>{const b=options.board();return b?regionShot(anchor,b.shots,b.version):null},makeAnchor(index,rect){const b=options.board();const shot=b?.shots[index];const path=b&&shot?imageOf(shot,b.version):null;if(!path||!shot)return null;const note=options.versionNote();const label=`\u955C\u5934 ${index+1} \u9759\u5E27 \xB7 ${rect.w===0&&rect.h===0?"\u4E00\u70B9":"\u4E00\u5757"}${note?` \xB7 ${note}`:""}`;return ctx.anchors.make("region",{path,label,rect},JSON.stringify({viewer:"storyboard",shotId:shot.id}))},changed:options.changed,renderSide:drawSide,heading(index){const b=options.board();const shot=b?.shots[index];return{title:`\u955C\u5934 ${index+1} / ${b?.shots.length} \xB7 ${shot?.title}`,meta:`${duration((shot?.end??0)-(shot?.start??0))}s`}},labels:{layer:"\u5206\u955C\u5927\u56FE",back:"\u8FD4\u56DE\u5206\u955C",stage:"\u9759\u5E27\u821E\u53F0",side:"\u672C\u955C\u4FE1\u606F\u4E0E\u610F\u89C1",strip:"\u955C\u5934\u80F6\u7247\u6761",previous:"\u4E0A\u4E00\u955C",next:"\u4E0B\u4E00\u955C",item:i=>`\u5207\u5230\u955C\u5934 ${i+1}`,error:"\u9759\u5E27\u6CA1\u52A0\u8F7D\u51FA\u6765\uFF0C\u8FD4\u56DE\u5206\u955C\u540E\u91CD\u8BD5\u3002"},notify:options.notify,returned:options.returned});return{open:lightbox.open,locate:lightbox.locate,reveal:lightbox.reveal,setThreads(next){clearThreadError();threads=next;lightbox.setThreads(next)},setThreadsFailure(error,retry){clearThreadError();threadError=el("div");offThreadError=threadReadError(threadError,error,retry);lightbox.refresh()},dispose(){clearThreadError();lightbox.dispose()}}}var STYLE=`
|
|
2
2
|
.bs-root { display: grid; gap: 8px; padding: 12px 16px; min-width: 0; min-height: 0; align-content: start;
|
|
3
3
|
overflow: auto; overscroll-behavior: contain;
|
|
4
4
|
container-type: inline-size; }
|
|
@@ -73,7 +73,7 @@ import{relocateFileAnchor,relocateShot}from"../chunks/chunk-Z47EOZYW.js";import"
|
|
|
73
73
|
.bs-root { padding: 8px; }
|
|
74
74
|
}
|
|
75
75
|
`;async function readText(ctx,v,path){if(!v.entries.some(e=>e.path===path))return null;try{return new TextDecoder().decode(await ctx.version.readFile(path,{versionId:v.id}))}catch{return null}}async function extrasOf(ctx,v){const[md,vo]=await Promise.all([readText(ctx,v,STORYBOARD_MD),readText(ctx,v,NARRATION_FILE)]);return{summary:md?summaryByShot(md):new Map,narration:vo?narrationByShot(vo):new Map}}function rowsOf(board,extras){return board.shots.map(shot=>{const row={shot};const summary=shot.summary??extras.summary.get(shot.id);if(summary)row.summary=summary;const narration=extras.narration.get(shot.id);if(narration)row.narration=narration;const image=imageOf(shot,board.version);const sha=image?board.version.entries.find(e=>e.path===image)?.sha256:void 0;if(sha)row.image=sha;return row})}async function previousOf(ctx,current){try{const all=await ctx.version.list(current.artifactId);const earlier=all.filter(v=>v.id!==current.id&&v.createdAt<current.createdAt&&v.entries.some(e=>e.path==="storyboard.json")).sort((a,b)=>a.createdAt<b.createdAt?1:-1);return earlier[0]??null}catch{return null}}function versionName(v){const at=localTime(v.createdAt);return typeof v.meta?.note==="string"?`${at} \xB7 ${v.meta.note}`:at}function mountShotTable(ctx,root,config={}){const doc=root.ownerDocument;const el=(tag,cls,text)=>{const n=doc.createElement(tag);if(cls)n.className=cls;if(text!==void 0)n.textContent=text;return n};const style=el("style");style.textContent=STYLE+LIGHTBOX_STYLE;const frame=el("div","bs-frame");const view=el("div","bs-root");view.setAttribute("aria-label","\u955C\u5934\u8868");const bar=el("div","bs-bar");const body=el("div");const status=el("div","bs-note");status.setAttribute("role","status");view.append(bar,body,status);frame.append(view);root.append(style,frame);let alive=true;let offComparison;let comparison=null;let board=null;let rows=[];let prev=null;let versions=null;let loaded=false;let prevSettled=false;let settle=()=>void 0;const settled=new Promise(r=>{settle=r});const listeners=new Set;const notify=()=>{for(const fn of listeners)fn()};let mode="table";let comparing=false;let showSame=false;let lit=null;const urls=new Map;let threads=[];const timers=new Set;const imageUrl=(v,path)=>{const key=`${v.id}
|
|
76
|
-
${path}`;let p=urls.get(key);if(!p){p=ctx.version.objectUrl(path,{versionId:v.id});urls.set(key,p);p.catch(()=>urls.delete(key))}return p};const thumb=(shot,v)=>{const path=imageOf(shot,v);if(!path)return null;const img=el("img","bs-thumb");img.alt="";img.loading="lazy";void imageUrl(v,path).then(url=>{if(alive)img.src=url},()=>img.remove());if(config.compare||v.id!==board?.version.id)return img;const button=el("button","bs-picture");button.type="button";const i=board?.shots.findIndex(s=>s.id===shot.id)??-1;button.setAttribute("aria-label",`\u653E\u5927\u955C\u5934 ${i+1} \u9759\u5E27`);const magnify=el("span","bs-magnify");magnify.append(lightboxIcon(doc,"plus"));button.append(img,magnify);const count=threads.filter(t=>board&®ionShot(t.anchor,board.shots,v)?.index===i&&t.status!=="resolved").length;if(count)button.append(el("span","bs-count",String(count)));button.addEventListener("click",e=>{e.stopPropagation();const index=board?.shots.findIndex(s=>s.id===shot.id)??-1;if(index>=0)lightbox.open(index)});return button};const pick=shot=>{if(!board)return;ctx.selection.set({kind:"entity",entityType:"shot",id:shot.id,artifactId:board.version.artifactId})};const selectable=(node,shot)=>{node.dataset.shot=shot.id;node.setAttribute("role","option");node.tabIndex=0;const act=()=>{if(!narrow()&&ctx.anchors.annotating.get()&&canComment()&&!config.compare)commentShot(shot);else pick(shot)};node.addEventListener("click",act);node.addEventListener("keydown",withImeGuard(e=>{if(e.target!==node||e.key!=="Enter"&&e.key!==" ")return;e.preventDefault();act()}))};const heading=(i,shot,time=true)=>{const h=el("h3",void 0,`${i+1} \xB7 ${shot.title}`);if(time){h.append(el("span",void 0,`${sec(shot.start)}\u2013${sec(shot.end)} \u79D2 \xB7 ${sec(shot.end-shot.start)} \u79D2`))}return h};const line=(label,text,none)=>{if(!text)return none?el("p","bs-none",none):null;const p=el("p");p.append(el("b",void 0,label),text);return p};const shotRow=(row,i,v,interactive)=>{const node=el("div","bs-shot");const img=thumb(row.shot,v);const text=el("div","bs-body");text.append(heading(i,row.shot));const pic=line("\u753B\u9762",row.summary);if(pic)text.append(pic);const vo=line("\u65C1\u767D",row.narration,"\u6CA1\u6709\u65C1\u767D");if(vo)text.append(vo);node.append(img??el("span"),text);if(interactive)selectable(node,row.shot);return node};const highlight=()=>{const picked=shotOf(board?.shots??[],ctx.selection.get());for(const node of body.querySelectorAll("[data-shot]")){const on=node.dataset.shot===picked;node.setAttribute("aria-selected",String(on));if(on&&picked!==lit)scrollIntoPanel(node,{block:"nearest"})}lit=picked};const canComment=()=>!config.compare&&ctx.member.can("comment")&&board!==null&&ctx.version.current()?.id===board.version.id;const lightbox=createShotLightbox(ctx,root,frame,{board:()=>board,rows:()=>rows,canComment,changed(anchor,path){if(!board||!versions||anchor.versionId===board.version.id)return false;const before=versions.find(v=>v.id===anchor.versionId);if(!before||before.createdAt>board.version.createdAt)return false;return relocateFileAnchor({},{before:before.entries.find(e=>e.path===path)?.sha256??null,after:board.version.entries.find(e=>e.path===path)?.sha256??null})==="changed"},versionNote(){const shown=board;if(!shown||!versions)return null;const index=versions.findIndex(v=>v.id===shown.version.id);return index>=0&&index<versions.length-1?`\u6302\u5728 v${index+1}\uFF08\u5386\u53F2\u7248\u672C\uFF09`:null},imageUrl:path=>board?imageUrl(board.version,path):Promise.reject(new Error("\u6CA1\u6709\u5206\u955C")),notify,returned(index){const shot=board?.shots[index];const row=shot?rowOf(shot.id):void 0;if(!row)return;scrollIntoPanel(row,{block:"nearest"});row.classList.add("bs-returned");(row.querySelector(".bs-picture")??row).focus({preventScroll:true});const timer=setTimeout(()=>{row.classList.remove("bs-returned");timers.delete(timer)},1400);timers.add(timer)}});const narrowMq=typeof window.matchMedia==="function"?window.matchMedia("(pointer: coarse), (max-width: 599px)"):void 0;const narrow=()=>narrowMq?.matches===true;const commentShot=shot=>{const i=rows.findIndex(r=>r.shot.id===shot.id);const label=`\u955C\u5934 ${i+1} \xB7 ${shot.title}`;ctx.threads.openAt(ctx.anchors.make("shot",{path:SHOT_LIST_PATH,label,shotId:shot.id},shot.title))};const addButton=(shot,i)=>{const add=el("button","bs-add","+");add.type="button";add.setAttribute("aria-label",`\u5BF9\u955C\u5934 ${i+1} \u8BC4\u8BBA`);add.title="\u5BF9\u8FD9\u4E2A\u955C\u5934\u8BC4\u8BBA";add.disabled=!canComment();add.addEventListener("click",e=>{e.stopPropagation();if(canComment())commentShot(shot)});return add};const drawTable=()=>{if(!board)return;const list=el("div","bs-list");list.setAttribute("role","listbox");list.setAttribute("aria-label","\u955C\u5934");const visible=comparison?.diffs??rows.map(row=>({id:row.shot.id,kind:"same",changes:[],before:row,after:row}));for(const diff of visible){const row=comparison?.side==="before"?diff.before:diff.after;if(!row){const gap=el("div","bs-gap",comparison?.side==="before"?"\u4E0A\u4E00\u7248\u6CA1\u6709\u8FD9\u4E2A\u955C\u5934":"\u8FD9\u4E00\u7248\u5220\u6389\u4E86\u8FD9\u4E2A\u955C\u5934");list.append(gap);continue}const i=rows.findIndex(r=>r.shot.id===row.shot.id);const node=shotRow(row,i,board.version,true);node.dataset.shot=row.shot.id;if(comparison)node.querySelector(".bs-body")?.append(tags(diff));if(narrow()&&!config.compare)node.append(addButton(row.shot,i));list.append(node)}body.replaceChildren(list)};const rowOf=shotId=>[...body.querySelectorAll("[data-shot]")].find(n=>n.dataset.shot===shotId&&n.dataset.side!=="before");const locate=anchor=>{if(anchor.kind==="region")return loaded?board?lightbox.locate(anchor):{at:"none"}:{at:"pending"};const target=shotAnchorOf2(anchor);if(!target)return{at:"none"};if(!board)return loaded?{at:"none"}:{at:"pending"};if(!loaded)return{at:"pending"};if(anchor.versionId!==board.version.id&&!prevSettled)return{at:"pending"};const after=shotFacts(board.list,board.version.entries);const before=anchor.versionId===board.version.id?after:prev&&anchor.versionId===prev.version.id?prev.facts:null;const status2=relocateShot(target,before,after);if(status2==="orphan")return{at:"none"};const node=rowOf(target.shotId);if(!node)return{at:"elsewhere"};const box=node.getBoundingClientRect();const at=root.getBoundingClientRect();return{at:"rects",rects:[{x:box.left-at.left,y:box.top-at.top,width:box.width,height:box.height}],...status2==="changed"?{status:status2}:{}}};const drawWall=()=>{if(!board)return;const wall=el("div","bs-wall");wall.setAttribute("role","listbox");wall.setAttribute("aria-label","\u9759\u5E27");board.shots.forEach((shot,i)=>{const node=el("div","bs-shot");const img=thumb(shot,board?.version);node.append(...img?[img]:[],heading(i,shot,false));node.querySelector("h3")?.append(el("span",void 0,`${sec(shot.end-shot.start)} \u79D2`));selectable(node,shot);wall.append(node)});body.replaceChildren(wall)};const tags=d=>{const box=el("div","bs-tags");const labels=d.kind==="added"?["\u65B0\u589E"]:d.kind==="removed"?["\u5220\u6389"]:d.changes;for(const label of labels){const t=el("span","bs-tag",label);if(d.kind==="added"||d.kind==="removed")t.dataset.kind=d.kind;box.append(t)}return box};const drawCompare=()=>{if(!board||!prev)return;const diffs=diffShots(prev.rows,rows);const index=(id,list)=>list.findIndex(r=>r.shot.id===id);const changed=diffs.filter(d=>d.kind!=="same").length;const added=diffs.filter(d=>d.kind==="added").length;const removed=diffs.filter(d=>d.kind==="removed").length;const same=diffs.length-changed;const grid=el("div","bs-cmp");grid.setAttribute("aria-label","\u548C\u4E0A\u4E00\u7248\u5BF9\u6BD4");const changedCount=changed-added-removed;const tail=added||removed?`${added?`\u65B0\u589E ${added} \u4E2A`:""}${added&&removed?"\u3001":""}${removed?`\u5220\u6389 ${removed} \u4E2A`:""}`:"\u6CA1\u6709\u65B0\u589E\u6216\u5220\u6389";grid.append(el("div","bs-head",`\u4E0A\u4E00\u7248 \xB7 ${versionName(prev.version)}`),el("div","bs-head",`\u8FD9\u4E00\u7248 \xB7 ${versionName(board.version)} \xB7 ${changedCount} \u4E2A\u955C\u5934\u6539\u4E86\uFF0C${tail}`));const side=(row,v,list,d,s)=>{if(!row){const gap=el("div","bs-gap",s==="before"?"\u4E0A\u4E00\u7248\u6CA1\u6709\u8FD9\u4E2A\u955C\u5934":"\u8FD9\u4E00\u7248\u5220\u6389\u4E86\u8FD9\u4E2A\u955C\u5934");gap.dataset.side=s;gap.dataset.kind=d.kind;return gap}const node=shotRow(row,index(row.shot.id,list),v,false);node.dataset.side=s;node.dataset.kind=d.kind;node.dataset.shot=row.shot.id;if(s==="after"||d.kind==="removed")node.querySelector(".bs-body")?.append(tags(d));return node};for(const d of diffs){if(d.kind==="same"&&!showSame)continue;grid.append(side(d.before,prev.version,prev.rows,d,"before"),side(d.after,board.version,rows,d,"after"))}if(same>0){const fold=el("button","bs-fold",showSame?`\u6536\u8D77\u6CA1\u53D8\u7684 ${same} \u4E2A\u955C\u5934`:`${same} \u4E2A\u955C\u5934\u6CA1\u53D8`);fold.type="button";fold.setAttribute("aria-expanded",String(showSame));fold.addEventListener("click",()=>{showSame=!showSame;draw()});grid.append(fold)}body.replaceChildren(grid)};const drawBar=()=>{bar.replaceChildren();if(!board)return;bar.append(el("span","bs-sum",summaryLine(board.list)),el("span","bs-grow"));if(config.compare)return;if(prev){const cmp=el("button","btn sm",comparing?"\u9000\u51FA\u5BF9\u6BD4":"\u548C\u4E0A\u4E00\u7248\u5BF9\u6BD4");cmp.type="button";cmp.setAttribute("aria-pressed",String(comparing));cmp.addEventListener("click",()=>{comparing=!comparing;draw()});bar.append(cmp)}if(!comparing){const seg=el("span","bs-seg");seg.setAttribute("role","group");seg.setAttribute("aria-label","\u663E\u793A\u65B9\u5F0F");for(const[key,label]of[["table","\u955C\u5934\u8868"],["wall","\u9759\u5E27\u5899"]]){const b=el("button",void 0,label);b.type="button";b.setAttribute("aria-pressed",String(mode===key));b.addEventListener("click",()=>{mode=key;draw()});seg.append(b)}bar.append(seg)}};const draw=()=>{drawBar();view.classList.toggle("bs-land",!isPortrait(board?.list.format));if(comparing&&prev)drawCompare();else if(mode==="wall")drawWall();else drawTable();lit=null;highlight();notify()};const load=async()=>{const current=ctx.version.current();let found=null;try{found=current?await storyboardFor(ctx,current):null}catch{}if(!alive)return;if(!found||!current){status.textContent=current?"\u8FD9\u4E2A\u7248\u672C\u6CA1\u6709\u955C\u5934\u8868\uFF08storyboard.json \u4E0D\u5728\u6216\u683C\u5F0F\u4E0D\u5BF9\uFF09":"\u6CA1\u6709\u53EF\u663E\u793A\u7684\u7248\u672C";return}versions=await ctx.version.list(found.version.artifactId).then(list=>[...list].sort((a,b)=>a.createdAt.localeCompare(b.createdAt)),()=>null);const extras=await extrasOf(ctx,found.version);if(!alive)return;board=found;rows=rowsOf(found,extras);loaded=true;refreshHost();draw();if(config.compare){offComparison?.();offComparison=joinComparison(ctx.project.id,{version:found.version,rows,draw(diffs,side){comparison=diffs?{diffs,side}:null;if(alive)draw()}});return}const before=await previousOf(ctx,found.version);const prevBoard=before?await storyboardFor(ctx,before).catch(()=>null):null;if(!alive||!prevBoard)return;const prevExtras=await extrasOf(ctx,prevBoard.version);if(!alive)return;prev={version:prevBoard.version,rows:rowsOf(prevBoard,prevExtras),facts:shotFacts(prevBoard.list,prevBoard.version.entries)};prevSettled=true;draw()};const offSel=ctx.selection.subscribe(()=>highlight());const hostDescriptor={kinds:["shot","region"],locate,async reveal(anchor){await settled;if(!alive)return false;if(anchor.kind==="region")return lightbox.reveal(anchor);const at=locate(anchor).at;if(at!=="rects"&&at!=="elsewhere")return false;const target=shotAnchorOf2(anchor);if(!target)return false;if(at==="elsewhere"&&comparing&&!showSame){showSame=true;draw()}const node=rowOf(target.shotId);if(!node)return false;scrollIntoPanel(node,{block:"nearest"});return true},onLayout(fn){listeners.add(fn);return()=>listeners.delete(fn)}};let offHost=ctx.anchors.host(hostDescriptor);const refreshHost=()=>{offHost();offHost=ctx.anchors.host({...hostDescriptor,...canComment()?{annotate:true}:{}})};let threadSeq=0;let offThreadError;const updateThreadCounts=()=>{if(!board)return;for(const button of body.querySelectorAll(".bs-picture")){const node=button.closest("[data-shot]");const index=board.shots.findIndex(s=>s.id===node?.dataset.shot);const count=threads.filter(t=>board&&t.status!=="resolved"&®ionShot(t.anchor,board.shots,board.version)?.index===index).length;button.querySelector(".bs-count")?.remove();if(count)button.append(el("span","bs-count",String(count)))}};const loadThreads=async()=>{if(!alive||!board)return;const seq=++threadSeq;try{const all=await ctx.threads.list();if(!alive||seq!==threadSeq)return;offThreadError?.();offThreadError=void 0;status.replaceChildren();threads=all.filter(t=>t.artifactId===board?.version.artifactId);lightbox.setThreads(threads);updateThreadCounts()}catch(error){if(!alive||seq!==threadSeq)return;if(isForbidden2(error)){threads=[];lightbox.setThreads(threads);updateThreadCounts()}const retry=()=>{void loadThreads()};offThreadError?.();status.replaceChildren();offThreadError=threadReadError(status,error,retry);lightbox.setThreadsFailure(error,retry)}};const offThreads=EVENT_GROUPS.threads.map(pattern=>ctx.events.subscribe(pattern,()=>{void loadThreads()}));view.addEventListener("load",notify,true);const observer=typeof ResizeObserver==="undefined"?null:new ResizeObserver(notify);observer?.observe(view);void load().catch(()=>void 0).finally(()=>{loaded=true;prevSettled=true;settle();if(alive){notify();void loadThreads()}});const paintAnnotating=()=>{body.dataset.annotating=String(ctx.anchors.annotating.get()&&canComment()&&!config.compare&&!narrow())};paintAnnotating();const offAnnotating=ctx.anchors.annotating.subscribe(paintAnnotating);const onNarrowChange=()=>{paintAnnotating();if(board)draw()};narrowMq?.addEventListener("change",onNarrowChange);return()=>{alive=false;offAnnotating();narrowMq?.removeEventListener("change",onNarrowChange);offComparison?.();offThreadError?.();lightbox.dispose();for(const timer of timers)clearTimeout(timer);for(const off of offThreads)off();offSel();offHost();view.removeEventListener("load",notify,true);observer?.disconnect();listeners.clear();style.remove();frame.remove()}}var EXTRA_STYLE=`
|
|
76
|
+
${path}`;let p=urls.get(key);if(!p){p=ctx.version.objectUrl(path,{versionId:v.id});urls.set(key,p);p.catch(()=>urls.delete(key))}return p};const thumb=(shot,v)=>{const path=imageOf(shot,v);if(!path)return null;const img=el("img","bs-thumb");img.alt="";img.loading="lazy";void imageUrl(v,path).then(url=>{if(alive)img.src=url},()=>img.remove());if(config.compare||v.id!==board?.version.id)return img;const button=el("button","bs-picture");button.type="button";const i=board?.shots.findIndex(s=>s.id===shot.id)??-1;button.setAttribute("aria-label",`\u653E\u5927\u955C\u5934 ${i+1} \u9759\u5E27`);const magnify=el("span","bs-magnify");magnify.append(lightboxIcon(doc,"plus"));button.append(img,magnify);const count=threads.filter(t=>board&®ionShot(t.anchor,board.shots,v)?.index===i&&t.status!=="resolved").length;if(count)button.append(el("span","bs-count",String(count)));button.addEventListener("click",e=>{e.stopPropagation();const index=board?.shots.findIndex(s=>s.id===shot.id)??-1;if(index>=0)lightbox.open(index)});return button};const pick=shot=>{if(!board)return;ctx.selection.set({kind:"entity",entityType:"shot",id:shot.id,artifactId:board.version.artifactId})};const selectable=(node,shot)=>{node.dataset.shot=shot.id;node.setAttribute("role","option");node.tabIndex=0;const act=()=>{if(!narrow()&&ctx.anchors.annotating.get()&&canComment()&&!config.compare)commentShot(shot);else pick(shot)};node.addEventListener("click",act);node.addEventListener("keydown",withImeGuard(e=>{if(e.target!==node||e.key!=="Enter"&&e.key!==" ")return;e.preventDefault();act()}))};const heading=(i,shot,time=true)=>{const h=el("h3",void 0,`${i+1} \xB7 ${shot.title}`);if(time){h.append(el("span",void 0,`${sec(shot.start)}\u2013${sec(shot.end)} \u79D2 \xB7 ${sec(shot.end-shot.start)} \u79D2`))}return h};const line=(label,text,none)=>{if(!text)return none?el("p","bs-none",none):null;const p=el("p");p.append(el("b",void 0,label),text);return p};const shotRow=(row,i,v,interactive)=>{const node=el("div","bs-shot");const img=thumb(row.shot,v);const text=el("div","bs-body");text.append(heading(i,row.shot));const pic=line("\u753B\u9762",row.summary);if(pic)text.append(pic);const vo=line("\u65C1\u767D",row.narration,"\u6CA1\u6709\u65C1\u767D");if(vo)text.append(vo);node.append(img??el("span"),text);if(interactive)selectable(node,row.shot);return node};const highlight=()=>{const picked=shotOf(board?.shots??[],ctx.selection.get());for(const node of body.querySelectorAll("[data-shot]")){const on=node.dataset.shot===picked;node.setAttribute("aria-selected",String(on));if(on&&picked!==lit)scrollIntoPanel(node,{block:"nearest"})}lit=picked};const canComment=()=>!config.compare&&ctx.member.can("comment")&&board!==null&&ctx.version.current()?.id===board.version.id;const lightbox=createShotLightbox(ctx,root,frame,{board:()=>board,rows:()=>rows,canComment,changed(anchor,path){if(!board||!versions||anchor.versionId===board.version.id)return false;const before=versions.find(v=>v.id===anchor.versionId);if(!before||before.createdAt>board.version.createdAt)return false;return relocateFileAnchor({},{before:before.entries.find(e=>e.path===path)?.sha256??null,after:board.version.entries.find(e=>e.path===path)?.sha256??null})==="changed"},versionNote(){const shown=board;if(!shown||!versions)return null;const index=versions.findIndex(v=>v.id===shown.version.id);return index>=0&&index<versions.length-1?`\u6302\u5728 v${index+1}\uFF08\u5386\u53F2\u7248\u672C\uFF09`:null},imageUrl:path=>board?imageUrl(board.version,path):Promise.reject(new Error("\u6CA1\u6709\u5206\u955C")),notify,returned(index){const shot=board?.shots[index];const row=shot?rowOf(shot.id):void 0;if(!row)return;scrollIntoPanel(row,{block:"nearest"});row.classList.add("bs-returned");(row.querySelector(".bs-picture")??row).focus({preventScroll:true});const timer=setTimeout(()=>{row.classList.remove("bs-returned");timers.delete(timer)},1400);timers.add(timer)}});const narrowMq=narrowMedia();const narrow=()=>narrowMq?.matches===true;const commentShot=shot=>{const i=rows.findIndex(r=>r.shot.id===shot.id);const label=`\u955C\u5934 ${i+1} \xB7 ${shot.title}`;ctx.threads.openAt(ctx.anchors.make("shot",{path:SHOT_LIST_PATH,label,shotId:shot.id},shot.title))};const addButton=(shot,i)=>{const add=el("button","bs-add","+");add.type="button";add.setAttribute("aria-label",`\u5BF9\u955C\u5934 ${i+1} \u8BC4\u8BBA`);add.title="\u5BF9\u8FD9\u4E2A\u955C\u5934\u8BC4\u8BBA";add.disabled=!canComment();add.addEventListener("click",e=>{e.stopPropagation();if(canComment())commentShot(shot)});return add};const drawTable=()=>{if(!board)return;const list=el("div","bs-list");list.setAttribute("role","listbox");list.setAttribute("aria-label","\u955C\u5934");const visible=comparison?.diffs??rows.map(row=>({id:row.shot.id,kind:"same",changes:[],before:row,after:row}));for(const diff of visible){const row=comparison?.side==="before"?diff.before:diff.after;if(!row){const gap=el("div","bs-gap",comparison?.side==="before"?"\u4E0A\u4E00\u7248\u6CA1\u6709\u8FD9\u4E2A\u955C\u5934":"\u8FD9\u4E00\u7248\u5220\u6389\u4E86\u8FD9\u4E2A\u955C\u5934");list.append(gap);continue}const i=rows.findIndex(r=>r.shot.id===row.shot.id);const node=shotRow(row,i,board.version,true);node.dataset.shot=row.shot.id;if(comparison)node.querySelector(".bs-body")?.append(tags(diff));if(narrow()&&!config.compare)node.append(addButton(row.shot,i));list.append(node)}body.replaceChildren(list)};const rowOf=shotId=>[...body.querySelectorAll("[data-shot]")].find(n=>n.dataset.shot===shotId&&n.dataset.side!=="before");const locate=anchor=>{if(anchor.kind==="region")return loaded?board?lightbox.locate(anchor):{at:"none"}:{at:"pending"};const target=shotAnchorOf2(anchor);if(!target)return{at:"none"};if(!board)return loaded?{at:"none"}:{at:"pending"};if(!loaded)return{at:"pending"};if(anchor.versionId!==board.version.id&&!prevSettled)return{at:"pending"};const after=shotFacts(board.list,board.version.entries);const before=anchor.versionId===board.version.id?after:prev&&anchor.versionId===prev.version.id?prev.facts:null;const status2=relocateShot(target,before,after);if(status2==="orphan")return{at:"none"};const node=rowOf(target.shotId);if(!node)return{at:"elsewhere"};const box=node.getBoundingClientRect();const at=root.getBoundingClientRect();return{at:"rects",rects:[{x:box.left-at.left,y:box.top-at.top,width:box.width,height:box.height}],...status2==="changed"?{status:status2}:{}}};const drawWall=()=>{if(!board)return;const wall=el("div","bs-wall");wall.setAttribute("role","listbox");wall.setAttribute("aria-label","\u9759\u5E27");board.shots.forEach((shot,i)=>{const node=el("div","bs-shot");const img=thumb(shot,board?.version);node.append(...img?[img]:[],heading(i,shot,false));node.querySelector("h3")?.append(el("span",void 0,`${sec(shot.end-shot.start)} \u79D2`));selectable(node,shot);wall.append(node)});body.replaceChildren(wall)};const tags=d=>{const box=el("div","bs-tags");const labels=d.kind==="added"?["\u65B0\u589E"]:d.kind==="removed"?["\u5220\u6389"]:d.changes;for(const label of labels){const t=el("span","bs-tag",label);if(d.kind==="added"||d.kind==="removed")t.dataset.kind=d.kind;box.append(t)}return box};const drawCompare=()=>{if(!board||!prev)return;const diffs=diffShots(prev.rows,rows);const index=(id,list)=>list.findIndex(r=>r.shot.id===id);const changed=diffs.filter(d=>d.kind!=="same").length;const added=diffs.filter(d=>d.kind==="added").length;const removed=diffs.filter(d=>d.kind==="removed").length;const same=diffs.length-changed;const grid=el("div","bs-cmp");grid.setAttribute("aria-label","\u548C\u4E0A\u4E00\u7248\u5BF9\u6BD4");const changedCount=changed-added-removed;const tail=added||removed?`${added?`\u65B0\u589E ${added} \u4E2A`:""}${added&&removed?"\u3001":""}${removed?`\u5220\u6389 ${removed} \u4E2A`:""}`:"\u6CA1\u6709\u65B0\u589E\u6216\u5220\u6389";grid.append(el("div","bs-head",`\u4E0A\u4E00\u7248 \xB7 ${versionName(prev.version)}`),el("div","bs-head",`\u8FD9\u4E00\u7248 \xB7 ${versionName(board.version)} \xB7 ${changedCount} \u4E2A\u955C\u5934\u6539\u4E86\uFF0C${tail}`));const side=(row,v,list,d,s)=>{if(!row){const gap=el("div","bs-gap",s==="before"?"\u4E0A\u4E00\u7248\u6CA1\u6709\u8FD9\u4E2A\u955C\u5934":"\u8FD9\u4E00\u7248\u5220\u6389\u4E86\u8FD9\u4E2A\u955C\u5934");gap.dataset.side=s;gap.dataset.kind=d.kind;return gap}const node=shotRow(row,index(row.shot.id,list),v,false);node.dataset.side=s;node.dataset.kind=d.kind;node.dataset.shot=row.shot.id;if(s==="after"||d.kind==="removed")node.querySelector(".bs-body")?.append(tags(d));return node};for(const d of diffs){if(d.kind==="same"&&!showSame)continue;grid.append(side(d.before,prev.version,prev.rows,d,"before"),side(d.after,board.version,rows,d,"after"))}if(same>0){const fold=el("button","bs-fold",showSame?`\u6536\u8D77\u6CA1\u53D8\u7684 ${same} \u4E2A\u955C\u5934`:`${same} \u4E2A\u955C\u5934\u6CA1\u53D8`);fold.type="button";fold.setAttribute("aria-expanded",String(showSame));fold.addEventListener("click",()=>{showSame=!showSame;draw()});grid.append(fold)}body.replaceChildren(grid)};const drawBar=()=>{bar.replaceChildren();if(!board)return;bar.append(el("span","bs-sum",summaryLine(board.list)),el("span","bs-grow"));if(config.compare)return;if(prev){const cmp=el("button","btn sm",comparing?"\u9000\u51FA\u5BF9\u6BD4":"\u548C\u4E0A\u4E00\u7248\u5BF9\u6BD4");cmp.type="button";cmp.setAttribute("aria-pressed",String(comparing));cmp.addEventListener("click",()=>{comparing=!comparing;draw()});bar.append(cmp)}if(!comparing){const seg=el("span","bs-seg");seg.setAttribute("role","group");seg.setAttribute("aria-label","\u663E\u793A\u65B9\u5F0F");for(const[key,label]of[["table","\u955C\u5934\u8868"],["wall","\u9759\u5E27\u5899"]]){const b=el("button",void 0,label);b.type="button";b.setAttribute("aria-pressed",String(mode===key));b.addEventListener("click",()=>{mode=key;draw()});seg.append(b)}bar.append(seg)}};const draw=()=>{drawBar();view.classList.toggle("bs-land",!isPortrait(board?.list.format));if(comparing&&prev)drawCompare();else if(mode==="wall")drawWall();else drawTable();lit=null;highlight();notify()};const load=async()=>{const current=ctx.version.current();let found=null;try{found=current?await storyboardFor(ctx,current):null}catch{}if(!alive)return;if(!found||!current){status.textContent=current?"\u8FD9\u4E2A\u7248\u672C\u6CA1\u6709\u955C\u5934\u8868\uFF08storyboard.json \u4E0D\u5728\u6216\u683C\u5F0F\u4E0D\u5BF9\uFF09":"\u6CA1\u6709\u53EF\u663E\u793A\u7684\u7248\u672C";return}versions=await ctx.version.list(found.version.artifactId).then(list=>[...list].sort((a,b)=>a.createdAt.localeCompare(b.createdAt)),()=>null);const extras=await extrasOf(ctx,found.version);if(!alive)return;board=found;rows=rowsOf(found,extras);loaded=true;refreshHost();draw();if(config.compare){offComparison?.();offComparison=joinComparison(ctx.project.id,{version:found.version,rows,draw(diffs,side){comparison=diffs?{diffs,side}:null;if(alive)draw()}});return}const before=await previousOf(ctx,found.version);const prevBoard=before?await storyboardFor(ctx,before).catch(()=>null):null;if(!alive||!prevBoard)return;const prevExtras=await extrasOf(ctx,prevBoard.version);if(!alive)return;prev={version:prevBoard.version,rows:rowsOf(prevBoard,prevExtras),facts:shotFacts(prevBoard.list,prevBoard.version.entries)};prevSettled=true;draw()};const offSel=ctx.selection.subscribe(()=>highlight());const hostDescriptor={kinds:["shot","region"],locate,async reveal(anchor){await settled;if(!alive)return false;if(anchor.kind==="region")return lightbox.reveal(anchor);const at=locate(anchor).at;if(at!=="rects"&&at!=="elsewhere")return false;const target=shotAnchorOf2(anchor);if(!target)return false;if(at==="elsewhere"&&comparing&&!showSame){showSame=true;draw()}const node=rowOf(target.shotId);if(!node)return false;scrollIntoPanel(node,{block:"nearest"});return true},onLayout(fn){listeners.add(fn);return()=>listeners.delete(fn)}};let offHost=ctx.anchors.host(hostDescriptor);const refreshHost=()=>{offHost();offHost=ctx.anchors.host({...hostDescriptor,...canComment()?{annotate:true}:{}})};let threadSeq=0;let offThreadError;const updateThreadCounts=()=>{if(!board)return;for(const button of body.querySelectorAll(".bs-picture")){const node=button.closest("[data-shot]");const index=board.shots.findIndex(s=>s.id===node?.dataset.shot);const count=threads.filter(t=>board&&t.status!=="resolved"&®ionShot(t.anchor,board.shots,board.version)?.index===index).length;button.querySelector(".bs-count")?.remove();if(count)button.append(el("span","bs-count",String(count)))}};const loadThreads=async()=>{if(!alive||!board)return;const seq=++threadSeq;try{const all=await ctx.threads.list();if(!alive||seq!==threadSeq)return;offThreadError?.();offThreadError=void 0;status.replaceChildren();threads=all.filter(t=>t.artifactId===board?.version.artifactId);lightbox.setThreads(threads);updateThreadCounts()}catch(error){if(!alive||seq!==threadSeq)return;if(isForbidden2(error)){threads=[];lightbox.setThreads(threads);updateThreadCounts()}const retry=()=>{void loadThreads()};offThreadError?.();status.replaceChildren();offThreadError=threadReadError(status,error,retry);lightbox.setThreadsFailure(error,retry)}};const offThreads=EVENT_GROUPS.threads.map(pattern=>ctx.events.subscribe(pattern,()=>{void loadThreads()}));view.addEventListener("load",notify,true);const observer=typeof ResizeObserver==="undefined"?null:new ResizeObserver(notify);observer?.observe(view);void load().catch(()=>void 0).finally(()=>{loaded=true;prevSettled=true;settle();if(alive){notify();void loadThreads()}});const paintAnnotating=()=>{body.dataset.annotating=String(ctx.anchors.annotating.get()&&canComment()&&!config.compare&&!narrow())};paintAnnotating();const offAnnotating=ctx.anchors.annotating.subscribe(paintAnnotating);const onNarrowChange=()=>{paintAnnotating();if(board)draw()};narrowMq?.addEventListener("change",onNarrowChange);return()=>{alive=false;offAnnotating();narrowMq?.removeEventListener("change",onNarrowChange);offComparison?.();offThreadError?.();lightbox.dispose();for(const timer of timers)clearTimeout(timer);for(const off of offThreads)off();offSel();offHost();view.removeEventListener("load",notify,true);observer?.disconnect();listeners.clear();style.remove();frame.remove()}}var EXTRA_STYLE=`
|
|
77
77
|
.bs-label { position: absolute; left: 8px; top: 8px; max-width: calc(100% - 16px);
|
|
78
78
|
padding: 2px 8px; border-radius: var(--r-sm); background: color-mix(in srgb, var(--panel) 88%, transparent);
|
|
79
79
|
color: var(--ink); font-size: var(--fs-meta); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kanyun-ai-infra/band-viewer-storyboard",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.6",
|
|
4
4
|
"description": "分镜镜头表:一行一个镜头(静帧、区间与时长、画面、旁白),按镜头 id 和上一版对比",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
7
7
|
".": "./index.js"
|
|
8
8
|
},
|
|
9
9
|
"peerDependencies": {
|
|
10
|
-
"@kanyun-ai-infra/band-plugin-sdk": "^1.
|
|
10
|
+
"@kanyun-ai-infra/band-plugin-sdk": "^1.222.0",
|
|
11
11
|
"@kanyun-ai-infra/band-project": "*",
|
|
12
12
|
"@kanyun-ai-infra/band-threads": "*",
|
|
13
13
|
"@kanyun-ai-infra/band-viewer-entity": "*",
|