fc0111a18e
CI / test (push) Has been cancelled
Decode the device's rendered 4bpp Spectra-6 .bin into a PNG (cached
next to the .bin) so the home-screen preview matches the dithered
6-color output the e-ink actually displays.
- New endpoint: GET /api/devices/{id}/preview
- Expose currentImageId on device JSON
- HomeView passes preview URL to FrameCard for both single and compact layouts
- Drive-by: fix vite.config.ts to import defineConfig from vitest/config
so the build no longer fails on the unknown `test` property; remove
unused useUploadStore import in HomeView test
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 line
12 KiB
JavaScript
1 line
12 KiB
JavaScript
import{B as e,E as t,H as n,K as r,_ as i,d as a,dt as o,f as s,g as c,h as l,j as u,k as d,l as f,o as p,p as m,pt as h,t as g,u as _,v,z as y}from"./_plugin-vue_export-helper-DVo1OUMD.js";import{a as b,d as x,f as S,i as C,o as w,s as T,u as E}from"./index-C0Yc8pEe.js";import{i as D,n as O,r as ee,t as k}from"./BaseBottomSheet-BODCttr7.js";import{t as A}from"./DevicePicker-Dz05cPit.js";var j={class:`approve-card`},M=[`src`,`alt`],N={class:`approve-card__body`},P={class:`approve-card__from`},F={class:`approve-card__date`},I={key:0,class:`approve-card__status`},L={class:`approve-card__actions`},te=g(v({__name:`ApproveCard`,props:{item:{}},emits:[`updated`],setup(e,{emit:t}){let l=e,u=t,g=b(),v=D(),x=n(!1),S=n(!1),C=n([]),w=f(()=>new Date(l.item.sharedAt).toLocaleDateString(void 0,{month:`short`,day:`numeric`,year:`numeric`}));async function T(){x.value=!1,S.value=!0;try{u(`updated`,await g.approveShared(l.item.id,C.value))}finally{S.value=!1,C.value=[]}}async function E(){S.value=!0;try{u(`updated`,await g.declineShared(l.item.id))}finally{S.value=!1}}return(t,n)=>(d(),m(p,null,[_(`div`,j,[_(`img`,{src:e.item.thumbnailUrl,alt:`Photo from ${e.item.sharedBy}`,class:`approve-card__thumb`,loading:`lazy`},null,8,M),_(`div`,N,[_(`p`,P,[n[3]||=c(`From `,-1),_(`strong`,null,h(e.item.sharedBy),1)]),_(`p`,F,h(w.value),1),e.item.status===`pending`?s(``,!0):(d(),m(`div`,I,[_(`span`,{class:o([`approve-card__badge`,`approve-card__badge--${e.item.status}`])},h(e.item.status),3)])),_(`div`,L,[e.item.status===`pending`||e.item.status===`declined`?(d(),a(O,{key:0,variant:`primary`,size:`sm`,disabled:S.value,onClick:n[0]||=e=>x.value=!0},{default:y(()=>[c(h(e.item.status===`declined`?`Add anyway`:`Add to frame`),1)]),_:1},8,[`disabled`])):s(``,!0),e.item.status===`pending`||e.item.status===`approved`?(d(),a(O,{key:1,variant:`ghost`,size:`sm`,disabled:S.value,onClick:E},{default:y(()=>[c(h(e.item.status===`approved`?`Remove`:`Decline`),1)]),_:1},8,[`disabled`])):s(``,!0)])])]),i(A,{modelValue:x.value,"onUpdate:modelValue":n[1]||=e=>x.value=e,devices:r(v).devices,selected:C.value,uploading:S.value,"confirm-label":`Add to frames`,"onUpdate:selected":n[2]||=e=>C.value=e,onConfirm:T},null,8,[`modelValue`,`devices`,`selected`,`uploading`])],64))}}),[[`__scopeId`,`data-v-6d3dd8b4`]]),R={class:`share-sheet__field`},z=[`onKeydown`],B={key:0,class:`share-sheet__error`},V={key:1,class:`share-sheet__success`},ne=g(v({__name:`ShareSheet`,props:{modelValue:{type:Boolean},imageId:{}},emits:[`update:modelValue`],setup(t,{emit:r}){let o=t,l=b(),u=n(``),f=n(!1),p=n(``),g=n(``);async function v(){if(p.value=``,g.value=``,u.value.trim()){f.value=!0;try{await l.shareImage(o.imageId,u.value.trim()),g.value=`Invite sent to ${u.value.trim()}`,u.value=``}catch(e){p.value=e instanceof Error?e.message:`Failed to send`}finally{f.value=!1}}}return(n,r)=>(d(),a(k,{"model-value":t.modelValue,label:`Share photo`,"onUpdate:modelValue":r[1]||=e=>n.$emit(`update:modelValue`,e)},{default:y(()=>[r[2]||=_(`h2`,{class:`share-sheet__title`},`Share with someone`,-1),r[3]||=_(`p`,{class:`share-sheet__sub`},`They'll get an email and can add it to their frame.`,-1),_(`div`,R,[e(_(`input`,{"onUpdate:modelValue":r[0]||=e=>u.value=e,type:`email`,class:`share-sheet__input`,placeholder:`their@email.com`,autocomplete:`email`,onKeydown:x(S(v,[`prevent`]),[`enter`])},null,40,z),[[E,u.value]])]),p.value?(d(),m(`p`,B,h(p.value),1)):s(``,!0),g.value?(d(),m(`p`,V,h(g.value),1)):s(``,!0),i(O,{variant:`primary`,class:`share-sheet__btn`,disabled:f.value||!u.value.trim(),onClick:v},{default:y(()=>[c(h(f.value?`Sending…`:`Send invite`),1)]),_:1},8,[`disabled`])]),_:1},8,[`model-value`]))}}),[[`__scopeId`,`data-v-24296e7b`]]),re={class:`library`},ie={class:`library__tabs`,role:`tablist`},ae=[`aria-selected`,`onClick`],oe={key:0,class:`library__loading`},se={key:0,class:`library__empty`},ce={key:1,class:`library__grid`},le={class:`library__thumb`},H=[`src`,`alt`],U={class:`library__thumb-actions`},W=[`aria-label`,`disabled`,`onClick`],ue={key:0,width:`13`,height:`13`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2.5`,"aria-hidden":`true`},de={key:1,width:`13`,height:`13`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"aria-hidden":`true`},fe=[`aria-label`,`onClick`],pe=[`onClick`],me={key:0,class:`library__approvals`},he=[`aria-label`,`onClick`],ge={key:1,class:`library__locks`},_e=[`aria-label`,`onClick`],ve={width:`10`,height:`10`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2.5`,"aria-hidden":`true`},ye={key:0,d:`M7 11V7a5 5 0 0 1 10 0v4`},be={key:1,d:`M7 11V7a5 5 0 0 1 9.9-1`},xe={class:`library__subtabs`,role:`tablist`},Se=[`aria-selected`,`onClick`],Ce={key:0,class:`library__loading`},we={key:1,class:`library__shared-empty`},Te={class:`library__empty-title`},Ee={class:`library__empty-sub`},De={key:2,class:`library__shared-list`},Oe={key:3,class:`library__pagination`},ke=[`disabled`],Ae={class:`library__page-info`},je=[`disabled`],Me={class:`library__sheet-actions`},G=g(v({__name:`LibraryView`,setup(e){let g=T(),v=b(),x=D(),S=ee(),E=C(),A=w(),j=[{id:`all`,label:`All`},{id:`mine`,label:`Mine`},{id:`shared`,label:`Shared`}],M=n(A.query.tab??`all`),N=[{id:`pending`,label:`Pending`},{id:`approved`,label:`Approved`},{id:`declined`,label:`Declined`}],P=n(`pending`),F=n([]),I=n(!1),L=n(1),R=n(1);async function z(e,t=1){I.value=!0;try{let n=await v.fetchSharedImages(e,t);F.value=n.items,L.value=n.page,R.value=n.totalPages}finally{I.value=!1}}function B(e){P.value=e,z(e,1)}function V(e){z(P.value,e)}function G(e){let t=F.value.findIndex(t=>t.id===e.id);t!==-1&&(F.value[t]=e)}t(()=>{v.fetchImages(),x.fetchDevices(),v.fetchPendingCount(),M.value===`shared`&&z(P.value)});let K=f(()=>v.images),q=n(!1),J=n(null);function Ne(e){J.value=e,q.value=!0}let Y=n(null);async function X(e){if(!Y.value){Y.value=e.id;try{await S.initEdit(e),g.push(`/upload`)}catch{E.show(`Could not load photo for editing`,`error`)}finally{Y.value=null}}}async function Pe(e,t){try{t.lockedImageId===e?await x.unlockImage(t.id):await x.lockImage(t.id,e)}catch{E.show(`Failed to update lock`,`error`)}}async function Fe(e,t,n){try{await v.setApproval(e,t,n)}catch{E.show(`Failed to update frame approval`,`error`)}}let Z=n(!1),Q=n(null),$=n(!1);function Ie(e){Q.value=e,Z.value=!0}async function Le(){if(Q.value){$.value=!0;try{await v.deleteImage(Q.value),Z.value=!1,E.show(`Photo deleted`,`success`)}catch{E.show(`Delete failed`,`error`)}finally{$.value=!1}}}return(e,t)=>(d(),m(`main`,re,[_(`div`,ie,[(d(),m(p,null,u(j,e=>_(`button`,{key:e.id,type:`button`,role:`tab`,"aria-selected":M.value===e.id,class:o([`library__tab`,{"library__tab--active":M.value===e.id}]),onClick:t=>M.value=e.id},h(e.label),11,ae)),64))]),r(v).loading?(d(),m(`div`,oe,`Loading…`)):M.value===`shared`?(d(),m(p,{key:2},[_(`div`,xe,[(d(),m(p,null,u(N,e=>_(`button`,{key:e.id,type:`button`,role:`tab`,"aria-selected":P.value===e.id,class:o([`library__subtab`,{"library__subtab--active":P.value===e.id}]),onClick:t=>B(e.id)},h(e.label),11,Se)),64))]),I.value?(d(),m(`div`,Ce,`Loading…`)):F.value.length===0?(d(),m(`div`,we,[t[11]||=l(`<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true" data-v-695e06b8><circle cx="18" cy="5" r="3" data-v-695e06b8></circle><circle cx="6" cy="12" r="3" data-v-695e06b8></circle><circle cx="18" cy="19" r="3" data-v-695e06b8></circle><line x1="8.59" y1="13.51" x2="15.42" y2="17.49" data-v-695e06b8></line><line x1="15.41" y1="6.51" x2="8.59" y2="10.49" data-v-695e06b8></line></svg>`,1),_(`p`,Te,h(P.value===`pending`?`No pending photos`:P.value===`approved`?`No approved photos`:`No declined photos`),1),_(`p`,Ee,h(P.value===`pending`?`Photos shared with you will appear here.`:`Photos you've added to a frame will appear here.`),1)])):(d(),m(`div`,De,[(d(!0),m(p,null,u(F.value,e=>(d(),a(te,{key:e.id,item:e,onUpdated:G},null,8,[`item`]))),128))])),R.value>1?(d(),m(`div`,Oe,[_(`button`,{class:`library__page-btn`,disabled:L.value<=1,onClick:t[0]||=e=>V(L.value-1)},`← Prev`,8,ke),_(`span`,Ae,h(L.value)+` / `+h(R.value),1),_(`button`,{class:`library__page-btn`,disabled:L.value>=R.value,onClick:t[1]||=e=>V(L.value+1)},`Next →`,8,je)])):s(``,!0)],64)):(d(),m(p,{key:1},[K.value.length===0?(d(),m(`div`,se,[...t[5]||=[l(`<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true" data-v-695e06b8><rect x="3" y="3" width="18" height="18" rx="2" data-v-695e06b8></rect><circle cx="8.5" cy="8.5" r="1.5" data-v-695e06b8></circle><polyline points="21,15 16,10 5,21" data-v-695e06b8></polyline></svg><p class="library__empty-title" data-v-695e06b8>No photos yet</p><p class="library__empty-sub" data-v-695e06b8>Tap "+ Add Photo" on the home screen to get started.</p>`,3)]])):(d(),m(`div`,ce,[(d(!0),m(p,null,u(K.value,e=>(d(),m(`div`,{key:e.id,class:`library__item`},[_(`div`,le,[_(`img`,{src:e.thumbnailUrl,alt:e.originalFilename,class:`library__img`,loading:`lazy`},null,8,H),_(`div`,U,[_(`button`,{class:`library__action-btn`,type:`button`,"aria-label":`Edit ${e.originalFilename}`,disabled:Y.value===e.id,onClick:t=>X(e)},[Y.value===e.id?(d(),m(`svg`,de,[...t[7]||=[_(`circle`,{cx:`12`,cy:`12`,r:`10`},null,-1),_(`line`,{x1:`12`,y1:`8`,x2:`12`,y2:`12`},null,-1),_(`line`,{x1:`12`,y1:`16`,x2:`12.01`,y2:`16`},null,-1)]])):(d(),m(`svg`,ue,[...t[6]||=[_(`path`,{d:`M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7`},null,-1),_(`path`,{d:`M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z`},null,-1)]]))],8,W),_(`button`,{class:`library__action-btn`,type:`button`,"aria-label":`Share ${e.originalFilename}`,onClick:t=>Ne(e.id)},[...t[8]||=[l(`<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true" data-v-695e06b8><circle cx="18" cy="5" r="3" data-v-695e06b8></circle><circle cx="6" cy="12" r="3" data-v-695e06b8></circle><circle cx="18" cy="19" r="3" data-v-695e06b8></circle><line x1="8.59" y1="13.51" x2="15.42" y2="17.49" data-v-695e06b8></line><line x1="15.41" y1="6.51" x2="8.59" y2="10.49" data-v-695e06b8></line></svg>`,1)]],8,fe),_(`button`,{class:`library__action-btn library__action-btn--danger`,type:`button`,"aria-label":`Delete photo`,onClick:t=>Ie(e.id)},[...t[9]||=[l(`<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true" data-v-695e06b8><polyline points="3 6 5 6 21 6" data-v-695e06b8></polyline><path d="M19 6l-1 14H6L5 6" data-v-695e06b8></path><path d="M10 11v6M14 11v6" data-v-695e06b8></path><path d="M9 6V4h6v2" data-v-695e06b8></path></svg>`,1)]],8,pe)])]),r(x).devices.length>0?(d(),m(`div`,me,[(d(!0),m(p,null,u(r(x).devices,t=>(d(),m(`button`,{key:t.id,class:o([`library__approval-chip`,{"library__approval-chip--on":e.approvedDeviceIds.includes(t.id)}]),type:`button`,"aria-label":`${e.approvedDeviceIds.includes(t.id)?`Remove from`:`Add to`} ${t.name}`,onClick:n=>Fe(e.id,t.id,!e.approvedDeviceIds.includes(t.id))},h(t.name),11,he))),128))])):s(``,!0),r(x).devices.length>0?(d(),m(`div`,ge,[(d(!0),m(p,null,u(r(x).devices.filter(t=>e.approvedDeviceIds.includes(t.id)),n=>(d(),m(`button`,{key:n.id,class:o([`library__lock-chip`,{"library__lock-chip--on":n.lockedImageId===e.id}]),type:`button`,"aria-label":`${n.lockedImageId===e.id?`Unlock from`:`Lock to`} ${n.name}`,onClick:t=>Pe(e.id,n)},[(d(),m(`svg`,ve,[t[10]||=_(`rect`,{x:`3`,y:`11`,width:`18`,height:`11`,rx:`2`,ry:`2`},null,-1),n.lockedImageId===e.id?(d(),m(`path`,ye)):(d(),m(`path`,be))])),c(` `+h(n.name),1)],10,_e))),128))])):s(``,!0)]))),128))]))],64)),J.value===null?s(``,!0):(d(),a(ne,{key:3,modelValue:q.value,"onUpdate:modelValue":t[2]||=e=>q.value=e,"image-id":J.value},null,8,[`modelValue`,`image-id`])),i(k,{modelValue:Z.value,"onUpdate:modelValue":t[4]||=e=>Z.value=e,label:`Delete photo`},{default:y(()=>[t[13]||=_(`h2`,{class:`library__sheet-title`},`Delete this photo?`,-1),t[14]||=_(`p`,{class:`library__sheet-sub`},`It will be removed from all frames.`,-1),_(`div`,Me,[i(O,{variant:`secondary`,onClick:t[3]||=e=>Z.value=!1},{default:y(()=>[...t[12]||=[c(`Cancel`,-1)]]),_:1}),i(O,{variant:`destructive`,disabled:$.value,onClick:Le},{default:y(()=>[c(h($.value?`Deleting…`:`Delete`),1)]),_:1},8,[`disabled`])])]),_:1},8,[`modelValue`])]))}}),[[`__scopeId`,`data-v-695e06b8`]]);export{G as default}; |