-
Notifications
You must be signed in to change notification settings - Fork 557
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add timeline view #4965
add timeline view #4965
Changes from all commits
991398c
e0e0dc5
37c8071
46461f9
9190e63
dc3a0ec
436c45c
6f53f9a
9c83376
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -7,6 +7,8 @@ import { usePanelId, useSetPanelStateById } from "@fiftyone/spaces"; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { useTimeline } from "@fiftyone/playback/src/lib/use-timeline"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import _ from "lodash"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const FRAME_LOADED_EVENT = "frames-loaded"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export default function FrameLoaderView(props: ViewPropsType) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const { schema, path, data } = props; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const { view = {} } = schema; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -16,15 +18,16 @@ export default function FrameLoaderView(props: ViewPropsType) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const setPanelState = useSetPanelStateById(true); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const localIdRef = React.useRef<string>(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const bufm = useRef(new BufferManager()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const frameDataRef = useRef<typeof data.frames>(null); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
useEffect(() => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
localIdRef.current = Math.random().toString(36).substring(7); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (data?.frames) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
window.dispatchEvent( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
new CustomEvent(`frames-loaded`, { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
detail: { localId: localIdRef.current }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (data?.frames) frameDataRef.current = data.frames; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
window.dispatchEvent( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
new CustomEvent(FRAME_LOADED_EVENT, { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
detail: { localId: localIdRef.current }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, [data?.signature]); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const loadRange = React.useCallback( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -41,15 +44,22 @@ export default function FrameLoaderView(props: ViewPropsType) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return new Promise<void>((resolve) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
window.addEventListener(`frames-loaded`, (e) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
e instanceof CustomEvent && | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
e.detail.localId === localIdRef.current | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
bufm.current.addNewRange(range); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
resolve(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (frameDataRef.current) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
bufm.current.addNewRange(range); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
resolve(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const onFramesLoaded = (e) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
e instanceof CustomEvent && | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
e.detail.localId === localIdRef.current | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
window.removeEventListener(FRAME_LOADED_EVENT, onFramesLoaded); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
bufm.current.addNewRange(range); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
resolve(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
window.addEventListener(FRAME_LOADED_EVENT, onFramesLoaded); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+47
to
+62
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Improve event listener typing and cleanup pattern. While the event listener cleanup is implemented, there are opportunities for improvement in typing and pattern usage. Apply this diff for better type safety and a more robust cleanup pattern: if (frameDataRef.current) {
bufm.current.addNewRange(range);
resolve();
} else {
- const onFramesLoaded = (e) => {
+ const onFramesLoaded = (e: CustomEvent<{ localId: string }>) => {
+ if (e.detail.localId !== localIdRef.current) return;
+
+ window.removeEventListener(FRAME_LOADED_EVENT, onFramesLoaded as EventListener);
+ bufm.current.addNewRange(range);
+ resolve();
+ };
- if (
- e instanceof CustomEvent &&
- e.detail.localId === localIdRef.current
- ) {
- window.removeEventListener(FRAME_LOADED_EVENT, onFramesLoaded);
- bufm.current.addNewRange(range);
- resolve();
- }
- };
window.addEventListener(FRAME_LOADED_EVENT, onFramesLoaded as EventListener);
} 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,43 @@ | ||||||||||||||
import React, { useMemo } from "react"; | ||||||||||||||
import { Timeline, useCreateTimeline, useTimeline } from "@fiftyone/playback"; | ||||||||||||||
import { ViewPropsType } from "../utils/types"; | ||||||||||||||
|
||||||||||||||
const DEFAULT_CONFIG = { loop: false }; | ||||||||||||||
|
||||||||||||||
export default function TimelineView(props: ViewPropsType) { | ||||||||||||||
const { schema } = props; | ||||||||||||||
const { view = {} } = schema; | ||||||||||||||
const { timeline_name, loop, total_frames } = view; | ||||||||||||||
|
||||||||||||||
const providedConfig = { | ||||||||||||||
loop, | ||||||||||||||
totalFrames: total_frames, | ||||||||||||||
}; | ||||||||||||||
ritch marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||
|
||||||||||||||
const finalConfig = useMemo( | ||||||||||||||
() => ({ ...DEFAULT_CONFIG, ...providedConfig }), | ||||||||||||||
[providedConfig] | ||||||||||||||
); | ||||||||||||||
if (!timeline_name) { | ||||||||||||||
throw new Error("Timeline name is required"); | ||||||||||||||
} | ||||||||||||||
if (!finalConfig.totalFrames) { | ||||||||||||||
throw new Error("Total frames is required"); | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
return <TimelineCreator timelineName={timeline_name} {...finalConfig} />; | ||||||||||||||
} | ||||||||||||||
ritch marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||
|
||||||||||||||
export const TimelineCreator = ({ timelineName, totalFrames, loop }) => { | ||||||||||||||
const config = useMemo(() => ({ totalFrames, loop }), [totalFrames, loop]); | ||||||||||||||
const { isTimelineInitialized } = useCreateTimeline({ | ||||||||||||||
name: timelineName, | ||||||||||||||
config, | ||||||||||||||
}); | ||||||||||||||
|
||||||||||||||
if (!isTimelineInitialized) { | ||||||||||||||
return null; | ||||||||||||||
} | ||||||||||||||
Comment on lines
+38
to
+40
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Enhance loading state feedback Returning if (!isTimelineInitialized) {
- return null;
+ return <div aria-busy="true" role="status">Initializing timeline...</div>;
} 📝 Committable suggestion
Suggested change
|
||||||||||||||
|
||||||||||||||
return <Timeline name={timelineName} />; | ||||||||||||||
}; | ||||||||||||||
ritch marked this conversation as resolved.
Show resolved
Hide resolved
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add missing dependency and cleanup to useEffect.
The effect should include
data.frames
in its dependency array and implement a cleanup function.Apply this diff:
📝 Committable suggestion