Files
pictureFrame-webApp/public/build/assets/HomeView-eb15wpSB.js
T
football2801 08d0968af0
CI / test (push) Has been cancelled
feat(setup): post-link redirects to SPA so first-setup matches live UI
Twig configure page replaced with a redirect: SetupController's index,
register, login, and the legacy /configure route all post-link redirect
to /?setup=<deviceId> for unconfigured devices. The SPA's HomeView
auto-opens its existing settings sheet for that id, with the same
controls everyone uses for live edits — themed to the user's choice,
pre-populated from the device record.

Fixes Matt's report:
  - "every 6 hours" lost on save: the configure form posted
    rotation_interval_hours but the controller read
    rotation_interval_minutes, so the value silently defaulted to
    1440 every time. Now the SPA's PATCH flow handles it correctly.
  - "old settings still there in live settings": SPA settings sheet
    pre-populates from the device's current state via onEdit.
  - "uniqueness window in setup but not live settings": removed
    from the (now-deleted) Twig form; both surfaces are consistent.
  - "color scheme didn't match account": SPA respects the user's
    theme natively (data-theme on <html>), so the first-setup screen
    looks like the rest of the app.

Also adds a "Sign out of pictureFrame" link at the bottom of the
per-frame settings sheet (the existing /settings tab still has the
primary one). Easy escape hatch from a deeply-nested settings flow.

Tests:
  - SetupControllerTest: S-03/04/05/06/08 updated for new redirect
    targets, S-CLAIM-03 updated.
  - HomeView.test.ts: useRoute now mockable per-test, two new cases
    pinning the ?setup=<id> auto-open and its absence.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 18:51:31 -04:00

1 line
22 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import{B as e,C as t,D as n,E as r,H as i,K as a,R as o,_ as s,c,d as l,dt as u,f as ee,ft as d,g as te,i as f,j as p,k as m,m as h,p as g,pt as _,s as v,t as y,u as b,v as x,z as S}from"./_plugin-vue_export-helper-DRLwVS0w.js";import{c as ne,d as re,l as ie,o as ae,p as oe,s as se,u as C}from"./index-DX-aWmo9.js";import{i as w,n as T,r as ce,t as le}from"./BaseBottomSheet-DKEsd9DM.js";import{t as ue}from"./PullToRefresh-D9_uAhZQ.js";var E=`https://pictureframe.edholm.me/devices/`;function de(){let{devices:e}=f(w()),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`,E+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 D=[`src`,`alt`],O={class:`frame-card__body`},k={class:`frame-card__info`},A={class:`frame-card__name`},fe={class:`frame-card__status-line`,"aria-live":`polite`},j={class:`frame-card__status-text`},M={key:0,class:`frame-card__sync-line`},pe={key:0},me={key:1,class:`frame-card__sync-sep`,"aria-hidden":`true`},N={key:2},he={key:1,class:`frame-card__count`},P={key:0},F={key:1,"aria-hidden":`true`},I=y(x({__name:`FrameCard`,props:{deviceId:{},name:{},size:{},status:{},orientation:{},thumbnailUrl:{},photoCount:{},lastSync:{},nextSync:{}},emits:[`add-photo`,`edit`],setup(e){let t=e,n=b(()=>({})),r=b(()=>t.size===`large`?{aspectRatio:t.orientation===`portrait`?`3 / 5`:`5 / 3`}:{}),i=b(()=>{switch(t.status){case`ok`:return`Online`;case`sync-fail`:return`Sync issue`;case`offline`:return`Offline`}});return(t,a)=>(m(),h(`div`,{class:u([`frame-card`,`frame-card--${e.size}`,`frame-card--${e.status}`])},[e.size===`large`?(m(),h(`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]||=[l(`svg`,{width:`18`,height:`18`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`1.5`,"aria-hidden":`true`},[l(`circle`,{cx:`12`,cy:`12`,r:`3`}),l(`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)]])):g(``,!0),l(`div`,{class:`frame-card__preview`,style:d(n.value)},[e.thumbnailUrl?(m(),h(`img`,{key:0,src:e.thumbnailUrl,alt:`Current photo on ${e.name}`,class:`frame-card__img`},null,8,D)):(m(),h(`div`,{key:1,class:`frame-card__empty-preview`,style:d(r.value),"aria-hidden":`true`},[...a[3]||=[l(`svg`,{width:`32`,height:`32`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`1.5`},[l(`rect`,{x:`3`,y:`3`,width:`18`,height:`18`,rx:`2`}),l(`circle`,{cx:`8.5`,cy:`8.5`,r:`1.5`}),l(`polyline`,{points:`21,15 16,10 5,21`})],-1)]],4))],4),l(`div`,O,[l(`div`,k,[l(`p`,A,_(e.name),1),l(`p`,fe,[a[4]||=l(`span`,{class:`frame-card__status-dot`,"aria-hidden":`true`},null,-1),l(`span`,j,_(i.value),1)]),e.size===`large`&&(e.lastSync||e.nextSync)?(m(),h(`p`,M,[e.lastSync?(m(),h(`span`,pe,`synced `+_(e.lastSync),1)):g(``,!0),e.lastSync&&e.nextSync?(m(),h(`span`,me,`·`)):g(``,!0),e.nextSync?(m(),h(`span`,N,_(e.nextSync),1)):g(``,!0)])):e.size===`compact`&&e.photoCount!==void 0?(m(),h(`p`,he,_(e.photoCount)+` `+_(e.photoCount===1?`photo`:`photos`),1)):g(``,!0)]),s(T,{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:S(()=>[e.size===`large`?(m(),h(`span`,P,`+ Add Photo`)):(m(),h(`span`,F,`+`))]),_:1},8,[`variant`,`aria-label`])])],2))}}),[[`__scopeId`,`data-v-608d39a4`]]),L=[`id`,`value`,`type`],R=[`for`],z=[`id`],ge=y(x({__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=b(()=>r.id??`input-${Math.random().toString(36).slice(2)}`);return(n,r)=>(m(),h(`div`,{class:u([`input-wrap`,{"input-wrap--error":!!e.error,"input-wrap--filled":!!e.modelValue}])},[l(`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,L),l(`label`,{for:a.value,class:`input-wrap__label`},_(e.label),9,R),e.error?(m(),h(`p`,{key:0,id:`${a.value}-error`,class:`input-wrap__error`,role:`alert`},_(e.error),9,z)):g(``,!0)],2))}}),[[`__scopeId`,`data-v-c8235ab2`]]),B={class:`orientation-picker`,role:`radiogroup`,"aria-label":`Display orientation`},V=[`aria-checked`,`aria-label`,`onClick`],H=[`viewBox`],U=[`stroke`,`fill`],W=[`fill`],G={class:`orientation-opt__label`},K={class:`orientation-opt__sub`},_e=y(x({__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)=>(m(),h(`div`,B,[(m(),h(v,null,p(n,n=>l(`button`,{key:n.value,type:`button`,role:`radio`,"aria-checked":e.modelValue===n.value,"aria-label":n.label,class:u([`orientation-opt`,{"orientation-opt--active":e.modelValue===n.value}]),onClick:e=>r.$emit(`update:modelValue`,n.value)},[(m(),h(`svg`,{class:`orientation-opt__diagram`,viewBox:n.viewBox,fill:`none`,"aria-hidden":`true`},[l(`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,U),l(`rect`,t({ref_for:!0},n.ribbon,{fill:e.modelValue===n.value?`var(--color-primary)`:`var(--color-text-muted)`,rx:`1`}),null,16,W)],8,H)),l(`span`,G,_(n.label),1),l(`span`,K,_(n.sub),1)],10,V)),64))]))}}),[[`__scopeId`,`data-v-679dae08`]]),ve={class:`home-view`},ye={key:0,class:`home-view__loading`,"aria-live":`polite`},be={key:1,class:`home-view__empty`},xe={key:2,class:`home-view__single`},Se=[`aria-label`],Ce={class:`home-view__sheet-field`},we={class:`home-view__sheet-field`},Te={class:`home-view__sheet-field`},Ee={key:0,class:`home-view__times-mode`},De={class:`home-view__times-list`},Oe=[`value`,`onChange`],ke=[`value`],Ae=[`value`,`onChange`],je=[`value`],Me=[`value`,`onChange`],Ne=[`aria-label`,`onClick`],Pe={key:0,class:`home-view__times-empty`},Fe=[`label`],Ie=[`value`],Le={key:1,class:`home-view__interval-mode`},Re={class:`home-view__interval-input-row`},ze={class:`home-view__next-update`,"aria-live":`polite`},Be={class:`home-view__sheet-field`},Ve={class:`home-view__rotation-checkbox`},He={class:`home-view__remove-modal-card`},Ue={class:`home-view__remove-confirm-actions`},We=[`disabled`],Ge=[`disabled`],q=y(x({__name:`HomeView`,setup(t){function o(e){return e.wakeTimes.length>0?1440*60*1e3:e.rotationIntervalMinutes*6e4}function u(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 d(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 f(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 y(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 x(e,t){if(e.length===0)return null;let n=y(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 E(e){let t=null;if(e.nextPollExpectedAt)t=new Date(e.nextPollExpectedAt).getTime();else if(e.wakeTimes.length>0){let t=x(e.wakeTimes,e.timezone||`UTC`);return t?`next sync ~${f(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=y(new Date(t),n),i=Ze(new Date(t),n),a=i===0?`today`:i===1?`tomorrow`:`in ${i}d`;return`next sync ~${f(r)} ${a}`}return`next sync in ${Math.round(n/864e5)}d`}function D(e){return e.currentImageId?`/api/devices/${e.id}/preview?v=${e.currentImageId}`:void 0}let O=se(),k=ae(),A=w(),fe=ce();de(),r(async()=>{await A.fetchDevices(),document.addEventListener(`visibilitychange`,j);let e=Number(k.query.setup);e&&($(e),O.replace({query:{...k.query,setup:void 0}}))}),n(()=>{document.removeEventListener(`visibilitychange`,j)});function j(){document.visibilityState===`visible`&&A.fetchDevices({silent:!0})}let M=i(null);function pe(){return window.scrollY>0?!1:(M.value?.scrollTop??0)===0}async function me(){await A.fetchDevices({silent:!0})}function N(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&&(fe.init(n,e),O.push(`/upload`))},t.click()}let he=[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 L(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),Ke=[540,1080,720,1260,360,900,450,1170,0];function qe(){for(let e of Ke)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 Je(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]=L(i,a,o),q.value=s}let Ye=b(()=>{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?Xe(r,e.wakeTimes,t):r+e.rotationIntervalMinutes*6e4}else return`Next update: when the frame next connects`;return n<Date.now()&&(n=Date.now()),Qe(n,t)});function Xe(e,t,n){let r=y(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 Ze(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 Qe(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=y(new Date(e),t),i=Ze(new Date(e),t),a=i===0?`today`:i===1?`tomorrow`:`in ${i} days`;return`Next update: ~${f(r)} ${a}`}function $(e){let t=A.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 $e(){if(U.value){V.value=!0;try{await A.removeDevice(U.value.id),z.value=!1,H.value=!1}finally{V.value=!1}}}async function et(){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 A.updateDevice(U.value.id,e),z.value=!1}finally{B.value=!1}}}return(t,n)=>(m(),h(v,null,[l(`main`,ve,[s(ue,{"is-at-top":pe,"on-refresh":me},{default:S(()=>[a(A).loading?(m(),h(`div`,ye,` Loading… `)):a(A).devices.length===0?(m(),h(`div`,be,[...n[11]||=[l(`div`,{class:`home-view__empty-card`},[l(`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`},[l(`rect`,{x:`3`,y:`3`,width:`18`,height:`18`,rx:`2`}),l(`circle`,{cx:`8.5`,cy:`8.5`,r:`1.5`}),l(`polyline`,{points:`21,15 16,10 5,21`})]),l(`p`,{class:`home-view__empty-title`},`Set up your first frame`),l(`p`,{class:`home-view__empty-sub`},` Power on your pictureFrame device and scan the QR code it displays to get started. `)],-1)]])):a(A).devices.length===1?(m(),h(`div`,xe,[s(I,{deviceId:a(A).devices[0].id,name:a(A).devices[0].name,size:`large`,status:u(a(A).devices[0]),orientation:a(A).devices[0].orientation,thumbnailUrl:D(a(A).devices[0]),lastSync:d(a(A).devices[0]),nextSync:E(a(A).devices[0]),onAddPhoto:N,onEdit:$},null,8,[`deviceId`,`name`,`status`,`orientation`,`thumbnailUrl`,`lastSync`,`nextSync`])])):(m(),h(`div`,{key:3,ref_key:`stackEl`,ref:M,class:`home-view__stack`,role:`list`,"aria-label":`Frames`},[(m(!0),h(v,null,p(a(A).devices,e=>(m(),h(`div`,{key:e.id,class:`home-view__slide`,role:`listitem`,"aria-label":e.name},[s(I,{deviceId:e.id,name:e.name,size:`large`,status:u(e),orientation:e.orientation,thumbnailUrl:D(e),lastSync:d(e),nextSync:E(e),onAddPhoto:N,onEdit:$},null,8,[`deviceId`,`name`,`status`,`orientation`,`thumbnailUrl`,`lastSync`,`nextSync`])],8,Se))),128))],512))]),_:1})]),s(le,{modelValue:z.value,"onUpdate:modelValue":n[8]||=e=>z.value=e,label:`Frame settings`},{default:S(()=>[n[24]||=l(`h2`,{class:`home-view__sheet-title`},`Frame settings`,-1),l(`div`,Ce,[s(ge,{modelValue:W.value,"onUpdate:modelValue":n[0]||=e=>W.value=e,label:`Frame name`,maxlength:`100`},null,8,[`modelValue`])]),l(`div`,we,[n[12]||=l(`p`,{class:`home-view__sheet-label`},`Orientation`,-1),s(_e,{modelValue:G.value,"onUpdate:modelValue":n[1]||=e=>G.value=e},null,8,[`modelValue`])]),l(`div`,Te,[n[19]||=l(`p`,{class:`home-view__sheet-label`},`Update frequency`,-1),e(l(`select`,{class:`home-view__mode-select`,"onUpdate:modelValue":n[2]||=e=>K.value=e,"aria-label":`Update frequency mode`},[...n[13]||=[l(`option`,{value:`times`},`At specific time(s)`,-1),l(`option`,{value:`interval`},`Every X minutes`,-1)]],512),[[C,K.value]]),K.value===`times`?(m(),h(`div`,Ee,[l(`div`,De,[(m(!0),h(v,null,p(q.value,(e,t)=>(m(),h(`div`,{key:t,class:`home-view__time-row`},[l(`select`,{class:`home-view__time-part`,value:F(e).h,"aria-label":`Hour`,onChange:e=>Q(t,`h`,e.target.value)},[(m(),h(v,null,p(he,e=>l(`option`,{key:e,value:e},_(e),9,ke)),64))],40,Oe),n[16]||=l(`span`,{class:`home-view__time-sep`},`:`,-1),l(`select`,{class:`home-view__time-part`,value:F(e).mm,"aria-label":`Minutes`,onChange:e=>Q(t,`mm`,e.target.value)},[(m(),h(v,null,p(P,e=>l(`option`,{key:e,value:e},_(String(e).padStart(2,`0`)),9,je)),64))],40,Ae),l(`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[14]||=[l(`option`,{value:`AM`},`AM`,-1),l(`option`,{value:`PM`},`PM`,-1)]],40,Me),l(`button`,{type:`button`,class:`home-view__time-remove`,"aria-label":`Remove ${f(e)}`,onClick:e=>Je(t)},[...n[15]||=[l(`svg`,{width:`18`,height:`18`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"aria-hidden":`true`},[l(`polyline`,{points:`3 6 5 6 21 6`}),l(`path`,{d:`M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6`}),l(`path`,{d:`M10 11v6`}),l(`path`,{d:`M14 11v6`})],-1)]],8,Ne)]))),128)),q.value.length===0?(m(),h(`p`,Pe,`No update times yet — add one below.`)):g(``,!0)]),l(`button`,{type:`button`,class:`home-view__time-add`,onClick:qe},`+ Add time`),e(l(`select`,{class:`home-view__tz-select`,"onUpdate:modelValue":n[3]||=e=>Y.value=e},[(m(),h(v,null,p(R,e=>l(`optgroup`,{key:e.label,label:e.label},[(m(!0),h(v,null,p(e.zones,e=>(m(),h(`option`,{key:e.value,value:e.value},_(e.label),9,Ie))),128))],8,Fe)),64))],512),[[C,Y.value]])])):(m(),h(`div`,Le,[l(`div`,Re,[n[17]||=l(`span`,null,`Every`,-1),e(l(`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),[[re,J.value,void 0,{number:!0}]]),n[18]||=l(`span`,null,`minutes`,-1)])])),l(`p`,ze,_(Ye.value),1),n[20]||=l(`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 frames power. `,-1)]),l(`div`,Be,[n[23]||=l(`p`,{class:`home-view__sheet-label`},`Image selection`,-1),e(l(`select`,{class:`home-view__mode-select`,"onUpdate:modelValue":n[5]||=e=>X.value=e,"aria-label":`Image selection mode`},[...n[21]||=[l(`option`,{value:`oldest_upload`},`Oldest upload first`,-1),l(`option`,{value:`newest_upload`},`Newest upload first`,-1),l(`option`,{value:`least_recently_shown`},`Least recently shown`,-1),l(`option`,{value:`random`},`Random`,-1)]],512),[[C,X.value]]),l(`label`,Ve,[e(l(`input`,{type:`checkbox`,"onUpdate:modelValue":n[6]||=e=>Z.value=e},null,512),[[ie,Z.value]]),n[22]||=l(`span`,null,`Show never-shown images first`,-1)])]),s(T,{variant:`primary`,class:`home-view__sheet-save`,disabled:B.value,onClick:et},{default:S(()=>[te(_(B.value?`Saving…`:`Save`),1)]),_:1},8,[`disabled`]),l(`button`,{type:`button`,class:`home-view__remove`,onClick:n[7]||=e=>H.value=!0},`Remove this frame`),n[25]||=l(`a`,{href:`/logout`,class:`home-view__logout`},`Sign out of pictureFrame`,-1)]),_:1},8,[`modelValue`]),(m(),ee(c,{to:`body`},[s(ne,{name:`home-view__remove-modal`},{default:S(()=>[H.value?(m(),h(`div`,{key:0,class:`home-view__remove-modal`,role:`alertdialog`,"aria-labelledby":`remove-confirm-title`,onClick:n[10]||=oe(e=>H.value=!1,[`self`])},[l(`div`,He,[n[26]||=l(`p`,{class:`home-view__remove-confirm-title`,id:`remove-confirm-title`},` Remove this frame? `,-1),n[27]||=l(`p`,{class:`home-view__remove-confirm-body`},` Use this if youre 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 cant be undone. `,-1),n[28]||=l(`p`,{class:`home-view__remove-confirm-aside`},` On the frame itself, the new owner can also do a factory reset by holding the small button on the back until the screen starts to flash. (If they only tap it briefly, the frame just refreshes its current image — keep holding until it flashes.) `,-1),l(`div`,Ue,[l(`button`,{type:`button`,class:`home-view__remove-cancel`,disabled:V.value,onClick:n[9]||=e=>H.value=!1},`Cancel`,8,We),l(`button`,{type:`button`,class:`home-view__remove-confirm-btn`,disabled:V.value,onClick:$e},_(V.value?`Removing…`:`Yes, remove`),9,Ge)])])])):g(``,!0)]),_:1})]))],64))}}),[[`__scopeId`,`data-v-78d7cbb7`]]);export{q as default};