Skip to content

Commit

Permalink
Merge branch 'develop' into feat/fo-assistant
Browse files Browse the repository at this point in the history
  • Loading branch information
Br2850 committed Sep 30, 2024
2 parents 82c2ba0 + a823b25 commit babdb74
Show file tree
Hide file tree
Showing 46 changed files with 798 additions and 210 deletions.
4 changes: 2 additions & 2 deletions app/packages/analytics/src/analytics.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ describe("Analytics", () => {
// segment should be called with context.page.url = undefined
expect(mockSegment.track).toHaveBeenCalledWith("custom_event", undefined, {
context: {
page: { url: undefined },
page: { url: null, path: null, title: null },
},
});
});
Expand Down Expand Up @@ -208,7 +208,7 @@ describe("Analytics", () => {
version: "1.0.0",
});
});

describe("analytics.page()", () => {
it("should call segment.page()", () => {
analytics = new Analytics();
Expand Down
12 changes: 8 additions & 4 deletions app/packages/analytics/src/usingAnalytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,10 @@ export class Analytics {
if (this._segment) return;
this._debug = info?.debug;
if (!info || info.doNotTrack) {
console.warn("Analytics disabled");
console.log(info);
if (this._debug) {
console.warn("Analytics disabled");
console.log(info);
}
this.disable();
return;
}
Expand All @@ -66,7 +68,9 @@ export class Analytics {
}
this._disableUrlTracking = info.disableUrlTracking;
if (!info.writeKey) {
console.warn("Analytics disabled (no write key)");
if (this._debug) {
console.warn("Analytics disabled (no write key)");
}
this.disable();
return;
}
Expand Down Expand Up @@ -119,7 +123,7 @@ export class Analytics {
if (!this._segment) return;
let opts;
if (this._disableUrlTracking) {
opts = { context: { page: { url: undefined } } };
opts = { context: { page: { url: null, path: null, title: null } } };
}
if (this._version) {
opts = { ...opts, version: this._version };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import { useTheme } from "@fiftyone/components";
import * as fos from "@fiftyone/state";
import { useBrowserStorage } from "@fiftyone/state";
import { Resizable } from "re-resizable";
import React from "react";
import { useRecoilValue } from "recoil";
import React, { useEffect, useState } from "react";
import { useRecoilCallback, useRecoilValue } from "recoil";
import { DynamicGroupsFlashlightWrapper } from "./DynamicGroupsFlashlightWrapper";

const MAX_CAROUSEL_HEIGHT = 600;

export const DynamicGroupCarousel = () => {
export const DynamicGroupCarousel = React.memo(() => {
const [height, setHeight] = useBrowserStorage(
"dynamic-group-carousel-height",
150
Expand All @@ -17,6 +17,36 @@ export const DynamicGroupCarousel = () => {
const theme = useTheme();
const isMainVisible = useRecoilValue(fos.groupMediaIsMainVisibleSetting);

/**
* BIG HACK: TODO: FIX ME
*
* Problem = flashlight is not re-rendering when group by field changes.
* Solution was to key it by groupByValue, but when the component
* subscribes to the groupByFieldValue using useRecoilValue(fos.groupByFieldValue),
* while it solves the problem, it causes flashlight to behave weirdly.
* (try scrolling carousel and selecting samples, flashlight will reset to the front)
*
*/
const getGroupByFieldValue = useRecoilCallback(({ snapshot }) => () => {
const groupByField = snapshot.getLoadable(fos.groupByFieldValue).getValue();
return groupByField;
});

const [groupByValue, setGroupByValue] = useState(getGroupByFieldValue());
const groupByValueRef = React.useRef(groupByValue);
groupByValueRef.current = groupByValue;

useEffect(() => {
const intervalId = window.setInterval(() => {
const groupByFieldValue = getGroupByFieldValue();
if (groupByFieldValue !== groupByValueRef.current) {
setGroupByValue(groupByFieldValue);
}
}, 50);

return () => window.clearInterval(intervalId);
}, []);

return (
<Resizable
size={{ height, width: "100%" }}
Expand All @@ -41,7 +71,7 @@ export const DynamicGroupCarousel = () => {
}}
data-cy={"group-carousel"}
>
<DynamicGroupsFlashlightWrapper />
<DynamicGroupsFlashlightWrapper key={groupByValue} />
</Resizable>
);
};
});
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Sample, freeVideos } from "@fiftyone/looker";
import * as fos from "@fiftyone/state";
import { selectedSamples } from "@fiftyone/state";
import { get } from "lodash";
import {
import React, {
useCallback,
useEffect,
useId,
Expand Down Expand Up @@ -46,7 +46,7 @@ const pageParams = selector({
},
});

export const DynamicGroupsFlashlightWrapper = () => {
export const DynamicGroupsFlashlightWrapper = React.memo(() => {
const id = useId();

const store = fos.useLookerStore();
Expand Down Expand Up @@ -175,4 +175,4 @@ export const DynamicGroupsFlashlightWrapper = () => {
id={id}
></div>
);
};
});
112 changes: 76 additions & 36 deletions app/packages/core/src/components/Modal/ImaVidLooker.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { useTheme } from "@fiftyone/components";
import { AbstractLooker, ImaVidLooker } from "@fiftyone/looker";
import { BUFFERING_PAUSE_TIMEOUT } from "@fiftyone/looker/src/lookers/imavid/constants";
import { BaseState } from "@fiftyone/looker/src/state";
import { FoTimelineConfig, useCreateTimeline } from "@fiftyone/playback";
import { useDefaultTimelineNameImperative } from "@fiftyone/playback/src/lib/use-default-timeline-name";
Expand Down Expand Up @@ -54,6 +53,8 @@ export const ImaVidLookerReact = React.memo(
});

const { activeLookerRef, setActiveLookerRef } = useModalContext();
const imaVidLookerRef =
activeLookerRef as unknown as React.MutableRefObject<ImaVidLooker>;

const looker = React.useMemo(
() => createLooker.current(sampleDataWithExtraParams),
Expand Down Expand Up @@ -152,19 +153,59 @@ export const ImaVidLookerReact = React.memo(
);
}, [ref]);

const loadRange = React.useCallback(async (range: BufferRange) => {
// todo: implement
return new Promise<void>((resolve) => {
setTimeout(() => {
resolve();
}, BUFFERING_PAUSE_TIMEOUT);
});
}, []);
const loadRange = React.useCallback(
async (range: Readonly<BufferRange>) => {
const storeBufferManager =
imaVidLookerRef.current.frameStoreController.storeBufferManager;
const fetchBufferManager =
imaVidLookerRef.current.frameStoreController.fetchBufferManager;

if (storeBufferManager.containsRange(range)) {
return;
}

const unprocessedStoreBufferRange =
storeBufferManager.getUnprocessedBufferRange(range);
const unprocessedBufferRange =
fetchBufferManager.getUnprocessedBufferRange(
unprocessedStoreBufferRange
);

if (!unprocessedBufferRange) {
return;
}

imaVidLookerRef.current.frameStoreController.enqueueFetch(
unprocessedBufferRange
);

return new Promise<void>((resolve) => {
const fetchMoreListener = (e: CustomEvent) => {
if (
e.detail.id === imaVidLookerRef.current.frameStoreController.key
) {
if (storeBufferManager.containsRange(unprocessedBufferRange)) {
resolve();
window.removeEventListener(
"fetchMore",
fetchMoreListener as EventListener
);
}
}
};

window.addEventListener(
"fetchMore",
fetchMoreListener as EventListener,
{ once: true }
);
});
},
[]
);

const renderFrame = React.useCallback((frameNumber: number) => {
(
activeLookerRef.current as unknown as ImaVidLooker
)?.element.drawFrameNoAnimation(frameNumber);
imaVidLookerRef.current?.element.drawFrameNoAnimation(frameNumber);
}, []);

const { getName } = useDefaultTimelineNameImperative();
Expand All @@ -189,7 +230,7 @@ export const ImaVidLookerReact = React.memo(

const readyWhen = useCallback(async () => {
return new Promise<void>((resolve) => {
// wait for total frame count to be resolved
// hack: wait for total frame count to be resolved
let intervalId;
intervalId = setInterval(() => {
if (totalFrameCountRef.current) {
Expand All @@ -200,6 +241,10 @@ export const ImaVidLookerReact = React.memo(
});
}, []);

const onAnimationStutter = useCallback(() => {
imaVidLookerRef.current?.element.checkFetchBufferManager();
}, []);

const {
isTimelineInitialized,
registerOnPauseCallback,
Expand All @@ -210,6 +255,10 @@ export const ImaVidLookerReact = React.memo(
name: timelineName,
config: timelineCreationConfig,
waitUntilInitialized: readyWhen,
// using this mechanism to resume fetch if it was paused
// ideally we have control of fetch in this component but can't do that yet
// since imavid is part of the grid too
onAnimationStutter,
});

/**
Expand All @@ -224,35 +273,27 @@ export const ImaVidLookerReact = React.memo(
});

registerOnPlayCallback(() => {
(activeLookerRef.current as unknown as ImaVidLooker).element.update(
() => ({
playing: true,
})
);
imaVidLookerRef.current?.element?.update(() => ({
playing: true,
}));
});

registerOnPauseCallback(() => {
(activeLookerRef.current as unknown as ImaVidLooker).element.update(
() => ({
playing: false,
})
);
imaVidLookerRef.current?.element?.update(() => ({
playing: false,
}));
});

registerOnSeekCallbacks({
start: () => {
(activeLookerRef.current as unknown as ImaVidLooker).element.update(
() => ({
seeking: true,
})
);
imaVidLookerRef.current?.element?.update(() => ({
seeking: true,
}));
},
end: () => {
(activeLookerRef.current as unknown as ImaVidLooker).element.update(
() => ({
seeking: false,
})
);
imaVidLookerRef.current?.element?.update(() => ({
seeking: false,
}));
},
});
}
Expand All @@ -265,9 +306,8 @@ export const ImaVidLookerReact = React.memo(
// hack: poll every 10ms for total frame count
// replace with event listener or callback
let intervalId = setInterval(() => {
const totalFrameCount = (
activeLookerRef.current as unknown as ImaVidLooker
).frameStoreController.totalFrameCount;
const totalFrameCount =
imaVidLookerRef.current.frameStoreController.totalFrameCount;
if (totalFrameCount) {
setTotalFrameCount(totalFrameCount);
clearInterval(intervalId);
Expand Down
Loading

0 comments on commit babdb74

Please sign in to comment.