livedesk 0.1.697 → 0.1.700
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/README.md +21 -3
- package/bin/livedesk.js +16 -8
- package/client/package.json +5 -5
- package/diagnostics/vuvodesk-linux-desktop.mjs +188 -0
- package/electron/entitlements.mac.plist +12 -12
- package/electron/recurring-update-owner.mjs +2 -2
- package/electron/update-manager.mjs +59 -16
- package/hub/src/plan-device-access.test.mjs +8 -8
- package/hub/src/server.js +1 -1
- package/package.json +7 -7
- package/web/dist/app.html +1 -1
- package/web/dist/app.webmanifest +1 -1
- package/web/dist/assets/{AgentSettingsTab-DRWDCG0o.js → AgentSettingsTab-CvKCM1zo.js} +1 -1
- package/web/dist/assets/{AgentsPage-BnF3p9G1.js → AgentsPage-C0yd93rX.js} +1 -1
- package/web/dist/assets/{CaptureGallery-8lr9Ct1i.js → CaptureGallery-CDp1NX62.js} +1 -1
- package/web/dist/assets/DesktopUpdatePanel-BaRZzRao.js +1 -0
- package/web/dist/assets/HubApp-BoHzIvar.js +182 -0
- package/web/dist/assets/HubApp-C-E5cpCr.css +1 -0
- package/web/dist/assets/{MonitorStackIcon-led0pnag.js → MonitorStackIcon-BLNbbRNY.js} +5 -5
- package/web/dist/assets/{SettingsPage-k202bRU1.js → SettingsPage-D-7mFs9n.js} +1 -1
- package/web/dist/assets/SettingsTabs-C_xNvq7v.js +1 -0
- package/web/dist/assets/{ShareFilesPage-DRW1qS1Z.js → ShareFilesPage-CKdD-FK5.js} +1 -1
- package/web/dist/assets/{SupportPage-DXkBQh_W.js → SupportPage-LJUVsA1x.js} +1 -1
- package/web/dist/assets/{VuvoDeskApp-BHcF72r3.js → VuvoDeskApp-nDShkdzM.js} +1 -1
- package/web/dist/assets/{app-DcrmhmnT.js → app-CUaudslO.js} +2 -2
- package/web/dist/assets/{client-D-D35ghV.js → client-DV0v4wud.js} +1 -1
- package/web/dist/assets/frame-lifecycle-CNz8ou2A.js +1 -0
- package/web/dist/assets/{icons-ChMazCZR.js → icons-BwhnWKHR.js} +1 -1
- package/web/dist/assets/main-DNiaJr76.js +2 -0
- package/web/dist/assets/{pwa-startup-BiuYh5eN.js → pwa-startup-C8kDd3Vd.js} +1 -1
- package/web/dist/assets/{react-CnkEM7Rb.js → react-Dm67yaJf.js} +1 -1
- package/web/dist/index.html +6 -6
- package/web/dist/sw.js +2 -2
- package/web/dist/vuvodesk-build-evidence.json +57 -57
- package/web/dist/assets/DesktopUpdatePanel-DopP2EeD.js +0 -1
- package/web/dist/assets/HubApp-CqNxUVJD.js +0 -182
- package/web/dist/assets/HubApp-DdHHVOM0.css +0 -1
- package/web/dist/assets/SettingsTabs-v57M-CCZ.js +0 -1
- package/web/dist/assets/frame-lifecycle-D91nchvm.js +0 -1
- package/web/dist/assets/main-BXBJt96-.js +0 -2
|
@@ -0,0 +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-developer-plan-notice{display:flex;align-items:center;gap:9px;padding:10px 12px;color:#4c1d95;border:1px solid #ddd6fe;border-radius:11px;background:#f5f3ff;font-size:11.5px;line-height:1.4}.account-developer-plan-notice svg{flex:0 0 auto}.account-developer-plan-notice strong{margin-right:4px}.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.developer{background:#6d28d9}.account-plan-action.developer:hover,.account-plan-action.developer:focus-visible{background:#4c1d95}.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}}.plan-limit-dialog{box-sizing:border-box;width:min(520px,calc(100vw - 28px));max-height:calc(100dvh - 28px);overflow:auto;margin:auto;padding:26px;border:1px solid #cbd5e1;border-radius:20px;background:#fff;color:#172033;box-shadow:0 24px 80px #0005;font-size:14px;line-height:1.55}.plan-limit-dialog::backdrop{background:#0f172a99}.plan-limit-heading{display:flex;justify-content:space-between;align-items:center;color:#536179;font-size:11px;font-weight:700;letter-spacing:.08em}.plan-limit-dialog h2{margin:8px 0 14px;font-size:24px;line-height:1.2}.plan-limit-dialog button{cursor:pointer;border:1px solid #cbd5e1;border-radius:9px;background:#fff;color:#172033;padding:10px 14px;font:inherit}.plan-limit-dialog button:focus-visible{outline:3px solid #2563eb;outline-offset:2px}.plan-limit-dialog .plan-limit-close{font-size:22px;line-height:1;padding:6px 10px}.plan-limit-counts{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin:22px 0;padding:14px 10px;border-radius:12px;background:#f1f5f9;text-align:center}.plan-limit-counts dt{color:#536179;font-size:12px}.plan-limit-counts dd{margin:4px 0 0;font-size:28px;font-weight:700}.plan-limit-counts div:last-child dd{color:#b45309}.plan-limit-note{color:#536179;font-size:12px}.plan-limit-actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:22px}.plan-limit-actions .primary{background:#2563eb;color:#fff;border-color:#2563eb}@media(max-width:400px){.plan-limit-dialog{padding:20px}.plan-limit-actions button{flex:1 1 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}.computer-stats-button{display:inline-flex;align-items:center;justify-content:center;gap:6px;width:auto;padding:0 10px;font-size:12px;font-weight:600}.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}}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import{j as A}from"./pwa-startup-
|
|
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
|
|
1
|
+
import{j as A}from"./pwa-startup-C8kDd3Vd.js";const W=15e3;function We(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 pe 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 Be(n,e,t){const i=We(e),r=new AbortController;let s=!1;const o=()=>{r.signal.aborted||r.abort(n?.reason)};n?.aborted?o():n?.addEventListener("abort",o,{once:!0});const a=setTimeout(()=>{s=!0,r.signal.aborted||r.abort(new pe(i))},i);try{return await t(r.signal)}catch(c){throw s?new pe(i):c}finally{clearTimeout(a),n?.removeEventListener("abort",o)}}function dn(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,Ue=12*1024*1024,M=24,O=oe-M,ye=1,He=2,ge=32,Z=4294967295,ee=Symbol("direct-console-wire-budget-reserve"),te=Object.freeze([76,68,67,87]),ke=Object.freeze({control:1,text:2,binary:3}),Fe=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 g(n,e=void 0){throw new B(n,e)}function ae(n,e){return n===void 0?{}:((!n||typeof n!="object"||Array.isArray(n))&&g(`${e}-options-invalid`),n)}function G(n,e,t,i){const r=Number(n);return(!Number.isInteger(r)||r<t||r>i)&&g(e),r}function Me(n){return n===void 0?k:G(n,"max-message-bytes-invalid",1,Z)}function qe(n,e){const t=n===void 0?e?"text":"binary":String(n);return Object.hasOwn(ke,t)||g("message-kind-invalid"),e&&t==="binary"&&g("binary-message-requires-bytes"),!e&&t!=="binary"&&g(`${t}-message-requires-text`),t}function Ge(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};g("message-payload-invalid")}function je(n){if(n instanceof Uint8Array)return n;if(n instanceof ArrayBuffer)return new Uint8Array(n);g("wire-chunk-type-invalid")}function $e(n,{kind:e,messageId:t,chunkIndex:i,chunkCount:r,totalLength:s}){n.set(te,0);const o=new DataView(n.buffer,n.byteOffset,M);o.setUint8(4,ye),o.setUint8(5,ke[e]),o.setUint16(6,0,!1),o.setUint32(8,t,!1),o.setUint32(12,i,!1),o.setUint32(16,r,!1),o.setUint32(20,s,!1)}function Ve(n,e){const t=je(n);(t.byteLength<M||t.byteLength>oe)&&g("wire-chunk-length-invalid");for(let u=0;u<te.length;u+=1)t[u]!==te[u]&&g("wire-magic-invalid");const i=new DataView(t.buffer,t.byteOffset,M);i.getUint8(4)!==ye&&g("wire-version-invalid");const r=Fe[i.getUint8(5)];r||g("wire-kind-invalid"),i.getUint16(6,!1)!==0&&g("wire-reserved-invalid");const s=i.getUint32(8,!1),o=i.getUint32(12,!1),a=i.getUint32(16,!1),c=i.getUint32(20,!1);c>e&&g("message-too-large");const d=Math.max(1,Math.ceil(c/O));(a!==d||o>=a)&&g("wire-chunk-layout-invalid");const f=t.byteLength-M,l=o<a-1?O:c-o*O;return f!==l&&g("wire-chunk-layout-invalid"),{bytes:t,kind:r,messageId:s,chunkIndex:o,chunkCount:a,totalLength:c,payloadLength:f}}function Te(n=void 0){const e=ae(n,"budget"),t=e.maxBytes===void 0?Ue:G(e.maxBytes,"budget-max-bytes-invalid",1,Number.MAX_SAFE_INTEGER);let i=0,r=0;const s=()=>Object.freeze({maxBytes:t,retainedBytes:i,reservationCount:r}),o=a=>{const c=G(a,"budget-reservation-invalid",0,Number.MAX_SAFE_INTEGER);c>t-i&&g("shared-budget-overflow"),i+=c,r+=1;let d=!0;return Object.freeze({byteLength:c,release(){return d?(d=!1,i-=c,r-=1,(i<0||r<0)&&(i=0,r=0,g("shared-budget-underflow")),!0):!1}})};return Object.freeze({inspect:s,[ee]:o})}function ze(n,e=void 0){const t=ae(e,"encode"),i=G(t.messageId,"message-id-invalid",0,Z),r=Me(t.maxMessageBytes),s=Ge(n),o=qe(t.kind,s.isText),a=s.bytes.byteLength;(a>r||a>Z)&&g("message-too-large");const c=Math.max(1,Math.ceil(a/O)),d=new Array(c);for(let f=0;f<c;f+=1){const l=f*O,u=Math.min(O,a-l),m=new Uint8Array(M+u);$e(m,{kind:o,messageId:i,chunkIndex:f,chunkCount:c,totalLength:a}),u>0&&m.set(s.bytes.subarray(l,l+u),M),d[f]=m}return d}function me(n=void 0){const e=ae(n,"assembler"),t=Me(e.maxMessageBytes),i=e.maxPendingMessages===void 0?He:Number(e.maxPendingMessages);(!Number.isSafeInteger(i)||i<1||i>ge)&&g("max-pending-messages-invalid");const r=e.budget===void 0?Te():e.budget;(!r||typeof r[ee]!="function"||typeof r.inspect!="function")&&g("shared-budget-invalid");const s=new Map,o=new Map;let a=!1;const c=()=>{for(const b of s.values())b.reservation.release();s.clear()},d=()=>{o.clear()},f=()=>{let b=0;for(const C of s.values())b+=C.totalLength;let h=0;for(const C of o.values())h+=C.remainingChunks;return Object.freeze({disposed:a,maxMessageBytes:t,maxPendingMessages:i,pendingMessages:s.size,pendingBytes:b,abandonedMessages:o.size,abandonedChunksRemaining:h,budget:r.inspect()})},l=()=>(a||(a=!0,c(),d()),f()),u=b=>{throw a=!0,c(),d(),b instanceof B?b:new B("wire-chunk-malformed")};return Object.freeze({abandonPending:()=>{a&&g("assembler-disposed");for(const[b,h]of s.entries()){if(o.size>=ge){const C=o.keys().next().value;o.delete(C)}o.set(b,{kind:h.kind,chunkCount:h.chunkCount,totalLength:h.totalLength,receivedChunks:new Uint8Array(h.receivedChunks),remainingChunks:Math.max(0,h.chunkCount-h.receivedChunkCount)}),h.reservation.release()}return s.clear(),f()},dispose:l,inspect:f,push:b=>{a&&g("assembler-disposed");try{const h=Ve(b,t),C=o.get(h.messageId);if(C)return(C.kind!==h.kind||C.chunkCount!==h.chunkCount||C.totalLength!==h.totalLength)&&g("wire-message-metadata-mismatch"),C.receivedChunks[h.chunkIndex]===0&&(C.receivedChunks[h.chunkIndex]=1,C.remainingChunks-=1),C.remainingChunks<=0&&o.delete(h.messageId),null;let w=s.get(h.messageId);if(w)(w.kind!==h.kind||w.chunkCount!==h.chunkCount||w.totalLength!==h.totalLength)&&g("wire-message-metadata-mismatch");else{s.size>=i&&g("pending-message-limit");const he=r[ee](h.totalLength);let fe;try{fe=new Uint8Array(h.totalLength)}catch{he.release(),g("message-allocation-failed")}w={kind:h.kind,chunkCount:h.chunkCount,totalLength:h.totalLength,receivedChunks:new Uint8Array(h.chunkCount),receivedChunkCount:0,receivedBytes:0,buffer:fe,reservation:he},s.set(h.messageId,w)}w.receivedChunks[h.chunkIndex]!==0&&g("duplicate-wire-chunk");const L=h.chunkIndex*O,xe=L+h.payloadLength;if((L<0||xe>w.totalLength)&&g("wire-chunk-overlap"),h.payloadLength>0&&w.buffer.set(h.bytes.subarray(M),L),w.receivedChunks[h.chunkIndex]=1,w.receivedChunkCount+=1,w.receivedBytes+=h.payloadLength,w.receivedChunkCount<w.chunkCount)return null;w.receivedBytes!==w.totalLength&&g("wire-message-length-mismatch");let de;try{de=w.kind==="binary"?w.buffer:new TextDecoder("utf-8",{fatal:!0}).decode(w.buffer)}catch{g("wire-text-invalid")}finally{s.delete(h.messageId),w.reservation.release()}return Object.freeze({messageId:h.messageId,kind:w.kind,byteLength:w.totalLength,data:de})}catch(h){return u(h)}}})}const Xe="Direct connection signaling is unavailable. Try again.",Ye="Desktop Hub is offline.",Ke="A direct connection could not be established on this network.",Ae=750,Je=2e3,Qe=1500,Ze=3e3,et=512*1024,tt=64*1024;function nt(n){return n.replace(/^a=sctp-init:[^\r\n]*(?:\r?\n|$)/gm,"")}function we(n){const e=Math.max(0,Number(n)||0),t=Math.ceil(e/et*1e3);return Math.min(Je,Ae+t)}function it(n){const e=Math.max(0,Number(n)||0),t=Math.ceil(e/tt*1e3);return Math.max(Qe,Math.min(Ze,Ae+t))}const ne=Object.freeze({"signal-service-unavailable":Xe,"hub-unavailable":Ye,"p2p-unavailable":Ke});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 Y(){return ce("hub-unavailable")}function p(){return ce("p2p-unavailable")}function K(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 rt({userId:n,connectionId:e,hubEpoch:t,generation:i}){const r={userId:String(n||""),connectionId:String(e||""),hubEpoch:String(t||""),generation:Number(i)};if(!r.userId||!r.connectionId||!r.hubEpoch||!Number.isSafeInteger(r.generation)||r.generation<1)throw new Error("console-direct-owner-invalid");return Object.freeze(r)}function st(n,e){return!!n&&!!e&&n.userId===e.userId&&n.connectionId===e.connectionId&&n.hubEpoch===e.hubEpoch&&n.generation===e.generation}const Oe="https://livedesk-wake.lovecrdm.workers.dev",ot="stun:stun.cloudflare.com:3478",at="livedesk-console-signal-v2",ct="livedesk-auth.",lt="livedesk-control-v1",ut="livedesk-ws-v1:",dt=1e4,F=12e3,be=1e4,ht=5e3,ft=5e3,pt=15e3,gt=15e3,Ee=24,mt=16,Ce=32,wt=64,bt=64,Et=4*1024,Ct=1024*1024,St=new Set(["/api/remote/status","/api/remote/devices"]),Se=4*1024*1024,It=12*1024*1024,Ie=8*1024*1024+oe,Lt=8,vt=1,yt=2,kt=2,Mt=new Set(["rtc-offer","rtc-ice","rtc-close"]),Tt=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 At(n){const e=String(Oe).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 Ot(n){const e=String(Oe).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 Dt(n){const e=String(n?.accessToken||"").trim(),t=String(n?.user?.id||"").trim(),i=String(n?.workspaceId||"").trim(),r=String(n?.workspaceKind||"").trim().toLowerCase(),s=String(n?.workspaceRole||"").trim().toLowerCase(),o=Number(n?.membershipRevision||0);return e&&t&&N.test(i)&&["personal","team"].includes(r)&&["owner","operator"].includes(s)&&Number.isSafeInteger(o)&&o>=1&&(r!=="personal"||i===t)?{accessToken:e,user:{id:t},workspaceId:i,workspaceKind:r,workspaceRole:s,membershipRevision:o}:null}function Rt(){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:[ot]}function Pt(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 _t(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 Nt(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 xt(n){const e=new Headers(n?.headers||{}),t={};for(const i of["accept","content-type","if-match","range","x-livedesk-csrf"]){const r=e.get(i);r&&(t[i]=r)}return t}function _(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 q(n,e="console-direct-failed"){return n instanceof Error?n:new Error(String(n||e))}function re(n){if(n instanceof ArrayBuffer||n instanceof Uint8Array)return n;throw new B("wire-chunk-type-invalid")}function Wt(n){const e=re(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<Ee)return i;const r=new DataView(t.buffer,t.byteOffset,Ee);return{...i,headerReadable:t[0]===76&&t[1]===68&&t[2]===67&&t[3]===87,messageId:r.getUint32(8,!1),chunkIndex:r.getUint32(12,!1),chunkCount:r.getUint32(16,!1),totalLength:r.getUint32(20,!1)}}function Bt(n,e){return e?e.aborted?Promise.reject(e.reason||new Error("Mobile Console request cancelled.")):new Promise((t,i)=>{let r=!1;const s=a=>{r||(r=!0,e.removeEventListener("abort",o),a())},o=()=>s(()=>i(e.reason||new Error("Mobile Console request cancelled.")));e.addEventListener("abort",o,{once:!0}),n.then(a=>s(()=>t(a)),a=>s(()=>i(a)))}):n}class Ut extends EventTarget{constructor(e,t,i,r){super(),this.manager=e,this.channelId=t,this.purpose=i,this.url=r}manager;channelId;purpose;url;protocol="livedesk-ws-v1";extensions="";binaryType="blob";readyState=WebSocket.CONNECTING;onopen=null;onmessage=null;onerror=null;onclose=null;handoffConnectingOwner(e){if(this.readyState!==WebSocket.CONNECTING)throw new Error("media-handoff-after-open");this.manager=e}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 r=new CloseEvent("close",{code:ie(e,1006),reason:String(t||"").slice(0,120),wasClean:e===1e3});this.onclose?.call(this,r),this.dispatchEvent(r)}}class le{constructor(e=null){this.mediaParent=e}mediaParent;mediaPeers=new Map;mediaPeerVersion=0;recentMediaClosures=[];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=Dt(e),i=this.session?`${this.session.user.id}
|
|
3
3
|
${this.session.workspaceId}
|
|
4
4
|
${this.session.workspaceRole}`:"",r=t?`${t.user.id}
|
|
5
5
|
${t.workspaceId}
|
|
6
|
-
${t.workspaceRole}`:"";this.session=t,i!==r&&(this.teardown("console-session-replaced",null,!0),this.recentMediaClosures.length=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.mediaPeers.entries()].map(([l,u])=>({channelId:l,connectionId:u.peerOwner?.connectionId||null,generation:u.generation,stage:u.stage,directReady:u.directReady,peerCount:u.peer?1:0,controlChannels:u.controlChannel?1:0,logicalChannels:u.channels.size,openLogicalChannels:[...u.channels.values()].filter(m=>m.opened).length,resourceTimers:+(u.connectTimer!==null)+ +(u.peerDisconnectTimer!==null)+ +(u.controlWireDeadline!==null)+[...u.channels.values()].reduce((m,E)=>m+ +(E.openDeadline!==null)+ +(E.wireDeadline!==null),0),sendBufferedBytes:u.peerBufferedAmount(),partialMediaWireTimeoutCount:u.partialMediaWireTimeoutCount,logicalChannelFailureCount:u.logicalChannelFailureCount,lastPartialMediaWireTimeout:u.lastPartialMediaWireTimeout,lastLogicalChannelFailure:u.lastLogicalChannelFailure})),t=this.wireBudget?.inspect()||{retainedBytes:0,reservationCount:0},i=[this,...this.mediaPeers.values()],r=i.flatMap(l=>[...l.channels.values()]),s=r.filter(l=>l.wireDeadline!==null).length,o=r.filter(l=>l.openDeadline!==null).length,a=i.filter(l=>l.connectTimer!==null).length,c=i.filter(l=>l.peerDisconnectTimer!==null).length,d=i.filter(l=>l.controlWireDeadline!==null).length,f=this.workspaceReauthAttempt?.deadline==null?0:1;return Object.freeze({preferred:this.preferred,stage:this.stage,directReady:this.directReady,generation:this.generation,consoleId:this.consoleId||null,connectionId:this.peerOwner?.connectionId||null,signalSockets:this.signalSocket?1:0,mediaPeerVersion:this.mediaPeerVersion,mediaPeers:e,recentMediaClosures:this.recentMediaClosures.slice(),peerCount:+!!this.peer+e.reduce((l,u)=>l+u.peerCount,0),controlChannels:this.controlChannel?1:0,mediaControlChannels:e.reduce((l,u)=>l+u.controlChannels,0),logicalChannels:this.channels.size+e.reduce((l,u)=>l+u.logicalChannels,0),openLogicalChannels:[...this.channels.values()].filter(l=>l.opened).length+e.reduce((l,u)=>l+u.openLogicalChannels,0),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(l=>(l.purpose==="frame"||l.purpose==="atlas")&&l.owner===null&&l.dataChannel===null).length,pendingRemoteCandidates:this.pendingRemoteCandidates.length,pendingLocalCandidates:this.pendingLocalCandidates.length,connectTimers:a,peerDisconnectTimers:c,controlWireTimers:d,workspaceReauthTimers:f,logicalOpenTimers:o,logicalWireTimers:s,resourceTimers:a+c+d+f+o+s+this.pendingHttp.size,wireRetainedBytes:t.retainedBytes,wireReservations:t.reservationCount,sendBufferedBytes:this.peerBufferedAmount()+e.reduce((l,u)=>l+u.sendBufferedBytes,0),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 rt(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 r=window.setTimeout(()=>{this.peerDisconnectTimer===r&&(this.peerDisconnectTimer=null,!(!this.isPeerOwner(e)||this.peer!==t)&&(t.connectionState==="disconnected"||t.iceConnectionState==="disconnected")&&this.fail(p(),"peer-disconnected-timeout",!0))},dt);this.peerDisconnectTimer=r}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 r=window.setTimeout(()=>{this.controlWireDeadline===r&&(this.controlWireDeadline=null,!(!this.isPeerOwner(e)||this.controlAssembler!==t)&&(t.inspect().pendingMessages||0)>0&&this.fail(p(),"control-wire-assembly-timeout",!0))},ft);this.controlWireDeadline=r}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(!kt.has(String(e.type||"")))throw new Error("console-direct-signal-type-forbidden");if(this.mediaParent){const{manager:i,owner:r,channelId:s}=this.mediaParent;if(!i.isPeerOwner(r)||i.mediaPeers.get(s)!==this)throw new Error("console-direct-media-parent-stale");i.sendControl({type:"media-signal",connectionId:r.connectionId,hubEpoch:r.hubEpoch,mediaId:s,signal:e});return}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,r){if(e.readyState!=="open")throw new Error("console-direct-data-channel-not-open");const s=Ve(t,{messageId:this.nextMessageId(),kind:i,maxMessageBytes:r}),o=s.reduce((a,c)=>a+c.byteLength,0);if(o>Se||this.peerBufferedAmount()>Se-o)throw new Error("console-direct-send-buffer-full");for(const a of s)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=K(e),this.teardown(t,e,i)}teardown(e,t,i,r=!1){const s=this.signalSocket,o=this.peerOwner;if(i&&(this.mediaParent||s?.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{}for(const l of[...this.mediaPeers.values()])l.teardown(e,t,!1);if(this.mediaPeers.clear(),this.mediaParent?.manager.mediaPeers.get(this.mediaParent.channelId)===this){const l=this.mediaParent.manager.recentMediaClosures;l.push({channelId:this.mediaParent.channelId,generation:this.generation,reason:String(e).slice(0,120),occurredAt:Date.now(),logicalFailure:this.lastLogicalChannelFailure}),l.length>8&&l.shift(),this.mediaParent.manager.mediaPeers.delete(this.mediaParent.channelId)}this.mediaPeerVersion=0,r?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[l,u]of this.pendingHttp)window.clearTimeout(u.timeout),u.detachAbort(),u.reject(a),this.pendingHttp.delete(l);for(const l of[...this.channels.values()])this.retireLogicalEntry(l,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 d=this.peer;if(this.peer=null,d){d.onicecandidate=null,d.onconnectionstatechange=null,d.oniceconnectionstatechange=null;try{d.close()}catch{}}if(!r)try{s?.close(1e3,String(e||"console-direct-closed").slice(0,120))}catch{}const f=this.wireBudget?.inspect();this.lastTerminalWireBytes=Number(f?.retainedBytes||0),this.lastTerminalWireReservations=Number(f?.reservationCount||0),this.wireBudget=null}async connect(){if(this.directReady&&this.peerOwner&&this.controlChannel?.readyState==="open")return;if(this.connectPromise)return this.connectPromise;if(this.mediaParent)return this.connectMediaPeer();const e=this.session;if(!e)throw S();const t=this.signalSocket?.readyState===WebSocket.OPEN&&this.signalReady;if(t&&this.stage==="hub-offline"){const s=Y();throw this.lastFailure=K(s),s}if(t&&this.stage==="p2p"&&this.peerOwner&&this.peer){const s=this.generation,o=new Promise((a,c)=>{this.resolveConnect=a,this.rejectConnect=c});return this.connectPromise=o,this.connectTimer===null&&(this.connectTimer=window.setTimeout(()=>{s===this.generation&&!this.directReady&&this.fail(p(),"direct-ready-timeout",!0)},F)),o}const i=this.generation+1;this.generation=i,this.stage="signal",this.lastFailure=null;const r=new Promise((s,o)=>{this.resolveConnect=s,this.rejectConnect=o});this.connectPromise=r,this.connectTimer=window.setTimeout(()=>{if(i!==this.generation)return;const s=this.stage==="signal"?S():p();this.fail(s,this.stage==="signal"?"signal-timeout":"direct-ready-timeout",!1)},this.stage==="signal"?ut:F);try{const s=new WebSocket(Tt(e.workspaceId),[ot,`${at}${e.accessToken}`]);this.signalSocket=s,s.addEventListener("message",o=>{if(!this.isSignalOwner(i,s)||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,s)}),s.addEventListener("error",()=>{this.isSignalOwner(i,s)&&(this.detachSignalFromReadyPeer(i,s,"signal-detached-after-ready")||this.fail(S(),"signal-service-unavailable",!1))}),s.addEventListener("close",()=>{this.isSignalOwner(i,s)&&(this.detachSignalFromReadyPeer(i,s,"signal-closed-after-ready")||this.fail(S(),"signal-service-closed",!1))})}catch{this.fail(S(),"signal-constructor-failed",!1)}return r}connectMediaPeer(){const e=this.mediaParent;if(!e.manager.isPeerOwner(e.owner)||!e.manager.hasReadyPayloadPeer()||e.manager.mediaPeers.get(e.channelId)!==this)return Promise.reject(new Error("console-direct-media-parent-stale"));this.session=e.manager.session,this.consoleId=e.channelId,this.hubEpoch=e.owner.hubEpoch,this.stage="p2p";const t=++this.generation,i=new Promise((r,s)=>{this.resolveConnect=r,this.rejectConnect=s});return this.connectPromise=i,this.connectTimer=window.setTimeout(()=>{t===this.generation&&!this.directReady&&this.fail(p(),"media-direct-ready-timeout",!0)},F),this.beginPeer(t,e.owner.hubEpoch),i}handleMediaSignal(e,t){if(this.mediaParent||t.connectionId!==e.connectionId||t.hubEpoch!==e.hubEpoch)return;const i=this.mediaPeers.get(String(t.mediaId||"")),r=t.signal,s=i?.peerOwner;!i||!s||!r||i.mediaParent?.owner!==e||r.connectionId!==s.connectionId||r.hubEpoch!==s.hubEpoch||(r.type==="rtc-answer"?i.acceptAnswer(s,r.description):r.type==="rtc-ice"?i.acceptRemoteCandidate(s,r.candidate,r.sdpMid):r.type==="rtc-close"&&i.fail(p(),String(r.reason||"media-peer-closed").slice(0,120),!1))}handleSignal(e,t,i){if(!this.isSignalOwner(t,i))return;if(e.type==="workspace-reauth-required"){const s=this.session,o=String(e.workspaceId||s?.workspaceId||"").trim(),a=String(e.challengeNonce||"").trim();if(!s||o!==s.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,d={challengeNonce:a,generation:t,socket:i,controller:c,deadline:null},f=Number(e.deadlineAt||0),l=Number.isFinite(f)&&f>0?Math.max(1,f-Date.now()):be;d.deadline=window.setTimeout(()=>{this.workspaceReauthAttempt===d&&this.cancelWorkspaceReauthAttempt(t,i)},Math.max(1,Math.min(be,l))),this.workspaceReauthAttempt=d,(async()=>{try{await fetch(At("/v2/rtc/reauth"),{method:"POST",headers:{Authorization:`Bearer ${s.accessToken}`,"Content-Type":"application/json"},body:JSON.stringify({workspaceId:s.workspaceId,challengeNonce:a}),signal:c.signal,cache:"no-store"})}catch{}})().finally(()=>{this.workspaceReauthAttempt===d&&(this.workspaceReauthAttempt=null,d.deadline!==null&&(window.clearTimeout(d.deadline),d.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 s=String(e.consoleId||""),o=String(e.hubEpoch||"");if(e.role!=="console"||!N.test(s)){this.fail(S(),"invalid-signal-ready",!1);return}if(this.signalReady=!0,this.consoleId=s,e.hubOnline!==!0){const a=Y();this.lastFailure=K(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)},F),this.beginPeer(t,o);return}const r=this.peerOwner;if(!(!r||String(e.connectionId||"")!==r.connectionId||String(e.hubEpoch||"")!==r.hubEpoch)){if(e.type==="rtc-answer")this.acceptAnswer(r,e.description);else if(e.type==="rtc-ice")this.acceptRemoteCandidate(r,e.candidate,e.sdpMid);else if(e.type==="rtc-close"){const s=String(e.reason||"rtc-closed"),o=/hub-offline/i.test(s)?Y():p();this.fail(o,s,!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 r=it({userId:i.user.id,connectionId:crypto.randomUUID(),hubEpoch:t,generation:e});this.consecutiveMediaLogicalOpenFailures=0,this.peerOwner=r,this.wireBudget=this.mediaParent?.manager.wireBudget||Me({maxBytes:St}),this.controlAssembler=me({budget:this.wireBudget,maxMessageBytes:k});let s;try{s=new RTCPeerConnection({iceServers:[{urls:Dt()}],iceTransportPolicy:"all",bundlePolicy:"max-bundle",rtcpMuxPolicy:"require"})}catch{this.fail(p(),"peer-constructor-failed",!0);return}this.peer=s;const o=s.createDataChannel(ct,{ordered:!0});o.binaryType="arraybuffer",this.controlChannel=o,s.onicecandidate=a=>{if(!this.isPeerOwner(r)||this.peer!==s||!a.candidate)return;const c=String(a.candidate.candidate||"");if(_(c)){this.fail(p(),"relay-ice-candidate-forbidden",!0);return}if(new TextEncoder().encode(c).byteLength>bt){this.fail(p(),"local-ice-candidate-invalid",!0);return}if(!this.localOfferSent){if(this.pendingLocalCandidates.length>=wt){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:r.connectionId,hubEpoch:r.hubEpoch,candidate:c,sdpMid:a.candidate.sdpMid})}catch{this.fail(S(),"signal-ice-failed",!1)}},s.onconnectionstatechange=()=>{if(!(!this.isPeerOwner(r)||this.peer!==s)){if(s.connectionState==="failed"||s.connectionState==="closed"){this.fail(p(),`peer-${s.connectionState}`,!0);return}this.refreshPeerDisconnectDeadline(r,s)}},s.oniceconnectionstatechange=()=>{if(!(!this.isPeerOwner(r)||this.peer!==s)){if(s.iceConnectionState==="failed"||s.iceConnectionState==="closed"){this.fail(p(),`ice-${s.iceConnectionState}`,!0);return}this.refreshPeerDisconnectDeadline(r,s)}},o.onmessage=a=>{!this.isPeerOwner(r)||this.controlChannel!==o||this.handleControlWire(r,a.data)},o.onerror=()=>{!this.isPeerOwner(r)||this.controlChannel!==o||this.fail(p(),"control-channel-error",!0)},o.onclose=()=>{!this.isPeerOwner(r)||this.controlChannel!==o||this.fail(p(),"control-channel-closed",!0)},(async()=>{try{const a=await s.createOffer();if(!this.isPeerOwner(r)||this.peer!==s)return;if(a.type!=="offer"||_(a.sdp))throw new Error("relay-sdp-forbidden");if(await s.setLocalDescription(a),!this.isPeerOwner(r)||this.peer!==s)return;const c=s.localDescription||a;if(c.type!=="offer"||_(c.sdp))throw new Error("relay-sdp-forbidden");this.signal({type:"rtc-offer",connectionId:r.connectionId,hubEpoch:r.hubEpoch,description:{type:"offer",sdp:tt(c.sdp||"")}}),this.localOfferSent=!0;const d=this.pendingLocalCandidates;this.pendingLocalCandidates=[];for(const f of d){if(!this.isPeerOwner(r)||this.peer!==s)return;this.signal({type:"rtc-ice",connectionId:r.connectionId,hubEpoch:r.hubEpoch,...f})}}catch(a){if(!this.isPeerOwner(r))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"||_(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 r=this.pendingRemoteCandidates;this.pendingRemoteCandidates=[];for(const s of r){if(!this.isPeerOwner(e)||this.peer!==i)return;await i.addIceCandidate(s.candidate?s:null)}}catch{this.isPeerOwner(e)&&this.fail(p(),"rtc-answer-apply-failed",!0)}}}async acceptRemoteCandidate(e,t,i){if(!this.isPeerOwner(e))return;const r=String(t??""),s=i==null?null:String(i);if(r.length>4*1024||s!==null&&s.length>256||_(r)){this.fail(p(),"rtc-candidate-invalid",!0);return}const o=this.peer;if(o){if(!this.remoteDescriptionApplied){if(this.pendingRemoteCandidates.length>=mt){this.fail(p(),"rtc-candidate-capacity",!0);return}this.pendingRemoteCandidates.push({candidate:r,sdpMid:s});return}try{await o.addIceCandidate(r?{candidate:r,sdpMid:s}: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 r=i.push(re(t));if(this.refreshControlWireDeadline(e,i),!r)return;if(r.kind!=="control"||typeof r.data!="string")throw new Error("control-wire-kind-invalid");const s=JSON.parse(r.data);if(s.type==="direct-ready"){if(s.connectionId!==e.connectionId||s.hubEpoch!==e.hubEpoch||this.controlChannel?.readyState!=="open")throw new Error("direct-ready-owner-invalid");this.directReady||(this.mediaPeerVersion=!this.mediaParent&&s.mediaPeerVersion===1?1:0,this.consecutiveLivenessRequestTimeouts=0,this.directReady=!0,this.stage="ready",this.resolveCurrentConnect());return}if(s.type==="media-signal"){this.handleMediaSignal(e,s);return}if(s.type==="http-response"){this.handleHttpResponse(e,s);return}if(s.type==="ws-opened"||s.type==="ws-closed"||s.type==="ws-error"){this.handleLogicalLifecycle(e,s);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 r=this.channels.get(i);if(!r)return;const s=r.dataChannel;if(!s||!r.openRequested||!this.logicalEntryIsCurrent(r,e,s))throw new Error("logical-lifecycle-owner-invalid");if(t.type==="ws-opened"){if(r.opened)return;r.opened=!0,(r.purpose==="frame"||r.purpose==="atlas")&&(this.consecutiveMediaLogicalOpenFailures=0),this.clearLogicalOpenDeadline(r);const o=r.pendingInbound.splice(0);if(r.pendingInboundBytes=0,r.socket.managerOpened(),!this.logicalEntryIsCurrent(r,e,s)||!r.opened)return;for(const a of o)this.deliverLogicalMessage(r,a);return}if(t.type==="ws-closed"){this.retireLogicalEntry(r,ie(t.code,1e3),String(t.reason||""),!1,!1);return}this.retireLogicalEntry(r,1011,String(t.error||"console-direct-websocket-error"),!0,!1)}handleHttpResponse(e,t){const i=String(t.requestId||""),r=this.pendingHttp.get(i);if(!r||r.generation!==e.generation||!this.isPeerOwner(e))return;this.consecutiveLivenessRequestTimeouts=0,this.livenessMediaRecoveryGeneration=0;const s=this.mediaAttachmentHoldGeneration===e.generation;this.pendingHttp.delete(i),window.clearTimeout(r.timeout),r.detachAbort();try{const o=Number(t.status||502),a=t.bodyBase64?Pt(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"}});r.resolve(c),s&&(this.mediaAttachmentHoldGeneration=0,this.attachHeldMediaChannels(e))}catch(o){r.reject(q(o))}}async fetch(e,t,i){await Wt(this.connect(),t?.signal);const r=this.peerOwner;if(!r||!this.directReady||this.controlChannel?.readyState!=="open")throw p();if(this.pendingHttp.size>=Ce)throw new Error("console-direct-http-capacity-reached");const s=await _t(t?.body);if(s.byteLength>Et)throw new Error("console-direct-http-body-too-large");if(!this.isPeerOwner(r)||!this.directReady)throw p();if(this.pendingHttp.size>=Ce)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(),d=c==="GET"&&Ct.has(e),f=d?this.livenessEvidenceEpoch:null,l=new Promise((u,m)=>{const E=(C,w=!1)=>{const L=this.pendingHttp.get(o);if(L){this.pendingHttp.delete(o),window.clearTimeout(L.timeout),L.detachAbort();try{this.sendControl({type:"http-cancel",requestId:o})}catch{}m(C),w&&d&&this.recordLivenessRequestTimeout(r,L.livenessEvidenceEpoch)}},b=()=>E(t?.signal?.reason instanceof Error?t.signal.reason:new Error("Mobile Console request cancelled."));t?.signal?.addEventListener("abort",b,{once:!0});const h=window.setTimeout(()=>{E(new Error("Mobile Console direct request timed out."),!0)},a);this.pendingHttp.set(o,{generation:r.generation,livenessEvidenceEpoch:f,resolve:u,reject:m,timeout:h,detachAbort:()=>t?.signal?.removeEventListener("abort",b)})});try{this.sendControl({type:"http-request",requestId:o,method:c,path:e,headers:Nt(t),bodyBase64:s.byteLength>0?Rt(s):""})}catch(u){const m=this.pendingHttp.get(o);m&&(this.pendingHttp.delete(o),window.clearTimeout(m.timeout),m.detachAbort(),m.reject(q(u))),this.fail(p(),"control-send-failed",!0)}return l}openWebSocket(e,t){if(!Mt.has(t))throw new Error("console-direct-purpose-invalid");if(this.channels.size+this.mediaPeers.size>=gt)throw new Error("console-direct-channel-capacity-reached");const i=crypto.randomUUID(),r=new Bt(this,i,t,e),s={channelId:i,path:e,purpose:t,socket:r,owner:null,dataChannel:null,assembler:null,openDeadline:null,wireDeadline:null,wireScheduledAtEpochMs:0,wireStartedAtEpochMs:0,wireLastProgressAtEpochMs:0,wireAbsoluteDeadlineAtEpochMs:0,openRequested:!1,opened:!1,pendingInbound:[],pendingInboundBytes:0};return this.channels.set(i,s),this.connect().then(()=>{if(this.channels.get(i)===s){if(!this.mediaParent&&this.mediaPeerVersion===1&&this.peerOwner&&(t==="frame"||t==="atlas")){const o=new le({manager:this,owner:this.peerOwner,channelId:i});this.channels.delete(i),this.mediaPeers.set(i,o),o.channels.set(i,s),r.handoffConnectingOwner(o),o.connect().then(()=>{o.channels.get(i)===s&&o.attachLogicalChannel(s)}).catch(a=>{o.retireLogicalEntry(s,1011,q(a).message,!0,!1)});return}this.attachLogicalChannel(s)}}).catch(o=>{this.channels.get(i)===s&&this.retireLogicalEntry(s,1011,q(o).message,!0,!1)}),r}attachLogicalChannel(e){const t=this.peerOwner,i=this.peer,r=this.wireBudget;if(!t||!i||!r||!this.directReady||this.channels.get(e.channelId)!==e){this.retireLogicalEntry(e,1011,"console-direct-not-ready",!0,!1);return}const s=e.purpose==="frame"||e.purpose==="atlas";if(s&&this.mediaAttachmentHoldGeneration===t.generation)return;e.owner=t;let o;try{o=i.createDataChannel(`${lt}${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=me({budget:r,maxMessageBytes:s?Ie:k,maxPendingMessages:s?It: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,r,s,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(r||"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(f=>f!==e&&f.opened&&(f.purpose==="frame"||f.purpose==="atlas")&&f.dataChannel?.readyState==="open"),d=a&&!c&&(o||this.consecutiveMediaLogicalOpenFailures>=yt);this.retireLogicalEntry(e,i,r,s,!1),d&&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 r=window.setTimeout(()=>{e.openDeadline===r&&(e.openDeadline=null,!(!this.logicalEntryIsCurrent(e,t,i)||e.opened)&&this.retireLogicalOpenFailure(e,t,1011,"console-direct-logical-open-timeout",!0,!1))},ht);e.openDeadline=r}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 r=e.assembler;if(!r||!this.logicalEntryIsCurrent(e,t,e.dataChannel))return;const s=r.inspect();let o={chunkBytes:0,headerReadable:!1,messageId:0,chunkIndex:0,chunkCount:0,totalLength:0};try{o=xt(i);const a=r.push(re(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(s.pendingMessages||0)),pendingBytesBefore:Math.max(0,Number(s.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",r=i?Ie:k;if(i){if(e.pendingInbound.length===0){e.pendingInbound.push(t),e.pendingInboundBytes=t.byteLength;return}if(e.pendingInbound.length<vt&&e.pendingInboundBytes+t.byteLength<=r){e.pendingInbound.push(t),e.pendingInboundBytes+=t.byteLength;return}const s=e.pendingInbound[0],o=s.byteLength+t.byteLength,a=o<=r?"replace-latest":"drop-over-budget";a==="replace-latest"&&(e.pendingInbound=[s,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>=Lt||e.pendingInboundBytes+t.byteLength>r)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;if(e.socket.binaryType==="arraybuffer"){const r=i.buffer instanceof ArrayBuffer&&i.byteOffset===0&&i.byteLength===i.buffer.byteLength?i.buffer:i.slice().buffer;e.socket.managerMessage(r)}else e.socket.managerMessage(new Blob([i]))}logicalBufferedAmount(e){return Number(this.channels.get(e)?.dataChannel?.bufferedAmount||0)}clearLogicalWireDeadline(e){e.wireDeadline!==null&&(window.clearTimeout(e.wireDeadline),e.wireDeadline=null),e.wireScheduledAtEpochMs=0,e.wireStartedAtEpochMs=0,e.wireLastProgressAtEpochMs=0,e.wireAbsoluteDeadlineAtEpochMs=0}scheduleLogicalWireDeadline(e,t){const i=e.purpose==="frame"||e.purpose==="atlas",r=Date.now(),s=e.assembler?.inspect(),o=i?we(Number(s?.pendingBytes||0)):Number.POSITIVE_INFINITY,a=i?Math.max(1,o-(r-e.wireLastProgressAtEpochMs)):Number.POSITIVE_INFINITY,c=Math.max(1,e.wireAbsoluteDeadlineAtEpochMs-r),d=Math.min(a,c),f=r+d;if(e.wireDeadline!==null&&e.wireScheduledAtEpochMs<=f)return;e.wireDeadline!==null&&window.clearTimeout(e.wireDeadline);const l=window.setTimeout(()=>{if(e.wireDeadline!==l)return;e.wireDeadline=null,e.wireScheduledAtEpochMs=0;const u=e.dataChannel;if(!u||!this.logicalEntryIsCurrent(e,t,u))return;const m=e.assembler?.inspect(),E=Number(m?.pendingMessages||0);if(E===0){this.clearLogicalWireDeadline(e);return}const b=Date.now(),h=Math.max(0,b-e.wireLastProgressAtEpochMs),C=Math.max(0,b-e.wireStartedAtEpochMs),w=i?we(Number(m?.pendingBytes||0)):Number.POSITIVE_INFINITY;if(!(!i||h>=w||b>=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:E,pendingBytes:Math.max(0,Number(m?.pendingBytes||0)),stalledForMs:h,lifetimeMs:C,idleDeadlineMs:w,absoluteDeadlineMs:Math.max(0,e.wireAbsoluteDeadlineAtEpochMs-e.wireStartedAtEpochMs),occurredAt:b}),e.assembler?.abandonPending(),this.clearLogicalWireDeadline(e);return}this.retireLogicalEntry(e,1011,"console-direct-partial-message-timeout",!0,!1)},d);e.wireDeadline=l,e.wireScheduledAtEpochMs=f}refreshLogicalWireDeadline(e,t){const i=e.assembler?.inspect();if(Number(i?.pendingMessages||0)===0){this.clearLogicalWireDeadline(e);return}const s=Date.now(),o=e.purpose==="frame"||e.purpose==="atlas";e.wireStartedAtEpochMs<=0&&(e.wireStartedAtEpochMs=s,e.wireAbsoluteDeadlineAtEpochMs=s+(o?nt(Number(i?.pendingBytes||0)):pt)),e.wireLastProgressAtEpochMs=s,this.scheduleLogicalWireDeadline(e,t)}sendLogicalMessage(e,t){const i=this.channels.get(e),r=i?.dataChannel;if(!i||!r||!i.opened||r.readyState!=="open")throw new DOMException("WebSocket is not open.","InvalidStateError");try{if(typeof t=="string")this.sendWire(r,t,"text",k);else if(t instanceof ArrayBuffer)this.sendWire(r,t,"binary",k);else if(ArrayBuffer.isView(t)){const s=new Uint8Array(t.buffer,t.byteOffset,t.byteLength);this.sendWire(r,s,"binary",k)}else throw new DOMException("Blob sends are not supported by the direct Console channel.","NotSupportedError")}catch(s){throw this.retireLogicalEntry(i,1011,"console-direct-send-failed",!0,!1),s}}closeLogicalChannel(e,t,i,r){const s=this.channels.get(e);s&&this.retireLogicalEntry(s,t,i,!1,r)}retireLogicalEntry(e,t,i,r,s){if(this.channels.get(e.channelId)!==e)return;this.channels.delete(e.channelId);const o=e.dataChannel,a=e.owner;if(s&&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{r=!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,r),this.mediaParent&&this.channels.size===0&&this.peerOwner&&this.teardown(i||"media-lane-idle",null,!0)}}const I=new le;function Oe(n){I.configure(n)}function Ut(){I.preferDirect()}function Ht(){I.markLocalHubReachable()}function hn(){I.resume()}function fn(){I.suspendLivenessEvidence()}function pn(){I.retry()}function J(n,e,t){return I.preferDirect(),I.fetch(n,e,t)}function gn(n,e,t){return I.shouldUseDirect()?I.openWebSocket(e,t):new WebSocket(n)}function mn(){return I.inspect()}function Ft(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 qt(n,e){return n&&await n.catch(()=>{}),e()}function Gt(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 ue(n){return!n?.user?.id||!n?.workspaceId?"":[n.user.id,n.workspaceId,n.workspaceKind,n.workspaceRole,Number(n.membershipRevision||0)].join(`
|
|
7
|
-
`)}function
|
|
8
|
-
`)}function $t({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,P=H(`http://127.0.0.1:${x}`);function Vt(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 De(n){const e=n.trim().toLowerCase();return e==="localhost"||e==="127.0.0.1"||e==="::1"||e==="[::1]"}function zt(n){const e=n.trim().toLowerCase();return!e||e==="0.0.0.0"||e==="::"||e==="[::]"}function Re(n){const e=Vt(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 Xt(n){return n.includes(":")&&!n.startsWith("[")?`[${n}]`:n}function Yt(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),r=i.hostname.replace(/^\[|\]$/g,""),s=Number(i.port);return!r||!Number.isInteger(s)||s<1||s>65535||zt(r)?null:{host:r,port:s}}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 Kt(n){const e=Yt(n);return e?H(`http://${Xt(e.host)}:${x}`):""}function wn(n){const t=[n?.endpoint,...Array.isArray(n?.endpoint_candidates)?n.endpoint_candidates:[]].map(i=>Kt(String(i||""))).filter(Boolean);return[...new Set(t)]}function Jt(n=P){if(!(typeof window>"u"||window.location.protocol!=="https:"))try{const e=new URL(n);if(e.protocol!=="http:")return;if(De(e.hostname))return"loopback";if(Re(e.hostname))return"local"}catch{return}}function bn(n,e=P){const t=new URL(n,H(e));return t.protocol=t.protocol==="https:"?"wss:":"ws:",t.toString()}let v=null,R="",T="";const y=new Map,D=new Map,U=new Map,j=new Set;function z(n){const e=U.get(n);e!==void 0&&typeof window<"u"&&window.clearTimeout(e),U.delete(n)}function Pe(){for(const n of U.keys())z(n)}function se(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 _e(n,e,t){if(z(n),typeof window>"u"||e<=Date.now())return;const i=Math.max(1e3,Math.min(45e3,e-Date.now()-15e3)),r=window.setTimeout(()=>{U.delete(n),!(t!==R||v?.workspaceKind!=="team")&&V(n,!0).catch(()=>{})},i);U.set(n,r)}function Qt(n,e,t){const i=v?.workspaceKind==="team",r=i?se(e.accessExpiresAt)||Date.now()+6e4:0;y.set(n,{csrfToken:e.csrfToken,expiresAt:e.expiresAt,accessExpiresAt:r,ownerSignature:T}),j.add(n),i?_e(n,r,t):z(n)}function En(n){const e=n?.accessToken&&n?.refreshToken&&n?.user?.id?n:null,t=ue(e),i=jt(e);if(t!==T&&(e&&y.clear(),T=t),i!==R&&(Pe(),R=i,e?.workspaceKind==="team"))for(const[r,s]of y)s.ownerSignature===t&&_e(r,s.accessExpiresAt,i);v=e,Oe(e?{accessToken:e.accessToken,user:{id:e.user.id},workspaceId:e.workspaceId,workspaceKind:e.workspaceKind,workspaceRole:e.workspaceRole,membershipRevision:e.membershipRevision}:null),e&&X()&&Ut()}function X(){if(typeof window>"u"||window.location.protocol!=="https:")return!1;const n=window.location.hostname.replace(/^\[|\]$/g,"");return!De(n)&&!Re(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 $(n,e,t,i,r){const s=Jt(t);return s&&(e.targetAddressSpace=s),We(r,i,async o=>{e.signal=o;try{return await fetch(`${t}${n}`,e)}catch(a){throw!o.aborted&&s?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 V(n,e=!1){if(X())throw new Error("Public Console uses verified P2P authorization instead of a Hub cookie session.");const t=y.get(n);if(!e&&t&&t.ownerSignature===T&&t.expiresAt>Date.now()+3e4&&(t.accessExpiresAt===0||t.accessExpiresAt>Date.now()+15e3))return;e&&y.delete(n);const i=v,r=R;if(!i)return;const s=D.get(n);if(s)return s.authSignature===r?s.promise:s.promise.catch(()=>{}).then(()=>V(n,e));let o;const a=(async()=>{const c=await $("/api/auth/session",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(Gt(i,{publicConsole:!1})),credentials:"include",cache:"no-store"},n,W),d=await c.json().catch(()=>null);if(!c.ok)throw new Error(`${c.status} ${d?.error||c.statusText}`);const f=String(d?.uiSession?.csrfToken||"").trim(),l=Number(d?.uiSession?.expiresAt||0);if(!f||!Number.isFinite(l)||l<=Date.now())throw new Error("VuvoDesk Hub did not issue a valid UI session.");if(r!==R)throw y.set(n,{csrfToken:f,expiresAt:l,accessExpiresAt:se(d?.uiSession?.accessExpiresAt),ownerSignature:ue(i)}),j.add(n),new Error("VuvoDesk workspace changed while the Hub session was opening.");Qt(n,{csrfToken:f,expiresAt:l,accessExpiresAt:se(d?.uiSession?.accessExpiresAt)},r)})().finally(()=>{D.get(n)===o&&D.delete(n)});return o={authSignature:r,promise:a},D.set(n,o),a}async function Zt(){const n=new Set(j);for(const t of D.keys())n.add(t);X()||n.add(H(P));const e=[...n].map(t=>qt(D.get(t)?.promise,async()=>{const i=y.get(t),r=await $("/api/auth/session",{method:"DELETE",headers:i?.csrfToken?{"X-LiveDesk-CSRF":i.csrfToken}:{},credentials:"include",cache:"no-store"},t,W);if(!r.ok&&r.status!==401){const s=await r.json().catch(()=>null);throw new Error(`${r.status} ${s?.error||r.statusText}`)}j.delete(t),y.delete(t),z(t)}));await Promise.all(e)}const en=Ft(Zt);function Cn(){return v=null,R="",T="",Pe(),Oe(null),en.run()}async function tn(n,e,t=P){const i=H(t),{timeoutMs:r=W,signal:s,transport:o="auto",...a}=e||{},c=!Q(n),d=c?T:"",f=()=>!c||!!d&&d===T,l=()=>{if(!f())throw new Error("VuvoDesk workspace changed while the Hub request was running.")},u=$t({publicConsole:X(),path:n,requiresUiSession:c});if(c&&!v)throw new Error("VuvoDesk account authority is not available for this Hub request.");const m=()=>{const E=String(a.method||"GET").toUpperCase(),b=y.get(i),h=b?.ownerSignature===T?b.csrfToken:"";return{...a,...s?{signal:s}:{},headers:{...a.headers||{},...!["GET","HEAD","OPTIONS"].includes(E)&&h?{"X-LiveDesk-CSRF":h}:{}},credentials:"include",cache:"no-store"}};if(u==="reject-auth-session")throw new Error("Public Console does not create a Hub cookie session.");if(u==="direct"){if(l(),s?.aborted)throw s.reason||new Error("VuvoDesk Hub request cancelled.");return J(n,m(),r)}if(o==="p2p"){if(l(),s?.aborted)throw s.reason||new Error("VuvoDesk Hub request cancelled.");if(!v||Q(n))throw new Error("Mobile Console direct connection requires an authenticated management request.");return J(n,m(),r)}try{c&&await V(i),l();let E=await $(n,m(),i,r,s);if(l(),Ht(),c&&E.status===401&&v){const b=await E.clone().json().catch(()=>null);/^hub-ui-session-(required|expired)$/.test(String(b?.error||""))&&(await V(i,!0),l(),E=await $(n,m(),i,r,s),l())}return E}catch(E){if(!f()||s?.aborted||!v||Q(n))throw E;return J(n,m(),r)}}async function nn(n,e,t=P){const i=await tn(n,{...e||{},headers:{"Content-Type":"application/json",...e?.headers||{}}},t);let r=null;try{r=await i.json()}catch(s){if(e?.signal?.aborted)throw s;r=null}if(!i.ok){const s=r&&typeof r=="object"&&"error"in r?String(r.error||""):"";throw new Error(`${i.status} ${s||i.statusText}`)}return r}async function Sn({baseUrl:n=P,targetRole:e,previousRuntimePid:t=0,allowedStates:i=["running","waiting-auth"],timeoutMs:r=3e4}){const s=Date.now()+r;let o=null;for(;Date.now()<s;){try{const c=await nn("/api/runtime/status",void 0,n),d=String(c.role||"").toLowerCase(),f=String(c.state||"").toLowerCase(),l=Number(c.runtimePid||0),u=t>1?l>1&&l!==t:l>1;if(d===e&&i.map(m=>m.toLowerCase()).includes(f)&&u)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 In(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 r=0;const s=()=>{fetch(i,{cache:"no-store",mode:"no-cors"}).then(()=>window.location.replace(i)).catch(()=>{if(r+=1,r>=e){window.location.replace(i);return}window.setTimeout(s,250)})};s()}function Ln(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 vn(n){await navigator.clipboard.writeText(n)}const rn=5,Le=20,sn=50,on=Number.POSITIVE_INFINITY,an=5,yn={free:{name:"Free",price:"$0",limit:rn,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:Le,people:1,audience:"Creators and homelabs",note:`${Le} 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:on,people:an,audience:"Shared business operations",note:"Commercial use, a shared Team Space, and up to 5 people using their own accounts."}},cn="0.1.697",ln={version:cn},kn=String(ln.version).trim();function Mn({size:n=22}){return A.jsxs("svg",{width:n,height:n,viewBox:"0 0 28 28",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",children:[A.jsx("rect",{x:"2.5",y:"4",width:"14",height:"9",rx:"1.5",stroke:"currentColor",strokeWidth:"1.7",opacity:"0.42"}),A.jsx("path",{d:"M7 16v1.5h5",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round",opacity:"0.42"}),A.jsx("rect",{x:"10.5",y:"2.5",width:"14",height:"9",rx:"1.5",stroke:"currentColor",strokeWidth:"1.7",opacity:"0.62"}),A.jsx("path",{d:"M15 14.5V16h5",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round",opacity:"0.62"}),A.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"}),A.jsx("path",{d:"M12 21v1.5H9.5M16 21v1.5h2.5M9.5 22.5h9",stroke:"currentColor",strokeWidth:"1.9",strokeLinecap:"round"})]})}export{P as D,rn as F,kn as L,Mn as M,Le as P,an as T,sn as a,Cn as b,vn as c,K as d,pn as e,Ln as f,Jt as g,nn as h,X as i,gn as j,bn as k,H as l,hn as m,In as n,tn as o,yn as p,En as q,dn as r,fn as s,wn as t,mn as u,Sn as w};
|
|
6
|
+
${t.workspaceRole}`:"";this.session=t,i!==r&&(this.teardown("console-session-replaced",null,!0),this.recentMediaClosures.length=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.mediaPeers.entries()].map(([l,u])=>({channelId:l,connectionId:u.peerOwner?.connectionId||null,generation:u.generation,stage:u.stage,directReady:u.directReady,peerCount:u.peer?1:0,controlChannels:u.controlChannel?1:0,logicalChannels:u.channels.size,openLogicalChannels:[...u.channels.values()].filter(m=>m.opened).length,resourceTimers:+(u.connectTimer!==null)+ +(u.peerDisconnectTimer!==null)+ +(u.controlWireDeadline!==null)+[...u.channels.values()].reduce((m,E)=>m+ +(E.openDeadline!==null)+ +(E.wireDeadline!==null),0),sendBufferedBytes:u.peerBufferedAmount(),partialMediaWireTimeoutCount:u.partialMediaWireTimeoutCount,logicalChannelFailureCount:u.logicalChannelFailureCount,lastPartialMediaWireTimeout:u.lastPartialMediaWireTimeout,lastLogicalChannelFailure:u.lastLogicalChannelFailure})),t=this.wireBudget?.inspect()||{retainedBytes:0,reservationCount:0},i=[this,...this.mediaPeers.values()],r=i.flatMap(l=>[...l.channels.values()]),s=r.filter(l=>l.wireDeadline!==null).length,o=r.filter(l=>l.openDeadline!==null).length,a=i.filter(l=>l.connectTimer!==null).length,c=i.filter(l=>l.peerDisconnectTimer!==null).length,d=i.filter(l=>l.controlWireDeadline!==null).length,f=this.workspaceReauthAttempt?.deadline==null?0:1;return Object.freeze({preferred:this.preferred,stage:this.stage,directReady:this.directReady,generation:this.generation,consoleId:this.consoleId||null,connectionId:this.peerOwner?.connectionId||null,signalSockets:this.signalSocket?1:0,mediaPeerVersion:this.mediaPeerVersion,mediaPeers:e,recentMediaClosures:this.recentMediaClosures.slice(),peerCount:+!!this.peer+e.reduce((l,u)=>l+u.peerCount,0),controlChannels:this.controlChannel?1:0,mediaControlChannels:e.reduce((l,u)=>l+u.controlChannels,0),logicalChannels:this.channels.size+e.reduce((l,u)=>l+u.logicalChannels,0),openLogicalChannels:[...this.channels.values()].filter(l=>l.opened).length+e.reduce((l,u)=>l+u.openLogicalChannels,0),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(l=>(l.purpose==="frame"||l.purpose==="atlas")&&l.owner===null&&l.dataChannel===null).length,pendingRemoteCandidates:this.pendingRemoteCandidates.length,pendingLocalCandidates:this.pendingLocalCandidates.length,connectTimers:a,peerDisconnectTimers:c,controlWireTimers:d,workspaceReauthTimers:f,logicalOpenTimers:o,logicalWireTimers:s,resourceTimers:a+c+d+f+o+s+this.pendingHttp.size,wireRetainedBytes:t.retainedBytes,wireReservations:t.reservationCount,sendBufferedBytes:this.peerBufferedAmount()+e.reduce((l,u)=>l+u.sendBufferedBytes,0),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 st(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 r=window.setTimeout(()=>{this.peerDisconnectTimer===r&&(this.peerDisconnectTimer=null,!(!this.isPeerOwner(e)||this.peer!==t)&&(t.connectionState==="disconnected"||t.iceConnectionState==="disconnected")&&this.fail(p(),"peer-disconnected-timeout",!0))},ht);this.peerDisconnectTimer=r}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 r=window.setTimeout(()=>{this.controlWireDeadline===r&&(this.controlWireDeadline=null,!(!this.isPeerOwner(e)||this.controlAssembler!==t)&&(t.inspect().pendingMessages||0)>0&&this.fail(p(),"control-wire-assembly-timeout",!0))},pt);this.controlWireDeadline=r}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(!Mt.has(String(e.type||"")))throw new Error("console-direct-signal-type-forbidden");if(this.mediaParent){const{manager:i,owner:r,channelId:s}=this.mediaParent;if(!i.isPeerOwner(r)||i.mediaPeers.get(s)!==this)throw new Error("console-direct-media-parent-stale");i.sendControl({type:"media-signal",connectionId:r.connectionId,hubEpoch:r.hubEpoch,mediaId:s,signal:e});return}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,r){if(e.readyState!=="open")throw new Error("console-direct-data-channel-not-open");const s=ze(t,{messageId:this.nextMessageId(),kind:i,maxMessageBytes:r}),o=s.reduce((a,c)=>a+c.byteLength,0);if(o>Se||this.peerBufferedAmount()>Se-o)throw new Error("console-direct-send-buffer-full");for(const a of s)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=K(e),this.teardown(t,e,i)}teardown(e,t,i,r=!1){const s=this.signalSocket,o=this.peerOwner;if(i&&(this.mediaParent||s?.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{}for(const l of[...this.mediaPeers.values()])l.teardown(e,t,!1);if(this.mediaPeers.clear(),this.mediaParent?.manager.mediaPeers.get(this.mediaParent.channelId)===this){const l=this.mediaParent.manager.recentMediaClosures;l.push({channelId:this.mediaParent.channelId,generation:this.generation,reason:String(e).slice(0,120),occurredAt:Date.now(),logicalFailure:this.lastLogicalChannelFailure}),l.length>8&&l.shift(),this.mediaParent.manager.mediaPeers.delete(this.mediaParent.channelId)}this.mediaPeerVersion=0,r?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[l,u]of this.pendingHttp)window.clearTimeout(u.timeout),u.detachAbort(),u.reject(a),this.pendingHttp.delete(l);for(const l of[...this.channels.values()])this.retireLogicalEntry(l,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 d=this.peer;if(this.peer=null,d){d.onicecandidate=null,d.onconnectionstatechange=null,d.oniceconnectionstatechange=null;try{d.close()}catch{}}if(!r)try{s?.close(1e3,String(e||"console-direct-closed").slice(0,120))}catch{}const f=this.wireBudget?.inspect();this.lastTerminalWireBytes=Number(f?.retainedBytes||0),this.lastTerminalWireReservations=Number(f?.reservationCount||0),this.wireBudget=null}async connect(){if(this.directReady&&this.peerOwner&&this.controlChannel?.readyState==="open")return;if(this.connectPromise)return this.connectPromise;if(this.mediaParent)return this.connectMediaPeer();const e=this.session;if(!e)throw S();const t=this.signalSocket?.readyState===WebSocket.OPEN&&this.signalReady;if(t&&this.stage==="hub-offline"){const s=Y();throw this.lastFailure=K(s),s}if(t&&this.stage==="p2p"&&this.peerOwner&&this.peer){const s=this.generation,o=new Promise((a,c)=>{this.resolveConnect=a,this.rejectConnect=c});return this.connectPromise=o,this.connectTimer===null&&(this.connectTimer=window.setTimeout(()=>{s===this.generation&&!this.directReady&&this.fail(p(),"direct-ready-timeout",!0)},F)),o}const i=this.generation+1;this.generation=i,this.stage="signal",this.lastFailure=null;const r=new Promise((s,o)=>{this.resolveConnect=s,this.rejectConnect=o});this.connectPromise=r,this.connectTimer=window.setTimeout(()=>{if(i!==this.generation)return;const s=this.stage==="signal"?S():p();this.fail(s,this.stage==="signal"?"signal-timeout":"direct-ready-timeout",!1)},this.stage==="signal"?dt:F);try{const s=new WebSocket(At(e.workspaceId),[at,`${ct}${e.accessToken}`]);this.signalSocket=s,s.addEventListener("message",o=>{if(!this.isSignalOwner(i,s)||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,s)}),s.addEventListener("error",()=>{this.isSignalOwner(i,s)&&(this.detachSignalFromReadyPeer(i,s,"signal-detached-after-ready")||this.fail(S(),"signal-service-unavailable",!1))}),s.addEventListener("close",()=>{this.isSignalOwner(i,s)&&(this.detachSignalFromReadyPeer(i,s,"signal-closed-after-ready")||this.fail(S(),"signal-service-closed",!1))})}catch{this.fail(S(),"signal-constructor-failed",!1)}return r}connectMediaPeer(){const e=this.mediaParent;if(!e.manager.isPeerOwner(e.owner)||!e.manager.hasReadyPayloadPeer()||e.manager.mediaPeers.get(e.channelId)!==this)return Promise.reject(new Error("console-direct-media-parent-stale"));this.session=e.manager.session,this.consoleId=e.channelId,this.hubEpoch=e.owner.hubEpoch,this.stage="p2p";const t=++this.generation,i=new Promise((r,s)=>{this.resolveConnect=r,this.rejectConnect=s});return this.connectPromise=i,this.connectTimer=window.setTimeout(()=>{t===this.generation&&!this.directReady&&this.fail(p(),"media-direct-ready-timeout",!0)},F),this.beginPeer(t,e.owner.hubEpoch),i}handleMediaSignal(e,t){if(this.mediaParent||t.connectionId!==e.connectionId||t.hubEpoch!==e.hubEpoch)return;const i=this.mediaPeers.get(String(t.mediaId||"")),r=t.signal,s=i?.peerOwner;!i||!s||!r||i.mediaParent?.owner!==e||r.connectionId!==s.connectionId||r.hubEpoch!==s.hubEpoch||(r.type==="rtc-answer"?i.acceptAnswer(s,r.description):r.type==="rtc-ice"?i.acceptRemoteCandidate(s,r.candidate,r.sdpMid):r.type==="rtc-close"&&i.fail(p(),String(r.reason||"media-peer-closed").slice(0,120),!1))}handleSignal(e,t,i){if(!this.isSignalOwner(t,i))return;if(e.type==="workspace-reauth-required"){const s=this.session,o=String(e.workspaceId||s?.workspaceId||"").trim(),a=String(e.challengeNonce||"").trim();if(!s||o!==s.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,d={challengeNonce:a,generation:t,socket:i,controller:c,deadline:null},f=Number(e.deadlineAt||0),l=Number.isFinite(f)&&f>0?Math.max(1,f-Date.now()):be;d.deadline=window.setTimeout(()=>{this.workspaceReauthAttempt===d&&this.cancelWorkspaceReauthAttempt(t,i)},Math.max(1,Math.min(be,l))),this.workspaceReauthAttempt=d,(async()=>{try{await fetch(Ot("/v2/rtc/reauth"),{method:"POST",headers:{Authorization:`Bearer ${s.accessToken}`,"Content-Type":"application/json"},body:JSON.stringify({workspaceId:s.workspaceId,challengeNonce:a}),signal:c.signal,cache:"no-store"})}catch{}})().finally(()=>{this.workspaceReauthAttempt===d&&(this.workspaceReauthAttempt=null,d.deadline!==null&&(window.clearTimeout(d.deadline),d.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 s=String(e.consoleId||""),o=String(e.hubEpoch||"");if(e.role!=="console"||!N.test(s)){this.fail(S(),"invalid-signal-ready",!1);return}if(this.signalReady=!0,this.consoleId=s,e.hubOnline!==!0){const a=Y();this.lastFailure=K(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)},F),this.beginPeer(t,o);return}const r=this.peerOwner;if(!(!r||String(e.connectionId||"")!==r.connectionId||String(e.hubEpoch||"")!==r.hubEpoch)){if(e.type==="rtc-answer")this.acceptAnswer(r,e.description);else if(e.type==="rtc-ice")this.acceptRemoteCandidate(r,e.candidate,e.sdpMid);else if(e.type==="rtc-close"){const s=String(e.reason||"rtc-closed"),o=/hub-offline/i.test(s)?Y():p();this.fail(o,s,!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 r=rt({userId:i.user.id,connectionId:crypto.randomUUID(),hubEpoch:t,generation:e});this.consecutiveMediaLogicalOpenFailures=0,this.peerOwner=r,this.wireBudget=this.mediaParent?.manager.wireBudget||Te({maxBytes:It}),this.controlAssembler=me({budget:this.wireBudget,maxMessageBytes:k});let s;try{s=new RTCPeerConnection({iceServers:[{urls:Rt()}],iceTransportPolicy:"all",bundlePolicy:"max-bundle",rtcpMuxPolicy:"require"})}catch{this.fail(p(),"peer-constructor-failed",!0);return}this.peer=s;const o=s.createDataChannel(lt,{ordered:!0});o.binaryType="arraybuffer",this.controlChannel=o,s.onicecandidate=a=>{if(!this.isPeerOwner(r)||this.peer!==s||!a.candidate)return;const c=String(a.candidate.candidate||"");if(_(c)){this.fail(p(),"relay-ice-candidate-forbidden",!0);return}if(new TextEncoder().encode(c).byteLength>Et){this.fail(p(),"local-ice-candidate-invalid",!0);return}if(!this.localOfferSent){if(this.pendingLocalCandidates.length>=bt){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:r.connectionId,hubEpoch:r.hubEpoch,candidate:c,sdpMid:a.candidate.sdpMid})}catch{this.fail(S(),"signal-ice-failed",!1)}},s.onconnectionstatechange=()=>{if(!(!this.isPeerOwner(r)||this.peer!==s)){if(s.connectionState==="failed"||s.connectionState==="closed"){this.fail(p(),`peer-${s.connectionState}`,!0);return}this.refreshPeerDisconnectDeadline(r,s)}},s.oniceconnectionstatechange=()=>{if(!(!this.isPeerOwner(r)||this.peer!==s)){if(s.iceConnectionState==="failed"||s.iceConnectionState==="closed"){this.fail(p(),`ice-${s.iceConnectionState}`,!0);return}this.refreshPeerDisconnectDeadline(r,s)}},o.onmessage=a=>{!this.isPeerOwner(r)||this.controlChannel!==o||this.handleControlWire(r,a.data)},o.onerror=()=>{!this.isPeerOwner(r)||this.controlChannel!==o||this.fail(p(),"control-channel-error",!0)},o.onclose=()=>{!this.isPeerOwner(r)||this.controlChannel!==o||this.fail(p(),"control-channel-closed",!0)},(async()=>{try{const a=await s.createOffer();if(!this.isPeerOwner(r)||this.peer!==s)return;if(a.type!=="offer"||_(a.sdp))throw new Error("relay-sdp-forbidden");if(await s.setLocalDescription(a),!this.isPeerOwner(r)||this.peer!==s)return;const c=s.localDescription||a;if(c.type!=="offer"||_(c.sdp))throw new Error("relay-sdp-forbidden");this.signal({type:"rtc-offer",connectionId:r.connectionId,hubEpoch:r.hubEpoch,description:{type:"offer",sdp:nt(c.sdp||"")}}),this.localOfferSent=!0;const d=this.pendingLocalCandidates;this.pendingLocalCandidates=[];for(const f of d){if(!this.isPeerOwner(r)||this.peer!==s)return;this.signal({type:"rtc-ice",connectionId:r.connectionId,hubEpoch:r.hubEpoch,...f})}}catch(a){if(!this.isPeerOwner(r))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"||_(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 r=this.pendingRemoteCandidates;this.pendingRemoteCandidates=[];for(const s of r){if(!this.isPeerOwner(e)||this.peer!==i)return;await i.addIceCandidate(s.candidate?s:null)}}catch{this.isPeerOwner(e)&&this.fail(p(),"rtc-answer-apply-failed",!0)}}}async acceptRemoteCandidate(e,t,i){if(!this.isPeerOwner(e))return;const r=String(t??""),s=i==null?null:String(i);if(r.length>4*1024||s!==null&&s.length>256||_(r)){this.fail(p(),"rtc-candidate-invalid",!0);return}const o=this.peer;if(o){if(!this.remoteDescriptionApplied){if(this.pendingRemoteCandidates.length>=wt){this.fail(p(),"rtc-candidate-capacity",!0);return}this.pendingRemoteCandidates.push({candidate:r,sdpMid:s});return}try{await o.addIceCandidate(r?{candidate:r,sdpMid:s}: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 r=i.push(re(t));if(this.refreshControlWireDeadline(e,i),!r)return;if(r.kind!=="control"||typeof r.data!="string")throw new Error("control-wire-kind-invalid");const s=JSON.parse(r.data);if(s.type==="direct-ready"){if(s.connectionId!==e.connectionId||s.hubEpoch!==e.hubEpoch||this.controlChannel?.readyState!=="open")throw new Error("direct-ready-owner-invalid");this.directReady||(this.mediaPeerVersion=!this.mediaParent&&s.mediaPeerVersion===1?1:0,this.consecutiveLivenessRequestTimeouts=0,this.directReady=!0,this.stage="ready",this.resolveCurrentConnect());return}if(s.type==="media-signal"){this.handleMediaSignal(e,s);return}if(s.type==="http-response"){this.handleHttpResponse(e,s);return}if(s.type==="ws-opened"||s.type==="ws-closed"||s.type==="ws-error"){this.handleLogicalLifecycle(e,s);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 r=this.channels.get(i);if(!r)return;const s=r.dataChannel;if(!s||!r.openRequested||!this.logicalEntryIsCurrent(r,e,s))throw new Error("logical-lifecycle-owner-invalid");if(t.type==="ws-opened"){if(r.opened)return;r.opened=!0,(r.purpose==="frame"||r.purpose==="atlas")&&(this.consecutiveMediaLogicalOpenFailures=0),this.clearLogicalOpenDeadline(r);const o=r.pendingInbound.splice(0);if(r.pendingInboundBytes=0,r.socket.managerOpened(),!this.logicalEntryIsCurrent(r,e,s)||!r.opened)return;for(const a of o)this.deliverLogicalMessage(r,a);return}if(t.type==="ws-closed"){this.retireLogicalEntry(r,ie(t.code,1e3),String(t.reason||""),!1,!1);return}this.retireLogicalEntry(r,1011,String(t.error||"console-direct-websocket-error"),!0,!1)}handleHttpResponse(e,t){const i=String(t.requestId||""),r=this.pendingHttp.get(i);if(!r||r.generation!==e.generation||!this.isPeerOwner(e))return;this.consecutiveLivenessRequestTimeouts=0,this.livenessMediaRecoveryGeneration=0;const s=this.mediaAttachmentHoldGeneration===e.generation;this.pendingHttp.delete(i),window.clearTimeout(r.timeout),r.detachAbort();try{const o=Number(t.status||502),a=t.bodyBase64?_t(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"}});r.resolve(c),s&&(this.mediaAttachmentHoldGeneration=0,this.attachHeldMediaChannels(e))}catch(o){r.reject(q(o))}}async fetch(e,t,i){await Bt(this.connect(),t?.signal);const r=this.peerOwner;if(!r||!this.directReady||this.controlChannel?.readyState!=="open")throw p();if(this.pendingHttp.size>=Ce)throw new Error("console-direct-http-capacity-reached");const s=await Nt(t?.body);if(s.byteLength>Ct)throw new Error("console-direct-http-body-too-large");if(!this.isPeerOwner(r)||!this.directReady)throw p();if(this.pendingHttp.size>=Ce)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(),d=c==="GET"&&St.has(e),f=d?this.livenessEvidenceEpoch:null,l=new Promise((u,m)=>{const E=(C,w=!1)=>{const L=this.pendingHttp.get(o);if(L){this.pendingHttp.delete(o),window.clearTimeout(L.timeout),L.detachAbort();try{this.sendControl({type:"http-cancel",requestId:o})}catch{}m(C),w&&d&&this.recordLivenessRequestTimeout(r,L.livenessEvidenceEpoch)}},b=()=>E(t?.signal?.reason instanceof Error?t.signal.reason:new Error("Mobile Console request cancelled."));t?.signal?.addEventListener("abort",b,{once:!0});const h=window.setTimeout(()=>{E(new Error("Mobile Console direct request timed out."),!0)},a);this.pendingHttp.set(o,{generation:r.generation,livenessEvidenceEpoch:f,resolve:u,reject:m,timeout:h,detachAbort:()=>t?.signal?.removeEventListener("abort",b)})});try{this.sendControl({type:"http-request",requestId:o,method:c,path:e,headers:xt(t),bodyBase64:s.byteLength>0?Pt(s):""})}catch(u){const m=this.pendingHttp.get(o);m&&(this.pendingHttp.delete(o),window.clearTimeout(m.timeout),m.detachAbort(),m.reject(q(u))),this.fail(p(),"control-send-failed",!0)}return l}openWebSocket(e,t){if(!Tt.has(t))throw new Error("console-direct-purpose-invalid");if(this.channels.size+this.mediaPeers.size>=mt)throw new Error("console-direct-channel-capacity-reached");const i=crypto.randomUUID(),r=new Ut(this,i,t,e),s={channelId:i,path:e,purpose:t,socket:r,owner:null,dataChannel:null,assembler:null,openDeadline:null,wireDeadline:null,wireScheduledAtEpochMs:0,wireStartedAtEpochMs:0,wireLastProgressAtEpochMs:0,wireAbsoluteDeadlineAtEpochMs:0,openRequested:!1,opened:!1,pendingInbound:[],pendingInboundBytes:0};return this.channels.set(i,s),this.connect().then(()=>{if(this.channels.get(i)===s){if(!this.mediaParent&&this.mediaPeerVersion===1&&this.peerOwner&&(t==="frame"||t==="atlas")){const o=new le({manager:this,owner:this.peerOwner,channelId:i});this.channels.delete(i),this.mediaPeers.set(i,o),o.channels.set(i,s),r.handoffConnectingOwner(o),o.connect().then(()=>{o.channels.get(i)===s&&o.attachLogicalChannel(s)}).catch(a=>{o.retireLogicalEntry(s,1011,q(a).message,!0,!1)});return}this.attachLogicalChannel(s)}}).catch(o=>{this.channels.get(i)===s&&this.retireLogicalEntry(s,1011,q(o).message,!0,!1)}),r}attachLogicalChannel(e){const t=this.peerOwner,i=this.peer,r=this.wireBudget;if(!t||!i||!r||!this.directReady||this.channels.get(e.channelId)!==e){this.retireLogicalEntry(e,1011,"console-direct-not-ready",!0,!1);return}const s=e.purpose==="frame"||e.purpose==="atlas";if(s&&this.mediaAttachmentHoldGeneration===t.generation)return;e.owner=t;let o;try{o=i.createDataChannel(`${ut}${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=me({budget:r,maxMessageBytes:s?Ie:k,maxPendingMessages:s?Lt: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,r,s,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(r||"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(f=>f!==e&&f.opened&&(f.purpose==="frame"||f.purpose==="atlas")&&f.dataChannel?.readyState==="open"),d=a&&!c&&(o||this.consecutiveMediaLogicalOpenFailures>=kt);this.retireLogicalEntry(e,i,r,s,!1),d&&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 r=window.setTimeout(()=>{e.openDeadline===r&&(e.openDeadline=null,!(!this.logicalEntryIsCurrent(e,t,i)||e.opened)&&this.retireLogicalOpenFailure(e,t,1011,"console-direct-logical-open-timeout",!0,!1))},ft);e.openDeadline=r}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 r=e.assembler;if(!r||!this.logicalEntryIsCurrent(e,t,e.dataChannel))return;const s=r.inspect();let o={chunkBytes:0,headerReadable:!1,messageId:0,chunkIndex:0,chunkCount:0,totalLength:0};try{o=Wt(i);const a=r.push(re(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(s.pendingMessages||0)),pendingBytesBefore:Math.max(0,Number(s.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",r=i?Ie:k;if(i){if(e.pendingInbound.length===0){e.pendingInbound.push(t),e.pendingInboundBytes=t.byteLength;return}if(e.pendingInbound.length<yt&&e.pendingInboundBytes+t.byteLength<=r){e.pendingInbound.push(t),e.pendingInboundBytes+=t.byteLength;return}const s=e.pendingInbound[0],o=s.byteLength+t.byteLength,a=o<=r?"replace-latest":"drop-over-budget";a==="replace-latest"&&(e.pendingInbound=[s,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>=vt||e.pendingInboundBytes+t.byteLength>r)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;if(e.socket.binaryType==="arraybuffer"){const r=i.buffer instanceof ArrayBuffer&&i.byteOffset===0&&i.byteLength===i.buffer.byteLength?i.buffer:i.slice().buffer;e.socket.managerMessage(r)}else e.socket.managerMessage(new Blob([i]))}logicalBufferedAmount(e){return Number(this.channels.get(e)?.dataChannel?.bufferedAmount||0)}clearLogicalWireDeadline(e){e.wireDeadline!==null&&(window.clearTimeout(e.wireDeadline),e.wireDeadline=null),e.wireScheduledAtEpochMs=0,e.wireStartedAtEpochMs=0,e.wireLastProgressAtEpochMs=0,e.wireAbsoluteDeadlineAtEpochMs=0}scheduleLogicalWireDeadline(e,t){const i=e.purpose==="frame"||e.purpose==="atlas",r=Date.now(),s=e.assembler?.inspect(),o=i?we(Number(s?.pendingBytes||0)):Number.POSITIVE_INFINITY,a=i?Math.max(1,o-(r-e.wireLastProgressAtEpochMs)):Number.POSITIVE_INFINITY,c=Math.max(1,e.wireAbsoluteDeadlineAtEpochMs-r),d=Math.min(a,c),f=r+d;if(e.wireDeadline!==null&&e.wireScheduledAtEpochMs<=f)return;e.wireDeadline!==null&&window.clearTimeout(e.wireDeadline);const l=window.setTimeout(()=>{if(e.wireDeadline!==l)return;e.wireDeadline=null,e.wireScheduledAtEpochMs=0;const u=e.dataChannel;if(!u||!this.logicalEntryIsCurrent(e,t,u))return;const m=e.assembler?.inspect(),E=Number(m?.pendingMessages||0);if(E===0){this.clearLogicalWireDeadline(e);return}const b=Date.now(),h=Math.max(0,b-e.wireLastProgressAtEpochMs),C=Math.max(0,b-e.wireStartedAtEpochMs),w=i?we(Number(m?.pendingBytes||0)):Number.POSITIVE_INFINITY;if(!(!i||h>=w||b>=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:E,pendingBytes:Math.max(0,Number(m?.pendingBytes||0)),stalledForMs:h,lifetimeMs:C,idleDeadlineMs:w,absoluteDeadlineMs:Math.max(0,e.wireAbsoluteDeadlineAtEpochMs-e.wireStartedAtEpochMs),occurredAt:b}),e.assembler?.abandonPending(),this.clearLogicalWireDeadline(e);return}this.retireLogicalEntry(e,1011,"console-direct-partial-message-timeout",!0,!1)},d);e.wireDeadline=l,e.wireScheduledAtEpochMs=f}refreshLogicalWireDeadline(e,t){const i=e.assembler?.inspect();if(Number(i?.pendingMessages||0)===0){this.clearLogicalWireDeadline(e);return}const s=Date.now(),o=e.purpose==="frame"||e.purpose==="atlas";e.wireStartedAtEpochMs<=0&&(e.wireStartedAtEpochMs=s,e.wireAbsoluteDeadlineAtEpochMs=s+(o?it(Number(i?.pendingBytes||0)):gt)),e.wireLastProgressAtEpochMs=s,this.scheduleLogicalWireDeadline(e,t)}sendLogicalMessage(e,t){const i=this.channels.get(e),r=i?.dataChannel;if(!i||!r||!i.opened||r.readyState!=="open")throw new DOMException("WebSocket is not open.","InvalidStateError");try{if(typeof t=="string")this.sendWire(r,t,"text",k);else if(t instanceof ArrayBuffer)this.sendWire(r,t,"binary",k);else if(ArrayBuffer.isView(t)){const s=new Uint8Array(t.buffer,t.byteOffset,t.byteLength);this.sendWire(r,s,"binary",k)}else throw new DOMException("Blob sends are not supported by the direct Console channel.","NotSupportedError")}catch(s){throw this.retireLogicalEntry(i,1011,"console-direct-send-failed",!0,!1),s}}closeLogicalChannel(e,t,i,r){const s=this.channels.get(e);s&&this.retireLogicalEntry(s,t,i,!1,r)}retireLogicalEntry(e,t,i,r,s){if(this.channels.get(e.channelId)!==e)return;this.channels.delete(e.channelId);const o=e.dataChannel,a=e.owner;if(s&&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{r=!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,r),this.mediaParent&&this.channels.size===0&&this.peerOwner&&this.teardown(i||"media-lane-idle",null,!0)}}const I=new le;function De(n){I.configure(n)}function Ht(){I.preferDirect()}function Ft(){I.markLocalHubReachable()}function hn(){I.resume()}function fn(){I.suspendLivenessEvidence()}function pn(){I.retry()}function J(n,e,t){return I.preferDirect(),I.fetch(n,e,t)}function gn(n,e,t){return I.shouldUseDirect()?I.openWebSocket(e,t):new WebSocket(n)}function mn(){return I.inspect()}function qt(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 Gt(n,e){return n&&await n.catch(()=>{}),e()}function jt(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 ue(n){return!n?.user?.id||!n?.workspaceId?"":[n.user.id,n.workspaceId,n.workspaceKind,n.workspaceRole,Number(n.membershipRevision||0)].join(`
|
|
7
|
+
`)}function $t(n){const e=ue(n);return!e||!n?.accessToken||!n?.refreshToken?"":[e,n.accessToken,n.refreshToken,Number(n.expiresAt||0)].join(`
|
|
8
|
+
`)}function Vt({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,P=H(`http://127.0.0.1:${x}`);function zt(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 Re(n){const e=n.trim().toLowerCase();return e==="localhost"||e==="127.0.0.1"||e==="::1"||e==="[::1]"}function Xt(n){const e=n.trim().toLowerCase();return!e||e==="0.0.0.0"||e==="::"||e==="[::]"}function Pe(n){const e=zt(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 Yt(n){return n.includes(":")&&!n.startsWith("[")?`[${n}]`:n}function Kt(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),r=i.hostname.replace(/^\[|\]$/g,""),s=Number(i.port);return!r||!Number.isInteger(s)||s<1||s>65535||Xt(r)?null:{host:r,port:s}}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 Jt(n){const e=Kt(n);return e?H(`http://${Yt(e.host)}:${x}`):""}function wn(n){const t=[n?.endpoint,...Array.isArray(n?.endpoint_candidates)?n.endpoint_candidates:[]].map(i=>Jt(String(i||""))).filter(Boolean);return[...new Set(t)]}function Qt(n=P){if(!(typeof window>"u"||window.location.protocol!=="https:"))try{const e=new URL(n);if(e.protocol!=="http:")return;if(Re(e.hostname))return"loopback";if(Pe(e.hostname))return"local"}catch{return}}function bn(n,e=P){const t=new URL(n,H(e));return t.protocol=t.protocol==="https:"?"wss:":"ws:",t.toString()}let v=null,R="",T="";const y=new Map,D=new Map,U=new Map,j=new Set;function z(n){const e=U.get(n);e!==void 0&&typeof window<"u"&&window.clearTimeout(e),U.delete(n)}function _e(){for(const n of U.keys())z(n)}function se(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 Ne(n,e,t){if(z(n),typeof window>"u"||e<=Date.now())return;const i=Math.max(1e3,Math.min(45e3,e-Date.now()-15e3)),r=window.setTimeout(()=>{U.delete(n),!(t!==R||v?.workspaceKind!=="team")&&V(n,!0).catch(()=>{})},i);U.set(n,r)}function Zt(n,e,t){const i=v?.workspaceKind==="team",r=i?se(e.accessExpiresAt)||Date.now()+6e4:0;y.set(n,{csrfToken:e.csrfToken,expiresAt:e.expiresAt,accessExpiresAt:r,ownerSignature:T}),j.add(n),i?Ne(n,r,t):z(n)}function En(n){const e=n?.accessToken&&n?.refreshToken&&n?.user?.id?n:null,t=ue(e),i=$t(e);if(t!==T&&(e&&y.clear(),T=t),i!==R&&(_e(),R=i,e?.workspaceKind==="team"))for(const[r,s]of y)s.ownerSignature===t&&Ne(r,s.accessExpiresAt,i);v=e,De(e?{accessToken:e.accessToken,user:{id:e.user.id},workspaceId:e.workspaceId,workspaceKind:e.workspaceKind,workspaceRole:e.workspaceRole,membershipRevision:e.membershipRevision}:null),e&&X()&&Ht()}function X(){if(typeof window>"u"||window.location.protocol!=="https:")return!1;const n=window.location.hostname.replace(/^\[|\]$/g,"");return!Re(n)&&!Pe(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 $(n,e,t,i,r){const s=Qt(t);return s&&(e.targetAddressSpace=s),Be(r,i,async o=>{e.signal=o;try{return await fetch(`${t}${n}`,e)}catch(a){throw!o.aborted&&s?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 V(n,e=!1){if(X())throw new Error("Public Console uses verified P2P authorization instead of a Hub cookie session.");const t=y.get(n);if(!e&&t&&t.ownerSignature===T&&t.expiresAt>Date.now()+3e4&&(t.accessExpiresAt===0||t.accessExpiresAt>Date.now()+15e3))return;e&&y.delete(n);const i=v,r=R;if(!i)return;const s=D.get(n);if(s)return s.authSignature===r?s.promise:s.promise.catch(()=>{}).then(()=>V(n,e));let o;const a=(async()=>{const c=await $("/api/auth/session",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(jt(i,{publicConsole:!1})),credentials:"include",cache:"no-store"},n,W),d=await c.json().catch(()=>null);if(!c.ok)throw new Error(`${c.status} ${d?.error||c.statusText}`);const f=String(d?.uiSession?.csrfToken||"").trim(),l=Number(d?.uiSession?.expiresAt||0);if(!f||!Number.isFinite(l)||l<=Date.now())throw new Error("VuvoDesk Hub did not issue a valid UI session.");if(r!==R)throw y.set(n,{csrfToken:f,expiresAt:l,accessExpiresAt:se(d?.uiSession?.accessExpiresAt),ownerSignature:ue(i)}),j.add(n),new Error("VuvoDesk workspace changed while the Hub session was opening.");Zt(n,{csrfToken:f,expiresAt:l,accessExpiresAt:se(d?.uiSession?.accessExpiresAt)},r)})().finally(()=>{D.get(n)===o&&D.delete(n)});return o={authSignature:r,promise:a},D.set(n,o),a}async function en(){const n=new Set(j);for(const t of D.keys())n.add(t);X()||n.add(H(P));const e=[...n].map(t=>Gt(D.get(t)?.promise,async()=>{const i=y.get(t),r=await $("/api/auth/session",{method:"DELETE",headers:i?.csrfToken?{"X-LiveDesk-CSRF":i.csrfToken}:{},credentials:"include",cache:"no-store"},t,W);if(!r.ok&&r.status!==401){const s=await r.json().catch(()=>null);throw new Error(`${r.status} ${s?.error||r.statusText}`)}j.delete(t),y.delete(t),z(t)}));await Promise.all(e)}const tn=qt(en);function Cn(){return v=null,R="",T="",_e(),De(null),tn.run()}async function nn(n,e,t=P){const i=H(t),{timeoutMs:r=W,signal:s,transport:o="auto",...a}=e||{},c=!Q(n),d=c?T:"",f=()=>!c||!!d&&d===T,l=()=>{if(!f())throw new Error("VuvoDesk workspace changed while the Hub request was running.")},u=Vt({publicConsole:X(),path:n,requiresUiSession:c});if(c&&!v)throw new Error("VuvoDesk account authority is not available for this Hub request.");const m=()=>{const E=String(a.method||"GET").toUpperCase(),b=y.get(i),h=b?.ownerSignature===T?b.csrfToken:"";return{...a,...s?{signal:s}:{},headers:{...a.headers||{},...!["GET","HEAD","OPTIONS"].includes(E)&&h?{"X-LiveDesk-CSRF":h}:{}},credentials:"include",cache:"no-store"}};if(u==="reject-auth-session")throw new Error("Public Console does not create a Hub cookie session.");if(u==="direct"){if(l(),s?.aborted)throw s.reason||new Error("VuvoDesk Hub request cancelled.");return J(n,m(),r)}if(o==="p2p"){if(l(),s?.aborted)throw s.reason||new Error("VuvoDesk Hub request cancelled.");if(!v||Q(n))throw new Error("Mobile Console direct connection requires an authenticated management request.");return J(n,m(),r)}try{c&&await V(i),l();let E=await $(n,m(),i,r,s);if(l(),Ft(),c&&E.status===401&&v){const b=await E.clone().json().catch(()=>null);/^hub-ui-session-(required|expired)$/.test(String(b?.error||""))&&(await V(i,!0),l(),E=await $(n,m(),i,r,s),l())}return E}catch(E){if(!f()||s?.aborted||!v||Q(n))throw E;return J(n,m(),r)}}async function rn(n,e,t=P){const i=await nn(n,{...e||{},headers:{"Content-Type":"application/json",...e?.headers||{}}},t);let r=null;try{r=await i.json()}catch(s){if(e?.signal?.aborted)throw s;r=null}if(!i.ok){const s=r&&typeof r=="object"&&"error"in r?String(r.error||""):"";throw new Error(`${i.status} ${s||i.statusText}`)}return r}async function Sn({baseUrl:n=P,targetRole:e,previousRuntimePid:t=0,allowedStates:i=["running","waiting-auth"],timeoutMs:r=3e4}){const s=Date.now()+r;let o=null;for(;Date.now()<s;){try{const c=await rn("/api/runtime/status",void 0,n),d=String(c.role||"").toLowerCase(),f=String(c.state||"").toLowerCase(),l=Number(c.runtimePid||0),u=t>1?l>1&&l!==t:l>1;if(d===e&&i.map(m=>m.toLowerCase()).includes(f)&&u)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 In(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 r=0;const s=()=>{fetch(i,{cache:"no-store",mode:"no-cors"}).then(()=>window.location.replace(i)).catch(()=>{if(r+=1,r>=e){window.location.replace(i);return}window.setTimeout(s,250)})};s()}function Ln(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 vn(n){await navigator.clipboard.writeText(n)}const Le=3,ve=20,sn=50,on=Number.POSITIVE_INFINITY,an=5,yn={free:{name:"Free",price:"$0",limit:Le,people:1,audience:"Personal, ad-supported",note:`Up to ${Le} personal devices supported by a standard banner.`},ltd:{name:"Plus",price:"$5",ltd:"$79 LTD",limit:ve,people:1,audience:"Creators, homelabs, and small businesses",note:`${ve} devices, no ads, personal and commercial 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:on,people:an,audience:"Shared business operations",note:"Commercial use, a shared Team Space, and up to 5 people using their own accounts."}},cn="0.1.700",ln={version:cn},kn=String(ln.version).trim();function Mn({size:n=22}){return A.jsxs("svg",{width:n,height:n,viewBox:"0 0 28 28",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",children:[A.jsx("rect",{x:"2.5",y:"4",width:"14",height:"9",rx:"1.5",stroke:"currentColor",strokeWidth:"1.7",opacity:"0.42"}),A.jsx("path",{d:"M7 16v1.5h5",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round",opacity:"0.42"}),A.jsx("rect",{x:"10.5",y:"2.5",width:"14",height:"9",rx:"1.5",stroke:"currentColor",strokeWidth:"1.7",opacity:"0.62"}),A.jsx("path",{d:"M15 14.5V16h5",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round",opacity:"0.62"}),A.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"}),A.jsx("path",{d:"M12 21v1.5H9.5M16 21v1.5h2.5M9.5 22.5h9",stroke:"currentColor",strokeWidth:"1.9",strokeLinecap:"round"})]})}export{P as D,Le as F,kn as L,Mn as M,ve as P,an as T,sn as a,Cn as b,vn as c,K as d,pn as e,Ln as f,Qt as g,rn as h,X as i,gn as j,bn as k,H as l,hn as m,In as n,nn as o,yn as p,En as q,dn as r,fn as s,wn as t,mn as u,Sn as w};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as e}from"./pwa-startup-BiuYh5eN.js";import{r as i,W as ee,S as te,F as q,b as be,M as F,c as je,L as Re,P as we,A as $}from"./icons-ChMazCZR.js";import{h as C,w as Se,n as ye}from"./MonitorStackIcon-led0pnag.js";import"./pwa-bootstrap-ljOQTt2e.js";const v={revision:0,settings:{connection:{showThisComputer:!1,temporaryRouterMapping:!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:ee},{id:"remote-access",label:"Remote Access",icon:te},{id:"capture-audio",label:"Capture & Audio",icon:q},{id:"agent",label:"Agent",icon:be}];function A(t,n){return t?.settings?.[n]||v.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 h({icon:t,title:n,description:a,children:m,recommended:l=!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}),l&&e.jsx("em",{children:"Recommended"}),e.jsx("small",{children:a})]})]})}function x({checked:t,onChange:n,label:a}){return e.jsxs("label",{className:"product-switch",children:[e.jsx("input",{"aria-label":a,type:"checkbox",checked:t,onChange:m=>n(m.target.checked)}),e.jsx("span",{})]})}function U({value:t,onChange:n,options:a,label:m}){return e.jsx("select",{"aria-label":m,value:String(t),onChange:l=>n(l.target.value),children:a.map(([l,K])=>e.jsx("option",{value:l,children:K},l))})}function Te({hubUrl:t="",mobileLayout:n=!1,runtimeRole:a="hub",runtimeDeviceId:m="",sessionAccessToken:l="",showThisComputerSetting:K=!0,onShowThisComputerChange:D,initialTab:J="connection",pin:se,agent:ne,captureGallery:ie,desktopUpdate:oe}){const[r,Q]=i.useState(()=>n&&J==="connection"?"remote-access":J),[b,k]=i.useState(null),[re,j]=i.useState("loading"),[G,T]=i.useState(""),[z,E]=i.useState("idle"),[L,H]=i.useState(""),R=i.useRef(null),g=i.useRef(null),p=i.useRef([]),M=i.useRef(Promise.resolve()),ce=i.useRef(0),f=i.useRef(0);i.useEffect(()=>{const s=++f.current;let u=!0;return p.current=[],g.current=null,R.current=null,M.current=Promise.resolve(),j("loading"),C("/api/settings",void 0,t).then(o=>{if(!u||s!==f.current)return;const c=O(o);g.current=c,R.current=c,k(c),j("saved")}).catch(o=>{!u||s!==f.current||(T(o instanceof Error?o.message:String(o)),g.current=v,R.current=v,k(v),j("failed"))}),()=>{u=!1}},[t]);const ae=async(s,u,o)=>{const c={id:++ce.current,section:s,key:u,value:o},I=f.current;p.current.push(c);const X=_(R.current||g.current||v,c);R.current=X,k(X),j("saving"),T(""),M.current=M.current.then(async()=>{if(I!==f.current)return;let S=null,y=null;for(let N=0;N<2&&!S;N+=1){const ve=g.current||v;try{const w=await C("/api/settings",{method:"PATCH",body:JSON.stringify({revision:ve.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(I!==f.current)return;g.current=O(W)}catch(W){y=W;break}}}if(I!==f.current)return;p.current=p.current.filter(N=>N.id!==c.id),S&&(g.current=S);const xe=g.current||v,Y=p.current.reduce(_,xe);R.current=Y,k(Y),S?(T(""),j(p.current.length>0?"saving":"saved")):(j(p.current.length>0?"saving":"failed"),T(y instanceof Error?y.message:String(y||"Settings could not be saved.")))}),await M.current},d=(s,u)=>o=>{ae(s,u,o)},le=async()=>{if(a!=="hub"||!m||!l){E("failed"),H("Sign in to this Hub before changing its runtime role.");return}E("changing"),H("");try{const s=await C("/api/runtime/status",void 0,t);await C("/api/runtime/role",{method:"POST",headers:{Authorization:`Bearer ${l}`},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"),H(s instanceof Error?s.message:String(s))}},de=A(b,"security"),V=A(b,"control"),B=A(b,"filesAudio"),P=A(b,"connection"),ue=`settings-panel-${r}`,he=n?Z.filter(s=>s.id!=="connection"):Z;i.useEffect(()=>{n&&r==="connection"&&Q("remote-access")},[r,n]),i.useEffect(()=>{b&&D?.(!!P.showThisComputer)},[P.showThisComputer,D,b]);const ge=e.jsxs("div",{className:"settings-tab-content product-settings-content",children:[se,oe,a==="hub"&&e.jsx("section",{className:"settings-section-card",children:e.jsx(h,{icon:ee,title:"Help mobile devices connect",description:"Temporarily opens a router port while a direct mobile connection starts, then removes it. Uses no video relay. Requires a compatible router.",children:e.jsx(x,{checked:!!P.temporaryRouterMapping,onChange:d("connection","temporaryRouterMapping"),label:"Help mobile devices connect"})})}),K&&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(F,{size:20})]}),e.jsx(h,{icon:F,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(x,{checked:!!P.showThisComputer,onChange:d("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(je,{size:20})]}),e.jsx("p",{className:"settings-help",children:"Stop hosting from this computer and reconnect it to the selected Hub."}),z==="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:()=>{le()},disabled:z==="changing"||a!=="hub",type:"button",children:z==="changing"?"Switching role...":"Switch this computer to Client"})]})]}),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:"Remote access"}),e.jsx("h3",{children:"Who may connect?"})]}),e.jsx(Re,{size:20})]}),e.jsx(h,{icon:te,title:"Access mode",description:"Choose the default permission boundary for remote sessions.",recommended:!0,children:e.jsx(U,{value:String(de.accessMode),onChange:d("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(F,{size:20})]}),e.jsx(h,{icon:F,title:"Keyboard and mouse control",description:"Allow Control to send keyboard and pointer input.",recommended:!0,children:e.jsx(x,{checked:!!V.allowKeyboardMouse,onChange:d("control","allowKeyboardMouse"),label:"Keyboard and mouse control"})}),e.jsx(h,{icon:we,title:"Power actions",description:"Allow confirmed sleep, restart, and shut down commands from the Hub.",children:e.jsx(x,{checked:!!V.allowRemoteRestart,onChange:d("control","allowRemoteRestart"),label:"Power actions"})}),e.jsx(h,{icon:q,title:"File transfer",description:"Allow files to be delivered to connected computers.",children:e.jsx(x,{checked:!!B.allowFileTransfer,onChange:d("filesAudio","allowFileTransfer"),label:"File transfer"})}),e.jsx(h,{icon:$,title:"Remote audio",description:"Allow sound capture from connected computers.",children:e.jsx(x,{checked:!!B.allowRemoteAudio,onChange:d("filesAudio","allowRemoteAudio"),label:"Remote audio"})})]})]}),pe=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(q,{size:20})]}),e.jsx(h,{icon:$,title:"Keep a Last 30s buffer",description:"Keep recent video in memory until you explicitly save it.",children:e.jsx(x,{checked:!!B.rollingBufferEnabled,onChange:d("filesAudio","rollingBufferEnabled"),label:"Keep a Last 30s buffer"})}),e.jsx(h,{icon:$,title:"Timelapse interval",description:"Choose how often a timelapse frame is captured.",children:e.jsx(U,{value:Number(B.timelapseIntervalSeconds),onChange:s=>d("filesAudio","timelapseIntervalSeconds")(Number(s)),label:"Timelapse interval",options:[["5","5 seconds"],["10","10 seconds"],["30","30 seconds"],["60","60 seconds"]]})})]}),ie]}),fe=r==="connection"?ge:r==="remote-access"?me:r==="capture-audio"?pe:ne;return e.jsxs("section",{className:"settings-page",children:[e.jsx("div",{className:"settings-page-tabs",role:"tablist","aria-label":"VuvoDesk settings",children:he.map(({id:s,label:u,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}),u]},s))}),re==="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:ue,role:"tabpanel","aria-labelledby":`settings-tab-${r}`,tabIndex:0,children:fe})]})}export{Te as SettingsPage};
|
|
1
|
+
import{j as e}from"./pwa-startup-C8kDd3Vd.js";import{r as i,W as ee,S as te,F as q,b as be,M as F,c as je,L as Re,P as we,A as $}from"./icons-BwhnWKHR.js";import{h as C,w as Se,n as ye}from"./MonitorStackIcon-BLNbbRNY.js";import"./pwa-bootstrap-ljOQTt2e.js";const v={revision:0,settings:{connection:{showThisComputer:!1,temporaryRouterMapping:!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:ee},{id:"remote-access",label:"Remote Access",icon:te},{id:"capture-audio",label:"Capture & Audio",icon:q},{id:"agent",label:"Agent",icon:be}];function A(t,n){return t?.settings?.[n]||v.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 h({icon:t,title:n,description:a,children:m,recommended:l=!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}),l&&e.jsx("em",{children:"Recommended"}),e.jsx("small",{children:a})]})]})}function x({checked:t,onChange:n,label:a}){return e.jsxs("label",{className:"product-switch",children:[e.jsx("input",{"aria-label":a,type:"checkbox",checked:t,onChange:m=>n(m.target.checked)}),e.jsx("span",{})]})}function U({value:t,onChange:n,options:a,label:m}){return e.jsx("select",{"aria-label":m,value:String(t),onChange:l=>n(l.target.value),children:a.map(([l,K])=>e.jsx("option",{value:l,children:K},l))})}function Te({hubUrl:t="",mobileLayout:n=!1,runtimeRole:a="hub",runtimeDeviceId:m="",sessionAccessToken:l="",showThisComputerSetting:K=!0,onShowThisComputerChange:D,initialTab:J="connection",pin:se,agent:ne,captureGallery:ie,desktopUpdate:oe}){const[r,Q]=i.useState(()=>n&&J==="connection"?"remote-access":J),[b,k]=i.useState(null),[re,j]=i.useState("loading"),[G,T]=i.useState(""),[z,E]=i.useState("idle"),[L,H]=i.useState(""),R=i.useRef(null),g=i.useRef(null),p=i.useRef([]),M=i.useRef(Promise.resolve()),ce=i.useRef(0),f=i.useRef(0);i.useEffect(()=>{const s=++f.current;let u=!0;return p.current=[],g.current=null,R.current=null,M.current=Promise.resolve(),j("loading"),C("/api/settings",void 0,t).then(o=>{if(!u||s!==f.current)return;const c=O(o);g.current=c,R.current=c,k(c),j("saved")}).catch(o=>{!u||s!==f.current||(T(o instanceof Error?o.message:String(o)),g.current=v,R.current=v,k(v),j("failed"))}),()=>{u=!1}},[t]);const ae=async(s,u,o)=>{const c={id:++ce.current,section:s,key:u,value:o},I=f.current;p.current.push(c);const X=_(R.current||g.current||v,c);R.current=X,k(X),j("saving"),T(""),M.current=M.current.then(async()=>{if(I!==f.current)return;let S=null,y=null;for(let N=0;N<2&&!S;N+=1){const ve=g.current||v;try{const w=await C("/api/settings",{method:"PATCH",body:JSON.stringify({revision:ve.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(I!==f.current)return;g.current=O(W)}catch(W){y=W;break}}}if(I!==f.current)return;p.current=p.current.filter(N=>N.id!==c.id),S&&(g.current=S);const xe=g.current||v,Y=p.current.reduce(_,xe);R.current=Y,k(Y),S?(T(""),j(p.current.length>0?"saving":"saved")):(j(p.current.length>0?"saving":"failed"),T(y instanceof Error?y.message:String(y||"Settings could not be saved.")))}),await M.current},d=(s,u)=>o=>{ae(s,u,o)},le=async()=>{if(a!=="hub"||!m||!l){E("failed"),H("Sign in to this Hub before changing its runtime role.");return}E("changing"),H("");try{const s=await C("/api/runtime/status",void 0,t);await C("/api/runtime/role",{method:"POST",headers:{Authorization:`Bearer ${l}`},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"),H(s instanceof Error?s.message:String(s))}},de=A(b,"security"),V=A(b,"control"),B=A(b,"filesAudio"),P=A(b,"connection"),ue=`settings-panel-${r}`,he=n?Z.filter(s=>s.id!=="connection"):Z;i.useEffect(()=>{n&&r==="connection"&&Q("remote-access")},[r,n]),i.useEffect(()=>{b&&D?.(!!P.showThisComputer)},[P.showThisComputer,D,b]);const ge=e.jsxs("div",{className:"settings-tab-content product-settings-content",children:[se,oe,a==="hub"&&e.jsx("section",{className:"settings-section-card",children:e.jsx(h,{icon:ee,title:"Help mobile devices connect",description:"Temporarily opens a router port while a direct mobile connection starts, then removes it. Uses no video relay. Requires a compatible router.",children:e.jsx(x,{checked:!!P.temporaryRouterMapping,onChange:d("connection","temporaryRouterMapping"),label:"Help mobile devices connect"})})}),K&&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(F,{size:20})]}),e.jsx(h,{icon:F,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(x,{checked:!!P.showThisComputer,onChange:d("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(je,{size:20})]}),e.jsx("p",{className:"settings-help",children:"Stop hosting from this computer and reconnect it to the selected Hub."}),z==="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:()=>{le()},disabled:z==="changing"||a!=="hub",type:"button",children:z==="changing"?"Switching role...":"Switch this computer to Client"})]})]}),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:"Remote access"}),e.jsx("h3",{children:"Who may connect?"})]}),e.jsx(Re,{size:20})]}),e.jsx(h,{icon:te,title:"Access mode",description:"Choose the default permission boundary for remote sessions.",recommended:!0,children:e.jsx(U,{value:String(de.accessMode),onChange:d("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(F,{size:20})]}),e.jsx(h,{icon:F,title:"Keyboard and mouse control",description:"Allow Control to send keyboard and pointer input.",recommended:!0,children:e.jsx(x,{checked:!!V.allowKeyboardMouse,onChange:d("control","allowKeyboardMouse"),label:"Keyboard and mouse control"})}),e.jsx(h,{icon:we,title:"Power actions",description:"Allow confirmed sleep, restart, and shut down commands from the Hub.",children:e.jsx(x,{checked:!!V.allowRemoteRestart,onChange:d("control","allowRemoteRestart"),label:"Power actions"})}),e.jsx(h,{icon:q,title:"File transfer",description:"Allow files to be delivered to connected computers.",children:e.jsx(x,{checked:!!B.allowFileTransfer,onChange:d("filesAudio","allowFileTransfer"),label:"File transfer"})}),e.jsx(h,{icon:$,title:"Remote audio",description:"Allow sound capture from connected computers.",children:e.jsx(x,{checked:!!B.allowRemoteAudio,onChange:d("filesAudio","allowRemoteAudio"),label:"Remote audio"})})]})]}),pe=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(q,{size:20})]}),e.jsx(h,{icon:$,title:"Keep a Last 30s buffer",description:"Keep recent video in memory until you explicitly save it.",children:e.jsx(x,{checked:!!B.rollingBufferEnabled,onChange:d("filesAudio","rollingBufferEnabled"),label:"Keep a Last 30s buffer"})}),e.jsx(h,{icon:$,title:"Timelapse interval",description:"Choose how often a timelapse frame is captured.",children:e.jsx(U,{value:Number(B.timelapseIntervalSeconds),onChange:s=>d("filesAudio","timelapseIntervalSeconds")(Number(s)),label:"Timelapse interval",options:[["5","5 seconds"],["10","10 seconds"],["30","30 seconds"],["60","60 seconds"]]})})]}),ie]}),fe=r==="connection"?ge:r==="remote-access"?me:r==="capture-audio"?pe:ne;return e.jsxs("section",{className:"settings-page",children:[e.jsx("div",{className:"settings-page-tabs",role:"tablist","aria-label":"VuvoDesk settings",children:he.map(({id:s,label:u,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}),u]},s))}),re==="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:ue,role:"tabpanel","aria-labelledby":`settings-tab-${r}`,tabIndex:0,children:fe})]})}export{Te as SettingsPage};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{j as i}from"./pwa-startup-C8kDd3Vd.js";import"./icons-BwhnWKHR.js";import"./pwa-bootstrap-ljOQTt2e.js";function r({children:t}){return i.jsx("div",{className:"settings-tab-content",children:t})}export{r as PinSettingsTab};
|