@homebridge-plugins/homebridge-eufy-security 5.0.0-beta.16 → 5.0.0-beta.17

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.
@@ -274,7 +274,9 @@ h2 {
274
274
  padding: 8px 12px;
275
275
  }
276
276
 
277
- .diagnostics-actions {
277
+ .diagnostics-actions:not([hidden]) {
278
+ display: flex;
279
+ gap: 8px;
278
280
  margin-top: 4px;
279
281
  }
280
282
 
@@ -290,42 +292,25 @@ h2 {
290
292
  padding: clamp(16px, 4vw, 24px);
291
293
  }
292
294
 
293
- .diagnostics-question,
294
- .diagnostics-direct,
295
- .diagnostics-frequency,
296
- .diagnostics-match {
295
+ .diagnostics-question {
297
296
  display: grid;
298
297
  gap: 16px;
299
298
  }
300
299
 
301
- .diagnostics-question > strong,
302
- .diagnostics-frequency > strong,
303
- .diagnostics-match > strong {
304
- font-size: clamp(17px, 4vw, 21px);
305
- line-height: 1.35;
306
- letter-spacing: -0.01em;
307
- text-wrap: balance;
308
- }
309
-
310
- .diagnostics-match p {
311
- margin-bottom: 0;
312
- }
313
-
314
- .diagnostics-choice-actions {
315
- display: grid;
316
- grid-template-columns: repeat(2, minmax(0, 1fr));
317
- gap: 8px;
300
+ .diagnostics-question > h3,
301
+ .diagnostics-guidance > h3 {
302
+ margin: 0;
318
303
  }
319
304
 
320
- .diagnostics-choice-actions button {
321
- width: 100%;
322
- padding-inline: 16px;
305
+ .diagnostics-guidance > h3 {
306
+ font-size: inherit;
323
307
  }
324
308
 
325
- button.diagnostics-secondary-action {
326
- border: 1px solid var(--line-strong);
327
- background: transparent;
328
- color: var(--ink);
309
+ .diagnostics-question > h3 {
310
+ font-size: clamp(17px, 4vw, 21px);
311
+ line-height: 1.35;
312
+ letter-spacing: -0.01em;
313
+ text-wrap: balance;
329
314
  }
330
315
 
331
316
  button.diagnostics-quiet-action {
@@ -366,103 +351,83 @@ button.diagnostics-quiet-action {
366
351
  text-transform: uppercase;
367
352
  }
368
353
 
369
- .diagnostics-actions button {
370
- width: 100%;
354
+ .diagnostics-actions [data-diagnostics-reproduction] {
355
+ flex: 1 1 auto;
371
356
  }
372
357
 
358
+ .diagnostics-result h2,
373
359
  .diagnostics-result p {
374
360
  margin-bottom: 0;
375
361
  }
376
362
 
377
- .diagnostics-privacy {
363
+ .diagnostics-note {
364
+ margin-bottom: 0;
378
365
  color: var(--muted);
379
366
  font-size: 12px;
380
367
  }
381
368
 
382
- .diagnostics-result {
369
+ .diagnostics-result[open] {
383
370
  display: grid;
371
+ max-width: 560px;
384
372
  gap: 8px;
385
373
  }
386
374
 
387
375
  /*
388
- * The two steps of the handoff share one shape, so the sequence reads as a sequence: same height, same
389
- * gap, same badge, and a colour each. The download is a button because it acts here; the report is an
390
- * anchor because it navigates to GitHub.
376
+ * The download is a button because it acts here; the two ways to report are anchors because they navigate to
377
+ * GitHub, side by side because either one finishes the handoff.
391
378
  */
392
379
  .diagnostics-result [data-diagnostics-export],
393
- .diagnostics-result [data-diagnostics-issue] {
380
+ .diagnostics-handoff a {
394
381
  display: flex;
395
- width: 100%;
396
382
  min-height: 44px;
397
383
  align-items: center;
398
384
  justify-content: center;
399
- gap: 10px;
400
- margin-top: 8px;
401
385
  border-radius: var(--radius-control);
386
+ padding: 8px 12px;
402
387
  font-weight: 600;
388
+ text-align: center;
403
389
  text-decoration: none;
404
390
  }
405
391
 
406
392
  /*
407
- * The step number is generated content rather than an element, because translation assigns `textContent`
408
- * on the control and would remove any child it had.
393
+ * The dialog sits in the top layer, which adds nothing to the page height Homebridge sizes its iframe by, so the
394
+ * stage keeps room for it rather than leaving it to scroll inside a sliver.
409
395
  */
410
- .diagnostics-result [data-diagnostics-export]::before,
411
- .diagnostics-result [data-diagnostics-issue]::before {
412
- display: inline-flex;
413
- width: 22px;
414
- height: 22px;
415
- flex: none;
416
- align-items: center;
417
- justify-content: center;
418
- border-radius: 50%;
419
- font-size: 12px;
420
- font-variant-numeric: tabular-nums;
421
- font-weight: 700;
422
- }
423
-
424
- /* Each badge inverts its own control's pair, so the digit keeps its contrast on either background. */
425
- .diagnostics-result [data-diagnostics-export]::before {
426
- background: var(--on-accent);
427
- color: var(--accent);
428
- content: '1';
396
+ .diagnostics-stage:has(> .diagnostics-result[open]) {
397
+ min-height: 320px;
429
398
  }
430
399
 
431
- /*
432
- * Step two is the same progression as step one and is filled differently rather than coloured
433
- * differently: a success colour would claim the task is complete, and colour alone must not be what
434
- * tells two controls apart.
435
- */
436
- .diagnostics-result [data-diagnostics-issue] {
437
- border: 1px solid var(--accent);
438
- background: transparent;
439
- color: var(--accent-ink);
400
+ .diagnostics-handoff:not([hidden]) {
401
+ display: grid;
402
+ grid-template-columns: 1fr 1fr;
403
+ gap: 8px;
404
+ margin-top: 8px;
440
405
  }
441
406
 
442
- .diagnostics-result [data-diagnostics-issue]::before {
407
+ .diagnostics-handoff [data-diagnostics-issue] {
443
408
  background: var(--accent);
444
409
  color: var(--on-accent);
445
- content: '2';
446
410
  }
447
411
 
448
- /* Without an archive there is nothing to attach, so the step is present and not yet a link. */
449
- .diagnostics-result a[data-diagnostics-issue][aria-disabled='true'] {
450
- border-color: var(--line);
451
- color: var(--ink-disabled);
452
- cursor: default;
412
+ .diagnostics-handoff [data-diagnostics-existing-issue] {
413
+ border: 1px solid var(--line-strong);
414
+ color: var(--ink);
453
415
  }
454
416
 
455
- .diagnostics-result a[data-diagnostics-issue][aria-disabled='true']::before {
456
- background: var(--ink-disabled);
457
- color: var(--panel);
417
+ .diagnostics-result [data-diagnostics-result-status]:empty {
418
+ display: none;
419
+ }
420
+
421
+ .diagnostics-result [data-diagnostics-download-again],
422
+ .diagnostics-result [data-diagnostics-start-another] {
423
+ justify-self: center;
458
424
  }
459
425
 
460
426
  /*
461
- * The opening screen: every area at once, three to a row.
427
+ * The opening screen: every area at once, three to a row, each label over its one-line summary.
462
428
  *
463
- * Each tile carries a Material Symbols outline glyph (Apache-2.0) as a mask rather than an element, because
464
- * translation assigns `textContent` on the tile and would remove any child it had. A mask also lets the glyph
465
- * take the tile's own colour in every state instead of being baked into an image. The data URI is inline, so
429
+ * Each tile carries a Material Symbols outline glyph (Apache-2.0) as a mask rather than an element. A mask lets
430
+ * the glyph take the tile's own colour in every state instead of being baked into an image. The data URI is inline, so
466
431
  * the panel renders the same on a host with no route to the internet.
467
432
  */
468
433
  .diagnostics-tiles {
@@ -501,6 +466,12 @@ button.diagnostics-quiet-action {
501
466
  mask-size: contain;
502
467
  }
503
468
 
469
+ .diagnostics-tiles small {
470
+ color: var(--muted);
471
+ font-size: 11px;
472
+ font-weight: 400;
473
+ }
474
+
504
475
  .diagnostics-tiles button:hover:not(:disabled) {
505
476
  border-color: var(--accent);
506
477
  background: var(--accent-soft);
@@ -535,107 +506,6 @@ button.diagnostics-quiet-action {
535
506
  mask-image: url('data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%20-960%20960%20960%22%3E%3Cpath%20d=%22M513.5-254.5Q528-269%20528-290t-14.5-35.5Q499-340%20478-340t-35.5%2014.5Q428-311%20428-290t14.5%2035.5Q457-240%20478-240t35.5-14.5ZM442-394h74q0-33%207.5-52t42.5-52q26-26%2041-49.5t15-56.5q0-56-41-86t-97-30q-57%200-92.5%2030T342-618l66%2026q5-18%2022.5-39t53.5-21q32%200%2048%2017.5t16%2038.5q0%2020-12%2037.5T506-526q-44%2039-54%2059t-10%2073Zm38%20314q-83%200-156-31.5T197-197q-54-54-85.5-127T80-480q0-83%2031.5-156T197-763q54-54%20127-85.5T480-880q83%200%20156%2031.5T763-763q54%2054%2085.5%20127T880-480q0%2083-31.5%20156T763-197q-54%2054-127%2085.5T480-80Zm0-80q134%200%20227-93t93-227q0-134-93-227t-227-93q-134%200-227%2093t-93%20227q0%20134%2093%20227t227%2093Zm0-320Z%22/%3E%3C/svg%3E');
536
507
  }
537
508
 
538
- /* The same grid as the areas, so picking hardware reads as the same kind of act as picking an area. */
539
- .diagnostics-device-list {
540
- display: grid;
541
- max-height: 264px;
542
- grid-template-columns: repeat(3, minmax(0, 1fr));
543
- gap: 8px;
544
- overflow-y: auto;
545
- margin: 8px 0 12px;
546
- }
547
-
548
- .diagnostics-device-list button {
549
- display: flex;
550
- min-height: 104px;
551
- flex-direction: column;
552
- align-items: center;
553
- justify-content: center;
554
- gap: 6px;
555
- padding: 8px 6px;
556
- border: 1px solid var(--line-strong);
557
- background: transparent;
558
- color: var(--ink);
559
- font-size: 11px;
560
- font-weight: 600;
561
- line-height: 1.2;
562
- overflow-wrap: break-word;
563
- text-align: center;
564
- }
565
-
566
- .diagnostics-device-list img {
567
- width: 24px;
568
- height: 24px;
569
- flex: none;
570
- }
571
-
572
- /*
573
- * The device's own artwork, contained rather than cropped and at half the tile.
574
- *
575
- * `contain` is how the devices view draws the same image, because it is a cutout of the hardware and not a
576
- * scene: cropping it to fill cuts the device out of its own picture. Half the tile keeps the name it belongs
577
- * to from competing with it. That view's darkening filter is not carried over — it exists to seat the image
578
- * under white text on a coloured tile, and these tiles read dark text on the panel.
579
- */
580
- .diagnostics-device-list img.device-photo {
581
- width: 100%;
582
- max-width: 100%;
583
- height: auto;
584
- max-height: 50%;
585
- object-fit: contain;
586
- }
587
-
588
- .diagnostics-device-list button:hover {
589
- border-color: var(--accent);
590
- background: var(--accent-soft);
591
- }
592
-
593
- /* Pressed is the selection, so it is the border and the fill that say so rather than the colour alone. */
594
- .diagnostics-device-list button[aria-pressed='true'] {
595
- border-color: var(--accent);
596
- border-width: 2px;
597
- background: var(--accent-soft);
598
- color: var(--accent-ink);
599
- }
600
-
601
- .diagnostics-step-hint {
602
- margin: 4px 0 0;
603
- color: var(--muted);
604
- font-size: 12px;
605
- }
606
-
607
- .diagnostics-local-note {
608
- margin: 12px 0 0;
609
- color: var(--ink-secondary);
610
- font-size: 12px;
611
- }
612
-
613
- .diagnostics-result button {
614
- width: 100%;
615
- }
616
-
617
- .diagnostics-manifest {
618
- margin-top: 12px;
619
- border-block: 1px solid var(--line);
620
- padding-block: 8px;
621
- font-size: 12px;
622
- font-variant-numeric: tabular-nums;
623
- }
624
-
625
- .diagnostics-manifest ul {
626
- margin: 8px 0;
627
- padding-left: 20px;
628
- }
629
-
630
- .diagnostics-review-confirm {
631
- display: flex;
632
- align-items: flex-start;
633
- gap: 8px;
634
- margin-top: 12px;
635
- font-size: 12px;
636
- cursor: pointer;
637
- }
638
-
639
509
  .advanced-fields {
640
510
  display: grid;
641
511
  grid-template-columns: 1fr;
@@ -755,6 +625,7 @@ button.diagnostics-quiet-action {
755
625
  border: 1px solid var(--line-strong);
756
626
  border-radius: var(--radius-control);
757
627
  background: var(--panel);
628
+ color: var(--ink);
758
629
  padding: 0;
759
630
  }
760
631
 
@@ -789,41 +660,63 @@ button.diagnostics-quiet-action {
789
660
  transform 150ms var(--ease-out);
790
661
  }
791
662
 
663
+ .dashboard-action[data-collecting],
664
+ .dashboard-action:has(.diagnostics-name) {
665
+ width: auto;
666
+ grid-auto-flow: column;
667
+ gap: 6px;
668
+ padding: 0 10px;
669
+ }
670
+
792
671
  .dashboard-action[data-collecting] {
793
672
  border-color: var(--accent);
794
673
  background: color-mix(in srgb, var(--accent) 16%, var(--panel));
795
674
  }
796
675
 
797
- .dashboard-action:hover::after,
798
- .dashboard-action:focus-visible::after {
799
- opacity: 1;
800
- transform: translateY(0);
801
- }
802
-
803
676
  /*
804
- * The way into a diagnostic run, standing where a status pill used to. A pill saying "Connected" was decoration on
805
- * the healthy path and a dead end on every other; this appears only where a run would explain something.
677
+ * The dashboard's diagnostics action is named in words at rest, and a capture under way replaces that name
678
+ * beside the icon, so neither rests on the icon or on colour alone.
806
679
  */
807
- .dashboard-diagnose {
808
- flex: 0 0 auto;
809
- /* Buttons are full width by default here, and this one sits inline beside the title. */
810
- width: auto;
811
- border: 1px solid var(--alert);
812
- border-radius: var(--radius-pill);
813
- background: color-mix(in srgb, var(--alert) 16%, var(--panel));
814
- color: var(--ink);
815
- padding: 6px 12px;
816
- font: inherit;
680
+ .diagnostics-name,
681
+ .diagnostics-capturing {
817
682
  font-size: 12px;
818
683
  font-weight: 600;
819
- cursor: pointer;
820
684
  }
821
685
 
822
- .dashboard-diagnose:hover {
823
- background: color-mix(in srgb, var(--alert) 26%, var(--panel));
686
+ .diagnostics-capturing,
687
+ .dashboard-action[data-collecting] .diagnostics-name {
688
+ display: none;
689
+ }
690
+
691
+ .dashboard-action[data-collecting] .diagnostics-capturing {
692
+ display: inline;
693
+ }
694
+
695
+ /* A problem the dashboard shows: an alert ring, and a dot so the state does not rest on colour alone. */
696
+ .dashboard-action[data-attention] {
697
+ border-color: var(--alert);
698
+ box-shadow: 0 0 0 2px color-mix(in srgb, var(--alert) 24%, transparent);
699
+ }
700
+
701
+ .dashboard-action[data-attention]::before {
702
+ content: '';
703
+ position: absolute;
704
+ top: -5px;
705
+ right: -5px;
706
+ width: 8px;
707
+ height: 8px;
708
+ border: 2px solid var(--panel);
709
+ border-radius: 50%;
710
+ background: var(--alert);
711
+ }
712
+
713
+ .dashboard-action:hover::after,
714
+ .dashboard-action:focus-visible::after {
715
+ opacity: 1;
716
+ transform: translateY(0);
824
717
  }
825
718
 
826
- .reauth-dialog {
719
+ .blocking-dialog {
827
720
  max-width: 420px;
828
721
  border: 0;
829
722
  border-radius: var(--radius-panel);
@@ -833,16 +726,16 @@ button.diagnostics-quiet-action {
833
726
  padding: 24px;
834
727
  }
835
728
 
836
- .reauth-dialog::backdrop {
729
+ .blocking-dialog::backdrop {
837
730
  background: rgb(0 0 0 / 30%);
838
731
  backdrop-filter: blur(5px);
839
732
  }
840
733
 
841
- .reauth-dialog h2 {
734
+ .blocking-dialog h2 {
842
735
  margin: 0 0 8px;
843
736
  }
844
737
 
845
- .reauth-dialog p {
738
+ .blocking-dialog p {
846
739
  margin: 0 0 20px;
847
740
  color: var(--ink-secondary);
848
741
  }
@@ -1686,8 +1579,7 @@ button.diagnostics-quiet-action {
1686
1579
  cursor: pointer;
1687
1580
  }
1688
1581
 
1689
- .first-setup-confirmation input,
1690
- .diagnostics-review-confirm input {
1582
+ .first-setup-confirmation input {
1691
1583
  appearance: none;
1692
1584
  display: grid;
1693
1585
  place-content: center;
@@ -1702,8 +1594,7 @@ button.diagnostics-quiet-action {
1702
1594
  padding: 0;
1703
1595
  }
1704
1596
 
1705
- .first-setup-confirmation input::before,
1706
- .diagnostics-review-confirm input::before {
1597
+ .first-setup-confirmation input::before {
1707
1598
  content: '';
1708
1599
  width: 8px;
1709
1600
  height: 4px;
@@ -1712,14 +1603,12 @@ button.diagnostics-quiet-action {
1712
1603
  transform: rotate(-45deg) scale(0);
1713
1604
  }
1714
1605
 
1715
- .first-setup-confirmation input:checked,
1716
- .diagnostics-review-confirm input:checked {
1606
+ .first-setup-confirmation input:checked {
1717
1607
  border-color: var(--accent);
1718
1608
  background: var(--accent);
1719
1609
  }
1720
1610
 
1721
- .first-setup-confirmation input:checked::before,
1722
- .diagnostics-review-confirm input:checked::before {
1611
+ .first-setup-confirmation input:checked::before {
1723
1612
  transform: rotate(-45deg) scale(1);
1724
1613
  }
1725
1614
 
@@ -2019,7 +1908,6 @@ button:disabled {
2019
1908
  cursor: not-allowed;
2020
1909
  }
2021
1910
 
2022
- button.diagnostics-secondary-action:hover:not(:disabled),
2023
1911
  .dashboard-page-back:hover:not(:disabled),
2024
1912
  .warm-up-controls button:hover:not(:disabled),
2025
1913
  .warm-up-column button:hover:not(:disabled),
@@ -2051,8 +1939,7 @@ button.diagnostics-quiet-action:hover:not(:disabled) {
2051
1939
  }
2052
1940
 
2053
1941
  .warm-up-controls button:disabled,
2054
- .warm-up-column button:disabled,
2055
- button.diagnostics-secondary-action:disabled {
1942
+ .warm-up-column button:disabled {
2056
1943
  border-color: var(--line);
2057
1944
  background: var(--panel);
2058
1945
  color: var(--ink-disabled);
@@ -2106,8 +1993,9 @@ input:focus-visible {
2106
1993
  grid-template-columns: repeat(2, minmax(0, 1fr));
2107
1994
  }
2108
1995
 
2109
- .diagnostics-device-list {
2110
- grid-template-columns: repeat(2, minmax(0, 1fr));
1996
+ /* The row keeps its three actions on one line by leaving the diagnostics action to its icon. */
1997
+ .diagnostics-name {
1998
+ display: none;
2111
1999
  }
2112
2000
 
2113
2001
 
@@ -2183,14 +2071,14 @@ input:focus-visible {
2183
2071
  width: 100%;
2184
2072
  }
2185
2073
 
2186
- .diagnostics-choice-actions {
2187
- display: grid;
2188
- grid-template-columns: repeat(2, minmax(0, 1fr));
2074
+ /* Two actions side by side leave each a sliver of a label at this width, so they stack. */
2075
+ .diagnostics-handoff:not([hidden]) {
2076
+ grid-template-columns: 1fr;
2189
2077
  }
2190
2078
 
2191
- .diagnostics-choice-actions button {
2192
- width: 100%;
2193
- min-width: 0;
2079
+ .diagnostics-choice-actions {
2080
+ display: grid;
2081
+ gap: 8px;
2194
2082
  }
2195
2083
 
2196
2084
  .device-grid {