@camstack/addon-agent-ui 1.2.313 → 1.2.314
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/CHANGELOG.md +6 -0
- package/dist/.bundle-modules.json +5 -5
- package/dist/addon.js +215 -38
- package/dist/assets/{MotionZonesSettings-B5LVS3-q.js → MotionZonesSettings-Xzz5k30V.js} +1 -1
- package/dist/assets/{PrivacyMaskSettings-DBY2agTe.js → PrivacyMaskSettings-0jO2dKUF.js} +1 -1
- package/dist/assets/{SceneMonitorEditor-Cis_4ZaK.js → SceneMonitorEditor-CN1S0Su1.js} +1 -1
- package/dist/assets/{index-D5vO_ttL.js → index-DlpbU1Jb.js} +15 -15
- package/dist/index.html +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -362,13 +362,13 @@
|
|
|
362
362
|
"server/server/packages/addon-agent-ui/src/updates-panel.tsx": "ec6b5b3701322bbb68dbe581703409cd373418cf9227ce829ea0945e70e60d54",
|
|
363
363
|
"server/server/packages/addon-agent-ui/src/use-pairing-status.ts": "46193a1e83a64250dfff75d417448d74ba0159465e710861b996e903b03e427a",
|
|
364
364
|
"server/server/packages/sdk/dist/index.js": "89409bfb9632c46ed63ee4882c70b7994c1ff90c67d27a5d4b86b0990c41a131",
|
|
365
|
-
"server/server/packages/types/dist/client.mjs": "
|
|
366
|
-
"server/server/packages/types/dist/composition-
|
|
365
|
+
"server/server/packages/types/dist/client.mjs": "9e01dabd3ccf8345ffe626226a594a2543bf48ff2b98441c457c6fa4f417d04a",
|
|
366
|
+
"server/server/packages/types/dist/composition-BDUoQsw9.mjs": "8fef3af56a932116cbb03695f20b3c17a9edf69ec25a1a55cf49fc5cbb3e31ca",
|
|
367
367
|
"server/server/packages/types/dist/device-type-BOWLtoOt.mjs": "cc8447229f79743a89db50f17befd0674934b4c79bc905aa1a7f4e8667453b2c",
|
|
368
368
|
"server/server/packages/types/dist/event-category-BmPm98n0.mjs": "3617fc3941b34f1dcc8ebd3c1360e8c302747400d43e3ab694388496c2bb568d",
|
|
369
|
-
"server/server/packages/types/dist/index.mjs": "
|
|
369
|
+
"server/server/packages/types/dist/index.mjs": "d12022d009587530dfcbf90ac0eccd799ea28926aa42b4c8c4f14eb55f5bad18",
|
|
370
370
|
"server/server/packages/types/dist/node-color.mjs": "942e663074f0a4ed2f8643848ec139eba4b5fd16d0d01c8a23e08a4819a8843b",
|
|
371
|
-
"server/server/packages/types/dist/sleep-
|
|
371
|
+
"server/server/packages/types/dist/sleep-CdJHPm-k.mjs": "9f8cc606eda8ac8b33aacbc6387d378bb1125f6d9c245ef1d3f35ee48256cab6",
|
|
372
372
|
"server/server/packages/ui-library/src/composites/adaptive-downlink.ts": "6e9698e97721461b72a3750f930dd7214d049be865491bfb5a64b87c032b0e22",
|
|
373
373
|
"server/server/packages/ui-library/src/composites/camera-stream-player.tsx": "c04809229b4e091fed09e2bcfe643d6b36cb3a39e294229b49f8a095e4e6ebd3",
|
|
374
374
|
"server/server/packages/ui-library/src/composites/cap-settings/CameraGridLayoutEditor.tsx": "bfe36ccad931ef0981fe24fa315f136d35dbc3164df221346806173447178324",
|
|
@@ -479,7 +479,7 @@
|
|
|
479
479
|
"server/server/packages/ui-library/src/contexts/vod-playback.tsx": "c07bc3ecc786182ef2f27d13bec3f520288e0b47367edd7ddf1c2e7b4a2bbaee",
|
|
480
480
|
"server/server/packages/ui-library/src/contexts/widget-registry.tsx": "71a2815c645abe96821a9e9e5668e321187527d569414f5ca197d615856cc17a",
|
|
481
481
|
"server/server/packages/ui-library/src/contexts/zone-editing.tsx": "275f680304ab09dd747fd9e859dc5aa0535df33eb2d33eb669a6de66bdd848d0",
|
|
482
|
-
"server/server/packages/ui-library/src/generated/system-hooks.ts": "
|
|
482
|
+
"server/server/packages/ui-library/src/generated/system-hooks.ts": "cf09d4a765ce36b589615ca6954d1a01adca02906c950ae03fed218e7ce5c5b7",
|
|
483
483
|
"server/server/packages/ui-library/src/hooks/turn-server-cache.ts": "fab22f069c3761e0d268449e056d9c499b6ea63b879684a40023735b34bad061",
|
|
484
484
|
"server/server/packages/ui-library/src/hooks/use-device-capability.ts": "b74ede60be8039c45f6c712a407ee838ab208610435870ddabaa8598cb7cd7f3",
|
|
485
485
|
"server/server/packages/ui-library/src/hooks/use-device-detections.ts": "61cc54cf2e7f53864e5aa533c05679e4c204c4004a0296f63ab169b003888611",
|
package/dist/addon.js
CHANGED
|
@@ -5840,7 +5840,7 @@ var ZodIssueCode = {
|
|
|
5840
5840
|
var ZodFirstPartyTypeKind;
|
|
5841
5841
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5842
5842
|
//#endregion
|
|
5843
|
-
//#region ../types/dist/sleep-
|
|
5843
|
+
//#region ../types/dist/sleep-CdJHPm-k.mjs
|
|
5844
5844
|
/**
|
|
5845
5845
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5846
5846
|
* window to float samples (D455).
|
|
@@ -5957,7 +5957,7 @@ function isKeychainStoredField(field) {
|
|
|
5957
5957
|
var SECRET_CLEAR = { $secretClear: true };
|
|
5958
5958
|
/** The `'***'` token D634 redaction writes for non-admins. */
|
|
5959
5959
|
var LEGACY_DEVICE_REDACTION = "***";
|
|
5960
|
-
function isRecord$
|
|
5960
|
+
function isRecord$7(value) {
|
|
5961
5961
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5962
5962
|
}
|
|
5963
5963
|
function makeSecretMarker(ref) {
|
|
@@ -5968,12 +5968,12 @@ function makeSecretMarker(ref) {
|
|
|
5968
5968
|
}
|
|
5969
5969
|
/** A stored marker: an object whose `$secret` is a non-empty string. */
|
|
5970
5970
|
function isSecretMarker(value) {
|
|
5971
|
-
if (!isRecord$
|
|
5971
|
+
if (!isRecord$7(value)) return false;
|
|
5972
5972
|
const ref = value["$secret"];
|
|
5973
5973
|
return typeof ref === "string" && ref.length > 0;
|
|
5974
5974
|
}
|
|
5975
5975
|
function isSecretClear(value) {
|
|
5976
|
-
return isRecord$
|
|
5976
|
+
return isRecord$7(value) && value["$secretClear"] === true;
|
|
5977
5977
|
}
|
|
5978
5978
|
/**
|
|
5979
5979
|
* The UI view of a stored secret field value: a marker becomes "set", inline
|
|
@@ -6679,7 +6679,7 @@ var KeychainWriteRefusedError = class extends Error {
|
|
|
6679
6679
|
}
|
|
6680
6680
|
};
|
|
6681
6681
|
var KEEP = { kind: "keep" };
|
|
6682
|
-
function isRecord$
|
|
6682
|
+
function isRecord$6(value) {
|
|
6683
6683
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6684
6684
|
}
|
|
6685
6685
|
function defaultMintId() {
|
|
@@ -6692,7 +6692,7 @@ function collectSecretMarkerRefs(value, out = []) {
|
|
|
6692
6692
|
return out;
|
|
6693
6693
|
}
|
|
6694
6694
|
if (Array.isArray(value)) for (const item of value) collectSecretMarkerRefs(item, out);
|
|
6695
|
-
else if (isRecord$
|
|
6695
|
+
else if (isRecord$6(value)) for (const child of Object.values(value)) collectSecretMarkerRefs(child, out);
|
|
6696
6696
|
return out;
|
|
6697
6697
|
}
|
|
6698
6698
|
async function storedValueEquals(secrets, marker, candidate) {
|
|
@@ -6747,7 +6747,7 @@ function rowId(row, idKey) {
|
|
|
6747
6747
|
return null;
|
|
6748
6748
|
}
|
|
6749
6749
|
async function writeArray(ctx, node, incoming, stored, fieldPath) {
|
|
6750
|
-
const storedRows = Array.isArray(stored) ? stored.filter(isRecord$
|
|
6750
|
+
const storedRows = Array.isArray(stored) ? stored.filter(isRecord$6) : [];
|
|
6751
6751
|
if (!Array.isArray(incoming)) {
|
|
6752
6752
|
ctx.deletes.push(...collectSecretMarkerRefs(storedRows));
|
|
6753
6753
|
return {
|
|
@@ -6763,7 +6763,7 @@ async function writeArray(ctx, node, incoming, stored, fieldPath) {
|
|
|
6763
6763
|
const kept = /* @__PURE__ */ new Set();
|
|
6764
6764
|
const rows = [];
|
|
6765
6765
|
for (const row of incoming) {
|
|
6766
|
-
if (!isRecord$
|
|
6766
|
+
if (!isRecord$6(row)) {
|
|
6767
6767
|
rows.push(row);
|
|
6768
6768
|
continue;
|
|
6769
6769
|
}
|
|
@@ -6788,7 +6788,7 @@ async function writeNode(ctx, node, incoming, stored, fieldPath) {
|
|
|
6788
6788
|
case "leaf": return writeLeaf(ctx, incoming, stored, fieldPath);
|
|
6789
6789
|
case "array": return writeArray(ctx, node, incoming, stored, fieldPath);
|
|
6790
6790
|
case "object": {
|
|
6791
|
-
if (!isRecord$
|
|
6791
|
+
if (!isRecord$6(incoming)) {
|
|
6792
6792
|
if (incoming === void 0) return KEEP;
|
|
6793
6793
|
ctx.deletes.push(...collectSecretMarkerRefs(stored));
|
|
6794
6794
|
return {
|
|
@@ -6796,7 +6796,7 @@ async function writeNode(ctx, node, incoming, stored, fieldPath) {
|
|
|
6796
6796
|
value: incoming
|
|
6797
6797
|
};
|
|
6798
6798
|
}
|
|
6799
|
-
const storedObj = isRecord$
|
|
6799
|
+
const storedObj = isRecord$6(stored) ? stored : {};
|
|
6800
6800
|
return {
|
|
6801
6801
|
kind: "value",
|
|
6802
6802
|
value: await writeMembers(ctx, node.children, incoming, storedObj, (m) => `${fieldPath}.${m}`)
|
|
@@ -6919,7 +6919,7 @@ async function resolveSecretMarkers(value, secrets, options = {}) {
|
|
|
6919
6919
|
value: items
|
|
6920
6920
|
};
|
|
6921
6921
|
}
|
|
6922
|
-
if (isRecord$
|
|
6922
|
+
if (isRecord$6(v)) {
|
|
6923
6923
|
const out = {};
|
|
6924
6924
|
for (const [k, child] of Object.entries(v)) {
|
|
6925
6925
|
const s = substitute(child);
|
|
@@ -6951,7 +6951,7 @@ var SecretOverwriteRefusedError = class extends Error {
|
|
|
6951
6951
|
this.name = "SecretOverwriteRefusedError";
|
|
6952
6952
|
}
|
|
6953
6953
|
};
|
|
6954
|
-
function isRecord$
|
|
6954
|
+
function isRecord$5(value) {
|
|
6955
6955
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6956
6956
|
}
|
|
6957
6957
|
function resolvedValue(pass, marker) {
|
|
@@ -6980,7 +6980,7 @@ function inArray(pass, incoming, stored) {
|
|
|
6980
6980
|
return incoming.map((item, index) => {
|
|
6981
6981
|
const twin = stored[index];
|
|
6982
6982
|
if (isSecretMarker(twin)) return typeof item === "string" && item === resolvedValue(pass, twin) ? twin : item;
|
|
6983
|
-
if (isRecord$
|
|
6983
|
+
if (isRecord$5(item) && isRecord$5(twin)) return inArrayRow(pass, item, twin);
|
|
6984
6984
|
if (Array.isArray(item) && Array.isArray(twin)) return inArray(pass, item, twin);
|
|
6985
6985
|
return item;
|
|
6986
6986
|
});
|
|
@@ -6991,7 +6991,7 @@ function inArrayRow(pass, incoming, stored) {
|
|
|
6991
6991
|
const twin = stored[key];
|
|
6992
6992
|
if (isSecretMarker(twin)) {
|
|
6993
6993
|
if (typeof value === "string" && value === resolvedValue(pass, twin)) out[key] = twin;
|
|
6994
|
-
} else if (isRecord$
|
|
6994
|
+
} else if (isRecord$5(value) && isRecord$5(twin)) out[key] = inArrayRow(pass, value, twin);
|
|
6995
6995
|
else if (Array.isArray(value) && Array.isArray(twin)) out[key] = inArray(pass, value, twin);
|
|
6996
6996
|
}
|
|
6997
6997
|
return out;
|
|
@@ -6999,7 +6999,7 @@ function inArrayRow(pass, incoming, stored) {
|
|
|
6999
6999
|
async function walk(pass, incoming, stored) {
|
|
7000
7000
|
if (isSecretMarker(stored)) return atMarker(pass, incoming, stored);
|
|
7001
7001
|
if (Array.isArray(incoming) && Array.isArray(stored)) return inArray(pass, incoming, stored);
|
|
7002
|
-
if (!isRecord$
|
|
7002
|
+
if (!isRecord$5(incoming) || !isRecord$5(stored)) return incoming;
|
|
7003
7003
|
const out = { ...incoming };
|
|
7004
7004
|
for (const [key, value] of Object.entries(incoming)) out[key] = await walk(pass, value, stored[key]);
|
|
7005
7005
|
return out;
|
|
@@ -7030,7 +7030,7 @@ async function restoreUnchangedSecrets(input) {
|
|
|
7030
7030
|
function isJsonEqual(a, b) {
|
|
7031
7031
|
if (Object.is(a, b)) return true;
|
|
7032
7032
|
if (Array.isArray(a)) return Array.isArray(b) && a.length === b.length && a.every((v, i) => isJsonEqual(v, b[i]));
|
|
7033
|
-
if (isRecord$
|
|
7033
|
+
if (isRecord$5(a) && isRecord$5(b)) {
|
|
7034
7034
|
const keys = Object.keys(a);
|
|
7035
7035
|
if (keys.length !== Object.keys(b).length) return false;
|
|
7036
7036
|
return keys.every((k) => Object.prototype.hasOwnProperty.call(b, k) && isJsonEqual(a[k], b[k]));
|
|
@@ -7054,7 +7054,7 @@ function markerKeysOf(blob, owner) {
|
|
|
7054
7054
|
}
|
|
7055
7055
|
function nodeFromStored(value, owner) {
|
|
7056
7056
|
if (isSecretMarker(value)) return isSecretRefOwnedBy(value.$secret, owner) ? { kind: "leaf" } : null;
|
|
7057
|
-
if (!isRecord$
|
|
7057
|
+
if (!isRecord$5(value)) return null;
|
|
7058
7058
|
const children = /* @__PURE__ */ new Map();
|
|
7059
7059
|
for (const [key, child] of Object.entries(value)) {
|
|
7060
7060
|
const node = nodeFromStored(child, owner);
|
|
@@ -7673,6 +7673,44 @@ var BaseAddon = class {
|
|
|
7673
7673
|
return null;
|
|
7674
7674
|
}
|
|
7675
7675
|
/**
|
|
7676
|
+
* D986 scoped settings: the form shape of the CLUSTER-wide settings one capability this addon
|
|
7677
|
+
* provides owns, or `null` when it has none. `cap` is a capability name the addon's manifest
|
|
7678
|
+
* declares. Stored as `addon-settings` rows `<addonId>.<field>`. The keys of this schema, of
|
|
7679
|
+
* {@link nodeSettingsSchema} and of {@link deviceDefaultsSchema} are disjoint, and a key never
|
|
7680
|
+
* contains `@` (guard `check-scoped-settings-declared`). SHAPE only: values are read by scope.
|
|
7681
|
+
*/
|
|
7682
|
+
async clusterSettingsSchema(_cap) {
|
|
7683
|
+
return null;
|
|
7684
|
+
}
|
|
7685
|
+
/**
|
|
7686
|
+
* D986: the form shape of the settings one capability owns PER NODE, or `null`. Stored as
|
|
7687
|
+
* `addon-settings` rows `<addonId>.<field>@<nodeId>` carrying `nodeId` in the row data, so a
|
|
7688
|
+
* forgotten node's rows go in one central delete.
|
|
7689
|
+
*/
|
|
7690
|
+
async nodeSettingsSchema(_cap) {
|
|
7691
|
+
return null;
|
|
7692
|
+
}
|
|
7693
|
+
/**
|
|
7694
|
+
* D986: the form shape of the FLEET DEFAULTS of the per-device settings one capability owns,
|
|
7695
|
+
* or `null`. Stored as `addon-settings` rows `<addonId>.<field>`; a device resolves its value
|
|
7696
|
+
* as device row, then this default, then the schema default (`resolveDeviceSettings`).
|
|
7697
|
+
*/
|
|
7698
|
+
async deviceDefaultsSchema(_cap) {
|
|
7699
|
+
return null;
|
|
7700
|
+
}
|
|
7701
|
+
/**
|
|
7702
|
+
* The host's read of the scoped declarations: the schema one capability declares for `scope`,
|
|
7703
|
+
* or `null`. Beside {@link getIntegrationFormSchema}, the same shape: the hook is protected, the
|
|
7704
|
+
* host asks this method.
|
|
7705
|
+
*/
|
|
7706
|
+
async getScopedSettingsSchema(scope, cap) {
|
|
7707
|
+
switch (scope) {
|
|
7708
|
+
case "cluster": return this.clusterSettingsSchema(cap);
|
|
7709
|
+
case "node": return this.nodeSettingsSchema(cap);
|
|
7710
|
+
case "device-defaults": return this.deviceDefaultsSchema(cap);
|
|
7711
|
+
}
|
|
7712
|
+
}
|
|
7713
|
+
/**
|
|
7676
7714
|
* What the create wizard and the integration edit page render for one instance: the addon's
|
|
7677
7715
|
* per-instance schema when it declares one, else its global schema (what they always showed).
|
|
7678
7716
|
*/
|
|
@@ -8466,6 +8504,21 @@ function normalizeAddonInitResult(result) {
|
|
|
8466
8504
|
if (Array.isArray(result)) return { providers: result };
|
|
8467
8505
|
return result;
|
|
8468
8506
|
}
|
|
8507
|
+
/** Limits and names of `ctx.records` (D881). One authority; the engine and the facade read it. */
|
|
8508
|
+
/** The files a kind may live in. `history` is device-history's (D850), never records. */
|
|
8509
|
+
var RECORD_DATABASES = ["settings", "events"];
|
|
8510
|
+
/** The classes of a kind: the `@durable` vocabulary, one authority (replaces the annotation). */
|
|
8511
|
+
var RECORD_CLASSES = [
|
|
8512
|
+
"config",
|
|
8513
|
+
"ledger",
|
|
8514
|
+
"audit",
|
|
8515
|
+
"mirror",
|
|
8516
|
+
"ephemeral"
|
|
8517
|
+
];
|
|
8518
|
+
var RECORD_DEFAULT_MAX_DATA_BYTES = 64 * 1024;
|
|
8519
|
+
var RECORD_MAX_DATA_BYTES = 1024 * 1024;
|
|
8520
|
+
var RECORD_BATCH_MAX = 1e3;
|
|
8521
|
+
var RECORD_QUERY_MAX = 1e3;
|
|
8469
8522
|
/**
|
|
8470
8523
|
* The share-view scope kinds a share-link token can carry. The hub mints
|
|
8471
8524
|
* and validates them (`ShareViewGrantSchema` builds its
|
|
@@ -8490,21 +8543,6 @@ var PeerBytesTicketSchema = object({
|
|
|
8490
8543
|
*/
|
|
8491
8544
|
declaredBytes: number().int().nonnegative().nullable()
|
|
8492
8545
|
});
|
|
8493
|
-
/** Limits and names of `ctx.records` (D881). One authority; the engine and the facade read it. */
|
|
8494
|
-
/** The files a kind may live in. `history` is device-history's (D850), never records. */
|
|
8495
|
-
var RECORD_DATABASES = ["settings", "events"];
|
|
8496
|
-
/** The classes of a kind: the `@durable` vocabulary, one authority (replaces the annotation). */
|
|
8497
|
-
var RECORD_CLASSES = [
|
|
8498
|
-
"config",
|
|
8499
|
-
"ledger",
|
|
8500
|
-
"audit",
|
|
8501
|
-
"mirror",
|
|
8502
|
-
"ephemeral"
|
|
8503
|
-
];
|
|
8504
|
-
var RECORD_DEFAULT_MAX_DATA_BYTES = 64 * 1024;
|
|
8505
|
-
var RECORD_MAX_DATA_BYTES = 1024 * 1024;
|
|
8506
|
-
var RECORD_BATCH_MAX = 1e3;
|
|
8507
|
-
var RECORD_QUERY_MAX = 1e3;
|
|
8508
8546
|
/**
|
|
8509
8547
|
* Record kinds (D881): the declaration an addon makes of one kind of fact, the
|
|
8510
8548
|
* Zod row schema that describes it, and the helper that turns the two into the
|
|
@@ -9304,6 +9342,7 @@ var CAP_NAMES = Object.freeze([
|
|
|
9304
9342
|
"humidity-sensor",
|
|
9305
9343
|
"image",
|
|
9306
9344
|
"image-settings",
|
|
9345
|
+
"integration-instances",
|
|
9307
9346
|
"integrations",
|
|
9308
9347
|
"intercom",
|
|
9309
9348
|
"ir-transmitter",
|
|
@@ -11237,7 +11276,7 @@ object({
|
|
|
11237
11276
|
params: record(string(), union([string(), number()])).optional()
|
|
11238
11277
|
});
|
|
11239
11278
|
//#endregion
|
|
11240
|
-
//#region ../types/dist/composition-
|
|
11279
|
+
//#region ../types/dist/composition-BDUoQsw9.mjs
|
|
11241
11280
|
/**
|
|
11242
11281
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
11243
11282
|
*
|
|
@@ -20720,6 +20759,7 @@ var SYSTEM_CAP_VOCABULARY = {
|
|
|
20720
20759
|
"load-contribution": system(INTERNAL),
|
|
20721
20760
|
"local-network": system(NETWORK),
|
|
20722
20761
|
"log-channels": system(INTERNAL),
|
|
20762
|
+
"integration-instances": system(INTERNAL),
|
|
20723
20763
|
"log-destination": system(INTERNAL),
|
|
20724
20764
|
"login-method": system(IDENTITY),
|
|
20725
20765
|
"mesh-network": system(NETWORK),
|
|
@@ -42866,7 +42906,7 @@ var TargetKindCapsSchema = object({
|
|
|
42866
42906
|
* the union is large and not meant for runtime validation here; the exported
|
|
42867
42907
|
* `TargetKind` type re-tightens `configSchema` to `ConfigUISchema`.
|
|
42868
42908
|
*/
|
|
42869
|
-
var ConfigSchemaPassthrough$
|
|
42909
|
+
var ConfigSchemaPassthrough$4 = unknown();
|
|
42870
42910
|
var TargetKindSchema = object({
|
|
42871
42911
|
kind: string(),
|
|
42872
42912
|
label: string(),
|
|
@@ -42903,7 +42943,7 @@ var TargetKindSchema = object({
|
|
|
42903
42943
|
* its raster path, which is the safe default for an unknown image.
|
|
42904
42944
|
*/
|
|
42905
42945
|
iconMediaType: string().optional(),
|
|
42906
|
-
configSchema: ConfigSchemaPassthrough$
|
|
42946
|
+
configSchema: ConfigSchemaPassthrough$4,
|
|
42907
42947
|
/**
|
|
42908
42948
|
* The config keys that decide WHERE this kind's secrets are sent (server,
|
|
42909
42949
|
* base URL, instance, chat, recipient). A save that changes any of them
|
|
@@ -52623,6 +52663,78 @@ method(_void(), array(IntegrationWithStateSchema)), method(object({ id: string()
|
|
|
52623
52663
|
auth: "admin"
|
|
52624
52664
|
});
|
|
52625
52665
|
/**
|
|
52666
|
+
* `integration-instances` - the connection of an addon that holds ONE or SEVERAL
|
|
52667
|
+
* (an account, a relay, a destination) as typed records (D985, D986). The addon's
|
|
52668
|
+
* own function page reads and writes them (Logging for Loki); the Integrations
|
|
52669
|
+
* page lists only the integrations that bring devices (D996).
|
|
52670
|
+
*
|
|
52671
|
+
* A collection of providers: each addon that holds connections registers one and a
|
|
52672
|
+
* caller reaches a provider with the pinned `addonId`.
|
|
52673
|
+
*
|
|
52674
|
+
* Identity: the instance id is immutable and opaque to the caller. A record the
|
|
52675
|
+
* Loki migration made keeps the `integrations` registry id it was created under
|
|
52676
|
+
* (`int_NNNN`); a single instance made by its function page takes the addon id.
|
|
52677
|
+
* `name` is the editable label.
|
|
52678
|
+
*
|
|
52679
|
+
* Secrets: every field the instance kind marks `.meta({ secret: true })` reaches
|
|
52680
|
+
* the form as a `SecretFieldView`, never text (D789). A patch value omitted, `''`
|
|
52681
|
+
* or the redaction token KEEPS the stored secret; `{ $secretClear: true }`
|
|
52682
|
+
* clears it.
|
|
52683
|
+
*/
|
|
52684
|
+
var ConfigSchemaPassthrough$3 = custom();
|
|
52685
|
+
var IntegrationInstanceIdSchema = string().min(1);
|
|
52686
|
+
var IntegrationInstanceDescriptionSchema = object({
|
|
52687
|
+
/** `single`: at most one instance can exist (Loki). `multiple`: an account each. */
|
|
52688
|
+
instanceMode: _enum(["single", "multiple"]),
|
|
52689
|
+
/** What the instance is, for the UI (`destination`, `relay`, `account`). */
|
|
52690
|
+
kind: string(),
|
|
52691
|
+
/** True when `testInstance` really probes the remote. */
|
|
52692
|
+
canTest: boolean()
|
|
52693
|
+
});
|
|
52694
|
+
var IntegrationInstanceStatusSchema = object({
|
|
52695
|
+
state: _enum([
|
|
52696
|
+
"ok",
|
|
52697
|
+
"off",
|
|
52698
|
+
"error",
|
|
52699
|
+
"unknown"
|
|
52700
|
+
]),
|
|
52701
|
+
detail: string().optional()
|
|
52702
|
+
});
|
|
52703
|
+
var IntegrationInstanceSchema = object({
|
|
52704
|
+
id: IntegrationInstanceIdSchema,
|
|
52705
|
+
name: string(),
|
|
52706
|
+
/** The addon's own rule (an URL is present, a client id is present...). */
|
|
52707
|
+
configured: boolean(),
|
|
52708
|
+
/** Values for the instance form; a secret is a `SecretFieldView`, never text. */
|
|
52709
|
+
formValues: record(string(), unknown()),
|
|
52710
|
+
status: IntegrationInstanceStatusSchema.optional()
|
|
52711
|
+
});
|
|
52712
|
+
var IntegrationInstancePatchSchema = object({
|
|
52713
|
+
id: IntegrationInstanceIdSchema,
|
|
52714
|
+
name: string().min(1).optional(),
|
|
52715
|
+
/** Omitted / '' / redaction token keeps a secret; `{ $secretClear: true }` clears it. */
|
|
52716
|
+
values: record(string(), unknown())
|
|
52717
|
+
});
|
|
52718
|
+
method(_void(), IntegrationInstanceDescriptionSchema, { auth: "admin" }), method(object({ id: IntegrationInstanceIdSchema.nullable() }), ConfigSchemaPassthrough$3, { auth: "admin" }), method(_void(), array(IntegrationInstanceSchema).readonly(), { auth: "admin" }), method(object({ id: IntegrationInstanceIdSchema }), IntegrationInstanceSchema.nullable(), { auth: "admin" }), method(object({
|
|
52719
|
+
id: IntegrationInstanceIdSchema,
|
|
52720
|
+
name: string().min(1)
|
|
52721
|
+
}), object({ id: string() }), {
|
|
52722
|
+
kind: "mutation",
|
|
52723
|
+
auth: "admin"
|
|
52724
|
+
}), method(IntegrationInstancePatchSchema, object({ ok: literal(true) }), {
|
|
52725
|
+
kind: "mutation",
|
|
52726
|
+
auth: "admin"
|
|
52727
|
+
}), method(object({ id: IntegrationInstanceIdSchema }), object({ ok: literal(true) }), {
|
|
52728
|
+
kind: "mutation",
|
|
52729
|
+
auth: "admin"
|
|
52730
|
+
}), optionalMethod(object({
|
|
52731
|
+
id: IntegrationInstanceIdSchema.nullable(),
|
|
52732
|
+
values: record(string(), unknown())
|
|
52733
|
+
}), TestConnectionResultSchema$1, {
|
|
52734
|
+
kind: "mutation",
|
|
52735
|
+
auth: "admin"
|
|
52736
|
+
});
|
|
52737
|
+
/**
|
|
52626
52738
|
* Two-way audio / talk-back cap. Clients open a WebRTC audio-only
|
|
52627
52739
|
* session (server-initiated offer pattern, identical to the main
|
|
52628
52740
|
* video WebRTC flow) and the browser captures the mic; the server
|
|
@@ -70323,7 +70435,16 @@ DeviceType.Sensor;
|
|
|
70323
70435
|
* future fields without breaking the existing call sites.
|
|
70324
70436
|
*/
|
|
70325
70437
|
var EmailAddressSchema = email();
|
|
70438
|
+
/**
|
|
70439
|
+
* Which relay of a multi-relay provider answers (D996). Absent = the provider's first / default
|
|
70440
|
+
* relay, so a caller written before relays existed keeps working unchanged. A provider with one
|
|
70441
|
+
* fixed relay ignores it. This is the integration instance id (`int_NNNN`), NOT the addon id: the
|
|
70442
|
+
* collection pin `addonId` still picks the provider, `instanceId` picks the relay inside it.
|
|
70443
|
+
*/
|
|
70444
|
+
var InstanceIdSchema = string().min(1).optional();
|
|
70445
|
+
var RelayPinSchema = object({ instanceId: InstanceIdSchema });
|
|
70326
70446
|
var SendEmailInputSchema = object({
|
|
70447
|
+
instanceId: InstanceIdSchema,
|
|
70327
70448
|
to: union([EmailAddressSchema, array(EmailAddressSchema).min(1)]),
|
|
70328
70449
|
cc: array(EmailAddressSchema).optional(),
|
|
70329
70450
|
bcc: array(EmailAddressSchema).optional(),
|
|
@@ -70359,11 +70480,11 @@ method(SendEmailInputSchema, SendEmailResultSchema, {
|
|
|
70359
70480
|
kind: "mutation",
|
|
70360
70481
|
auth: "admin",
|
|
70361
70482
|
access: "create"
|
|
70362
|
-
}), method(
|
|
70483
|
+
}), method(RelayPinSchema, SmtpStatusSchema, {
|
|
70363
70484
|
kind: "mutation",
|
|
70364
70485
|
auth: "admin",
|
|
70365
70486
|
access: "view"
|
|
70366
|
-
}), method(
|
|
70487
|
+
}), method(RelayPinSchema, SmtpStatusSchema, { auth: "admin" });
|
|
70367
70488
|
/**
|
|
70368
70489
|
* A single device snapshot returned as base64 JPEG/PNG.
|
|
70369
70490
|
*
|
|
@@ -77976,6 +78097,62 @@ Object.freeze({
|
|
|
77976
78097
|
access: "create",
|
|
77977
78098
|
role: "admin"
|
|
77978
78099
|
},
|
|
78100
|
+
"integrationInstances.createInstance": {
|
|
78101
|
+
capName: "integration-instances",
|
|
78102
|
+
capScope: "system",
|
|
78103
|
+
addonId: null,
|
|
78104
|
+
access: "create",
|
|
78105
|
+
role: "admin"
|
|
78106
|
+
},
|
|
78107
|
+
"integrationInstances.deleteInstance": {
|
|
78108
|
+
capName: "integration-instances",
|
|
78109
|
+
capScope: "system",
|
|
78110
|
+
addonId: null,
|
|
78111
|
+
access: "delete",
|
|
78112
|
+
role: "admin"
|
|
78113
|
+
},
|
|
78114
|
+
"integrationInstances.describe": {
|
|
78115
|
+
capName: "integration-instances",
|
|
78116
|
+
capScope: "system",
|
|
78117
|
+
addonId: null,
|
|
78118
|
+
access: "view",
|
|
78119
|
+
role: "admin"
|
|
78120
|
+
},
|
|
78121
|
+
"integrationInstances.getInstance": {
|
|
78122
|
+
capName: "integration-instances",
|
|
78123
|
+
capScope: "system",
|
|
78124
|
+
addonId: null,
|
|
78125
|
+
access: "view",
|
|
78126
|
+
role: "admin"
|
|
78127
|
+
},
|
|
78128
|
+
"integrationInstances.instanceFormSchema": {
|
|
78129
|
+
capName: "integration-instances",
|
|
78130
|
+
capScope: "system",
|
|
78131
|
+
addonId: null,
|
|
78132
|
+
access: "view",
|
|
78133
|
+
role: "admin"
|
|
78134
|
+
},
|
|
78135
|
+
"integrationInstances.listInstances": {
|
|
78136
|
+
capName: "integration-instances",
|
|
78137
|
+
capScope: "system",
|
|
78138
|
+
addonId: null,
|
|
78139
|
+
access: "view",
|
|
78140
|
+
role: "admin"
|
|
78141
|
+
},
|
|
78142
|
+
"integrationInstances.testInstance": {
|
|
78143
|
+
capName: "integration-instances",
|
|
78144
|
+
capScope: "system",
|
|
78145
|
+
addonId: null,
|
|
78146
|
+
access: "create",
|
|
78147
|
+
role: "admin"
|
|
78148
|
+
},
|
|
78149
|
+
"integrationInstances.updateInstance": {
|
|
78150
|
+
capName: "integration-instances",
|
|
78151
|
+
capScope: "system",
|
|
78152
|
+
addonId: null,
|
|
78153
|
+
access: "create",
|
|
78154
|
+
role: "admin"
|
|
78155
|
+
},
|
|
77979
78156
|
"integrations.create": {
|
|
77980
78157
|
capName: "integrations",
|
|
77981
78158
|
capScope: "system",
|
|
@@ -89281,7 +89458,7 @@ var AgentUIAddon = class extends BaseAddon {
|
|
|
89281
89458
|
capability: adminUiCapability,
|
|
89282
89459
|
provider: {
|
|
89283
89460
|
getStaticDir: async () => ({ staticDir: path.resolve(__dirname) }),
|
|
89284
|
-
getVersion: async () => ({ version: "1.2.
|
|
89461
|
+
getVersion: async () => ({ version: "1.2.314" })
|
|
89285
89462
|
}
|
|
89286
89463
|
}];
|
|
89287
89464
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as e,i as t,l as n,n as r,o as i}from"./scheduler-0XZJE03d.js";import{c as a,d as o,g as s,l as c,p as l,t as u,w as d}from"./index-
|
|
1
|
+
import{a as e,i as t,l as n,n as r,o as i}from"./scheduler-0XZJE03d.js";import{c as a,d as o,g as s,l as c,p as l,t as u,w as d}from"./index-DlpbU1Jb.js";import{MaskShapeCanvas as f}from"./MaskShapeCanvas-BTvl6Rin.js";var p=d(`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=n(i(),1),h=n(e(),1),g=110,_=`motion-zones`,v=0,y=[1,2,3],b=1,x=`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`,S=`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 C(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 w(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 T(e,t){return Math.ceil(e/t)}function E(e,t,n){return Math.min(n-1,Math.floor((e+.5)/t*n))}function D(e,t,n,r){let i=T(t,r),a=T(n,r),o=Array.from({length:i*a},()=>!1);for(let r=0;r<n;r+=1){let s=E(r,n,a);for(let n=0;n<t;n+=1)e[r*t+n]===!0&&(o[s*i+E(n,t,i)]=!0)}return o}function O(e,t,n,r){let i=T(t,r),a=T(n,r),o=Array.from({length:t*n},()=>!1);for(let r=0;r<n;r+=1){let s=E(r,n,a);for(let n=0;n<t;n+=1)o[r*t+n]=e[s*i+E(n,t,i)]===!0}return o}function k({deviceId:e}){let n=t(),i=o(s().trpcClient,e),[d,E]=(0,m.useState)(null),[k,A]=(0,m.useState)(!1),[j,M]=(0,m.useState)(null),[N,P]=(0,m.useState)(null),[F,I]=(0,m.useState)(b),[L,R]=(0,m.useState)(!1),[z,B]=(0,m.useState)(!1),V=(0,m.useRef)(!1);(0,m.useEffect)(()=>{if(!i)return;let e=!1;return V.current=!1,E(null),A(!1),M(null),P(null),I(b),B(!1),(async()=>{try{let t=await i.motionZones?.getOptions({});if(e)return;if(!t)throw Error(`device proxy not ready`);if(E(t),V.current)return;let n=await i.motionZones?.getStatus({});if(e)return;if(!n)throw Error(`device proxy not ready`);V.current=!0;let r=n.regions.find(e=>e.shape.kind===`grid`),a=C(r?r.shape.cells:[],t.grid.width,t.grid.height);P(a),M(D(a,t.grid.width,t.grid.height,b))}catch(t){if(e)return;c(t)?A(!0):console.error(`Motion Zones load failed`,t)}})(),()=>{e=!0}},[i]);let H=d?d.grid.width:0,U=d?d.grid.height:0,W=T(H,F),G=T(U,F),K=(0,m.useMemo)(()=>j&&d?O(j,H,U,F):null,[j,d,H,U,F]),q=(0,m.useMemo)(()=>K!==null&&N!==null&&!w(K,N),[K,N]),J=(0,m.useMemo)(()=>K?K.reduce((e,t)=>t?e+1:e,0):0,[K]),Y=H*U,X=W*G,Z=(0,m.useCallback)(e=>{X>0&&M(Array.from({length:X},()=>e))},[X]),ee=(0,m.useCallback)(()=>{M(e=>e&&e.map(e=>!e))},[]),te=(0,m.useCallback)(()=>{N&&d&&M(D(N,H,U,F))},[N,d,H,U,F]),ne=(0,m.useCallback)(e=>{e===F||!d||M(t=>{if(!t)return I(e),t;let n=D(O(t,H,U,F),H,U,e);return I(e),n})},[F,d,H,U]),Q=(0,m.useMemo)(()=>d&&j?[{id:v,shape:{kind:`grid`,gridWidth:W,gridHeight:G,cells:[...j]}}]:[],[d,j,W,G]),$=(0,m.useCallback)((e,t)=>{t.kind===`grid`&&M(t.cells)},[]),re=(0,m.useCallback)(async()=>{if(!(!i||!j||!d)){R(!0);try{let e=O(j,d.grid.width,d.grid.height,F),t={kind:`grid`,gridWidth:d.grid.width,gridHeight:d.grid.height,cells:e};await i.motionZones?.setZone({patch:{regions:[{id:v,enabled:!0,shape:t}]}});let n=await i.motionZones?.getStatus({});if(n){let e=n.regions.find(e=>e.shape.kind===`grid`),t=C(e?e.shape.cells:[],d.grid.width,d.grid.height);P(t),M(D(t,d.grid.width,d.grid.height,F))}}catch(e){console.error(`Motion Zones save failed`,e)}finally{R(!1)}}},[i,j,d,F]);u((0,m.useMemo)(()=>z&&!k&&d&&j?{id:_,order:g,node:(0,h.jsx)(f,{transparent:!0,items:Q,supportedShapes:[`grid`],grid:{width:W,height:G},selectedId:v,onSelect:()=>{},onShapeChange:$,onDrawComplete:()=>{},drawingKind:null})}:null,[z,k,d,j,Q,$,W,G]));let ie=!k&&d!==null&&j!==null;return i?(0,h.jsx)(l,{title:n(`uiLibrary.motionZones.title`,`Motion Zones`),icon:(0,h.jsx)(p,{className:`h-3.5 w-3.5 text-foreground-subtle`}),children:(0,h.jsx)(`div`,{className:`flex flex-col gap-3`,children:k?(0,h.jsx)(`p`,{className:`${a} leading-relaxed`,children:n(`uiLibrary.motionZones.unsupported`,`This camera doesn't expose an on-board motion zones grid.`)}):ie?(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(`p`,{className:`${a} leading-relaxed`,children:(0,h.jsx)(r,{uiKey:`uiLibrary.motionZones.intro`,fallback:`Toggle <0>Edit grid</0> to paint the region directly on the live frame, then <1>Save</1> to push the mask to the camera. Pick a bigger <2>Cell size</2> for quicker, broad-stroke painting — it's resampled to the camera's native {{width}}×{{height}} grid on save (×1 is the finest).`,components:[(0,h.jsx)(`strong`,{className:`text-foreground`},`e`),(0,h.jsx)(`strong`,{className:`text-foreground`},`s`),(0,h.jsx)(`strong`,{className:`text-foreground`},`c`)],values:{width:d.grid.width,height:d.grid.height}})}),(0,h.jsxs)(`div`,{className:`flex items-center gap-2 flex-wrap`,children:[(0,h.jsx)(`button`,{type:`button`,onClick:()=>B(e=>!e),disabled:L,"aria-pressed":z,className:z?S:x,children:z?n(`uiLibrary.motionZones.doneEditing`,`Done editing`):n(`uiLibrary.motionZones.editGrid`,`Edit grid`)}),(0,h.jsx)(`button`,{type:`button`,onClick:()=>Z(!0),disabled:L,className:x,children:n(`uiLibrary.motionZones.allOn`,`All on`)}),(0,h.jsx)(`button`,{type:`button`,onClick:()=>Z(!1),disabled:L,className:x,children:n(`uiLibrary.motionZones.allOff`,`All off`)}),(0,h.jsx)(`button`,{type:`button`,onClick:ee,disabled:L,className:x,children:n(`uiLibrary.motionZones.invert`,`Invert`)}),(0,h.jsxs)(`div`,{className:`flex items-center gap-1 ml-1`,role:`group`,"aria-label":n(`uiLibrary.motionZones.cellSize`,`Cell size`),children:[(0,h.jsx)(`span`,{className:`${a} mr-0.5`,children:n(`uiLibrary.motionZones.cellSize`,`Cell size`)}),y.map(e=>(0,h.jsxs)(`button`,{type:`button`,onClick:()=>ne(e),disabled:L,"aria-pressed":F===e,title:e===1?n(`uiLibrary.motionZones.cameraGrid`,`Camera grid {{width}}×{{height}} (finest)`,{width:H,height:U}):n(`uiLibrary.motionZones.paintingGrid`,`{{width}}×{{height}} painting grid · cells ×{{factor}} bigger`,{width:T(H,e),height:T(U,e),factor:e}),className:F===e?S:x,children:[`×`,e]},e))]}),(0,h.jsxs)(`span`,{className:`${a} ml-1 tabular-nums`,children:[n(`uiLibrary.motionZones.cells`,`{{active}} / {{total}} cells · {{width}}×{{height}}`,{active:J,total:Y,width:d.grid.width,height:d.grid.height}),F===1?``:n(`uiLibrary.motionZones.paintSuffix`,` · paint {{width}}×{{height}}`,{width:W,height:G})]}),(0,h.jsx)(`span`,{className:`flex-1`}),(0,h.jsx)(`button`,{type:`button`,onClick:te,disabled:L||!q,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:n(`uiLibrary.motionZones.revert`,`Revert`)}),(0,h.jsx)(`button`,{type:`button`,onClick:()=>void re(),disabled:L||!q,className:S,children:L?n(`uiLibrary.motionZones.saving`,`Saving…`):n(`uiLibrary.motionZones.save`,`Save`)})]})]}):(0,h.jsx)(`p`,{className:`${a} leading-relaxed`,children:n(`uiLibrary.motionZones.loading`,`Loading the camera's grid…`)})})}):null}export{k as MotionZonesSettings};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as e,i as t,l as n,n as r,o as i}from"./scheduler-0XZJE03d.js";import{S as ee,_ as a,b as te,c as o,d as ne,g as s,l as c,p as re,t as l,v as u,w as d}from"./index-D5vO_ttL.js";import{MaskShapeCanvas as ie}from"./MaskShapeCanvas-BTvl6Rin.js";var ae=d(`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`}]]),oe=d(`mic-off`,[[`path`,{d:`M12 19v3`,key:`npa21l`}],[`path`,{d:`M15 9.34V5a3 3 0 0 0-5.68-1.33`,key:`1gzdoj`}],[`path`,{d:`M16.95 16.95A7 7 0 0 1 5 12v-2`,key:`cqa7eg`}],[`path`,{d:`M18.89 13.23A7 7 0 0 0 19 12v-2`,key:`16hl24`}],[`path`,{d:`m2 2 20 20`,key:`1ooewy`}],[`path`,{d:`M9 9v3a3 3 0 0 0 5.12 2.12`,key:`r2i35w`}]]),f=n(i(),1),p=`Microphone`,m=`The camera encodes no audio at all — live view, recordings, exports and the audio analyzer are all silent.`;function se(e){let t=e.supportsAudioMute===!0,n=t?e.audioEnabled:null,r=e.pendingOn??null;return{label:p,supported:t,on:n===null?null:r??n,available:t&&n!==null,costWhenOff:m}}function ce(e){return!e.available||e.on===null?null:{enabled:!e.on}}var h=n(e(),1),le=120,ue=`privacy-mask`,g=`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`,_=`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 v(e){return e.kind===`rect`||e.kind===`polygon`?e:null}function de(e){let t=new Set(e.map(e=>e.id)),n=0;for(;t.has(n);)n+=1;return n}function fe(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 y({deviceId:e}){let n=t(),i=ne(s().trpcClient,e),[d,p]=(0,f.useState)(null),[m,y]=(0,f.useState)(!1),[b,x]=(0,f.useState)(!1),[S,C]=(0,f.useState)(null),[w,T]=(0,f.useState)(null),[E,D]=(0,f.useState)(!1),[O,k]=(0,f.useState)(!1),[A,j]=(0,f.useState)(null),[M,N]=(0,f.useState)(null),[pe,P]=(0,f.useState)(null),[F,I]=(0,f.useState)(null),[L,R]=(0,f.useState)(null),z=(0,f.useRef)(!1);(0,f.useEffect)(()=>{if(!i)return;let e=!1;return z.current=!1,p(null),y(!1),x(!1),C(null),T(null),k(!1),j(null),N(null),P(null),I(null),R(null),(async()=>{try{let t=await i.privacyMask?.getOptions({});if(e)return;if(!t)throw Error(`device proxy not ready`);if(p(t),z.current)return;let n=await i.privacyMask?.getStatus({});if(e)return;if(!n)throw Error(`device proxy not ready`);if(n.regions===null){x(!0),P(n.audioEnabled);return}z.current=!0;let r={enabled:n.enabled,regions:n.regions};T(r),C(r),P(n.audioEnabled)}catch(t){if(e)return;c(t)?y(!0):console.error(`Privacy Mask load failed`,t)}})(),()=>{e=!0}},[i]);let B=(0,f.useMemo)(()=>S!==null&&w!==null&&(S.enabled!==w.enabled||!fe(S.regions,w.regions)),[S,w]),V=S?S.regions.length:0,H=d?d.maxRegions:0,U=(0,f.useRef)(0);(0,f.useEffect)(()=>{U.current=H},[H]);let W=H>0&&V>=H,me=(0,f.useCallback)(()=>{C(e=>e&&{...e,enabled:!e.enabled})},[]),G=(0,f.useCallback)(e=>{j(typeof e==`number`?e:null)},[]),K=(0,f.useMemo)(()=>S?S.regions.map(e=>({id:e.id,shape:e.shape,enabled:e.enabled,label:n(`uiLibrary.privacyMaskSettings.zoneN`,`Zone {{id}}`,{id:e.id})})):[],[S,n]),q=(0,f.useCallback)((e,t)=>{let n=v(t);n&&C(t=>t&&{...t,regions:t.regions.map(t=>t.id===e?{...t,shape:n}:t)})},[]),J=(0,f.useCallback)(e=>{let t=v(e);t&&(N(null),C(e=>{if(!e)return e;let n=U.current;if(n>0&&e.regions.length>=n)return e;let r=de(e.regions),i={id:r,enabled:!0,shape:t};return j(r),{...e,regions:[...e.regions,i]}}))},[]),Y=(0,f.useCallback)(e=>{k(!0),j(null),N(e)},[]),he=(0,f.useCallback)(e=>{k(!0),N(null),j(e)},[]),ge=(0,f.useCallback)(e=>{j(t=>t===e?null:t),C(t=>t&&{...t,regions:t.regions.filter(t=>t.id!==e)})},[]),_e=(0,f.useCallback)(()=>{N(null),j(null),w&&C({enabled:w.enabled,regions:w.regions})},[w]),X=(0,f.useCallback)(async()=>{if(!(!i||!S)){D(!0);try{await i.privacyMask?.setMask({patch:{enabled:S.enabled,regions:[...S.regions]}});let e=await i.privacyMask?.getStatus({});if(e&&e.regions!==null){let t={enabled:e.enabled,regions:e.regions};T(t),C(t)}}catch(e){console.error(`Privacy Mask save failed`,e)}finally{D(!1)}}},[i,S]),Z=se({supportsAudioMute:d===null?null:d.supportsAudioMute,audioEnabled:pe,pendingOn:F}),ve=(0,f.useCallback)(async()=>{let e=ce(Z);if(!(!i||e===null)){I(e.enabled),R(null);try{await i.privacyMask?.setAudioEnabled(e);let t=await i.privacyMask?.getStatus({});t&&P(t.audioEnabled)}catch(e){console.error(`Privacy microphone write failed — reverting`,e),R(e instanceof Error?e.message:String(e))}finally{I(null)}}},[i,Z]),ye=(0,f.useCallback)(()=>{k(e=>(e&&(N(null),j(null)),!e))},[]),Q=d?.supportedShapes??[];l((0,f.useMemo)(()=>O&&!m&&d&&S?{id:ue,order:le,node:(0,h.jsx)(ie,{transparent:!0,items:K,supportedShapes:Q,polygonVertices:d.polygonVertices,selectedId:A,onSelect:G,onShapeChange:q,onDrawComplete:J,drawingKind:M})}:null,[O,m,d,S,K,Q,A,G,q,J,M]));let be=d?.supportedShapes.includes(`rect`)??!1,xe=d?.supportedShapes.includes(`polygon`)??!1,$=d!==null&&(d.maxRegions<=0||d.supportedShapes.length===0),Se=!m&&!$&&!b&&d!==null&&S!==null;return i?(0,h.jsx)(re,{title:n(`uiLibrary.privacyMaskSettings.title`,`Privacy Mask`),icon:(0,h.jsx)(ee,{className:`h-3.5 w-3.5 text-foreground-subtle`}),children:(0,h.jsxs)(`div`,{className:`flex flex-col gap-3`,children:[m||$?(0,h.jsx)(`p`,{className:`${o} leading-relaxed`,children:n(`uiLibrary.privacyMaskSettings.unsupported`,`This camera doesn't support an on-board privacy mask.`)}):b?(0,h.jsx)(`p`,{className:`${o} leading-relaxed`,children:n(`uiLibrary.privacyMaskSettings.unreadable`,`This camera hasn't answered, so what it currently masks is unknown — the editor stays closed rather than showing an empty frame you could save over. A battery camera answers once it wakes; otherwise check that it is reachable.`)}):Se?(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(`p`,{className:`${o} leading-relaxed`,children:(0,h.jsx)(r,{uiKey:`uiLibrary.privacyMaskSettings.help`,fallback:`Toggle <0>Edit mask</0> to draw blanked-out zones on the live frame, then <1>Save</1> 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.`,components:[(0,h.jsx)(`strong`,{className:`text-foreground`},`edit`),(0,h.jsx)(`strong`,{className:`text-foreground`},`save`)]})}),(0,h.jsxs)(`div`,{className:`flex items-center gap-2 flex-wrap`,children:[(0,h.jsx)(`button`,{type:`button`,onClick:ye,disabled:E,"aria-pressed":O,className:O?_:g,children:O?n(`uiLibrary.privacyMaskSettings.doneEditing`,`Done editing`):n(`uiLibrary.privacyMaskSettings.editMask`,`Edit mask`)}),(0,h.jsx)(`button`,{type:`button`,onClick:me,disabled:E,"aria-pressed":S.enabled,className:S.enabled?_:g,children:S.enabled?n(`uiLibrary.privacyMaskSettings.maskOn`,`Mask on`):n(`uiLibrary.privacyMaskSettings.maskOff`,`Mask off`)}),be&&(0,h.jsx)(`button`,{type:`button`,onClick:()=>Y(`rect`),disabled:E||W,"aria-pressed":M===`rect`,className:M===`rect`?_:g,title:W?n(`uiLibrary.privacyMaskSettings.maxZones`,`Maximum zones reached`):n(`uiLibrary.privacyMaskSettings.addRect`,`Add a rectangle zone`),children:n(`uiLibrary.privacyMaskSettings.rectButton`,`+ Rect`)}),xe&&(0,h.jsx)(`button`,{type:`button`,onClick:()=>Y(`polygon`),disabled:E||W,"aria-pressed":M===`polygon`,className:M===`polygon`?_:g,title:W?n(`uiLibrary.privacyMaskSettings.maxZones`,`Maximum zones reached`):n(`uiLibrary.privacyMaskSettings.addPolygon`,`Add a polygon zone`),children:n(`uiLibrary.privacyMaskSettings.polygonButton`,`+ Polygon`)}),(0,h.jsx)(`span`,{className:`${o} ml-1 tabular-nums`,children:n(`uiLibrary.privacyMaskSettings.zoneCount`,`{{active}} / {{max}} zones`,{active:V,max:H})}),(0,h.jsx)(`span`,{className:`flex-1`}),(0,h.jsx)(`button`,{type:`button`,onClick:_e,disabled:E||!B,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:n(`uiLibrary.privacyMaskSettings.revert`,`Revert`)}),(0,h.jsx)(`button`,{type:`button`,onClick:()=>void X(),disabled:E||!B,className:_,children:E?n(`uiLibrary.privacyMaskSettings.saving`,`Saving…`):n(`uiLibrary.privacyMaskSettings.save`,`Save`)})]}),V>0?(0,h.jsx)(`div`,{className:`flex flex-col gap-1`,children:S.regions.map(e=>{let t=A===e.id,r=e.shape.kind===`polygon`?ae:u;return(0,h.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,h.jsxs)(`button`,{type:`button`,onClick:()=>he(e.id),disabled:E,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,h.jsx)(r,{className:`h-3.5 w-3.5 shrink-0`}),(0,h.jsx)(`span`,{children:n(`uiLibrary.privacyMaskSettings.zoneN`,`Zone {{id}}`,{id:e.id})}),(0,h.jsx)(`span`,{className:`text-foreground-faint capitalize`,children:e.shape.kind})]}),(0,h.jsx)(`button`,{type:`button`,onClick:()=>ge(e.id),disabled:E,"aria-label":n(`uiLibrary.privacyMaskSettings.deleteZoneN`,`Delete zone {{id}}`,{id:e.id}),title:n(`uiLibrary.privacyMaskSettings.deleteZone`,`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,h.jsx)(a,{className:`h-3.5 w-3.5`})})]},e.id)})}):null]}):(0,h.jsx)(`p`,{className:`${o} leading-relaxed`,children:n(`uiLibrary.privacyMaskSettings.loading`,`Loading the camera's privacy mask…`)}),Z.supported&&(0,h.jsxs)(`div`,{className:`flex items-start gap-3 rounded-md border border-border bg-surface px-2 py-2`,children:[(0,h.jsx)(`button`,{type:`button`,role:`switch`,"aria-label":Z.label,"aria-checked":Z.on===!0,disabled:!Z.available||F!==null,onClick:()=>void ve(),title:Z.on===null?n(`uiLibrary.privacyMaskSettings.micTitleUnknown`,`Microphone — state unknown; the camera did not answer.`):Z.on?n(`uiLibrary.privacyMaskSettings.micTitleOn`,`The camera is capturing sound. Turning it off: {{cost}}`,{cost:Z.costWhenOff}):n(`uiLibrary.privacyMaskSettings.micTitleOff`,`The camera is silent. {{cost}}`,{cost:Z.costWhenOff}),className:Z.on===!1||Z.on===null?g:_,children:(0,h.jsxs)(`span`,{className:`inline-flex items-center gap-1.5`,children:[Z.on===!1?(0,h.jsx)(oe,{className:`h-3.5 w-3.5`}):(0,h.jsx)(te,{className:`h-3.5 w-3.5`}),Z.on===null?n(`uiLibrary.privacyMaskSettings.micUnknown`,`Microphone unknown`):Z.on?n(`uiLibrary.privacyMaskSettings.micOn`,`Microphone on`):n(`uiLibrary.privacyMaskSettings.micOff`,`Microphone off`)]})}),(0,h.jsx)(`p`,{className:`text-[10px] text-foreground-subtle flex-1 leading-relaxed`,children:L===null?Z.on===null?n(`uiLibrary.privacyMaskSettings.micNotReported`,`The camera did not report its microphone, so this state is unknown.`):Z.costWhenOff:n(`uiLibrary.privacyMaskSettings.writeFailed`,`Write failed: {{reason}}`,{reason:L})})]})]})}):null}export{y as PrivacyMaskSettings};
|
|
1
|
+
import{a as e,i as t,l as n,n as r,o as i}from"./scheduler-0XZJE03d.js";import{S as ee,_ as a,b as te,c as o,d as ne,g as s,l as c,p as re,t as l,v as u,w as d}from"./index-DlpbU1Jb.js";import{MaskShapeCanvas as ie}from"./MaskShapeCanvas-BTvl6Rin.js";var ae=d(`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`}]]),oe=d(`mic-off`,[[`path`,{d:`M12 19v3`,key:`npa21l`}],[`path`,{d:`M15 9.34V5a3 3 0 0 0-5.68-1.33`,key:`1gzdoj`}],[`path`,{d:`M16.95 16.95A7 7 0 0 1 5 12v-2`,key:`cqa7eg`}],[`path`,{d:`M18.89 13.23A7 7 0 0 0 19 12v-2`,key:`16hl24`}],[`path`,{d:`m2 2 20 20`,key:`1ooewy`}],[`path`,{d:`M9 9v3a3 3 0 0 0 5.12 2.12`,key:`r2i35w`}]]),f=n(i(),1),p=`Microphone`,m=`The camera encodes no audio at all — live view, recordings, exports and the audio analyzer are all silent.`;function se(e){let t=e.supportsAudioMute===!0,n=t?e.audioEnabled:null,r=e.pendingOn??null;return{label:p,supported:t,on:n===null?null:r??n,available:t&&n!==null,costWhenOff:m}}function ce(e){return!e.available||e.on===null?null:{enabled:!e.on}}var h=n(e(),1),le=120,ue=`privacy-mask`,g=`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`,_=`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 v(e){return e.kind===`rect`||e.kind===`polygon`?e:null}function de(e){let t=new Set(e.map(e=>e.id)),n=0;for(;t.has(n);)n+=1;return n}function fe(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 y({deviceId:e}){let n=t(),i=ne(s().trpcClient,e),[d,p]=(0,f.useState)(null),[m,y]=(0,f.useState)(!1),[b,x]=(0,f.useState)(!1),[S,C]=(0,f.useState)(null),[w,T]=(0,f.useState)(null),[E,D]=(0,f.useState)(!1),[O,k]=(0,f.useState)(!1),[A,j]=(0,f.useState)(null),[M,N]=(0,f.useState)(null),[pe,P]=(0,f.useState)(null),[F,I]=(0,f.useState)(null),[L,R]=(0,f.useState)(null),z=(0,f.useRef)(!1);(0,f.useEffect)(()=>{if(!i)return;let e=!1;return z.current=!1,p(null),y(!1),x(!1),C(null),T(null),k(!1),j(null),N(null),P(null),I(null),R(null),(async()=>{try{let t=await i.privacyMask?.getOptions({});if(e)return;if(!t)throw Error(`device proxy not ready`);if(p(t),z.current)return;let n=await i.privacyMask?.getStatus({});if(e)return;if(!n)throw Error(`device proxy not ready`);if(n.regions===null){x(!0),P(n.audioEnabled);return}z.current=!0;let r={enabled:n.enabled,regions:n.regions};T(r),C(r),P(n.audioEnabled)}catch(t){if(e)return;c(t)?y(!0):console.error(`Privacy Mask load failed`,t)}})(),()=>{e=!0}},[i]);let B=(0,f.useMemo)(()=>S!==null&&w!==null&&(S.enabled!==w.enabled||!fe(S.regions,w.regions)),[S,w]),V=S?S.regions.length:0,H=d?d.maxRegions:0,U=(0,f.useRef)(0);(0,f.useEffect)(()=>{U.current=H},[H]);let W=H>0&&V>=H,me=(0,f.useCallback)(()=>{C(e=>e&&{...e,enabled:!e.enabled})},[]),G=(0,f.useCallback)(e=>{j(typeof e==`number`?e:null)},[]),K=(0,f.useMemo)(()=>S?S.regions.map(e=>({id:e.id,shape:e.shape,enabled:e.enabled,label:n(`uiLibrary.privacyMaskSettings.zoneN`,`Zone {{id}}`,{id:e.id})})):[],[S,n]),q=(0,f.useCallback)((e,t)=>{let n=v(t);n&&C(t=>t&&{...t,regions:t.regions.map(t=>t.id===e?{...t,shape:n}:t)})},[]),J=(0,f.useCallback)(e=>{let t=v(e);t&&(N(null),C(e=>{if(!e)return e;let n=U.current;if(n>0&&e.regions.length>=n)return e;let r=de(e.regions),i={id:r,enabled:!0,shape:t};return j(r),{...e,regions:[...e.regions,i]}}))},[]),Y=(0,f.useCallback)(e=>{k(!0),j(null),N(e)},[]),he=(0,f.useCallback)(e=>{k(!0),N(null),j(e)},[]),ge=(0,f.useCallback)(e=>{j(t=>t===e?null:t),C(t=>t&&{...t,regions:t.regions.filter(t=>t.id!==e)})},[]),_e=(0,f.useCallback)(()=>{N(null),j(null),w&&C({enabled:w.enabled,regions:w.regions})},[w]),X=(0,f.useCallback)(async()=>{if(!(!i||!S)){D(!0);try{await i.privacyMask?.setMask({patch:{enabled:S.enabled,regions:[...S.regions]}});let e=await i.privacyMask?.getStatus({});if(e&&e.regions!==null){let t={enabled:e.enabled,regions:e.regions};T(t),C(t)}}catch(e){console.error(`Privacy Mask save failed`,e)}finally{D(!1)}}},[i,S]),Z=se({supportsAudioMute:d===null?null:d.supportsAudioMute,audioEnabled:pe,pendingOn:F}),ve=(0,f.useCallback)(async()=>{let e=ce(Z);if(!(!i||e===null)){I(e.enabled),R(null);try{await i.privacyMask?.setAudioEnabled(e);let t=await i.privacyMask?.getStatus({});t&&P(t.audioEnabled)}catch(e){console.error(`Privacy microphone write failed — reverting`,e),R(e instanceof Error?e.message:String(e))}finally{I(null)}}},[i,Z]),ye=(0,f.useCallback)(()=>{k(e=>(e&&(N(null),j(null)),!e))},[]),Q=d?.supportedShapes??[];l((0,f.useMemo)(()=>O&&!m&&d&&S?{id:ue,order:le,node:(0,h.jsx)(ie,{transparent:!0,items:K,supportedShapes:Q,polygonVertices:d.polygonVertices,selectedId:A,onSelect:G,onShapeChange:q,onDrawComplete:J,drawingKind:M})}:null,[O,m,d,S,K,Q,A,G,q,J,M]));let be=d?.supportedShapes.includes(`rect`)??!1,xe=d?.supportedShapes.includes(`polygon`)??!1,$=d!==null&&(d.maxRegions<=0||d.supportedShapes.length===0),Se=!m&&!$&&!b&&d!==null&&S!==null;return i?(0,h.jsx)(re,{title:n(`uiLibrary.privacyMaskSettings.title`,`Privacy Mask`),icon:(0,h.jsx)(ee,{className:`h-3.5 w-3.5 text-foreground-subtle`}),children:(0,h.jsxs)(`div`,{className:`flex flex-col gap-3`,children:[m||$?(0,h.jsx)(`p`,{className:`${o} leading-relaxed`,children:n(`uiLibrary.privacyMaskSettings.unsupported`,`This camera doesn't support an on-board privacy mask.`)}):b?(0,h.jsx)(`p`,{className:`${o} leading-relaxed`,children:n(`uiLibrary.privacyMaskSettings.unreadable`,`This camera hasn't answered, so what it currently masks is unknown — the editor stays closed rather than showing an empty frame you could save over. A battery camera answers once it wakes; otherwise check that it is reachable.`)}):Se?(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(`p`,{className:`${o} leading-relaxed`,children:(0,h.jsx)(r,{uiKey:`uiLibrary.privacyMaskSettings.help`,fallback:`Toggle <0>Edit mask</0> to draw blanked-out zones on the live frame, then <1>Save</1> 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.`,components:[(0,h.jsx)(`strong`,{className:`text-foreground`},`edit`),(0,h.jsx)(`strong`,{className:`text-foreground`},`save`)]})}),(0,h.jsxs)(`div`,{className:`flex items-center gap-2 flex-wrap`,children:[(0,h.jsx)(`button`,{type:`button`,onClick:ye,disabled:E,"aria-pressed":O,className:O?_:g,children:O?n(`uiLibrary.privacyMaskSettings.doneEditing`,`Done editing`):n(`uiLibrary.privacyMaskSettings.editMask`,`Edit mask`)}),(0,h.jsx)(`button`,{type:`button`,onClick:me,disabled:E,"aria-pressed":S.enabled,className:S.enabled?_:g,children:S.enabled?n(`uiLibrary.privacyMaskSettings.maskOn`,`Mask on`):n(`uiLibrary.privacyMaskSettings.maskOff`,`Mask off`)}),be&&(0,h.jsx)(`button`,{type:`button`,onClick:()=>Y(`rect`),disabled:E||W,"aria-pressed":M===`rect`,className:M===`rect`?_:g,title:W?n(`uiLibrary.privacyMaskSettings.maxZones`,`Maximum zones reached`):n(`uiLibrary.privacyMaskSettings.addRect`,`Add a rectangle zone`),children:n(`uiLibrary.privacyMaskSettings.rectButton`,`+ Rect`)}),xe&&(0,h.jsx)(`button`,{type:`button`,onClick:()=>Y(`polygon`),disabled:E||W,"aria-pressed":M===`polygon`,className:M===`polygon`?_:g,title:W?n(`uiLibrary.privacyMaskSettings.maxZones`,`Maximum zones reached`):n(`uiLibrary.privacyMaskSettings.addPolygon`,`Add a polygon zone`),children:n(`uiLibrary.privacyMaskSettings.polygonButton`,`+ Polygon`)}),(0,h.jsx)(`span`,{className:`${o} ml-1 tabular-nums`,children:n(`uiLibrary.privacyMaskSettings.zoneCount`,`{{active}} / {{max}} zones`,{active:V,max:H})}),(0,h.jsx)(`span`,{className:`flex-1`}),(0,h.jsx)(`button`,{type:`button`,onClick:_e,disabled:E||!B,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:n(`uiLibrary.privacyMaskSettings.revert`,`Revert`)}),(0,h.jsx)(`button`,{type:`button`,onClick:()=>void X(),disabled:E||!B,className:_,children:E?n(`uiLibrary.privacyMaskSettings.saving`,`Saving…`):n(`uiLibrary.privacyMaskSettings.save`,`Save`)})]}),V>0?(0,h.jsx)(`div`,{className:`flex flex-col gap-1`,children:S.regions.map(e=>{let t=A===e.id,r=e.shape.kind===`polygon`?ae:u;return(0,h.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,h.jsxs)(`button`,{type:`button`,onClick:()=>he(e.id),disabled:E,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,h.jsx)(r,{className:`h-3.5 w-3.5 shrink-0`}),(0,h.jsx)(`span`,{children:n(`uiLibrary.privacyMaskSettings.zoneN`,`Zone {{id}}`,{id:e.id})}),(0,h.jsx)(`span`,{className:`text-foreground-faint capitalize`,children:e.shape.kind})]}),(0,h.jsx)(`button`,{type:`button`,onClick:()=>ge(e.id),disabled:E,"aria-label":n(`uiLibrary.privacyMaskSettings.deleteZoneN`,`Delete zone {{id}}`,{id:e.id}),title:n(`uiLibrary.privacyMaskSettings.deleteZone`,`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,h.jsx)(a,{className:`h-3.5 w-3.5`})})]},e.id)})}):null]}):(0,h.jsx)(`p`,{className:`${o} leading-relaxed`,children:n(`uiLibrary.privacyMaskSettings.loading`,`Loading the camera's privacy mask…`)}),Z.supported&&(0,h.jsxs)(`div`,{className:`flex items-start gap-3 rounded-md border border-border bg-surface px-2 py-2`,children:[(0,h.jsx)(`button`,{type:`button`,role:`switch`,"aria-label":Z.label,"aria-checked":Z.on===!0,disabled:!Z.available||F!==null,onClick:()=>void ve(),title:Z.on===null?n(`uiLibrary.privacyMaskSettings.micTitleUnknown`,`Microphone — state unknown; the camera did not answer.`):Z.on?n(`uiLibrary.privacyMaskSettings.micTitleOn`,`The camera is capturing sound. Turning it off: {{cost}}`,{cost:Z.costWhenOff}):n(`uiLibrary.privacyMaskSettings.micTitleOff`,`The camera is silent. {{cost}}`,{cost:Z.costWhenOff}),className:Z.on===!1||Z.on===null?g:_,children:(0,h.jsxs)(`span`,{className:`inline-flex items-center gap-1.5`,children:[Z.on===!1?(0,h.jsx)(oe,{className:`h-3.5 w-3.5`}):(0,h.jsx)(te,{className:`h-3.5 w-3.5`}),Z.on===null?n(`uiLibrary.privacyMaskSettings.micUnknown`,`Microphone unknown`):Z.on?n(`uiLibrary.privacyMaskSettings.micOn`,`Microphone on`):n(`uiLibrary.privacyMaskSettings.micOff`,`Microphone off`)]})}),(0,h.jsx)(`p`,{className:`text-[10px] text-foreground-subtle flex-1 leading-relaxed`,children:L===null?Z.on===null?n(`uiLibrary.privacyMaskSettings.micNotReported`,`The camera did not report its microphone, so this state is unknown.`):Z.costWhenOff:n(`uiLibrary.privacyMaskSettings.writeFailed`,`Write failed: {{reason}}`,{reason:L})})]})]})}):null}export{y as PrivacyMaskSettings};
|