import * as React from 'react';
import { observable, autorun } from 'mobx';
import { observer, inject } from 'mobx-react';
// Containers
import ControlContainer from './ControlContainer';
import SelectorContainer from './SelectorContainer';
import DrawerContainer from './DrawerContainer';
import MenuContainer from './MenuContainer';
// Components
import { Cover, Progress } from '../components';
// Stylus
import '../styles/MUSE.styl';
// Utils
import { applyMiddleware } from '../utils';
interface UIContainerProps {
id: any;
store?: any;
accuracy: any;
}
interface UIContainerState {
currentTime: number;
duration: number;
}
interface Document {
exitFullscreen: () => void;
mozCancelFullScreen: () => void;
webkitExitFullscreen: () => void;
fullscreenElement: () => void;
mozFullScreenElement: () => void;
webkitFullscreenElement: () => void;
}
@inject('store')
@observer
export class UIContainer extends React.Component<
UIContainerProps,
UIContainerState
> {
@observable touchTimer: any = undefined;
id: string | number = undefined;
player: HTMLElement;
unsubscriber: any = undefined;
public constructor(props: UIContainerProps) {
super(props);
this.id = props.id;
this.state = {
currentTime: 0,
duration: 0
};
}
render(): JSX.Element {
const {
playList,
currentMusicIndex,
playerLayout,
isDrawerOpen,
coverImage
} = this.props.store,
{ id, store } = this.props,
cover = playList[currentMusicIndex].cover;
const className: string =
'muse-player ' +
playerLayout +
(isDrawerOpen ? ' muse-root__state-drawer-open' : '');
return (
(this.player = ref)}
data-length={playList.length}
>
);
}
/* life cycles */
public componentDidMount(): void {
const { store } = this.props,
instance = {
component: this,
ref: this.player,
id: this.id
};
store.pushPlayerInstance(instance, this.id);
window.addEventListener('resize', this.onWindowResize);
this.player.addEventListener('contextmenu', this.onPlayerContextMenu);
this.player.addEventListener('touchstart', this.onMobileTouchStart);
this.player.addEventListener('touchend', this.onMobileTouchEnd);
this.player.addEventListener(
'webkitfullscreenchange',
this.onFullscreenChange
);
this.player.addEventListener(
'mozfullscreenchange',
this.onFullscreenChange
);
this.unsubscriber = autorun(this.subscriber);
applyMiddleware('afterRender', instance);
applyMiddleware('onPlayerResize', instance);
}
public componentWillUnmount(): void {
window.removeEventListener('resize', this.onWindowResize);
this.player.removeEventListener('contextmenu', this.onPlayerContextMenu);
this.player.removeEventListener('touchstart', this.onMobileTouchStart);
this.player.removeEventListener('touchend', this.onMobileTouchEnd);
this.player.removeEventListener(
'webkitfullscreenchange',
this.onFullscreenChange
);
this.player.removeEventListener(
'mozfullscreenchange',
this.onFullscreenChange
);
this.unsubscriber();
}
protected getFullscreenState = (): boolean => {
return (document as any).fullscreenElement
? true
: (document as any).webkitFullscreenElement
? true
: (document as any).mozFullScreenElement ? true : false;
};
/* fullscreen related store subscribers */
protected subscriber = (): void => {
const eleFSState = this.getFullscreenState(),
{ isFullscreen } = this.props.store,
{ player } = this;
if (eleFSState !== isFullscreen && isFullscreen) {
setTimeout(() => {
const state = player.requestFullscreen
? player.requestFullscreen() || true
: (player as any).webkitRequestFullscreen
? (player as any).webkitRequestFullscreen() || true
: false;
if (!state && !(player as any).mozRequestFullScreen) {
console.error(
'It seems that your browser does not support HTML5 Fullscreen feature.'
);
}
}, 10);
} else if (eleFSState !== isFullscreen && !isFullscreen) {
document.exitFullscreen
? document.exitFullscreen()
: (document as any).webkitExitFullscreen
? (document as any).webkitExitFullscreen()
: (document as any).mozCancelFullScreen
? (document as any).mozCancelFullScreen()
: () => false;
} else {
return;
}
};
/* event listeners */
protected onMobileTouchStart = (e: any): void => {
const state = this.props.store;
if (state.isMenuOpen) {
return;
}
this.touchTimer = setTimeout(() => this.onPlayerContextMenu(e), 1000);
};
protected onMobileTouchEnd = (): void => {
clearTimeout(this.touchTimer);
};
protected onPlayerContextMenu = (e: any): void => {
e.preventDefault();
e.stopPropagation();
this.props.store.toggleMenu(true);
// set position
const menuElement: any = this.player.querySelector('.muse-menu');
if (!e.touches) {
menuElement.style.top = e.clientY + 'px';
menuElement.style.left = e.clientX + 'px';
} else {
menuElement.style.top = e.touches[0].clientY + 'px';
menuElement.style.left = e.touches[0].clientX + 'px';
}
// register destroy events
document.body.addEventListener('click', this.destroyPlayerMenu);
};
protected onWindowResize = (e: any): void => {
applyMiddleware('onPlayerResize', this.props.store.playerInstance, e);
};
protected onFullscreenChange = (): void => {
const currentState = this.getFullscreenState(),
storedState = this.props.store.isFullscreen;
if (currentState !== storedState) {
this.props.store.toggleFullscreen(currentState);
}
};
protected destroyPlayerMenu = (e: any): any => {
e.preventDefault();
this.props.store.toggleMenu(false);
document.body.removeEventListener('click', this.destroyPlayerMenu);
};
}
export default UIContainer;