fix: Adjust media size to take maximum available space (#2346)
- Closes #2109
This commit is contained in:
@@ -53,6 +53,16 @@ export class MediaHeightController {
|
|||||||
this._debouncedSetHeight();
|
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 {
|
public destroy(): void {
|
||||||
this._mutationObserver.disconnect();
|
this._mutationObserver.disconnect();
|
||||||
this._resizeObserver.disconnect();
|
this._resizeObserver.disconnect();
|
||||||
@@ -76,6 +86,7 @@ export class MediaHeightController {
|
|||||||
|
|
||||||
// Calculate the true height.
|
// Calculate the true height.
|
||||||
const selectedHeight = this._selectedChild.getBoundingClientRect().height;
|
const selectedHeight = this._selectedChild.getBoundingClientRect().height;
|
||||||
|
const hostHeight = this._host.getBoundingClientRect().height;
|
||||||
|
|
||||||
// Reset the original height so that browser transition animation can be
|
// Reset the original height so that browser transition animation can be
|
||||||
// applied from the current to the target.
|
// applied from the current to the target.
|
||||||
@@ -85,7 +96,12 @@ export class MediaHeightController {
|
|||||||
this._selectedChild.getBoundingClientRect();
|
this._selectedChild.getBoundingClientRect();
|
||||||
|
|
||||||
if (selectedHeight && !isNaN(selectedHeight) && selectedHeight > 0) {
|
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`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -344,6 +344,7 @@ export class AdvancedCameraCardLiveCarousel extends LitElement {
|
|||||||
@advanced-camera-card:carousel:select=${this._setViewHandler.bind(this)}
|
@advanced-camera-card:carousel:select=${this._setViewHandler.bind(this)}
|
||||||
@advanced-camera-card:media:loaded=${() => {
|
@advanced-camera-card:media:loaded=${() => {
|
||||||
this._mediaHasLoaded = true;
|
this._mediaHasLoaded = true;
|
||||||
|
this._mediaHeightController.recalculate();
|
||||||
}}
|
}}
|
||||||
@advanced-camera-card:media:unloaded=${() => {
|
@advanced-camera-card:media:unloaded=${() => {
|
||||||
this._mediaHasLoaded = false;
|
this._mediaHasLoaded = false;
|
||||||
|
|||||||
@@ -346,6 +346,7 @@ export class AdvancedCameraCardViewerCarousel extends LitElement {
|
|||||||
}}
|
}}
|
||||||
@advanced-camera-card:media:loaded=${(ev: CustomEvent<MediaLoadedInfo>) => {
|
@advanced-camera-card:media:loaded=${(ev: CustomEvent<MediaLoadedInfo>) => {
|
||||||
this._loadedMediaPlayerController = ev.detail.mediaPlayerController ?? null;
|
this._loadedMediaPlayerController = ev.detail.mediaPlayerController ?? null;
|
||||||
|
this._mediaHeightController.recalculate();
|
||||||
this._seekHandler();
|
this._seekHandler();
|
||||||
}}
|
}}
|
||||||
@advanced-camera-card:media:unloaded=${() => {
|
@advanced-camera-card:media:unloaded=${() => {
|
||||||
|
|||||||
@@ -139,30 +139,29 @@ describe('MediaHeightController', () => {
|
|||||||
expect(host.style.maxHeight).toBe('200px');
|
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 host = document.createElement('div');
|
||||||
const controller = new MediaHeightController(host, 'div');
|
const controller = new MediaHeightController(host, 'div');
|
||||||
|
|
||||||
const root = document.createElement('div');
|
const root = document.createElement('div');
|
||||||
const child_0 = document.createElement('div');
|
const child = document.createElement('div');
|
||||||
child_0.getBoundingClientRect = vi.fn().mockReturnValue({
|
child.getBoundingClientRect = vi.fn().mockReturnValue({
|
||||||
height: 100,
|
height: 700,
|
||||||
});
|
});
|
||||||
root.appendChild(child_0);
|
root.appendChild(child);
|
||||||
|
|
||||||
controller.setRoot(root);
|
controller.setRoot(root);
|
||||||
|
controller.setSelected(0);
|
||||||
|
|
||||||
const child_1 = document.createElement('div');
|
expect(host.style.maxHeight).toBe('700px');
|
||||||
child_1.getBoundingClientRect = vi.fn().mockReturnValue({
|
|
||||||
height: 200,
|
child.getBoundingClientRect = vi.fn().mockReturnValue({
|
||||||
|
height: 900,
|
||||||
});
|
});
|
||||||
root.appendChild(child_1);
|
|
||||||
|
|
||||||
callMutationHandler();
|
controller.recalculate();
|
||||||
|
|
||||||
controller.setSelected(1);
|
expect(host.style.maxHeight).toBe('900px');
|
||||||
|
|
||||||
expect(host.style.maxHeight).toBe('200px');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user