Recalculate grid for a slot change.
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import isEqual from 'lodash-es/isEqual';
|
||||
import throttle from 'lodash-es/throttle';
|
||||
import Masonry from 'masonry-layout';
|
||||
import { MediaLoadedInfo, ViewDisplayConfig } from '../types';
|
||||
@@ -27,6 +28,7 @@ export interface MediaGridSelected {
|
||||
export interface MediaGridConstructorOptions {
|
||||
selected?: GridID;
|
||||
idAttribute?: string;
|
||||
displayConfig?: ViewDisplayConfig;
|
||||
}
|
||||
|
||||
export class MediaGridController {
|
||||
@@ -62,14 +64,26 @@ export class MediaGridController {
|
||||
this._idAttribute = options?.idAttribute ?? 'grid-id';
|
||||
this._hostWidth = this._host.getBoundingClientRect().width;
|
||||
this._hostResizeObserver.observe(host);
|
||||
this._displayConfig = options?.displayConfig ?? null;
|
||||
|
||||
this._calculateGridContentsFromHost();
|
||||
this._mutationObserver.observe(host, { childList: true });
|
||||
// Need to separately listen for slotchanges since mutation observer will
|
||||
// not be called for shadom DOM slotted changes.
|
||||
if (host instanceof HTMLSlotElement) {
|
||||
host.addEventListener('slotchange', this._calculateGridContentsFromHost);
|
||||
}
|
||||
this._calculateGridContentsFromHost();
|
||||
}
|
||||
|
||||
public destroy(): void {
|
||||
this._hostResizeObserver.disconnect();
|
||||
this._cellResizeObserver.disconnect();
|
||||
|
||||
this._mutationObserver.disconnect();
|
||||
if (this._host instanceof HTMLSlotElement) {
|
||||
this._host.removeEventListener('slotchange', this._calculateGridContentsFromHost);
|
||||
}
|
||||
|
||||
this._mediaLoadedInfoMap.clear();
|
||||
this._masonry?.destroy?.();
|
||||
this._masonry = null;
|
||||
@@ -81,8 +95,10 @@ export class MediaGridController {
|
||||
}
|
||||
|
||||
public setDisplayConfig(displayConfig: ViewDisplayConfig | null): void {
|
||||
this._displayConfig = displayConfig;
|
||||
this._calculateGridContentsFromHost();
|
||||
if (!isEqual(displayConfig, this._displayConfig)) {
|
||||
this._displayConfig = displayConfig;
|
||||
this._calculateGridContentsFromHost();
|
||||
}
|
||||
}
|
||||
|
||||
public getGridContents(): MediaGridContents {
|
||||
@@ -127,11 +143,11 @@ export class MediaGridController {
|
||||
this._updateSelectedStylesOnElements();
|
||||
}
|
||||
|
||||
protected _calculateGridContentsFromHost(): void {
|
||||
protected _calculateGridContentsFromHost = (): void => {
|
||||
let childrenElements: Element[];
|
||||
|
||||
if (this._host instanceof HTMLSlotElement) {
|
||||
childrenElements = this._host.assignedElements({ flatten: true });
|
||||
childrenElements = this._host.assignedElements();
|
||||
} else {
|
||||
childrenElements = [...this._host.children];
|
||||
}
|
||||
@@ -145,7 +161,7 @@ export class MediaGridController {
|
||||
}
|
||||
|
||||
this._setGridContents(gridContents);
|
||||
}
|
||||
};
|
||||
|
||||
protected _setGridContents(elements: MediaGridContents): void {
|
||||
this._gridContents = elements;
|
||||
|
||||
@@ -169,10 +169,11 @@ export const executeMediaQueryForView = async (
|
||||
|
||||
const queryResults = new MediaQueriesResults({ results: mediaArray });
|
||||
let viewerContext: ViewContext | undefined = {};
|
||||
const cameraID = options?.targetCameraID ?? view.camera;
|
||||
|
||||
if (options?.select === 'time' && options?.targetTime) {
|
||||
queryResults.selectBestResult((media) =>
|
||||
findBestMediaIndex(media, options.targetTime as Date),
|
||||
findBestMediaIndex(media, options.targetTime as Date, cameraID),
|
||||
);
|
||||
viewerContext = {
|
||||
mediaViewer: {
|
||||
@@ -186,7 +187,7 @@ export const executeMediaQueryForView = async (
|
||||
query: query,
|
||||
queryResults: queryResults,
|
||||
view: options?.targetView,
|
||||
camera: options?.targetCameraID,
|
||||
camera: cameraID,
|
||||
})
|
||||
.mergeInContext(viewerContext);
|
||||
};
|
||||
@@ -201,11 +202,13 @@ export const executeMediaQueryForView = async (
|
||||
export const findBestMediaIndex = (
|
||||
mediaArray: ViewMedia[],
|
||||
targetTime: Date,
|
||||
favorCameraID?: string,
|
||||
): number | null => {
|
||||
let bestMatch:
|
||||
| {
|
||||
index: number;
|
||||
duration: number;
|
||||
cameraID: string;
|
||||
}
|
||||
| undefined;
|
||||
|
||||
@@ -215,8 +218,21 @@ export const findBestMediaIndex = (
|
||||
|
||||
if (media.includesTime(targetTime) && start && end) {
|
||||
const duration = end.getTime() - start.getTime();
|
||||
if (!bestMatch || duration > bestMatch.duration) {
|
||||
bestMatch = { index: i, duration: duration };
|
||||
|
||||
if (
|
||||
// No best match so far ...
|
||||
!bestMatch ||
|
||||
// ... or there is a best-match, but it's from a non-favored camera (unlike this one) ...
|
||||
(favorCameraID &&
|
||||
bestMatch.cameraID !== favorCameraID &&
|
||||
media.getCameraID() === favorCameraID) ||
|
||||
// ... or this match is longer and either there's no favored camera or this is it.
|
||||
(duration > bestMatch.duration &&
|
||||
(!favorCameraID ||
|
||||
bestMatch.cameraID !== favorCameraID ||
|
||||
media.getCameraID() === favorCameraID))
|
||||
) {
|
||||
bestMatch = { index: i, duration: duration, cameraID: media.getCameraID() };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user