diff --git a/components/chart/chart.js b/components/chart/chart.js index 49ddaa1a29c01a805b4fc45dba3116525f5423be..ffc311f348666c28eded1c639b2dfda92115e435 100644 --- a/components/chart/chart.js +++ b/components/chart/chart.js @@ -1,5 +1,6 @@ import React, { Component } from 'react' -import { View, FlatList } from 'react-native' +import { View } from 'react-native' +import { RecyclerListView, DataProvider, LayoutProvider } from "recyclerlistview" import range from 'date-range' import { LocalDate } from 'js-joda' import { yAxis, normalizeToScale } from './y-axis' @@ -10,12 +11,53 @@ import config from './config' const yAxisView = <View {...styles.yAxis}>{yAxis.labels}</View> +const dataProvider = new DataProvider((a,b) => { + return Object.keys(a).some(key => a[key] != b[key]) +}) + +const layoutProvider = new LayoutProvider( + () => DayColumn, + (_, item) => { + item.height = config.chartHeight + item.width = config.columnWidth + return item + } +) + +function getInfoForNeighborColumns(index, cols) { + const ret = {} + const right = index > 0 ? cols[index - 1] : undefined + const left = index < cols.length - 1 ? cols[index + 1] : undefined + if (right && right.y) { + ret.rightY = right.y + ret.rightTemperatureExclude = right.temperatureExclude + } + if (left && left.y) { + ret.leftY = left.y + ret.leftTemperatureExclude = left.temperatureExclude + } + return ret +} + +function rowRenderer (_, item, index) { + return ( + <DayColumn + item={item} + index={index} + navigate={this.props.navigation.navigate} + {...getInfoForNeighborColumns(index, this.columns)} + /> + ) +} + export default class CycleChart extends Component { constructor(props) { super(props) + this.columns = makeColumnInfo(config.xAxisRangeInDays) this.state = { - columns: makeColumnInfo(config.xAxisRangeInDays) + dataProvider: dataProvider.cloneWithRows(this.columns) } + this.rowRenderer = rowRenderer.bind(this) this.reCalculateChartInfo = (function(Chart) { return function() { @@ -35,34 +77,21 @@ export default class CycleChart extends Component { return ( <View style={{flexDirection: 'row'}}> { yAxisView } - <FlatList - horizontal={true} - inverted={true} - showsHorizontalScrollIndicator={false} - data={this.state.columns} - renderItem={({ item, index }) => { - const cols = this.state.columns - return ( - <DayColumn - item={item} - index={index} - rightNeighbor = { index > 0 ? cols[index - 1] : undefined } - leftNeighbor = {index < cols.length - 1 ? cols[index + 1] : undefined } - navigate={this.props.navigation.navigate} - /> - ) - }} - keyExtractor={item => item.dateString} + <RecyclerListView + layoutProvider={layoutProvider} + dataProvider={this.state.dataProvider} + rowRenderer={this.rowRenderer} + isHorizontal={true} initialNumToRender={15} > - </FlatList> + </RecyclerListView> </View> ) } } function makeColumnInfo(n) { - const xAxisDates = getPreviousDays(n).map(jsDate => { + const xAxisDates = getPreviousDays(n).reverse().map(jsDate => { return LocalDate.of( jsDate.getFullYear(), jsDate.getMonth() + 1, @@ -72,11 +101,16 @@ function makeColumnInfo(n) { return xAxisDates.map(dateString => { const cycleDay = getCycleDay(dateString) - const temp = cycleDay && cycleDay.temperature && cycleDay.temperature.value + const symptoms = ['temperature', 'mucus', 'bleeding'].reduce((acc, symptom) => { + acc[symptom] = cycleDay && cycleDay[symptom] && cycleDay[symptom].value + acc[`${symptom}Exclude`] = cycleDay && cycleDay[symptom] && cycleDay[symptom].exclude + return acc + }, {}) + return { dateString, - cycleDay, - y: temp ? normalizeToScale(temp) : null + y: symptoms.temperature ? normalizeToScale(symptoms.temperature) : null, + ...symptoms } }) } diff --git a/components/chart/day-column.js b/components/chart/day-column.js index 1b9b2f1818362ca3a0761b48d8db46603987fa41..2fda961038b14c782d8255d7b2a2801418590d5e 100644 --- a/components/chart/day-column.js +++ b/components/chart/day-column.js @@ -17,7 +17,15 @@ import { horizontalGrid } from './y-axis' const getCycleDayNumber = cycleModule().getCycleDayNumber export default class DayColumn extends Component { - makeDayColumn({ dateString, cycleDay, y }, index) { + makeDayColumn(data, index) { + const { + dateString, + y, + temperature, + temperatureExclude, + bleeding, + mucus + } = data const cycleDayNumber = getCycleDayNumber(dateString) const label = styles.column.label const dateLabel = dateString.split('-').slice(1).join('-') diff --git a/components/chart/nfp-lines.js b/components/chart/nfp-lines.js index e091597be3a4c64640774e98efcaf68cc917e3ad..a58abc06e20264db2b8f73cc9abb544d619326fb 100644 --- a/components/chart/nfp-lines.js +++ b/components/chart/nfp-lines.js @@ -43,14 +43,13 @@ export default function () { ) } - function isInTempMeasuringPhase(cycleDay, dateString) { + function isInTempMeasuringPhase(temperature, dateString) { return ( - cycleDay && cycleDay.temperature - || precededByAnotherTempValue(dateString) + temperature || precededByAnotherTempValue(dateString) ) } - return function(dateString, cycleDay) { + return function(dateString, temperature) { const ret = {} if (!cycleStatus && !noMoreCycles) updateCurrentCycle(dateString) if (noMoreCycles) return ret @@ -67,7 +66,7 @@ export default function () { if ( dateIsInPeriOrPostPhase(dateString) && - isInTempMeasuringPhase(cycleDay, dateString) + isInTempMeasuringPhase(temperature, dateString) ) { ret.drawLtlAt = normalizeToScale(tempShift.ltl) } diff --git a/package.json b/package.json index 217d5ffc6ac2d8f6bfb2d711e49275c35fbf89bd..d54f08b6852424e16154b86dc6393f65a75663d1 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "react-native-svg": "^6.3.1", "react-navigation": "^2.0.4", "realm": "^2.7.1", + "recyclerlistview": "^1.3.4", "uuid": "^3.2.1" }, "devDependencies": {