@camstack/addon-pipeline 1.1.40 → 1.1.41
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/dist/session-decode/decode-worker-child.js +52 -19
- package/dist/session-decode/decode-worker-child.mjs +52 -19
- package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-6I7-nufj.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-C2l0kmD4.mjs} +3 -3
- package/dist/stream-broker/{hostInit-CUkFGqiI.mjs → hostInit-DHaCRMjM.mjs} +3 -3
- package/dist/stream-broker/remoteEntry.js +1 -1
- package/embed-dist/assets/{MaskShapeCanvas-DI4BY7W2-Cr_fCzY5.js → MaskShapeCanvas-DI4BY7W2-B6fza7ic.js} +1 -1
- package/embed-dist/assets/{MotionZonesSettings-NcxxQN8r-COcvoHDH.js → MotionZonesSettings-NcxxQN8r-Cy-4iTog.js} +1 -1
- package/embed-dist/assets/{PrivacyMaskSettings-APgPLF7p-Bv-bbyJl.js → PrivacyMaskSettings-APgPLF7p-CYX33lJb.js} +1 -1
- package/embed-dist/assets/{index-jMj5PyJk.js → index-BPkayx9u.js} +3 -3
- package/embed-dist/assets/index-CSFtK41z.css +2 -0
- package/embed-dist/index.html +2 -2
- package/package.json +1 -1
- package/embed-dist/assets/index-Ctbq9AXh.css +0 -2
|
@@ -191,6 +191,17 @@ var DecodeWorkerChild = class {
|
|
|
191
191
|
nav = null;
|
|
192
192
|
consts = null;
|
|
193
193
|
hwContext = null;
|
|
194
|
+
/**
|
|
195
|
+
* Reused software scaler + the geometry/format key it was built for.
|
|
196
|
+
* Building a fresh `SoftwareScaleContext` on EVERY `toBuffer` (24fps)
|
|
197
|
+
* churned native libav memory unboundedly (a persistent worker grew to
|
|
198
|
+
* ~10GB/h). Detection uses a stable ROI + resize target, so the scaler is
|
|
199
|
+
* built once and reused, rebuilt only when the key changes — mirroring the
|
|
200
|
+
* shared decoder session (`nodeav-decoder-session.ts`, which reuses one
|
|
201
|
+
* `this.scaler` for the same reason). Disposed in `teardown`.
|
|
202
|
+
*/
|
|
203
|
+
scaler = null;
|
|
204
|
+
scalerKey = "";
|
|
194
205
|
demuxer = null;
|
|
195
206
|
decoder = null;
|
|
196
207
|
abortController = null;
|
|
@@ -246,6 +257,9 @@ var DecodeWorkerChild = class {
|
|
|
246
257
|
this.abortController?.abort();
|
|
247
258
|
this.closeInput();
|
|
248
259
|
this.frames.free();
|
|
260
|
+
this.scaler?.[Symbol.dispose]?.();
|
|
261
|
+
this.scaler = null;
|
|
262
|
+
this.scalerKey = "";
|
|
249
263
|
this.hwContext?.[Symbol.dispose]?.();
|
|
250
264
|
this.hwContext = null;
|
|
251
265
|
if (this.pendingPull) {
|
|
@@ -417,28 +431,47 @@ var DecodeWorkerChild = class {
|
|
|
417
431
|
const ySlice = yPlane.subarray(region.top * yStride + region.left);
|
|
418
432
|
const uSlice = uPlane.subarray(region.top / 2 * cStride + region.left / 2);
|
|
419
433
|
const vSlice = vPlane.subarray(region.top / 2 * cStride + region.left / 2);
|
|
434
|
+
const scaler = this.ensureScaler(nav, C, region.width, region.height, target.width, target.height, dstFmt);
|
|
435
|
+
const dstStride = target.width * channels;
|
|
436
|
+
const dstBuffer = Buffer.allocUnsafe(dstStride * target.height);
|
|
437
|
+
const scaledHeight = scaler.scaleSync([
|
|
438
|
+
ySlice,
|
|
439
|
+
uSlice,
|
|
440
|
+
vSlice
|
|
441
|
+
], [
|
|
442
|
+
yStride,
|
|
443
|
+
cStride,
|
|
444
|
+
cStride
|
|
445
|
+
], 0, region.height, [dstBuffer], [dstStride]);
|
|
446
|
+
if (scaledHeight < 0) throw new Error(`sws_scale failed: ${scaledHeight}`);
|
|
447
|
+
if (scaledHeight !== target.height) throw new Error(`scaler produced ${scaledHeight} of ${target.height} rows`);
|
|
448
|
+
return dstBuffer;
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* Build-once / reuse the {@link NavScaler} for a given src+dst geometry and
|
|
452
|
+
* dst format. Rebuilt (old disposed) only when the key changes — detection's
|
|
453
|
+
* ROI + resize target are stable, so this is a per-worker singleton in the
|
|
454
|
+
* steady state. Replaces the previous per-frame `new SoftwareScaleContext()`
|
|
455
|
+
* that leaked native libav memory at frame rate. Synchronous + single-thread
|
|
456
|
+
* (Node), so no epoch/race guard is needed (unlike the async shared session).
|
|
457
|
+
*/
|
|
458
|
+
ensureScaler(nav, C, srcW, srcH, dstW, dstH, dstFmt) {
|
|
459
|
+
const key = `${srcW}x${srcH}->${dstW}x${dstH}:${dstFmt}`;
|
|
460
|
+
const cached = this.scaler;
|
|
461
|
+
if (cached && key === this.scalerKey) return cached;
|
|
462
|
+
this.scaler?.[Symbol.dispose]?.();
|
|
463
|
+
this.scaler = null;
|
|
464
|
+
this.scalerKey = "";
|
|
420
465
|
const scaler = new nav.SoftwareScaleContext();
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
if (initRet < 0) throw new Error(`sws_init_context failed: ${initRet}`);
|
|
425
|
-
const dstStride = target.width * channels;
|
|
426
|
-
const dstBuffer = Buffer.allocUnsafe(dstStride * target.height);
|
|
427
|
-
const scaledHeight = scaler.scaleSync([
|
|
428
|
-
ySlice,
|
|
429
|
-
uSlice,
|
|
430
|
-
vSlice
|
|
431
|
-
], [
|
|
432
|
-
yStride,
|
|
433
|
-
cStride,
|
|
434
|
-
cStride
|
|
435
|
-
], 0, region.height, [dstBuffer], [dstStride]);
|
|
436
|
-
if (scaledHeight < 0) throw new Error(`sws_scale failed: ${scaledHeight}`);
|
|
437
|
-
if (scaledHeight !== target.height) throw new Error(`scaler produced ${scaledHeight} of ${target.height} rows`);
|
|
438
|
-
return dstBuffer;
|
|
439
|
-
} finally {
|
|
466
|
+
scaler.getContext(srcW, srcH, C.AV_PIX_FMT_YUV420P, dstW, dstH, dstFmt, C.SWS_FAST_BILINEAR);
|
|
467
|
+
const initRet = scaler.initContext();
|
|
468
|
+
if (initRet < 0) {
|
|
440
469
|
scaler[Symbol.dispose]?.();
|
|
470
|
+
throw new Error(`sws_init_context failed: ${initRet}`);
|
|
441
471
|
}
|
|
472
|
+
this.scaler = scaler;
|
|
473
|
+
this.scalerKey = key;
|
|
474
|
+
return scaler;
|
|
442
475
|
}
|
|
443
476
|
/**
|
|
444
477
|
* Resolve the HW context ONCE (reused across every re-dial, freed in
|
|
@@ -190,6 +190,17 @@ var DecodeWorkerChild = class {
|
|
|
190
190
|
nav = null;
|
|
191
191
|
consts = null;
|
|
192
192
|
hwContext = null;
|
|
193
|
+
/**
|
|
194
|
+
* Reused software scaler + the geometry/format key it was built for.
|
|
195
|
+
* Building a fresh `SoftwareScaleContext` on EVERY `toBuffer` (24fps)
|
|
196
|
+
* churned native libav memory unboundedly (a persistent worker grew to
|
|
197
|
+
* ~10GB/h). Detection uses a stable ROI + resize target, so the scaler is
|
|
198
|
+
* built once and reused, rebuilt only when the key changes — mirroring the
|
|
199
|
+
* shared decoder session (`nodeav-decoder-session.ts`, which reuses one
|
|
200
|
+
* `this.scaler` for the same reason). Disposed in `teardown`.
|
|
201
|
+
*/
|
|
202
|
+
scaler = null;
|
|
203
|
+
scalerKey = "";
|
|
193
204
|
demuxer = null;
|
|
194
205
|
decoder = null;
|
|
195
206
|
abortController = null;
|
|
@@ -245,6 +256,9 @@ var DecodeWorkerChild = class {
|
|
|
245
256
|
this.abortController?.abort();
|
|
246
257
|
this.closeInput();
|
|
247
258
|
this.frames.free();
|
|
259
|
+
this.scaler?.[Symbol.dispose]?.();
|
|
260
|
+
this.scaler = null;
|
|
261
|
+
this.scalerKey = "";
|
|
248
262
|
this.hwContext?.[Symbol.dispose]?.();
|
|
249
263
|
this.hwContext = null;
|
|
250
264
|
if (this.pendingPull) {
|
|
@@ -416,28 +430,47 @@ var DecodeWorkerChild = class {
|
|
|
416
430
|
const ySlice = yPlane.subarray(region.top * yStride + region.left);
|
|
417
431
|
const uSlice = uPlane.subarray(region.top / 2 * cStride + region.left / 2);
|
|
418
432
|
const vSlice = vPlane.subarray(region.top / 2 * cStride + region.left / 2);
|
|
433
|
+
const scaler = this.ensureScaler(nav, C, region.width, region.height, target.width, target.height, dstFmt);
|
|
434
|
+
const dstStride = target.width * channels;
|
|
435
|
+
const dstBuffer = Buffer.allocUnsafe(dstStride * target.height);
|
|
436
|
+
const scaledHeight = scaler.scaleSync([
|
|
437
|
+
ySlice,
|
|
438
|
+
uSlice,
|
|
439
|
+
vSlice
|
|
440
|
+
], [
|
|
441
|
+
yStride,
|
|
442
|
+
cStride,
|
|
443
|
+
cStride
|
|
444
|
+
], 0, region.height, [dstBuffer], [dstStride]);
|
|
445
|
+
if (scaledHeight < 0) throw new Error(`sws_scale failed: ${scaledHeight}`);
|
|
446
|
+
if (scaledHeight !== target.height) throw new Error(`scaler produced ${scaledHeight} of ${target.height} rows`);
|
|
447
|
+
return dstBuffer;
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* Build-once / reuse the {@link NavScaler} for a given src+dst geometry and
|
|
451
|
+
* dst format. Rebuilt (old disposed) only when the key changes — detection's
|
|
452
|
+
* ROI + resize target are stable, so this is a per-worker singleton in the
|
|
453
|
+
* steady state. Replaces the previous per-frame `new SoftwareScaleContext()`
|
|
454
|
+
* that leaked native libav memory at frame rate. Synchronous + single-thread
|
|
455
|
+
* (Node), so no epoch/race guard is needed (unlike the async shared session).
|
|
456
|
+
*/
|
|
457
|
+
ensureScaler(nav, C, srcW, srcH, dstW, dstH, dstFmt) {
|
|
458
|
+
const key = `${srcW}x${srcH}->${dstW}x${dstH}:${dstFmt}`;
|
|
459
|
+
const cached = this.scaler;
|
|
460
|
+
if (cached && key === this.scalerKey) return cached;
|
|
461
|
+
this.scaler?.[Symbol.dispose]?.();
|
|
462
|
+
this.scaler = null;
|
|
463
|
+
this.scalerKey = "";
|
|
419
464
|
const scaler = new nav.SoftwareScaleContext();
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
if (initRet < 0) throw new Error(`sws_init_context failed: ${initRet}`);
|
|
424
|
-
const dstStride = target.width * channels;
|
|
425
|
-
const dstBuffer = Buffer.allocUnsafe(dstStride * target.height);
|
|
426
|
-
const scaledHeight = scaler.scaleSync([
|
|
427
|
-
ySlice,
|
|
428
|
-
uSlice,
|
|
429
|
-
vSlice
|
|
430
|
-
], [
|
|
431
|
-
yStride,
|
|
432
|
-
cStride,
|
|
433
|
-
cStride
|
|
434
|
-
], 0, region.height, [dstBuffer], [dstStride]);
|
|
435
|
-
if (scaledHeight < 0) throw new Error(`sws_scale failed: ${scaledHeight}`);
|
|
436
|
-
if (scaledHeight !== target.height) throw new Error(`scaler produced ${scaledHeight} of ${target.height} rows`);
|
|
437
|
-
return dstBuffer;
|
|
438
|
-
} finally {
|
|
465
|
+
scaler.getContext(srcW, srcH, C.AV_PIX_FMT_YUV420P, dstW, dstH, dstFmt, C.SWS_FAST_BILINEAR);
|
|
466
|
+
const initRet = scaler.initContext();
|
|
467
|
+
if (initRet < 0) {
|
|
439
468
|
scaler[Symbol.dispose]?.();
|
|
469
|
+
throw new Error(`sws_init_context failed: ${initRet}`);
|
|
440
470
|
}
|
|
471
|
+
this.scaler = scaler;
|
|
472
|
+
this.scalerKey = key;
|
|
473
|
+
return scaler;
|
|
441
474
|
}
|
|
442
475
|
/**
|
|
443
476
|
* Resolve the HW context ONCE (reused across every re-dial, freed in
|
|
@@ -3,7 +3,7 @@ import "./dist-CYZr2fwk.mjs";
|
|
|
3
3
|
var e = {
|
|
4
4
|
"@camstack/sdk": {
|
|
5
5
|
name: "@camstack/sdk",
|
|
6
|
-
version: "1.1.
|
|
6
|
+
version: "1.1.18",
|
|
7
7
|
scope: ["default"],
|
|
8
8
|
loaded: !1,
|
|
9
9
|
from: "addon_stream_broker_widgets",
|
|
@@ -18,7 +18,7 @@ var e = {
|
|
|
18
18
|
},
|
|
19
19
|
"@camstack/types": {
|
|
20
20
|
name: "@camstack/types",
|
|
21
|
-
version: "1.1.
|
|
21
|
+
version: "1.1.31",
|
|
22
22
|
scope: ["default"],
|
|
23
23
|
loaded: !1,
|
|
24
24
|
from: "addon_stream_broker_widgets",
|
|
@@ -33,7 +33,7 @@ var e = {
|
|
|
33
33
|
},
|
|
34
34
|
"@camstack/ui-library": {
|
|
35
35
|
name: "@camstack/ui-library",
|
|
36
|
-
version: "1.1.
|
|
36
|
+
version: "1.1.26",
|
|
37
37
|
scope: ["default"],
|
|
38
38
|
loaded: !1,
|
|
39
39
|
from: "addon_stream_broker_widgets",
|
|
@@ -36,7 +36,7 @@ async function r() {
|
|
|
36
36
|
}
|
|
37
37
|
},
|
|
38
38
|
"@camstack/types": {
|
|
39
|
-
version: "1.1.
|
|
39
|
+
version: "1.1.31",
|
|
40
40
|
scope: "default",
|
|
41
41
|
shareConfig: {
|
|
42
42
|
singleton: !0,
|
|
@@ -45,7 +45,7 @@ async function r() {
|
|
|
45
45
|
}
|
|
46
46
|
},
|
|
47
47
|
"@camstack/sdk": {
|
|
48
|
-
version: "1.1.
|
|
48
|
+
version: "1.1.18",
|
|
49
49
|
scope: "default",
|
|
50
50
|
shareConfig: {
|
|
51
51
|
singleton: !0,
|
|
@@ -81,7 +81,7 @@ async function r() {
|
|
|
81
81
|
}
|
|
82
82
|
},
|
|
83
83
|
"@camstack/ui-library": {
|
|
84
|
-
version: "1.1.
|
|
84
|
+
version: "1.1.26",
|
|
85
85
|
scope: "default",
|
|
86
86
|
shareConfig: {
|
|
87
87
|
singleton: !0,
|
|
@@ -30,7 +30,7 @@ async function d(e) {
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
async function f() {
|
|
33
|
-
return l ||= d(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-
|
|
33
|
+
return l ||= d(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-C2l0kmD4.mjs")).catch((e) => {
|
|
34
34
|
throw l = void 0, e;
|
|
35
35
|
}), l;
|
|
36
36
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{d as e,f as t,g as n,h as r,m as i,p as a}from"./index-
|
|
1
|
+
import{d as e,f as t,g as n,h as r,m as i,p as a}from"./index-BPkayx9u.js";var o=n(t()),s=n(e(),1),c=Math.PI/180;function l(){return typeof window<`u`&&({}.toString.call(window)===`[object Window]`||{}.toString.call(window)===`[object global]`)}var u=typeof global<`u`?global:typeof window<`u`?window:typeof WorkerGlobalScope<`u`?self:{},d={_global:u,version:`10.3.0`,isBrowser:l(),isUnminified:/param/.test(function(e){}.toString()),dblClickWindow:400,getAngle(e){return d.angleDeg?e*c:e},enableTrace:!1,pointerEventsEnabled:!0,autoDrawEnabled:!0,hitOnDragEnabled:!1,capturePointerEventsEnabled:!1,_mouseListenClick:!1,_touchListenClick:!1,_pointerListenClick:!1,_mouseInDblClickWindow:!1,_touchInDblClickWindow:!1,_pointerInDblClickWindow:!1,_mouseDblClickPointerId:null,_touchDblClickPointerId:null,_pointerDblClickPointerId:null,_renderBackend:`web`,legacyTextRendering:!1,pixelRatio:typeof window<`u`&&window.devicePixelRatio||1,dragDistance:3,angleDeg:!0,showWarnings:!0,dragButtons:[0,1],isDragging(){return d.DD.isDragging},isTransforming(){return d.Transformer?.isTransforming()??!1},isDragReady(){return!!d.DD.node},releaseCanvasOnDestroy:!0,document:u.document,_injectGlobal(e){u.Konva!==void 0&&console.error(`Several Konva instances detected. It is not recommended to use multiple Konva instances in the same environment.`),u.Konva=e}},f=e=>{d[e.prototype.getClassName()]=e};d._injectGlobal(d);var p=`Konva.js unsupported environment.
|
|
2
2
|
|
|
3
3
|
Looks like you are trying to use Konva.js in Node.js environment. because "document" object is undefined.
|
|
4
4
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as e,c as t,d as n,f as r,g as i,l as a,o,r as s,s as c,u as l}from"./index-
|
|
1
|
+
import{a as e,c as t,d as n,f as r,g as i,l as a,o,r as s,s as c,u as l}from"./index-BPkayx9u.js";import{MaskShapeCanvas as u}from"./MaskShapeCanvas-DI4BY7W2-B6fza7ic.js";var d=i(r(),1),f=i(n(),1),p=o(`grid-2x2`,[[`path`,{d:`M12 3v18`,key:`108xh3`}],[`path`,{d:`M3 12h18`,key:`1i2n21`}],[`rect`,{x:`3`,y:`3`,width:`18`,height:`18`,rx:`2`,key:`h1oib`}]]),m=110,h=`motion-zones`,g=0,_=[1,2,3],v=1,y=`rounded-md border border-border bg-surface px-2 py-1 text-[11px] font-medium text-foreground-subtle hover:bg-surface-hover disabled:opacity-40 transition-colors`,b=`rounded-md border border-primary/50 bg-primary/15 px-2.5 py-1 text-[11px] font-medium text-primary hover:bg-primary/25 disabled:opacity-40 transition-colors`;function x(e,t,n){let r=t*n,i=Array.from({length:r});for(let t=0;t<r;t+=1)i[t]=e[t]===!0;return i}function S(e,t){if(e.length!==t.length)return!1;for(let n=0;n<e.length;n+=1)if(e[n]!==t[n])return!1;return!0}function C(e,t){return Math.ceil(e/t)}function w(e,t,n){return Math.min(n-1,Math.floor((e+.5)/t*n))}function T(e,t,n,r){let i=C(t,r),a=C(n,r),o=Array.from({length:i*a},()=>!1);for(let r=0;r<n;r+=1){let s=w(r,n,a);for(let n=0;n<t;n+=1)e[r*t+n]===!0&&(o[s*i+w(n,t,i)]=!0)}return o}function E(e,t,n,r){let i=C(t,r),a=C(n,r),o=Array.from({length:t*n},()=>!1);for(let r=0;r<n;r+=1){let s=w(r,n,a);for(let n=0;n<t;n+=1)o[r*t+n]=e[s*i+w(n,t,i)]===!0}return o}function D({deviceId:n}){let r=t(l().trpcClient,n),[i,o]=(0,d.useState)(null),[w,D]=(0,d.useState)(!1),[O,k]=(0,d.useState)(null),[A,j]=(0,d.useState)(null),[M,N]=(0,d.useState)(v),[P,F]=(0,d.useState)(!1),[I,L]=(0,d.useState)(!1),R=(0,d.useRef)(!1);(0,d.useEffect)(()=>{if(!r)return;let e=!1;return R.current=!1,o(null),D(!1),k(null),j(null),N(v),L(!1),(async()=>{try{let t=await r.motionZones?.getOptions({});if(e)return;if(!t)throw Error(`device proxy not ready`);if(o(t),R.current)return;let n=await r.motionZones?.getStatus({});if(e)return;if(!n)throw Error(`device proxy not ready`);R.current=!0;let i=n.regions.find(e=>e.shape.kind===`grid`),a=x(i?i.shape.cells:[],t.grid.width,t.grid.height);j(a),k(T(a,t.grid.width,t.grid.height,v))}catch(t){if(e)return;c(t)?D(!0):console.error(`Motion Zones load failed`,t)}})(),()=>{e=!0}},[r]);let z=i?i.grid.width:0,B=i?i.grid.height:0,V=C(z,M),H=C(B,M),U=(0,d.useMemo)(()=>O&&i?E(O,z,B,M):null,[O,i,z,B,M]),W=(0,d.useMemo)(()=>U!==null&&A!==null&&!S(U,A),[U,A]),G=(0,d.useMemo)(()=>U?U.reduce((e,t)=>t?e+1:e,0):0,[U]),K=z*B,q=V*H,J=(0,d.useCallback)(e=>{q>0&&k(Array.from({length:q},()=>e))},[q]),Y=(0,d.useCallback)(()=>{k(e=>e&&e.map(e=>!e))},[]),X=(0,d.useCallback)(()=>{A&&i&&k(T(A,z,B,M))},[A,i,z,B,M]),Z=(0,d.useCallback)(e=>{e===M||!i||k(t=>{if(!t)return N(e),t;let n=T(E(t,z,B,M),z,B,e);return N(e),n})},[M,i,z,B]),Q=(0,d.useMemo)(()=>i&&O?[{id:g,shape:{kind:`grid`,gridWidth:V,gridHeight:H,cells:[...O]}}]:[],[i,O,V,H]),$=(0,d.useCallback)((e,t)=>{t.kind===`grid`&&k(t.cells)},[]),ee=(0,d.useCallback)(async()=>{if(!(!r||!O||!i)){F(!0);try{let e=E(O,i.grid.width,i.grid.height,M),t={kind:`grid`,gridWidth:i.grid.width,gridHeight:i.grid.height,cells:e};await r.motionZones?.setZone({patch:{regions:[{id:g,enabled:!0,shape:t}]}});let n=await r.motionZones?.getStatus({});if(n){let e=n.regions.find(e=>e.shape.kind===`grid`),t=x(e?e.shape.cells:[],i.grid.width,i.grid.height);j(t),k(T(t,i.grid.width,i.grid.height,M))}}catch(e){console.error(`Motion Zones save failed`,e)}finally{F(!1)}}},[r,O,i,M]);a((0,d.useMemo)(()=>I&&!w&&i&&O?{id:h,order:m,node:(0,f.jsx)(u,{transparent:!0,items:Q,supportedShapes:[`grid`],grid:{width:V,height:H},selectedId:g,onSelect:()=>{},onShapeChange:$,onDrawComplete:()=>{},drawingKind:null})}:null,[I,w,i,O,Q,$,V,H]));let te=!w&&i!==null&&O!==null;return r?(0,f.jsx)(e,{title:`Motion Zones`,icon:(0,f.jsx)(p,{className:`h-3.5 w-3.5 text-foreground-subtle`}),children:(0,f.jsx)(`div`,{className:`flex flex-col gap-3`,children:w?(0,f.jsx)(`p`,{className:`${s} leading-relaxed`,children:`This camera doesn't expose an on-board motion zones grid.`}):te?(0,f.jsxs)(f.Fragment,{children:[(0,f.jsxs)(`p`,{className:`${s} leading-relaxed`,children:[`Toggle `,(0,f.jsx)(`strong`,{className:`text-foreground`,children:`Edit grid`}),` to paint the region directly on the live frame, then `,(0,f.jsx)(`strong`,{className:`text-foreground`,children:`Save`}),` to push the mask to the camera. Pick a bigger`,` `,(0,f.jsx)(`strong`,{className:`text-foreground`,children:`Cell size`}),` for quicker, broad-stroke painting — it's resampled to the camera's native `,i.grid.width,`×`,i.grid.height,` grid on save (×1 is the finest).`]}),(0,f.jsxs)(`div`,{className:`flex items-center gap-2 flex-wrap`,children:[(0,f.jsx)(`button`,{type:`button`,onClick:()=>L(e=>!e),disabled:P,"aria-pressed":I,className:I?b:y,children:I?`Done editing`:`Edit grid`}),(0,f.jsx)(`button`,{type:`button`,onClick:()=>J(!0),disabled:P,className:y,children:`All on`}),(0,f.jsx)(`button`,{type:`button`,onClick:()=>J(!1),disabled:P,className:y,children:`All off`}),(0,f.jsx)(`button`,{type:`button`,onClick:Y,disabled:P,className:y,children:`Invert`}),(0,f.jsxs)(`div`,{className:`flex items-center gap-1 ml-1`,role:`group`,"aria-label":`Cell size`,children:[(0,f.jsx)(`span`,{className:`${s} mr-0.5`,children:`Cell size`}),_.map(e=>(0,f.jsxs)(`button`,{type:`button`,onClick:()=>Z(e),disabled:P,"aria-pressed":M===e,title:e===1?`Camera grid ${z}×${B} (finest)`:`${C(z,e)}×${C(B,e)} painting grid · cells ×${e} bigger`,className:M===e?b:y,children:[`×`,e]},e))]}),(0,f.jsxs)(`span`,{className:`${s} ml-1 tabular-nums`,children:[G,` / `,K,` cells · `,i.grid.width,`×`,i.grid.height,M===1?``:` · paint ${V}×${H}`]}),(0,f.jsx)(`span`,{className:`flex-1`}),(0,f.jsx)(`button`,{type:`button`,onClick:X,disabled:P||!W,className:`rounded-md border border-border bg-surface px-2 py-1 text-[11px] text-foreground-subtle hover:bg-surface-hover disabled:opacity-40 transition-colors`,children:`Revert`}),(0,f.jsx)(`button`,{type:`button`,onClick:()=>void ee(),disabled:P||!W,className:b,children:P?`Saving…`:`Save`})]})]}):(0,f.jsx)(`p`,{className:`${s} leading-relaxed`,children:`Loading the camera's grid…`})})}):null}export{D as MotionZonesSettings};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as e,c as t,d as n,f as r,g as i,i as a,l as o,n as s,o as c,r as l,s as u,t as d,u as ee}from"./index-
|
|
1
|
+
import{a as e,c as t,d as n,f as r,g as i,i as a,l as o,n as s,o as c,r as l,s as u,t as d,u as ee}from"./index-BPkayx9u.js";import{MaskShapeCanvas as te}from"./MaskShapeCanvas-DI4BY7W2-B6fza7ic.js";var f=i(r(),1),p=i(n(),1),m=c(`hexagon`,[[`path`,{d:`M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z`,key:`yt0hxn`}]]),h=120,g=`privacy-mask`,_=`rounded-md border border-border bg-surface px-2 py-1 text-[11px] font-medium text-foreground-subtle hover:bg-surface-hover disabled:opacity-40 transition-colors`,v=`rounded-md border border-primary/50 bg-primary/15 px-2.5 py-1 text-[11px] font-medium text-primary hover:bg-primary/25 disabled:opacity-40 transition-colors`;function y(e){return e.kind===`rect`||e.kind===`polygon`?e:null}function b(e){let t=new Set(e.map(e=>e.id)),n=0;for(;t.has(n);)n+=1;return n}function x(e,t){if(e.length!==t.length)return!1;for(let n=0;n<e.length;n+=1)if(JSON.stringify(e[n])!==JSON.stringify(t[n]))return!1;return!0}function S({deviceId:n}){let r=t(ee().trpcClient,n),[i,c]=(0,f.useState)(null),[S,C]=(0,f.useState)(!1),[w,T]=(0,f.useState)(null),[E,D]=(0,f.useState)(null),[O,k]=(0,f.useState)(!1),[A,j]=(0,f.useState)(!1),[M,N]=(0,f.useState)(null),[P,F]=(0,f.useState)(null),I=(0,f.useRef)(!1);(0,f.useEffect)(()=>{if(!r)return;let e=!1;return I.current=!1,c(null),C(!1),T(null),D(null),j(!1),N(null),F(null),(async()=>{try{let t=await r.privacyMask?.getOptions({});if(e)return;if(!t)throw Error(`device proxy not ready`);if(c(t),I.current)return;let n=await r.privacyMask?.getStatus({});if(e)return;if(!n)throw Error(`device proxy not ready`);I.current=!0;let i={enabled:n.enabled,regions:n.regions};D(i),T(i)}catch(t){if(e)return;u(t)?C(!0):console.error(`Privacy Mask load failed`,t)}})(),()=>{e=!0}},[r]);let L=(0,f.useMemo)(()=>w!==null&&E!==null&&(w.enabled!==E.enabled||!x(w.regions,E.regions)),[w,E]),R=w?w.regions.length:0,z=i?i.maxRegions:0,B=(0,f.useRef)(0);(0,f.useEffect)(()=>{B.current=z},[z]);let V=z>0&&R>=z,H=(0,f.useCallback)(()=>{T(e=>e&&{...e,enabled:!e.enabled})},[]),U=(0,f.useCallback)(e=>{N(typeof e==`number`?e:null)},[]),W=(0,f.useMemo)(()=>w?w.regions.map(e=>({id:e.id,shape:e.shape,enabled:e.enabled,label:`Zone ${String(e.id)}`})):[],[w]),G=(0,f.useCallback)((e,t)=>{let n=y(t);n&&T(t=>t&&{...t,regions:t.regions.map(t=>t.id===e?{...t,shape:n}:t)})},[]),K=(0,f.useCallback)(e=>{let t=y(e);t&&(F(null),T(e=>{if(!e)return e;let n=B.current;if(n>0&&e.regions.length>=n)return e;let r=b(e.regions),i={id:r,enabled:!0,shape:t};return N(r),{...e,regions:[...e.regions,i]}}))},[]),q=(0,f.useCallback)(e=>{j(!0),N(null),F(e)},[]),J=(0,f.useCallback)(e=>{j(!0),F(null),N(e)},[]),Y=(0,f.useCallback)(e=>{N(t=>t===e?null:t),T(t=>t&&{...t,regions:t.regions.filter(t=>t.id!==e)})},[]),X=(0,f.useCallback)(()=>{F(null),N(null),E&&T({enabled:E.enabled,regions:E.regions})},[E]),Z=(0,f.useCallback)(async()=>{if(!(!r||!w)){k(!0);try{await r.privacyMask?.setMask({patch:{enabled:w.enabled,regions:[...w.regions]}});let e=await r.privacyMask?.getStatus({});if(e){let t={enabled:e.enabled,regions:e.regions};D(t),T(t)}}catch(e){console.error(`Privacy Mask save failed`,e)}finally{k(!1)}}},[r,w]),ne=(0,f.useCallback)(()=>{j(e=>(e&&(F(null),N(null)),!e))},[]),Q=i?.supportedShapes??[];o((0,f.useMemo)(()=>A&&!S&&i&&w?{id:g,order:h,node:(0,p.jsx)(te,{transparent:!0,items:W,supportedShapes:Q,polygonVertices:i.polygonVertices,selectedId:M,onSelect:U,onShapeChange:G,onDrawComplete:K,drawingKind:P})}:null,[A,S,i,w,W,Q,M,U,G,K,P]));let re=i?.supportedShapes.includes(`rect`)??!1,ie=i?.supportedShapes.includes(`polygon`)??!1,$=i!==null&&(i.maxRegions<=0||i.supportedShapes.length===0),ae=!S&&!$&&i!==null&&w!==null;return r?(0,p.jsx)(e,{title:`Privacy Mask`,icon:(0,p.jsx)(d,{className:`h-3.5 w-3.5 text-foreground-subtle`}),children:(0,p.jsx)(`div`,{className:`flex flex-col gap-3`,children:S||$?(0,p.jsx)(`p`,{className:`${l} leading-relaxed`,children:`This camera doesn't support an on-board privacy mask.`}):ae?(0,p.jsxs)(p.Fragment,{children:[(0,p.jsxs)(`p`,{className:`${l} leading-relaxed`,children:[`Toggle `,(0,p.jsx)(`strong`,{className:`text-foreground`,children:`Edit mask`}),` to draw blanked-out zones on the live frame, then `,(0,p.jsx)(`strong`,{className:`text-foreground`,children:`Save`}),` to push them to the camera. Drag a rectangle to move, its corner to resize; drag polygon vertices, click an edge midpoint to add one, or right-click a vertex to remove it.`]}),(0,p.jsxs)(`div`,{className:`flex items-center gap-2 flex-wrap`,children:[(0,p.jsx)(`button`,{type:`button`,onClick:ne,disabled:O,"aria-pressed":A,className:A?v:_,children:A?`Done editing`:`Edit mask`}),(0,p.jsx)(`button`,{type:`button`,onClick:H,disabled:O,"aria-pressed":w.enabled,className:w.enabled?v:_,children:w.enabled?`Mask on`:`Mask off`}),re&&(0,p.jsx)(`button`,{type:`button`,onClick:()=>q(`rect`),disabled:O||V,"aria-pressed":P===`rect`,className:P===`rect`?v:_,title:V?`Maximum zones reached`:`Add a rectangle zone`,children:`+ Rect`}),ie&&(0,p.jsx)(`button`,{type:`button`,onClick:()=>q(`polygon`),disabled:O||V,"aria-pressed":P===`polygon`,className:P===`polygon`?v:_,title:V?`Maximum zones reached`:`Add a polygon zone`,children:`+ Polygon`}),(0,p.jsxs)(`span`,{className:`${l} ml-1 tabular-nums`,children:[R,` / `,z,` zones`]}),(0,p.jsx)(`span`,{className:`flex-1`}),(0,p.jsx)(`button`,{type:`button`,onClick:X,disabled:O||!L,className:`rounded-md border border-border bg-surface px-2 py-1 text-[11px] text-foreground-subtle hover:bg-surface-hover disabled:opacity-40 transition-colors`,children:`Revert`}),(0,p.jsx)(`button`,{type:`button`,onClick:()=>void Z(),disabled:O||!L,className:v,children:O?`Saving…`:`Save`})]}),R>0?(0,p.jsx)(`div`,{className:`flex flex-col gap-1`,children:w.regions.map(e=>{let t=M===e.id,n=e.shape.kind===`polygon`?m:s;return(0,p.jsxs)(`div`,{className:`flex items-center gap-2 rounded-md border px-2 py-1 transition-colors ${t?`border-primary/50 bg-primary/10`:`border-border bg-surface`}`,children:[(0,p.jsxs)(`button`,{type:`button`,onClick:()=>J(e.id),disabled:O,className:`flex flex-1 items-center gap-2 text-left text-[11px] font-medium text-foreground-subtle hover:text-foreground disabled:opacity-40 transition-colors`,children:[(0,p.jsx)(n,{className:`h-3.5 w-3.5 shrink-0`}),(0,p.jsxs)(`span`,{children:[`Zone `,e.id]}),(0,p.jsx)(`span`,{className:`text-foreground-faint capitalize`,children:e.shape.kind})]}),(0,p.jsx)(`button`,{type:`button`,onClick:()=>Y(e.id),disabled:O,"aria-label":`Delete zone ${String(e.id)}`,title:`Delete zone`,className:`inline-flex h-6 w-6 items-center justify-center rounded border border-border bg-surface text-foreground-subtle hover:border-red-400/40 hover:bg-red-500/10 hover:text-red-400 disabled:opacity-40 transition-colors`,children:(0,p.jsx)(a,{className:`h-3.5 w-3.5`})})]},e.id)})}):null]}):(0,p.jsx)(`p`,{className:`${l} leading-relaxed`,children:`Loading the camera's privacy mask…`})})}):null}export{S as PrivacyMaskSettings};
|