d31698e7b3
CI / test (push) Has been cancelled
StickerCanvas was being passed contextOrientation (the target device's orientation), so the final composited.jpg was always sized to the device's aspect — even when the user toggled the crop tool to a different orientation. A landscape crop on a portrait device would produce a 1600x960 cropped blob, then the StickerCanvas would re-render it into a 960x1600 frame, visibly stretching the image into portrait dimensions and saving it that way. UploadView now derives an effectiveOrientation that prefers the user's chosen crop orientation (uploadStore.cropOrientation) and falls back to the device's orientation only before the crop step has run. The StickerCanvas honors that. Also adds a temporary debug log in the upload controller to verify the cropOrientation form field is arriving and being persisted — recent uploads have NULL cropOrientation despite the frontend sending it, and this log will make the next upload's payload visible. Will remove once diagnosed. 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-DuvRERmn.js";import{i as D,n as O,r as ee,t as k}from"./BaseBottomSheet-CPiyXFZV.js";import{t as A}from"./DevicePicker-B3wGBAmT.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}; |