fix(player, frontend): use ScaleMode for screen
This commit is contained in:
parent
654682f4c9
commit
da264f41f5
7 changed files with 71 additions and 72 deletions
|
|
@ -7,21 +7,15 @@ import { PlayerContext } from 'App/components/Session/playerContext';
|
|||
import { observer } from 'mobx-react-lite'
|
||||
|
||||
function Player() {
|
||||
const [wrapperHeight, setWrapperHeight] = React.useState(0);
|
||||
const playerContext = React.useContext(PlayerContext);
|
||||
const screenWrapper = React.useRef<HTMLDivElement>(null);
|
||||
const portHeight = playerContext.store.get().portHeight
|
||||
React.useEffect(() => {
|
||||
const parentElement = findDOMNode(screenWrapper.current) as HTMLDivElement | null; //TODO: good architecture
|
||||
const parentElement = findDOMNode(screenWrapper.current) as HTMLDivElement | null;
|
||||
if (parentElement) {
|
||||
playerContext.player.attach(parentElement);
|
||||
playerContext.player.play();
|
||||
}
|
||||
}, []);
|
||||
|
||||
React.useEffect(() => {
|
||||
setWrapperHeight(portHeight)
|
||||
}, [portHeight]);
|
||||
|
||||
if (!playerContext.player) return null;
|
||||
|
||||
|
|
@ -31,7 +25,7 @@ function Player() {
|
|||
>
|
||||
<div className={cn("relative flex-1", 'overflow-visible')}>
|
||||
<Overlay isClickmap />
|
||||
<div className={cn(stl.screenWrapper, '!overflow-y-scroll')} style={{ height: wrapperHeight, maxHeight: 800 }} ref={screenWrapper} />
|
||||
<div className={cn(stl.screenWrapper, '!overflow-y-scroll')} style={{ maxHeight: 800 }} ref={screenWrapper} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { createWebPlayer } from 'Player';
|
||||
import { createClickMapPlayer } from 'Player';
|
||||
import { makeAutoObservable } from 'mobx';
|
||||
import withLocationHandlers from 'HOCs/withLocationHandlers';
|
||||
import PlayerContent from './ThinPlayerContent';
|
||||
|
|
@ -20,7 +20,7 @@ function WebPlayer(props: any) {
|
|||
const [contextValue, setContextValue] = useState<IPlayerContext>(defaultContextValue);
|
||||
|
||||
useEffect(() => {
|
||||
const [WebPlayerInst, PlayerStore] = createWebPlayer(customSession, (state) =>
|
||||
const [WebPlayerInst, PlayerStore] = createClickMapPlayer(customSession, (state) =>
|
||||
makeAutoObservable(state)
|
||||
);
|
||||
setContextValue({ player: WebPlayerInst, store: PlayerStore });
|
||||
|
|
@ -35,9 +35,9 @@ function WebPlayer(props: any) {
|
|||
contextValue.player && contextValue.player.play()
|
||||
if (isPlayerReady && insights.size > 0) {
|
||||
setTimeout(() => {
|
||||
contextValue.player.jump(jumpTimestamp)
|
||||
contextValue.player.pause()
|
||||
contextValue.player.scaleFullPage()
|
||||
contextValue.player.jump(jumpTimestamp)
|
||||
contextValue.player.scale()
|
||||
setTimeout(() => { contextValue.player.showClickmap(insights) }, 250)
|
||||
}, 500)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,18 @@ export function createWebPlayer(session: Record<string, any>, wrapStore?: (s:IWe
|
|||
}
|
||||
|
||||
|
||||
export function createClickMapPlayer(session: Record<string, any>, wrapStore?: (s:IWebPlayerStore) => IWebPlayerStore): [IWebPlayer, IWebPlayerStore] {
|
||||
let store: WebPlayerStore = new SimpleStore<WebState>({
|
||||
...WebPlayer.INITIAL_STATE,
|
||||
})
|
||||
if (wrapStore) {
|
||||
store = wrapStore(store)
|
||||
}
|
||||
|
||||
const player = new WebPlayer(store, session, false, true)
|
||||
return [player, store]
|
||||
}
|
||||
|
||||
export function createLiveWebPlayer(session: Record<string, any>, config: RTCIceServer[], wrapStore?: (s:IWebLivePlayerStore) => IWebLivePlayerStore): [IWebLivePlayer, IWebLivePlayerStore] {
|
||||
let store: WebLivePlayerStore = new SimpleStore<WebLiveState>({
|
||||
...WebLivePlayer.INITIAL_STATE,
|
||||
|
|
|
|||
|
|
@ -153,15 +153,18 @@ export default class Animator {
|
|||
}
|
||||
|
||||
freeze() {
|
||||
if (this.store.get().ready) {
|
||||
// making sure that replay is displayed completely
|
||||
setTimeout(() => {
|
||||
this.store.update({ freeze: true })
|
||||
this.pause()
|
||||
}, 250)
|
||||
} else {
|
||||
setTimeout(() => this.freeze(), 500)
|
||||
}
|
||||
return new Promise<void>(res => {
|
||||
if (this.store.get().ready) {
|
||||
// making sure that replay is displayed completely
|
||||
setTimeout(() => {
|
||||
this.store.update({ freeze: true })
|
||||
this.pause()
|
||||
res()
|
||||
}, 250)
|
||||
} else {
|
||||
setTimeout(() => res(this.freeze()), 500)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
togglePlay = () => {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,13 @@ export const INITIAL_STATE: State = {
|
|||
}
|
||||
|
||||
|
||||
export enum ScaleMode {
|
||||
Embed,
|
||||
//AdjustParentWidth
|
||||
AdjustParentHeight,
|
||||
}
|
||||
|
||||
|
||||
function getElementsFromInternalPoint(doc: Document, { x, y }: Point): Element[] {
|
||||
// @ts-ignore (IE, Edge)
|
||||
if (typeof doc.msElementsFromRect === 'function') {
|
||||
|
|
@ -55,9 +62,9 @@ export default class Screen {
|
|||
|
||||
private readonly iframe: HTMLIFrameElement;
|
||||
private readonly screen: HTMLDivElement;
|
||||
private parentElement: HTMLElement | null = null;
|
||||
private parentElement: HTMLElement | null = null
|
||||
|
||||
constructor(isMobile: boolean) {
|
||||
constructor(isMobile: boolean, private scaleMode: ScaleMode = ScaleMode.Embed) {
|
||||
const iframe = document.createElement('iframe');
|
||||
iframe.className = styles.iframe;
|
||||
this.iframe = iframe;
|
||||
|
|
@ -79,11 +86,10 @@ export default class Screen {
|
|||
attach(parentElement: HTMLElement) {
|
||||
if (this.parentElement) {
|
||||
this.parentElement = null
|
||||
console.error("BaseScreen: Trying to attach an attached screen.");
|
||||
console.warn("BaseScreen: reattaching the screen.");
|
||||
}
|
||||
|
||||
parentElement.appendChild(this.screen);
|
||||
|
||||
this.parentElement = parentElement;
|
||||
|
||||
/* == For the Inspecting Document content == */
|
||||
|
|
@ -124,6 +130,7 @@ export default class Screen {
|
|||
private boundingRect: DOMRect | null = null;
|
||||
private getBoundingClientRect(): DOMRect {
|
||||
if (this.boundingRect === null) {
|
||||
// TODO: use this.screen instead in order to separate overlay functionality
|
||||
return this.boundingRect = this.overlay.getBoundingClientRect() // expensive operation?
|
||||
}
|
||||
return this.boundingRect
|
||||
|
|
@ -200,48 +207,41 @@ export default class Screen {
|
|||
if (!this.parentElement) return;
|
||||
const { offsetWidth, offsetHeight } = this.parentElement;
|
||||
|
||||
this.scaleRatio = Math.min(offsetWidth / width, offsetHeight / height);
|
||||
if (this.scaleRatio > 1) {
|
||||
this.scaleRatio = 1;
|
||||
} else {
|
||||
this.scaleRatio = Math.round(this.scaleRatio * 1e3) / 1e3;
|
||||
let translate = ""
|
||||
let posStyles = {}
|
||||
switch (this.scaleMode) {
|
||||
case ScaleMode.Embed:
|
||||
this.scaleRatio = Math.min(offsetWidth / width, offsetHeight / height)
|
||||
translate = "translate(-50%, -50%)"
|
||||
break;
|
||||
case ScaleMode.AdjustParentHeight:
|
||||
this.scaleRatio = offsetWidth / width
|
||||
translate = "translate(-50%, 0)"
|
||||
posStyles = { top: 0 }
|
||||
break;
|
||||
}
|
||||
this.screen.style.transform = `scale(${ this.scaleRatio }) translate(-50%, -50%)`;
|
||||
this.screen.style.width = width + 'px';
|
||||
this.screen.style.height = height + 'px';
|
||||
this.iframe.style.width = width + 'px';
|
||||
this.iframe.style.height = height + 'px';
|
||||
|
||||
this.boundingRect = this.overlay.getBoundingClientRect();
|
||||
}
|
||||
|
||||
scaleFullPage() {
|
||||
if (!this.parentElement || !this.document) return;
|
||||
|
||||
const { width: boxWidth } = this.parentElement.getBoundingClientRect();
|
||||
const { height, width } = this.document.body.getBoundingClientRect();
|
||||
this.overlay.remove()
|
||||
|
||||
this.scaleRatio = boxWidth/width;
|
||||
if (this.scaleRatio > 1) {
|
||||
this.scaleRatio = 1;
|
||||
} else {
|
||||
this.scaleRatio = Math.round(this.scaleRatio * 1e3) / 1e3;
|
||||
}
|
||||
|
||||
Object.assign(this.screen.style, {
|
||||
top: '0',
|
||||
left: '50%',
|
||||
if (this.scaleMode === ScaleMode.AdjustParentHeight) {
|
||||
this.parentElement.style.height = this.scaleRatio * height + 'px'
|
||||
}
|
||||
|
||||
Object.assign(this.screen.style, posStyles, {
|
||||
height: height + 'px',
|
||||
width: width + 'px',
|
||||
transform: `scale(${this.scaleRatio}) translate(-50%, 0)`,
|
||||
transform: `scale(${this.scaleRatio}) ${translate}`,
|
||||
})
|
||||
Object.assign(this.iframe.style, {
|
||||
width: width + 'px',
|
||||
height: height + 'px',
|
||||
})
|
||||
|
||||
return height
|
||||
this.boundingRect = this.overlay.getBoundingClientRect();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@ import Player from '../player/Player'
|
|||
import MessageManager from './MessageManager'
|
||||
import InspectorController from './addons/InspectorController'
|
||||
import TargetMarker from './addons/TargetMarker'
|
||||
import Screen from './Screen/Screen'
|
||||
import Screen, { ScaleMode } from './Screen/Screen'
|
||||
|
||||
|
||||
// export type State = typeof WebPlayer.INITIAL_STATE
|
||||
|
||||
|
|
@ -17,7 +18,6 @@ export default class WebPlayer extends Player {
|
|||
...MessageManager.INITIAL_STATE,
|
||||
|
||||
inspectorMode: false,
|
||||
portHeight: 0,
|
||||
}
|
||||
|
||||
private readonly inspectorController: InspectorController
|
||||
|
|
@ -26,7 +26,7 @@ export default class WebPlayer extends Player {
|
|||
|
||||
private targetMarker: TargetMarker
|
||||
|
||||
constructor(protected wpState: Store<typeof WebPlayer.INITIAL_STATE>, session: any, live: boolean) {
|
||||
constructor(protected wpState: Store<typeof WebPlayer.INITIAL_STATE>, session: any, live: boolean, isClickMap = false) {
|
||||
let initialLists = live ? {} : {
|
||||
event: session.events || [],
|
||||
stack: session.stackEvents || [],
|
||||
|
|
@ -40,7 +40,7 @@ export default class WebPlayer extends Player {
|
|||
) || [],
|
||||
}
|
||||
|
||||
const screen = new Screen(session.isMobile)
|
||||
const screen = new Screen(session.isMobile, isClickMap ? ScaleMode.AdjustParentHeight : ScaleMode.Embed)
|
||||
const messageManager = new MessageManager(session, wpState, screen, initialLists)
|
||||
super(wpState, messageManager)
|
||||
this.screen = screen
|
||||
|
|
@ -71,20 +71,11 @@ export default class WebPlayer extends Player {
|
|||
}
|
||||
|
||||
scale = () => {
|
||||
console.log('called scale')
|
||||
const { width, height } = this.wpState.get()
|
||||
this.screen.scale({ width, height })
|
||||
this.inspectorController.scale({ width, height })
|
||||
|
||||
// this.updateMarketTargets() ??
|
||||
}
|
||||
|
||||
scaleFullPage = () => {
|
||||
window.removeEventListener('resize', this.scale)
|
||||
window.addEventListener('resize', this.scaleFullPage)
|
||||
|
||||
const portHeight = this.screen.scaleFullPage()
|
||||
return this.wpState.update({ portHeight })
|
||||
this.targetMarker.updateMarkedTargets()
|
||||
}
|
||||
|
||||
// Inspector & marker
|
||||
|
|
@ -119,12 +110,11 @@ export default class WebPlayer extends Player {
|
|||
}
|
||||
|
||||
showClickmap = (...args: Parameters<TargetMarker['injectTargets']>) => {
|
||||
this.freeze()
|
||||
if (this.wpState.get().portHeight !== 0) {
|
||||
this.targetMarker.injectTargets(...args)
|
||||
} else {
|
||||
setTimeout(() => this.showClickmap(...args), 500)
|
||||
}
|
||||
this.screen.overlay.remove() // hack. TODO: 1.split Screen functionalities (overlay, mounter) 2. separate ClickMapPlayer class that does not create overlay
|
||||
this.targetMarker.injectTargets(...args)
|
||||
this.freeze().then(() => {
|
||||
this.targetMarker.updateMarkedTargets()
|
||||
})
|
||||
}
|
||||
|
||||
setMarkerClick = (...args: Parameters<TargetMarker['setOnMarkerClick']>) => {
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ export default class TargetMarker {
|
|||
private readonly store: Store<State>,
|
||||
) {}
|
||||
|
||||
updateMarketTargets() {
|
||||
updateMarkedTargets() {
|
||||
const { markedTargets } = this.store.get()
|
||||
if (markedTargets) {
|
||||
this.store.update({
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue