From 0b7917ef7046c4c8c83cc1cf1c20f0adf70fc34b Mon Sep 17 00:00:00 2001 From: Dermot Duffy Date: Sun, 8 Feb 2026 16:39:15 +0000 Subject: [PATCH 1/2] fix: Increase go2rtc metadata fetch timeout (#2336) - Related: #2313 --- src/camera-manager/utils/go2rtc/audio.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/camera-manager/utils/go2rtc/audio.ts b/src/camera-manager/utils/go2rtc/audio.ts index f2e93149..7c45ca66 100644 --- a/src/camera-manager/utils/go2rtc/audio.ts +++ b/src/camera-manager/utils/go2rtc/audio.ts @@ -6,7 +6,10 @@ import { errorToConsole } from '../../../utils/basic'; import { CameraProxyConfig } from '../../types'; import { Go2RTCStreamInfo, go2RTCStreamInfoSchema } from './types'; -const GO2RTC_METADATA_TIMEOUT_SECONDS = 2; +// Allow generous amount of time to fetch metadata (timeout matches that used in +// the Frigate frontend for the same call). +// See: https://github.com/dermotduffy/advanced-camera-card/issues/2313 +const GO2RTC_METADATA_TIMEOUT_SECONDS = 10; const getGo2RTCStreamMetadata = async ( hass: HomeAssistant, From be61d7fa2432ab351030388a617366df869ba1ea Mon Sep 17 00:00:00 2001 From: Dermot Duffy Date: Sat, 14 Feb 2026 21:33:05 +0000 Subject: [PATCH 2/2] fix: Adjust media size to take maximum available space (#2346) - Closes #2109 --- src/components-lib/media-height-controller.ts | 18 ++++++++++++- src/components/live/carousel.ts | 1 + src/components/viewer/carousel.ts | 1 + .../media-height-controller.test.ts | 25 +++++++++---------- 4 files changed, 31 insertions(+), 14 deletions(-) diff --git a/src/components-lib/media-height-controller.ts b/src/components-lib/media-height-controller.ts index 06ae0341..374904d9 100644 --- a/src/components-lib/media-height-controller.ts +++ b/src/components-lib/media-height-controller.ts @@ -53,6 +53,16 @@ export class MediaHeightController { this._debouncedSetHeight(); } + // Recalculate the height. This is necessary because ResizeObserver may not + // fire if the height of the media is constrained by the host's own max-height + // (e.g. during initial load, everything is 100% height of the host, so the + // rendered height never changes and thus ResizeObserver never fires). This + // manual "wakeup" allows the controller to temporarily lift the constraint + // and peek at the true desired height. + public recalculate(): void { + this._debouncedSetHeight(); + } + public destroy(): void { this._mutationObserver.disconnect(); this._resizeObserver.disconnect(); @@ -76,6 +86,7 @@ export class MediaHeightController { // Calculate the true height. const selectedHeight = this._selectedChild.getBoundingClientRect().height; + const hostHeight = this._host.getBoundingClientRect().height; // Reset the original height so that browser transition animation can be // applied from the current to the target. @@ -85,7 +96,12 @@ export class MediaHeightController { this._selectedChild.getBoundingClientRect(); if (selectedHeight && !isNaN(selectedHeight) && selectedHeight > 0) { - this._host.style.maxHeight = `${selectedHeight}px`; + // Set the height to the larger of the selected child or the host itself. + // This ensures that the host (the carousel) expands to fit the media, but + // does not shrink smaller than itself (which would cause a "flash" or + // jump). + // See: https://github.com/dermotduffy/advanced-camera-card/issues/2109 + this._host.style.maxHeight = `${Math.max(selectedHeight, hostHeight)}px`; } } diff --git a/src/components/live/carousel.ts b/src/components/live/carousel.ts index dffb4de7..567eba34 100644 --- a/src/components/live/carousel.ts +++ b/src/components/live/carousel.ts @@ -344,6 +344,7 @@ export class AdvancedCameraCardLiveCarousel extends LitElement { @advanced-camera-card:carousel:select=${this._setViewHandler.bind(this)} @advanced-camera-card:media:loaded=${() => { this._mediaHasLoaded = true; + this._mediaHeightController.recalculate(); }} @advanced-camera-card:media:unloaded=${() => { this._mediaHasLoaded = false; diff --git a/src/components/viewer/carousel.ts b/src/components/viewer/carousel.ts index b9cc6ff5..900fe197 100644 --- a/src/components/viewer/carousel.ts +++ b/src/components/viewer/carousel.ts @@ -346,6 +346,7 @@ export class AdvancedCameraCardViewerCarousel extends LitElement { }} @advanced-camera-card:media:loaded=${(ev: CustomEvent) => { this._loadedMediaPlayerController = ev.detail.mediaPlayerController ?? null; + this._mediaHeightController.recalculate(); this._seekHandler(); }} @advanced-camera-card:media:unloaded=${() => { diff --git a/tests/components-lib/media-height-controller.test.ts b/tests/components-lib/media-height-controller.test.ts index cd821d5b..73076c97 100644 --- a/tests/components-lib/media-height-controller.test.ts +++ b/tests/components-lib/media-height-controller.test.ts @@ -139,30 +139,29 @@ describe('MediaHeightController', () => { expect(host.style.maxHeight).toBe('200px'); }); - it('should ignore new chil to new children being added', () => { + it('should set height on recalculate', () => { const host = document.createElement('div'); const controller = new MediaHeightController(host, 'div'); const root = document.createElement('div'); - const child_0 = document.createElement('div'); - child_0.getBoundingClientRect = vi.fn().mockReturnValue({ - height: 100, + const child = document.createElement('div'); + child.getBoundingClientRect = vi.fn().mockReturnValue({ + height: 700, }); - root.appendChild(child_0); + root.appendChild(child); controller.setRoot(root); + controller.setSelected(0); - const child_1 = document.createElement('div'); - child_1.getBoundingClientRect = vi.fn().mockReturnValue({ - height: 200, + expect(host.style.maxHeight).toBe('700px'); + + child.getBoundingClientRect = vi.fn().mockReturnValue({ + height: 900, }); - root.appendChild(child_1); - callMutationHandler(); + controller.recalculate(); - controller.setSelected(1); - - expect(host.style.maxHeight).toBe('200px'); + expect(host.style.maxHeight).toBe('900px'); }); });