fix(ui) - fixes from dev (#1175)
* fix(player): consider stringDict before any CreateDocument (fastfix) * style(player/DOMManager/safeCSSRules): depend on interfaces * fixup! fix(player): consider stringDict before any CreateDocument (fastfix) * fix(ui) - user sessions modal - navigation * fix(player): proper unmount --------- Co-authored-by: Alex Kaminskii <alex@openreplay.com> Co-authored-by: nick-delirium <nikita@openreplay.com>
This commit is contained in:
parent
8d8f320ddb
commit
c3ce2dfeb8
10 changed files with 62 additions and 46 deletions
|
|
@ -1,37 +1,29 @@
|
|||
import { useModal } from 'App/components/Modal';
|
||||
import React, { useState } from 'react';
|
||||
import React from 'react';
|
||||
import SessionList from '../SessionList';
|
||||
import stl from './assistTabs.module.css'
|
||||
import stl from './assistTabs.module.css';
|
||||
|
||||
interface Props {
|
||||
userId: any,
|
||||
userNumericHash: any,
|
||||
userId: any;
|
||||
}
|
||||
|
||||
const AssistTabs = (props: Props) => {
|
||||
const [showMenu, setShowMenu] = useState(false)
|
||||
const { showModal } = useModal();
|
||||
|
||||
return (
|
||||
<div className="relative mr-4">
|
||||
<div className="flex items-center">
|
||||
{props.userId && (
|
||||
<>
|
||||
<div
|
||||
className={stl.btnLink}
|
||||
onClick={() => showModal(<SessionList userId={props.userId} />, { right: true, width: 700 })}
|
||||
>
|
||||
Active Sessions
|
||||
</div>
|
||||
</>
|
||||
<div
|
||||
className={stl.btnLink}
|
||||
onClick={() =>
|
||||
showModal(<SessionList userId={props.userId} />, { right: true, width: 700 })
|
||||
}
|
||||
>
|
||||
Active Sessions
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{/* <SlideModal
|
||||
title={ <div>{props.userId}'s <span className="color-gray-medium">Live Sessions</span> </div> }
|
||||
isDisplayed={ showMenu }
|
||||
content={ showMenu && <SessionList /> }
|
||||
onClose={ () => setShowMenu(false) }
|
||||
/> */}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ function SessionList(props: Props) {
|
|||
>
|
||||
<div className="p-4">
|
||||
{props.list.map((session: any) => (
|
||||
<div className="mb-6">
|
||||
<div className="mb-6" key={session.sessionId}>
|
||||
{session.pageTitle && session.pageTitle !== '' && (
|
||||
<div className="flex items-center mb-2">
|
||||
<Label size="small" className="p-1">
|
||||
|
|
@ -55,7 +55,7 @@ function SessionList(props: Props) {
|
|||
<span className="ml-2 font-medium">{session.pageTitle}</span>
|
||||
</div>
|
||||
)}
|
||||
<SessionItem compact={true} onClick={() => hideModal()} key={session.sessionId} session={session} />
|
||||
<SessionItem compact={true} onClick={hideModal} session={session} />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -71,12 +71,13 @@ function LivePlayer({
|
|||
|
||||
return () => {
|
||||
if (!location.pathname.includes('multiview') || !location.pathname.includes(usedSession.sessionId)) {
|
||||
console.debug('unmount', usedSession.sessionId)
|
||||
playerInst?.clean?.();
|
||||
// @ts-ignore default empty
|
||||
setContextValue(defaultContextValue)
|
||||
}
|
||||
}
|
||||
}, [location.pathname]);
|
||||
}, [location.pathname, usedSession.sessionId]);
|
||||
|
||||
// LAYOUT (TODO: local layout state - useContext or something..)
|
||||
useEffect(() => {
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ function LivePlayerBlockHeader(props: any) {
|
|||
history.push(withSiteId(ASSIST_ROUTE, siteId));
|
||||
};
|
||||
|
||||
const { userId, userNumericHash, metadata, isCallActive, agentIds } = session;
|
||||
const { userId, metadata, isCallActive, agentIds } = session;
|
||||
let _metaList = Object.keys(metadata)
|
||||
.filter((i) => metaList.includes(i))
|
||||
.map((key) => {
|
||||
|
|
@ -87,7 +87,7 @@ function LivePlayerBlockHeader(props: any) {
|
|||
</div>
|
||||
)}
|
||||
<UserCard className="" width={width} height={height} />
|
||||
<AssistTabs userId={userId} userNumericHash={userNumericHash} />
|
||||
<AssistTabs userId={userId} />
|
||||
|
||||
<div className={cn('ml-auto flex items-center h-full', { hidden: closedLive })}>
|
||||
{_metaList.length > 0 && (
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ interface Props {
|
|||
compact?: boolean;
|
||||
isDisabled?: boolean;
|
||||
isAdd?: boolean;
|
||||
ignoreAssist?: boolean;
|
||||
}
|
||||
|
||||
function SessionItem(props: RouteComponentProps & Props) {
|
||||
|
|
@ -70,6 +71,7 @@ function SessionItem(props: RouteComponentProps & Props) {
|
|||
lastPlayedSessionId,
|
||||
onClick = null,
|
||||
compact = false,
|
||||
ignoreAssist = false,
|
||||
} = props;
|
||||
|
||||
const {
|
||||
|
|
@ -99,9 +101,10 @@ function SessionItem(props: RouteComponentProps & Props) {
|
|||
const hasUserId = userId || userAnonymousId;
|
||||
const isSessions = isRoute(SESSIONS_ROUTE, location.pathname);
|
||||
const isAssist =
|
||||
isRoute(ASSIST_ROUTE, location.pathname) ||
|
||||
isRoute(ASSIST_LIVE_SESSION, location.pathname) ||
|
||||
location.pathname.includes('multiview');
|
||||
!ignoreAssist &&
|
||||
(isRoute(ASSIST_ROUTE, location.pathname) ||
|
||||
isRoute(ASSIST_LIVE_SESSION, location.pathname) ||
|
||||
location.pathname.includes('multiview'));
|
||||
const isLastPlayed = lastPlayedSessionId === sessionId;
|
||||
|
||||
const _metaList = Object.keys(metadata)
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ function UserSessionsModal(props: Props) {
|
|||
<Loader loading={loading}>
|
||||
{data.sessions.map((session: any) => (
|
||||
<div className="border-b last:border-none" key={session.sessionId}>
|
||||
<SessionItem key={session.sessionId} session={session} compact={true} onClick={hideModal} />
|
||||
<SessionItem key={session.sessionId} session={session} compact={true} onClick={hideModal} ignoreAssist={true} />
|
||||
</div>
|
||||
))}
|
||||
</Loader>
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ export default class WebLivePlayer extends WebPlayer {
|
|||
clean = () => {
|
||||
this.incomingMessages.length = 0
|
||||
this.assistManager.clean()
|
||||
this.screen.clean()
|
||||
this.screen?.clean?.()
|
||||
// @ts-ignore
|
||||
this.screen = undefined;
|
||||
super.clean()
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@ export default class DOMManager extends ListWalker<Message> {
|
|||
private olStyleSheets: Map<number, OnloadStyleSheet> = new Map()
|
||||
/** @depreacted since tracker 4.0.2 Mapping by nodeID */
|
||||
private olStyleSheetsDeprecated: Map<number, OnloadStyleSheet> = new Map()
|
||||
private stringDict: Record<number,string> = {}
|
||||
|
||||
private upperBodyId: number = -1;
|
||||
private nodeScrollManagers: Map<number, ListWalker<SetNodeScroll>> = new Map()
|
||||
|
|
@ -49,6 +48,7 @@ export default class DOMManager extends ListWalker<Message> {
|
|||
constructor(
|
||||
private readonly screen: Screen,
|
||||
private readonly isMobile: boolean,
|
||||
private stringDict: Record<number,string>,
|
||||
public readonly time: number,
|
||||
setCssLoading: ConstructorParameters<typeof StylesManager>[1],
|
||||
) {
|
||||
|
|
@ -57,6 +57,10 @@ export default class DOMManager extends ListWalker<Message> {
|
|||
this.stylesManager = new StylesManager(screen, setCssLoading)
|
||||
}
|
||||
|
||||
setStringDict(stringDict: Record<number,string>) {
|
||||
this.stringDict = stringDict
|
||||
}
|
||||
|
||||
append(m: Message): void {
|
||||
if (m.tp === MType.SetNodeScroll) {
|
||||
let scrollManager = this.nodeScrollManagers.get(m.id)
|
||||
|
|
@ -192,7 +196,6 @@ export default class DOMManager extends ListWalker<Message> {
|
|||
// Maybetodo: start Document as 0-node in tracker
|
||||
this.vTexts.clear()
|
||||
this.stylesManager.reset()
|
||||
this.stringDict = {}
|
||||
return
|
||||
}
|
||||
case MType.CreateTextNode: {
|
||||
|
|
@ -227,12 +230,9 @@ export default class DOMManager extends ListWalker<Message> {
|
|||
case MType.SetNodeAttribute:
|
||||
this.setNodeAttribute(msg)
|
||||
return
|
||||
case MType.StringDict:
|
||||
this.stringDict[msg.key] = msg.value
|
||||
return
|
||||
case MType.SetNodeAttributeDict:
|
||||
this.stringDict[msg.nameKey] === undefined && logger.error("No dictionary key for msg 'name': ", msg)
|
||||
this.stringDict[msg.valueKey] === undefined && logger.error("No dictionary key for msg 'value': ", msg)
|
||||
this.stringDict[msg.nameKey] === undefined && logger.error("No dictionary key for msg 'name': ", msg, this.stringDict)
|
||||
this.stringDict[msg.valueKey] === undefined && logger.error("No dictionary key for msg 'value': ", msg, this.stringDict)
|
||||
if (this.stringDict[msg.nameKey] === undefined || this.stringDict[msg.valueKey] === undefined ) { return }
|
||||
this.setNodeAttribute({
|
||||
id: msg.id,
|
||||
|
|
|
|||
|
|
@ -1,14 +1,15 @@
|
|||
import logger from 'App/logger';
|
||||
|
||||
export type { PostponedStyleSheet } from './VirtualDOM'
|
||||
|
||||
export function insertRule(sheet: CSSStyleSheet | PostponedStyleSheet, msg: { rule: string, index: number }) {
|
||||
export function insertRule(
|
||||
sheet: { insertRule: (rule: string, index: number) => void },
|
||||
msg: { rule: string, index: number }
|
||||
) {
|
||||
try {
|
||||
sheet.insertRule(msg.rule, msg.index)
|
||||
} catch (e) {
|
||||
logger.warn(e, msg)
|
||||
try {
|
||||
sheet.insertRule(msg.rule, 0)
|
||||
sheet.insertRule(msg.rule, 0) // TODO: index renumeration in case of subsequent rule deletion
|
||||
logger.warn("Inserting rule into 0-index", e, msg)
|
||||
} catch (e) {
|
||||
logger.warn("Cannot insert rule.", e, msg)
|
||||
|
|
@ -16,7 +17,10 @@ export function insertRule(sheet: CSSStyleSheet | PostponedStyleSheet, msg: { ru
|
|||
}
|
||||
}
|
||||
|
||||
export function deleteRule(sheet: CSSStyleSheet | PostponedStyleSheet, msg: { index: number }) {
|
||||
export function deleteRule(
|
||||
sheet: { deleteRule: (index: number) => void },
|
||||
msg: { index: number }
|
||||
) {
|
||||
try {
|
||||
sheet.deleteRule(msg.index)
|
||||
} catch (e) {
|
||||
|
|
|
|||
|
|
@ -1,13 +1,21 @@
|
|||
import type Screen from '../Screen/Screen';
|
||||
import type { Message } from '../messages';
|
||||
import logger from 'App/logger';
|
||||
|
||||
import { MType } from '../messages';
|
||||
import type Screen from '../Screen/Screen';
|
||||
import type { Message, StringDict } from '../messages';
|
||||
|
||||
import { MType} from '../messages';
|
||||
import ListWalker from '../../common/ListWalker';
|
||||
import DOMManager from './DOM/DOMManager';
|
||||
|
||||
|
||||
export default class PagesManager extends ListWalker<DOMManager> {
|
||||
private currentPage: DOMManager | null = null
|
||||
/**
|
||||
* String Dictionary in tracker may be desync with CreateDocument (why???)
|
||||
* e.g. some StringDictionary and other messages before any 'CreateDocument' one
|
||||
* TODO: understand why and fix
|
||||
*/
|
||||
private currentStringDict: Record<number, string> = {}
|
||||
|
||||
constructor(
|
||||
private screen: Screen,
|
||||
|
|
@ -19,11 +27,19 @@ export default class PagesManager extends ListWalker<DOMManager> {
|
|||
Assumed that messages added in a correct time sequence.
|
||||
*/
|
||||
appendMessage(m: Message): void {
|
||||
if (m.tp === MType.StringDict) {
|
||||
if (this.currentStringDict[m.key] !== undefined) {
|
||||
this.currentStringDict = {} /* refresh stringDict */
|
||||
this.last?.setStringDict(this.currentStringDict)
|
||||
}
|
||||
this.currentStringDict[m.key] = m.value
|
||||
return
|
||||
}
|
||||
if (m.tp === MType.CreateDocument) {
|
||||
super.append(new DOMManager(this.screen, this.isMobile, m.time, this.setCssLoading))
|
||||
super.append(new DOMManager(this.screen, this.isMobile, this.currentStringDict, m.time, this.setCssLoading))
|
||||
}
|
||||
if (this.last === null) {
|
||||
// Log wrong
|
||||
logger.warn("DOMMessage before any document created, skipping:", m)
|
||||
return;
|
||||
}
|
||||
this.last.append(m)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue