e4f811581a
CI / test (push) Has been cancelled
Three coordinated UX changes touching defaults and the settings sheet.
1. Server defaults: DeviceService::linkToUser now sets timezone =
user.timezone and wakeTimes = [12*60] (noon-daily) when creating a
new Device row OR transferring ownership on takeover. Replaces the
prior "1440-min interval anchored to last-seen-time" default that
could land a recipient's first photo at 3 am.
2. PWA propagation note: now mentions "briefly disconnect and reconnect
the frame's power" as the immediate-refresh gesture. Pairs with the
existing X-Boot-Reason: cold force-resync — the firmware already
honors a power-cycle as a deliberate refresh request, but users had
no way to discover that.
3. Remove-this-frame: replaced the native window.confirm() with an
in-sheet confirmation panel showing the explanatory text. Inline
keeps the gesture inside the existing sheet flow and gives the
destructive button a fixed location, instead of a floating native
dialog that varies per browser. The confirm body explicitly says
"this can't be undone" to match the irreversibility.
Tests:
- DeviceServiceTest: new-device default, takeover-resets-with-default,
UTC fallback when user has empty timezone.
- SetupControllerTest: claim-takes-over-defaults updated to assert
[12*60] wakeTimes.
- HomeView.test: 4 cases covering open-confirm, yes-confirm, cancel,
propagation-note text.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 line
22 KiB
JavaScript
1 line
22 KiB
JavaScript
import{B as e,C as t,D as n,E as r,H as i,K as a,R as o,_ as s,d as c,dt as l,ft as u,g as ee,i as d,j as f,k as p,m,p as h,pt as g,s as _,t as v,u as y,v as b,z as x}from"./_plugin-vue_export-helper-DRLwVS0w.js";import{d as te,l as ne,s as re,u as S}from"./index-CPVhLfHG.js";import{i as C,n as w,r as ie,t as ae}from"./BaseBottomSheet-C-CffjbC.js";import{t as oe}from"./PullToRefresh-D9_uAhZQ.js";var T=`https://pictureframe.edholm.me/devices/`;function se(){let{devices:e}=d(C()),t=new Map,r=new Map,i=window.__PF_MERCURE_URL__;if(!i)return{connectedCount:()=>0};function a(n){if(!t.has(n))try{let o=new URL(i);o.searchParams.append(`topic`,T+n);let c=new EventSource(o.toString(),{withCredentials:!0});c.onmessage=t=>{try{let n=JSON.parse(t.data);if(`deleted`in n&&n.deleted===!0){e.value=e.value.filter(e=>e.id!==n.id),s(n.id);return}let r=n,i=e.value.findIndex(e=>e.id===r.id);i!==-1&&(e.value[i]=r)}catch(e){console.warn(`[mercure] parse error`,e)}},c.onerror=()=>{if(c.readyState===EventSource.CLOSED){s(n);let e=window.setTimeout(()=>{r.delete(n),a(n)},5e3);r.set(n,e)}},t.set(n,c)}catch(e){console.warn(`[mercure] open failed for device `+n,e)}}function s(e){let n=t.get(e);n&&(n.close(),t.delete(e));let i=r.get(e);i!==void 0&&(clearTimeout(i),r.delete(e))}return o(e,e=>{let n=new Set(e.map(e=>e.id));for(let e of n)t.has(e)||a(e);for(let e of[...t.keys()])n.has(e)||s(e)},{immediate:!0,deep:!1}),n(()=>{for(let e of[...t.keys()])s(e)}),{connectedCount:()=>t.size}}var E=[`src`,`alt`],ce={class:`frame-card__body`},D={class:`frame-card__info`},le={class:`frame-card__name`},O={class:`frame-card__status-line`,"aria-live":`polite`},k={class:`frame-card__status-text`},A={key:0,class:`frame-card__sync-line`},j={key:0},M={key:1,class:`frame-card__sync-sep`,"aria-hidden":`true`},N={key:2},P={key:1,class:`frame-card__count`},F={key:0},I={key:1,"aria-hidden":`true`},L=v(b({__name:`FrameCard`,props:{deviceId:{},name:{},size:{},status:{},orientation:{},thumbnailUrl:{},photoCount:{},lastSync:{},nextSync:{}},emits:[`add-photo`,`edit`],setup(e){let t=e,n=y(()=>({})),r=y(()=>t.size===`large`?{aspectRatio:t.orientation===`portrait`?`3 / 5`:`5 / 3`}:{}),i=y(()=>{switch(t.status){case`ok`:return`Online`;case`sync-fail`:return`Sync issue`;case`offline`:return`Offline`}});return(t,a)=>(p(),m(`div`,{class:l([`frame-card`,`frame-card--${e.size}`,`frame-card--${e.status}`])},[e.size===`large`?(p(),m(`button`,{key:0,class:`frame-card__settings-btn`,type:`button`,"aria-label":`Frame settings`,onClick:a[0]||=n=>t.$emit(`edit`,e.deviceId)},[...a[2]||=[c(`svg`,{width:`18`,height:`18`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`1.5`,"aria-hidden":`true`},[c(`circle`,{cx:`12`,cy:`12`,r:`3`}),c(`path`,{d:`M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z`})],-1)]])):h(``,!0),c(`div`,{class:`frame-card__preview`,style:u(n.value)},[e.thumbnailUrl?(p(),m(`img`,{key:0,src:e.thumbnailUrl,alt:`Current photo on ${e.name}`,class:`frame-card__img`},null,8,E)):(p(),m(`div`,{key:1,class:`frame-card__empty-preview`,style:u(r.value),"aria-hidden":`true`},[...a[3]||=[c(`svg`,{width:`32`,height:`32`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`1.5`},[c(`rect`,{x:`3`,y:`3`,width:`18`,height:`18`,rx:`2`}),c(`circle`,{cx:`8.5`,cy:`8.5`,r:`1.5`}),c(`polyline`,{points:`21,15 16,10 5,21`})],-1)]],4))],4),c(`div`,ce,[c(`div`,D,[c(`p`,le,g(e.name),1),c(`p`,O,[a[4]||=c(`span`,{class:`frame-card__status-dot`,"aria-hidden":`true`},null,-1),c(`span`,k,g(i.value),1)]),e.size===`large`&&(e.lastSync||e.nextSync)?(p(),m(`p`,A,[e.lastSync?(p(),m(`span`,j,`synced `+g(e.lastSync),1)):h(``,!0),e.lastSync&&e.nextSync?(p(),m(`span`,M,`·`)):h(``,!0),e.nextSync?(p(),m(`span`,N,g(e.nextSync),1)):h(``,!0)])):e.size===`compact`&&e.photoCount!==void 0?(p(),m(`p`,P,g(e.photoCount)+` `+g(e.photoCount===1?`photo`:`photos`),1)):h(``,!0)]),s(w,{variant:e.size===`large`?`primary`:`icon-pill`,"aria-label":`Add photo to ${e.name}`,class:`frame-card__add-btn`,onClick:a[1]||=n=>t.$emit(`add-photo`,e.deviceId)},{default:x(()=>[e.size===`large`?(p(),m(`span`,F,`+ Add Photo`)):(p(),m(`span`,I,`+`))]),_:1},8,[`variant`,`aria-label`])])],2))}}),[[`__scopeId`,`data-v-608d39a4`]]),R=[`id`,`value`,`type`],z=[`for`],B=[`id`],ue=v(b({__name:`BaseInput`,props:{modelValue:{default:``},label:{},type:{default:`text`},error:{},id:{}},emits:[`update:modelValue`,`blur`],setup(e,{emit:n}){let r=e,i=n,a=y(()=>r.id??`input-${Math.random().toString(36).slice(2)}`);return(n,r)=>(p(),m(`div`,{class:l([`input-wrap`,{"input-wrap--error":!!e.error,"input-wrap--filled":!!e.modelValue}])},[c(`input`,t({id:a.value},n.$attrs,{value:e.modelValue,type:e.type,class:`input-wrap__field`,placeholder:` `,onInput:r[0]||=e=>i(`update:modelValue`,e.target.value),onBlur:r[1]||=e=>i(`blur`,e)}),null,16,R),c(`label`,{for:a.value,class:`input-wrap__label`},g(e.label),9,z),e.error?(p(),m(`p`,{key:0,id:`${a.value}-error`,class:`input-wrap__error`,role:`alert`},g(e.error),9,B)):h(``,!0)],2))}}),[[`__scopeId`,`data-v-c8235ab2`]]),V={class:`orientation-picker`,role:`radiogroup`,"aria-label":`Display orientation`},H=[`aria-checked`,`aria-label`,`onClick`],U=[`viewBox`],W=[`stroke`,`fill`],G=[`fill`],K={class:`orientation-opt__label`},q={class:`orientation-opt__sub`},de=v(b({__name:`OrientationPicker`,props:{modelValue:{}},emits:[`update:modelValue`],setup(e){let n=[{value:`landscape`,label:`Landscape`,sub:`Ribbon at bottom`,viewBox:`0 0 48 48`,rect:{x:4,y:12,width:40,height:24},ribbon:{x:20,y:36,width:8,height:5}},{value:`portrait`,label:`Portrait`,sub:`Ribbon on left`,viewBox:`0 0 48 48`,rect:{x:12,y:4,width:24,height:40},ribbon:{x:7,y:20,width:5,height:8}}];return(r,i)=>(p(),m(`div`,V,[(p(),m(_,null,f(n,n=>c(`button`,{key:n.value,type:`button`,role:`radio`,"aria-checked":e.modelValue===n.value,"aria-label":n.label,class:l([`orientation-opt`,{"orientation-opt--active":e.modelValue===n.value}]),onClick:e=>r.$emit(`update:modelValue`,n.value)},[(p(),m(`svg`,{class:`orientation-opt__diagram`,viewBox:n.viewBox,fill:`none`,"aria-hidden":`true`},[c(`rect`,t({ref_for:!0},n.rect,{rx:`2`,stroke:e.modelValue===n.value?`var(--color-primary)`:`currentColor`,"stroke-width":`1.5`,fill:e.modelValue===n.value?`color-mix(in srgb, var(--color-primary) 12%, transparent)`:`var(--color-surface-2)`}),null,16,W),c(`rect`,t({ref_for:!0},n.ribbon,{fill:e.modelValue===n.value?`var(--color-primary)`:`var(--color-text-muted)`,rx:`1`}),null,16,G)],8,U)),c(`span`,K,g(n.label),1),c(`span`,q,g(n.sub),1)],10,H)),64))]))}}),[[`__scopeId`,`data-v-679dae08`]]),fe={class:`home-view`},pe={key:0,class:`home-view__loading`,"aria-live":`polite`},me={key:1,class:`home-view__empty`},he={key:2,class:`home-view__single`},ge=[`aria-label`],_e={class:`home-view__sheet-field`},ve={class:`home-view__sheet-field`},ye={class:`home-view__sheet-field`},be={key:0,class:`home-view__times-mode`},xe={class:`home-view__times-list`},Se=[`value`,`onChange`],Ce=[`value`],we=[`value`,`onChange`],Te=[`value`],Ee=[`value`,`onChange`],De=[`aria-label`,`onClick`],Oe={key:0,class:`home-view__times-empty`},ke=[`label`],Ae=[`value`],je={key:1,class:`home-view__interval-mode`},Me={class:`home-view__interval-input-row`},Ne={class:`home-view__next-update`,"aria-live":`polite`},Pe={class:`home-view__sheet-field`},Fe={class:`home-view__rotation-checkbox`},Ie={key:1,class:`home-view__remove-confirm`,role:`alertdialog`,"aria-labelledby":`remove-confirm-title`},Le={class:`home-view__remove-confirm-actions`},Re=[`disabled`],ze=[`disabled`],J=v(b({__name:`HomeView`,setup(t){function o(e){return e.wakeTimes.length>0?1440*60*1e3:e.rotationIntervalMinutes*6e4}function l(e){if(!e.lastSeenAt)return`offline`;let t=Date.now()-new Date(e.lastSeenAt).getTime(),n=o(e);return t<=n?`ok`:t<=2*n?`sync-fail`:`offline`}function u(e){if(!e.lastSeenAt)return null;let t=Date.now()-new Date(e.lastSeenAt).getTime();if(t<6e4)return`just now`;if(t<36e5)return`${Math.round(t/6e4)}m ago`;if(t<864e5)return`${Math.round(t/36e5)}h ago`;let n=Math.round(t/864e5);return n===1?`yesterday`:`${n} days ago`}function d(e){let t=Math.floor(e/60),n=e%60,r=t>=12?`PM`:`AM`,i=t%12;i===0&&(i=12);let a=n===0?``:`:${String(n).padStart(2,`0`)}`;return`${i}${a} ${r}`}function v(e,t){let n=new Intl.DateTimeFormat(`en-GB`,{timeZone:t,hour:`2-digit`,minute:`2-digit`,hour12:!1}).formatToParts(e),r=parseInt(n.find(e=>e.type===`hour`)?.value??`0`,10),i=parseInt(n.find(e=>e.type===`minute`)?.value??`0`,10);return r*60+i}function b(e,t){if(e.length===0)return null;let n=v(new Date,t),r=null,i=1/0;for(let t of e){let e=t>n?t-n:1440+(t-n);e<i&&(i=e,r={minutes:t,today:t>n})}return r}function T(e){let t=null;if(e.nextPollExpectedAt)t=new Date(e.nextPollExpectedAt).getTime();else if(e.wakeTimes.length>0){let t=b(e.wakeTimes,e.timezone||`UTC`);return t?`next sync ~${d(t.minutes)} ${t.today?`today`:`tomorrow`}`:null}else if(e.lastSeenAt)t=new Date(e.lastSeenAt).getTime()+e.rotationIntervalMinutes*6e4;else return null;let n=t-Date.now();if(n<=0)return null;if(n<6e4)return`next sync in <1m`;if(n<36e5)return`next sync in ${Math.round(n/6e4)}m`;if(n<864e5){let n=e.timezone||`UTC`,r=v(new Date(t),n),i=Ge(new Date(t),n),a=i===0?`today`:i===1?`tomorrow`:`in ${i}d`;return`next sync ~${d(r)} ${a}`}return`next sync in ${Math.round(n/864e5)}d`}function E(e){return e.currentImageId?`/api/devices/${e.id}/preview?v=${e.currentImageId}`:void 0}let ce=re(),D=C(),le=ie();se(),r(()=>{D.fetchDevices(),document.addEventListener(`visibilitychange`,O)}),n(()=>{document.removeEventListener(`visibilitychange`,O)});function O(){document.visibilityState===`visible`&&D.fetchDevices({silent:!0})}let k=i(null);function A(){return window.scrollY>0?!1:(k.value?.scrollTop??0)===0}async function j(){await D.fetchDevices({silent:!0})}function M(e){let t=document.createElement(`input`);t.type=`file`,t.accept=`image/jpeg,image/png,image/webp,image/gif`,t.onchange=()=>{let n=t.files?.[0];n&&(le.init(n,e),ce.push(`/upload`))},t.click()}let N=[1,2,3,4,5,6,7,8,9,10,11,12],P=[0,5,10,15,20,25,30,35,40,45,50,55];function F(e){let t=Math.floor(e/60),n=e%60,r=t>=12?`PM`:`AM`,i=t%12;return i===0&&(i=12),{h:i,mm:n,p:r}}function I(e,t,n){let r=e%12;return n===`PM`&&(r+=12),r*60+t}let R=[{label:`Americas`,zones:[{value:`America/New_York`,label:`Eastern — New York, Toronto`},{value:`America/Chicago`,label:`Central — Chicago, Mexico City`},{value:`America/Denver`,label:`Mountain — Denver, Calgary`},{value:`America/Phoenix`,label:`Mountain (no DST) — Phoenix`},{value:`America/Los_Angeles`,label:`Pacific — Los Angeles, Vancouver`},{value:`America/Anchorage`,label:`Alaska — Anchorage`},{value:`Pacific/Honolulu`,label:`Hawaii — Honolulu`},{value:`America/Sao_Paulo`,label:`Brasília — São Paulo`},{value:`America/Argentina/Buenos_Aires`,label:`Argentina — Buenos Aires`},{value:`America/Bogota`,label:`Colombia — Bogotá`}]},{label:`Europe`,zones:[{value:`Europe/London`,label:`GMT/BST — London, Dublin`},{value:`Europe/Lisbon`,label:`WET/WEST — Lisbon`},{value:`Europe/Paris`,label:`CET/CEST — Paris, Brussels, Amsterdam`},{value:`Europe/Berlin`,label:`CET/CEST — Berlin, Vienna, Zurich`},{value:`Europe/Stockholm`,label:`CET/CEST — Stockholm, Oslo, Copenhagen`},{value:`Europe/Helsinki`,label:`EET/EEST — Helsinki, Tallinn, Riga`},{value:`Europe/Warsaw`,label:`CET/CEST — Warsaw, Prague, Budapest`},{value:`Europe/Rome`,label:`CET/CEST — Rome, Madrid`},{value:`Europe/Athens`,label:`EET/EEST — Athens, Bucharest`},{value:`Europe/Istanbul`,label:`TRT — Istanbul`},{value:`Europe/Moscow`,label:`MSK — Moscow`}]},{label:`Asia & Pacific`,zones:[{value:`Asia/Dubai`,label:`GST — Dubai, Abu Dhabi`},{value:`Asia/Karachi`,label:`PKT — Karachi, Islamabad`},{value:`Asia/Kolkata`,label:`IST — India`},{value:`Asia/Dhaka`,label:`BST — Dhaka, Bangladesh`},{value:`Asia/Bangkok`,label:`ICT — Bangkok, Jakarta, Hanoi`},{value:`Asia/Singapore`,label:`SGT — Singapore, Kuala Lumpur`},{value:`Asia/Shanghai`,label:`CST — Beijing, Shanghai, Taipei`},{value:`Asia/Seoul`,label:`KST — Seoul`},{value:`Asia/Tokyo`,label:`JST — Tokyo`},{value:`Australia/Sydney`,label:`AEDT/AEST — Sydney, Melbourne`},{value:`Australia/Brisbane`,label:`AEST (no DST) — Brisbane`},{value:`Australia/Perth`,label:`AWST — Perth`},{value:`Pacific/Auckland`,label:`NZDT/NZST — Auckland`}]},{label:`Africa & Middle East`,zones:[{value:`Africa/Cairo`,label:`EET — Cairo`},{value:`Africa/Nairobi`,label:`EAT — Nairobi, East Africa`},{value:`Africa/Johannesburg`,label:`SAST — Johannesburg`},{value:`Africa/Lagos`,label:`WAT — Lagos, West Africa`}]},{label:`UTC`,zones:[{value:`UTC`,label:`UTC — Coordinated Universal Time`}]}],z=i(!1),B=i(!1),V=i(!1),H=i(!1),U=i(null),W=i(``),G=i(`landscape`),K=i(`interval`),q=i([]),J=i(60),Y=i(`UTC`),X=i(`oldest_upload`),Z=i(!1),Be=[540,1080,720,1260,360,900,450,1170,0];function Ve(){for(let e of Be)if(!q.value.includes(e)){q.value=[...q.value,e];return}for(let e=0;e<1440;e+=5)if(!q.value.includes(e)){q.value=[...q.value,e];return}}function He(e){q.value=q.value.filter((t,n)=>n!==e)}function Q(e,t,n){let r=F(q.value[e]),i=t===`h`?parseInt(n,10):r.h,a=t===`mm`?parseInt(n,10):r.mm,o=t===`p`?n:r.p,s=[...q.value];s[e]=I(i,a,o),q.value=s}let Ue=y(()=>{let e=U.value;if(!e)return``;let t=e.timezone||`UTC`,n;if(e.nextPollExpectedAt)n=new Date(e.nextPollExpectedAt).getTime();else if(e.lastSeenAt){let r=new Date(e.lastSeenAt).getTime();n=e.wakeTimes.length>0?We(r,e.wakeTimes,t):r+e.rotationIntervalMinutes*6e4}else return`Next update: when the frame next connects`;return n<Date.now()&&(n=Date.now()),Ke(n,t)});function We(e,t,n){let r=v(new Date(e),n),i=1/0;for(let e of t){let t=e-r;t<=0&&(t+=1440),t<i&&(i=t)}return e+i*6e4}function Ge(e,t){let n=new Intl.DateTimeFormat(`en-CA`,{timeZone:t,year:`numeric`,month:`2-digit`,day:`2-digit`}),r=Date.parse(n.format(new Date)+`T00:00:00Z`),i=Date.parse(n.format(e)+`T00:00:00Z`);return Math.round((i-r)/864e5)}function Ke(e,t){let n=e-Date.now();if(n<=0)return`Next update: any moment`;if(n<9e4)return`Next update: in <1 min`;if(n<36e5)return`Next update: in ~${Math.round(n/6e4)} min`;let r=v(new Date(e),t),i=Ge(new Date(e),t),a=i===0?`today`:i===1?`tomorrow`:`in ${i} days`;return`Next update: ~${d(r)} ${a}`}function $(e){let t=D.devices.find(t=>t.id===e);t&&(U.value=t,W.value=t.name,G.value=t.orientation,Y.value=t.timezone??`UTC`,J.value=t.rotationIntervalMinutes,q.value=[...t.wakeTimes],K.value=t.wakeTimes.length>0?`times`:`interval`,X.value=t.rotationMode,Z.value=t.prioritizeNeverShown,H.value=!1,z.value=!0)}async function qe(){if(U.value){V.value=!0;try{await D.removeDevice(U.value.id),z.value=!1,H.value=!1}finally{V.value=!1}}}async function Je(){if(U.value){B.value=!0;try{let e={name:W.value.trim()||U.value.name,orientation:G.value,timezone:Y.value,rotationMode:X.value,prioritizeNeverShown:Z.value};K.value===`times`?e.wakeTimes=[...q.value]:(e.wakeTimes=[],e.rotationIntervalMinutes=Math.max(1,Math.min(1440,J.value||1))),await D.updateDevice(U.value.id,e),z.value=!1}finally{B.value=!1}}}return(t,n)=>(p(),m(_,null,[c(`main`,fe,[s(oe,{"is-at-top":A,"on-refresh":j},{default:x(()=>[a(D).loading?(p(),m(`div`,pe,` Loading… `)):a(D).devices.length===0?(p(),m(`div`,me,[...n[10]||=[c(`div`,{class:`home-view__empty-card`},[c(`svg`,{class:`home-view__empty-icon`,width:`48`,height:`48`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`1.5`,"aria-hidden":`true`},[c(`rect`,{x:`3`,y:`3`,width:`18`,height:`18`,rx:`2`}),c(`circle`,{cx:`8.5`,cy:`8.5`,r:`1.5`}),c(`polyline`,{points:`21,15 16,10 5,21`})]),c(`p`,{class:`home-view__empty-title`},`Set up your first frame`),c(`p`,{class:`home-view__empty-sub`},` Power on your pictureFrame device and scan the QR code it displays to get started. `)],-1)]])):a(D).devices.length===1?(p(),m(`div`,he,[s(L,{deviceId:a(D).devices[0].id,name:a(D).devices[0].name,size:`large`,status:l(a(D).devices[0]),orientation:a(D).devices[0].orientation,thumbnailUrl:E(a(D).devices[0]),lastSync:u(a(D).devices[0]),nextSync:T(a(D).devices[0]),onAddPhoto:M,onEdit:$},null,8,[`deviceId`,`name`,`status`,`orientation`,`thumbnailUrl`,`lastSync`,`nextSync`])])):(p(),m(`div`,{key:3,ref_key:`stackEl`,ref:k,class:`home-view__stack`,role:`list`,"aria-label":`Frames`},[(p(!0),m(_,null,f(a(D).devices,e=>(p(),m(`div`,{key:e.id,class:`home-view__slide`,role:`listitem`,"aria-label":e.name},[s(L,{deviceId:e.id,name:e.name,size:`large`,status:l(e),orientation:e.orientation,thumbnailUrl:E(e),lastSync:u(e),nextSync:T(e),onAddPhoto:M,onEdit:$},null,8,[`deviceId`,`name`,`status`,`orientation`,`thumbnailUrl`,`lastSync`,`nextSync`])],8,ge))),128))],512))]),_:1})]),s(ae,{modelValue:z.value,"onUpdate:modelValue":n[9]||=e=>z.value=e,label:`Frame settings`},{default:x(()=>[n[25]||=c(`h2`,{class:`home-view__sheet-title`},`Frame settings`,-1),c(`div`,_e,[s(ue,{modelValue:W.value,"onUpdate:modelValue":n[0]||=e=>W.value=e,label:`Frame name`,maxlength:`100`},null,8,[`modelValue`])]),c(`div`,ve,[n[11]||=c(`p`,{class:`home-view__sheet-label`},`Orientation`,-1),s(de,{modelValue:G.value,"onUpdate:modelValue":n[1]||=e=>G.value=e},null,8,[`modelValue`])]),c(`div`,ye,[n[18]||=c(`p`,{class:`home-view__sheet-label`},`Update frequency`,-1),e(c(`select`,{class:`home-view__mode-select`,"onUpdate:modelValue":n[2]||=e=>K.value=e,"aria-label":`Update frequency mode`},[...n[12]||=[c(`option`,{value:`times`},`At specific time(s)`,-1),c(`option`,{value:`interval`},`Every X minutes`,-1)]],512),[[S,K.value]]),K.value===`times`?(p(),m(`div`,be,[c(`div`,xe,[(p(!0),m(_,null,f(q.value,(e,t)=>(p(),m(`div`,{key:t,class:`home-view__time-row`},[c(`select`,{class:`home-view__time-part`,value:F(e).h,"aria-label":`Hour`,onChange:e=>Q(t,`h`,e.target.value)},[(p(),m(_,null,f(N,e=>c(`option`,{key:e,value:e},g(e),9,Ce)),64))],40,Se),n[15]||=c(`span`,{class:`home-view__time-sep`},`:`,-1),c(`select`,{class:`home-view__time-part`,value:F(e).mm,"aria-label":`Minutes`,onChange:e=>Q(t,`mm`,e.target.value)},[(p(),m(_,null,f(P,e=>c(`option`,{key:e,value:e},g(String(e).padStart(2,`0`)),9,Te)),64))],40,we),c(`select`,{class:`home-view__time-part home-view__time-part--ampm`,value:F(e).p,"aria-label":`AM or PM`,onChange:e=>Q(t,`p`,e.target.value)},[...n[13]||=[c(`option`,{value:`AM`},`AM`,-1),c(`option`,{value:`PM`},`PM`,-1)]],40,Ee),c(`button`,{type:`button`,class:`home-view__time-remove`,"aria-label":`Remove ${d(e)}`,onClick:e=>He(t)},[...n[14]||=[c(`svg`,{width:`18`,height:`18`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"aria-hidden":`true`},[c(`polyline`,{points:`3 6 5 6 21 6`}),c(`path`,{d:`M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6`}),c(`path`,{d:`M10 11v6`}),c(`path`,{d:`M14 11v6`})],-1)]],8,De)]))),128)),q.value.length===0?(p(),m(`p`,Oe,`No update times yet — add one below.`)):h(``,!0)]),c(`button`,{type:`button`,class:`home-view__time-add`,onClick:Ve},`+ Add time`),e(c(`select`,{class:`home-view__tz-select`,"onUpdate:modelValue":n[3]||=e=>Y.value=e},[(p(),m(_,null,f(R,e=>c(`optgroup`,{key:e.label,label:e.label},[(p(!0),m(_,null,f(e.zones,e=>(p(),m(`option`,{key:e.value,value:e.value},g(e.label),9,Ae))),128))],8,ke)),64))],512),[[S,Y.value]])])):(p(),m(`div`,je,[c(`div`,Me,[n[16]||=c(`span`,null,`Every`,-1),e(c(`input`,{type:`number`,inputmode:`numeric`,pattern:`[0-9]*`,min:`1`,max:`1440`,class:`home-view__interval-input`,"onUpdate:modelValue":n[4]||=e=>J.value=e,"aria-label":`Update interval in minutes`},null,512),[[te,J.value,void 0,{number:!0}]]),n[17]||=c(`span`,null,`minutes`,-1)])])),c(`p`,Ne,g(Ue.value),1),n[19]||=c(`p`,{class:`home-view__propagation-note`},` Changes will only take effect at the next device update. To force an immediate refresh, briefly disconnect and reconnect the frame’s power. `,-1)]),c(`div`,Pe,[n[22]||=c(`p`,{class:`home-view__sheet-label`},`Image selection`,-1),e(c(`select`,{class:`home-view__mode-select`,"onUpdate:modelValue":n[5]||=e=>X.value=e,"aria-label":`Image selection mode`},[...n[20]||=[c(`option`,{value:`oldest_upload`},`Oldest upload first`,-1),c(`option`,{value:`newest_upload`},`Newest upload first`,-1),c(`option`,{value:`least_recently_shown`},`Least recently shown`,-1),c(`option`,{value:`random`},`Random`,-1)]],512),[[S,X.value]]),c(`label`,Fe,[e(c(`input`,{type:`checkbox`,"onUpdate:modelValue":n[6]||=e=>Z.value=e},null,512),[[ne,Z.value]]),n[21]||=c(`span`,null,`Show never-shown images first`,-1)])]),s(w,{variant:`primary`,class:`home-view__sheet-save`,disabled:B.value,onClick:Je},{default:x(()=>[ee(g(B.value?`Saving…`:`Save`),1)]),_:1},8,[`disabled`]),H.value?(p(),m(`div`,Ie,[n[23]||=c(`p`,{class:`home-view__remove-confirm-title`,id:`remove-confirm-title`},` Remove this frame? `,-1),n[24]||=c(`p`,{class:`home-view__remove-confirm-body`},` Use this if you’re selling or giving away the frame. It deletes this frame from your account and unlinks it from your photos so the next owner can claim it fresh. This can’t be undone. `,-1),c(`div`,Le,[c(`button`,{type:`button`,class:`home-view__remove-cancel`,disabled:V.value,onClick:n[8]||=e=>H.value=!1},`Cancel`,8,Re),c(`button`,{type:`button`,class:`home-view__remove-confirm-btn`,disabled:V.value,onClick:qe},g(V.value?`Removing…`:`Yes, remove`),9,ze)])])):(p(),m(`button`,{key:0,type:`button`,class:`home-view__remove`,onClick:n[7]||=e=>H.value=!0},`Remove this frame`))]),_:1},8,[`modelValue`])],64))}}),[[`__scopeId`,`data-v-556624d3`]]);export{J as default}; |