diff --git a/src/components/mindset/components/PlayerContols/ProgressBar/Markers/index.tsx b/src/components/mindset/components/PlayerContols/ProgressBar/Markers/index.tsx index 26272ebe0..ae5692cb6 100644 --- a/src/components/mindset/components/PlayerContols/ProgressBar/Markers/index.tsx +++ b/src/components/mindset/components/PlayerContols/ProgressBar/Markers/index.tsx @@ -9,12 +9,13 @@ type Props = { export const Markers = memo(({ markers, duration }: Props) => ( <> - {markers.map((node) => { - const position = Math.floor(((node?.start || 0) / duration) * 100) + {markers.map((node, index) => { + const position = Math.floor(((node?.start || 0) / duration) * 200) const type = node?.node_type || '' const img = node?.properties?.image_url || '' - return + // eslint-disable-next-line react/no-array-index-key + return })} )) diff --git a/src/components/mindset/components/Sidebar/Transcript/index.tsx b/src/components/mindset/components/Sidebar/Transcript/index.tsx index b0b713889..dc9cfea28 100644 --- a/src/components/mindset/components/Sidebar/Transcript/index.tsx +++ b/src/components/mindset/components/Sidebar/Transcript/index.tsx @@ -1,11 +1,10 @@ import { useEffect, useState } from 'react' import styled from 'styled-components' import { Flex } from '~/components/common/Flex' -import { fetchNodeEdges } from '~/network/fetchGraphData' import { useGraphStore } from '~/stores/useGraphStore' import { useMindsetStore } from '~/stores/useMindsetStore' import { usePlayerStore } from '~/stores/usePlayerStore' -import { NodeExtended } from '~/types' +import { Node, NodeExtended } from '~/types' import { colors } from '~/utils' import { Viewer } from './Viewer' @@ -14,39 +13,13 @@ type Props = { } export const Transcript = ({ name }: Props) => { - const { selectedEpisodeId } = useMindsetStore((s) => s) + const clips = useMindsetStore((s) => s.clips) const { playerRef } = usePlayerStore((s) => s) const [currentTime, setCurrentTime] = useState(0) - const [activeClip, setActiveClip] = useState(null) + const [activeClip, setActiveClip] = useState(null) const [isFirst, setIsFirst] = useState(true) const [setActiveNode, activeNode, simulation] = useGraphStore((s) => [s.setActiveNode, s.activeNode, s.simulation]) - const [clips, setClips] = useState([]) - - useEffect(() => { - const fetchClips = async () => { - try { - const res = await fetchNodeEdges(selectedEpisodeId, 0, 50, { nodeType: ['Clip'], useSubGraph: false }) - - if (res?.nodes) { - const sortedClips = res.nodes.sort((a, b) => { - const startA = parseTimestamp(a.properties?.timestamp)[0] - const startB = parseTimestamp(b.properties?.timestamp)[0] - - return startA - startB // Ascending order - }) - - setClips(sortedClips) - } - } catch (error) { - console.error('Failed to fetch clips:', error) - } - } - - if (selectedEpisodeId) { - fetchClips() - } - }, [selectedEpisodeId]) useEffect(() => { const interval = setInterval(() => { diff --git a/src/components/mindset/index.tsx b/src/components/mindset/index.tsx index dd2a17a04..dd5e6f8e6 100644 --- a/src/components/mindset/index.tsx +++ b/src/components/mindset/index.tsx @@ -21,6 +21,8 @@ export const MindSet = () => { const [dataInitial, setDataInitial] = useState(null) const [showTwoD, setShowTwoD] = useState(false) const { selectedEpisodeId, setSelectedEpisode } = useMindsetStore((s) => s) + const setClips = useMindsetStore((s) => s.setClips) + const clips = useMindsetStore((s) => s.clips) const socket: Socket | undefined = useSocket() const requestRef = useRef(null) const previousTimeRef = useRef(null) @@ -31,6 +33,96 @@ export const MindSet = () => { const { setPlayingNode } = usePlayerStore((s) => s) + useEffect(() => { + const init = async () => { + try { + const data = await getNode(selectedEpisodeId) + + if (data) { + setPlayingNode(data) + setSelectedEpisode(data) + addNewNode({ nodes: [data], edges: [] }) + } + } catch (error) { + console.error(error) + } + } + + if (selectedEpisodeId) { + init() + } + }, [selectedEpisodeId, setPlayingNode, setSelectedEpisode, addNewNode]) + + useEffect(() => { + const fetchInitialData = async () => { + try { + // Fetch the initial set of edges and nodes for the episode + const starterNodes = await fetchNodeEdges(selectedEpisodeId, 0, 50, { + nodeType: ['Show', 'Host', 'Guest'], + useSubGraph: false, + }) + + const clipNodes = await fetchNodeEdges(selectedEpisodeId, 0, 50, { + nodeType: ['Clip'], + useSubGraph: false, + }) + + // Update the graph with starter nodes + addNewNode({ + nodes: starterNodes?.nodes ? starterNodes?.nodes : [], + edges: starterNodes?.edges ? starterNodes.edges : [], + }) + + if (clipNodes?.nodes) { + setClips(clipNodes?.nodes) + } + } catch (error) { + console.error('Error fetching initial data:', error) + } + } + + if (selectedEpisodeId) { + fetchInitialData() + } + }, [selectedEpisodeId, addNewNode, setClips]) + + useEffect(() => { + if (!clips) { + return + } + + const processClipNodes = async () => { + try { + const refIds = clips?.map((node) => node.ref_id).filter(Boolean) || [] + + const combinedData: FetchDataResponse = { + nodes: nodesAndEdgesRef.current?.nodes || [], + edges: nodesAndEdgesRef.current?.edges || [], + } + + // eslint-disable-next-line no-restricted-syntax + for (const refId of refIds) { + // eslint-disable-next-line no-await-in-loop + const data = await fetchNodeEdges(refId, 0, 50) + + if (data) { + combinedData.nodes.push(...(data?.nodes || [])) + combinedData.edges.push(...(data?.edges || [])) + + nodesAndEdgesRef.current = combinedData + setDataInitial({ ...combinedData }) + } + } + + // Update references and state after all requests complete + } catch (error) { + console.error('Error processing clip nodes:', error) + } + } + + processClipNodes() + }, [clips]) + const handleNewNodeCreated = useCallback( (data: FetchDataResponse) => { if (isFetching) { @@ -68,76 +160,6 @@ export const MindSet = () => { [addNewNode, isFetching], ) - useEffect(() => { - const init = async () => { - try { - const data = await fetchNodeEdges(selectedEpisodeId, 0, 50) - - setDataInitial(data) - - const [episodesAndClips, remainingNodes] = (data?.nodes || []).reduce<[Node[], Node[]]>( - ([matches, remaining], node) => { - if (['Episode', 'Show', 'Host', 'Guest'].includes(node.node_type)) { - matches.push(node) - } else { - remaining.push(node) - } - - return [matches, remaining] - }, - [[], []], - ) - - const refIds = new Set(episodesAndClips.map((n) => n.ref_id)) - - const [matchingLinks, remainingLinks] = (data?.edges || []).reduce<[Link[], Link[]]>( - ([matches, remaining], link) => { - if (refIds.has(link.source) && refIds.has(link.target)) { - matches.push(link) - } else { - remaining.push(link) - } - - return [matches, remaining] - }, - [[], []], - ) - - nodesAndEdgesRef.current = { - nodes: remainingNodes || [], - edges: remainingLinks || [], - } - - addNewNode({ nodes: episodesAndClips, edges: matchingLinks }) - } catch (error) { - console.error(error) - } - } - - if (selectedEpisodeId) { - init() - } - }, [selectedEpisodeId, addNewNode]) - - useEffect(() => { - const init = async () => { - try { - const data = await getNode(selectedEpisodeId) - - if (data) { - setPlayingNode(data) - setSelectedEpisode(data) - } - } catch (error) { - console.error(error) - } - } - - if (selectedEpisodeId) { - init() - } - }, [selectedEpisodeId, setPlayingNode, setSelectedEpisode]) - useEffect(() => { if (socket) { socket.connect() diff --git a/src/stores/useMindsetStore/index.ts b/src/stores/useMindsetStore/index.ts index 2b936cbfc..f6db4351d 100644 --- a/src/stores/useMindsetStore/index.ts +++ b/src/stores/useMindsetStore/index.ts @@ -1,19 +1,25 @@ import { create } from 'zustand' -import { NodeExtended } from '~/types' +import { Node, NodeExtended } from '~/types' type MindsetStore = { selectedEpisodeId: string + clips: NodeExtended[] selectedEpisode: NodeExtended | null selectedEpisodeLink: string setSelectedEpisodeId: (id: string) => void setSelectedEpisode: (node: NodeExtended) => void setSelectedEpisodeLink: (link: string) => void + setClips: (clips: Node[]) => void } -const defaultData: Omit = { +const defaultData: Omit< + MindsetStore, + 'setSelectedEpisodeId' | 'setSelectedEpisodeLink' | 'setSelectedEpisode' | 'setClips' +> = { selectedEpisodeId: '', selectedEpisodeLink: '', selectedEpisode: null, + clips: [], } export const useMindsetStore = create((set) => ({ @@ -21,4 +27,5 @@ export const useMindsetStore = create((set) => ({ setSelectedEpisodeId: (selectedEpisodeId) => set({ selectedEpisodeId }), setSelectedEpisodeLink: (selectedEpisodeLink) => set({ selectedEpisodeLink }), setSelectedEpisode: (selectedEpisode) => set({ selectedEpisode }), + setClips: (clips) => set({ clips }), }))