openreplay/frontend/app/components/Session/Player/LivePlayer/LiveControls.tsx
Delirium 2ed4bba33e
feat(tracker/ui): support for multi tab sessions (#1236)
* feat(tracker): add support for multi tab sessions

* feat(backend): added support of multitabs

* fix(backend): added support of deprecated batch meta message to pre-decoder

* fix(backend): fixed nil meta issue for TabData messages in sink

* feat(player): add tabmanager

* feat(player): basic tabchange event support

* feat(player): pick tabstate for console panel and timeline

* fix(player): only display tabs that are created

* feat(player): connect performance, xray and events to tab state

* feat(player): merge all tabs data for overview

* feat(backend/tracker): extract tabdata into separate message from batchmeta

* fix(tracker): fix new session check

* fix(backend): remove batchmetadeprecated

* fix(backend): fix switch case

* fix(player): fix for tab message size

* feat(tracker): check for active tabs with broadcast channel

* feat(tracker): prevent multiple messages

* fix(tracker): ignore beacons from same tab, only ask if token isnt present yet, add small delay before start to wait for answer

* feat(player): support new msg struct in assist player

* fix(player): fix some livepl components for multi tab states

* feat(tracker): add option to disable multitab

* feat(tracker): add multitab to assist plugin

* feat(player): back compat for tab id

* fix(ui): fix missing list in controls

* fix(ui): optional list update

* feat(ui): fix visuals for multitab; use window focus event for tabs

* fix(tracker): fix for dying tests (added tabid to writer, refactored other tests)

* feat(ui): update LivePlayerSubHeader.tsx to support tabs

* feat(backend): added tabs support to devtools mob files

* feat(ui): connect state to current tab properly

* feat(backend): added multitab support to assits

* feat(backend): removed data check in agent message

* feat(backend): debug on

* fix(backend): fixed typo in message broadcast

* feat(backend): fixed issue in connect method

* fix(assist): fixed typo

* feat(assist): added more debug logs

* feat(assist): removed one log

* feat(assist): more logs

* feat(assist): use query.peerId

* feat(assist): more logs

* feat(assist): fixed session update

* fix(assist): fixed getSessions

* fix(assist): fixed request_control broadcast

* fix(assist): fixed typo

* fix(assist): added missed line

* fix(assist): fix typo

* feat(tracker): multitab support for assist sessions

* fix(tracker): fix dead tests (tabid prop)

* fix(tracker): fix yaml

* fix(tracker): timers issue

* fix(ui): fix ui E2E tests with magic?

* feat(assist): multitabs support for ee version

* fix(assist): added missed method import

* fix(tracker): fix fix events in assist

* feat(assist): added back compatibility for sessions without tabId

* fix(assist): apply message's top layer structure before broadcast call

* fix(assist): added random tabID for prev version

* fix(assist): added random tabID for prev version (ee)

* feat(assist): added debug logs

* fix(assist): fix typo in sessions_agents_count method

* fix(assist): fixed more typos in copy-pastes

* fix(tracker): fix restart timings

* feat(backend): added tabIDs for some events

* feat(ui): add tab change event to the user steps bar

* Revert "feat(backend): added tabIDs for some events"

This reverts commit 1467ad7f9f.

* feat(ui): revert timeline and xray to grab events from all tabs

* fix(ui): fix typo

---------

Co-authored-by: Alexander Zavorotynskiy <zavorotynskiy@pm.me>
2023-06-07 10:40:32 +02:00

134 lines
No EOL
3.7 KiB
TypeScript

import React from 'react';
import cn from 'classnames';
import { connect } from 'react-redux';
import LiveTag from './LiveTag';
import AssistSessionsTabs from './AssistSessionsTabs';
import {
CONSOLE, toggleBottomBlock,
} from 'Duck/components/player';
import { PlayerContext, ILivePlayerContext } from 'App/components/Session/playerContext';
import { observer } from 'mobx-react-lite';
import { fetchSessions } from 'Duck/liveSearch';
import AssistDuration from './AssistDuration';
import Timeline from './Timeline';
import ControlButton from 'Components/Session_/Player/Controls/ControlButton';
import { SKIP_INTERVALS } from 'Components/Session_/Player/Controls/Controls'
import styles from 'Components/Session_/Player/Controls/controls.module.css';
function Controls(props: any) {
// @ts-ignore ?? TODO
const { player, store } = React.useContext<ILivePlayerContext>(PlayerContext);
const { jumpToLive } = player;
const {
livePlay,
currentTab,
tabStates
} = store.get();
const exceptionsList = tabStates[currentTab]?.exceptionsList || [];
const logRedCount = tabStates[currentTab]?.logMarkedCountNow || 0;
const showExceptions = exceptionsList.length > 0;
const {
bottomBlock,
toggleBottomBlock,
closedLive,
skipInterval,
session,
fetchSessions: fetchAssistSessions,
totalAssistSessions,
} = props;
const onKeyDown = (e: any) => {
if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) {
return;
}
if (e.key === 'ArrowRight') {
forthTenSeconds();
}
if (e.key === 'ArrowLeft') {
backTenSeconds();
}
};
React.useEffect(() => {
document.addEventListener('keydown', onKeyDown.bind(this));
if (totalAssistSessions === 0) {
fetchAssistSessions();
}
return () => {
document.removeEventListener('keydown', onKeyDown.bind(this));
};
}, []);
const forthTenSeconds = () => {
// @ts-ignore
player.jumpInterval(SKIP_INTERVALS[skipInterval]);
};
const backTenSeconds = () => {
// @ts-ignore
player.jumpInterval(-SKIP_INTERVALS[skipInterval]);
};
const toggleBottomTools = (blockName: number) => {
toggleBottomBlock(blockName);
};
return (
<div className={styles.controls}>
<Timeline />
<div className={cn(styles.buttons, '!px-5 !pt-0')} data-is-live>
<div className="flex items-center">
{!closedLive && (
<div className={styles.buttonsLeft}>
<LiveTag isLive={livePlay} onClick={() => (livePlay ? null : jumpToLive())} />
<div className="font-semibold px-2">
<AssistDuration />
</div>
</div>
)}
</div>
{totalAssistSessions > 1 ? (
<div>
<AssistSessionsTabs session={session} />
</div>
) : null}
<div className="flex items-center h-full">
<ControlButton
onClick={() => toggleBottomTools(CONSOLE)}
active={bottomBlock === CONSOLE}
label="CONSOLE"
noIcon
labelClassName="!text-base font-semibold"
hasErrors={logRedCount > 0 || showExceptions}
containerClassName="mx-2"
/>
</div>
</div>
</div>
);
}
const ControlPlayer = observer(Controls);
export default connect(
(state: any) => {
return {
session: state.getIn(['sessions', 'current']),
totalAssistSessions: state.getIn(['liveSearch', 'total']),
closedLive:
!!state.getIn(['sessions', 'errors']) || !state.getIn(['sessions', 'current']).live,
};
},
{
fetchSessions,
toggleBottomBlock
}
)(ControlPlayer);