@camstack/addon-agent-ui 1.2.318 → 1.2.320
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 +12 -0
- package/dist/.bundle-modules.json +18 -10
- package/dist/addon.js +262 -204
- package/dist/assets/{MotionZonesSettings-Bp6yIDkW.js → MotionZonesSettings-CT7V6A2O.js} +1 -1
- package/dist/assets/{PrivacyMaskSettings-DMvmTLe5.js → PrivacyMaskSettings-RsvMNMX6.js} +1 -1
- package/dist/assets/{SceneMonitorEditor-FlmCqKaT.js → SceneMonitorEditor-B9DbNWmO.js} +1 -1
- package/dist/assets/index-BXAblT4K.js +145 -0
- package/dist/assets/index-DCzD3MGc.css +2 -0
- package/dist/index.html +2 -2
- package/package.json +2 -2
- package/dist/assets/index-ByJhjoZZ.js +0 -127
- package/dist/assets/index-DDtWrhPa.css +0 -2
package/dist/addon.js
CHANGED
|
@@ -5849,7 +5849,7 @@ var ZodIssueCode = {
|
|
|
5849
5849
|
var ZodFirstPartyTypeKind;
|
|
5850
5850
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5851
5851
|
//#endregion
|
|
5852
|
-
//#region ../types/dist/sleep-
|
|
5852
|
+
//#region ../types/dist/sleep-hK-Dss3z.mjs
|
|
5853
5853
|
/**
|
|
5854
5854
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5855
5855
|
* window to float samples (D455).
|
|
@@ -7890,6 +7890,10 @@ var BaseAddon = class {
|
|
|
7890
7890
|
const stored = keychain ? await this.readAddonStoreWithRetry() : {};
|
|
7891
7891
|
const patch = {};
|
|
7892
7892
|
for (const key of keys) {
|
|
7893
|
+
if (tree.get(key)?.kind === "array") {
|
|
7894
|
+
patch[key] = [];
|
|
7895
|
+
continue;
|
|
7896
|
+
}
|
|
7893
7897
|
const keychainStored = tree.has(key) || collectSecretMarkerRefs(stored[key]).length > 0;
|
|
7894
7898
|
patch[key] = keychain && keychainStored ? SECRET_CLEAR : "";
|
|
7895
7899
|
}
|
|
@@ -11305,7 +11309,7 @@ object({
|
|
|
11305
11309
|
params: record(string(), union([string(), number()])).optional()
|
|
11306
11310
|
});
|
|
11307
11311
|
//#endregion
|
|
11308
|
-
//#region ../types/dist/composition-
|
|
11312
|
+
//#region ../types/dist/composition-BSGHhcr8.mjs
|
|
11309
11313
|
/**
|
|
11310
11314
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
11311
11315
|
*
|
|
@@ -12068,38 +12072,6 @@ function validateExpressionSource(src) {
|
|
|
12068
12072
|
return null;
|
|
12069
12073
|
}
|
|
12070
12074
|
/**
|
|
12071
|
-
* One power reading becomes a washer, dryer or dishwasher (D944 helper).
|
|
12072
|
-
*
|
|
12073
|
-
* Standby of the control board is under 5 W; a motor or a heater is far
|
|
12074
|
-
* above that, so 5 W is the line. A door lock or a short pump spike is not
|
|
12075
|
-
* a cycle, so running starts only after 30 s above the line.
|
|
12076
|
-
*
|
|
12077
|
-
* A wash, dry or dishwasher pause (soak, heat-wait, heater off between
|
|
12078
|
-
* bursts) lasts several minutes. Ending the cycle on the first dip would
|
|
12079
|
-
* report "finished" in the middle of the program, so the stop dwell is
|
|
12080
|
-
* 10 minutes on every type. The number is stored per type so one machine
|
|
12081
|
-
* can move later without moving the others.
|
|
12082
|
-
*/
|
|
12083
|
-
var APPLIANCE_TEMPLATE_ID = "appliance";
|
|
12084
|
-
var APPLIANCE_KINDS = [
|
|
12085
|
-
"washer",
|
|
12086
|
-
"dryer",
|
|
12087
|
-
"dishwasher"
|
|
12088
|
-
];
|
|
12089
|
-
DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher;
|
|
12090
|
-
/**
|
|
12091
|
-
* A dumb plug-in stove or heater, built from a smart plug (a `Heater`).
|
|
12092
|
-
*
|
|
12093
|
-
* The plug is the actuator: `switch.setState` is a FORWARD to the plug's own
|
|
12094
|
-
* (D967), so the heater switches exactly as the plug does. Running is the
|
|
12095
|
-
* plug being on; when a power reading is also named, running is the draw
|
|
12096
|
-
* staying above the line instead (a plug left on with the stove's own
|
|
12097
|
-
* thermostat open is not heating). 50 W is far above any standby and below
|
|
12098
|
-
* the smallest radiator.
|
|
12099
|
-
*/
|
|
12100
|
-
var HEATER_TEMPLATE_ID = "heater";
|
|
12101
|
-
DeviceType.Heater;
|
|
12102
|
-
/**
|
|
12103
12075
|
* Statistics and integrals over a history read (D944).
|
|
12104
12076
|
*
|
|
12105
12077
|
* Pure: the same points always give the same answer, so a restart recomputes
|
|
@@ -12243,34 +12215,6 @@ var HelperSpecSchema = discriminatedUnion("kind", [
|
|
|
12243
12215
|
/** Actuator groups only. Readings leave this unset. */
|
|
12244
12216
|
active: ActiveCriterionSchema.optional()
|
|
12245
12217
|
}),
|
|
12246
|
-
object({
|
|
12247
|
-
kind: literal("appliance"),
|
|
12248
|
-
templateId: literal(APPLIANCE_TEMPLATE_ID),
|
|
12249
|
-
appliance: _enum(APPLIANCE_KINDS),
|
|
12250
|
-
thresholdWatts: number().positive(),
|
|
12251
|
-
startDwellMs: number().int().nonnegative(),
|
|
12252
|
-
stopDwellMs: number().int().nonnegative(),
|
|
12253
|
-
member: HelperMemberSchema,
|
|
12254
|
-
/**
|
|
12255
|
-
* The plug that powers the appliance (`switch.on`). Optional: when set, the
|
|
12256
|
-
* composition carries a `power-source` feature, so the hub can cut and restore
|
|
12257
|
-
* that plug (power-source link of a NEW-target composition).
|
|
12258
|
-
*/
|
|
12259
|
-
powerSwitch: HelperMemberSchema.optional(),
|
|
12260
|
-
/** How long a forced restart keeps the plug off; the cap's default when unset. */
|
|
12261
|
-
offSeconds: number().optional()
|
|
12262
|
-
}),
|
|
12263
|
-
object({
|
|
12264
|
-
kind: literal("heater"),
|
|
12265
|
-
templateId: literal(HEATER_TEMPLATE_ID),
|
|
12266
|
-
/** The plug, read and commanded at `switch.on`. */
|
|
12267
|
-
plug: HelperMemberSchema,
|
|
12268
|
-
/** The plug's power reading, when it has one: running is then the draw, not the switch. */
|
|
12269
|
-
meter: HelperMemberSchema.optional(),
|
|
12270
|
-
thresholdWatts: number().positive(),
|
|
12271
|
-
startDwellMs: number().int().nonnegative(),
|
|
12272
|
-
stopDwellMs: number().int().nonnegative()
|
|
12273
|
-
}),
|
|
12274
12218
|
object({
|
|
12275
12219
|
kind: literal("statistic"),
|
|
12276
12220
|
stat: _enum(STATISTIC_STATS),
|
|
@@ -12494,7 +12438,7 @@ var CompositionSchema = object({
|
|
|
12494
12438
|
kind: literal("existing"),
|
|
12495
12439
|
device: CompositionSourceRefSchema
|
|
12496
12440
|
})]),
|
|
12497
|
-
features: array(CompositionFeatureSchema).min(
|
|
12441
|
+
features: array(CompositionFeatureSchema).min(0).max(16),
|
|
12498
12442
|
/**
|
|
12499
12443
|
* Present when the block is a helper template. Absent on a free
|
|
12500
12444
|
* composition (the room example, device 4603). The editor reads this,
|
|
@@ -48077,49 +48021,6 @@ function actuator(input) {
|
|
|
48077
48021
|
};
|
|
48078
48022
|
}
|
|
48079
48023
|
new Map(GROUP_TEMPLATES.map((template) => [template.id, template]));
|
|
48080
|
-
var PowerSourceRefusalReasonSchema = _enum([
|
|
48081
|
-
"no-power-source",
|
|
48082
|
-
"switch-missing",
|
|
48083
|
-
"switch-offline",
|
|
48084
|
-
"switch-unknown",
|
|
48085
|
-
"restart-in-progress",
|
|
48086
|
-
"switch-call-failed"
|
|
48087
|
-
]);
|
|
48088
|
-
var PowerSourceActionResultSchema = discriminatedUnion("accepted", [object({ accepted: literal(true) }), object({
|
|
48089
|
-
accepted: literal(false),
|
|
48090
|
-
reason: PowerSourceRefusalReasonSchema,
|
|
48091
|
-
/** One line for the operator, naming the switch. */
|
|
48092
|
-
message: string()
|
|
48093
|
-
})]);
|
|
48094
|
-
var PowerSourceInfoSchema = object({
|
|
48095
|
-
/** False when the device has no power source linked; the rest is then empty. */
|
|
48096
|
-
linked: boolean(),
|
|
48097
|
-
switchDeviceId: number().nullable(),
|
|
48098
|
-
switchName: string().nullable(),
|
|
48099
|
-
/** The switch's on/off state, or null when it is unknown. Never false for unknown (D393). */
|
|
48100
|
-
switchOn: boolean().nullable(),
|
|
48101
|
-
switchOnline: boolean().nullable(),
|
|
48102
|
-
restartInProgress: boolean(),
|
|
48103
|
-
offSeconds: number().int()
|
|
48104
|
-
});
|
|
48105
|
-
object({
|
|
48106
|
-
/** Null while the switch has not reported: unknown is never `false` (D393). */
|
|
48107
|
-
switchOn: boolean().nullable(),
|
|
48108
|
-
offSeconds: number().int(),
|
|
48109
|
-
lastFetchedAt: number()
|
|
48110
|
-
});
|
|
48111
|
-
DeviceType.Gateway, DeviceType.Hub, DeviceType.Camera, DeviceType.Sensor, DeviceType.MediaPlayer, DeviceType.Vacuum, DeviceType.Generic, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.PetFountain, DeviceType.Fan, DeviceType.Humidifier, DeviceType.Climate, DeviceType.WaterHeater;
|
|
48112
|
-
var deviceInput$2 = object({ deviceId: number().int().nonnegative() });
|
|
48113
|
-
systemMethod(deviceInput$2, PowerSourceInfoSchema, { auth: "admin" }), systemMethod(deviceInput$2, PowerSourceActionResultSchema, {
|
|
48114
|
-
kind: "mutation",
|
|
48115
|
-
auth: "admin"
|
|
48116
|
-
}), systemMethod(deviceInput$2, PowerSourceActionResultSchema, {
|
|
48117
|
-
kind: "mutation",
|
|
48118
|
-
auth: "admin"
|
|
48119
|
-
}), systemMethod(deviceInput$2, PowerSourceActionResultSchema, {
|
|
48120
|
-
kind: "mutation",
|
|
48121
|
-
auth: "admin"
|
|
48122
|
-
});
|
|
48123
48024
|
DeviceFeature.LightColorRgb, DeviceFeature.LightColorHsv, DeviceFeature.LightColorMired;
|
|
48124
48025
|
DeviceType.Camera;
|
|
48125
48026
|
`${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
|
|
@@ -48147,6 +48048,165 @@ var ComposableCapabilitiesSchema = object({ caps: array(object({
|
|
|
48147
48048
|
}).optional()
|
|
48148
48049
|
})) });
|
|
48149
48050
|
/**
|
|
48051
|
+
* A saved Customize assignment (D936). The schema is the type: callers use
|
|
48052
|
+
* `z.infer`, they do not restate the shape.
|
|
48053
|
+
*/
|
|
48054
|
+
var OverrideSourceSchema = object({
|
|
48055
|
+
addonId: string().min(1),
|
|
48056
|
+
stableId: string().min(1),
|
|
48057
|
+
cap: string().min(1),
|
|
48058
|
+
fieldPath: string().min(1)
|
|
48059
|
+
});
|
|
48060
|
+
var IdentityTransformDraftSchema = object({ kind: literal("identity") });
|
|
48061
|
+
var InvertTransformDraftSchema = object({ kind: literal("invert") });
|
|
48062
|
+
var ThresholdTransformDraftSchema = object({
|
|
48063
|
+
kind: literal("threshold"),
|
|
48064
|
+
comparison: _enum(["gte", "lte"]),
|
|
48065
|
+
threshold: number(),
|
|
48066
|
+
startDwellMs: number().nonnegative(),
|
|
48067
|
+
stopDwellMs: number().nonnegative()
|
|
48068
|
+
});
|
|
48069
|
+
var CustomizeTransformDraftSchema = discriminatedUnion("kind", [
|
|
48070
|
+
IdentityTransformDraftSchema,
|
|
48071
|
+
InvertTransformDraftSchema,
|
|
48072
|
+
ThresholdTransformDraftSchema,
|
|
48073
|
+
object({
|
|
48074
|
+
kind: literal("linear"),
|
|
48075
|
+
scale: number(),
|
|
48076
|
+
offset: number(),
|
|
48077
|
+
clampMin: number().optional(),
|
|
48078
|
+
clampMax: number().optional()
|
|
48079
|
+
}),
|
|
48080
|
+
object({
|
|
48081
|
+
kind: literal("enum-map"),
|
|
48082
|
+
mapping: record(string(), string().nullable())
|
|
48083
|
+
}),
|
|
48084
|
+
object({ kind: literal("number") })
|
|
48085
|
+
]);
|
|
48086
|
+
var ScalarOverrideDraftSchema = object({
|
|
48087
|
+
kind: literal("scalar"),
|
|
48088
|
+
cap: string().min(1),
|
|
48089
|
+
targetId: string().min(1),
|
|
48090
|
+
source: OverrideSourceSchema,
|
|
48091
|
+
transform: CustomizeTransformDraftSchema
|
|
48092
|
+
});
|
|
48093
|
+
var KeyedArrayOverrideDraftSchema = object({
|
|
48094
|
+
kind: literal("keyedArray"),
|
|
48095
|
+
cap: string().min(1),
|
|
48096
|
+
targetId: string().min(1),
|
|
48097
|
+
key: string().min(1),
|
|
48098
|
+
label: string().min(1),
|
|
48099
|
+
fieldPath: string().min(1),
|
|
48100
|
+
source: OverrideSourceSchema,
|
|
48101
|
+
transform: CustomizeTransformDraftSchema
|
|
48102
|
+
});
|
|
48103
|
+
var PulseOverrideDraftSchema = object({
|
|
48104
|
+
kind: literal("pulse"),
|
|
48105
|
+
cap: string().min(1),
|
|
48106
|
+
targetId: string().min(1),
|
|
48107
|
+
enabled: boolean(),
|
|
48108
|
+
debounceMs: number().nonnegative(),
|
|
48109
|
+
edges: array(_enum([
|
|
48110
|
+
"rising",
|
|
48111
|
+
"button",
|
|
48112
|
+
"native-event"
|
|
48113
|
+
])).min(1).optional(),
|
|
48114
|
+
sources: array(OverrideSourceSchema).min(1)
|
|
48115
|
+
});
|
|
48116
|
+
var SpanSourceDraftSchema = OverrideSourceSchema.extend({ mode: _enum([
|
|
48117
|
+
"in-addition",
|
|
48118
|
+
"confirm",
|
|
48119
|
+
"replace"
|
|
48120
|
+
]).optional() });
|
|
48121
|
+
discriminatedUnion("kind", [
|
|
48122
|
+
ScalarOverrideDraftSchema,
|
|
48123
|
+
KeyedArrayOverrideDraftSchema,
|
|
48124
|
+
PulseOverrideDraftSchema,
|
|
48125
|
+
object({
|
|
48126
|
+
kind: literal("span"),
|
|
48127
|
+
cap: string().min(1),
|
|
48128
|
+
targetId: string().min(1),
|
|
48129
|
+
timeoutMs: number().nonnegative(),
|
|
48130
|
+
cooldownMs: number().nonnegative().optional(),
|
|
48131
|
+
sources: array(SpanSourceDraftSchema)
|
|
48132
|
+
})
|
|
48133
|
+
]);
|
|
48134
|
+
object({
|
|
48135
|
+
targetId: string().min(1),
|
|
48136
|
+
configured: boolean(),
|
|
48137
|
+
source: _enum(["native", "assigned"]),
|
|
48138
|
+
state: _enum([
|
|
48139
|
+
"active",
|
|
48140
|
+
"stale",
|
|
48141
|
+
"released",
|
|
48142
|
+
"unavailable"
|
|
48143
|
+
]),
|
|
48144
|
+
reason: string().nullable()
|
|
48145
|
+
});
|
|
48146
|
+
/**
|
|
48147
|
+
* What a running-threshold proposal says (planning#405). The schema is the
|
|
48148
|
+
* type: the algorithm, the capability method and the UI all read `z.infer`.
|
|
48149
|
+
*
|
|
48150
|
+
* A proposal is read-only advice: it carries the numbers it was derived from
|
|
48151
|
+
* (`evidence`) so the operator can judge it, and an `insufficient` answer names
|
|
48152
|
+
* WHY with a typed reason and the catalog defaults, never an invented number.
|
|
48153
|
+
*/
|
|
48154
|
+
var RunningProposalTierSchema = _enum(["raw", "5m"]);
|
|
48155
|
+
var RunningProposalConfidenceSchema = _enum([
|
|
48156
|
+
"high",
|
|
48157
|
+
"medium",
|
|
48158
|
+
"low"
|
|
48159
|
+
]);
|
|
48160
|
+
var RunningProposalInsufficientReasonSchema = _enum([
|
|
48161
|
+
"no-history",
|
|
48162
|
+
"span-too-short",
|
|
48163
|
+
"truncated",
|
|
48164
|
+
"no-idle-floor",
|
|
48165
|
+
"no-runs",
|
|
48166
|
+
"no-separation"
|
|
48167
|
+
]);
|
|
48168
|
+
var RunningProposalReplaySchema = object({
|
|
48169
|
+
/** Intervals the real dwell expression held true over the window. */
|
|
48170
|
+
intervals: number().int().nonnegative(),
|
|
48171
|
+
/** Intervals outside every run, or a second interval inside one. */
|
|
48172
|
+
extra: number().int().nonnegative(),
|
|
48173
|
+
/** Runs without an interval of their own (none, or merged into a neighbour). */
|
|
48174
|
+
missed: number().int().nonnegative()
|
|
48175
|
+
});
|
|
48176
|
+
var RunningProposalEvidenceSchema = object({
|
|
48177
|
+
tier: RunningProposalTierSchema,
|
|
48178
|
+
spanMs: number().nonnegative(),
|
|
48179
|
+
from: number(),
|
|
48180
|
+
to: number(),
|
|
48181
|
+
points: number().int().nonnegative(),
|
|
48182
|
+
runsFound: number().int().nonnegative(),
|
|
48183
|
+
pausesFound: number().int().nonnegative(),
|
|
48184
|
+
longestPauseMs: number().nonnegative(),
|
|
48185
|
+
idleFloorW: number(),
|
|
48186
|
+
noiseCeilingW: number(),
|
|
48187
|
+
plateauW: number(),
|
|
48188
|
+
replay: RunningProposalReplaySchema
|
|
48189
|
+
});
|
|
48190
|
+
var RunningProposalInsufficientEvidenceSchema = object({
|
|
48191
|
+
spanMs: number().nonnegative(),
|
|
48192
|
+
points: number().int().nonnegative(),
|
|
48193
|
+
runsFound: number().int().nonnegative()
|
|
48194
|
+
});
|
|
48195
|
+
var RunningThresholdProposalSchema = discriminatedUnion("state", [object({
|
|
48196
|
+
state: literal("proposal"),
|
|
48197
|
+
transform: ThresholdTransformDraftSchema,
|
|
48198
|
+
evidence: RunningProposalEvidenceSchema,
|
|
48199
|
+
confidence: RunningProposalConfidenceSchema,
|
|
48200
|
+
/** Why the confidence is not higher; empty when nothing held it back. */
|
|
48201
|
+
notes: array(string())
|
|
48202
|
+
}), object({
|
|
48203
|
+
state: literal("insufficient"),
|
|
48204
|
+
reason: RunningProposalInsufficientReasonSchema,
|
|
48205
|
+
evidence: RunningProposalInsufficientEvidenceSchema,
|
|
48206
|
+
/** The catalog defaults, offered as what stands when nothing better is known. */
|
|
48207
|
+
fallback: ThresholdTransformDraftSchema
|
|
48208
|
+
})]);
|
|
48209
|
+
/**
|
|
48150
48210
|
* The report of a one-shot "move this owner's plaintext secrets into the
|
|
48151
48211
|
* keychain" run (D878). COUNTS only - never a value, never a ref.
|
|
48152
48212
|
*
|
|
@@ -48436,6 +48496,14 @@ method(object({}), object({ blocks: array(CoreBlockSchema) }), { auth: "admin" }
|
|
|
48436
48496
|
kind: "mutation",
|
|
48437
48497
|
auth: "admin",
|
|
48438
48498
|
access: "view"
|
|
48499
|
+
}), method(object({
|
|
48500
|
+
deviceId: number().int(),
|
|
48501
|
+
cap: string().min(1),
|
|
48502
|
+
fieldPath: string().min(1),
|
|
48503
|
+
deviceType: _enum(DeviceType).optional()
|
|
48504
|
+
}), RunningThresholdProposalSchema, {
|
|
48505
|
+
auth: "admin",
|
|
48506
|
+
access: "view"
|
|
48439
48507
|
}), method(object({
|
|
48440
48508
|
blockId: string().min(1),
|
|
48441
48509
|
trace: AutomationRunTraceSchema.optional(),
|
|
@@ -52536,15 +52604,15 @@ var FanPresetCaptureResultSchema = object({
|
|
|
52536
52604
|
items: array(FanCaptureItemSchema),
|
|
52537
52605
|
omitted: array(FanCaptureOmissionSchema)
|
|
52538
52606
|
});
|
|
52539
|
-
var deviceInput$
|
|
52607
|
+
var deviceInput$2 = object({ deviceId: number().int().nonnegative() });
|
|
52540
52608
|
DeviceType.Fan;
|
|
52541
|
-
method(deviceInput$
|
|
52609
|
+
method(deviceInput$2, array(FanPresetSchema), { auth: "protected" }), method(deviceInput$2.extend({ presets: array(FanPresetSchema).max(12) }), FanPresetsSetResultSchema, {
|
|
52542
52610
|
kind: "mutation",
|
|
52543
52611
|
auth: "admin"
|
|
52544
|
-
}), method(deviceInput$
|
|
52612
|
+
}), method(deviceInput$2.extend({ presetId: string().min(1) }), FanPresetApplyResultSchema, {
|
|
52545
52613
|
kind: "mutation",
|
|
52546
52614
|
auth: "protected"
|
|
52547
|
-
}), method(deviceInput$
|
|
52615
|
+
}), method(deviceInput$2.extend({
|
|
52548
52616
|
fields: array(FanCaptureFieldSchema).optional(),
|
|
52549
52617
|
steps: array(ActionStepSchema).max(20).default([])
|
|
52550
52618
|
}), FanPresetCaptureResultSchema, { auth: "protected" });
|
|
@@ -66580,6 +66648,49 @@ object({
|
|
|
66580
66648
|
DeviceType.PetFeeder,
|
|
66581
66649
|
DeviceType.Heater
|
|
66582
66650
|
].filter((type) => type !== DeviceType.Sensor);
|
|
66651
|
+
var PowerSourceRefusalReasonSchema = _enum([
|
|
66652
|
+
"no-power-source",
|
|
66653
|
+
"switch-missing",
|
|
66654
|
+
"switch-offline",
|
|
66655
|
+
"switch-unknown",
|
|
66656
|
+
"restart-in-progress",
|
|
66657
|
+
"switch-call-failed"
|
|
66658
|
+
]);
|
|
66659
|
+
var PowerSourceActionResultSchema = discriminatedUnion("accepted", [object({ accepted: literal(true) }), object({
|
|
66660
|
+
accepted: literal(false),
|
|
66661
|
+
reason: PowerSourceRefusalReasonSchema,
|
|
66662
|
+
/** One line for the operator, naming the switch. */
|
|
66663
|
+
message: string()
|
|
66664
|
+
})]);
|
|
66665
|
+
var PowerSourceInfoSchema = object({
|
|
66666
|
+
/** False when the device has no power source linked; the rest is then empty. */
|
|
66667
|
+
linked: boolean(),
|
|
66668
|
+
switchDeviceId: number().nullable(),
|
|
66669
|
+
switchName: string().nullable(),
|
|
66670
|
+
/** The switch's on/off state, or null when it is unknown. Never false for unknown (D393). */
|
|
66671
|
+
switchOn: boolean().nullable(),
|
|
66672
|
+
switchOnline: boolean().nullable(),
|
|
66673
|
+
restartInProgress: boolean(),
|
|
66674
|
+
offSeconds: number().int()
|
|
66675
|
+
});
|
|
66676
|
+
object({
|
|
66677
|
+
/** Null while the switch has not reported: unknown is never `false` (D393). */
|
|
66678
|
+
switchOn: boolean().nullable(),
|
|
66679
|
+
offSeconds: number().int(),
|
|
66680
|
+
lastFetchedAt: number()
|
|
66681
|
+
});
|
|
66682
|
+
DeviceType.Gateway, DeviceType.Hub, DeviceType.Camera, DeviceType.Sensor, DeviceType.MediaPlayer, DeviceType.Vacuum, DeviceType.Generic, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.PetFountain, DeviceType.Fan, DeviceType.Humidifier, DeviceType.Climate, DeviceType.WaterHeater;
|
|
66683
|
+
var deviceInput$1 = object({ deviceId: number().int().nonnegative() });
|
|
66684
|
+
systemMethod(deviceInput$1, PowerSourceInfoSchema, { auth: "admin" }), systemMethod(deviceInput$1, PowerSourceActionResultSchema, {
|
|
66685
|
+
kind: "mutation",
|
|
66686
|
+
auth: "admin"
|
|
66687
|
+
}), systemMethod(deviceInput$1, PowerSourceActionResultSchema, {
|
|
66688
|
+
kind: "mutation",
|
|
66689
|
+
auth: "admin"
|
|
66690
|
+
}), systemMethod(deviceInput$1, PowerSourceActionResultSchema, {
|
|
66691
|
+
kind: "mutation",
|
|
66692
|
+
auth: "admin"
|
|
66693
|
+
});
|
|
66583
66694
|
/**
|
|
66584
66695
|
* Presence cap. Models HA `person.*` and `device_tracker.*` entities
|
|
66585
66696
|
* on `DeviceType.Presence`. Read-only — no setters: presence is
|
|
@@ -74760,6 +74871,34 @@ discriminatedUnion("kind", [object({
|
|
|
74760
74871
|
kind: literal("pronto"),
|
|
74761
74872
|
code: string()
|
|
74762
74873
|
})]);
|
|
74874
|
+
/**
|
|
74875
|
+
* Propose a running threshold from a device's own power history (planning#405).
|
|
74876
|
+
*
|
|
74877
|
+
* Pure and deterministic: the same series gives the same answer. The series is
|
|
74878
|
+
* a HELD-VALUE step series — a point's value stands until the next point — which
|
|
74879
|
+
* is how device-history stores a gauge, so "time at a level" is exact, not a
|
|
74880
|
+
* count of samples.
|
|
74881
|
+
*
|
|
74882
|
+
* 1. idle floor F = time-weighted median; noise ceiling N = highest value seen
|
|
74883
|
+
* near F. A device that is not near one level most of the time has no floor.
|
|
74884
|
+
* 2. coarse activity = above max(2N, N + 5 W); consecutive stretches are episodes.
|
|
74885
|
+
* 3. gaps between episodes split in two by the largest log-scale jump (>= 3x):
|
|
74886
|
+
* the short ones are pauses INSIDE a run (a soak), the long ones separate runs.
|
|
74887
|
+
* 4. T = geometric mean of N and the plateau's 10th percentile, snapped to a
|
|
74888
|
+
* grid a person would type; stop dwell covers the longest pause; start dwell
|
|
74889
|
+
* covers the longest standby blip above T.
|
|
74890
|
+
* 5. the numbers are proved by REPLAY through the real `dwell` evaluation: each
|
|
74891
|
+
* run must hold exactly one true interval and nothing may flap outside.
|
|
74892
|
+
*/
|
|
74893
|
+
var SECOND_MS = 1e3;
|
|
74894
|
+
var MINUTE_MS$1 = 60 * SECOND_MS;
|
|
74895
|
+
24 * (60 * MINUTE_MS$1);
|
|
74896
|
+
10 * MINUTE_MS$1;
|
|
74897
|
+
30 * SECOND_MS;
|
|
74898
|
+
60 * SECOND_MS;
|
|
74899
|
+
20 * MINUTE_MS$1;
|
|
74900
|
+
10 * SECOND_MS;
|
|
74901
|
+
10 * SECOND_MS;
|
|
74763
74902
|
DeviceFeature.FanSpeed, DeviceFeature.FanPreset, DeviceFeature.FanDirection, DeviceFeature.FanOscillating, DeviceFeature.CoverStoppable, DeviceFeature.CoverPositionable, DeviceFeature.CoverTilt, DeviceFeature.ValvePositionable, DeviceFeature.MediaPlayerVolume, DeviceFeature.ClimateFanMode;
|
|
74764
74903
|
SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
|
|
74765
74904
|
String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
|
|
@@ -76301,6 +76440,13 @@ Object.freeze({
|
|
|
76301
76440
|
access: "create",
|
|
76302
76441
|
role: "admin"
|
|
76303
76442
|
},
|
|
76443
|
+
"coreBlocks.proposeRunningThreshold": {
|
|
76444
|
+
capName: "core-blocks",
|
|
76445
|
+
capScope: "system",
|
|
76446
|
+
addonId: null,
|
|
76447
|
+
access: "view",
|
|
76448
|
+
role: "admin"
|
|
76449
|
+
},
|
|
76304
76450
|
"coreBlocks.reportAutomationRun": {
|
|
76305
76451
|
capName: "core-blocks",
|
|
76306
76452
|
capScope: "system",
|
|
@@ -85759,6 +85905,11 @@ Object.freeze({
|
|
|
85759
85905
|
form: "single",
|
|
85760
85906
|
optional: false
|
|
85761
85907
|
}],
|
|
85908
|
+
"coreBlocks.proposeRunningThreshold": [{
|
|
85909
|
+
name: "deviceId",
|
|
85910
|
+
form: "single",
|
|
85911
|
+
optional: false
|
|
85912
|
+
}],
|
|
85762
85913
|
"cover.close": [{
|
|
85763
85914
|
name: "deviceId",
|
|
85764
85915
|
form: "single",
|
|
@@ -88422,99 +88573,6 @@ Object.freeze({
|
|
|
88422
88573
|
"network-access": "ingress",
|
|
88423
88574
|
"smtp-provider": "email"
|
|
88424
88575
|
});
|
|
88425
|
-
/**
|
|
88426
|
-
* A saved Customize assignment (D936). The schema is the type: callers use
|
|
88427
|
-
* `z.infer`, they do not restate the shape.
|
|
88428
|
-
*/
|
|
88429
|
-
var OverrideSourceSchema = object({
|
|
88430
|
-
addonId: string().min(1),
|
|
88431
|
-
stableId: string().min(1),
|
|
88432
|
-
cap: string().min(1),
|
|
88433
|
-
fieldPath: string().min(1)
|
|
88434
|
-
});
|
|
88435
|
-
var CustomizeTransformDraftSchema = discriminatedUnion("kind", [
|
|
88436
|
-
object({ kind: literal("identity") }),
|
|
88437
|
-
object({ kind: literal("invert") }),
|
|
88438
|
-
object({
|
|
88439
|
-
kind: literal("threshold"),
|
|
88440
|
-
comparison: _enum(["gte", "lte"]),
|
|
88441
|
-
threshold: number(),
|
|
88442
|
-
startDwellMs: number().nonnegative(),
|
|
88443
|
-
stopDwellMs: number().nonnegative()
|
|
88444
|
-
}),
|
|
88445
|
-
object({
|
|
88446
|
-
kind: literal("linear"),
|
|
88447
|
-
scale: number(),
|
|
88448
|
-
offset: number(),
|
|
88449
|
-
clampMin: number().optional(),
|
|
88450
|
-
clampMax: number().optional()
|
|
88451
|
-
}),
|
|
88452
|
-
object({
|
|
88453
|
-
kind: literal("enum-map"),
|
|
88454
|
-
mapping: record(string(), string().nullable())
|
|
88455
|
-
}),
|
|
88456
|
-
object({ kind: literal("number") })
|
|
88457
|
-
]);
|
|
88458
|
-
var ScalarOverrideDraftSchema = object({
|
|
88459
|
-
kind: literal("scalar"),
|
|
88460
|
-
cap: string().min(1),
|
|
88461
|
-
targetId: string().min(1),
|
|
88462
|
-
source: OverrideSourceSchema,
|
|
88463
|
-
transform: CustomizeTransformDraftSchema
|
|
88464
|
-
});
|
|
88465
|
-
var KeyedArrayOverrideDraftSchema = object({
|
|
88466
|
-
kind: literal("keyedArray"),
|
|
88467
|
-
cap: string().min(1),
|
|
88468
|
-
targetId: string().min(1),
|
|
88469
|
-
key: string().min(1),
|
|
88470
|
-
label: string().min(1),
|
|
88471
|
-
fieldPath: string().min(1),
|
|
88472
|
-
source: OverrideSourceSchema,
|
|
88473
|
-
transform: CustomizeTransformDraftSchema
|
|
88474
|
-
});
|
|
88475
|
-
var PulseOverrideDraftSchema = object({
|
|
88476
|
-
kind: literal("pulse"),
|
|
88477
|
-
cap: string().min(1),
|
|
88478
|
-
targetId: string().min(1),
|
|
88479
|
-
enabled: boolean(),
|
|
88480
|
-
debounceMs: number().nonnegative(),
|
|
88481
|
-
edges: array(_enum([
|
|
88482
|
-
"rising",
|
|
88483
|
-
"button",
|
|
88484
|
-
"native-event"
|
|
88485
|
-
])).min(1).optional(),
|
|
88486
|
-
sources: array(OverrideSourceSchema).min(1)
|
|
88487
|
-
});
|
|
88488
|
-
var SpanSourceDraftSchema = OverrideSourceSchema.extend({ mode: _enum([
|
|
88489
|
-
"in-addition",
|
|
88490
|
-
"confirm",
|
|
88491
|
-
"replace"
|
|
88492
|
-
]).optional() });
|
|
88493
|
-
discriminatedUnion("kind", [
|
|
88494
|
-
ScalarOverrideDraftSchema,
|
|
88495
|
-
KeyedArrayOverrideDraftSchema,
|
|
88496
|
-
PulseOverrideDraftSchema,
|
|
88497
|
-
object({
|
|
88498
|
-
kind: literal("span"),
|
|
88499
|
-
cap: string().min(1),
|
|
88500
|
-
targetId: string().min(1),
|
|
88501
|
-
timeoutMs: number().nonnegative(),
|
|
88502
|
-
cooldownMs: number().nonnegative().optional(),
|
|
88503
|
-
sources: array(SpanSourceDraftSchema)
|
|
88504
|
-
})
|
|
88505
|
-
]);
|
|
88506
|
-
object({
|
|
88507
|
-
targetId: string().min(1),
|
|
88508
|
-
configured: boolean(),
|
|
88509
|
-
source: _enum(["native", "assigned"]),
|
|
88510
|
-
state: _enum([
|
|
88511
|
-
"active",
|
|
88512
|
-
"stale",
|
|
88513
|
-
"released",
|
|
88514
|
-
"unavailable"
|
|
88515
|
-
]),
|
|
88516
|
-
reason: string().nullable()
|
|
88517
|
-
});
|
|
88518
88576
|
var G711_SCALE_CORRECTION_DB = {
|
|
88519
88577
|
PCMU: 20 * Math.log10(4),
|
|
88520
88578
|
PCMA: 20 * Math.log10(8)
|
|
@@ -89866,7 +89924,7 @@ var AgentUIAddon = class extends BaseAddon {
|
|
|
89866
89924
|
capability: adminUiCapability,
|
|
89867
89925
|
provider: {
|
|
89868
89926
|
getStaticDir: async () => ({ staticDir: path.resolve(__dirname) }),
|
|
89869
|
-
getVersion: async () => ({ version: "1.2.
|
|
89927
|
+
getVersion: async () => ({ version: "1.2.320" })
|
|
89870
89928
|
}
|
|
89871
89929
|
}];
|
|
89872
89930
|
}
|
|
@@ -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-BXAblT4K.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-ByJhjoZZ.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-BXAblT4K.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};
|