diff --git a/app/packages/core/src/components/ImageContainerHeader.tsx b/app/packages/core/src/components/ImageContainerHeader.tsx index 1b062e0ae6..5accbd04f1 100644 --- a/app/packages/core/src/components/ImageContainerHeader.tsx +++ b/app/packages/core/src/components/ImageContainerHeader.tsx @@ -115,7 +115,7 @@ const ImageContainerHeader = () => { const groupStats = useRecoilValue(groupStatistics(false)); const shouldShowSliceSelector = useMemo( - () => isGroup && groupSlices.length > 0, + () => isGroup && groupSlices.length > 1, [isGroup, groupSlices] ); diff --git a/app/packages/core/src/components/Modal/Group/DynamicGroup/carousel/DynamicGroupsFlashlightWrapper.tsx b/app/packages/core/src/components/Modal/Group/DynamicGroup/carousel/DynamicGroupsFlashlightWrapper.tsx index a600b42685..51fea5da24 100644 --- a/app/packages/core/src/components/Modal/Group/DynamicGroup/carousel/DynamicGroupsFlashlightWrapper.tsx +++ b/app/packages/core/src/components/Modal/Group/DynamicGroup/carousel/DynamicGroupsFlashlightWrapper.tsx @@ -4,6 +4,7 @@ import * as foq from "@fiftyone/relay"; import * as fos from "@fiftyone/state"; import React, { MutableRefObject, + useCallback, useEffect, useId, useLayoutEffect, @@ -140,6 +141,24 @@ export const DynamicGroupsFlashlightWrapper = () => { const flashlightRef = useRef>(); selectSample.current = select; + const getScrollParams = useCallback(() => { + const flashlight = flashlightRef.current; + + if (!flashlight) { + return; + } + + const containerWidth = flashlight.element.clientWidth; + // elementWidth represents the width of the first element in the flashlight + const elementWidth = + flashlight.element.firstElementChild?.firstElementChild?.clientWidth ?? + 100; + + const elementsCount = Math.ceil(containerWidth / elementWidth!); + + return { elementWidth, elementsCount, containerWidth }; + }, []); + const navigationCallback = useRecoilCallback( ({ snapshot }) => async (isPrevious) => { @@ -167,18 +186,18 @@ export const DynamicGroupsFlashlightWrapper = () => { const nextSample = store.samples.get(nextSampleId); nextSample && setSample(nextSample); - // todo: very unstable, just ideating auto scroll based on quickstart groups params + // todo: implement better scrolling logic if (flashlightRef.current) { + const { elementWidth } = getScrollParams()!; + const newLeft = isPrevious - ? flashlightRef.current?.element.scrollLeft - 325 * 3 - : flashlightRef.current?.element.scrollLeft + 325 * 3; - - nextSampleIndex !== 0 && - nextSampleIndex % 3 === 0 && - flashlightRef.current?.element.scroll({ - left: newLeft, - behavior: "smooth", - }); + ? flashlightRef.current?.element.scrollLeft - elementWidth + : flashlightRef.current?.element.scrollLeft + elementWidth; + + flashlightRef.current?.element.scroll({ + left: newLeft, + behavior: "smooth", + }); } }, [setSample, store.indices, store.samples] @@ -189,7 +208,7 @@ export const DynamicGroupsFlashlightWrapper = () => { horizontal: true, containerId: DYNAMIC_GROUPS_FLASHLIGHT_CONTAINER_ID, elementId: DYNAMIC_GROUPS_FLASHLIGHT_ELEMENT_ID, - enableKeyNavigation: { + enableHorizontalKeyNavigation: { navigationCallback, previousKey: "<", nextKey: ">", diff --git a/app/packages/core/src/components/Modal/Group/GroupView.tsx b/app/packages/core/src/components/Modal/Group/GroupView.tsx index d77066e8f9..5da8af3352 100644 --- a/app/packages/core/src/components/Modal/Group/GroupView.tsx +++ b/app/packages/core/src/components/Modal/Group/GroupView.tsx @@ -105,7 +105,7 @@ export const GroupView: React.FC = ({ subBar }) => { {!shouldSplitVertically && is3DVisible && } - {subBar ?? subBar} + {subBar && subBar} ); }; diff --git a/app/packages/flashlight/src/index.ts b/app/packages/flashlight/src/index.ts index 48bb75964a..2094a7b53d 100644 --- a/app/packages/flashlight/src/index.ts +++ b/app/packages/flashlight/src/index.ts @@ -37,7 +37,7 @@ export interface FlashlightConfig { options: FlashlightOptions; elementId?: string; containerId?: string; - enableKeyNavigation?: { + enableHorizontalKeyNavigation?: { navigationCallback: (isPrev: boolean) => Promise; previousKey: string; nextKey: string; @@ -70,20 +70,19 @@ export default class Flashlight { document.addEventListener("visibilitychange", () => this.render()); - if (config.enableKeyNavigation) { + if (config.enableHorizontalKeyNavigation && config.horizontal) { const keyDownEventListener = (e) => { if (!this.isAttached()) { document.removeEventListener("keydown", keyDownEventListener); return; } - if (e.key === config.enableKeyNavigation.previousKey) { + if (e.key === config.enableHorizontalKeyNavigation.previousKey) { e.preventDefault(); - config.enableKeyNavigation.navigationCallback(true); - this.container.scrollLeft -= 316; - } else if (e.key === config.enableKeyNavigation.nextKey) { + config.enableHorizontalKeyNavigation.navigationCallback(true); + } else if (e.key === config.enableHorizontalKeyNavigation.nextKey) { e.preventDefault(); - config.enableKeyNavigation.navigationCallback(false); + config.enableHorizontalKeyNavigation.navigationCallback(false); } }; diff --git a/app/packages/state/src/recoil/groups.ts b/app/packages/state/src/recoil/groups.ts index 42c9601a60..6e61657867 100644 --- a/app/packages/state/src/recoil/groups.ts +++ b/app/packages/state/src/recoil/groups.ts @@ -26,6 +26,13 @@ import { RelayEnvironmentKey } from "./relay"; import { fieldSchema } from "./schema"; import { datasetName } from "./selectors"; import { dynamicGroupViewQuery, view } from "./view"; +import { + FLOAT_FIELD, + FRAME_NUMBER_FIELD, + INT_FIELD, + OBJECT_ID_FIELD, + STRING_FIELD, +} from "@fiftyone/utilities"; export type SliceName = string | undefined | null; @@ -240,11 +247,11 @@ export const dynamicGroupCandidateFields = selector({ ([_, { name, ftype }]) => name !== "filepath" && name !== "id" && - (ftype === "fiftyone.core.fields.IntField" || - ftype === "fiftyone.core.fields.FloatField" || - ftype === "fiftyone.core.fields.StringField" || - ftype === "fiftyone.core.fields.FrameNumberField" || - ftype === "fiftyone.core.fields.ObjectIdField") + (ftype === INT_FIELD || + ftype === FLOAT_FIELD || + ftype === STRING_FIELD || + ftype === FRAME_NUMBER_FIELD || + ftype === OBJECT_ID_FIELD) ) .map(([_, { name }]) => name); },