@homebridge-plugins/homebridge-eufy-security 5.0.0-beta.35 → 5.0.0-beta.37

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.
Files changed (87) hide show
  1. package/CONTRIBUTING.md +9 -17
  2. package/config.schema.json +6 -0
  3. package/dist/account/ownership.js +16 -16
  4. package/dist/account/ownership.js.map +1 -1
  5. package/dist/account/persistence.js +24 -74
  6. package/dist/account/persistence.js.map +1 -1
  7. package/dist/account/temporary-authentication.js +2 -2
  8. package/dist/account/temporary-authentication.js.map +1 -1
  9. package/dist/configuration.js +18 -25
  10. package/dist/configuration.js.map +1 -1
  11. package/dist/device/member-evidence.js +1 -1
  12. package/dist/device/member-evidence.js.map +1 -1
  13. package/dist/device/member-trust.js +14 -32
  14. package/dist/device/member-trust.js.map +1 -1
  15. package/dist/device/snapshot.js +5 -17
  16. package/dist/device/snapshot.js.map +1 -1
  17. package/dist/diagnostics.js +268 -308
  18. package/dist/diagnostics.js.map +1 -1
  19. package/dist/homekit/adapter.js +4 -1
  20. package/dist/homekit/adapter.js.map +1 -1
  21. package/dist/homekit/adapters/battery.js +3 -3
  22. package/dist/homekit/adapters/battery.js.map +1 -1
  23. package/dist/homekit/adapters/camera-controls.js +15 -37
  24. package/dist/homekit/adapters/camera-controls.js.map +1 -1
  25. package/dist/homekit/adapters/camera-streaming.js +9 -19
  26. package/dist/homekit/adapters/camera-streaming.js.map +1 -1
  27. package/dist/homekit/adapters/contact.js +5 -5
  28. package/dist/homekit/adapters/contact.js.map +1 -1
  29. package/dist/homekit/adapters/doorbell.js +3 -15
  30. package/dist/homekit/adapters/doorbell.js.map +1 -1
  31. package/dist/homekit/adapters/lock.js +15 -214
  32. package/dist/homekit/adapters/lock.js.map +1 -1
  33. package/dist/homekit/adapters/motion.js +2 -2
  34. package/dist/homekit/adapters/motion.js.map +1 -1
  35. package/dist/homekit/adapters/package-sensor.js +2 -2
  36. package/dist/homekit/adapters/package-sensor.js.map +1 -1
  37. package/dist/homekit/adapters/security-system.js +11 -211
  38. package/dist/homekit/adapters/security-system.js.map +1 -1
  39. package/dist/homekit/adapters/siren.js +5 -33
  40. package/dist/homekit/adapters/siren.js.map +1 -1
  41. package/dist/homekit/adapters/smart-light.js +19 -217
  42. package/dist/homekit/adapters/smart-light.js.map +1 -1
  43. package/dist/homekit/coverage-matrix.js +8 -65
  44. package/dist/homekit/coverage-matrix.js.map +1 -1
  45. package/dist/homekit/device-control.js +249 -13
  46. package/dist/homekit/device-control.js.map +1 -1
  47. package/dist/homekit/reconciler.js +5 -5
  48. package/dist/homekit/reconciler.js.map +1 -1
  49. package/dist/media/last-successful-image.js +3 -20
  50. package/dist/media/last-successful-image.js.map +1 -1
  51. package/dist/media/live-preview.js +163 -42
  52. package/dist/media/live-preview.js.map +1 -1
  53. package/dist/media/live-stream.js +126 -72
  54. package/dist/media/live-stream.js.map +1 -1
  55. package/dist/media/recording.js +37 -120
  56. package/dist/media/recording.js.map +1 -1
  57. package/dist/media/snapshot.js +1 -9
  58. package/dist/media/snapshot.js.map +1 -1
  59. package/dist/media/station-live-sessions.js +0 -15
  60. package/dist/media/station-live-sessions.js.map +1 -1
  61. package/dist/platform.js +10 -10
  62. package/dist/platform.js.map +1 -1
  63. package/dist/runtime/channel.js +91 -69
  64. package/dist/runtime/channel.js.map +1 -1
  65. package/dist/runtime/owner.js +6 -6
  66. package/dist/runtime/owner.js.map +1 -1
  67. package/dist/runtime/sdk-client.js +3 -14
  68. package/dist/runtime/sdk-client.js.map +1 -1
  69. package/dist/runtime/tracker.js +8 -38
  70. package/dist/runtime/tracker.js.map +1 -1
  71. package/dist/storage.js +1 -1
  72. package/dist/storage.js.map +1 -1
  73. package/dist/ui/runtime-channel-client.js +145 -282
  74. package/dist/ui/runtime-channel-client.js.map +1 -1
  75. package/dist/ui/server.js +39 -53
  76. package/dist/ui/server.js.map +1 -1
  77. package/homebridge-ui/public/app.css +150 -78
  78. package/homebridge-ui/public/i18n/en.json +15 -2
  79. package/homebridge-ui/public/i18n/fr.json +15 -2
  80. package/homebridge-ui/public/index.html +59 -10
  81. package/homebridge-ui/public/js/app.js +206 -42
  82. package/homebridge-ui/public/js/dashboard.js +4 -19
  83. package/i18n/runtime/en.json +1 -0
  84. package/package.json +3 -7
  85. package/homebridge-ui/public/js/legacy-settings.js +0 -37
  86. package/homebridge-ui/public/js/profile-wizard.js +0 -31
  87. package/homebridge-ui/public/js/setup-wizard.js +0 -52
@@ -107,6 +107,11 @@ body {
107
107
  sans-serif;
108
108
  -webkit-font-smoothing: antialiased;
109
109
  text-rendering: optimizeLegibility;
110
+ accent-color: var(--accent);
111
+ }
112
+
113
+ ::selection {
114
+ background: color-mix(in srgb, var(--accent) 28%, transparent);
110
115
  }
111
116
 
112
117
  .shell {
@@ -263,7 +268,8 @@ h2 {
263
268
  color: var(--muted);
264
269
  }
265
270
 
266
- .diagnostics-panel select {
271
+ .diagnostics-panel select,
272
+ .wizard-setting select {
267
273
  width: 100%;
268
274
  min-height: 44px;
269
275
  margin-top: 8px;
@@ -444,7 +450,7 @@ button.diagnostics-quiet-action {
444
450
  align-items: center;
445
451
  justify-content: center;
446
452
  gap: 8px;
447
- padding: 10px 6px;
453
+ padding: 12px 8px;
448
454
  border: 1px solid var(--line-strong);
449
455
  background: transparent;
450
456
  color: var(--ink);
@@ -670,8 +676,8 @@ button.diagnostics-quiet-action {
670
676
  .dashboard-action:has(.diagnostics-name) {
671
677
  width: auto;
672
678
  grid-auto-flow: column;
673
- gap: 6px;
674
- padding: 0 10px;
679
+ gap: 8px;
680
+ padding: 0 12px;
675
681
  }
676
682
 
677
683
  .dashboard-action[data-collecting] {
@@ -712,7 +718,7 @@ button.diagnostics-quiet-action {
712
718
  width: 8px;
713
719
  height: 8px;
714
720
  border: 2px solid var(--panel);
715
- border-radius: 50%;
721
+ border-radius: var(--radius-pill);
716
722
  background: var(--alert);
717
723
  }
718
724
 
@@ -822,7 +828,7 @@ button.diagnostics-quiet-action {
822
828
  padding: 12px;
823
829
  }
824
830
 
825
- .device-tile:not([data-device-class='camera']) /*
831
+ /*
826
832
  * A device's settings are a page rather than a face on the tile, so they are read at the page's scale and have as
827
833
  * much room as the device needs. The tile is the summary and the way in; nothing about its size bounds this.
828
834
  */
@@ -867,7 +873,7 @@ button.diagnostics-quiet-action {
867
873
  }
868
874
  }
869
875
 
870
- .diagnostic-panel img {
876
+ .device-tile:not([data-device-class='camera']) .diagnostic-panel img {
871
877
  display: none;
872
878
  }
873
879
 
@@ -885,7 +891,7 @@ button.diagnostics-quiet-action {
885
891
  width: 8px;
886
892
  height: 8px;
887
893
  border: 2px solid var(--tile-bg);
888
- border-radius: 50%;
894
+ border-radius: var(--radius-pill);
889
895
  background: var(--alert);
890
896
  pointer-events: none;
891
897
  }
@@ -1291,7 +1297,7 @@ button.diagnostics-quiet-action {
1291
1297
  font-weight: 700;
1292
1298
  }
1293
1299
 
1294
- .preference-grid .preference-changed /*
1300
+ /*
1295
1301
  * The guard-mode map: four HomeKit states against nine station modes, one pairing per row.
1296
1302
  *
1297
1303
  * A table because the content is one, which also gives each select its own row label without a second element
@@ -1307,7 +1313,7 @@ button.diagnostics-quiet-action {
1307
1313
  display: grid;
1308
1314
  grid-template-columns: minmax(0, 1fr) 12px;
1309
1315
  align-items: center;
1310
- gap: 2px 8px;
1316
+ gap: 4px 8px;
1311
1317
  cursor: pointer;
1312
1318
  }
1313
1319
 
@@ -1353,7 +1359,7 @@ button.diagnostics-quiet-action {
1353
1359
  }
1354
1360
 
1355
1361
  .arming-table thead th {
1356
- padding: 0 0 6px;
1362
+ padding: 0 0 4px;
1357
1363
  border-bottom: 1px solid var(--line-strong);
1358
1364
  color: var(--muted);
1359
1365
  font-size: 10px;
@@ -1370,7 +1376,7 @@ button.diagnostics-quiet-action {
1370
1376
 
1371
1377
  .arming-table th[scope='row'] {
1372
1378
  width: 38%;
1373
- padding: 6px 10px 6px 0;
1379
+ padding: 4px 8px 4px 0;
1374
1380
  color: var(--ink);
1375
1381
  font-size: 11px;
1376
1382
  font-weight: 600;
@@ -1382,7 +1388,7 @@ button.diagnostics-quiet-action {
1382
1388
  }
1383
1389
 
1384
1390
  .arming-table td {
1385
- padding: 6px 0;
1391
+ padding: 4px 0;
1386
1392
  }
1387
1393
 
1388
1394
  .arming-table select {
@@ -1392,13 +1398,13 @@ button.diagnostics-quiet-action {
1392
1398
  border-radius: var(--radius-control);
1393
1399
  background: var(--panel);
1394
1400
  color: var(--ink);
1395
- padding: 2px 6px;
1401
+ padding: 4px 8px;
1396
1402
  font-size: 11px;
1397
1403
  }
1398
1404
 
1399
1405
  /* The changed row carries the weight, so a pending map reads as which pairing moved rather than as a heavier table. */
1400
1406
  .arming-setting .snapshot-help {
1401
- margin-top: 6px;
1407
+ margin-top: 8px;
1402
1408
  }
1403
1409
 
1404
1410
  .arming-table select.preference-control-changed {
@@ -1412,7 +1418,7 @@ button.diagnostics-quiet-action {
1412
1418
  }
1413
1419
  }
1414
1420
 
1415
- .snapshot-description {
1421
+ .preference-grid .preference-changed .snapshot-description {
1416
1422
  font-weight: 400;
1417
1423
  }
1418
1424
 
@@ -1513,7 +1519,7 @@ button.diagnostics-quiet-action {
1513
1519
  left: 2px;
1514
1520
  width: 14px;
1515
1521
  height: 14px;
1516
- border-radius: 50%;
1522
+ border-radius: var(--radius-pill);
1517
1523
  background: var(--panel);
1518
1524
  box-shadow: 0 1px 2px rgb(0 0 0 / 22%);
1519
1525
  transition: transform 140ms var(--ease-out);
@@ -1762,7 +1768,6 @@ button {
1762
1768
  text-align: center;
1763
1769
  }
1764
1770
 
1765
- /* One setting per row, so a control that needs width gets it and nothing sits half-read beside it. */
1766
1771
  /*
1767
1772
  * Two lists with a column of transfer buttons between them, sharing the parent's rows so the three columns line up.
1768
1773
  *
@@ -1900,11 +1905,11 @@ button {
1900
1905
  transform 100ms var(--ease-out);
1901
1906
  }
1902
1907
 
1903
- button:hover:not(:disabled) {
1908
+ button:hover:not(:disabled, .wizard-live-play) {
1904
1909
  background: color-mix(in srgb, var(--accent) 88%, var(--on-accent));
1905
1910
  }
1906
1911
 
1907
- button:active:not(:disabled, .device-open-control) {
1912
+ button:active:not(:disabled, .device-open-control, .wizard-live-play) {
1908
1913
  transform: scale(0.97);
1909
1914
  }
1910
1915
 
@@ -1936,6 +1941,21 @@ button.diagnostics-quiet-action:hover:not(:disabled) {
1936
1941
  background: transparent;
1937
1942
  }
1938
1943
 
1944
+ .wizard-map-device:hover:not(:disabled, [aria-current='step']) {
1945
+ background: color-mix(in srgb, var(--ink) 5%, transparent);
1946
+ }
1947
+
1948
+ .wizard-map-device[aria-current='step']:hover {
1949
+ background: color-mix(in srgb, var(--accent) 16%, transparent);
1950
+ }
1951
+
1952
+ /* The frame is black in both themes, so the icon's fill is a fixed deep teal the white glyph reads against; the
1953
+ button itself covers the whole frame and stays transparent. */
1954
+ .wizard-live-play:hover:not(:disabled) img,
1955
+ .wizard-live-play:focus-visible img {
1956
+ background: color-mix(in srgb, var(--accent) 55%, #000000);
1957
+ }
1958
+
1939
1959
  /*
1940
1960
  * The tile is the dashboard's primary target and artwork covers everything but its edge, so the edge carries the
1941
1961
  * hover. A step in `--line` alone was too quiet to register as feedback; the accent in the edge is not.
@@ -2004,7 +2024,6 @@ input:focus-visible {
2004
2024
  display: none;
2005
2025
  }
2006
2026
 
2007
-
2008
2027
  .status-row {
2009
2028
  display: grid;
2010
2029
  }
@@ -2018,11 +2037,11 @@ input:focus-visible {
2018
2037
  }
2019
2038
 
2020
2039
  .legacy-notice {
2021
- display: grid;
2040
+ grid-template-columns: auto minmax(0, 1fr);
2022
2041
  }
2023
2042
 
2024
2043
  .legacy-notice button {
2025
- width: 100%;
2044
+ grid-column: 1 / -1;
2026
2045
  }
2027
2046
  }
2028
2047
 
@@ -2069,10 +2088,6 @@ input:focus-visible {
2069
2088
  }
2070
2089
 
2071
2090
  @media (max-width: 520px) {
2072
- .advanced-fields {
2073
- grid-template-columns: 1fr;
2074
- }
2075
-
2076
2091
  .diagnostics-actions button {
2077
2092
  width: 100%;
2078
2093
  }
@@ -2119,7 +2134,6 @@ input:focus-visible {
2119
2134
  gap: 4px;
2120
2135
  padding: 32px 16px 8px;
2121
2136
  }
2122
-
2123
2137
  }
2124
2138
 
2125
2139
  .shell[data-theme='dark'] {
@@ -2172,45 +2186,85 @@ input:focus-visible {
2172
2186
  display: block;
2173
2187
  }
2174
2188
 
2189
+ /* Sized by its container alone, never by a picture, and never selected or dragged by a click on it. One 16:9 frame
2190
+ split down the middle: the camera's left half beside the right half of the same view as HomeKit receives it. */
2175
2191
  .wizard-live {
2176
2192
  position: relative;
2177
2193
  aspect-ratio: 16 / 9;
2194
+ min-width: 0;
2178
2195
  overflow: hidden;
2179
- border-radius: 12px;
2180
- background: #000;
2196
+ border-radius: var(--radius-card);
2197
+ background: #000000;
2198
+ user-select: none;
2199
+ -webkit-user-select: none;
2200
+ -webkit-touch-callout: none;
2181
2201
  }
2182
2202
 
2183
- .wizard-live > img {
2203
+ .wizard-live figure {
2204
+ position: absolute;
2205
+ inset: 0;
2206
+ margin: 0;
2207
+ clip-path: inset(0 50% 0 0);
2208
+ }
2209
+
2210
+ .wizard-live figure + figure {
2211
+ clip-path: inset(0 0 0 50%);
2212
+ }
2213
+
2214
+ /* Until the HomeKit side has a picture, the camera's picture shows whole, with no split and no labels. */
2215
+ .wizard-live:has(figure + figure > img[hidden]) figure {
2216
+ clip-path: none;
2217
+ }
2218
+
2219
+ .wizard-live:has(figure + figure > img[hidden]) :is(.wizard-live-label, figure + figure),
2220
+ .wizard-live:has(figure + figure > img[hidden])::after {
2221
+ display: none;
2222
+ }
2223
+
2224
+ .wizard-live::after {
2225
+ position: absolute;
2226
+ inset: 0 auto 0 50%;
2227
+ width: 2px;
2228
+ margin-left: -1px;
2229
+ background: rgb(255 255 255 / 80%);
2230
+ content: '';
2231
+ pointer-events: none;
2232
+ }
2233
+
2234
+ .wizard-live figure > img {
2184
2235
  display: block;
2185
2236
  width: 100%;
2186
2237
  height: 100%;
2187
2238
  object-fit: contain;
2239
+ pointer-events: none;
2188
2240
  }
2189
2241
 
2242
+ /* The whole box plays and stops; the pill is the icon. */
2190
2243
  .wizard-live-play {
2191
2244
  position: absolute;
2192
- inset: 50% auto auto 50%;
2245
+ z-index: 1;
2246
+ inset: 0;
2193
2247
  display: grid;
2194
2248
  place-items: center;
2195
- width: 72px;
2196
- height: 52px;
2197
2249
  padding: 0;
2198
2250
  border: 0;
2199
- border-radius: 14px;
2200
- background: rgb(0 0 0 / 70%);
2201
- transform: translate(-50%, -50%);
2251
+ background: transparent;
2202
2252
  cursor: pointer;
2203
2253
  }
2204
2254
 
2205
- .wizard-live-play:hover,
2206
- .wizard-live-play:focus-visible {
2207
- background: #e53935;
2255
+ .wizard-live-play img {
2256
+ box-sizing: border-box;
2257
+ width: 72px;
2258
+ height: 52px;
2259
+ padding: 8px 18px;
2260
+ border-radius: var(--radius-card);
2261
+ background: rgb(0 0 0 / 70%);
2208
2262
  }
2209
2263
 
2210
2264
  /* Stop stays out of the picture until the pointer or the keyboard is on the video. */
2211
2265
  .wizard-live-stop {
2212
2266
  opacity: 0;
2213
- transition: opacity 0.15s;
2267
+ transition: opacity 150ms var(--ease-out);
2214
2268
  }
2215
2269
 
2216
2270
  .wizard-live:hover .wizard-live-stop,
@@ -2224,24 +2278,45 @@ input:focus-visible {
2224
2278
  }
2225
2279
  }
2226
2280
 
2227
- .wizard-live-play img {
2228
- width: 36px;
2229
- height: 36px;
2230
- }
2231
-
2281
+ /* The reason the box has no picture, centred and large; below the spinner or the play button when either shows. */
2232
2282
  .wizard-live-status {
2233
2283
  position: absolute;
2234
- inset: auto 0 0;
2284
+ inset: 0;
2285
+ display: grid;
2286
+ place-items: center;
2235
2287
  margin: 0;
2236
- padding: 8px 12px;
2237
- color: #fff;
2238
- background: linear-gradient(transparent, rgb(0 0 0 / 70%));
2288
+ pointer-events: none;
2289
+ padding: 24px;
2290
+ color: var(--tile-scene-ink);
2291
+ font-size: 1.5rem;
2292
+ font-weight: 600;
2293
+ text-align: center;
2294
+ background: rgb(0 0 0 / 45%);
2295
+ }
2296
+
2297
+ .wizard-live:has(.wizard-live-spinner:not([hidden]), [data-wizard-live-play]:not([hidden])) .wizard-live-status {
2298
+ padding-top: 120px;
2239
2299
  }
2240
2300
 
2241
2301
  .wizard-live-status:empty {
2242
2302
  display: none;
2243
2303
  }
2244
2304
 
2305
+ /* Over the picture, so showing it does not move the play and stop buttons under the pointer. */
2306
+ .wizard-live-label {
2307
+ position: absolute;
2308
+ inset: 0 50% auto 0;
2309
+ margin: 0;
2310
+ padding: 8px 12px;
2311
+ color: var(--tile-scene-ink);
2312
+ background: linear-gradient(rgb(0 0 0 / 70%), transparent);
2313
+ }
2314
+
2315
+ .wizard-live figure + figure .wizard-live-label {
2316
+ inset: 0 0 auto 50%;
2317
+ text-align: right;
2318
+ }
2319
+
2245
2320
  .wizard-nav {
2246
2321
  display: flex;
2247
2322
  justify-content: flex-end;
@@ -2252,8 +2327,9 @@ input:focus-visible {
2252
2327
  flex-wrap: wrap;
2253
2328
  gap: 12px;
2254
2329
  padding: 12px;
2255
- border: 1px solid var(--border, rgb(128 128 128 / 30%));
2256
- border-radius: 12px;
2330
+ border: 1px solid var(--line);
2331
+ border-radius: var(--radius-card);
2332
+ background: var(--panel);
2257
2333
  }
2258
2334
 
2259
2335
  .wizard-map-group {
@@ -2261,7 +2337,7 @@ input:focus-visible {
2261
2337
  }
2262
2338
 
2263
2339
  .wizard-map-base {
2264
- margin: 0 0 6px;
2340
+ margin: 0 0 4px;
2265
2341
  font-weight: 600;
2266
2342
  }
2267
2343
 
@@ -2269,49 +2345,43 @@ input:focus-visible {
2269
2345
  display: flex;
2270
2346
  flex-direction: column;
2271
2347
  gap: 4px;
2272
- padding-left: 14px;
2273
- border-left: 2px solid rgb(128 128 128 / 40%);
2348
+ padding-left: 12px;
2349
+ border-left: 2px solid var(--line-strong);
2274
2350
  }
2275
2351
 
2276
2352
  .wizard-map-device {
2277
2353
  padding: 4px 8px;
2278
2354
  border: 0;
2279
- border-radius: 6px;
2355
+ border-radius: var(--radius-sm);
2280
2356
  background: transparent;
2281
2357
  color: inherit;
2282
2358
  text-align: left;
2283
2359
  cursor: pointer;
2284
2360
  }
2285
2361
 
2286
- .wizard-map-device[aria-current='step'] {
2287
- background: rgb(229 57 53 / 15%);
2288
- font-weight: 600;
2289
- }
2290
-
2291
- .wizard-stage {
2292
- display: grid;
2293
- grid-template-columns: auto 1fr auto;
2362
+ /* A HomeBase heading is a button and a standalone heading is not: the plain one takes the button's size. */
2363
+ p.wizard-map-base {
2364
+ display: flex;
2294
2365
  align-items: center;
2295
- gap: 8px;
2366
+ min-height: 44px;
2367
+ padding: 4px 8px;
2296
2368
  }
2297
2369
 
2298
- .wizard-arrow {
2299
- display: grid;
2300
- place-items: center;
2301
- width: 40px;
2302
- height: 40px;
2303
- padding: 0;
2304
- border-radius: 50%;
2370
+ .wizard-map-device[aria-current='step'] {
2371
+ background: color-mix(in srgb, var(--accent) 16%, transparent);
2372
+ color: var(--accent-ink);
2373
+ font-weight: 600;
2305
2374
  }
2306
2375
 
2307
- .wizard-arrow:disabled {
2308
- visibility: hidden;
2376
+ .wizard-live figure + figure .wizard-live-spinner {
2377
+ left: 75%;
2309
2378
  }
2310
2379
 
2311
2380
  .wizard-card {
2312
2381
  padding: 12px 16px;
2313
- border: 1px solid var(--border, rgb(128 128 128 / 30%));
2314
- border-radius: 12px;
2382
+ border: 1px solid var(--line);
2383
+ border-radius: var(--radius-card);
2384
+ background: var(--panel);
2315
2385
  }
2316
2386
 
2317
2387
  .wizard-card h3 {
@@ -2325,8 +2395,8 @@ input:focus-visible {
2325
2395
  height: 48px;
2326
2396
  margin: -24px 0 0 -24px;
2327
2397
  border: 4px solid rgb(255 255 255 / 30%);
2328
- border-top-color: #fff;
2329
- border-radius: 50%;
2398
+ border-top-color: var(--tile-scene-ink);
2399
+ border-radius: var(--radius-pill);
2330
2400
  animation: wizard-live-spin 0.9s linear infinite;
2331
2401
  }
2332
2402
 
@@ -2350,5 +2420,7 @@ input:focus-visible {
2350
2420
  }
2351
2421
 
2352
2422
  .wizard-setting select {
2423
+ width: auto;
2353
2424
  min-width: 160px;
2425
+ margin-top: 0;
2354
2426
  }
@@ -173,6 +173,7 @@
173
173
  "log.action.retryCameraControl": "Try the control again; the camera did not confirm the change.",
174
174
  "log.action.retryLight": "Retry the smart-light control manually.",
175
175
  "log.action.retryLiveView": "Open live view again, and check network access between Homebridge and the camera.",
176
+ "log.action.retryLiveViewNoPicture": "The camera answered but sent no picture in time. Open live view again; if it keeps happening, send a diagnostics file.",
176
177
  "log.action.retryLock": "Retry the lock control manually.",
177
178
  "log.action.retryRecording": "No action is needed; recording is attempted again on the next trigger.",
178
179
  "log.action.retryTalkback": "Close and reopen the camera, then try speaking again.",
@@ -263,12 +264,24 @@
263
264
  "wizardTitle": "Setup assistant",
264
265
  "wizardProgress": "Device {current} of {total}",
265
266
  "wizardRestartSummary": "Restart Homebridge to connect your cameras. This assistant opens again on its own once the plugin is running, to go through each device with you.",
266
- "wizardBack": "Back",
267
- "wizardNext": "Next",
268
267
  "wizardFinish": "Finish",
269
268
  "wizardClose": "Close",
270
269
  "wizardLiveStarting": "Connecting to the camera. This can take up to 30 seconds.",
271
270
  "wizardLiveFailed": "The camera did not send video. Check it is on and online, then try again.",
271
+ "wizardLiveEncoder": "{encoder} coded this video at {kbps} kbps, as HomeKit receives it.",
272
+ "wizardLiveCamera": "The camera",
273
+ "wizardLiveHomeKit": "As HomeKit receives it",
274
+ "wizardLiveAsk": "Watched on",
275
+ "wizardLiveAskWifi": "iPhone on Wi-Fi",
276
+ "wizardLiveAskCellular": "iPhone on cellular",
277
+ "wizardLiveSave": "Save for this camera",
278
+ "wizardLiveTitle": "Live video in HomeKit",
279
+ "wizardLiveThisCamera": "This camera",
280
+ "wizardLiveAllCameras": "All cameras, saved with the plugin settings",
281
+ "wizardLiveHelp": "Try a setting on the HomeKit picture above before keeping it.",
282
+ "wizardLiveUnplayable": "The video coded for HomeKit did not produce a picture, so the Home app will likely fail to show it too.",
283
+ "wizardLiveDiagnoseHelp": "A live video diagnostics capture records why, so it can be reported and fixed.",
284
+ "wizardLiveDiagnose": "Capture diagnostics",
272
285
  "wizardEufySettings": "Camera settings in the eufy app",
273
286
  "wizardMotionDetection": "Motion detection",
274
287
  "wizardNightVision": "Night vision",
@@ -173,6 +173,7 @@
173
173
  "log.action.retryCameraControl": "Réessayez la commande ; la caméra n’a pas confirmé le changement.",
174
174
  "log.action.retryLight": "Relancez manuellement la commande de l’éclairage.",
175
175
  "log.action.retryLiveView": "Rouvrez la vue en direct et vérifiez l’accès réseau entre Homebridge et la caméra.",
176
+ "log.action.retryLiveViewNoPicture": "La caméra a répondu mais n’a envoyé aucune image à temps. Rouvrez la vue en direct ; si cela se reproduit, envoyez un fichier de diagnostic.",
176
177
  "log.action.retryLock": "Relancez manuellement la commande de la serrure.",
177
178
  "log.action.retryRecording": "Aucune action n’est nécessaire ; l’enregistrement sera retenté au prochain déclenchement.",
178
179
  "log.action.retryTalkback": "Fermez et rouvrez la caméra, puis essayez de parler de nouveau.",
@@ -263,12 +264,24 @@
263
264
  "wizardTitle": "Assistant de configuration",
264
265
  "wizardProgress": "Appareil {current} sur {total}",
265
266
  "wizardRestartSummary": "Redémarrez Homebridge pour connecter vos caméras. Cet assistant s’ouvrira de lui-même une fois le plugin lancé, pour passer chaque appareil en revue avec vous.",
266
- "wizardBack": "Retour",
267
- "wizardNext": "Suivant",
268
267
  "wizardFinish": "Terminer",
269
268
  "wizardClose": "Fermer",
270
269
  "wizardLiveStarting": "Connexion à la caméra. Cela peut prendre jusqu’à 30 secondes.",
271
270
  "wizardLiveFailed": "La caméra n’a pas envoyé de vidéo. Vérifiez qu’elle est allumée et en ligne, puis réessayez.",
271
+ "wizardLiveEncoder": "{encoder} a codé cette vidéo à {kbps} kbit/s, comme HomeKit la reçoit.",
272
+ "wizardLiveCamera": "La caméra",
273
+ "wizardLiveHomeKit": "Comme HomeKit la reçoit",
274
+ "wizardLiveAsk": "Regardée sur",
275
+ "wizardLiveAskWifi": "iPhone en Wi-Fi",
276
+ "wizardLiveAskCellular": "iPhone en réseau mobile",
277
+ "wizardLiveSave": "Enregistrer pour cette caméra",
278
+ "wizardLiveTitle": "Vidéo en direct dans HomeKit",
279
+ "wizardLiveThisCamera": "Cette caméra",
280
+ "wizardLiveAllCameras": "Toutes les caméras, enregistré avec les réglages du plugin",
281
+ "wizardLiveHelp": "Essayez un réglage sur l’image HomeKit ci-dessus avant de le garder.",
282
+ "wizardLiveUnplayable": "La vidéo codée pour HomeKit n’a produit aucune image, l’app Maison ne l’affichera donc probablement pas non plus.",
283
+ "wizardLiveDiagnoseHelp": "Une capture de diagnostic vidéo en direct enregistre pourquoi, pour pouvoir le signaler et le corriger.",
284
+ "wizardLiveDiagnose": "Capturer un diagnostic",
272
285
  "wizardEufySettings": "Réglages de la caméra dans l’app eufy",
273
286
  "wizardMotionDetection": "Détection de mouvement",
274
287
  "wizardNightVision": "Vision nocturne",
@@ -214,11 +214,16 @@
214
214
  <p class="summary" data-wizard-restart hidden data-i18n="wizardRestartSummary"></p>
215
215
  <nav class="wizard-map" data-wizard-map data-i18n-aria-label="wizardMapLabel"></nav>
216
216
  <div class="wizard-stage" data-wizard-stage>
217
- <button type="button" class="wizard-arrow" data-wizard-back data-i18n-aria-label="wizardBack">
218
- <img src="assets/icons/keyboard_arrow_left.svg" alt="" />
219
- </button>
220
217
  <div class="wizard-live" data-wizard-live>
221
- <img data-wizard-live-image alt="" hidden />
218
+ <figure>
219
+ <img data-wizard-live-image alt="" draggable="false" hidden />
220
+ <figcaption class="wizard-live-label" data-wizard-live-camera data-i18n="wizardLiveCamera"></figcaption>
221
+ </figure>
222
+ <figure>
223
+ <img data-wizard-live-homekit alt="" draggable="false" hidden />
224
+ <span class="wizard-live-spinner" data-wizard-live-homekit-spinner hidden aria-hidden="true"></span>
225
+ <figcaption class="wizard-live-label" data-wizard-live-encoder></figcaption>
226
+ </figure>
222
227
  <button type="button" class="wizard-live-play" data-wizard-live-play data-i18n-aria-label="wizardLivePlay">
223
228
  <img src="assets/icons/play_arrow.svg" alt="" />
224
229
  </button>
@@ -234,10 +239,57 @@
234
239
  <span class="wizard-live-spinner" data-wizard-live-spinner hidden aria-hidden="true"></span>
235
240
  <p class="wizard-live-status" role="status" aria-live="polite" data-wizard-live-status></p>
236
241
  </div>
237
- <button type="button" class="wizard-arrow" data-wizard-next data-i18n-aria-label="wizardNext">
238
- <img src="assets/icons/keyboard_arrow_right.svg" alt="" />
239
- </button>
240
242
  </div>
243
+ <form class="wizard-card" data-wizard-live-controls hidden aria-labelledby="wizard-live-title">
244
+ <h3 id="wizard-live-title" data-i18n="wizardLiveTitle"></h3>
245
+ <p class="preference-note" data-i18n="wizardLiveHelp"></p>
246
+ <div class="preference-grid">
247
+ <label class="wizard-setting" data-setting>
248
+ <span class="setting-label" data-i18n="wizardLiveAsk"></span>
249
+ <select name="ask">
250
+ <option value="wifi" data-i18n="wizardLiveAskWifi"></option>
251
+ <option value="cellular" data-i18n="wizardLiveAskCellular"></option>
252
+ </select>
253
+ </label>
254
+ <p class="preference-representation" data-i18n="wizardLiveThisCamera"></p>
255
+ <div data-setting>
256
+ <label class="toggle">
257
+ <input type="checkbox" name="liveVideoPassthrough" />
258
+ <span class="setting-label" data-i18n="advancedLiveVideoPassthroughLabel"></span>
259
+ </label>
260
+ <p data-i18n="advancedLiveVideoPassthroughHelp"></p>
261
+ </div>
262
+ <div data-setting>
263
+ <label class="toggle">
264
+ <input type="checkbox" name="ignoreHomeBitRate" />
265
+ <span class="setting-label" data-i18n="advancedIgnoreHomeBitRateLabel"></span>
266
+ </label>
267
+ <p data-i18n="advancedIgnoreHomeBitRateHelp"></p>
268
+ </div>
269
+ <div class="wizard-nav">
270
+ <button type="button" data-wizard-live-save data-i18n="wizardLiveSave"></button>
271
+ </div>
272
+ <p class="preference-representation" data-i18n="wizardLiveAllCameras"></p>
273
+ <div data-setting>
274
+ <label class="toggle">
275
+ <input type="checkbox" name="hardwareVideoEncoder" />
276
+ <span class="setting-label" data-i18n="advancedHardwareVideoEncoderLabel"></span>
277
+ </label>
278
+ <p data-i18n="advancedHardwareVideoEncoderHelp"></p>
279
+ </div>
280
+ <div data-setting>
281
+ <label class="toggle">
282
+ <input type="checkbox" name="smallVideoPackets" />
283
+ <span class="setting-label" data-i18n="advancedSmallVideoPacketsLabel"></span>
284
+ </label>
285
+ <p data-i18n="advancedSmallVideoPacketsHelp"></p>
286
+ </div>
287
+ </div>
288
+ </form>
289
+ <p class="summary" data-wizard-live-diagnose hidden>
290
+ <span data-i18n="wizardLiveDiagnoseHelp"></span>
291
+ <button type="button" data-wizard-live-diagnose-start data-i18n="wizardLiveDiagnose"></button>
292
+ </p>
241
293
  <section class="wizard-card" data-wizard-homekit aria-labelledby="wizard-homekit-title">
242
294
  <h3 id="wizard-homekit-title" data-i18n="wizardHomeKitTitle"></h3>
243
295
  <p class="preference-note" data-i18n="wizardHomeKitHelp"></p>
@@ -443,7 +495,4 @@
443
495
  </main>
444
496
 
445
497
  <script src="js/dashboard.js"></script>
446
- <script src="js/legacy-settings.js"></script>
447
- <script src="js/profile-wizard.js"></script>
448
- <script src="js/setup-wizard.js"></script>
449
498
  <script src="js/app.js"></script>