Open Library to pick a still or clip
@@ -431,7 +437,7 @@
@@ -677,6 +683,25 @@ watch(()=>form.identityStillId,id=>{if(import.meta.client&&form.folderId&&form.e
const stills=computed(()=>library.value.stills.filter((s:any)=>s.folderId===form.folderId))
const clips=computed(()=>library.value.clips.filter((s:any)=>s.folderId===form.folderId))
const stillUrl=(id:string)=>`/api/library/stills/${id}`
+const stillThumbUrl=(id:string)=>`/api/library/stills/${id}/thumb`
+/** Stage shows thumb first, then swaps to original after decode — never leave the previous still painted. */
+const stageStillHiRes=ref(false)
+const stageStillSrc=computed(()=>{
+ const id=selected.value?.id
+ if(!id || selected.value?.kind==='clip' || selected.value?.kind==='track') return ''
+ if(isHidden(selected.value)) return ''
+ return stageStillHiRes.value ? stillUrl(id) : stillThumbUrl(id)
+})
+function onStageStillLoad(e:Event){
+ const id=selected.value?.id
+ if(!id || stageStillHiRes.value) return
+ const img=e.target as HTMLImageElement
+ const bump=()=>{ if(selected.value?.id===id) stageStillHiRes.value=true }
+ if(typeof img.decode==='function') void img.decode().then(bump).catch(bump)
+ else bump()
+}
+watch(()=>selected.value?.id,()=>{ stageStillHiRes.value=false })
+watch(eyeOpen,()=>{ if(eyeOpen.value) stageStillHiRes.value=false })
const folderJobs=computed(()=>jobs.value.filter(j=>j.request.folderId===form.folderId))
const benchJobs=computed(()=>queueJobs(folderJobs.value))
const musicJobs=computed(()=>studioQueue.value
@@ -1423,6 +1448,9 @@ const mobileCtx=computed(()=>({
loraTriggers:{...loraNames.value.triggers,...library.value.loraTriggers},
aspectOptions,
stillUrl,
+ stillThumbUrl,
+ stageStillSrc:stageStillSrc.value,
+ onStageStillLoad,
isHidden,
slotHidden,
stillById,
diff --git a/components/studio2/Mobile.vue b/components/studio2/Mobile.vue
index a36bb53..56e31d4 100644
--- a/components/studio2/Mobile.vue
+++ b/components/studio2/Mobile.vue
@@ -117,7 +117,7 @@
controls
playsinline
/>
-
+
Open Library to pick a still or clip