* ui: start highlight ui * ui: tag items * ui: connecting highlights to notes api... * Highlight feature refinements (#2948) * ui: move clips player to foss, connect notes api to hl * ui: tune note/hl editing, prevent zoom slider body from jumping around * ui: safe check for tag * ui: fix thumbnail gen * ui: fix thumbnail gen * ui: make player modal wider, add shadow * ui: custom warn barge for clips * ui: swap icon for note event wrapper * ui: rm other, fix cancel * ui: moving around creation modal * ui: bg tint * ui: rm disabled for text btn * ui: fix ownership sorting * ui: close player on bg click * ui: fix query, fix min distance for default range * ui: move hl list header out of list comp * ui: spot list header segmented size * Various improvements in highlights (#2955) * ui: update hl in hlPanel comp * ui: rm debug * ui: fix icons file --------- Co-authored-by: Sudheer Salavadi <connect.uxmaster@gmail.com>
159 lines
4.2 KiB
TypeScript
159 lines
4.2 KiB
TypeScript
import { createClipPlayer } from 'Player';
|
|
import { makeAutoObservable } from 'mobx';
|
|
import { observer } from 'mobx-react-lite';
|
|
import React, { useEffect, useState } from 'react';
|
|
import { toast } from 'react-toastify';
|
|
|
|
import { useStore } from 'App/mstore';
|
|
import { Loader } from 'UI';
|
|
import {
|
|
IPlayerContext,
|
|
PlayerContext,
|
|
defaultContextValue,
|
|
} from './playerContext';
|
|
|
|
import ClipPlayerHeader from 'Components/Session/Player/ClipPlayer/ClipPlayerHeader';
|
|
import ClipPlayerContent from 'Components/Session/Player/ClipPlayer/ClipPlayerContent';
|
|
import Session from 'Types/session';
|
|
import { sessionService } from '@/services';
|
|
|
|
let playerInst: IPlayerContext['player'] | undefined;
|
|
|
|
interface Props {
|
|
clip: any;
|
|
currentIndex: number;
|
|
isCurrent: boolean;
|
|
autoplay: boolean;
|
|
onClose?: () => void;
|
|
isHighlight?: boolean;
|
|
}
|
|
|
|
function WebPlayer(props: Props) {
|
|
const { clip, currentIndex, isCurrent, onClose, isHighlight } = props;
|
|
const { sessionStore } = useStore();
|
|
const prefetched = sessionStore.prefetched;
|
|
const [windowActive, setWindowActive] = useState(!document.hidden);
|
|
const [contextValue, setContextValue] =
|
|
// @ts-ignore
|
|
useState<IPlayerContext>(defaultContextValue);
|
|
const openedAt = React.useRef<number>();
|
|
const [session, setSession] = useState<Session | undefined>(undefined);
|
|
|
|
useEffect(() => {
|
|
if (!clip.sessionId) return;
|
|
|
|
const fetchSession = async () => {
|
|
if (clip.sessionId != null && clip?.sessionId !== '') {
|
|
try {
|
|
// const data = await sessionStore.fetchSessionData(props.sessionId);
|
|
const data = await sessionService.getSessionInfo(clip.sessionId);
|
|
setSession(new Session(data));
|
|
} catch (error) {
|
|
console.error('Error fetching session data:', error);
|
|
}
|
|
} else {
|
|
console.error('No sessionID in route.');
|
|
}
|
|
};
|
|
|
|
void fetchSession();
|
|
}, [clip]);
|
|
|
|
React.useEffect(() => {
|
|
openedAt.current = Date.now();
|
|
if (windowActive) {
|
|
const handleActivation = () => {
|
|
if (!document.hidden) {
|
|
setWindowActive(true);
|
|
document.removeEventListener('visibilitychange', handleActivation);
|
|
}
|
|
};
|
|
document.addEventListener('visibilitychange', handleActivation);
|
|
}
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
playerInst = undefined;
|
|
if (!clip.sessionId || contextValue.player !== undefined || !session)
|
|
return;
|
|
|
|
// @ts-ignore
|
|
sessionStore.setUserTimezone(session?.timezone);
|
|
const [WebPlayerInst, PlayerStore] = createClipPlayer(
|
|
session,
|
|
(state) => makeAutoObservable(state),
|
|
toast,
|
|
clip.range
|
|
);
|
|
|
|
setContextValue({ player: WebPlayerInst, store: PlayerStore });
|
|
playerInst = WebPlayerInst;
|
|
// playerInst.pause();
|
|
}, [session]);
|
|
|
|
const domFiles = session?.domURL?.length ?? 0;
|
|
|
|
useEffect(() => {
|
|
if (!prefetched && domFiles > 0) {
|
|
playerInst?.reinit(session!);
|
|
playerInst?.pause();
|
|
}
|
|
}, [session, domFiles, prefetched]);
|
|
|
|
const {
|
|
firstVisualEvent: visualOffset,
|
|
messagesProcessed,
|
|
tabStates,
|
|
ready,
|
|
playing,
|
|
} = contextValue.store?.get() || {};
|
|
|
|
const cssLoading =
|
|
ready && tabStates
|
|
? Object.values(tabStates).some(({ cssLoading }) => cssLoading)
|
|
: true;
|
|
|
|
useEffect(() => {
|
|
if (ready) {
|
|
if (!isCurrent) {
|
|
contextValue.player?.pause();
|
|
}
|
|
}
|
|
}, [ready]);
|
|
|
|
useEffect(() => {
|
|
contextValue.player?.jump(clip.range[0]);
|
|
setTimeout(() => {
|
|
contextValue.player?.play();
|
|
}, 500);
|
|
}, [currentIndex]);
|
|
|
|
if (!session || !session?.sessionId)
|
|
return (
|
|
<Loader
|
|
size={75}
|
|
style={{
|
|
position: 'fixed',
|
|
top: '50%',
|
|
left: '50%',
|
|
transform: 'translateX(-50%)',
|
|
height: 75,
|
|
}}
|
|
/>
|
|
);
|
|
|
|
return (
|
|
<PlayerContext.Provider value={contextValue}>
|
|
{contextValue.player ? (
|
|
<>
|
|
<ClipPlayerHeader isHighlight={isHighlight} onClose={onClose} range={clip.range} session={session!} />
|
|
<ClipPlayerContent message={clip.message} isHighlight={isHighlight} autoplay={props.autoplay} range={clip.range} session={session!} />
|
|
</>
|
|
) : (
|
|
<Loader />
|
|
)}
|
|
</PlayerContext.Provider>
|
|
);
|
|
}
|
|
|
|
export default observer(WebPlayer);
|