// Dynamically set the css background images for all the sprites import React from "react"; import { createPortal } from "react-dom"; import { connect } from "react-redux"; import { imageSelectors, cursorSelectors } from "../skinSelectors"; const mapRegionNamesToIds = { normal: "mainWindowClipPath", windowshade: "shadeMainWindowClipPath", equalizer: "equalizerWindowClipPath", equalizerws: "shadeEqualizerWindowClipPath" }; const mapRegionNamesToMatcher = { normal: "#main-window:not(.shade)", windowshade: "#main-window.shade", equalizer: "#equalizer-window:not(.shade)", equalizerws: "#equalizer-window.shade" }; const numExIsUsed = skinImages => !!skinImages.DIGIT_0_EX; class Css extends React.Component { componentWillMount() { const style = document.createElement("style"); style.type = "text/css"; document.head.appendChild(style); this.style = style; } componentWillUnmount() { this.style.remove(); this.style = null; } render() { return createPortal(this.props.children, this.style); } } class ClipPaths extends React.Component { componentWillMount() { const paths = document.createElement("div"); document.body.appendChild(paths); this.paths = paths; } componentWillUnmount() { this.paths.remove(); this.paths = null; } render() { // this.props.children should be an object containing arrays of strings. The // keys are ids, and the arrays are arrays of polygon point strings const { children } = this.props; return createPortal( , this.paths ); } } const Skin = props => { const { skinImages, skinCursors } = props; if (!skinImages || !skinCursors) { return null; } const cssRules = []; Object.keys(imageSelectors).map(imageName => { const imageUrl = skinImages[imageName]; if (imageUrl) { imageSelectors[imageName].forEach(selector => { cssRules.push( `#winamp2-js ${selector} {background-image: url(${imageUrl})}` ); }); } }); Object.keys(cursorSelectors).map(cursorName => { const cursorUrl = skinCursors[cursorName]; if (cursorUrl) { cursorSelectors[cursorName].forEach(selector => { cssRules.push( `#winamp2-js ${selector} {cursor: url(${cursorUrl}), auto}` ); }); } }); if (numExIsUsed(skinImages)) { // This alternate number file requires that the minus sign be // formatted differently. cssRules.push( "#winamp2-js .status #time #minus-sign { top: 0px; left: -1px; width: 9px; height: 13px; }" ); } const clipPaths = {}; for (const [regionName, polygons] of Object.entries(props.skinRegion)) { if (polygons) { const matcher = mapRegionNamesToMatcher[regionName]; const id = mapRegionNamesToIds[regionName]; clipPaths[id] = polygons; cssRules.push(`#winamp2-js ${matcher} { clip-path: url(#${id}); }`); } } return (