livedesk 0.1.685 → 0.1.686
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/livedesk.js +1 -0
- package/bootstrap/hub-self-agent.js +1 -0
- package/client/bin/livedesk-client.js +1 -1
- package/client/package.json +5 -5
- package/electron/main.mjs +3 -1
- package/hub/package.json +32 -32
- package/hub/src/console-direct.js +4 -1
- package/hub/src/console-direct.test.mjs +70 -4
- package/package.json +6 -6
- package/runtime-core/package.json +18 -18
- package/web/dist/app.html +1 -1
- package/web/dist/app.webmanifest +1 -1
- package/web/dist/assets/{AgentSettingsTab-C2yWMYVI.js → AgentSettingsTab-BpaAvVmS.js} +1 -1
- package/web/dist/assets/{AgentsPage-BlV_riNE.js → AgentsPage-CviietlX.js} +1 -1
- package/web/dist/assets/{CaptureGallery-Dbn6VhEu.js → CaptureGallery-v-uzDN4q.js} +1 -1
- package/web/dist/assets/HubApp-CEZWMXxq.js +182 -0
- package/web/dist/assets/{HubApp-DFLBNvIi.css → HubApp-DdHHVOM0.css} +1 -1
- package/web/dist/assets/MonitorStackIcon-JfWhLRS2.js +8 -0
- package/web/dist/assets/{SettingsPage-49Z3Hv0p.js → SettingsPage-XqN0yfRR.js} +1 -1
- package/web/dist/assets/{ShareFilesPage-BEOcL51r.js → ShareFilesPage-BcxBsXoN.js} +1 -1
- package/web/dist/assets/{SupportPage-CB0Hrnri.js → SupportPage-D_60jn3l.js} +1 -1
- package/web/dist/assets/{VuvoDeskApp-CFZWGgYH.js → VuvoDeskApp-DsIm_aTa.js} +1 -1
- package/web/dist/assets/{app-CoHWIYYA.js → app-DA8I23kG.js} +2 -2
- package/web/dist/assets/{main-D83bJX4i.js → main-B1P8Damh.js} +2 -2
- package/web/dist/assets/styles-CQz52HHV.css +1 -0
- package/web/dist/index.html +3 -3
- package/web/dist/sw.js +2 -2
- package/web/dist/vuvodesk-build-evidence.json +47 -47
- package/web/dist/assets/HubApp-CjBsQESw.js +0 -182
- package/web/dist/assets/MonitorStackIcon-BTi3OZ_m.js +0 -8
- package/web/dist/assets/styles-BjyLRq6m.css +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
.account-dialog-backdrop{position:fixed;inset:0;z-index:1700;display:grid;place-items:center;padding:20px;background:#080f1ca3;backdrop-filter:blur(5px);-webkit-backdrop-filter:blur(5px);overscroll-behavior:contain}.account-dialog{width:min(1120px,calc(100vw - 40px));max-height:min(860px,calc(100dvh - 40px));display:grid;grid-template-rows:auto minmax(0,1fr) auto;overflow:hidden;color:#172033;border:1px solid rgb(255 255 255 / 72%);border-radius:24px;background:#f8fafc;box-shadow:0 28px 80px #03081459}.account-dialog button,.account-dialog input{font:inherit}.account-dialog button{touch-action:manipulation}.account-dialog-header{min-height:88px;display:flex;align-items:center;justify-content:space-between;gap:24px;padding:18px 22px;border-bottom:1px solid #e5eaf1;background:#fff}.account-dialog-identity{min-width:0;display:flex;align-items:center;gap:14px}.account-dialog-identity>span:last-child{min-width:0;display:grid;gap:2px}.account-dialog-identity small,.account-section-heading>div>span,.account-current-plan-copy small{color:#68758a;font-size:11px;font-weight:750;letter-spacing:.055em;text-transform:uppercase}.account-dialog-identity strong{overflow:hidden;font-size:18px;line-height:1.25;text-overflow:ellipsis;white-space:nowrap}.account-dialog-identity>span:last-child>span{overflow:hidden;color:#6b7280;font-size:12px;text-overflow:ellipsis;white-space:nowrap}.account-dialog-avatar{width:50px;height:50px;flex:0 0 50px;display:grid;place-items:center;overflow:hidden;color:#fff;border-radius:16px;background:#172033;font-size:18px;font-weight:800}.account-dialog-avatar img{width:100%;height:100%;object-fit:cover}.account-dialog-close{width:40px;height:40px;flex:0 0 40px;display:grid;place-items:center;color:#5b6574;border:1px solid #dbe1e9;border-radius:12px;background:#f8fafc;cursor:pointer}.account-dialog-close:hover,.account-dialog-close:focus-visible{color:#111827;border-color:#aeb8c6;outline:3px solid rgb(91 87 255 / 16%)}.account-dialog-body{min-height:0;display:grid;gap:22px;padding:22px;overflow-y:auto;overscroll-behavior:contain}.account-workspace-switcher{display:grid;gap:9px}.account-workspace-switcher>div:first-child{display:flex;align-items:baseline;justify-content:space-between;gap:12px}.account-workspace-switcher>div:first-child>span{color:#273449;font-size:11px;font-weight:820;letter-spacing:.045em;text-transform:uppercase}.account-workspace-switcher>div:first-child>small{color:#7b8595;font-size:10px}.account-workspace-list{display:flex;gap:8px;overflow-x:auto;padding:2px;scrollbar-width:thin}.account-workspace-list button{min-width:195px;display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:9px;padding:10px;color:#435066;border:1px solid #dfe5ed;border-radius:12px;background:#fff;text-align:left;cursor:pointer}.account-workspace-list button.active{color:#2f2a70;border-color:#8c85e8;background:#f3f1ff;box-shadow:0 0 0 2px #5b57ff17}.account-workspace-list button:disabled:not(.active){opacity:.58;cursor:not-allowed}.account-workspace-list button>span:first-child{width:30px;height:30px;display:grid;place-items:center;color:#fff;border-radius:9px;background:#26354c}.account-workspace-list button.active>span:first-child{background:#5b57cf}.account-workspace-list button>span:nth-child(2){min-width:0;display:grid;gap:2px}.account-workspace-list button strong,.account-workspace-list button small{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.account-workspace-list button strong{font-size:11px}.account-workspace-list button small{color:#7b8595;font-size:9px}.account-workspace-list button em{color:#5a55a9;font-size:9px;font-style:normal;font-weight:800}.account-current-plan{display:grid;grid-template-columns:minmax(220px,1.1fr) minmax(190px,.75fr) minmax(220px,.9fr);align-items:center;gap:20px;padding:20px;color:#fff;border-radius:18px;background:linear-gradient(135deg,#111827,#25344d);box-shadow:0 12px 30px #0f172a24}.account-current-plan.plan-plus{background:linear-gradient(135deg,#312e81,#5b57ff)}.account-current-plan.plan-business{background:linear-gradient(135deg,#0f3f38,#117565)}.account-current-plan.plan-team{background:linear-gradient(135deg,#4c1d95,#7c3aed)}.account-current-plan-copy{min-width:0;display:flex;align-items:center;gap:13px}.account-current-plan-copy>span:last-child{min-width:0;display:grid;gap:3px}.account-current-plan-copy small,.account-current-plan-copy>span:last-child>span{color:#ffffffb3}.account-current-plan-copy strong{font-size:22px}.account-current-plan-copy>span:last-child>span{overflow:hidden;font-size:12px;text-overflow:ellipsis;white-space:nowrap}.account-current-plan-icon{width:42px;height:42px;flex:0 0 42px;display:grid;place-items:center;border:1px solid rgb(255 255 255 / 18%);border-radius:13px;background:#ffffff1f}.account-device-usage{display:grid;gap:6px}.account-device-usage>span:first-child{display:flex;align-items:center;gap:6px;color:#ffffffb8;font-size:11px;font-weight:700}.account-device-usage>strong{font-size:22px}.account-device-usage>strong small{color:#ffffffa6;font-size:12px;font-weight:650}.account-device-meter{width:100%;height:5px;overflow:hidden;border-radius:999px;background:#ffffff2e}.account-device-meter i{height:100%;display:block;border-radius:inherit;background:#fff}.account-runtime-facts{margin:0;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}.account-runtime-facts div{min-width:0;display:grid;gap:2px;padding:9px 11px;border:1px solid rgb(255 255 255 / 12%);border-radius:11px;background:#ffffff14}.account-runtime-facts dt{color:#fff9;font-size:10px}.account-runtime-facts dd{margin:0;overflow:hidden;font-size:11px;font-weight:700;text-overflow:ellipsis;white-space:nowrap}.account-plan-section,.account-team-panel{display:grid;gap:14px}.account-section-heading{display:flex;align-items:end;justify-content:space-between;gap:18px}.account-section-heading h2{margin:4px 0 0;color:#172033;font-size:17px;letter-spacing:-.02em}.account-section-heading>small{color:#68758a;font-size:11px;text-align:right}.account-plan-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px}.account-plan-card{min-width:0;display:grid;grid-template-rows:auto auto auto auto 1fr auto;gap:9px;padding:16px;border:1px solid #dfe5ed;border-radius:15px;background:#fff}.account-plan-card.current{border-color:#5b57ff;box-shadow:0 0 0 2px #5b57ff1c}.account-plan-card.plan-team{background:linear-gradient(180deg,#fbf9ff,#fff)}.account-plan-card-title{display:flex;align-items:center;justify-content:space-between;gap:8px}.account-plan-card-title>span{display:flex;align-items:center;gap:6px;color:#172033;font-size:14px;font-weight:800}.account-plan-card-title em{display:flex;align-items:center;gap:3px;padding:4px 6px;color:#4338ca;border-radius:999px;background:#eef2ff;font-size:9px;font-style:normal;font-weight:800;text-transform:uppercase}.account-plan-card>p{margin:0;color:#7a8494;font-size:11px}.account-plan-card>strong{color:#273449;font-size:12px}.account-plan-price{color:#172033;font-size:15px;font-weight:850;letter-spacing:-.025em}.account-plan-ltd-price{width:fit-content;padding:4px 7px;color:#075985;border:1px solid #bae6fd;border-radius:8px;background:#f0f9ff;font-size:10px;font-weight:800}.account-plan-card ul{margin:0;padding:0;display:grid;align-content:start;gap:7px;list-style:none}.account-plan-card li{display:flex;align-items:flex-start;gap:5px;color:#526075;font-size:10.5px;line-height:1.35}.account-plan-card li svg{flex:0 0 auto;margin-top:1px;color:#159275}.account-plan-action,.account-plan-state{min-height:34px;display:flex;align-items:center;justify-content:center;gap:6px;border-radius:10px;font-size:10.5px;font-weight:780}.account-plan-actions{display:grid;gap:6px}.account-plan-action{color:#fff;border:0;background:#172033;cursor:pointer}.account-plan-action.secondary{color:#273449;border:1px solid #cfd7e3;background:#f7f9fc}.account-plan-action.secondary:hover,.account-plan-action.secondary:focus-visible{color:#fff;border-color:#172033;background:#172033}.account-plan-action:hover,.account-plan-action:focus-visible{background:#000;outline:3px solid rgb(91 87 255 / 16%)}.account-plan-action:disabled{opacity:.5;cursor:not-allowed}.account-plan-state{color:#556176;border:1px solid #e3e7ed;background:#f6f8fa}.account-plan-card.current .account-plan-state{color:#4338ca;border-color:#d8d7ff;background:#f1f0ff}.account-team-panel{padding:18px;border:1px solid #dfd8f5;border-radius:16px;background:#fbf9ff}.account-team-members{margin:0;padding:0;display:grid;gap:7px;list-style:none}.account-team-rename{display:grid;gap:6px;margin-bottom:10px}.account-team-rename>label{color:#4e5a6c;font-size:10px;font-weight:750}.account-team-rename>span,.account-team-invite-compose{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:7px}.account-team-rename input,.account-team-rename button,.account-team-leave{height:38px;border-radius:10px;font-size:10.5px}.account-team-operator-note{margin:10px 0 0;padding:10px 12px;color:#514868;border:1px solid #ded6ef;border-radius:10px;background:#fff;font-size:10.5px;font-weight:700}.account-team-error{display:block;margin-top:8px;color:#b42318;font-size:10px}.account-session-revocation-error{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:.25rem .75rem;align-items:center;padding:.8rem .9rem;border:1px solid #fca5a5;border-radius:.75rem;background:#fff1f2;color:#7f1d1d}.account-session-revocation-error strong,.account-session-revocation-error span{grid-column:1}.account-session-revocation-error span{font-size:.8rem;color:#991b1b}.account-session-revocation-error button{grid-column:2;grid-row:1 / span 2;border:1px solid rgba(254,202,202,.42);border-radius:.55rem;padding:.55rem .7rem;background:#7f1d1d;color:#fff;cursor:pointer}.account-session-revocation-error button:disabled{cursor:wait;opacity:.6}.account-team-rename input{min-width:0;padding:0 11px;color:#172033;border:1px solid #d9d4e6;background:#fff}.account-team-rename button{padding:0 13px;color:#fff;border:0;background:#5b45bf;font-weight:780;cursor:pointer}.account-team-members li{display:grid;grid-template-columns:auto minmax(0,1fr) auto auto auto;align-items:center;gap:10px;padding:9px 10px;border:1px solid #e3dff0;border-radius:11px;background:#fff}.account-member-avatar{width:31px;height:31px;display:grid;place-items:center;color:#fff;border-radius:9px;background:#6d5bd0;font-size:11px;font-weight:800}.account-team-members li>span:nth-child(2){min-width:0;display:grid}.account-team-members li strong,.account-team-members li small{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.account-team-members li strong{font-size:11px}.account-team-members li small{color:#778195;font-size:9.5px}.account-team-members li em,.account-member-status{font-size:9px;font-style:normal;font-weight:750;text-transform:capitalize}.account-team-members li em{color:#4c3fb2}.account-member-status{padding:4px 6px;color:#17745f;border-radius:999px;background:#e7f7f1}.account-member-status.status-invited{color:#98620c;background:#fff5d9}.account-team-members li>button{color:#a23636;border:0;background:transparent;font-size:9.5px;font-weight:750;cursor:pointer}.account-team-invite{display:grid;gap:6px}.account-team-invite>label{color:#4e5a6c;font-size:10px;font-weight:750}.account-team-invite>span{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:7px}.account-team-invite input{min-width:0;height:38px;padding:0 11px;color:#172033;border:1px solid #d9d4e6;border-radius:10px;background:#fff;font-size:11px}.account-team-invite button{height:38px;display:flex;align-items:center;gap:6px;padding:0 13px;color:#fff;border:0;border-radius:10px;background:#5b45bf;font-size:10.5px;font-weight:780;cursor:pointer}.account-team-invite>.account-create-invite{width:fit-content}.account-team-invite-compose>.account-create-invite{width:auto}.account-team-invite-result{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:7px}.account-team-invite-result>small{grid-column:1 / -1;color:#746d86;font-size:9.5px}.account-team-invite>p{margin:0;color:#7a738b;font-size:9.5px}.account-team-invite button:disabled,.account-team-invite input:disabled{opacity:.55;cursor:not-allowed}.account-team-invite>small{color:#b42318;font-size:10px}.account-team-empty{margin:0;padding:15px;color:#6c6680;border:1px dashed #d6cde9;border-radius:11px;background:#ffffffb3;font-size:11px}.account-team-leave{width:fit-content;margin-top:10px;padding:0 13px;color:#a23636;border:1px solid #ead1d1;background:#fff;font-weight:750;cursor:pointer}.account-team-rename button:disabled,.account-team-rename input:disabled,.account-team-leave:disabled{opacity:.55;cursor:not-allowed}.account-dialog-footer{min-height:66px;display:flex;align-items:center;justify-content:space-between;gap:18px;padding:13px 22px;border-top:1px solid #e5eaf1;background:#fff}.account-dialog-footer>span{display:flex;align-items:center;gap:7px;color:#697589;font-size:11px}.account-auth-action{min-height:38px;display:flex;align-items:center;justify-content:center;gap:7px;padding:0 15px;color:#2c3749;border:1px solid #d8dee7;border-radius:11px;background:#fff;font-size:11px;font-weight:780;cursor:pointer}.account-auth-action.primary{color:#fff;border-color:#172033;background:#172033}.account-auth-action:disabled{opacity:.55;cursor:wait}@media(max-width:900px){.account-dialog{width:min(760px,calc(100vw - 24px));max-height:calc(100dvh - 24px);border-radius:20px}.account-dialog-backdrop{padding:12px}.account-current-plan{grid-template-columns:minmax(0,1fr) minmax(160px,.75fr)}.account-runtime-facts{grid-column:1 / -1}.account-plan-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(max-width:560px){.account-dialog-backdrop{align-items:stretch;padding:0}.account-dialog{width:100vw;max-height:100dvh;border:0;border-radius:0}.account-dialog-header{min-height:74px;padding:12px 14px}.account-dialog-avatar{width:42px;height:42px;flex-basis:42px;border-radius:13px}.account-dialog-identity strong{font-size:15px}.account-dialog-body{gap:18px;padding:14px}.account-current-plan{grid-template-columns:minmax(0,1fr);gap:14px;padding:16px}.account-runtime-facts{grid-column:auto}.account-section-heading{align-items:flex-start;flex-direction:column;gap:5px}.account-section-heading>small{text-align:left}.account-plan-grid{grid-template-columns:minmax(0,1fr)}.account-plan-card{min-height:auto}.account-team-members li{grid-template-columns:auto minmax(0,1fr) auto}.account-team-members li>em{grid-column:2}.account-member-status{grid-column:3;grid-row:1}.account-team-members li>button{grid-column:3;grid-row:2}.account-team-invite>span{grid-template-columns:minmax(0,1fr)}.account-team-invite button{justify-content:center}.account-dialog-footer{align-items:stretch;flex-direction:column;padding:11px 14px}.account-dialog-footer>span{line-height:1.4}.account-auth-action{width:100%}}@media(max-height:520px)and (orientation:landscape){.account-dialog-backdrop{padding:6px}.account-dialog{width:min(1000px,calc(100vw - 12px));max-height:calc(100dvh - 12px);border-radius:15px}.account-dialog-header{min-height:60px;padding:8px 14px}.account-dialog-avatar{width:38px;height:38px;flex-basis:38px;border-radius:11px}.account-dialog-body{gap:14px;padding:12px 14px}.account-current-plan{grid-template-columns:repeat(3,minmax(0,1fr));gap:12px;padding:12px}.account-runtime-facts{grid-column:auto}.account-plan-grid{grid-template-columns:repeat(4,minmax(0,1fr))}.account-plan-card{padding:12px}.account-dialog-footer{min-height:54px;padding:8px 14px}}@media(prefers-reduced-motion:reduce){.account-dialog-backdrop,.account-dialog{scroll-behavior:auto}}.remote-status-button{position:relative;display:inline-grid;place-items:center;width:34px;height:34px;padding:0;border:1px solid #d8e1ed;border-radius:9px;background:#fff;color:#24344d;cursor:pointer;transition:.15s}.remote-status-button:hover,.remote-status-button:focus-visible,.remote-status-button.active{border-color:#6d9df8;background:#edf4ff;color:#285fb7;outline:none}.debug-status-button:hover,.debug-status-button:focus-visible,.debug-status-button.active{border-color:#9b83e6;background:#f4f0ff;color:#6842bd}.remote-status-spinner{width:15px;height:15px;border:2px solid #c4d4ed;border-top-color:#356ec2;border-radius:50%;animation:remote-status-spin .7s linear infinite}@keyframes remote-status-spin{to{transform:rotate(360deg)}}.remote-status-lines{position:absolute;left:10px;right:10px;bottom:10px;z-index:7;display:grid;gap:4px;max-height:calc(100% - 50px);overflow:auto;line-height:1;pointer-events:none}.remote-status-lines.mode-debug{pointer-events:auto;touch-action:pan-y;overscroll-behavior:contain;scrollbar-gutter:stable}.remote-status-line{display:grid;grid-template-columns:17px minmax(0,1fr);align-items:start;gap:6px;padding:6px 7px;border:1px solid rgba(255,255,255,.12);border-radius:7px;background:#05090fdb;box-shadow:0 6px 16px #0003;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}.remote-status-line>svg{margin-top:1px}.remote-status-line>span{min-width:0;display:flex;align-items:baseline;gap:5px;overflow:hidden}.remote-status-line strong,.remote-status-line small{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.remote-status-line strong{flex:0 1 auto;color:#f8fafc;font-size:10px;font-weight:900}.remote-status-line small{flex:1 1 auto;color:#b9c4d4;font-size:9px}.remote-status-line small:before{content:"—";margin-right:5px;color:#738096}.remote-status-line.state-ok>svg{color:#34d399}.remote-status-line.state-warning>svg{color:#f59e0b}.remote-status-lines.mode-debug .remote-status-line{border-color:#a78bfa3d;background:#0f0a1ce6}.remote-status-lines.mode-debug .remote-status-line strong{color:#ede9fe}.remote-status-lines.mode-debug .remote-status-line small{color:#c4b5fd}.remote-status-dialog{position:fixed;top:70px;left:50%;z-index:80;width:min(430px,calc(100vw - 32px));max-height:calc(100vh - 92px);overflow:auto;padding:16px;transform:translate(-50%);border:1px solid #d6e0ee;border-radius:14px;background:#fffffffa;box-shadow:0 24px 64px #0f172a3d;color:#172033}.remote-status-dialog>header{display:grid;grid-template-columns:38px minmax(0,1fr) 32px;align-items:center;gap:10px}.remote-status-dialog-mark{display:grid;place-items:center;width:36px;height:36px;border-radius:10px;background:#e8f1ff;color:#285fb7}.remote-status-dialog h2{margin:2px 0 0;font-size:18px}.remote-status-dialog header small{color:#718096;font-size:10px;font-weight:800;text-transform:uppercase;letter-spacing:.08em}.remote-status-dialog header button{display:grid;place-items:center;width:30px;height:30px;padding:0;border:0;border-radius:8px;background:transparent;color:#5c6c82;cursor:pointer}.remote-status-dialog header button:hover{background:#eef2f7}.remote-status-dialog>p{margin:13px 0;color:#5b6b80;font-size:12px;line-height:1.55}.remote-status-dialog-list{display:grid;gap:7px}.remote-status-dialog-row{display:grid;grid-template-columns:19px minmax(0,1fr);align-items:start;gap:8px;padding:10px;border:1px solid #e3e9f1;border-radius:10px;background:#f8fafc}.remote-status-dialog-row>svg{margin-top:1px}.remote-status-dialog-row>span{display:grid;gap:4px}.remote-status-dialog-row strong{font-size:12px}.remote-status-dialog-row small{color:#64748b;font-size:10px;line-height:1.4}.remote-status-dialog-row.state-ok>svg{color:#10b981}.remote-status-dialog-row.state-warning{border-color:#f3d49c;background:#fffaf0}.remote-status-dialog-row.state-warning>svg{color:#e58b08}.remote-status-dialog>footer{margin-top:12px;color:#8491a3;font-size:10px;text-align:right}@media(max-width:900px){.remote-status-dialog{top:62px}.remote-status-lines{left:6px;right:6px;bottom:6px}.remote-status-line{padding:5px}.remote-status-line small{display:none}}.capture-toolbar{display:flex;align-items:center;gap:6px}.capture-action{position:relative;display:inline-flex;align-items:center;justify-content:center;gap:5px;min-width:34px;height:34px;padding:0 8px;border:1px solid #d8e1ed;border-radius:9px;background:#fff;color:#24344d;cursor:pointer;transition:.15s}.capture-action:hover:not(:disabled),.capture-action:focus-visible{border-color:#7da7ff;background:#f2f6ff;outline:none}.capture-action:disabled{opacity:.42;cursor:not-allowed}.capture-action.active{border-color:#ef7d83;background:#fff0f1;color:#c6323a}.capture-action.timelapse-active{border-color:#a887e8;background:#f3efff;color:#7043be}.capture-action small{font-size:9px;font-weight:700;line-height:1}.capture-action span{font-size:11px;font-variant-numeric:tabular-nums}.capture-toolbar.compact .capture-action{height:32px;min-width:32px}.capture-toolbar.recording-active{border-radius:10px}.capture-toolbar.recording-active .capture-action:first-child{border-color:#efc7ca}.top-actions-divider{width:1px;height:22px;background:#d8e1ed;margin:0 4px}.capture-gallery{margin-top:16px;padding:18px;border:1px solid #dbe4ef;border-radius:14px;background:#fff}.capture-gallery>header{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:14px}.capture-gallery>header h2{margin:3px 0 0;font-size:20px}.capture-gallery>header .text-button{display:inline-flex;align-items:center;gap:6px}.capture-gallery-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px}.capture-gallery-card{overflow:hidden;border:1px solid #e1e8f0;border-radius:11px;background:#f8fafc}.capture-gallery-card>img,.capture-gallery-card>video{display:block;width:100%;height:130px;object-fit:contain;background:#0b1220}.capture-gallery-card-body{display:grid;gap:6px;padding:10px}.capture-gallery-card-body>strong{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:12px}.capture-gallery-card-body>small{color:#64748b;font-size:10px;line-height:1.4}.capture-gallery-card-body>div{display:flex;gap:5px}.capture-gallery-card-body .icon-button{display:inline-flex;align-items:center;justify-content:center}.capture-gallery-card-body .icon-button.danger{color:#bd3c4a}@media(max-width:900px){.capture-toolbar{display:none}.capture-toolbar.compact{display:flex}.capture-toolbar.compact .capture-action:not(:nth-child(2)){display:none}.capture-toolbar.compact:after{content:"Capture";font-size:11px;font-weight:700;color:#53657e;margin-left:2px}}
|
|
1
|
+
.account-dialog-backdrop{position:fixed;inset:0;z-index:1700;display:grid;place-items:center;padding:20px;background:#080f1ca3;backdrop-filter:blur(5px);-webkit-backdrop-filter:blur(5px);overscroll-behavior:contain}.account-dialog{width:min(1120px,calc(100vw - 40px));max-height:min(860px,calc(100dvh - 40px));display:grid;grid-template-rows:auto minmax(0,1fr) auto;overflow:hidden;color:#172033;border:1px solid rgb(255 255 255 / 72%);border-radius:24px;background:#f8fafc;box-shadow:0 28px 80px #03081459}.account-dialog button,.account-dialog input{font:inherit}.account-dialog button{touch-action:manipulation}.account-dialog-header{min-height:88px;display:flex;align-items:center;justify-content:space-between;gap:24px;padding:18px 22px;border-bottom:1px solid #e5eaf1;background:#fff}.account-dialog-identity{min-width:0;display:flex;align-items:center;gap:14px}.account-dialog-identity>span:last-child{min-width:0;display:grid;gap:2px}.account-dialog-identity small,.account-section-heading>div>span,.account-current-plan-copy small{color:#68758a;font-size:11px;font-weight:750;letter-spacing:.055em;text-transform:uppercase}.account-dialog-identity strong{overflow:hidden;font-size:18px;line-height:1.25;text-overflow:ellipsis;white-space:nowrap}.account-dialog-identity>span:last-child>span{overflow:hidden;color:#6b7280;font-size:12px;text-overflow:ellipsis;white-space:nowrap}.account-dialog-avatar{width:50px;height:50px;flex:0 0 50px;display:grid;place-items:center;overflow:hidden;color:#fff;border-radius:16px;background:#172033;font-size:18px;font-weight:800}.account-dialog-avatar img{width:100%;height:100%;object-fit:cover}.account-dialog-close{width:40px;height:40px;flex:0 0 40px;display:grid;place-items:center;color:#5b6574;border:1px solid #dbe1e9;border-radius:12px;background:#f8fafc;cursor:pointer}.account-dialog-close:hover,.account-dialog-close:focus-visible{color:#111827;border-color:#aeb8c6;outline:3px solid rgb(91 87 255 / 16%)}.account-dialog-body{min-height:0;display:grid;gap:22px;padding:22px;overflow-y:auto;overscroll-behavior:contain}.account-workspace-switcher{display:grid;gap:9px}.account-workspace-switcher>div:first-child{display:flex;align-items:baseline;justify-content:space-between;gap:12px}.account-workspace-switcher>div:first-child>span{color:#273449;font-size:11px;font-weight:820;letter-spacing:.045em;text-transform:uppercase}.account-workspace-switcher>div:first-child>small{color:#7b8595;font-size:10px}.account-workspace-list{display:flex;gap:8px;overflow-x:auto;padding:2px;scrollbar-width:thin}.account-workspace-list button{min-width:195px;display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:9px;padding:10px;color:#435066;border:1px solid #dfe5ed;border-radius:12px;background:#fff;text-align:left;cursor:pointer}.account-workspace-list button.active{color:#2f2a70;border-color:#8c85e8;background:#f3f1ff;box-shadow:0 0 0 2px #5b57ff17}.account-workspace-list button:disabled:not(.active){opacity:.58;cursor:not-allowed}.account-workspace-list button>span:first-child{width:30px;height:30px;display:grid;place-items:center;color:#fff;border-radius:9px;background:#26354c}.account-workspace-list button.active>span:first-child{background:#5b57cf}.account-workspace-list button>span:nth-child(2){min-width:0;display:grid;gap:2px}.account-workspace-list button strong,.account-workspace-list button small{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.account-workspace-list button strong{font-size:11px}.account-workspace-list button small{color:#7b8595;font-size:9px}.account-workspace-list button em{color:#5a55a9;font-size:9px;font-style:normal;font-weight:800}.account-current-plan{display:grid;grid-template-columns:minmax(220px,1.1fr) minmax(190px,.75fr) minmax(220px,.9fr);align-items:center;gap:20px;padding:20px;color:#fff;border-radius:18px;background:linear-gradient(135deg,#111827,#25344d);box-shadow:0 12px 30px #0f172a24}.account-current-plan.plan-plus{background:linear-gradient(135deg,#312e81,#5b57ff)}.account-current-plan.plan-business{background:linear-gradient(135deg,#0f3f38,#117565)}.account-current-plan.plan-team{background:linear-gradient(135deg,#4c1d95,#7c3aed)}.account-current-plan-copy{min-width:0;display:flex;align-items:center;gap:13px}.account-current-plan-copy>span:last-child{min-width:0;display:grid;gap:3px}.account-current-plan-copy small,.account-current-plan-copy>span:last-child>span{color:#ffffffb3}.account-current-plan-copy strong{font-size:22px}.account-current-plan-copy>span:last-child>span{overflow:hidden;font-size:12px;text-overflow:ellipsis;white-space:nowrap}.account-current-plan-icon{width:42px;height:42px;flex:0 0 42px;display:grid;place-items:center;border:1px solid rgb(255 255 255 / 18%);border-radius:13px;background:#ffffff1f}.account-device-usage{display:grid;gap:6px}.account-device-usage>span:first-child{display:flex;align-items:center;gap:6px;color:#ffffffb8;font-size:11px;font-weight:700}.account-device-usage>strong{font-size:22px}.account-device-usage>strong small{color:#ffffffa6;font-size:12px;font-weight:650}.account-device-meter{width:100%;height:5px;overflow:hidden;border-radius:999px;background:#ffffff2e}.account-device-meter i{height:100%;display:block;border-radius:inherit;background:#fff}.account-runtime-facts{margin:0;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}.account-runtime-facts div{min-width:0;display:grid;gap:2px;padding:9px 11px;border:1px solid rgb(255 255 255 / 12%);border-radius:11px;background:#ffffff14}.account-runtime-facts dt{color:#fff9;font-size:10px}.account-runtime-facts dd{margin:0;overflow:hidden;font-size:11px;font-weight:700;text-overflow:ellipsis;white-space:nowrap}.account-plan-section,.account-team-panel{display:grid;gap:14px}.account-section-heading{display:flex;align-items:end;justify-content:space-between;gap:18px}.account-section-heading h2{margin:4px 0 0;color:#172033;font-size:17px;letter-spacing:-.02em}.account-section-heading>small{color:#68758a;font-size:11px;text-align:right}.account-plan-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px}.account-plan-card{min-width:0;display:grid;grid-template-rows:auto auto auto auto 1fr auto;gap:9px;padding:16px;border:1px solid #dfe5ed;border-radius:15px;background:#fff}.account-plan-card.current{border-color:#5b57ff;box-shadow:0 0 0 2px #5b57ff1c}.account-plan-card.plan-team{background:linear-gradient(180deg,#fbf9ff,#fff)}.account-plan-card-title{display:flex;align-items:center;justify-content:space-between;gap:8px}.account-plan-card-title>span{display:flex;align-items:center;gap:6px;color:#172033;font-size:14px;font-weight:800}.account-plan-card-title em{display:flex;align-items:center;gap:3px;padding:4px 6px;color:#4338ca;border-radius:999px;background:#eef2ff;font-size:9px;font-style:normal;font-weight:800;text-transform:uppercase}.account-plan-card>p{margin:0;color:#7a8494;font-size:11px}.account-plan-card>strong{color:#273449;font-size:12px}.account-plan-price{color:#172033;font-size:15px;font-weight:850;letter-spacing:-.025em}.account-plan-ltd-price{width:fit-content;padding:4px 7px;color:#075985;border:1px solid #bae6fd;border-radius:8px;background:#f0f9ff;font-size:10px;font-weight:800}.account-plan-card ul{margin:0;padding:0;display:grid;align-content:start;gap:7px;list-style:none}.account-plan-card li{display:flex;align-items:flex-start;gap:5px;color:#526075;font-size:10.5px;line-height:1.35}.account-plan-card li svg{flex:0 0 auto;margin-top:1px;color:#159275}.account-plan-action,.account-plan-state{min-height:34px;display:flex;align-items:center;justify-content:center;gap:6px;border-radius:10px;font-size:10.5px;font-weight:780}.account-plan-actions{display:grid;gap:6px}.account-plan-action{color:#fff;border:0;background:#172033;cursor:pointer}.account-plan-action.secondary{color:#273449;border:1px solid #cfd7e3;background:#f7f9fc}.account-plan-action.secondary:hover,.account-plan-action.secondary:focus-visible{color:#fff;border-color:#172033;background:#172033}.account-plan-action:hover,.account-plan-action:focus-visible{background:#000;outline:3px solid rgb(91 87 255 / 16%)}.account-plan-action:disabled{opacity:.5;cursor:not-allowed}.account-plan-state{color:#556176;border:1px solid #e3e7ed;background:#f6f8fa}.account-plan-card.current .account-plan-state{color:#4338ca;border-color:#d8d7ff;background:#f1f0ff}.account-team-panel{padding:18px;border:1px solid #dfd8f5;border-radius:16px;background:#fbf9ff}.account-team-members{margin:0;padding:0;display:grid;gap:7px;list-style:none}.account-team-rename{display:grid;gap:6px;margin-bottom:10px}.account-team-rename>label{color:#4e5a6c;font-size:10px;font-weight:750}.account-team-rename>span,.account-team-invite-compose{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:7px}.account-team-rename input,.account-team-rename button,.account-team-leave{height:38px;border-radius:10px;font-size:10.5px}.account-team-operator-note{margin:10px 0 0;padding:10px 12px;color:#514868;border:1px solid #ded6ef;border-radius:10px;background:#fff;font-size:10.5px;font-weight:700}.account-team-error{display:block;margin-top:8px;color:#b42318;font-size:10px}.account-session-revocation-error{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:.25rem .75rem;align-items:center;padding:.8rem .9rem;border:1px solid #fca5a5;border-radius:.75rem;background:#fff1f2;color:#7f1d1d}.account-session-revocation-error strong,.account-session-revocation-error span{grid-column:1}.account-session-revocation-error span{font-size:.8rem;color:#991b1b}.account-session-revocation-error button{grid-column:2;grid-row:1 / span 2;border:1px solid rgba(254,202,202,.42);border-radius:.55rem;padding:.55rem .7rem;background:#7f1d1d;color:#fff;cursor:pointer}.account-session-revocation-error button:disabled{cursor:wait;opacity:.6}.account-team-rename input{min-width:0;padding:0 11px;color:#172033;border:1px solid #d9d4e6;background:#fff}.account-team-rename button{padding:0 13px;color:#fff;border:0;background:#5b45bf;font-weight:780;cursor:pointer}.account-team-members li{display:grid;grid-template-columns:auto minmax(0,1fr) auto auto auto;align-items:center;gap:10px;padding:9px 10px;border:1px solid #e3dff0;border-radius:11px;background:#fff}.account-member-avatar{width:31px;height:31px;display:grid;place-items:center;color:#fff;border-radius:9px;background:#6d5bd0;font-size:11px;font-weight:800}.account-team-members li>span:nth-child(2){min-width:0;display:grid}.account-team-members li strong,.account-team-members li small{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.account-team-members li strong{font-size:11px}.account-team-members li small{color:#778195;font-size:9.5px}.account-team-members li em,.account-member-status{font-size:9px;font-style:normal;font-weight:750;text-transform:capitalize}.account-team-members li em{color:#4c3fb2}.account-member-status{padding:4px 6px;color:#17745f;border-radius:999px;background:#e7f7f1}.account-member-status.status-invited{color:#98620c;background:#fff5d9}.account-team-members li>button{color:#a23636;border:0;background:transparent;font-size:9.5px;font-weight:750;cursor:pointer}.account-team-invite{display:grid;gap:6px}.account-team-invite>label{color:#4e5a6c;font-size:10px;font-weight:750}.account-team-invite>span{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:7px}.account-team-invite input{min-width:0;height:38px;padding:0 11px;color:#172033;border:1px solid #d9d4e6;border-radius:10px;background:#fff;font-size:11px}.account-team-invite button{height:38px;display:flex;align-items:center;gap:6px;padding:0 13px;color:#fff;border:0;border-radius:10px;background:#5b45bf;font-size:10.5px;font-weight:780;cursor:pointer}.account-team-invite>.account-create-invite{width:fit-content}.account-team-invite-compose>.account-create-invite{width:auto}.account-team-invite-result{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:7px}.account-team-invite-result>small{grid-column:1 / -1;color:#746d86;font-size:9.5px}.account-team-invite>p{margin:0;color:#7a738b;font-size:9.5px}.account-team-invite button:disabled,.account-team-invite input:disabled{opacity:.55;cursor:not-allowed}.account-team-invite>small{color:#b42318;font-size:10px}.account-team-empty{margin:0;padding:15px;color:#6c6680;border:1px dashed #d6cde9;border-radius:11px;background:#ffffffb3;font-size:11px}.account-team-leave{width:fit-content;margin-top:10px;padding:0 13px;color:#a23636;border:1px solid #ead1d1;background:#fff;font-weight:750;cursor:pointer}.account-team-rename button:disabled,.account-team-rename input:disabled,.account-team-leave:disabled{opacity:.55;cursor:not-allowed}.account-dialog-footer{min-height:66px;display:flex;align-items:center;justify-content:space-between;gap:18px;padding:13px 22px;border-top:1px solid #e5eaf1;background:#fff}.account-dialog-footer>span{display:flex;align-items:center;gap:7px;color:#697589;font-size:11px}.account-auth-action{min-height:38px;display:flex;align-items:center;justify-content:center;gap:7px;padding:0 15px;color:#2c3749;border:1px solid #d8dee7;border-radius:11px;background:#fff;font-size:11px;font-weight:780;cursor:pointer}.account-auth-action.primary{color:#fff;border-color:#172033;background:#172033}.account-auth-action:disabled{opacity:.55;cursor:wait}@media(max-width:900px){.account-dialog{width:min(760px,calc(100vw - 24px));max-height:calc(100dvh - 24px);border-radius:20px}.account-dialog-backdrop{padding:12px}.account-current-plan{grid-template-columns:minmax(0,1fr) minmax(160px,.75fr)}.account-runtime-facts{grid-column:1 / -1}.account-plan-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(max-width:560px){.account-dialog-backdrop{align-items:stretch;padding:0}.account-dialog{width:100vw;max-height:100dvh;border:0;border-radius:0}.account-dialog-header{min-height:74px;padding:12px 14px}.account-dialog-avatar{width:42px;height:42px;flex-basis:42px;border-radius:13px}.account-dialog-identity strong{font-size:15px}.account-dialog-body{gap:18px;padding:14px}.account-current-plan{grid-template-columns:minmax(0,1fr);gap:14px;padding:16px}.account-runtime-facts{grid-column:auto}.account-section-heading{align-items:flex-start;flex-direction:column;gap:5px}.account-section-heading>small{text-align:left}.account-plan-grid{grid-template-columns:minmax(0,1fr)}.account-plan-card{min-height:auto}.account-team-members li{grid-template-columns:auto minmax(0,1fr) auto}.account-team-members li>em{grid-column:2}.account-member-status{grid-column:3;grid-row:1}.account-team-members li>button{grid-column:3;grid-row:2}.account-team-invite>span{grid-template-columns:minmax(0,1fr)}.account-team-invite button{justify-content:center}.account-dialog-footer{align-items:stretch;flex-direction:column;padding:11px 14px}.account-dialog-footer>span{line-height:1.4}.account-auth-action{width:100%}}@media(max-height:520px)and (orientation:landscape){.account-dialog-backdrop{padding:6px}.account-dialog{width:min(1000px,calc(100vw - 12px));max-height:calc(100dvh - 12px);border-radius:15px}.account-dialog-header{min-height:60px;padding:8px 14px}.account-dialog-avatar{width:38px;height:38px;flex-basis:38px;border-radius:11px}.account-dialog-body{gap:14px;padding:12px 14px}.account-current-plan{grid-template-columns:repeat(3,minmax(0,1fr));gap:12px;padding:12px}.account-runtime-facts{grid-column:auto}.account-plan-grid{grid-template-columns:repeat(4,minmax(0,1fr))}.account-plan-card{padding:12px}.account-dialog-footer{min-height:54px;padding:8px 14px}}@media(prefers-reduced-motion:reduce){.account-dialog-backdrop,.account-dialog{scroll-behavior:auto}}.remote-status-button{position:relative;display:inline-grid;place-items:center;width:34px;height:34px;padding:0;border:1px solid #d8e1ed;border-radius:9px;background:#fff;color:#24344d;cursor:pointer;transition:.15s}.remote-status-button:hover,.remote-status-button:focus-visible,.remote-status-button.active{border-color:#6d9df8;background:#edf4ff;color:#285fb7;outline:none}.debug-status-button:hover,.debug-status-button:focus-visible,.debug-status-button.active{border-color:#9b83e6;background:#f4f0ff;color:#6842bd}.remote-status-spinner{width:15px;height:15px;border:2px solid #c4d4ed;border-top-color:#356ec2;border-radius:50%;animation:remote-status-spin .7s linear infinite}@keyframes remote-status-spin{to{transform:rotate(360deg)}}.remote-status-lines{position:absolute;left:10px;right:10px;bottom:10px;z-index:7;display:grid;gap:4px;max-height:calc(100% - 50px);overflow:auto;line-height:1;pointer-events:none}.remote-status-lines.mode-debug{pointer-events:auto;touch-action:pan-y;overscroll-behavior:contain;scrollbar-gutter:stable}.remote-status-line{display:grid;grid-template-columns:17px minmax(0,1fr);align-items:start;gap:6px;padding:6px 7px;border:1px solid rgba(255,255,255,.12);border-radius:7px;background:#05090fdb;box-shadow:0 6px 16px #0003}.remote-status-line>svg{margin-top:1px}.remote-status-line>span{min-width:0;display:flex;align-items:baseline;gap:5px;overflow:hidden}.remote-status-line strong,.remote-status-line small{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.remote-status-line strong{flex:0 1 auto;color:#f8fafc;font-size:10px;font-weight:900}.remote-status-line small{flex:1 1 auto;color:#b9c4d4;font-size:9px}.remote-status-line small:before{content:"—";margin-right:5px;color:#738096}.remote-status-line.state-ok>svg{color:#34d399}.remote-status-line.state-warning>svg{color:#f59e0b}.remote-status-lines.mode-debug .remote-status-line{border-color:#a78bfa3d;background:#0f0a1ce6}.remote-status-lines.mode-debug .remote-status-line strong{color:#ede9fe}.remote-status-lines.mode-debug .remote-status-line small{color:#c4b5fd}.remote-status-dialog{position:fixed;top:70px;left:50%;z-index:80;width:min(430px,calc(100vw - 32px));max-height:calc(100vh - 92px);overflow:auto;padding:16px;transform:translate(-50%);border:1px solid #d6e0ee;border-radius:14px;background:#fffffffa;box-shadow:0 24px 64px #0f172a3d;color:#172033}.remote-status-dialog>header{display:grid;grid-template-columns:38px minmax(0,1fr) 32px;align-items:center;gap:10px}.remote-status-dialog-mark{display:grid;place-items:center;width:36px;height:36px;border-radius:10px;background:#e8f1ff;color:#285fb7}.remote-status-dialog h2{margin:2px 0 0;font-size:18px}.remote-status-dialog header small{color:#718096;font-size:10px;font-weight:800;text-transform:uppercase;letter-spacing:.08em}.remote-status-dialog header button{display:grid;place-items:center;width:30px;height:30px;padding:0;border:0;border-radius:8px;background:transparent;color:#5c6c82;cursor:pointer}.remote-status-dialog header button:hover{background:#eef2f7}.remote-status-dialog>p{margin:13px 0;color:#5b6b80;font-size:12px;line-height:1.55}.remote-status-dialog-list{display:grid;gap:7px}.remote-status-dialog-row{display:grid;grid-template-columns:19px minmax(0,1fr);align-items:start;gap:8px;padding:10px;border:1px solid #e3e9f1;border-radius:10px;background:#f8fafc}.remote-status-dialog-row>svg{margin-top:1px}.remote-status-dialog-row>span{display:grid;gap:4px}.remote-status-dialog-row strong{font-size:12px}.remote-status-dialog-row small{color:#64748b;font-size:10px;line-height:1.4}.remote-status-dialog-row.state-ok>svg{color:#10b981}.remote-status-dialog-row.state-warning{border-color:#f3d49c;background:#fffaf0}.remote-status-dialog-row.state-warning>svg{color:#e58b08}.remote-status-dialog>footer{margin-top:12px;color:#8491a3;font-size:10px;text-align:right}@media(max-width:900px){.remote-status-dialog{top:62px}.remote-status-lines{left:6px;right:6px;bottom:6px}.remote-status-line{padding:5px}.remote-status-line small{display:none}}.capture-toolbar{display:flex;align-items:center;gap:6px}.capture-action{position:relative;display:inline-flex;align-items:center;justify-content:center;gap:5px;min-width:34px;height:34px;padding:0 8px;border:1px solid #d8e1ed;border-radius:9px;background:#fff;color:#24344d;cursor:pointer;transition:.15s}.capture-action:hover:not(:disabled),.capture-action:focus-visible{border-color:#7da7ff;background:#f2f6ff;outline:none}.capture-action:disabled{opacity:.42;cursor:not-allowed}.capture-action.active{border-color:#ef7d83;background:#fff0f1;color:#c6323a}.capture-action.timelapse-active{border-color:#a887e8;background:#f3efff;color:#7043be}.capture-action small{font-size:9px;font-weight:700;line-height:1}.capture-action span{font-size:11px;font-variant-numeric:tabular-nums}.capture-toolbar.compact .capture-action{height:32px;min-width:32px}.capture-toolbar.recording-active{border-radius:10px}.capture-toolbar.recording-active .capture-action:first-child{border-color:#efc7ca}.top-actions-divider{width:1px;height:22px;background:#d8e1ed;margin:0 4px}.capture-gallery{margin-top:16px;padding:18px;border:1px solid #dbe4ef;border-radius:14px;background:#fff}.capture-gallery>header{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:14px}.capture-gallery>header h2{margin:3px 0 0;font-size:20px}.capture-gallery>header .text-button{display:inline-flex;align-items:center;gap:6px}.capture-gallery-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px}.capture-gallery-card{overflow:hidden;border:1px solid #e1e8f0;border-radius:11px;background:#f8fafc}.capture-gallery-card>img,.capture-gallery-card>video{display:block;width:100%;height:130px;object-fit:contain;background:#0b1220}.capture-gallery-card-body{display:grid;gap:6px;padding:10px}.capture-gallery-card-body>strong{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:12px}.capture-gallery-card-body>small{color:#64748b;font-size:10px;line-height:1.4}.capture-gallery-card-body>div{display:flex;gap:5px}.capture-gallery-card-body .icon-button{display:inline-flex;align-items:center;justify-content:center}.capture-gallery-card-body .icon-button.danger{color:#bd3c4a}@media(max-width:900px){.capture-toolbar{display:none}.capture-toolbar.compact{display:flex}.capture-toolbar.compact .capture-action:not(:nth-child(2)){display:none}.capture-toolbar.compact:after{content:"Capture";font-size:11px;font-weight:700;color:#53657e;margin-left:2px}}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import{j as M}from"./pwa-startup-DvbrYEQi.js";const W=15e3;function Pe(n,e=W){const t=Number(n),i=Number.isFinite(Number(e))?Number(e):W;return Math.max(250,Math.min(12e4,Math.trunc(Number.isFinite(t)?t:i)))}class fe extends Error{constructor(e){super(`VuvoDesk Hub request timed out after ${e} ms.`),this.name="HubRequestTimeoutError",this.code="livedesk-hub-request-timeout",this.timeoutMs=e}}async function Ne(n,e,t){const i=Pe(e),s=new AbortController;let r=!1;const o=()=>{s.signal.aborted||s.abort(n?.reason)};n?.aborted?o():n?.addEventListener("abort",o,{once:!0});const a=setTimeout(()=>{r=!0,s.signal.aborted||s.abort(new fe(i))},i);try{return await t(s.signal)}catch(c){throw r?new fe(i):c}finally{clearTimeout(a),n?.removeEventListener("abort",o)}}function un(n,e){if(n.current)return n.current;const t=Promise.resolve().then(e);return n.current=t,t.finally(()=>{n.current===t&&(n.current=null)}).catch(()=>{}),t}const oe=16*1024,k=6*1024*1024,xe=12*1024*1024,T=24,D=oe-T,Ie=1,We=2,pe=32,Z=4294967295,ee=Symbol("direct-console-wire-budget-reserve"),te=Object.freeze([76,68,67,87]),Le=Object.freeze({control:1,text:2,binary:3}),Be=Object.freeze({1:"control",2:"text",3:"binary"});class B extends Error{constructor(e,t=void 0){super(String(e||"direct-console-wire-error")),this.name="DirectConsoleWireError",this.code=String(e||"direct-console-wire-error"),t!==void 0&&(this.details=t)}}function f(n,e=void 0){throw new B(n,e)}function ae(n,e){return n===void 0?{}:((!n||typeof n!="object"||Array.isArray(n))&&f(`${e}-options-invalid`),n)}function F(n,e,t,i){const s=Number(n);return(!Number.isInteger(s)||s<t||s>i)&&f(e),s}function ve(n){return n===void 0?k:F(n,"max-message-bytes-invalid",1,Z)}function Ue(n,e){const t=n===void 0?e?"text":"binary":String(n);return Object.hasOwn(Le,t)||f("message-kind-invalid"),e&&t==="binary"&&f("binary-message-requires-bytes"),!e&&t!=="binary"&&f(`${t}-message-requires-text`),t}function He(n){if(typeof n=="string")return{bytes:new TextEncoder().encode(n),isText:!0};if(n instanceof Uint8Array)return{bytes:n,isText:!1};if(n instanceof ArrayBuffer)return{bytes:new Uint8Array(n),isText:!1};f("message-payload-invalid")}function Fe(n){if(n instanceof Uint8Array)return n;if(n instanceof ArrayBuffer)return new Uint8Array(n);f("wire-chunk-type-invalid")}function qe(n,{kind:e,messageId:t,chunkIndex:i,chunkCount:s,totalLength:r}){n.set(te,0);const o=new DataView(n.buffer,n.byteOffset,T);o.setUint8(4,Ie),o.setUint8(5,Le[e]),o.setUint16(6,0,!1),o.setUint32(8,t,!1),o.setUint32(12,i,!1),o.setUint32(16,s,!1),o.setUint32(20,r,!1)}function Ge(n,e){const t=Fe(n);(t.byteLength<T||t.byteLength>oe)&&f("wire-chunk-length-invalid");for(let g=0;g<te.length;g+=1)t[g]!==te[g]&&f("wire-magic-invalid");const i=new DataView(t.buffer,t.byteOffset,T);i.getUint8(4)!==Ie&&f("wire-version-invalid");const s=Be[i.getUint8(5)];s||f("wire-kind-invalid"),i.getUint16(6,!1)!==0&&f("wire-reserved-invalid");const r=i.getUint32(8,!1),o=i.getUint32(12,!1),a=i.getUint32(16,!1),c=i.getUint32(20,!1);c>e&&f("message-too-large");const u=Math.max(1,Math.ceil(c/D));(a!==u||o>=a)&&f("wire-chunk-layout-invalid");const d=t.byteLength-T,h=o<a-1?D:c-o*D;return d!==h&&f("wire-chunk-layout-invalid"),{bytes:t,kind:s,messageId:r,chunkIndex:o,chunkCount:a,totalLength:c,payloadLength:d}}function ye(n=void 0){const e=ae(n,"budget"),t=e.maxBytes===void 0?xe:F(e.maxBytes,"budget-max-bytes-invalid",1,Number.MAX_SAFE_INTEGER);let i=0,s=0;const r=()=>Object.freeze({maxBytes:t,retainedBytes:i,reservationCount:s}),o=a=>{const c=F(a,"budget-reservation-invalid",0,Number.MAX_SAFE_INTEGER);c>t-i&&f("shared-budget-overflow"),i+=c,s+=1;let u=!0;return Object.freeze({byteLength:c,release(){return u?(u=!1,i-=c,s-=1,(i<0||s<0)&&(i=0,s=0,f("shared-budget-underflow")),!0):!1}})};return Object.freeze({inspect:r,[ee]:o})}function je(n,e=void 0){const t=ae(e,"encode"),i=F(t.messageId,"message-id-invalid",0,Z),s=ve(t.maxMessageBytes),r=He(n),o=Ue(t.kind,r.isText),a=r.bytes.byteLength;(a>s||a>Z)&&f("message-too-large");const c=Math.max(1,Math.ceil(a/D)),u=new Array(c);for(let d=0;d<c;d+=1){const h=d*D,g=Math.min(D,a-h),w=new Uint8Array(T+g);qe(w,{kind:o,messageId:i,chunkIndex:d,chunkCount:c,totalLength:a}),g>0&&w.set(r.bytes.subarray(h,h+g),T),u[d]=w}return u}function ge(n=void 0){const e=ae(n,"assembler"),t=ve(e.maxMessageBytes),i=e.maxPendingMessages===void 0?We:Number(e.maxPendingMessages);(!Number.isSafeInteger(i)||i<1||i>pe)&&f("max-pending-messages-invalid");const s=e.budget===void 0?ye():e.budget;(!s||typeof s[ee]!="function"||typeof s.inspect!="function")&&f("shared-budget-invalid");const r=new Map,o=new Map;let a=!1;const c=()=>{for(const b of r.values())b.reservation.release();r.clear()},u=()=>{o.clear()},d=()=>{let b=0;for(const E of r.values())b+=E.totalLength;let l=0;for(const E of o.values())l+=E.remainingChunks;return Object.freeze({disposed:a,maxMessageBytes:t,maxPendingMessages:i,pendingMessages:r.size,pendingBytes:b,abandonedMessages:o.size,abandonedChunksRemaining:l,budget:s.inspect()})},h=()=>(a||(a=!0,c(),u()),d()),g=b=>{throw a=!0,c(),u(),b instanceof B?b:new B("wire-chunk-malformed")};return Object.freeze({abandonPending:()=>{a&&f("assembler-disposed");for(const[b,l]of r.entries()){if(o.size>=pe){const E=o.keys().next().value;o.delete(E)}o.set(b,{kind:l.kind,chunkCount:l.chunkCount,totalLength:l.totalLength,receivedChunks:new Uint8Array(l.receivedChunks),remainingChunks:Math.max(0,l.chunkCount-l.receivedChunkCount)}),l.reservation.release()}return r.clear(),d()},dispose:h,inspect:d,push:b=>{a&&f("assembler-disposed");try{const l=Ge(b,t),E=o.get(l.messageId);if(E)return(E.kind!==l.kind||E.chunkCount!==l.chunkCount||E.totalLength!==l.totalLength)&&f("wire-message-metadata-mismatch"),E.receivedChunks[l.chunkIndex]===0&&(E.receivedChunks[l.chunkIndex]=1,E.remainingChunks-=1),E.remainingChunks<=0&&o.delete(l.messageId),null;let m=r.get(l.messageId);if(m)(m.kind!==l.kind||m.chunkCount!==l.chunkCount||m.totalLength!==l.totalLength)&&f("wire-message-metadata-mismatch");else{r.size>=i&&f("pending-message-limit");const de=s[ee](l.totalLength);let he;try{he=new Uint8Array(l.totalLength)}catch{de.release(),f("message-allocation-failed")}m={kind:l.kind,chunkCount:l.chunkCount,totalLength:l.totalLength,receivedChunks:new Uint8Array(l.chunkCount),receivedChunkCount:0,receivedBytes:0,buffer:he,reservation:de},r.set(l.messageId,m)}m.receivedChunks[l.chunkIndex]!==0&&f("duplicate-wire-chunk");const y=l.chunkIndex*D,_e=y+l.payloadLength;if((y<0||_e>m.totalLength)&&f("wire-chunk-overlap"),l.payloadLength>0&&m.buffer.set(l.bytes.subarray(T),y),m.receivedChunks[l.chunkIndex]=1,m.receivedChunkCount+=1,m.receivedBytes+=l.payloadLength,m.receivedChunkCount<m.chunkCount)return null;m.receivedBytes!==m.totalLength&&f("wire-message-length-mismatch");let ue;try{ue=m.kind==="binary"?m.buffer:new TextDecoder("utf-8",{fatal:!0}).decode(m.buffer)}catch{f("wire-text-invalid")}finally{r.delete(l.messageId),m.reservation.release()}return Object.freeze({messageId:l.messageId,kind:m.kind,byteLength:m.totalLength,data:ue})}catch(l){return g(l)}}})}const $e="Direct connection signaling is unavailable. Try again.",ze="Desktop Hub is offline.",Ve="A direct connection could not be established on this network.",ke=750,Xe=2e3,Ye=1500,Ke=3e3,Je=512*1024,Qe=64*1024;function we(n){const e=Math.max(0,Number(n)||0),t=Math.ceil(e/Je*1e3);return Math.min(Xe,ke+t)}function Ze(n){const e=Math.max(0,Number(n)||0),t=Math.ceil(e/Qe*1e3);return Math.max(Ye,Math.min(Ke,ke+t))}const ne=Object.freeze({"signal-service-unavailable":$e,"hub-unavailable":ze,"p2p-unavailable":Ve});function ce(n){const e=new Error(ne[n]);return e.name="ConsoleDirectError",e.code=n,e.directFailureKind=n,e}function S(){return ce("signal-service-unavailable")}function V(){return ce("hub-unavailable")}function p(){return ce("p2p-unavailable")}function X(n){const e=String(n?.directFailureKind||n?.code||""),t=`${e}
|
|
2
|
+
${String(n?.message||n||"")}`.toLowerCase(),i=Object.hasOwn(ne,e)?e:/hub[- ]?(offline|unavailable)|desktop hub is offline/.test(t)?"hub-unavailable":/signal|websocket|wake-service/.test(t)?"signal-service-unavailable":"p2p-unavailable";return Object.freeze({kind:i,message:ne[i],retryAt:0})}function et({userId:n,connectionId:e,hubEpoch:t,generation:i}){const s={userId:String(n||""),connectionId:String(e||""),hubEpoch:String(t||""),generation:Number(i)};if(!s.userId||!s.connectionId||!s.hubEpoch||!Number.isSafeInteger(s.generation)||s.generation<1)throw new Error("console-direct-owner-invalid");return Object.freeze(s)}function tt(n,e){return!!n&&!!e&&n.userId===e.userId&&n.connectionId===e.connectionId&&n.hubEpoch===e.hubEpoch&&n.generation===e.generation}const Te="https://livedesk-wake.lovecrdm.workers.dev",nt="stun:stun.cloudflare.com:3478",it="livedesk-console-signal-v2",st="livedesk-auth.",rt="livedesk-control-v1",ot="livedesk-ws-v1:",at=1e4,Y=12e3,me=1e4,ct=5e3,lt=5e3,ut=15e3,dt=15e3,be=24,ht=16,Ee=32,ft=64,pt=64,gt=4*1024,wt=1024*1024,mt=new Set(["/api/remote/status","/api/remote/devices"]),Ce=4*1024*1024,bt=12*1024*1024,Se=8*1024*1024+oe,Et=8,Ct=1,St=2,It=2,Lt=new Set(["rtc-offer","rtc-ice","rtc-close"]),vt=new Set(["frame","atlas","input","audio"]),N=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;function yt(n){const e=String(Te).trim(),t=new URL(e);return t.protocol=t.protocol==="http:"?"ws:":t.protocol==="https:"?"wss:":t.protocol,t.pathname="/v2/rtc/console",t.search="",t.searchParams.set("workspaceId",n),t.hash="",t.toString()}function kt(n){const e=String(Te).trim(),t=new URL(e);if(t.protocol!=="http:"&&t.protocol!=="https:")throw new Error("console-direct-signal-http-url-invalid");return t.pathname=n,t.search="",t.hash="",t.toString()}function Tt(n){const e=String(n?.accessToken||"").trim(),t=String(n?.user?.id||"").trim(),i=String(n?.workspaceId||"").trim(),s=String(n?.workspaceKind||"").trim().toLowerCase(),r=String(n?.workspaceRole||"").trim().toLowerCase(),o=Number(n?.membershipRevision||0);return e&&t&&N.test(i)&&["personal","team"].includes(s)&&["owner","operator"].includes(r)&&Number.isSafeInteger(o)&&o>=1&&(s!=="personal"||i===t)?{accessToken:e,user:{id:t},workspaceId:i,workspaceKind:s,workspaceRole:r,membershipRevision:o}:null}function At(){const n="".split(/[\s,]+/).map(t=>t.trim()).filter(t=>/^stun:[^\s@]+$/i.test(t)&&t.length<=512),e=[...new Set(n)].slice(0,4);return e.length>0?e:[nt]}function Mt(n){let e="";for(let i=0;i<n.byteLength;i+=32768)e+=String.fromCharCode(...n.subarray(i,Math.min(n.byteLength,i+32768)));return btoa(e)}function Dt(n){const e=atob(n),t=new Uint8Array(e.length);for(let i=0;i<e.length;i+=1)t[i]=e.charCodeAt(i);return t}async function Ot(n){if(n==null)return new Uint8Array;if(typeof n=="string")return new TextEncoder().encode(n);if(n instanceof URLSearchParams)return new TextEncoder().encode(n.toString());if(n instanceof Blob)return new Uint8Array(await n.arrayBuffer());if(n instanceof ArrayBuffer)return new Uint8Array(n);if(ArrayBuffer.isView(n))return new Uint8Array(n.buffer,n.byteOffset,n.byteLength);throw new Error("This request body cannot be sent through the direct mobile Console connection.")}function Rt(n){const e=new Headers(n?.headers||{}),t={};for(const i of["accept","content-type","if-match","range","x-livedesk-csrf"]){const s=e.get(i);s&&(t[i]=s)}return t}function P(n){return/(?:^|\r?\n)(?:a=)?candidate:[^\r\n]*\btyp\s+relay(?:\s|$)/i.test(String(n||""))}function ie(n,e=1e3){const t=Number(n);return Number.isInteger(t)&&t>=0&&t<=65535?t:e}function K(n,e="console-direct-failed"){return n instanceof Error?n:new Error(String(n||e))}function se(n){if(n instanceof ArrayBuffer||n instanceof Uint8Array)return n;throw new B("wire-chunk-type-invalid")}function _t(n){const e=se(n),t=e instanceof Uint8Array?e:new Uint8Array(e),i={chunkBytes:t.byteLength,headerReadable:!1,messageId:0,chunkIndex:0,chunkCount:0,totalLength:0};if(t.byteLength<be)return i;const s=new DataView(t.buffer,t.byteOffset,be);return{...i,headerReadable:t[0]===76&&t[1]===68&&t[2]===67&&t[3]===87,messageId:s.getUint32(8,!1),chunkIndex:s.getUint32(12,!1),chunkCount:s.getUint32(16,!1),totalLength:s.getUint32(20,!1)}}function Pt(n,e){return e?e.aborted?Promise.reject(e.reason||new Error("Mobile Console request cancelled.")):new Promise((t,i)=>{let s=!1;const r=a=>{s||(s=!0,e.removeEventListener("abort",o),a())},o=()=>r(()=>i(e.reason||new Error("Mobile Console request cancelled.")));e.addEventListener("abort",o,{once:!0}),n.then(a=>r(()=>t(a)),a=>r(()=>i(a)))}):n}class Nt extends EventTarget{constructor(e,t,i,s){super(),this.manager=e,this.channelId=t,this.purpose=i,this.url=s}manager;channelId;purpose;url;protocol="livedesk-ws-v1";extensions="";binaryType="blob";readyState=WebSocket.CONNECTING;onopen=null;onmessage=null;onerror=null;onclose=null;get bufferedAmount(){return this.manager.logicalBufferedAmount(this.channelId)}send(e){if(this.readyState!==WebSocket.OPEN)throw new DOMException("WebSocket is not open.","InvalidStateError");this.manager.sendLogicalMessage(this.channelId,e)}close(e=1e3,t=""){this.readyState===WebSocket.CLOSED||this.readyState===WebSocket.CLOSING||(this.readyState=WebSocket.CLOSING,this.manager.closeLogicalChannel(this.channelId,ie(e),String(t||"").slice(0,120),!0))}managerOpened(){if(this.readyState!==WebSocket.CONNECTING)return;this.readyState=WebSocket.OPEN;const e=new Event("open");this.onopen?.call(this,e),this.dispatchEvent(e)}managerMessage(e){if(this.readyState!==WebSocket.OPEN)return;const t=new MessageEvent("message",{data:e});this.onmessage?.call(this,t),this.dispatchEvent(t)}managerError(){if(this.readyState===WebSocket.CLOSED)return;const e=new Event("error");this.onerror?.call(this,e),this.dispatchEvent(e)}managerClosed(e,t,i=!1){if(this.readyState===WebSocket.CLOSED)return;i&&this.managerError(),this.readyState=WebSocket.CLOSED;const s=new CloseEvent("close",{code:ie(e,1006),reason:String(t||"").slice(0,120),wasClean:e===1e3});this.onclose?.call(this,s),this.dispatchEvent(s)}}class xt{session=null;preferred=!1;generation=0;stage="idle";signalSocket=null;signalReady=!1;consoleId="";hubEpoch="";peerOwner=null;peer=null;controlChannel=null;controlAssembler=null;controlWireDeadline=null;wireBudget=null;remoteDescriptionApplied=!1;localOfferSent=!1;pendingLocalCandidates=[];pendingRemoteCandidates=[];directReady=!1;connectPromise=null;resolveConnect=null;rejectConnect=null;connectTimer=null;peerDisconnectTimer=null;wireMessageId=0;pendingHttp=new Map;channels=new Map;livenessEvidenceEpoch=0;consecutiveLivenessRequestTimeouts=0;livenessRequestTimeoutCount=0;consecutiveMediaLogicalOpenFailures=0;logicalChannelFailureCount=0;lastLogicalChannelFailure=null;partialMediaWireTimeoutCount=0;lastPartialMediaWireTimeout=null;preOpenMediaCoalesceCount=0;lastPreOpenMediaCoalesce=null;logicalWireFailureCount=0;lastLogicalWireFailure=null;controlMediaRecoveryCount=0;lastControlMediaRecovery=null;livenessMediaRecoveryGeneration=0;mediaAttachmentHoldGeneration=0;lastFailure=null;lastTerminalWireBytes=0;lastTerminalWireReservations=0;workspaceReauthAttempt=null;configure(e){const t=Tt(e),i=this.session?`${this.session.user.id}
|
|
3
|
+
${this.session.workspaceId}
|
|
4
|
+
${this.session.workspaceRole}`:"",s=t?`${t.user.id}
|
|
5
|
+
${t.workspaceId}
|
|
6
|
+
${t.workspaceRole}`:"";this.session=t,i!==s&&(this.teardown("console-session-replaced",null,!0),this.lastFailure=null)}preferDirect(){this.preferred=!0}markLocalHubReachable(){this.preferred=!1,this.teardown("local-hub-reachable",null,!0),this.lastFailure=null}resume(){if(this.invalidateLivenessEvidence(),this.hasReadyPayloadPeer()){this.lastFailure=null;return}this.teardown("console-resume",null,!0),this.lastFailure=null}suspendLivenessEvidence(){this.invalidateLivenessEvidence()}retry(){this.preferred=!0,this.teardown("console-manual-retry",null,!0),this.lastFailure=null}shouldUseDirect(){return this.preferred&&!!this.session?.accessToken}inspect(){const e=this.wireBudget?.inspect()||{retainedBytes:0,reservationCount:0},t=[...this.channels.values()].filter(c=>c.wireDeadline!==null).length,i=[...this.channels.values()].filter(c=>c.openDeadline!==null).length,s=this.connectTimer===null?0:1,r=this.peerDisconnectTimer===null?0:1,o=this.controlWireDeadline===null?0:1,a=this.workspaceReauthAttempt?.deadline==null?0:1;return Object.freeze({preferred:this.preferred,stage:this.stage,directReady:this.directReady,generation:this.generation,signalSockets:this.signalSocket?1:0,peerCount:this.peer?1:0,controlChannels:this.controlChannel?1:0,logicalChannels:this.channels.size,openLogicalChannels:[...this.channels.values()].filter(c=>c.opened).length,pendingHttpRequests:this.pendingHttp.size,livenessEvidenceEpoch:this.livenessEvidenceEpoch,workspaceReauthRequests:this.workspaceReauthAttempt?1:0,consecutiveLivenessRequestTimeouts:this.consecutiveLivenessRequestTimeouts,livenessRequestTimeoutCount:this.livenessRequestTimeoutCount,consecutiveMediaLogicalOpenFailures:this.consecutiveMediaLogicalOpenFailures,logicalChannelFailureCount:this.logicalChannelFailureCount,lastLogicalChannelFailure:this.lastLogicalChannelFailure,partialMediaWireTimeoutCount:this.partialMediaWireTimeoutCount,lastPartialMediaWireTimeout:this.lastPartialMediaWireTimeout,preOpenMediaCoalesceCount:this.preOpenMediaCoalesceCount,lastPreOpenMediaCoalesce:this.lastPreOpenMediaCoalesce,logicalWireFailureCount:this.logicalWireFailureCount,lastLogicalWireFailure:this.lastLogicalWireFailure,controlMediaRecoveryCount:this.controlMediaRecoveryCount,lastControlMediaRecovery:this.lastControlMediaRecovery,mediaAttachmentHoldGeneration:this.mediaAttachmentHoldGeneration,heldMediaLogicalChannels:[...this.channels.values()].filter(c=>(c.purpose==="frame"||c.purpose==="atlas")&&c.owner===null&&c.dataChannel===null).length,pendingRemoteCandidates:this.pendingRemoteCandidates.length,pendingLocalCandidates:this.pendingLocalCandidates.length,connectTimers:s,peerDisconnectTimers:r,controlWireTimers:o,workspaceReauthTimers:a,logicalOpenTimers:i,logicalWireTimers:t,resourceTimers:s+r+o+a+i+t+this.pendingHttp.size,wireRetainedBytes:e.retainedBytes,wireReservations:e.reservationCount,sendBufferedBytes:this.peerBufferedAmount(),lastTerminalWireBytes:this.lastTerminalWireBytes,lastTerminalWireReservations:this.lastTerminalWireReservations,failure:this.lastFailure})}nextMessageId(){return this.wireMessageId=this.wireMessageId>=4294967295?1:this.wireMessageId+1,this.wireMessageId}isSignalOwner(e,t){return e===this.generation&&this.signalSocket===t}isPeerOwner(e){return tt(this.peerOwner,e)}hasReadyPayloadPeer(){return this.directReady&&!!this.peerOwner&&!!this.peer&&this.peer?.connectionState!=="failed"&&this.peer?.connectionState!=="closed"&&this.controlChannel?.readyState==="open"}detachSignalFromReadyPeer(e,t,i){if(!this.isSignalOwner(e,t)||!this.hasReadyPayloadPeer())return!1;this.cancelWorkspaceReauthAttempt(e,t),this.signalSocket=null,this.signalReady=!1,this.consoleId="";try{t.close(1e3,i)}catch{}return!0}clearConnectTimer(){this.connectTimer!==null&&(window.clearTimeout(this.connectTimer),this.connectTimer=null)}clearPeerDisconnectTimer(){this.peerDisconnectTimer!==null&&(window.clearTimeout(this.peerDisconnectTimer),this.peerDisconnectTimer=null)}cancelWorkspaceReauthAttempt(e,t){const i=this.workspaceReauthAttempt;if(!i||e!==void 0&&i.generation!==e||t!==void 0&&i.socket!==t)return!1;this.workspaceReauthAttempt=null,i.deadline!==null&&(window.clearTimeout(i.deadline),i.deadline=null);try{i.controller.abort()}catch{}return!0}refreshPeerDisconnectDeadline(e,t){if(!this.isPeerOwner(e)||this.peer!==t)return;if(!(t.connectionState==="disconnected"||t.iceConnectionState==="disconnected")){this.clearPeerDisconnectTimer();return}if(this.peerDisconnectTimer!==null)return;const s=window.setTimeout(()=>{this.peerDisconnectTimer===s&&(this.peerDisconnectTimer=null,!(!this.isPeerOwner(e)||this.peer!==t)&&(t.connectionState==="disconnected"||t.iceConnectionState==="disconnected")&&this.fail(p(),"peer-disconnected-timeout",!0))},ct);this.peerDisconnectTimer=s}clearControlWireDeadline(){this.controlWireDeadline!==null&&(window.clearTimeout(this.controlWireDeadline),this.controlWireDeadline=null)}refreshControlWireDeadline(e,t){if((t.inspect().pendingMessages||0)===0){this.clearControlWireDeadline();return}if(this.controlWireDeadline!==null)return;const s=window.setTimeout(()=>{this.controlWireDeadline===s&&(this.controlWireDeadline=null,!(!this.isPeerOwner(e)||this.controlAssembler!==t)&&(t.inspect().pendingMessages||0)>0&&this.fail(p(),"control-wire-assembly-timeout",!0))},ut);this.controlWireDeadline=s}resolveCurrentConnect(){const e=this.resolveConnect;this.resolveConnect=null,this.rejectConnect=null,this.connectPromise=null,this.clearConnectTimer(),e?.()}rejectCurrentConnect(e){const t=this.rejectConnect;this.resolveConnect=null,this.rejectConnect=null,this.connectPromise=null,this.clearConnectTimer(),t?.(e)}signal(e){if(!Lt.has(String(e.type||"")))throw new Error("console-direct-signal-type-forbidden");const t=this.signalSocket;if(!t||t.readyState!==WebSocket.OPEN||!this.signalReady)throw S();t.send(JSON.stringify(e))}peerBufferedAmount(){let e=Number(this.controlChannel?.bufferedAmount||0);for(const t of this.channels.values())e+=Number(t.dataChannel?.bufferedAmount||0);return e}sendWire(e,t,i,s){if(e.readyState!=="open")throw new Error("console-direct-data-channel-not-open");const r=je(t,{messageId:this.nextMessageId(),kind:i,maxMessageBytes:s}),o=r.reduce((a,c)=>a+c.byteLength,0);if(o>Ce||this.peerBufferedAmount()>Ce-o)throw new Error("console-direct-send-buffer-full");for(const a of r)e.send(a)}sendControl(e){const t=this.controlChannel;if(!t||!this.directReady||!this.peerOwner)throw p();this.sendWire(t,JSON.stringify(e),"control",k)}fail(e,t,i=!0){this.lastFailure=X(e),this.teardown(t,e,i)}teardown(e,t,i,s=!1){const r=this.signalSocket,o=this.peerOwner;if(i&&r?.readyState===WebSocket.OPEN&&this.signalReady&&o)try{this.signal({type:"rtc-close",connectionId:o.connectionId,hubEpoch:o.hubEpoch,reason:String(e||"console-direct-closed").slice(0,120)})}catch{}s?this.stage="hub-offline":(this.generation+=1,this.stage="idle",this.signalSocket=null,this.signalReady=!1,this.consoleId="",this.cancelWorkspaceReauthAttempt()),this.hubEpoch="",this.peerOwner=null,this.directReady=!1,this.remoteDescriptionApplied=!1,this.localOfferSent=!1,this.pendingLocalCandidates=[],this.pendingRemoteCandidates=[],this.invalidateLivenessEvidence(),this.clearConnectTimer(),this.clearPeerDisconnectTimer();const a=t||new Error(e||"console-direct-closed");this.rejectCurrentConnect(a);for(const[h,g]of this.pendingHttp)window.clearTimeout(g.timeout),g.detachAbort(),g.reject(a),this.pendingHttp.delete(h);for(const h of[...this.channels.values()])this.retireLogicalEntry(h,t?1011:1001,e,!!t,!1);this.clearControlWireDeadline(),this.controlAssembler?.dispose(),this.controlAssembler=null;const c=this.controlChannel;if(this.controlChannel=null,c){c.onopen=null,c.onmessage=null,c.onerror=null,c.onclose=null;try{c.close()}catch{}}const u=this.peer;if(this.peer=null,u){u.onicecandidate=null,u.onconnectionstatechange=null,u.oniceconnectionstatechange=null;try{u.close()}catch{}}if(!s)try{r?.close(1e3,String(e||"console-direct-closed").slice(0,120))}catch{}const d=this.wireBudget?.inspect();this.lastTerminalWireBytes=Number(d?.retainedBytes||0),this.lastTerminalWireReservations=Number(d?.reservationCount||0),this.wireBudget=null}async connect(){if(this.directReady&&this.peerOwner&&this.controlChannel?.readyState==="open")return;if(this.connectPromise)return this.connectPromise;const e=this.session;if(!e)throw S();const t=this.signalSocket?.readyState===WebSocket.OPEN&&this.signalReady;if(t&&this.stage==="hub-offline"){const r=V();throw this.lastFailure=X(r),r}if(t&&this.stage==="p2p"&&this.peerOwner&&this.peer){const r=this.generation,o=new Promise((a,c)=>{this.resolveConnect=a,this.rejectConnect=c});return this.connectPromise=o,this.connectTimer===null&&(this.connectTimer=window.setTimeout(()=>{r===this.generation&&!this.directReady&&this.fail(p(),"direct-ready-timeout",!0)},Y)),o}const i=this.generation+1;this.generation=i,this.stage="signal",this.lastFailure=null;const s=new Promise((r,o)=>{this.resolveConnect=r,this.rejectConnect=o});this.connectPromise=s,this.connectTimer=window.setTimeout(()=>{if(i!==this.generation)return;const r=this.stage==="signal"?S():p();this.fail(r,this.stage==="signal"?"signal-timeout":"direct-ready-timeout",!1)},this.stage==="signal"?at:Y);try{const r=new WebSocket(yt(e.workspaceId),[it,`${st}${e.accessToken}`]);this.signalSocket=r,r.addEventListener("message",o=>{if(!this.isSignalOwner(i,r)||typeof o.data!="string")return;let a;try{a=JSON.parse(o.data)}catch{this.fail(S(),"invalid-signal-json",!1);return}this.handleSignal(a,i,r)}),r.addEventListener("error",()=>{this.isSignalOwner(i,r)&&(this.detachSignalFromReadyPeer(i,r,"signal-detached-after-ready")||this.fail(S(),"signal-service-unavailable",!1))}),r.addEventListener("close",()=>{this.isSignalOwner(i,r)&&(this.detachSignalFromReadyPeer(i,r,"signal-closed-after-ready")||this.fail(S(),"signal-service-closed",!1))})}catch{this.fail(S(),"signal-constructor-failed",!1)}return s}handleSignal(e,t,i){if(!this.isSignalOwner(t,i))return;if(e.type==="workspace-reauth-required"){const r=this.session,o=String(e.workspaceId||r?.workspaceId||"").trim(),a=String(e.challengeNonce||"").trim();if(!r||o!==r.workspaceId||!N.test(a)){this.fail(S(),"workspace-reauth-owner-mismatch",!1);return}if(this.workspaceReauthAttempt?.challengeNonce===a&&this.workspaceReauthAttempt.generation===t&&this.workspaceReauthAttempt.socket===i)return;this.cancelWorkspaceReauthAttempt();const c=new AbortController,u={challengeNonce:a,generation:t,socket:i,controller:c,deadline:null},d=Number(e.deadlineAt||0),h=Number.isFinite(d)&&d>0?Math.max(1,d-Date.now()):me;u.deadline=window.setTimeout(()=>{this.workspaceReauthAttempt===u&&this.cancelWorkspaceReauthAttempt(t,i)},Math.max(1,Math.min(me,h))),this.workspaceReauthAttempt=u,(async()=>{try{await fetch(kt("/v2/rtc/reauth"),{method:"POST",headers:{Authorization:`Bearer ${r.accessToken}`,"Content-Type":"application/json"},body:JSON.stringify({workspaceId:r.workspaceId,challengeNonce:a}),signal:c.signal,cache:"no-store"})}catch{}})().finally(()=>{this.workspaceReauthAttempt===u&&(this.workspaceReauthAttempt=null,u.deadline!==null&&(window.clearTimeout(u.deadline),u.deadline=null))});return}if(e.type==="workspace-access-refreshed"||e.type==="workspace-reauth-ok"){e.type==="workspace-reauth-ok"&&this.cancelWorkspaceReauthAttempt(t,i);return}if(e.type==="workspace-access-expired"){this.fail(S(),"workspace-access-expired",!1);return}if(e.type==="signal-ready"){const r=String(e.consoleId||""),o=String(e.hubEpoch||"");if(e.role!=="console"||!N.test(r)){this.fail(S(),"invalid-signal-ready",!1);return}if(this.signalReady=!0,this.consoleId=r,e.hubOnline!==!0){const a=V();this.lastFailure=X(a),this.teardown("hub-offline",a,!1,!0);return}if(!N.test(o)){this.fail(S(),"invalid-hub-epoch",!1);return}if(this.peerOwner){this.peerOwner.hubEpoch!==o&&this.fail(p(),"hub-epoch-replaced",!1);return}this.hubEpoch=o,this.stage="p2p",this.lastFailure=null,this.clearConnectTimer(),this.connectTimer=window.setTimeout(()=>{t===this.generation&&!this.directReady&&this.fail(p(),"direct-ready-timeout",!0)},Y),this.beginPeer(t,o);return}const s=this.peerOwner;if(!(!s||String(e.connectionId||"")!==s.connectionId||String(e.hubEpoch||"")!==s.hubEpoch)){if(e.type==="rtc-answer")this.acceptAnswer(s,e.description);else if(e.type==="rtc-ice")this.acceptRemoteCandidate(s,e.candidate,e.sdpMid);else if(e.type==="rtc-close"){const r=String(e.reason||"rtc-closed"),o=/hub-offline/i.test(r)?V():p();this.fail(o,r,!1)}}}beginPeer(e,t){if(e!==this.generation||this.peer)return;const i=this.session;if(!i){this.fail(S(),"session-missing",!1);return}const s=et({userId:i.user.id,connectionId:crypto.randomUUID(),hubEpoch:t,generation:e});this.consecutiveMediaLogicalOpenFailures=0,this.peerOwner=s,this.wireBudget=ye({maxBytes:bt}),this.controlAssembler=ge({budget:this.wireBudget,maxMessageBytes:k});let r;try{r=new RTCPeerConnection({iceServers:[{urls:At()}],iceTransportPolicy:"all",bundlePolicy:"max-bundle",rtcpMuxPolicy:"require"})}catch{this.fail(p(),"peer-constructor-failed",!0);return}this.peer=r;const o=r.createDataChannel(rt,{ordered:!0});o.binaryType="arraybuffer",this.controlChannel=o,r.onicecandidate=a=>{if(!this.isPeerOwner(s)||this.peer!==r||!a.candidate)return;const c=String(a.candidate.candidate||"");if(P(c)){this.fail(p(),"relay-ice-candidate-forbidden",!0);return}if(new TextEncoder().encode(c).byteLength>gt){this.fail(p(),"local-ice-candidate-invalid",!0);return}if(!this.localOfferSent){if(this.pendingLocalCandidates.length>=pt){this.fail(p(),"local-ice-capacity-reached",!0);return}this.pendingLocalCandidates.push({candidate:c,sdpMid:a.candidate.sdpMid});return}try{this.signal({type:"rtc-ice",connectionId:s.connectionId,hubEpoch:s.hubEpoch,candidate:c,sdpMid:a.candidate.sdpMid})}catch{this.fail(S(),"signal-ice-failed",!1)}},r.onconnectionstatechange=()=>{if(!(!this.isPeerOwner(s)||this.peer!==r)){if(r.connectionState==="failed"||r.connectionState==="closed"){this.fail(p(),`peer-${r.connectionState}`,!0);return}this.refreshPeerDisconnectDeadline(s,r)}},r.oniceconnectionstatechange=()=>{if(!(!this.isPeerOwner(s)||this.peer!==r)){if(r.iceConnectionState==="failed"||r.iceConnectionState==="closed"){this.fail(p(),`ice-${r.iceConnectionState}`,!0);return}this.refreshPeerDisconnectDeadline(s,r)}},o.onmessage=a=>{!this.isPeerOwner(s)||this.controlChannel!==o||this.handleControlWire(s,a.data)},o.onerror=()=>{!this.isPeerOwner(s)||this.controlChannel!==o||this.fail(p(),"control-channel-error",!0)},o.onclose=()=>{!this.isPeerOwner(s)||this.controlChannel!==o||this.fail(p(),"control-channel-closed",!0)},(async()=>{try{const a=await r.createOffer();if(!this.isPeerOwner(s)||this.peer!==r)return;if(a.type!=="offer"||P(a.sdp))throw new Error("relay-sdp-forbidden");if(await r.setLocalDescription(a),!this.isPeerOwner(s)||this.peer!==r)return;const c=r.localDescription||a;if(c.type!=="offer"||P(c.sdp))throw new Error("relay-sdp-forbidden");this.signal({type:"rtc-offer",connectionId:s.connectionId,hubEpoch:s.hubEpoch,description:{type:"offer",sdp:c.sdp||""}}),this.localOfferSent=!0;const u=this.pendingLocalCandidates;this.pendingLocalCandidates=[];for(const d of u){if(!this.isPeerOwner(s)||this.peer!==r)return;this.signal({type:"rtc-ice",connectionId:s.connectionId,hubEpoch:s.hubEpoch,...d})}}catch(a){if(!this.isPeerOwner(s))return;const c=/signal/i.test(String(a?.message||""))?S():p();this.fail(c,"rtc-offer-failed",!0)}})()}async acceptAnswer(e,t){const i=this.peer;if(!(!this.isPeerOwner(e)||!i||this.remoteDescriptionApplied)){if(t?.type!=="answer"||typeof t.sdp!="string"||P(t.sdp)){this.fail(p(),"rtc-answer-invalid",!0);return}try{if(await i.setRemoteDescription({type:"answer",sdp:t.sdp}),!this.isPeerOwner(e)||this.peer!==i)return;this.remoteDescriptionApplied=!0;const s=this.pendingRemoteCandidates;this.pendingRemoteCandidates=[];for(const r of s){if(!this.isPeerOwner(e)||this.peer!==i)return;await i.addIceCandidate(r.candidate?r:null)}}catch{this.isPeerOwner(e)&&this.fail(p(),"rtc-answer-apply-failed",!0)}}}async acceptRemoteCandidate(e,t,i){if(!this.isPeerOwner(e))return;const s=String(t??""),r=i==null?null:String(i);if(s.length>4*1024||r!==null&&r.length>256||P(s)){this.fail(p(),"rtc-candidate-invalid",!0);return}const o=this.peer;if(o){if(!this.remoteDescriptionApplied){if(this.pendingRemoteCandidates.length>=ft){this.fail(p(),"rtc-candidate-capacity",!0);return}this.pendingRemoteCandidates.push({candidate:s,sdpMid:r});return}try{await o.addIceCandidate(s?{candidate:s,sdpMid:r}:null)}catch{this.isPeerOwner(e)&&this.fail(p(),"rtc-candidate-apply-failed",!0)}}}handleControlWire(e,t){const i=this.controlAssembler;if(!(!this.isPeerOwner(e)||!i))try{const s=i.push(se(t));if(this.refreshControlWireDeadline(e,i),!s)return;if(s.kind!=="control"||typeof s.data!="string")throw new Error("control-wire-kind-invalid");const r=JSON.parse(s.data);if(r.type==="direct-ready"){if(r.connectionId!==e.connectionId||r.hubEpoch!==e.hubEpoch||this.controlChannel?.readyState!=="open")throw new Error("direct-ready-owner-invalid");this.directReady||(this.consecutiveLivenessRequestTimeouts=0,this.directReady=!0,this.stage="ready",this.resolveCurrentConnect());return}if(r.type==="http-response"){this.handleHttpResponse(e,r);return}if(r.type==="ws-opened"||r.type==="ws-closed"||r.type==="ws-error"){this.handleLogicalLifecycle(e,r);return}throw new Error("control-message-type-invalid")}catch{this.isPeerOwner(e)&&this.fail(p(),"control-wire-invalid",!0)}}handleLogicalLifecycle(e,t){if(t.connectionId!==e.connectionId||t.hubEpoch!==e.hubEpoch)throw new Error("logical-lifecycle-owner-invalid");const i=String(t.channelId||"");if(!N.test(i))throw new Error("logical-lifecycle-channel-invalid");const s=this.channels.get(i);if(!s)return;const r=s.dataChannel;if(!r||!s.openRequested||!this.logicalEntryIsCurrent(s,e,r))throw new Error("logical-lifecycle-owner-invalid");if(t.type==="ws-opened"){if(s.opened)return;s.opened=!0,(s.purpose==="frame"||s.purpose==="atlas")&&(this.consecutiveMediaLogicalOpenFailures=0),this.clearLogicalOpenDeadline(s);const o=s.pendingInbound.splice(0);if(s.pendingInboundBytes=0,s.socket.managerOpened(),!this.logicalEntryIsCurrent(s,e,r)||!s.opened)return;for(const a of o)this.deliverLogicalMessage(s,a);return}if(t.type==="ws-closed"){this.retireLogicalEntry(s,ie(t.code,1e3),String(t.reason||""),!1,!1);return}this.retireLogicalEntry(s,1011,String(t.error||"console-direct-websocket-error"),!0,!1)}handleHttpResponse(e,t){const i=String(t.requestId||""),s=this.pendingHttp.get(i);if(!s||s.generation!==e.generation||!this.isPeerOwner(e))return;this.consecutiveLivenessRequestTimeouts=0,this.livenessMediaRecoveryGeneration=0;const r=this.mediaAttachmentHoldGeneration===e.generation;this.pendingHttp.delete(i),window.clearTimeout(s.timeout),s.detachAbort();try{const o=Number(t.status||502),a=t.bodyBase64?Dt(t.bodyBase64):new TextEncoder().encode(JSON.stringify({ok:!1,error:t.error||"console-direct-request-failed"})),c=new Response(a,{status:Number.isInteger(o)&&o>=200&&o<=599?o:502,statusText:String(t.statusText||""),headers:t.headers||{"content-type":"application/json"}});s.resolve(c),r&&(this.mediaAttachmentHoldGeneration=0,this.attachHeldMediaChannels(e))}catch(o){s.reject(K(o))}}async fetch(e,t,i){await Pt(this.connect(),t?.signal);const s=this.peerOwner;if(!s||!this.directReady||this.controlChannel?.readyState!=="open")throw p();if(this.pendingHttp.size>=Ee)throw new Error("console-direct-http-capacity-reached");const r=await Ot(t?.body);if(r.byteLength>wt)throw new Error("console-direct-http-body-too-large");if(!this.isPeerOwner(s)||!this.directReady)throw p();if(this.pendingHttp.size>=Ee)throw new Error("console-direct-http-capacity-reached");if(t?.signal?.aborted)throw t.signal.reason||new Error("Mobile Console request cancelled.");const o=crypto.randomUUID(),a=Number.isFinite(i)&&i>0?Math.floor(i):4e3,c=String(t?.method||"GET").toUpperCase(),u=c==="GET"&&mt.has(e),d=u?this.livenessEvidenceEpoch:null,h=new Promise((g,w)=>{const C=(E,m=!1)=>{const y=this.pendingHttp.get(o);if(y){this.pendingHttp.delete(o),window.clearTimeout(y.timeout),y.detachAbort();try{this.sendControl({type:"http-cancel",requestId:o})}catch{}w(E),m&&u&&this.recordLivenessRequestTimeout(s,y.livenessEvidenceEpoch)}},b=()=>C(t?.signal?.reason instanceof Error?t.signal.reason:new Error("Mobile Console request cancelled."));t?.signal?.addEventListener("abort",b,{once:!0});const l=window.setTimeout(()=>{C(new Error("Mobile Console direct request timed out."),!0)},a);this.pendingHttp.set(o,{generation:s.generation,livenessEvidenceEpoch:d,resolve:g,reject:w,timeout:l,detachAbort:()=>t?.signal?.removeEventListener("abort",b)})});try{this.sendControl({type:"http-request",requestId:o,method:c,path:e,headers:Rt(t),bodyBase64:r.byteLength>0?Mt(r):""})}catch(g){const w=this.pendingHttp.get(o);w&&(this.pendingHttp.delete(o),window.clearTimeout(w.timeout),w.detachAbort(),w.reject(K(g))),this.fail(p(),"control-send-failed",!0)}return h}openWebSocket(e,t){if(!vt.has(t))throw new Error("console-direct-purpose-invalid");if(this.channels.size>=ht)throw new Error("console-direct-channel-capacity-reached");const i=crypto.randomUUID(),s=new Nt(this,i,t,e),r={channelId:i,path:e,purpose:t,socket:s,owner:null,dataChannel:null,assembler:null,openDeadline:null,wireDeadline:null,wireStartedAtEpochMs:0,wireLastProgressAtEpochMs:0,wireAbsoluteDeadlineAtEpochMs:0,openRequested:!1,opened:!1,pendingInbound:[],pendingInboundBytes:0};return this.channels.set(i,r),this.connect().then(()=>{this.channels.get(i)===r&&this.attachLogicalChannel(r)}).catch(o=>{this.channels.get(i)===r&&this.retireLogicalEntry(r,1011,K(o).message,!0,!1)}),s}attachLogicalChannel(e){const t=this.peerOwner,i=this.peer,s=this.wireBudget;if(!t||!i||!s||!this.directReady||this.channels.get(e.channelId)!==e){this.retireLogicalEntry(e,1011,"console-direct-not-ready",!0,!1);return}const r=e.purpose==="frame"||e.purpose==="atlas";if(r&&this.mediaAttachmentHoldGeneration===t.generation)return;e.owner=t;let o;try{o=i.createDataChannel(`${ot}${e.channelId}:${e.purpose}`,{ordered:!0})}catch{this.retireLogicalOpenFailure(e,t,1011,"console-direct-channel-create-failed",!0,!0);return}o.binaryType="arraybuffer",e.dataChannel=o,e.assembler=ge({budget:s,maxMessageBytes:r?Se:k,maxPendingMessages:r?Et:2}),this.refreshLogicalOpenDeadline(e,t,o),o.onopen=()=>{if(this.logicalEntryIsCurrent(e,t,o))try{this.sendControl({type:"ws-open",connectionId:t.connectionId,hubEpoch:t.hubEpoch,channelId:e.channelId,purpose:e.purpose,path:e.path}),e.openRequested=!0}catch{this.retireLogicalEntry(e,1011,"console-direct-ws-open-failed",!0,!1)}},o.onmessage=a=>{this.logicalEntryIsCurrent(e,t,o)&&this.handleLogicalWire(e,t,a.data)},o.onerror=()=>{this.logicalEntryIsCurrent(e,t,o)&&this.retireLogicalOpenFailure(e,t,1011,"console-direct-channel-error",!0,!1)},o.onclose=()=>{this.logicalEntryIsCurrent(e,t,o)&&this.retireLogicalOpenFailure(e,t,1006,"console-direct-channel-closed",!1,!1)}}retireLogicalOpenFailure(e,t,i,s,r,o){if(this.channels.get(e.channelId)!==e||!this.isPeerOwner(t))return;const a=!e.openRequested&&(e.purpose==="frame"||e.purpose==="atlas");this.logicalChannelFailureCount+=1,this.lastLogicalChannelFailure=Object.freeze({reason:String(s||"console-direct-logical-channel-failed").slice(0,120),purpose:e.purpose,generation:t.generation,occurredAt:Date.now()}),a&&(this.consecutiveMediaLogicalOpenFailures+=1);const c=[...this.channels.values()].some(d=>d!==e&&d.opened&&(d.purpose==="frame"||d.purpose==="atlas")&&d.dataChannel?.readyState==="open"),u=a&&!c&&(o||this.consecutiveMediaLogicalOpenFailures>=It);this.retireLogicalEntry(e,i,s,r,!1),u&&this.isPeerOwner(t)&&this.fail(p(),"console-direct-media-channel-unusable",!0)}logicalEntryIsCurrent(e,t,i){return this.channels.get(e.channelId)===e&&e.owner===t&&e.dataChannel===i&&this.isPeerOwner(t)}clearLogicalOpenDeadline(e){e.openDeadline!==null&&(window.clearTimeout(e.openDeadline),e.openDeadline=null)}refreshLogicalOpenDeadline(e,t,i){this.clearLogicalOpenDeadline(e);const s=window.setTimeout(()=>{e.openDeadline===s&&(e.openDeadline=null,!(!this.logicalEntryIsCurrent(e,t,i)||e.opened)&&this.retireLogicalOpenFailure(e,t,1011,"console-direct-logical-open-timeout",!0,!1))},lt);e.openDeadline=s}invalidateLivenessEvidence(){this.livenessEvidenceEpoch+=1,this.consecutiveLivenessRequestTimeouts=0,this.livenessMediaRecoveryGeneration=0,this.peerOwner||(this.mediaAttachmentHoldGeneration=0)}attachHeldMediaChannels(e){if(!this.isPeerOwner(e)||!this.directReady)return 0;let t=0;for(const i of[...this.channels.values()])i.owner!==null||i.dataChannel!==null||i.purpose!=="frame"&&i.purpose!=="atlas"||(this.attachLogicalChannel(i),t+=1);return t}recoverControlFromMediaPressure(e){if(!this.isPeerOwner(e)||this.livenessMediaRecoveryGeneration===e.generation)return!1;const t=[...this.channels.values()].filter(i=>(i.purpose==="frame"||i.purpose==="atlas")&&i.owner===e&&i.dataChannel?.readyState==="open");if(t.length===0)return!1;this.livenessMediaRecoveryGeneration=e.generation,this.mediaAttachmentHoldGeneration=e.generation,this.livenessEvidenceEpoch+=1,this.consecutiveLivenessRequestTimeouts=0,this.controlMediaRecoveryCount+=1,this.lastControlMediaRecovery=Object.freeze({generation:e.generation,retiredMediaLanes:t.length,occurredAt:Date.now()});for(const i of t)this.retireLogicalEntry(i,1013,"console-direct-control-media-recovery",!1,!0);return!0}recordLivenessRequestTimeout(e,t){t===null||t!==this.livenessEvidenceEpoch||!this.isPeerOwner(e)||!this.directReady||(this.livenessRequestTimeoutCount+=1,this.consecutiveLivenessRequestTimeouts+=1,!(this.consecutiveLivenessRequestTimeouts<2)&&(this.recoverControlFromMediaPressure(e)||this.fail(p(),"control-http-timeout",!0)))}handleLogicalWire(e,t,i){const s=e.assembler;if(!s||!this.logicalEntryIsCurrent(e,t,e.dataChannel))return;const r=s.inspect();let o={chunkBytes:0,headerReadable:!1,messageId:0,chunkIndex:0,chunkCount:0,totalLength:0};try{o=_t(i);const a=s.push(se(i));if(this.refreshLogicalWireDeadline(e,t),!a)return;if(a.kind==="control")throw new Error("logical-control-forbidden");let c;if(a.kind==="text"&&typeof a.data=="string")c={kind:"text",data:a.data,byteLength:a.byteLength};else if(a.kind==="binary"&&a.data instanceof Uint8Array)c={kind:"binary",data:a.data,byteLength:a.byteLength};else throw new Error("logical-wire-kind-invalid");if(!e.opened){this.queuePreOpenLogicalMessage(e,c);return}this.deliverLogicalMessage(e,c)}catch(a){this.logicalWireFailureCount+=1,this.lastLogicalWireFailure=Object.freeze({errorCode:a instanceof B?a.code:a instanceof Error?a.message.slice(0,120):"logical-wire-invalid",purpose:e.purpose,generation:t.generation,pendingMessagesBefore:Math.max(0,Number(r.pendingMessages||0)),pendingBytesBefore:Math.max(0,Number(r.pendingBytes||0)),...o,occurredAt:Date.now()}),this.retireLogicalEntry(e,1011,"console-direct-wire-invalid",!0,!1)}}queuePreOpenLogicalMessage(e,t){const i=e.purpose==="frame"||e.purpose==="atlas",s=i?Se:k;if(i){if(e.pendingInbound.length===0){e.pendingInbound.push(t),e.pendingInboundBytes=t.byteLength;return}if(e.pendingInbound.length<St&&e.pendingInboundBytes+t.byteLength<=s){e.pendingInbound.push(t),e.pendingInboundBytes+=t.byteLength;return}const r=e.pendingInbound[0],o=r.byteLength+t.byteLength,a=o<=s?"replace-latest":"drop-over-budget";a==="replace-latest"&&(e.pendingInbound=[r,t],e.pendingInboundBytes=o),this.preOpenMediaCoalesceCount+=1,this.lastPreOpenMediaCoalesce=Object.freeze({action:a,purpose:e.purpose==="atlas"?"atlas":"frame",generation:e.owner?.generation||0,retainedMessages:e.pendingInbound.length,retainedBytes:e.pendingInboundBytes,incomingBytes:t.byteLength,occurredAt:Date.now()});return}if(e.pendingInbound.length>=Ct||e.pendingInboundBytes+t.byteLength>s)throw new Error("logical-preopen-buffer-full");e.pendingInbound.push(t),e.pendingInboundBytes+=t.byteLength}deliverLogicalMessage(e,t){if(t.kind==="text"){e.socket.managerMessage(t.data);return}const i=t.data,s=i.buffer.slice(i.byteOffset,i.byteOffset+i.byteLength);e.socket.managerMessage(e.socket.binaryType==="arraybuffer"?s:new Blob([s]))}logicalBufferedAmount(e){return Number(this.channels.get(e)?.dataChannel?.bufferedAmount||0)}clearLogicalWireDeadline(e){e.wireDeadline!==null&&(window.clearTimeout(e.wireDeadline),e.wireDeadline=null),e.wireStartedAtEpochMs=0,e.wireLastProgressAtEpochMs=0,e.wireAbsoluteDeadlineAtEpochMs=0}scheduleLogicalWireDeadline(e,t){e.wireDeadline!==null&&window.clearTimeout(e.wireDeadline);const i=e.purpose==="frame"||e.purpose==="atlas",s=Date.now(),r=e.assembler?.inspect(),o=i?we(Number(r?.pendingBytes||0)):Number.POSITIVE_INFINITY,a=i?Math.max(1,o-(s-e.wireLastProgressAtEpochMs)):Number.POSITIVE_INFINITY,c=Math.max(1,e.wireAbsoluteDeadlineAtEpochMs-s),u=window.setTimeout(()=>{if(e.wireDeadline!==u)return;e.wireDeadline=null;const d=e.dataChannel;if(!d||!this.logicalEntryIsCurrent(e,t,d))return;const h=e.assembler?.inspect(),g=Number(h?.pendingMessages||0);if(g===0){this.clearLogicalWireDeadline(e);return}const w=Date.now(),C=Math.max(0,w-e.wireLastProgressAtEpochMs),b=Math.max(0,w-e.wireStartedAtEpochMs),l=i?we(Number(h?.pendingBytes||0)):Number.POSITIVE_INFINITY;if(!(!i||C>=l||w>=e.wireAbsoluteDeadlineAtEpochMs)){this.scheduleLogicalWireDeadline(e,t);return}if(i){this.partialMediaWireTimeoutCount+=1,this.lastPartialMediaWireTimeout=Object.freeze({recovery:"abandon-message",purpose:e.purpose,generation:t.generation,pendingMessages:g,pendingBytes:Math.max(0,Number(h?.pendingBytes||0)),stalledForMs:C,lifetimeMs:b,idleDeadlineMs:l,absoluteDeadlineMs:Math.max(0,e.wireAbsoluteDeadlineAtEpochMs-e.wireStartedAtEpochMs),occurredAt:w}),e.assembler?.abandonPending(),this.clearLogicalWireDeadline(e);return}this.retireLogicalEntry(e,1011,"console-direct-partial-message-timeout",!0,!1)},Math.min(a,c));e.wireDeadline=u}refreshLogicalWireDeadline(e,t){const i=e.assembler?.inspect();if(Number(i?.pendingMessages||0)===0){this.clearLogicalWireDeadline(e);return}const r=Date.now(),o=e.purpose==="frame"||e.purpose==="atlas";e.wireStartedAtEpochMs<=0&&(e.wireStartedAtEpochMs=r,e.wireAbsoluteDeadlineAtEpochMs=r+(o?Ze(Number(i?.pendingBytes||0)):dt)),e.wireLastProgressAtEpochMs=r,this.scheduleLogicalWireDeadline(e,t)}sendLogicalMessage(e,t){const i=this.channels.get(e),s=i?.dataChannel;if(!i||!s||!i.opened||s.readyState!=="open")throw new DOMException("WebSocket is not open.","InvalidStateError");try{if(typeof t=="string")this.sendWire(s,t,"text",k);else if(t instanceof ArrayBuffer)this.sendWire(s,t,"binary",k);else if(ArrayBuffer.isView(t)){const r=new Uint8Array(t.buffer,t.byteOffset,t.byteLength);this.sendWire(s,r,"binary",k)}else throw new DOMException("Blob sends are not supported by the direct Console channel.","NotSupportedError")}catch(r){throw this.retireLogicalEntry(i,1011,"console-direct-send-failed",!0,!1),r}}closeLogicalChannel(e,t,i,s){const r=this.channels.get(e);r&&this.retireLogicalEntry(r,t,i,!1,s)}retireLogicalEntry(e,t,i,s,r){if(this.channels.get(e.channelId)!==e)return;this.channels.delete(e.channelId);const o=e.dataChannel,a=e.owner;if(r&&a&&e.openRequested&&this.isPeerOwner(a)&&this.controlChannel?.readyState==="open")try{this.sendControl({type:"ws-close",connectionId:a.connectionId,hubEpoch:a.hubEpoch,channelId:e.channelId,code:t,reason:i})}catch{s=!0}if(this.clearLogicalWireDeadline(e),this.clearLogicalOpenDeadline(e),e.assembler?.dispose(),e.assembler=null,e.pendingInbound=[],e.pendingInboundBytes=0,e.dataChannel=null,e.owner=null,e.openRequested=!1,e.opened=!1,o){o.onopen=null,o.onmessage=null,o.onerror=null,o.onclose=null;try{o.close()}catch{}}e.socket.managerClosed(t,i,s)}}const I=new xt;function Ae(n){I.configure(n)}function Wt(){I.preferDirect()}function Bt(){I.markLocalHubReachable()}function dn(){I.resume()}function hn(){I.suspendLivenessEvidence()}function fn(){I.retry()}function J(n,e,t){return I.preferDirect(),I.fetch(n,e,t)}function pn(n,e,t){return I.shouldUseDirect()?I.openWebSocket(e,t):new WebSocket(n)}function gn(){return I.inspect()}function Ut(n){let e=null;return{run(){if(e)return e;const t=Promise.resolve().then(n);e=t.finally(()=>{(e===t||e===i)&&(e=null)});const i=e;return i}}}async function Ht(n,e){return n&&await n.catch(()=>{}),e()}function Ft(n,e={}){if(e.publicConsole===!0)throw new Error("Public Console does not create a Hub cookie session.");return n?.workspaceKind==="team"&&n?.workspaceRole==="operator"?{accessToken:n.accessToken,workspaceId:n.workspaceId}:{accessToken:n.accessToken,refreshToken:n.refreshToken,expiresAt:n.expiresAt,user:n.user,workspaceId:n.workspaceId}}function le(n){return!n?.user?.id||!n?.workspaceId?"":[n.user.id,n.workspaceId,n.workspaceKind,n.workspaceRole,Number(n.membershipRevision||0)].join(`
|
|
7
|
+
`)}function qt(n){const e=le(n);return!e||!n?.accessToken||!n?.refreshToken?"":[e,n.accessToken,n.refreshToken,Number(n.expiresAt||0)].join(`
|
|
8
|
+
`)}function Gt({publicConsole:n,path:e,requiresUiSession:t}){return n?String(e||"").split("?")[0]==="/api/auth/session"?"reject-auth-session":t?"direct":"local":"local"}const x=5179,_=H(`http://127.0.0.1:${x}`);function jt(n){const e=n.split(".").map(t=>Number(t));return e.length===4&&e.every(t=>Number.isInteger(t)&&t>=0&&t<=255)?e:[]}function Me(n){const e=n.trim().toLowerCase();return e==="localhost"||e==="127.0.0.1"||e==="::1"||e==="[::1]"}function $t(n){const e=n.trim().toLowerCase();return!e||e==="0.0.0.0"||e==="::"||e==="[::]"}function De(n){const e=jt(n);return e.length===0?!1:e[0]===10||e[0]===172&&e[1]>=16&&e[1]<=31||e[0]===192&&e[1]===168}function zt(n){return n.includes(":")&&!n.startsWith("[")?`[${n}]`:n}function Vt(n){const e=String(n||"").trim();if(!e)return null;const t=/^[a-z][a-z\d+.-]*:\/\//i.test(e)?e:`tcp://${e}`;try{const i=new URL(t),s=i.hostname.replace(/^\[|\]$/g,""),r=Number(i.port);return!s||!Number.isInteger(r)||r<1||r>65535||$t(s)?null:{host:s,port:r}}catch{return null}}function H(n){const e=String(n||"").trim()||`http://127.0.0.1:${x}`,t=/^[a-z][a-z\d+.-]*:\/\//i.test(e)?e:`http://${e}`;try{const i=new URL(t);return i.port||(i.port=String(x)),i.hash="",i.search="",i.toString().replace(/\/+$/,"")}catch{return`http://127.0.0.1:${x}`}}function Xt(n){const e=Vt(n);return e?H(`http://${zt(e.host)}:${x}`):""}function wn(n){const t=[n?.endpoint,...Array.isArray(n?.endpoint_candidates)?n.endpoint_candidates:[]].map(i=>Xt(String(i||""))).filter(Boolean);return[...new Set(t)]}function Yt(n=_){if(!(typeof window>"u"||window.location.protocol!=="https:"))try{const e=new URL(n);if(e.protocol!=="http:")return;if(Me(e.hostname))return"loopback";if(De(e.hostname))return"local"}catch{return}}function mn(n,e=_){const t=new URL(n,H(e));return t.protocol=t.protocol==="https:"?"wss:":"ws:",t.toString()}let L=null,R="",A="";const v=new Map,O=new Map,U=new Map,q=new Set;function $(n){const e=U.get(n);e!==void 0&&typeof window<"u"&&window.clearTimeout(e),U.delete(n)}function Oe(){for(const n of U.keys())$(n)}function re(n){const e=Number(n||0);if(Number.isFinite(e)&&e>0)return e<1e10?e*1e3:e;const t=Date.parse(String(n||""));return Number.isFinite(t)?t:0}function Re(n,e,t){if($(n),typeof window>"u"||e<=Date.now())return;const i=Math.max(1e3,Math.min(45e3,e-Date.now()-15e3)),s=window.setTimeout(()=>{U.delete(n),!(t!==R||L?.workspaceKind!=="team")&&j(n,!0).catch(()=>{})},i);U.set(n,s)}function Kt(n,e,t){const i=L?.workspaceKind==="team",s=i?re(e.accessExpiresAt)||Date.now()+6e4:0;v.set(n,{csrfToken:e.csrfToken,expiresAt:e.expiresAt,accessExpiresAt:s,ownerSignature:A}),q.add(n),i?Re(n,s,t):$(n)}function bn(n){const e=n?.accessToken&&n?.refreshToken&&n?.user?.id?n:null,t=le(e),i=qt(e);if(t!==A&&(e&&v.clear(),A=t),i!==R&&(Oe(),R=i,e?.workspaceKind==="team"))for(const[s,r]of v)r.ownerSignature===t&&Re(s,r.accessExpiresAt,i);L=e,Ae(e?{accessToken:e.accessToken,user:{id:e.user.id},workspaceId:e.workspaceId,workspaceKind:e.workspaceKind,workspaceRole:e.workspaceRole,membershipRevision:e.membershipRevision}:null),e&&z()&&Wt()}function z(){if(typeof window>"u"||window.location.protocol!=="https:")return!1;const n=window.location.hostname.replace(/^\[|\]$/g,"");return!Me(n)&&!De(n)}function Q(n){const e=n.split("?")[0];return e==="/api/health"||e==="/api/runtime/status"||e==="/api/auth/status"||e==="/api/auth/session"}async function G(n,e,t,i,s){const r=Yt(t);return r&&(e.targetAddressSpace=r),Ne(s,i,async o=>{e.signal=o;try{return await fetch(`${t}${n}`,e)}catch(a){throw!o.aborted&&r?new Error("VuvoDesk Hub is not reachable at this local network address. If Chrome shows a local network prompt, allow it; otherwise restart the Hub so port 5179 is open on the network."):a}})}async function j(n,e=!1){if(z())throw new Error("Public Console uses verified P2P authorization instead of a Hub cookie session.");const t=v.get(n);if(!e&&t&&t.ownerSignature===A&&t.expiresAt>Date.now()+3e4&&(t.accessExpiresAt===0||t.accessExpiresAt>Date.now()+15e3))return;e&&v.delete(n);const i=L,s=R;if(!i)return;const r=O.get(n);if(r)return r.authSignature===s?r.promise:r.promise.catch(()=>{}).then(()=>j(n,e));let o;const a=(async()=>{const c=await G("/api/auth/session",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(Ft(i,{publicConsole:!1})),credentials:"include",cache:"no-store"},n,W),u=await c.json().catch(()=>null);if(!c.ok)throw new Error(`${c.status} ${u?.error||c.statusText}`);const d=String(u?.uiSession?.csrfToken||"").trim(),h=Number(u?.uiSession?.expiresAt||0);if(!d||!Number.isFinite(h)||h<=Date.now())throw new Error("VuvoDesk Hub did not issue a valid UI session.");if(s!==R)throw v.set(n,{csrfToken:d,expiresAt:h,accessExpiresAt:re(u?.uiSession?.accessExpiresAt),ownerSignature:le(i)}),q.add(n),new Error("VuvoDesk workspace changed while the Hub session was opening.");Kt(n,{csrfToken:d,expiresAt:h,accessExpiresAt:re(u?.uiSession?.accessExpiresAt)},s)})().finally(()=>{O.get(n)===o&&O.delete(n)});return o={authSignature:s,promise:a},O.set(n,o),a}async function Jt(){const n=new Set(q);for(const t of O.keys())n.add(t);z()||n.add(H(_));const e=[...n].map(t=>Ht(O.get(t)?.promise,async()=>{const i=v.get(t),s=await G("/api/auth/session",{method:"DELETE",headers:i?.csrfToken?{"X-LiveDesk-CSRF":i.csrfToken}:{},credentials:"include",cache:"no-store"},t,W);if(!s.ok&&s.status!==401){const r=await s.json().catch(()=>null);throw new Error(`${s.status} ${r?.error||s.statusText}`)}q.delete(t),v.delete(t),$(t)}));await Promise.all(e)}const Qt=Ut(Jt);function En(){return L=null,R="",A="",Oe(),Ae(null),Qt.run()}async function Zt(n,e,t=_){const i=H(t),{timeoutMs:s=W,signal:r,transport:o="auto",...a}=e||{},c=!Q(n),u=c?A:"",d=()=>!c||!!u&&u===A,h=()=>{if(!d())throw new Error("VuvoDesk workspace changed while the Hub request was running.")},g=Gt({publicConsole:z(),path:n,requiresUiSession:c});if(c&&!L)throw new Error("VuvoDesk account authority is not available for this Hub request.");const w=()=>{const C=String(a.method||"GET").toUpperCase(),b=v.get(i),l=b?.ownerSignature===A?b.csrfToken:"";return{...a,...r?{signal:r}:{},headers:{...a.headers||{},...!["GET","HEAD","OPTIONS"].includes(C)&&l?{"X-LiveDesk-CSRF":l}:{}},credentials:"include",cache:"no-store"}};if(g==="reject-auth-session")throw new Error("Public Console does not create a Hub cookie session.");if(g==="direct"){if(h(),r?.aborted)throw r.reason||new Error("VuvoDesk Hub request cancelled.");return J(n,w(),s)}if(o==="p2p"){if(h(),r?.aborted)throw r.reason||new Error("VuvoDesk Hub request cancelled.");if(!L||Q(n))throw new Error("Mobile Console direct connection requires an authenticated management request.");return J(n,w(),s)}try{c&&await j(i),h();let C=await G(n,w(),i,s,r);if(h(),Bt(),c&&C.status===401&&L){const b=await C.clone().json().catch(()=>null);/^hub-ui-session-(required|expired)$/.test(String(b?.error||""))&&(await j(i,!0),h(),C=await G(n,w(),i,s,r),h())}return C}catch(C){if(!d()||r?.aborted||!L||Q(n))throw C;return J(n,w(),s)}}async function en(n,e,t=_){const i=await Zt(n,{...e||{},headers:{"Content-Type":"application/json",...e?.headers||{}}},t);let s=null;try{s=await i.json()}catch(r){if(e?.signal?.aborted)throw r;s=null}if(!i.ok){const r=s&&typeof s=="object"&&"error"in s?String(s.error||""):"";throw new Error(`${i.status} ${r||i.statusText}`)}return s}async function Cn({baseUrl:n=_,targetRole:e,previousRuntimePid:t=0,allowedStates:i=["running","waiting-auth"],timeoutMs:s=3e4}){const r=Date.now()+s;let o=null;for(;Date.now()<r;){try{const c=await en("/api/runtime/status",void 0,n),u=String(c.role||"").toLowerCase(),d=String(c.state||"").toLowerCase(),h=Number(c.runtimePid||0),g=t>1?h>1&&h!==t:h>1;if(u===e&&i.map(w=>w.toLowerCase()).includes(d)&&g)return c}catch(c){o=c}await new Promise(c=>setTimeout(c,300))}const a=o instanceof Error?` ${o.message}`:"";throw new Error(`VuvoDesk runtime did not become ${e} with a new process.${a}`)}function Sn(n,e=120){if(typeof window>"u")return;const t=new URL(window.location.href);t.port=String(n),t.pathname="/",t.search="",t.hash="";const i=t.toString();let s=0;const r=()=>{fetch(i,{cache:"no-store",mode:"no-cors"}).then(()=>window.location.replace(i)).catch(()=>{if(s+=1,s>=e){window.location.replace(i);return}window.setTimeout(r,250)})};r()}function In(n){if(!n)return"-";const e=Date.now()-Date.parse(n);return Number.isFinite(e)?e<1e3?"now":e<6e4?`${Math.round(e/1e3)}s`:e<36e5?`${Math.round(e/6e4)}m`:`${Math.round(e/36e5)}h`:"-"}async function Ln(n){await navigator.clipboard.writeText(n)}const tn=5,nn=15,sn=50,rn=Number.POSITIVE_INFINITY,on=5,vn={free:{name:"Free",price:"$0",limit:tn,people:1,audience:"Personal, ad-supported",note:"Up to 5 personal devices supported by a standard banner."},ltd:{name:"Plus",price:"$5",ltd:"$79 LTD",limit:nn,people:1,audience:"Creators and homelabs",note:"15 devices, no ads, personal use."},pro:{name:"Pro / Business",price:"$15",ltd:"$199 LTD",limit:sn,people:1,audience:"Schools, academies, studios, and businesses",note:"Up to 50 devices for school, academy, and commercial use."},team:{name:"Team",price:"$49",limit:rn,people:on,audience:"Shared business operations",note:"Commercial use, a shared Team Space, and up to 5 people using their own accounts."}},an="0.1.686",cn={version:an},yn=String(cn.version).trim();function kn({size:n=22}){return M.jsxs("svg",{width:n,height:n,viewBox:"0 0 28 28",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",children:[M.jsx("rect",{x:"2.5",y:"4",width:"14",height:"9",rx:"1.5",stroke:"currentColor",strokeWidth:"1.7",opacity:"0.42"}),M.jsx("path",{d:"M7 16v1.5h5",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round",opacity:"0.42"}),M.jsx("rect",{x:"10.5",y:"2.5",width:"14",height:"9",rx:"1.5",stroke:"currentColor",strokeWidth:"1.7",opacity:"0.62"}),M.jsx("path",{d:"M15 14.5V16h5",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round",opacity:"0.62"}),M.jsx("rect",{x:"6.5",y:"8.5",width:"15",height:"10",rx:"1.7",fill:"currentColor",fillOpacity:"0.12",stroke:"currentColor",strokeWidth:"1.9"}),M.jsx("path",{d:"M12 21v1.5H9.5M16 21v1.5h2.5M9.5 22.5h9",stroke:"currentColor",strokeWidth:"1.9",strokeLinecap:"round"})]})}export{_ as D,tn as F,yn as L,kn as M,nn as P,on as T,sn as a,En as b,Ln as c,X as d,fn as e,In as f,Yt as g,en as h,z as i,pn as j,mn as k,H as l,dn as m,Sn as n,Zt as o,vn as p,bn as q,un as r,hn as s,wn as t,gn as u,Cn as w};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as e}from"./pwa-startup-DvbrYEQi.js";import{r as i,W as je,S as ee,F as D,b as ve,M,c as be,L as we,P as Re,A as $}from"./icons-CuXJn-Hz.js";import{h as C,w as Se,n as ye}from"./MonitorStackIcon-
|
|
1
|
+
import{j as e}from"./pwa-startup-DvbrYEQi.js";import{r as i,W as je,S as ee,F as D,b as ve,M,c as be,L as we,P as Re,A as $}from"./icons-CuXJn-Hz.js";import{h as C,w as Se,n as ye}from"./MonitorStackIcon-JfWhLRS2.js";import"./pwa-bootstrap-ljOQTt2e.js";const x={revision:0,settings:{connection:{showThisComputer:!1},security:{accessMode:"trusted-only"},control:{allowKeyboardMouse:!0,allowRemoteRestart:!1},filesAudio:{allowFileTransfer:!0,allowRemoteAudio:!0,rollingBufferEnabled:!1,recordingQuality:"standard",timelapseIntervalSeconds:10,includeRemoteCursor:!0}}},Z=[{id:"connection",label:"Connection",icon:je},{id:"remote-access",label:"Remote Access",icon:ee},{id:"capture-audio",label:"Capture & Audio",icon:D},{id:"agent",label:"Agent",icon:ve}];function A(t,n){return t?.settings?.[n]||x.settings[n]||{}}function _(t,n){return{...t,settings:{...t.settings,[n.section]:{...A(t,n.section),[n.key]:n.value}}}}function O(t){return{revision:Number(t.revision||0),updatedAt:t.updatedAt,settings:t.settings}}function g({icon:t,title:n,description:d,children:m,recommended:a=!1}){return e.jsxs("div",{className:"product-setting-row",children:[e.jsx("div",{className:"product-setting-control",children:m}),t&&e.jsx("span",{className:"product-setting-icon",children:e.jsx(t,{size:17})}),e.jsxs("div",{className:"product-setting-copy",children:[e.jsx("strong",{children:n}),a&&e.jsx("em",{children:"Recommended"}),e.jsx("small",{children:d})]})]})}function R({checked:t,onChange:n,label:d}){return e.jsxs("label",{className:"product-switch",children:[e.jsx("input",{"aria-label":d,type:"checkbox",checked:t,onChange:m=>n(m.target.checked)}),e.jsx("span",{})]})}function U({value:t,onChange:n,options:d,label:m}){return e.jsx("select",{"aria-label":m,value:String(t),onChange:a=>n(a.target.value),children:d.map(([a,F])=>e.jsx("option",{value:a,children:F},a))})}function Te({hubUrl:t="",mobileLayout:n=!1,runtimeRole:d="hub",runtimeDeviceId:m="",sessionAccessToken:a="",showThisComputerSetting:F=!0,onShowThisComputerChange:J,initialTab:Q="connection",pin:te,agent:se,captureGallery:ne,desktopUpdate:ie}){const[r,q]=i.useState(()=>n&&Q==="connection"?"remote-access":Q),[j,k]=i.useState(null),[oe,v]=i.useState("loading"),[G,T]=i.useState(""),[K,E]=i.useState("idle"),[L,z]=i.useState(""),b=i.useRef(null),u=i.useRef(null),p=i.useRef([]),B=i.useRef(Promise.resolve()),re=i.useRef(0),f=i.useRef(0);i.useEffect(()=>{const s=++f.current;let l=!0;return p.current=[],u.current=null,b.current=null,B.current=Promise.resolve(),v("loading"),C("/api/settings",void 0,t).then(o=>{if(!l||s!==f.current)return;const c=O(o);u.current=c,b.current=c,k(c),v("saved")}).catch(o=>{!l||s!==f.current||(T(o instanceof Error?o.message:String(o)),u.current=x,b.current=x,k(x),v("failed"))}),()=>{l=!1}},[t]);const ce=async(s,l,o)=>{const c={id:++re.current,section:s,key:l,value:o},H=f.current;p.current.push(c);const X=_(b.current||u.current||x,c);b.current=X,k(X),v("saving"),T(""),B.current=B.current.then(async()=>{if(H!==f.current)return;let S=null,y=null;for(let N=0;N<2&&!S;N+=1){const xe=u.current||x;try{const w=await C("/api/settings",{method:"PATCH",body:JSON.stringify({revision:xe.revision,[c.section]:{[c.key]:c.value}})},t);S=O(w)}catch(w){if(y=w,N!==0||!String(w instanceof Error?w.message:w).startsWith("409 "))break;try{const W=await C("/api/settings",void 0,t);if(H!==f.current)return;u.current=O(W)}catch(W){y=W;break}}}if(H!==f.current)return;p.current=p.current.filter(N=>N.id!==c.id),S&&(u.current=S);const fe=u.current||x,Y=p.current.reduce(_,fe);b.current=Y,k(Y),S?(T(""),v(p.current.length>0?"saving":"saved")):(v(p.current.length>0?"saving":"failed"),T(y instanceof Error?y.message:String(y||"Settings could not be saved.")))}),await B.current},h=(s,l)=>o=>{ce(s,l,o)},ae=async()=>{if(d!=="hub"||!m||!a){E("failed"),z("Sign in to this Hub before changing its runtime role.");return}E("changing"),z("");try{const s=await C("/api/runtime/status",void 0,t);await C("/api/runtime/role",{method:"POST",headers:{Authorization:`Bearer ${a}`},body:JSON.stringify({role:"client"})},t),E("accepted"),await Se({baseUrl:t,targetRole:"client",previousRuntimePid:Number(s.runtimePid||0),allowedStates:["running","waiting-auth"]}),ye(5179)}catch(s){E("failed"),z(s instanceof Error?s.message:String(s))}},le=A(j,"security"),V=A(j,"control"),P=A(j,"filesAudio"),I=A(j,"connection"),de=`settings-panel-${r}`,ue=n?Z.filter(s=>s.id!=="connection"):Z;i.useEffect(()=>{n&&r==="connection"&&q("remote-access")},[r,n]),i.useEffect(()=>{j&&J?.(!!I.showThisComputer)},[I.showThisComputer,J,j]);const he=e.jsxs("div",{className:"settings-tab-content product-settings-content",children:[te,ie,F&&e.jsxs("section",{className:"settings-section-card",children:[e.jsxs("div",{className:"settings-section-heading",children:[e.jsxs("div",{children:[e.jsx("span",{children:"Hub computer list"}),e.jsx("h3",{children:"This computer"})]}),e.jsx(M,{size:20})]}),e.jsx(g,{icon:M,title:"Show this computer",description:"Show this Hub computer in its own Wall and computer lists. It stays available from other computers and the mobile app when hidden.",children:e.jsx(R,{checked:!!I.showThisComputer,onChange:h("connection","showThisComputer"),label:"Show this computer"})})]}),e.jsxs("section",{className:"settings-section-card runtime-role-settings",children:[e.jsxs("div",{className:"settings-section-heading",children:[e.jsxs("div",{children:[e.jsx("span",{children:"Runtime role"}),e.jsx("h3",{children:"Use this computer as a Client"})]}),e.jsx(be,{size:20})]}),e.jsx("p",{className:"settings-help",children:"Stop hosting from this computer and reconnect it to the selected Hub."}),K==="accepted"?e.jsx("p",{className:"settings-help runtime-role-success",children:"VuvoDesk is restarting as Client."}):L?e.jsx("p",{className:"settings-help runtime-role-error",role:"alert",children:L}):null,e.jsx("button",{className:"settings-reset",onClick:()=>{ae()},disabled:K==="changing"||d!=="hub",type:"button",children:K==="changing"?"Switching role...":"Switch this computer to Client"})]})]}),ge=e.jsxs("div",{className:"settings-tab-content product-settings-content",children:[e.jsxs("section",{className:"settings-section-card",children:[e.jsxs("div",{className:"settings-section-heading",children:[e.jsxs("div",{children:[e.jsx("span",{children:"Remote access"}),e.jsx("h3",{children:"Who may connect?"})]}),e.jsx(we,{size:20})]}),e.jsx(g,{icon:ee,title:"Access mode",description:"Choose the default permission boundary for remote sessions.",recommended:!0,children:e.jsx(U,{value:String(le.accessMode),onChange:h("security","accessMode"),label:"Access mode",options:[["trusted-only","Trusted devices only"],["block-remote-access","Block remote access"]]})})]}),e.jsxs("section",{className:"settings-section-card",children:[e.jsxs("div",{className:"settings-section-heading",children:[e.jsxs("div",{children:[e.jsx("span",{children:"Session permissions"}),e.jsx("h3",{children:"What may remote users do?"})]}),e.jsx(M,{size:20})]}),e.jsx(g,{icon:M,title:"Keyboard and mouse control",description:"Allow Control to send keyboard and pointer input.",recommended:!0,children:e.jsx(R,{checked:!!V.allowKeyboardMouse,onChange:h("control","allowKeyboardMouse"),label:"Keyboard and mouse control"})}),e.jsx(g,{icon:Re,title:"Power actions",description:"Allow confirmed sleep, restart, and shut down commands from the Hub.",children:e.jsx(R,{checked:!!V.allowRemoteRestart,onChange:h("control","allowRemoteRestart"),label:"Power actions"})}),e.jsx(g,{icon:D,title:"File transfer",description:"Allow files to be delivered to connected computers.",children:e.jsx(R,{checked:!!P.allowFileTransfer,onChange:h("filesAudio","allowFileTransfer"),label:"File transfer"})}),e.jsx(g,{icon:$,title:"Remote audio",description:"Allow sound capture from connected computers.",children:e.jsx(R,{checked:!!P.allowRemoteAudio,onChange:h("filesAudio","allowRemoteAudio"),label:"Remote audio"})})]})]}),me=e.jsxs("div",{className:"settings-tab-content product-settings-content",children:[e.jsxs("section",{className:"settings-section-card",children:[e.jsxs("div",{className:"settings-section-heading",children:[e.jsxs("div",{children:[e.jsx("span",{children:"Capture"}),e.jsx("h3",{children:"Recording defaults"})]}),e.jsx(D,{size:20})]}),e.jsx(g,{icon:$,title:"Keep a Last 30s buffer",description:"Keep recent video in memory until you explicitly save it.",children:e.jsx(R,{checked:!!P.rollingBufferEnabled,onChange:h("filesAudio","rollingBufferEnabled"),label:"Keep a Last 30s buffer"})}),e.jsx(g,{icon:$,title:"Timelapse interval",description:"Choose how often a timelapse frame is captured.",children:e.jsx(U,{value:Number(P.timelapseIntervalSeconds),onChange:s=>h("filesAudio","timelapseIntervalSeconds")(Number(s)),label:"Timelapse interval",options:[["5","5 seconds"],["10","10 seconds"],["30","30 seconds"],["60","60 seconds"]]})})]}),ne]}),pe=r==="connection"?he:r==="remote-access"?ge:r==="capture-audio"?me:se;return e.jsxs("section",{className:"settings-page",children:[e.jsx("div",{className:"settings-page-tabs",role:"tablist","aria-label":"VuvoDesk settings",children:ue.map(({id:s,label:l,icon:o})=>e.jsxs("button",{className:r===s?"active":"",id:`settings-tab-${s}`,role:"tab","aria-selected":r===s,"aria-controls":`settings-panel-${s}`,tabIndex:r===s?0:-1,onClick:()=>q(s),type:"button",children:[e.jsx(o,{size:16}),l]},s))}),oe==="saving"&&e.jsx("div",{className:"product-save-state",role:"status",children:"Saving settings..."}),G&&e.jsx("div",{className:"agent-settings-alert error",role:"alert",children:G}),e.jsx("section",{className:"settings-page-panel",id:de,role:"tabpanel","aria-labelledby":`settings-tab-${r}`,tabIndex:0,children:pe})]})}export{Te as SettingsPage};
|