diff options
Diffstat (limited to 'scraper/client/search/search.query.js')
| -rw-r--r-- | scraper/client/search/search.query.js | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/scraper/client/search/search.query.js b/scraper/client/search/search.query.js new file mode 100644 index 00000000..276f1943 --- /dev/null +++ b/scraper/client/search/search.query.js @@ -0,0 +1,227 @@ +import React, { Component } from 'react' +import { Link } from 'react-router-dom' +import { bindActionCreators } from 'redux' +import { connect } from 'react-redux' +import toBlob from 'data-uri-to-blob' + +import { clamp, px } from '../util' +import { Loader } from '../common' + +import * as searchActions from './search.actions' +import SearchMeta from './search.meta' + +const defaultState = { + dragging: false, + draggingBox: false, + bounds: null, + mouseX: 0, + mouseY: 0, + box: { + x: 0, + y: 0, + w: 0, + h: 0, + } +} + +class SearchQuery extends Component { + state = { + ...defaultState + } + + constructor() { + super() + this.handleMouseDown = this.handleMouseDown.bind(this) + this.handleMouseDownOnBox = this.handleMouseDownOnBox.bind(this) + this.handleMouseMove = this.handleMouseMove.bind(this) + this.handleMouseUp = this.handleMouseUp.bind(this) + } + + componentDidMount() { + document.body.addEventListener('mousemove', this.handleMouseMove) + document.body.addEventListener('mouseup', this.handleMouseUp) + } + + componentDidUpdate(prevProps) { + // console.log(this.props.query.query, !prevProps.query.query) + if (this.state.bounds && (!this.props.query.query || !prevProps.query.query || this.props.query.query.url !== prevProps.query.query.url)) { + this.setState({ ...defaultState }) + } + } + + componentWillUnmount() { + document.body.removeEventListener('mousemove', this.handleMouseMove) + document.body.removeEventListener('mouseup', this.handleMouseUp) + } + + handleMouseDown(e) { + e.preventDefault() + const bounds = this.imgRef.getBoundingClientRect() + const mouseX = e.pageX + const mouseY = e.pageY + const x = mouseX - bounds.left + const y = mouseY - bounds.top + const w = 1 + const h = 1 + this.setState({ + dragging: true, + bounds, + mouseX, + mouseY, + box: { + x, y, w, h, + } + }) + } + + handleMouseDownOnBox(e) { + const bounds = this.imgRef.getBoundingClientRect() + const mouseX = e.pageX + const mouseY = e.pageY + this.setState({ + draggingBox: true, + bounds, + mouseX, + mouseY, + initialBox: { + ...this.state.box + }, + box: { + ...this.state.box + } + }) + } + + handleMouseMove(e) { + const { + dragging, draggingBox, + bounds, mouseX, mouseY, initialBox, box + } = this.state + if (dragging) { + e.preventDefault() + let { x, y } = box + let w = clamp(e.pageX - mouseX, 0, bounds.width - x) + let h = clamp(e.pageY - mouseY, 0, bounds.height - y) + this.setState({ + box: { + x, y, w, h, + } + }) + } else if (draggingBox) { + e.preventDefault() + let { x, y, w, h } = initialBox + let dx = (e.pageX - mouseX) + let dy = (e.pageY - mouseY) + this.setState({ + box: { + x: clamp(x + dx, 0, bounds.width - w), + y: clamp(y + dy, 0, bounds.height - h), + w, + h, + } + }) + } + } + + handleMouseUp(e) { + const { actions } = this.props + const { dragging, draggingBox, bounds, box } = this.state + if (!dragging && !draggingBox) return + e.preventDefault() + const { x, y, w, h } = box + // console.log(x, y, w, h) + const img = this.imgRef + const canvas = document.createElement('canvas') + const ctx = canvas.getContext('2d') + const ratio = img.naturalWidth / bounds.width + canvas.width = w * ratio + canvas.height = h * ratio + if (w < 10 || h < 10) { + this.setState({ dragging: false, draggingBox: false, box: { x: 0, y: 0, w: 0, h: 0 } }) + return + } + this.setState({ dragging: false, draggingBox: false }) + // query_div.appendChild(canvas) + const newImage = new Image() + let loaded = false + newImage.onload = () => { + if (loaded) return + loaded = true + newImage.onload = null + ctx.drawImage( + newImage, + Math.round(x * ratio), + Math.round(y * ratio), + Math.round(w * ratio), + Math.round(h * ratio), + 0, 0, canvas.width, canvas.height + ) + const blob = toBlob(canvas.toDataURL('image/jpeg', 0.9)) + actions.upload(blob, { + ...this.props.query.query, + crop: { + x, y, w, h, + } + }) + } + // console.log(img.src) + newImage.crossOrigin = 'anonymous' + newImage.src = img.src + if (newImage.complete) { + newImage.onload() + } + } + + render() { + const { query } = this.props.query + const { box } = this.state + const { x, y, w, h } = box + if (!query) return null + if (query.loading) { + return <div className="searchQuery column"><h2>Loading results...</h2><Loader /></div> + } + let { url } = query + if (url && url.indexOf('static') === 0) { + url = '/search/' + url + } + return ( + <div className="searchQuery row"> + <div className="searchBox"> + <img + src={url} + ref={ref => this.imgRef = ref} + onMouseDown={this.handleMouseDown} + crossOrigin='anonymous' + /> + {!!w && + <div + className="box" + style={{ + left: x, + top: y, + width: w, + height: h, + }} + onMouseDown={this.handleMouseDownOnBox} + /> + } + </div> + <div> + <h3>Your Query</h3> + <SearchMeta query={query} /> + </div> + </div> + ) + } +} + +const mapStateToProps = state => ({ + query: state.search.query, + options: state.search.options, +}) + +const mapDispatchToProps = dispatch => ({ + actions: bindActionCreators({ ...searchActions }, dispatch), +}) + +export default connect(mapStateToProps, mapDispatchToProps)(SearchQuery) |
