@camstack/addon-pipeline 1.2.31 → 1.2.36
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/detection-pipeline/index.js +839 -1013
- package/dist/detection-pipeline/index.mjs +839 -1013
- package/dist/pipeline-runner/index.js +30 -4
- package/dist/pipeline-runner/index.mjs +30 -4
- package/dist/{step-definitions-BkY9_IM6.mjs → step-definitions-C8tk9fPJ.mjs} +11 -2
- package/dist/{step-definitions-gC-Ovglc.js → step-definitions-i8O-hxyI.js} +16 -1
- package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-BUXeX-vb.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-C5m4hC2K.mjs} +3 -3
- package/dist/stream-broker/{hostInit-DJ3h-b1X.mjs → hostInit-WXFrgppm.mjs} +3 -3
- package/dist/stream-broker/remoteEntry.js +1 -1
- package/embed-dist/assets/{MaskShapeCanvas-DI4BY7W2-B0DyP46h.js → MaskShapeCanvas-DI4BY7W2-Dx-Vrpyt.js} +1 -1
- package/embed-dist/assets/{MotionZonesSettings-NcxxQN8r-CzGSy_EO.js → MotionZonesSettings-NcxxQN8r-9D-BWwQP.js} +1 -1
- package/embed-dist/assets/{PrivacyMaskSettings-APgPLF7p-CEgMcOOW.js → PrivacyMaskSettings-APgPLF7p-HvAetfA4.js} +1 -1
- package/embed-dist/assets/{index-CHXOWKHF.js → index-9Ob2YrIf.js} +5 -5
- package/embed-dist/index.html +1 -1
- package/package.json +1 -1
|
@@ -7,7 +7,7 @@ const require_dist = require("../dist-BvFLZyhW.js");
|
|
|
7
7
|
const require_remote_restream = require("../remote-restream-CO36Sr30.js");
|
|
8
8
|
const require_hub_hostname = require("../hub-hostname-DAJXlOgV.js");
|
|
9
9
|
const require_worker_protocol = require("../worker-protocol-DextwlTX.js");
|
|
10
|
-
const require_step_definitions = require("../step-definitions-
|
|
10
|
+
const require_step_definitions = require("../step-definitions-i8O-hxyI.js");
|
|
11
11
|
let node_os = require("node:os");
|
|
12
12
|
node_os = require_chunk.__toESM(node_os);
|
|
13
13
|
let node_child_process = require("node:child_process");
|
|
@@ -2645,6 +2645,28 @@ function pickWeightedLeastLoaded(devices) {
|
|
|
2645
2645
|
});
|
|
2646
2646
|
}
|
|
2647
2647
|
/**
|
|
2648
|
+
* Build the `canRun` predicate for ONE enrichment dispatch. The step and its
|
|
2649
|
+
* enabled descendants ride the SAME `runPipeline` call — one pool, one format
|
|
2650
|
+
* (detail-subtree contract: "its inherited children ride the same call → same
|
|
2651
|
+
* device") — so a format can run the dispatch only when EVERY catalog-known
|
|
2652
|
+
* step in the subtree ships a build for it. Gating only the subtree TOP let a
|
|
2653
|
+
* `face-detection` with a tflite build stay on the Coral while its
|
|
2654
|
+
* `face-embedding` child (no tflite build anywhere) doomed the call.
|
|
2655
|
+
* Unknown/custom addonIds (`getStepDef` → null) have no catalog to gate on
|
|
2656
|
+
* and never block. `getStepDef` is injected — this module stays catalog-free.
|
|
2657
|
+
*/
|
|
2658
|
+
function buildSubtreeCanRun(step, getStepDef) {
|
|
2659
|
+
const defs = [];
|
|
2660
|
+
const walk = (s) => {
|
|
2661
|
+
if (s.enabled === false) return;
|
|
2662
|
+
const def = getStepDef(s.addonId);
|
|
2663
|
+
if (def !== null) defs.push(def);
|
|
2664
|
+
for (const child of s.children ?? []) walk(child);
|
|
2665
|
+
};
|
|
2666
|
+
walk(step);
|
|
2667
|
+
return (format) => defs.every((def) => def.models.some((m) => m.formats[format]));
|
|
2668
|
+
}
|
|
2669
|
+
/**
|
|
2648
2670
|
* Resolve the device one enrichment step runs on. See the module header for the
|
|
2649
2671
|
* decision table. Pure — never throws, no I/O.
|
|
2650
2672
|
*/
|
|
@@ -3727,8 +3749,7 @@ var PipelineRunnerAddon = class extends require_dist.BaseAddon {
|
|
|
3727
3749
|
maxSessions: d.maxSessions,
|
|
3728
3750
|
attachedCameras: attachedByKey.get(d.deviceKey) ?? 0
|
|
3729
3751
|
}));
|
|
3730
|
-
const
|
|
3731
|
-
const canRun = (format) => def === null || def.models.some((m) => m.formats[format]);
|
|
3752
|
+
const canRun = buildSubtreeCanRun(step, tryGetStepDefinition);
|
|
3732
3753
|
const result = resolveStepDevice({
|
|
3733
3754
|
effectiveDeviceKey,
|
|
3734
3755
|
devices,
|
|
@@ -4346,7 +4367,12 @@ var PipelineRunnerAddon = class extends require_dist.BaseAddon {
|
|
|
4346
4367
|
});
|
|
4347
4368
|
} catch (err) {
|
|
4348
4369
|
const msg = require_dist.errMsg(err);
|
|
4349
|
-
log.error("runInference failed", { meta: {
|
|
4370
|
+
log.error("runInference failed", { meta: {
|
|
4371
|
+
error: msg,
|
|
4372
|
+
nodeId: this.nodeId,
|
|
4373
|
+
steps: dispatchSteps.map((s) => s.addonId).join(","),
|
|
4374
|
+
...camConfig?.deviceKey ? { deviceKey: camConfig.deviceKey } : {}
|
|
4375
|
+
} });
|
|
4350
4376
|
return null;
|
|
4351
4377
|
}
|
|
4352
4378
|
}
|
|
@@ -2,7 +2,7 @@ import { B as errMsg, G as createEvent, M as pipelineRunnerCapability, S as defi
|
|
|
2
2
|
import { n as profileForStreamId, t as isRemoteRestream } from "../remote-restream-BeHi78PZ.mjs";
|
|
3
3
|
import { t as resolveHubHostname } from "../hub-hostname-cCknRYKj.mjs";
|
|
4
4
|
import { t as isWorkerReply } from "../worker-protocol-D7RzZIla.mjs";
|
|
5
|
-
import {
|
|
5
|
+
import { o as getStepDefinition } from "../step-definitions-C8tk9fPJ.mjs";
|
|
6
6
|
import * as os from "node:os";
|
|
7
7
|
import { fork } from "node:child_process";
|
|
8
8
|
import { fileURLToPath } from "node:url";
|
|
@@ -2638,6 +2638,28 @@ function pickWeightedLeastLoaded(devices) {
|
|
|
2638
2638
|
});
|
|
2639
2639
|
}
|
|
2640
2640
|
/**
|
|
2641
|
+
* Build the `canRun` predicate for ONE enrichment dispatch. The step and its
|
|
2642
|
+
* enabled descendants ride the SAME `runPipeline` call — one pool, one format
|
|
2643
|
+
* (detail-subtree contract: "its inherited children ride the same call → same
|
|
2644
|
+
* device") — so a format can run the dispatch only when EVERY catalog-known
|
|
2645
|
+
* step in the subtree ships a build for it. Gating only the subtree TOP let a
|
|
2646
|
+
* `face-detection` with a tflite build stay on the Coral while its
|
|
2647
|
+
* `face-embedding` child (no tflite build anywhere) doomed the call.
|
|
2648
|
+
* Unknown/custom addonIds (`getStepDef` → null) have no catalog to gate on
|
|
2649
|
+
* and never block. `getStepDef` is injected — this module stays catalog-free.
|
|
2650
|
+
*/
|
|
2651
|
+
function buildSubtreeCanRun(step, getStepDef) {
|
|
2652
|
+
const defs = [];
|
|
2653
|
+
const walk = (s) => {
|
|
2654
|
+
if (s.enabled === false) return;
|
|
2655
|
+
const def = getStepDef(s.addonId);
|
|
2656
|
+
if (def !== null) defs.push(def);
|
|
2657
|
+
for (const child of s.children ?? []) walk(child);
|
|
2658
|
+
};
|
|
2659
|
+
walk(step);
|
|
2660
|
+
return (format) => defs.every((def) => def.models.some((m) => m.formats[format]));
|
|
2661
|
+
}
|
|
2662
|
+
/**
|
|
2641
2663
|
* Resolve the device one enrichment step runs on. See the module header for the
|
|
2642
2664
|
* decision table. Pure — never throws, no I/O.
|
|
2643
2665
|
*/
|
|
@@ -3720,8 +3742,7 @@ var PipelineRunnerAddon = class extends BaseAddon {
|
|
|
3720
3742
|
maxSessions: d.maxSessions,
|
|
3721
3743
|
attachedCameras: attachedByKey.get(d.deviceKey) ?? 0
|
|
3722
3744
|
}));
|
|
3723
|
-
const
|
|
3724
|
-
const canRun = (format) => def === null || def.models.some((m) => m.formats[format]);
|
|
3745
|
+
const canRun = buildSubtreeCanRun(step, tryGetStepDefinition);
|
|
3725
3746
|
const result = resolveStepDevice({
|
|
3726
3747
|
effectiveDeviceKey,
|
|
3727
3748
|
devices,
|
|
@@ -4339,7 +4360,12 @@ var PipelineRunnerAddon = class extends BaseAddon {
|
|
|
4339
4360
|
});
|
|
4340
4361
|
} catch (err) {
|
|
4341
4362
|
const msg = errMsg(err);
|
|
4342
|
-
log.error("runInference failed", { meta: {
|
|
4363
|
+
log.error("runInference failed", { meta: {
|
|
4364
|
+
error: msg,
|
|
4365
|
+
nodeId: this.nodeId,
|
|
4366
|
+
steps: dispatchSteps.map((s) => s.addonId).join(","),
|
|
4367
|
+
...camConfig?.deviceKey ? { deviceKey: camConfig.deviceKey } : {}
|
|
4368
|
+
} });
|
|
4343
4369
|
return null;
|
|
4344
4370
|
}
|
|
4345
4371
|
}
|
|
@@ -1759,7 +1759,16 @@ function getStepDefinition(stepId) {
|
|
|
1759
1759
|
* build — an unloadable case flagged elsewhere, not resolved here.
|
|
1760
1760
|
*/
|
|
1761
1761
|
function getDefaultModelForFormat(stepId, format) {
|
|
1762
|
-
|
|
1762
|
+
return getDefaultModelForFormatFromDef(getStepDefinition(stepId), format);
|
|
1763
|
+
}
|
|
1764
|
+
/**
|
|
1765
|
+
* {@link getDefaultModelForFormat} over an explicit {@link StepDefinition} —
|
|
1766
|
+
* the def-based seam callers with an INJECTED catalog use
|
|
1767
|
+
* (`resolveDefaultDetectionModel`'s `getStepDef` parameter must flow into the
|
|
1768
|
+
* fallback too, or a test-injected catalog silently falls back to the real
|
|
1769
|
+
* one). Identical resolution order; see the doc above.
|
|
1770
|
+
*/
|
|
1771
|
+
function getDefaultModelForFormatFromDef(def, format) {
|
|
1763
1772
|
const hasFormatBuild = (modelId) => def.models.find((m) => m.id === modelId)?.formats[format] !== void 0;
|
|
1764
1773
|
const declaredForFormat = def.defaultModelIdByFormat?.[format];
|
|
1765
1774
|
if (declaredForFormat !== void 0 && hasFormatBuild(declaredForFormat)) return declaredForFormat;
|
|
@@ -1798,4 +1807,4 @@ function resolveModelForFormat(stepId, chosenModelId, format) {
|
|
|
1798
1807
|
return getDefaultModelForFormat(stepId, format);
|
|
1799
1808
|
}
|
|
1800
1809
|
//#endregion
|
|
1801
|
-
export {
|
|
1810
|
+
export { getStep as a, getDefaultModelForFormatFromDef as i, ALL_STEPS as n, getStepDefinition as o, getDefaultModelForFormat as r, resolveModelForFormat as s, ALL_PIPELINE_STEPS as t };
|
|
@@ -1759,7 +1759,16 @@ function getStepDefinition(stepId) {
|
|
|
1759
1759
|
* build — an unloadable case flagged elsewhere, not resolved here.
|
|
1760
1760
|
*/
|
|
1761
1761
|
function getDefaultModelForFormat(stepId, format) {
|
|
1762
|
-
|
|
1762
|
+
return getDefaultModelForFormatFromDef(getStepDefinition(stepId), format);
|
|
1763
|
+
}
|
|
1764
|
+
/**
|
|
1765
|
+
* {@link getDefaultModelForFormat} over an explicit {@link StepDefinition} —
|
|
1766
|
+
* the def-based seam callers with an INJECTED catalog use
|
|
1767
|
+
* (`resolveDefaultDetectionModel`'s `getStepDef` parameter must flow into the
|
|
1768
|
+
* fallback too, or a test-injected catalog silently falls back to the real
|
|
1769
|
+
* one). Identical resolution order; see the doc above.
|
|
1770
|
+
*/
|
|
1771
|
+
function getDefaultModelForFormatFromDef(def, format) {
|
|
1763
1772
|
const hasFormatBuild = (modelId) => def.models.find((m) => m.id === modelId)?.formats[format] !== void 0;
|
|
1764
1773
|
const declaredForFormat = def.defaultModelIdByFormat?.[format];
|
|
1765
1774
|
if (declaredForFormat !== void 0 && hasFormatBuild(declaredForFormat)) return declaredForFormat;
|
|
@@ -1816,6 +1825,12 @@ Object.defineProperty(exports, "getDefaultModelForFormat", {
|
|
|
1816
1825
|
return getDefaultModelForFormat;
|
|
1817
1826
|
}
|
|
1818
1827
|
});
|
|
1828
|
+
Object.defineProperty(exports, "getDefaultModelForFormatFromDef", {
|
|
1829
|
+
enumerable: true,
|
|
1830
|
+
get: function() {
|
|
1831
|
+
return getDefaultModelForFormatFromDef;
|
|
1832
|
+
}
|
|
1833
|
+
});
|
|
1819
1834
|
Object.defineProperty(exports, "getStep", {
|
|
1820
1835
|
enumerable: true,
|
|
1821
1836
|
get: function() {
|
|
@@ -3,7 +3,7 @@ import "./dist-CYZr2fwk.mjs";
|
|
|
3
3
|
var e = {
|
|
4
4
|
"@camstack/sdk": {
|
|
5
5
|
name: "@camstack/sdk",
|
|
6
|
-
version: "1.2.
|
|
6
|
+
version: "1.2.8",
|
|
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.2.
|
|
21
|
+
version: "1.2.19",
|
|
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.2.
|
|
36
|
+
version: "1.2.15",
|
|
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.2.
|
|
39
|
+
version: "1.2.19",
|
|
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.2.
|
|
48
|
+
version: "1.2.8",
|
|
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.2.
|
|
84
|
+
version: "1.2.15",
|
|
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-C5m4hC2K.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-9Ob2YrIf.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-9Ob2YrIf.js";import{MaskShapeCanvas as u}from"./MaskShapeCanvas-DI4BY7W2-Dx-Vrpyt.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-9Ob2YrIf.js";import{MaskShapeCanvas as te}from"./MaskShapeCanvas-DI4BY7W2-Dx-Vrpyt.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};
|