livedesk 0.1.678 → 0.1.680
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/electron/electron-builder.mac-arm64-dev.yml +3 -0
- package/electron/electron-builder.mac-x64-dev.yml +3 -0
- package/electron/macos-permission-onboarding.mjs +169 -0
- package/electron/main.mjs +15 -1
- package/package.json +1 -1
- package/web/dist/app.html +1 -1
- package/web/dist/app.webmanifest +1 -1
- package/web/dist/assets/{AgentSettingsTab-WHlPq5WO.js → AgentSettingsTab-DRpAmtEB.js} +1 -1
- package/web/dist/assets/{AgentsPage-CdnqnRRy.js → AgentsPage-6cBmEoox.js} +1 -1
- package/web/dist/assets/{CaptureGallery-r0hgHzWE.js → CaptureGallery-D0lGAcNW.js} +1 -1
- package/web/dist/assets/{HubApp-D1-hYJ7F.js → HubApp-k5_04IYv.js} +3 -3
- package/web/dist/assets/{MonitorStackIcon-D1k9mjDe.js → MonitorStackIcon-DDuMtcFd.js} +1 -1
- package/web/dist/assets/{SettingsPage-BML3sxcB.js → SettingsPage-DwinQOF0.js} +1 -1
- package/web/dist/assets/{ShareFilesPage-5yMuAAX8.js → ShareFilesPage-oyaBEwDC.js} +1 -1
- package/web/dist/assets/{SupportPage-BYJoKypB.js → SupportPage-DsOnSA2Z.js} +1 -1
- package/web/dist/assets/{VuvoDeskApp-w5anguIc.js → VuvoDeskApp-DbKDh8Ra.js} +1 -1
- package/web/dist/assets/{app-jQLAg5d2.js → app-BjUA2t1N.js} +2 -2
- package/web/dist/assets/{main-BB-Bb6Vm.js → main-BDc3XoFI.js} +2 -2
- package/web/dist/index.html +2 -2
- package/web/dist/sw.js +2 -2
- package/web/dist/vuvodesk-build-evidence.json +39 -39
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { mkdirSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { dirname, join } from 'node:path';
|
|
3
|
+
|
|
4
|
+
export const VUVODESK_MAC_BUNDLE_IDENTIFIER = 'com.gn.vuvodesk';
|
|
5
|
+
const PERMISSION_MARKER_VERSION = 1;
|
|
6
|
+
|
|
7
|
+
function normalizeScreenStatus(value) {
|
|
8
|
+
const normalized = String(value || '').trim().toLowerCase();
|
|
9
|
+
return ['not-determined', 'granted', 'denied', 'restricted'].includes(normalized)
|
|
10
|
+
? normalized
|
|
11
|
+
: 'unknown';
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function claimOnce(path) {
|
|
15
|
+
try {
|
|
16
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
17
|
+
writeFileSync(path, `${new Date().toISOString()}\n`, {
|
|
18
|
+
encoding: 'utf8',
|
|
19
|
+
flag: 'wx',
|
|
20
|
+
mode: 0o600
|
|
21
|
+
});
|
|
22
|
+
return true;
|
|
23
|
+
} catch (error) {
|
|
24
|
+
if (error?.code === 'EEXIST') return false;
|
|
25
|
+
throw error;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function createMacosPermissionOnboardingOwner({
|
|
30
|
+
desktopCapturer,
|
|
31
|
+
systemPreferences,
|
|
32
|
+
stateRoot,
|
|
33
|
+
runtimeStateDir,
|
|
34
|
+
platform = process.platform,
|
|
35
|
+
isPackaged = false,
|
|
36
|
+
bundleIdentifier = VUVODESK_MAC_BUNDLE_IDENTIFIER,
|
|
37
|
+
log = () => {}
|
|
38
|
+
}) {
|
|
39
|
+
const supported = platform === 'darwin' && isPackaged === true;
|
|
40
|
+
const safeBundleIdentifier = String(bundleIdentifier || '')
|
|
41
|
+
.trim()
|
|
42
|
+
.toLowerCase()
|
|
43
|
+
.replace(/[^a-z0-9.-]/g, '-');
|
|
44
|
+
const markerRoot = join(stateRoot, 'permissions');
|
|
45
|
+
const screenMarkerPath = join(
|
|
46
|
+
markerRoot,
|
|
47
|
+
`macos-screen-recording-${safeBundleIdentifier}-v${PERMISSION_MARKER_VERSION}`
|
|
48
|
+
);
|
|
49
|
+
const accessibilityMarkerPath = join(
|
|
50
|
+
markerRoot,
|
|
51
|
+
`macos-accessibility-${safeBundleIdentifier}-v${PERMISSION_MARKER_VERSION}`
|
|
52
|
+
);
|
|
53
|
+
// RemoteFast is a command-line child and cannot reliably own the GUI app's
|
|
54
|
+
// TCC identity. Keep its legacy one-shot prompt disabled while Electron Main
|
|
55
|
+
// performs the request as the signed VuvoDesk bundle.
|
|
56
|
+
const nativeDesktopScreenMarkerPath = join(
|
|
57
|
+
runtimeStateDir,
|
|
58
|
+
'permissions',
|
|
59
|
+
'macos-screen-recording-requested-desktop-v1'
|
|
60
|
+
);
|
|
61
|
+
let primePromise = null;
|
|
62
|
+
|
|
63
|
+
function readScreenStatus() {
|
|
64
|
+
try {
|
|
65
|
+
return normalizeScreenStatus(systemPreferences?.getMediaAccessStatus?.('screen'));
|
|
66
|
+
} catch {
|
|
67
|
+
return 'unknown';
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function readAccessibilityTrusted() {
|
|
72
|
+
try {
|
|
73
|
+
return systemPreferences?.isTrustedAccessibilityClient?.(false) === true;
|
|
74
|
+
} catch {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function logResult(result) {
|
|
80
|
+
log(
|
|
81
|
+
`macos-permission event=onboarding supported=${result.supported} screenBefore=${result.screenBefore} screenAfter=${result.screenAfter} screenRequested=${result.screenRequested} accessibilityBefore=${result.accessibilityBefore} accessibilityAfter=${result.accessibilityAfter} accessibilityRequested=${result.accessibilityRequested} error=${result.error || 'none'}`,
|
|
82
|
+
{ source: 'macos-permission', level: result.error ? 'warn' : 'info' }
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async function primeCore() {
|
|
87
|
+
if (!supported) {
|
|
88
|
+
const result = {
|
|
89
|
+
supported: false,
|
|
90
|
+
screenBefore: 'unknown',
|
|
91
|
+
screenAfter: 'unknown',
|
|
92
|
+
screenRequested: false,
|
|
93
|
+
accessibilityBefore: false,
|
|
94
|
+
accessibilityAfter: false,
|
|
95
|
+
accessibilityRequested: false,
|
|
96
|
+
error: ''
|
|
97
|
+
};
|
|
98
|
+
logResult(result);
|
|
99
|
+
return result;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
let error = '';
|
|
103
|
+
try {
|
|
104
|
+
claimOnce(nativeDesktopScreenMarkerPath);
|
|
105
|
+
} catch {
|
|
106
|
+
error = 'native-marker-unavailable';
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const screenBefore = readScreenStatus();
|
|
110
|
+
let screenRequested = false;
|
|
111
|
+
if (screenBefore === 'not-determined') {
|
|
112
|
+
try {
|
|
113
|
+
if (claimOnce(screenMarkerPath)) {
|
|
114
|
+
screenRequested = true;
|
|
115
|
+
// A zero-sized thumbnail asks macOS for the signed app permission
|
|
116
|
+
// without retaining a screen image or starting a capture stream.
|
|
117
|
+
await desktopCapturer.getSources({
|
|
118
|
+
types: ['screen'],
|
|
119
|
+
thumbnailSize: { width: 0, height: 0 },
|
|
120
|
+
fetchWindowIcons: false
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
} catch {
|
|
124
|
+
error ||= 'screen-request-failed';
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
const screenAfter = readScreenStatus();
|
|
128
|
+
|
|
129
|
+
const accessibilityBefore = readAccessibilityTrusted();
|
|
130
|
+
let accessibilityAfter = accessibilityBefore;
|
|
131
|
+
let accessibilityRequested = false;
|
|
132
|
+
if (!accessibilityBefore) {
|
|
133
|
+
try {
|
|
134
|
+
if (claimOnce(accessibilityMarkerPath)) {
|
|
135
|
+
accessibilityRequested = true;
|
|
136
|
+
accessibilityAfter = systemPreferences.isTrustedAccessibilityClient(true) === true;
|
|
137
|
+
}
|
|
138
|
+
} catch {
|
|
139
|
+
error ||= 'accessibility-request-failed';
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const result = {
|
|
144
|
+
supported: true,
|
|
145
|
+
screenBefore,
|
|
146
|
+
screenAfter,
|
|
147
|
+
screenRequested,
|
|
148
|
+
accessibilityBefore,
|
|
149
|
+
accessibilityAfter,
|
|
150
|
+
accessibilityRequested,
|
|
151
|
+
error
|
|
152
|
+
};
|
|
153
|
+
logResult(result);
|
|
154
|
+
return result;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function prime() {
|
|
158
|
+
if (!primePromise) primePromise = primeCore();
|
|
159
|
+
return primePromise;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return {
|
|
163
|
+
prime,
|
|
164
|
+
supported,
|
|
165
|
+
screenMarkerPath,
|
|
166
|
+
accessibilityMarkerPath,
|
|
167
|
+
nativeDesktopScreenMarkerPath
|
|
168
|
+
};
|
|
169
|
+
}
|
package/electron/main.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { app, autoUpdater as electronAutoUpdater, BrowserWindow, clipboard, dialog, ipcMain, Menu, nativeImage, powerMonitor, safeStorage, shell, Tray } from 'electron';
|
|
1
|
+
import { app, autoUpdater as electronAutoUpdater, BrowserWindow, clipboard, desktopCapturer, dialog, ipcMain, Menu, nativeImage, powerMonitor, safeStorage, shell, systemPreferences, Tray } from 'electron';
|
|
2
2
|
import { existsSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
3
3
|
import { homedir } from 'node:os';
|
|
4
4
|
import { dirname, join, resolve } from 'node:path';
|
|
@@ -52,6 +52,7 @@ import {
|
|
|
52
52
|
import { createDesktopClipboardOwner } from './desktop-clipboard-owner.mjs';
|
|
53
53
|
import { createRuntimeWindowLoadOwner } from './runtime-window-load-owner.mjs';
|
|
54
54
|
import { createDesktopAutoStartOwner } from './desktop-auto-start.mjs';
|
|
55
|
+
import { createMacosPermissionOnboardingOwner, VUVODESK_MAC_BUNDLE_IDENTIFIER } from './macos-permission-onboarding.mjs';
|
|
55
56
|
|
|
56
57
|
// Chromium otherwise leaves an out-of-process Audio Service (~80-90 MiB on
|
|
57
58
|
// Windows) alive after the exact Remote Audio owner, AudioContext, worklet,
|
|
@@ -1549,6 +1550,19 @@ if (!app.requestSingleInstanceLock()) {
|
|
|
1549
1550
|
log
|
|
1550
1551
|
});
|
|
1551
1552
|
desktopAutoStartOwner.reconcile('startup');
|
|
1553
|
+
const macosPermissionOnboardingOwner = createMacosPermissionOnboardingOwner({
|
|
1554
|
+
desktopCapturer,
|
|
1555
|
+
systemPreferences,
|
|
1556
|
+
stateRoot,
|
|
1557
|
+
runtimeStateDir,
|
|
1558
|
+
isPackaged: app.isPackaged && DESKTOP_BUILD_FLAVOR !== 'e2e',
|
|
1559
|
+
bundleIdentifier: VUVODESK_MAC_BUNDLE_IDENTIFIER,
|
|
1560
|
+
log
|
|
1561
|
+
});
|
|
1562
|
+
// Permission UI cannot hold Hub or Client startup. Marker claims are
|
|
1563
|
+
// synchronous, so RemoteFast cannot race a second TCC request before the
|
|
1564
|
+
// signed Electron Main request settles.
|
|
1565
|
+
void macosPermissionOnboardingOwner.prime();
|
|
1552
1566
|
if (process.argv.includes('--updated')) {
|
|
1553
1567
|
log(
|
|
1554
1568
|
`desktop update event=post-install-startup platform=${process.platform} version=${app.getVersion()} marker=updated`,
|
package/package.json
CHANGED
package/web/dist/app.html
CHANGED
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
.vuvodesk-static-boot [hidden] { display: none; }
|
|
53
53
|
@keyframes vuvodesk-static-boot-spin { to { transform: rotate(360deg); } }
|
|
54
54
|
</style>
|
|
55
|
-
<script type="module" crossorigin src="/assets/app-
|
|
55
|
+
<script type="module" crossorigin src="/assets/app-BjUA2t1N.js" data-vuvodesk-entry></script>
|
|
56
56
|
<link rel="modulepreload" crossorigin href="/assets/preload-helper-DD1OZmLC.js">
|
|
57
57
|
<link rel="modulepreload" crossorigin href="/assets/pwa-bootstrap-ljOQTt2e.js">
|
|
58
58
|
</head>
|
package/web/dist/app.webmanifest
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as t}from"./pwa-startup-DvbrYEQi.js";import{r as c,d as A,S as q,T as I,e as z}from"./icons-CuXJn-Hz.js";import{h as x}from"./MonitorStackIcon-
|
|
1
|
+
import{j as t}from"./pwa-startup-DvbrYEQi.js";import{r as c,d as A,S as q,T as I,e as z}from"./icons-CuXJn-Hz.js";import{h as x}from"./MonitorStackIcon-DDuMtcFd.js";import"./pwa-bootstrap-ljOQTt2e.js";const E={enabled:!0};function w(i){return{enabled:i?.enabled===!0}}async function L(i,p,f){let l=null;for(let s=0;s<2;s+=1){const g=await x("/api/settings",{signal:f},p);if(g.settings.agent?.enabled===i)return;try{await x("/api/settings",{method:"PATCH",signal:f,body:JSON.stringify({revision:g.revision,agent:{enabled:i}})},p);return}catch(a){if(l=a,s!==0||!String(a instanceof Error?a.message:a).startsWith("409 "))throw a}}throw l}function H({hubUrl:i,showToast:p}){const[f,l]=c.useState(E),[s,g]=c.useState(null),[a,m]=c.useState(""),[j,v]=c.useState(""),[y,d]=c.useState(""),b=c.useRef(0),u=c.useRef(null);c.useEffect(()=>{let e=!0;u.current?.abort();const n=new AbortController;u.current=n;const h=++b.current;return g(null),l(E),m(""),d(""),v(""),x("/api/settings/agent",{signal:n.signal},i).then(o=>{!e||n.signal.aborted||h!==b.current||(g(o.settings),l(w(o.settings)))}).catch(o=>{e&&!n.signal.aborted&&h===b.current&&d(o instanceof Error?o.message:String(o))}),()=>{e=!1,n.abort(),u.current===n&&(u.current=null)}},[i]);const k=(e,n)=>l(h=>({...h,[e]:n})),C=e=>{g(e),l(w(e))},S=()=>({generation:b.current,controller:u.current}),r=e=>e.generation===b.current&&e.controller!==null&&e.controller===u.current&&!e.controller.signal.aborted,R=async()=>{if(!s){d("Agent settings are not available yet.");return}const e=S();if(r(e)){m("save"),d(""),v("");try{if(await L(f.enabled,i,e.controller.signal),!r(e))return;const n=await x("/api/settings/agent",{signal:e.controller.signal},i);if(!r(e))return;C(n.settings),v("Codex Agent settings saved.")}catch(n){r(e)&&d(n instanceof Error?n.message:String(n))}finally{r(e)&&m("")}}},T=async()=>{const e=S();if(r(e)){m("test"),d(""),v("");try{const n=await x("/api/settings/agent/test",{method:"POST",signal:e.controller.signal,body:JSON.stringify({})},i);if(!r(e))return;const h=await x("/api/settings/agent",{signal:e.controller.signal},i);if(!r(e))return;C(h.settings);const o=Number.isFinite(n.connection?.latencyMs)?Math.max(0,Math.round(n.connection.latencyMs)):null;p(`Codex Agent connection verified${o!==null?` in ${o} ms.`:"."}`,"success")}catch(n){r(e)&&d(n instanceof Error?n.message:String(n))}finally{r(e)&&m("")}}},D=s?.codexInstallation==="installed"&&s.codexAuth==="signed-in",N=s!==null;return t.jsxs("div",{className:"settings-tab-content agent-settings-content",children:[t.jsxs("section",{className:"settings-section-card agent-enable-card",children:[t.jsxs("label",{className:"settings-toggle agent-enable-toggle",children:[t.jsx("input",{type:"checkbox",checked:f.enabled,onChange:e=>k("enabled",e.target.checked),disabled:!N||a!==""}),t.jsx("span",{children:"Enable Codex Agent"})]}),t.jsxs("p",{className:"settings-help",children:[t.jsx(A,{size:12})," Enabled by default. Agent commands use only the Codex account signed in on this Hub."]})]}),y&&t.jsx("div",{className:"agent-settings-alert error",role:"alert",children:y}),j&&t.jsx("div",{className:"agent-settings-alert success",role:"status",children:j}),t.jsxs("section",{className:"settings-section-card",children:[t.jsxs("div",{className:"settings-section-heading",children:[t.jsxs("div",{children:[t.jsx("span",{children:"Connection"}),t.jsx("h3",{children:"Codex SDK / CLI"})]}),t.jsx(q,{size:20})]}),t.jsxs("div",{className:"agent-connection-row",children:[t.jsx("span",{className:`agent-connection-dot ${D?"connected":s?.codexAuth==="not-signed-in"?"unavailable":""}`}),t.jsx("span",{children:s?.codexInstallation==="not-installed"?"Codex SDK not installed":s?.codexAuth==="signed-in"?"Codex CLI signed in":s?.codexAuth==="not-signed-in"?"Codex CLI sign-in required":"Codex status not tested"}),t.jsxs("button",{className:"settings-reset",onClick:()=>{T()},disabled:a!=="",type:"button",children:[t.jsx(I,{size:15})," ",a==="test"?"Testing":"Test connection"]})]}),t.jsxs("p",{className:"settings-help",children:[t.jsx(A,{size:12})," The Hub uses the installed Codex SDK / CLI to plan approved commands and run them through VuvoDesk Agent tools on selected computers. VuvoDesk never asks for separate credentials."]})]}),t.jsx("div",{className:"settings-action-row agent-settings-actions",children:t.jsxs("button",{className:"text-button primary",onClick:()=>{R()},disabled:!N||a!=="",type:"button",children:[t.jsx(z,{size:15})," ",a==="save"?"Saving":"Save Agent settings"]})})]})}export{H as AgentSettingsTab};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{j as t}from"./pwa-startup-DvbrYEQi.js";import{r as d,ae as ht,af as Ce,z as yt,G as ee,X as xe,ag as vt,ah as wt,ai as Ze,aj as kt,ak as bt,al as Se,b as H,am as Ct,p as xt,an as _e,o as St,ao as jt,S as Je,ap as At,a9 as Rt,c as Nt,aq as Pt,ar as It,A as Tt,as as ue,M as Xe}from"./icons-CuXJn-Hz.js";import{r as Et,h as F}from"./MonitorStackIcon-
|
|
1
|
+
import{j as t}from"./pwa-startup-DvbrYEQi.js";import{r as d,ae as ht,af as Ce,z as yt,G as ee,X as xe,ag as vt,ah as wt,ai as Ze,aj as kt,ak as bt,al as Se,b as H,am as Ct,p as xt,an as _e,o as St,ao as jt,S as Je,ap as At,a9 as Rt,c as Nt,aq as Pt,ar as It,A as Tt,as as ue,M as Xe}from"./icons-CuXJn-Hz.js";import{r as Et,h as F}from"./MonitorStackIcon-DDuMtcFd.js";import"./pwa-bootstrap-ljOQTt2e.js";const Ot=d.forwardRef(function({value:s,onChange:n,onSubmit:r,onOpenSuggestedTasks:i,suggestedOpen:f=!1,suggestedTaskCount:c,disabled:v=!1,placeholder:S="Ask VuvoDesk to work across your machines...",compact:g=!1},x){return t.jsxs("form",{className:"agents-composer",onSubmit:w=>{w.preventDefault(),r()},children:[t.jsx("button",{className:`agents-suggested-trigger ${f?"active":""}`,type:"button","aria-label":c===void 0?"Open Suggested tasks":`Open Suggested tasks (${c} available)`,"aria-expanded":f,onClick:i,disabled:v,children:t.jsx(ht,{size:17})}),t.jsx("textarea",{ref:x,value:s,onChange:w=>n(w.target.value.slice(0,4e3)),placeholder:S,"aria-label":"Ask VuvoDesk",rows:g?1:2,disabled:v}),t.jsxs("button",{className:"agents-run-button",type:"submit",disabled:v||!s.trim(),children:[v?t.jsx(Ce,{className:"spin",size:16}):t.jsx(yt,{size:16}),v?"Running":"Run"]})]})}),$t=["read","processControl","serviceControl","applicationControl","fileRead","fileWrite","fileDelete","shell","script","softwareInstall","network","systemPower","systemConfiguration","userAccount"];function de(e){return e.deviceName?.trim()||e.hostname?.trim()||e.deviceId}function pe(e){return e.connected!==!0?!1:e.synthetic===!0?!0:!e.channels||e.channels.control===!0}function Dt(e){return e==="running"||e==="completed"||e==="failed"||e==="cancelled"?e:"queued"}function _t(e){switch(e){case"process.list":return"Process list";case"system.health":return"System health";case"gpu.status":return"GPU status";case"disk.status":return"Disk status";case"service.status":return"Service status";case"diagnostics.collect":return"Diagnostics";case"process.control":return"Process control";case"service.control":return"Service control";case"application.launch":return"Launch application";case"application.close":return"Close application";case"file.read":return"Read file";case"file.write":return"Write file";case"file.delete":return"Delete file";case"file.list":return"List directory";case"command.run":return"Run command";case"script.run":return"Run script";case"software.install":return"Install software";case"network.status":return"Network status";case"system.power":return"Power action";case"system.configure":return"System configuration";case"logs.collect":return"Collect logs"}}const Mt=64*1024,Me="[Earlier log output hidden by PWA display limit.]",Qe=new TextEncoder,zt=new TextDecoder("utf-8",{fatal:!0}),ze=16*1024,Lt=200,Le="(?:access[_-]?(?:token|key)|refresh[_-]?token|id[_-]?token|pair[_-]?(?:token|key)|authorization|api[_-]?key|private[_-]?key|connection[_-]?string|credential|password|passwd|secret|cookie|set-cookie)",Ft="(?:access[_-]?(?:token|key)|refresh[_-]?token|id[_-]?token|pair[_-]?(?:token|key)|token|authorization|api[_-]?key|private[_-]?key|connection[_-]?string|credential|password|passwd|secret|cookie|set-cookie)",Bt="(?:access[_-]?(?:token|key)|refresh[_-]?token|id[_-]?token|pair[_-]?(?:token|key)|token|authorization|api[_-]?key|credential|password|secret|cookie)",qt=/\b(?:sk-(?:proj-|ant-)?[A-Za-z0-9_-]{8,}|gh[pousr]_[A-Za-z0-9]{8,}|github_pat_[A-Za-z0-9_]{8,}|(?:AKIA|ASIA)[A-Z0-9]{16}|AIza[A-Za-z0-9_-]{35}|npm_[A-Za-z0-9]{8,}|xox[a-z]-[A-Za-z0-9-]{8,}|(?:sk|rk)_(?:live|test)_[A-Za-z0-9]{8,})\b/g;function Ut(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:null}function Fe(e){return Qe.encode(e).byteLength}function Be(e,s){const n=Qe.encode(e);if(n.byteLength<=s)return{value:e,truncated:!1};let r=n.byteLength-s;for(;r<n.byteLength&&(n[r]&192)===128;)r+=1;let i=zt.decode(n.subarray(r));const f=i.indexOf(`
|
|
2
2
|
`);return f>=0&&f<i.length-1&&(i=i.slice(f+1)),{value:i,truncated:!0}}function et(e){return e.replace(/-----BEGIN [^-\r\n]*PRIVATE KEY-----[\s\S]*?-----END [^-\r\n]*PRIVATE KEY-----/gi,"[REDACTED PRIVATE KEY]").replace(/\b(?:proxy-)?authorization\s*[:=]\s*[^\r\n]*|\b(?:set-)?cookie\s*[:=]\s*[^\r\n]*/gi,"credential-header=[REDACTED]").replace(/\bBearer\s+(?:"[^"]*"|'[^']*'|[^\s,;]+)/gi,"Bearer [REDACTED]").replace(new RegExp(`("${Le}"\\s*:\\s*")[^"\\r\\n]*(")`,"gi"),"$1[REDACTED]$2").replace(new RegExp(`('${Le}'\\s*:\\s*')[^'\\r\\n]*(')`,"gi"),"$1[REDACTED]$2").replace(new RegExp(`((?:[A-Za-z0-9.-]+[_-])?${Ft}\\s*[:=]\\s*)(?!\\[REDACTED\\])[^\\s,;&]+`,"gi"),"$1[REDACTED]").replace(new RegExp(`([?&]${Bt}=)[^&\\s]+`,"gi"),"$1[REDACTED]").replace(/\b(?:eyJ|[A-Za-z0-9_-]{8,}\.)[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g,"[REDACTED TOKEN]").replace(qt,"[REDACTED KEY]")}function Gt(e){return typeof e!="string"?"source unknown":et(e).replace(/[\u0000-\u001f\u007f]/g," ").trim().slice(0,64)||"source unknown"}function qe(e){return typeof e=="number"&&Number.isSafeInteger(e)&&e>=0?Math.floor(e):null}function Vt(e){if(typeof e!="string"||e.length===0)return{output:"",displayTruncated:!1};const s=Be(e.replace(/\r\n?/g,`
|
|
3
3
|
`),Mt);let n=et(s.value).replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/g," ").trim(),r=s.truncated;const i=n?n.split(`
|
|
4
4
|
`):[];if(i.length>Lt-1&&(n=i.slice(-199).join(`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as e}from"./pwa-startup-DvbrYEQi.js";import{r as i,R as x,E as j,D as u,f as g,h as f}from"./icons-CuXJn-Hz.js";import{l as b,c as d,d as y}from"./HubApp-
|
|
1
|
+
import{j as e}from"./pwa-startup-DvbrYEQi.js";import{r as i,R as x,E as j,D as u,f as g,h as f}from"./icons-CuXJn-Hz.js";import{l as b,c as d,d as y}from"./HubApp-k5_04IYv.js";import"./pwa-bootstrap-ljOQTt2e.js";import"./preload-helper-DD1OZmLC.js";import"./MonitorStackIcon-DDuMtcFd.js";import"./supabase-C7qjtLN3.js";import"./frame-lifecycle-D91nchvm.js";function z({hubUrl:s,onToast:n}){const[o,m]=i.useState([]),[h,c]=i.useState(!0),r=i.useCallback(async()=>{c(!0);try{m((await b(s)).captures||[])}catch(t){n(t instanceof Error?t.message:String(t))}finally{c(!1)}},[s,n]);i.useEffect(()=>{r()},[r]);const p=async t=>{const a=d(t.id,s);if(navigator.share)try{await navigator.share({title:t.fileName,url:a});return}catch{}window.open(a,"_blank","noopener,noreferrer")};return e.jsxs("section",{className:"capture-gallery",children:[e.jsxs("header",{children:[e.jsxs("div",{children:[e.jsx("span",{className:"settings-eyebrow",children:"Capture Gallery"}),e.jsx("h2",{children:"Saved captures"})]}),e.jsxs("button",{className:"text-button",onClick:()=>{r()},type:"button",children:[e.jsx(x,{size:15})," Refresh"]})]}),h?e.jsx("p",{className:"settings-help",children:"Loading captures..."}):o.length===0?e.jsx("p",{className:"settings-help",children:"No captures saved yet."}):e.jsx("div",{className:"capture-gallery-grid",children:o.map(t=>{const a=d(t.id,s);return e.jsxs("article",{className:"capture-gallery-card",children:[t.mimeType.startsWith("image/")?e.jsx("img",{src:a,alt:t.target.label}):e.jsx("video",{src:a,controls:!0,preload:"metadata"}),e.jsxs("div",{className:"capture-gallery-card-body",children:[e.jsx("strong",{children:t.fileName}),e.jsxs("small",{children:[t.target.label," · ",new Date(t.createdAt).toLocaleString()," · ",Math.ceil(t.sizeBytes/1024)," KB"]}),e.jsxs("div",{children:[e.jsx("button",{className:"icon-button",title:"Open","aria-label":"Open",onClick:()=>window.open(a,"_blank","noopener,noreferrer"),type:"button",children:e.jsx(j,{size:15})}),e.jsx("a",{className:"icon-button",title:"Download","aria-label":"Download",href:`${a}?download=1`,download:t.fileName,children:e.jsx(u,{size:15})}),e.jsx("button",{className:"icon-button",title:"Share","aria-label":"Share",onClick:()=>{p(t)},type:"button",children:e.jsx(g,{size:15})}),e.jsx("button",{className:"icon-button danger",title:"Delete","aria-label":"Delete",onClick:()=>{window.confirm(`Delete ${t.fileName}?`)&&y(t.id,s).then(()=>r()).catch(l=>n(l instanceof Error?l.message:String(l)))},type:"button",children:e.jsx(f,{size:15})})]})]})]},t.id)})})]})}export{z as CaptureGallery};
|