@camstack/addon-pipeline 1.1.15 → 1.1.16
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/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-BnYGzPbK.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-C_-BRUwT.mjs} +1 -1
- package/dist/stream-broker/{hostInit-BUQQ0XCv.mjs → hostInit-CMwPCLAg.mjs} +1 -1
- package/dist/stream-broker/index.js +27 -12
- package/dist/stream-broker/index.mjs +28 -13
- package/dist/stream-broker/remoteEntry.js +1 -1
- package/embed-dist/assets/{MaskShapeCanvas-DI4BY7W2-Bt06M6Ro.js → MaskShapeCanvas-DI4BY7W2-Dtwz1l14.js} +1 -1
- package/embed-dist/assets/{MotionZonesSettings-NcxxQN8r-_uecETOR.js → MotionZonesSettings-NcxxQN8r-CHgwusi0.js} +1 -1
- package/embed-dist/assets/{PrivacyMaskSettings-APgPLF7p--hxwpjE2.js → PrivacyMaskSettings-APgPLF7p-DgE0UI5N.js} +1 -1
- package/embed-dist/assets/{index-7-Kh7maK.js → index-z3LC2BKs.js} +4 -4
- package/embed-dist/index.html +1 -1
- package/package.json +1 -1
|
@@ -7635,6 +7635,17 @@ var StreamBrokerManager = class {
|
|
|
7635
7635
|
* `CapabilityRegistry` lookup, which only worked on the hub.
|
|
7636
7636
|
*/
|
|
7637
7637
|
api = null;
|
|
7638
|
+
/**
|
|
7639
|
+
* This broker node's own Moleculer nodeID (`ctx.kernel.localNodeId`). The
|
|
7640
|
+
* shm frame plane's decoder sessions MUST be co-located on this node — an
|
|
7641
|
+
* shm frame ring is node-local, so a decoder placed on any OTHER node can
|
|
7642
|
+
* never deliver handles to this broker's consumers (the reader's
|
|
7643
|
+
* `shm_open` fails "No such file"). The `decoder` cap is a `singleton`, so
|
|
7644
|
+
* an UNPINNED `createSession` resolves to the cluster-elected active node —
|
|
7645
|
+
* which may be a remote agent. We therefore pin every decode to this local
|
|
7646
|
+
* node. `null` until `setApiAccess` wires it (falls back to unpinned).
|
|
7647
|
+
*/
|
|
7648
|
+
localNodeId = null;
|
|
7638
7649
|
defaultPreBufferSec = 10;
|
|
7639
7650
|
webrtcServer = null;
|
|
7640
7651
|
/**
|
|
@@ -7708,16 +7719,17 @@ var StreamBrokerManager = class {
|
|
|
7708
7719
|
const decoder = this.api["decoder"];
|
|
7709
7720
|
return decoder ? decoder : null;
|
|
7710
7721
|
};
|
|
7722
|
+
const pin = this.localNodeId ? require_dist.nodePin(this.localNodeId) : void 0;
|
|
7711
7723
|
return {
|
|
7712
7724
|
supportsCodec: async (input) => {
|
|
7713
7725
|
const proxy = apiDecoder();
|
|
7714
|
-
if (proxy) return proxy.supportsCodec.query(input);
|
|
7726
|
+
if (proxy) return proxy.supportsCodec.query(input, pin);
|
|
7715
7727
|
if (!localApi) return false;
|
|
7716
7728
|
return localApi.supportsCodec(input);
|
|
7717
7729
|
},
|
|
7718
7730
|
getInfo: async () => {
|
|
7719
7731
|
const proxy = apiDecoder();
|
|
7720
|
-
if (proxy) return proxy.getInfo.query();
|
|
7732
|
+
if (proxy) return proxy.getInfo.query(void 0, pin);
|
|
7721
7733
|
if (!localApi) return {
|
|
7722
7734
|
id: "none",
|
|
7723
7735
|
name: "No decoder"
|
|
@@ -7726,49 +7738,49 @@ var StreamBrokerManager = class {
|
|
|
7726
7738
|
},
|
|
7727
7739
|
createSession: async (config) => {
|
|
7728
7740
|
const proxy = apiDecoder();
|
|
7729
|
-
if (proxy) return proxy.createSession.query(config);
|
|
7741
|
+
if (proxy) return proxy.createSession.query(config, pin);
|
|
7730
7742
|
if (!localApi) throw new Error("No decoder provider available");
|
|
7731
7743
|
return localApi.createSession(config);
|
|
7732
7744
|
},
|
|
7733
7745
|
pushPacket: async (input) => {
|
|
7734
7746
|
const proxy = apiDecoder();
|
|
7735
|
-
if (proxy) return proxy.pushPacket.query(input);
|
|
7747
|
+
if (proxy) return proxy.pushPacket.query(input, pin);
|
|
7736
7748
|
if (!localApi) return;
|
|
7737
7749
|
return localApi.pushPacket(input);
|
|
7738
7750
|
},
|
|
7739
7751
|
pullFrames: async (input) => {
|
|
7740
7752
|
const proxy = apiDecoder();
|
|
7741
|
-
if (proxy) return proxy.pullFrames.query(input);
|
|
7753
|
+
if (proxy) return proxy.pullFrames.query(input, pin);
|
|
7742
7754
|
if (!localApi) return [];
|
|
7743
7755
|
return localApi.pullFrames(input);
|
|
7744
7756
|
},
|
|
7745
7757
|
pullHandles: async (input) => {
|
|
7746
7758
|
const proxy = apiDecoder();
|
|
7747
|
-
if (proxy) return proxy.pullHandles.query(input);
|
|
7759
|
+
if (proxy) return proxy.pullHandles.query(input, pin);
|
|
7748
7760
|
if (!localApi) return [];
|
|
7749
7761
|
return localApi.pullHandles(input);
|
|
7750
7762
|
},
|
|
7751
7763
|
destroySession: async (input) => {
|
|
7752
7764
|
const proxy = apiDecoder();
|
|
7753
|
-
if (proxy) return proxy.destroySession.query(input);
|
|
7765
|
+
if (proxy) return proxy.destroySession.query(input, pin);
|
|
7754
7766
|
if (!localApi) return;
|
|
7755
7767
|
return localApi.destroySession(input);
|
|
7756
7768
|
},
|
|
7757
7769
|
openStream: async (input) => {
|
|
7758
7770
|
const proxy = apiDecoder();
|
|
7759
|
-
if (proxy) return proxy.openStream.query(input);
|
|
7771
|
+
if (proxy) return proxy.openStream.query(input, pin);
|
|
7760
7772
|
if (!localApi) return;
|
|
7761
7773
|
return localApi.openStream(input);
|
|
7762
7774
|
},
|
|
7763
7775
|
updateConfig: async (input) => {
|
|
7764
7776
|
const proxy = apiDecoder();
|
|
7765
|
-
if (proxy) return proxy.updateConfig.query(input);
|
|
7777
|
+
if (proxy) return proxy.updateConfig.query(input, pin);
|
|
7766
7778
|
if (!localApi) return;
|
|
7767
7779
|
return localApi.updateConfig(input);
|
|
7768
7780
|
},
|
|
7769
7781
|
getStats: async (input) => {
|
|
7770
7782
|
const proxy = apiDecoder();
|
|
7771
|
-
if (proxy) return proxy.getStats.query(input);
|
|
7783
|
+
if (proxy) return proxy.getStats.query(input, pin);
|
|
7772
7784
|
if (!localApi) return {
|
|
7773
7785
|
inputFps: 0,
|
|
7774
7786
|
outputFps: 0,
|
|
@@ -7871,8 +7883,9 @@ var StreamBrokerManager = class {
|
|
|
7871
7883
|
* resolve the `decoder` capability via tRPC — see
|
|
7872
7884
|
* `buildDecoderCapApi` for the full rationale.
|
|
7873
7885
|
*/
|
|
7874
|
-
setApiAccess(api) {
|
|
7886
|
+
setApiAccess(api, localNodeId) {
|
|
7875
7887
|
this.api = api;
|
|
7888
|
+
if (localNodeId !== void 0) this.localNodeId = localNodeId;
|
|
7876
7889
|
}
|
|
7877
7890
|
/** Update the system `ffmpeg` config snapshot used by the transcode egress. */
|
|
7878
7891
|
setFfmpegConfig(cfg) {
|
|
@@ -16345,7 +16358,9 @@ var StreamBrokerAddon = class extends require_dist.BaseAddon {
|
|
|
16345
16358
|
this.brokerManager = new StreamBrokerManager(void 0, this.ctx.logger);
|
|
16346
16359
|
this.brokerManager.setDefaultPreBufferSec(this.config.defaultPreBufferSec);
|
|
16347
16360
|
this.brokerManager.setEventBus(this.ctx.eventBus);
|
|
16348
|
-
this.
|
|
16361
|
+
const localNode = this.ctx.kernel.localNodeId;
|
|
16362
|
+
const localNodeId = localNode ? localNode.includes("/") ? localNode.split("/")[0] : localNode : void 0;
|
|
16363
|
+
this.brokerManager.setApiAccess(this.ctx.api, localNodeId);
|
|
16349
16364
|
if (this.capabilities) this.brokerManager.setCapabilitiesAccess(this.capabilities);
|
|
16350
16365
|
await this.loadFfmpegConfig();
|
|
16351
16366
|
const rtspProvider = this.brokerManager.getRtspRestreamProvider();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as __require } from "../chunk-BdkLduGY.mjs";
|
|
2
|
-
import { B as BaseAddon, D as maskUrlCredentials, G as asJsonObject, H as DeviceFeature, I as streamBrokerCapability, Q as parseProfileBrokerId, R as webrtcSessionCapability, U as DeviceType, V as CAM_PROFILE_ORDER, W as EventCategory, X as makeSourceBrokerId, Y as makeProfileBrokerId, c as EncodeProfileSchema, ct as object, dt as union, f as RingBuffer, it as discriminatedUnion, lt as record, m as addonWidgetsSourceCapability, ot as literal, q as createEvent, rt as boolean, st as number, tt as _enum, ut as string, v as cameraStreamsCapability, z as errMsg } from "../dist-CBcVKDyT.mjs";
|
|
2
|
+
import { A as nodePin, B as BaseAddon, D as maskUrlCredentials, G as asJsonObject, H as DeviceFeature, I as streamBrokerCapability, Q as parseProfileBrokerId, R as webrtcSessionCapability, U as DeviceType, V as CAM_PROFILE_ORDER, W as EventCategory, X as makeSourceBrokerId, Y as makeProfileBrokerId, c as EncodeProfileSchema, ct as object, dt as union, f as RingBuffer, it as discriminatedUnion, lt as record, m as addonWidgetsSourceCapability, ot as literal, q as createEvent, rt as boolean, st as number, tt as _enum, ut as string, v as cameraStreamsCapability, z as errMsg } from "../dist-CBcVKDyT.mjs";
|
|
3
3
|
import { t as createFileDataPlaneHandler } from "../model-download-service-C-IHWnXx-3Mmeob3l.mjs";
|
|
4
4
|
import { t as DecodeRuntime } from "../codec-runtime-BsqlEjPi.mjs";
|
|
5
5
|
import { createRequire } from "node:module";
|
|
@@ -7631,6 +7631,17 @@ var StreamBrokerManager = class {
|
|
|
7631
7631
|
* `CapabilityRegistry` lookup, which only worked on the hub.
|
|
7632
7632
|
*/
|
|
7633
7633
|
api = null;
|
|
7634
|
+
/**
|
|
7635
|
+
* This broker node's own Moleculer nodeID (`ctx.kernel.localNodeId`). The
|
|
7636
|
+
* shm frame plane's decoder sessions MUST be co-located on this node — an
|
|
7637
|
+
* shm frame ring is node-local, so a decoder placed on any OTHER node can
|
|
7638
|
+
* never deliver handles to this broker's consumers (the reader's
|
|
7639
|
+
* `shm_open` fails "No such file"). The `decoder` cap is a `singleton`, so
|
|
7640
|
+
* an UNPINNED `createSession` resolves to the cluster-elected active node —
|
|
7641
|
+
* which may be a remote agent. We therefore pin every decode to this local
|
|
7642
|
+
* node. `null` until `setApiAccess` wires it (falls back to unpinned).
|
|
7643
|
+
*/
|
|
7644
|
+
localNodeId = null;
|
|
7634
7645
|
defaultPreBufferSec = 10;
|
|
7635
7646
|
webrtcServer = null;
|
|
7636
7647
|
/**
|
|
@@ -7704,16 +7715,17 @@ var StreamBrokerManager = class {
|
|
|
7704
7715
|
const decoder = this.api["decoder"];
|
|
7705
7716
|
return decoder ? decoder : null;
|
|
7706
7717
|
};
|
|
7718
|
+
const pin = this.localNodeId ? nodePin(this.localNodeId) : void 0;
|
|
7707
7719
|
return {
|
|
7708
7720
|
supportsCodec: async (input) => {
|
|
7709
7721
|
const proxy = apiDecoder();
|
|
7710
|
-
if (proxy) return proxy.supportsCodec.query(input);
|
|
7722
|
+
if (proxy) return proxy.supportsCodec.query(input, pin);
|
|
7711
7723
|
if (!localApi) return false;
|
|
7712
7724
|
return localApi.supportsCodec(input);
|
|
7713
7725
|
},
|
|
7714
7726
|
getInfo: async () => {
|
|
7715
7727
|
const proxy = apiDecoder();
|
|
7716
|
-
if (proxy) return proxy.getInfo.query();
|
|
7728
|
+
if (proxy) return proxy.getInfo.query(void 0, pin);
|
|
7717
7729
|
if (!localApi) return {
|
|
7718
7730
|
id: "none",
|
|
7719
7731
|
name: "No decoder"
|
|
@@ -7722,49 +7734,49 @@ var StreamBrokerManager = class {
|
|
|
7722
7734
|
},
|
|
7723
7735
|
createSession: async (config) => {
|
|
7724
7736
|
const proxy = apiDecoder();
|
|
7725
|
-
if (proxy) return proxy.createSession.query(config);
|
|
7737
|
+
if (proxy) return proxy.createSession.query(config, pin);
|
|
7726
7738
|
if (!localApi) throw new Error("No decoder provider available");
|
|
7727
7739
|
return localApi.createSession(config);
|
|
7728
7740
|
},
|
|
7729
7741
|
pushPacket: async (input) => {
|
|
7730
7742
|
const proxy = apiDecoder();
|
|
7731
|
-
if (proxy) return proxy.pushPacket.query(input);
|
|
7743
|
+
if (proxy) return proxy.pushPacket.query(input, pin);
|
|
7732
7744
|
if (!localApi) return;
|
|
7733
7745
|
return localApi.pushPacket(input);
|
|
7734
7746
|
},
|
|
7735
7747
|
pullFrames: async (input) => {
|
|
7736
7748
|
const proxy = apiDecoder();
|
|
7737
|
-
if (proxy) return proxy.pullFrames.query(input);
|
|
7749
|
+
if (proxy) return proxy.pullFrames.query(input, pin);
|
|
7738
7750
|
if (!localApi) return [];
|
|
7739
7751
|
return localApi.pullFrames(input);
|
|
7740
7752
|
},
|
|
7741
7753
|
pullHandles: async (input) => {
|
|
7742
7754
|
const proxy = apiDecoder();
|
|
7743
|
-
if (proxy) return proxy.pullHandles.query(input);
|
|
7755
|
+
if (proxy) return proxy.pullHandles.query(input, pin);
|
|
7744
7756
|
if (!localApi) return [];
|
|
7745
7757
|
return localApi.pullHandles(input);
|
|
7746
7758
|
},
|
|
7747
7759
|
destroySession: async (input) => {
|
|
7748
7760
|
const proxy = apiDecoder();
|
|
7749
|
-
if (proxy) return proxy.destroySession.query(input);
|
|
7761
|
+
if (proxy) return proxy.destroySession.query(input, pin);
|
|
7750
7762
|
if (!localApi) return;
|
|
7751
7763
|
return localApi.destroySession(input);
|
|
7752
7764
|
},
|
|
7753
7765
|
openStream: async (input) => {
|
|
7754
7766
|
const proxy = apiDecoder();
|
|
7755
|
-
if (proxy) return proxy.openStream.query(input);
|
|
7767
|
+
if (proxy) return proxy.openStream.query(input, pin);
|
|
7756
7768
|
if (!localApi) return;
|
|
7757
7769
|
return localApi.openStream(input);
|
|
7758
7770
|
},
|
|
7759
7771
|
updateConfig: async (input) => {
|
|
7760
7772
|
const proxy = apiDecoder();
|
|
7761
|
-
if (proxy) return proxy.updateConfig.query(input);
|
|
7773
|
+
if (proxy) return proxy.updateConfig.query(input, pin);
|
|
7762
7774
|
if (!localApi) return;
|
|
7763
7775
|
return localApi.updateConfig(input);
|
|
7764
7776
|
},
|
|
7765
7777
|
getStats: async (input) => {
|
|
7766
7778
|
const proxy = apiDecoder();
|
|
7767
|
-
if (proxy) return proxy.getStats.query(input);
|
|
7779
|
+
if (proxy) return proxy.getStats.query(input, pin);
|
|
7768
7780
|
if (!localApi) return {
|
|
7769
7781
|
inputFps: 0,
|
|
7770
7782
|
outputFps: 0,
|
|
@@ -7867,8 +7879,9 @@ var StreamBrokerManager = class {
|
|
|
7867
7879
|
* resolve the `decoder` capability via tRPC — see
|
|
7868
7880
|
* `buildDecoderCapApi` for the full rationale.
|
|
7869
7881
|
*/
|
|
7870
|
-
setApiAccess(api) {
|
|
7882
|
+
setApiAccess(api, localNodeId) {
|
|
7871
7883
|
this.api = api;
|
|
7884
|
+
if (localNodeId !== void 0) this.localNodeId = localNodeId;
|
|
7872
7885
|
}
|
|
7873
7886
|
/** Update the system `ffmpeg` config snapshot used by the transcode egress. */
|
|
7874
7887
|
setFfmpegConfig(cfg) {
|
|
@@ -16341,7 +16354,9 @@ var StreamBrokerAddon = class extends BaseAddon {
|
|
|
16341
16354
|
this.brokerManager = new StreamBrokerManager(void 0, this.ctx.logger);
|
|
16342
16355
|
this.brokerManager.setDefaultPreBufferSec(this.config.defaultPreBufferSec);
|
|
16343
16356
|
this.brokerManager.setEventBus(this.ctx.eventBus);
|
|
16344
|
-
this.
|
|
16357
|
+
const localNode = this.ctx.kernel.localNodeId;
|
|
16358
|
+
const localNodeId = localNode ? localNode.includes("/") ? localNode.split("/")[0] : localNode : void 0;
|
|
16359
|
+
this.brokerManager.setApiAccess(this.ctx.api, localNodeId);
|
|
16345
16360
|
if (this.capabilities) this.brokerManager.setCapabilitiesAccess(this.capabilities);
|
|
16346
16361
|
await this.loadFfmpegConfig();
|
|
16347
16362
|
const rtspProvider = this.brokerManager.getRtspRestreamProvider();
|
|
@@ -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-C_-BRUwT.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-z3LC2BKs.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-z3LC2BKs.js";import{MaskShapeCanvas as u}from"./MaskShapeCanvas-DI4BY7W2-Dtwz1l14.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-z3LC2BKs.js";import{MaskShapeCanvas as te}from"./MaskShapeCanvas-DI4BY7W2-Dtwz1l14.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};
|