<commit_before>import React, { Component } from 'react';
import { PanResponder, TouchableOpacity, View, Text, Dimensions,  ScrollView, StyleSheet } from 'react-native';

import Svg, { G, Text as SvgText, Rect, Path } from 'react-native-svg';
import StaticContainer from 'react-static-container';

import * as d3Scale from 'd3-scale';

import T from '../components/T';


const deviceWidth = Dimensions.get('window').width;
const barMargin = 1; // 1 on each side
const defaultStockChartHeight = 200;
const barWidth = 5;


class CandleStickWithPan extends Component {
  constructor(props) {
    super(props);
    this.state = {
      data: {},
      showGridline: false,
			offset: 0,
      dragging: false
    };
  }

	componentWillMount() {
		this._panResponder = PanResponder.create({
			onStartShouldSetPanResponder: this._handleStartShouldSetPanResponder,
      onMoveShouldSetPanResponder: this._alwaysTrue,
			onPanResponderGrant: this._alwaysTrue,
			onPanResponderMove: this._handlePanResponderMove,
			onPanResponderRelease: this._handlePanResponderEnd,
			onPanResponderTerminate: this._handlePanResponderEnd
		});
	}

	_alwaysTrue = () => true

  componentDidMount() {
    this.getStockQuotes();
  }

  _handlePanResponderEnd = () => {
    this.setState({dragging: false});
  }

	_handlePanResponderMove = (e, gestureState) => {
		const { dx } = gestureState;
    console.log('_handlePanResponderMove', gestureState)
    if (dx) {
      this.setState({offset: Math.max(this.state.offset + dx, 0)});
    }
	}

  // show the cross line
  _handleStartShouldSetPanResponder = (e, gestureState) => {
    const { locationX, locationY } = e.nativeEvent;

    const current = Math.floor((deviceWidth - locationX) / (barWidth + 2 * barMargin));
    this.setCurrentItem(current)
    this.setState({dragging: true});
    return true;
  }

  getStockQuotes = () => {
    const d = new Date();
    const today = new Date(`${d.getFullYear()}/${d.getMonth() + 1}/${d.getDate()}`).getTime();
    const from = today + 86400 * 1000;
    const to = from - 86400 * 30 * 1000;
    // const url = `http://hulk.dev.cnyes.cool/api/v1/history?symbol=2330&from=1467302400&to=1471536000&resolution=D`;
    const url = `http://hulk.dev.cnyes.cool/api/v1/history?symbol=2330&from=${Math.floor(from/1000)}&to=${Math.floor(to/1000)}&resolution=D`;
    fetch(url)
      .then(rsp => rsp.json())
      .then(data => {
        this.setState({ data, current: 0 });
      });
  }

  loadMore = () => {
    const { nextTime } = this.state.data;
    const to = (nextTime * 1000- 86400 * 30 * 1000) / 1000;
    if (nextTime) {
      const url = `http://hulk.dev.cnyes.cool/api/v1/history?symbol=2330&from=${nextTime}&to=${Math.floor(to)}&resolution=D`;
      fetch(url)
        .then(rsp => rsp.json())
        .then(data => {
          const originData = this.state.data;
          const newData = {
            ...originData,
            ...data,
            c: [...originData.c, ...data.c],
            h: [...originData.h, ...data.h],
            l: [...originData.l, ...data.l],
            o: [...originData.o, ...data.o],
            t: [...originData.t, ...data.t],
            v: [...originData.v, ...data.v],
          }
          this.setState({data: newData});
        });
    }
  }

  getLinearScale(domain, range, isTime = false) {
    return (isTime ? d3Scale.scaleTime() : d3Scale.scaleLinear()).domain(domain).range(range);
  }

  getItemByIndex = (i) => {
    const { c, h, l, o, t, v, s } = this.state.data;
    const { current } = this.state;
    return {
      c: c[i],
      h: h[i],
      l: l[i],
      o: o[i],
      t: new Date(t[i] * 1000),
      v: v[i],
      s,
      color: o[i] <= c[i] ? 'rgb(210, 72, 62)' : 'rgb(28, 193, 135)'
    };
  }

  setCurrentItem = (i) => {
    if (i <= this.state.data.o.length - 1) {
      this.setState({ current: i });
    }
  }

  toggleGridline = () => {
    this.setState({ showGridline: !this.state.showGridline });
  }


  render() {
    console.log('state', this.state);
    // console.log('dragging', this.state.dragging)
    const { current, offset } = this.state;
    const { c, h, l, o, t, s } = this.state.data;
    if (s === undefined) {
      return null;
    }
    const highestPrice = Math.max(...h);
    const lowestPrice = Math.min(...l);
    const priceScale = this.getLinearScale([lowestPrice, highestPrice], [0, defaultStockChartHeight].reverse());
    const svgWidth = Math.max(deviceWidth, c.length * (barWidth + 2 * barMargin));<commit_msg>fix when keep pressing, the svg will slides<commit_after>import React, { Component } from 'react';
import { PanResponder, TouchableOpacity, View, Text, Dimensions,  ScrollView, StyleSheet } from 'react-native';

import Svg, { G, Text as SvgText, Rect, Path } from 'react-native-svg';
import StaticContainer from 'react-static-container';

import * as d3Scale from 'd3-scale';

import T from '../components/T';


const deviceWidth = Dimensions.get('window').width;
const barMargin = 1; // 1 on each side
const defaultStockChartHeight = 200;
const barWidth = 5;


class CandleStickWithPan extends Component {
  constructor(props) {
    super(props);
    this.state = {
      data: {},
      showGridline: false,
			offset: 0,
      dragging: false
    };
    this._previousOffset = 0;
  }

	componentWillMount() {
		this._panResponder = PanResponder.create({
			onStartShouldSetPanResponder: this._handleStartShouldSetPanResponder,
      onMoveShouldSetPanResponder: this._alwaysTrue,
			onPanResponderGrant: this._alwaysTrue,
			onPanResponderMove: this._handlePanResponderMove,
			onPanResponderRelease: this._handlePanResponderEnd,
			onPanResponderTerminate: this._handlePanResponderEnd
		});
	}

	_alwaysTrue = () => true

  componentDidMount() {
    this.getStockQuotes();
  }

  // show the cross line
  _handleStartShouldSetPanResponder = (e, gestureState) => {
    const { locationX, locationY } = e.nativeEvent;

    const current = Math.floor((deviceWidth - locationX) / (barWidth + 2 * barMargin));
    this.setCurrentItem(current)
    this.setState({dragging: true});
    return true;
  }

	_handlePanResponderMove = (e, gestureState) => {
		const { dx } = gestureState;
    const newOffset = Math.max(this._previousOffset + dx, 0);
    if (newOffset !== this.state.offset) {
      this.setState({offset: newOffset});
    }
	}

  _handlePanResponderEnd = (e, gestureState) => {
    this._previousOffset = Math.max(this._previousOffset + gestureState.dx, 0);
    this.setState({dragging: false});
  }

  getStockQuotes = () => {
    const d = new Date();
    const today = new Date(`${d.getFullYear()}/${d.getMonth() + 1}/${d.getDate()}`).getTime();
    const from = today + 86400 * 1000;
    const to = from - 86400 * 30 * 1000;
    // const url = `http://hulk.dev.cnyes.cool/api/v1/history?symbol=2330&from=1467302400&to=1471536000&resolution=D`;
    const url = `http://hulk.dev.cnyes.cool/api/v1/history?symbol=2330&from=${Math.floor(from/1000)}&to=${Math.floor(to/1000)}&resolution=D`;
    fetch(url)
      .then(rsp => rsp.json())
      .then(data => {
        this.setState({ data, current: 0 });
      });
  }

  loadMore = () => {
    const { nextTime } = this.state.data;
    const to = (nextTime * 1000- 86400 * 30 * 1000) / 1000;
    if (nextTime) {
      const url = `http://hulk.dev.cnyes.cool/api/v1/history?symbol=2330&from=${nextTime}&to=${Math.floor(to)}&resolution=D`;
      fetch(url)
        .then(rsp => rsp.json())
        .then(data => {
          const originData = this.state.data;
          const newData = {
            ...originData,
            ...data,
            c: [...originData.c, ...data.c],
            h: [...originData.h, ...data.h],
            l: [...originData.l, ...data.l],
            o: [...originData.o, ...data.o],
            t: [...originData.t, ...data.t],
            v: [...originData.v, ...data.v],
          }
          this.setState({data: newData});
        });
    }
  }

  getLinearScale(domain, range, isTime = false) {
    return (isTime ? d3Scale.scaleTime() : d3Scale.scaleLinear()).domain(domain).range(range);
  }

  getItemByIndex = (i) => {
    const { c, h, l, o, t, v, s } = this.state.data;
    const { current } = this.state;
    return {
      c: c[i],
      h: h[i],
      l: l[i],
      o: o[i],
      t: new Date(t[i] * 1000),
      v: v[i],
      s,
      color: o[i] <= c[i] ? 'rgb(210, 72, 62)' : 'rgb(28, 193, 135)'
    };
  }

  setCurrentItem = (i) => {
    if (i <= this.state.data.o.length - 1) {
      this.setState({ current: i });
    }
  }

  toggleGridline = () => {
    this.setState({ showGridline: !this.state.showGridline });
  }


  render() {
    const { current, offset } = this.state;
    const { c, h, l, o, t, s } = this.state.data;
    if (s === undefined) {
      return null;
    }
    const highestPrice = Math.max(...h);
    const lowestPrice = Math.min(...l);
    const priceScale = this.getLinearScale([lowestPrice, highestPrice], [0, defaultStockChartHeight].reverse());
    const svgWidth = Math.max(deviceWidth, c.length * (barWidth + 2 * barMargin));
{'fraction_non_alphanumeric': 0.16686886511525312, 'fraction_numerical': 0.0264696150876806, 'mean_word_length': 2.7517583781547374, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1858454', 'n_tokens_mistral': 3365, 'n_tokens_neox': 3099, 'n_words': 634}