import React, { Component } from 'react' import { Route } from 'react-router-dom' import { bindActionCreators } from 'redux' import { connect } from 'react-redux' import { session } from '../../../session' import actions from '../../../actions' import * as pageActions from '../page.actions' import * as tileActions from '../../tile/tile.actions' import { Loader } from '../../../common' import { clamp, dist } from '../../../util' const defaultState = { dragging: false, bounds: null, mouseX: 0, mouseY: 0, box: { x: 0, y: 0, w: 0, h: 0, }, tile: null, } class PageEditor extends Component { state = { ...defaultState, } constructor() { super() // bind these events in the constructor, so we can remove event listeners later this.handleMouseDown = this.handleMouseDown.bind(this) this.handleMouseMove = this.handleMouseMove.bind(this) this.handleMouseUp = this.handleMouseUp.bind(this) this.handleWindowResize = this.handleWindowResize.bind(this) this.pageRef = React.createRef() } getBoundingClientRect() { if (!this.pageRef.current) return null const rect = this.pageRef.current.getBoundingClientRect() const scrollTop = document.body.scrollTop || document.body.parentNode.scrollTop const scrollLeft = document.body.scrollLeft || document.body.parentNode.scrollLeft const bounds = { top: rect.top + scrollTop, left: rect.left + scrollLeft, width: rect.width, height: rect.height, } // console.log(bounds) return bounds } componentDidMount() { document.body.addEventListener('mousemove', this.handleMouseMove) document.body.addEventListener('mouseup', this.handleMouseUp) window.addEventListener('resize', this.handleWindowResize) this.setState({ bounds: this.getBoundingClientRect() }) } componentDidUpdate(prevProps) { if (!this.state.bounds) { this.setState({ bounds: this.getBoundingClientRect() }) } } handleWindowResize() { this.setState({ bounds: this.getBoundingClientRect() }) } handleMouseDown(e, tile) { const bounds = this.getBoundingClientRect() const mouseX = e.pageX const mouseY = e.pageY // let w = 128 / bounds.width // let h = 16 / bounds.height let { x, y } = tile.settings // x = clamp(x, 0, 1) // y = clamp(y, 0, 1) this.setState({ tile, draggingBox: true, bounds, mouseX, mouseY, box: { dx: 0, dy: 0, // x, y, // w, h, }, initialBox: { // x, y, // w, h, } }) } handleMouseMove(e) { const { dragging, draggingBox, bounds, mouseX, mouseY, initialBox, box } = this.state if (draggingBox) { e.preventDefault() let { x, y, w, h } = initialBox let dx = (e.pageX - mouseX) let dy = (e.pageY - mouseY) this.setState({ box: { dx, dy, // x: clamp(x + (dx / bounds.width), 0, 1.0 - w), // y: clamp(y + (dy / bounds.height), 0, 1.0 - h), // w, h, } }) } } handleMouseUp(e) { // const { actions } = this.props const { temporaryTile } = this.props const { dragging, draggingBox, bounds, box, tile } = this.state if (!dragging && !draggingBox) return e.preventDefault() // const { x, y, w, h } = box const { dx, dy } = box let url = window.location.pathname this.setState({ page: null, box: null, initialBox: null, dragging: false, draggingBox: false, }) // console.log(page) if (dist(0, 0, dx, dy) < 2) { return } const updatedTile = { ...tile, settings: { ...tile.settings, x: tile.settings.x + dx, y: tile.settings.y + dy, } } if (temporaryTile && tile.id === temporaryTile.id) { this.props.tileActions.updateTemporaryTile(updatedTile) } if (tile.id !== 'new') { this.props.pageActions.updatePageTile(updatedTile) actions.tile.update(updatedTile) } } render(){ if (!this.state.bounds) { return (
) } const { temporaryTile } = this.props const currentTile = this.state.tile const currentBox = this.state.box const { res } = this.props.page.show return (
{res.tiles.map(tile => { if (temporaryTile && temporaryTile.id === tile.id) { tile = temporaryTile } return ( this.handleMouseDown(e, tile)} onDoubleClick={e => this.props.pageActions.showEditTileForm(tile.id)} /> ) })} {!!(temporaryTile && temporaryTile.id === 'new') && ( this.handleMouseDown(e, temporaryTile)} /> )}
) } } const TileHandle = ({ tile, bounds, box, onMouseDown, onDoubleClick }) => { // console.log(tile) const { width, height } = tile.settings const style = { transform: generateTransform(tile, box), } // console.log(generateTransform(tile)) let content; let className = 'tile ' + tile.type // console.log(tile.settings) switch (tile.type) { case 'image': if (!tile.settings.url) { return null } if (tile.settings.is_tiled) { style.backgroundImage = 'url(' + tile.settings.url + ')' style.backgroundPosition = tile.settings.align.replace('_', ' ') switch (tile.settings.tile_style) { default: case 'tile': break case 'cover': style.backgroundSize = 'cover' break case 'contain': style.backgroundSize = 'contain' break case 'contain no-repeat': style.backgroundSize = 'contain' style.backgroundRepeat = 'no-repeat' break } className += ' is_tiled' } else { className += ' ' + tile.settings.align content = } break case 'text': if (!tile.settings.content) { return null } content = className += ' ' + tile.settings.align style.width = tile.settings.width ? tile.settings.width + 'px' : 'auto' style.height = tile.settings.height ? tile.settings.height + 'px' : 'auto' break } return (
{content}
) } const generateTransform = (tile, box) => { let { x, y, align, rotation, scale, is_tiled } = tile.settings if (is_tiled) { return 'translateZ(0)' } if (box) { x += box.dx y += box.dy } const [yalign, xalign] = align.split('_') let transform = ['translateZ(0)'] if (yalign === 'center') { transform.push('translateY(-50%)') } if (xalign === 'center') { transform.push('translateX(-50%)') } // if (x % 2 == 1) x += 0.5 // if (y % 2 == 1) y += 0.5 transform.push('translateX(' + x + 'px)') transform.push('translateY(' + y + 'px)') if (scale !== 1) { transform.push('scale(' + scale + ')') } if (rotation !== 0) { transform.push('rotateZ(' + rotation + 'rad)') } return transform.join(' ') } const mapStateToProps = state => ({ graph: state.graph, page: state.page, temporaryTile: state.tile.temporaryTile, }) const mapDispatchToProps = dispatch => ({ pageActions: bindActionCreators({ ...pageActions }, dispatch), tileActions: bindActionCreators({ ...tileActions }, dispatch), }) export default connect(mapStateToProps, mapDispatchToProps)(PageEditor)