import React, { ReactNode } from "react"; import { connect } from "react-redux"; import GenWindow from "../GenWindow"; import { WINDOWS } from "../../constants"; import { AppState, SkinGenExColors } from "../../types"; import * as Selectors from "../../selectors"; interface StateProps { skinGenExColors: SkinGenExColors; } interface OwnProps { sidebar: ReactNode; artists: ReactNode; albums: ReactNode; tracks: ReactNode; } type Props = StateProps & OwnProps; interface State { sidebarWidth: number; topPlaylistSectionHeight: number; artistsPanelWidth: number; } const DIVIDER_WIDTH = 9; // TODO: Tune these const SIDEBAR_MIN = 25; const SIDEBAR_MAX = 200; class LibraryLayout extends React.Component { constructor(props: Props) { super(props); this.state = { sidebarWidth: 100, // Pixels topPlaylistSectionHeight: 0.25, // Percent artistsPanelWidth: 0.5, // Percent }; } _onMouseMove(cb: (e: MouseEvent) => void) { const handleMouseUp = () => { document.removeEventListener("mousemove", cb); document.removeEventListener("mouseup", handleMouseUp); }; // TODO: Technically there's a leak here since the component could unmount while we are moving document.addEventListener("mousemove", cb); document.addEventListener("mouseup", handleMouseUp); } _handleSidebarMouseDown = (e: React.MouseEvent) => { const { pageX: startX } = e; const initialWidth = this.state.sidebarWidth; this._onMouseMove((moveEvent: MouseEvent) => { let sidebarWidth = initialWidth + moveEvent.pageX - startX; if (sidebarWidth < SIDEBAR_MIN) { sidebarWidth = 0; } sidebarWidth = Math.min(sidebarWidth, SIDEBAR_MAX); this.setState({ sidebarWidth }); }); }; _handlePlaylistResizeMouseDown = ( e: React.MouseEvent, windowHeight: number ) => { const { pageY: startY } = e; const avaliableHeight = windowHeight - DIVIDER_WIDTH; const initialHeight = avaliableHeight * this.state.topPlaylistSectionHeight; this._onMouseMove((moveEvent: MouseEvent) => { const deltaY = moveEvent.pageY - startY; const topPlaylistSectionPixelHeight = initialHeight + deltaY; this.setState({ topPlaylistSectionHeight: topPlaylistSectionPixelHeight / avaliableHeight, }); }); }; _handleArtistsResizeMouseDown = ( e: React.MouseEvent, windowWidth: number ) => { const { pageX: startX } = e; const avaliableWidth = windowWidth - DIVIDER_WIDTH - this.state.sidebarWidth; const initialWidth = avaliableWidth * this.state.artistsPanelWidth; this._onMouseMove((moveEvent: MouseEvent) => { const deltaX = moveEvent.pageX - startX; const artistsPanelPixelWidth = initialWidth + deltaX; this.setState({ artistsPanelWidth: artistsPanelPixelWidth / avaliableWidth, }); }); }; render() { return ( {({ width, height }) => (
{this.state.sidebarWidth === 0 ?
: this.props.sidebar}
{this.props.artists}
) => this._handleArtistsResizeMouseDown(e, width) } >
{this.props.albums}
) => this._handlePlaylistResizeMouseDown(e, height) } >
{this.props.tracks}
)} ); } } const mapStateToProps = (state: AppState): StateProps => { return { skinGenExColors: Selectors.getSkinGenExColors(state), }; }; export default connect(mapStateToProps)(LibraryLayout);