diff --git a/android/app/build.gradle b/android/app/build.gradle index 3fd611efc888e1645c94958fae33442ce4ff8958..fa56b475b947fe38815dcf124054886df40ae966 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -77,6 +77,7 @@ project.ext.react = [ ] apply from: "../../node_modules/react-native/react.gradle" +apply from: "../../node_modules/react-native-vector-icons/fonts.gradle" /** * Set this to true to create two separate APKs instead of one: @@ -137,11 +138,11 @@ android { } dependencies { + compile project(':react-native-vector-icons') compile project(':react-native-fs') compile project(':react-native-document-picker') compile project(':react-native-share') compile project(':realm') - compile project(':react-native-svg') compile fileTree(dir: "libs", include: ["*.jar"]) compile "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}" compile "com.facebook.react:react-native:+" // From node_modules diff --git a/android/app/src/main/assets/fonts/Entypo.ttf b/android/app/src/main/assets/fonts/Entypo.ttf new file mode 100644 index 0000000000000000000000000000000000000000..1c8f5e910bfb1a4a2871eeedc6eae01ca25e7ce1 Binary files /dev/null and b/android/app/src/main/assets/fonts/Entypo.ttf differ diff --git a/android/app/src/main/assets/fonts/EvilIcons.ttf b/android/app/src/main/assets/fonts/EvilIcons.ttf new file mode 100644 index 0000000000000000000000000000000000000000..6868f7bb64ba71b131690286ddc82aa0f542293e Binary files /dev/null and b/android/app/src/main/assets/fonts/EvilIcons.ttf differ diff --git a/android/app/src/main/assets/fonts/Feather.ttf b/android/app/src/main/assets/fonts/Feather.ttf new file mode 100755 index 0000000000000000000000000000000000000000..fc963dfe2292c4e241afb5950e063414d544c093 Binary files /dev/null and b/android/app/src/main/assets/fonts/Feather.ttf differ diff --git a/android/app/src/main/assets/fonts/FontAwesome.ttf b/android/app/src/main/assets/fonts/FontAwesome.ttf new file mode 100644 index 0000000000000000000000000000000000000000..35acda2fa1196aad98c2adf4378a7611dd713aa3 Binary files /dev/null and b/android/app/src/main/assets/fonts/FontAwesome.ttf differ diff --git a/android/app/src/main/assets/fonts/FontAwesome5_Brands.ttf b/android/app/src/main/assets/fonts/FontAwesome5_Brands.ttf new file mode 100644 index 0000000000000000000000000000000000000000..2ffa92d4fadb1ccccee6568190d19de33a649c87 Binary files /dev/null and b/android/app/src/main/assets/fonts/FontAwesome5_Brands.ttf differ diff --git a/android/app/src/main/assets/fonts/FontAwesome5_Regular.ttf b/android/app/src/main/assets/fonts/FontAwesome5_Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..43406e854c2da65c8b265caef07f3c211ee88528 Binary files /dev/null and b/android/app/src/main/assets/fonts/FontAwesome5_Regular.ttf differ diff --git a/android/app/src/main/assets/fonts/FontAwesome5_Solid.ttf b/android/app/src/main/assets/fonts/FontAwesome5_Solid.ttf new file mode 100644 index 0000000000000000000000000000000000000000..a1da1bbb5cfe3dada307313edf776231171c80e9 Binary files /dev/null and b/android/app/src/main/assets/fonts/FontAwesome5_Solid.ttf differ diff --git a/android/app/src/main/assets/fonts/Foundation.ttf b/android/app/src/main/assets/fonts/Foundation.ttf new file mode 100644 index 0000000000000000000000000000000000000000..6cce217ddc2efe3411dc9fa34e294e48e4cdf4f5 Binary files /dev/null and b/android/app/src/main/assets/fonts/Foundation.ttf differ diff --git a/android/app/src/main/assets/fonts/Ionicons.ttf b/android/app/src/main/assets/fonts/Ionicons.ttf new file mode 100644 index 0000000000000000000000000000000000000000..67bd84202ad5b2e307d3b6fac1731c2a5d963e0b Binary files /dev/null and b/android/app/src/main/assets/fonts/Ionicons.ttf differ diff --git a/android/app/src/main/assets/fonts/MaterialCommunityIcons.ttf b/android/app/src/main/assets/fonts/MaterialCommunityIcons.ttf new file mode 100644 index 0000000000000000000000000000000000000000..7845112675481a1feaec41905f7bf47d55cb8ff3 Binary files /dev/null and b/android/app/src/main/assets/fonts/MaterialCommunityIcons.ttf differ diff --git a/android/app/src/main/assets/fonts/MaterialIcons.ttf b/android/app/src/main/assets/fonts/MaterialIcons.ttf new file mode 100644 index 0000000000000000000000000000000000000000..7015564ad166a3e9d88c82f17829f0cc01ebe29a Binary files /dev/null and b/android/app/src/main/assets/fonts/MaterialIcons.ttf differ diff --git a/android/app/src/main/assets/fonts/Octicons.ttf b/android/app/src/main/assets/fonts/Octicons.ttf new file mode 100644 index 0000000000000000000000000000000000000000..0ffe00b92b2e2d21c1f33024760f685cbb7ffdb8 Binary files /dev/null and b/android/app/src/main/assets/fonts/Octicons.ttf differ diff --git a/android/app/src/main/assets/fonts/SimpleLineIcons.ttf b/android/app/src/main/assets/fonts/SimpleLineIcons.ttf new file mode 100644 index 0000000000000000000000000000000000000000..6ecb68683477ecc5aed38ec3fc8910d9bb66276c Binary files /dev/null and b/android/app/src/main/assets/fonts/SimpleLineIcons.ttf differ diff --git a/android/app/src/main/assets/fonts/Zocial.ttf b/android/app/src/main/assets/fonts/Zocial.ttf new file mode 100644 index 0000000000000000000000000000000000000000..e4ae46c6286b2d6c6676b0c3192fc92876778498 Binary files /dev/null and b/android/app/src/main/assets/fonts/Zocial.ttf differ diff --git a/android/app/src/main/java/com/drip/MainApplication.java b/android/app/src/main/java/com/drip/MainApplication.java index b0f0e16337e81cd8b46df8214a4f674b0fefb23f..4dc63a4e890ef14381f722b9a044c3114945f809 100644 --- a/android/app/src/main/java/com/drip/MainApplication.java +++ b/android/app/src/main/java/com/drip/MainApplication.java @@ -3,12 +3,12 @@ package com.drip; import android.app.Application; import com.facebook.react.ReactApplication; +import com.oblador.vectoricons.VectorIconsPackage; import com.rnfs.RNFSPackage; import com.reactnativedocumentpicker.ReactNativeDocumentPicker; import cl.json.RNSharePackage; import cl.json.ShareApplication; import io.realm.react.RealmReactPackage; -import com.horcrux.svg.SvgPackage; import com.facebook.react.ReactNativeHost; import com.facebook.react.ReactPackage; import com.facebook.react.shell.MainReactPackage; @@ -29,11 +29,11 @@ public class MainApplication extends Application implements ReactApplication, Sh protected List<ReactPackage> getPackages() { return Arrays.<ReactPackage>asList( new MainReactPackage(), + new VectorIconsPackage(), new RNFSPackage(), new ReactNativeDocumentPicker(), new RNSharePackage(), - new RealmReactPackage(), - new SvgPackage() + new RealmReactPackage() ); } diff --git a/android/settings.gradle b/android/settings.gradle index 7412acd91ce41de68ac1d1f2af75e7beb4bd0969..6a9c8c84200f3d0b63b9697454df468f2d5e1484 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -1,4 +1,6 @@ rootProject.name = 'drip' +include ':react-native-vector-icons' +project(':react-native-vector-icons').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-vector-icons/android') include ':react-native-fs' project(':react-native-fs').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fs/android') include ':react-native-document-picker' @@ -7,7 +9,5 @@ include ':react-native-share' project(':react-native-share').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-share/android') include ':realm' project(':realm').projectDir = new File(rootProject.projectDir, '../node_modules/realm/android') -include ':react-native-svg' -project(':react-native-svg').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-svg/android') include ':app' diff --git a/components/chart/chart.js b/components/chart/chart.js index 79bea872cefe9ea3785ea8471071858bfda4ea4d..ded01cfecaa565fc8d89374f17d76e7c28d8a080 100644 --- a/components/chart/chart.js +++ b/components/chart/chart.js @@ -1,35 +1,34 @@ import React, { Component } from 'react' -import { Text as ReactNativeText, View, FlatList, ScrollView } from 'react-native' +import { View, FlatList } from 'react-native' import range from 'date-range' -import Svg,{ - G, - Rect, - Text, - Circle, - Line, - Path -} from 'react-native-svg' import { LocalDate } from 'js-joda' -import { getCycleDay, getOrCreateCycleDay, cycleDaysSortedByDate } from '../../db' -import cycleModule from '../../lib/cycle' +import { yAxis, normalizeToScale, horizontalGrid } from './y-axis' +import setUpFertilityStatusFunc from './nfp-lines' +import DayColumn from './day-column' +import { getCycleDay, cycleDaysSortedByDate, getAmountOfCycleDays } from '../../db' import styles from './styles' -import config from './config' -import { getCycleStatusForDay } from '../../lib/sympto-adapter' -const getCycleDayNumber = cycleModule().getCycleDayNumber - -const yAxis = makeYAxis(config) +const yAxisView = <View {...styles.yAxis}>{yAxis.labels}</View> export default class CycleChart extends Component { constructor(props) { super(props) this.state = { - columns: makeColumnInfo(config.xAxisRangeInDays) + columns: makeColumnInfo(setUpFertilityStatusFunc()), + } + this.renderColumn = ({item, index}) => { + return ( + <DayColumn + {...item} + index={index} + navigate={this.props.navigation.navigate} + /> + ) } this.reCalculateChartInfo = (function(Chart) { return function() { - Chart.setState({columns: makeColumnInfo(config.xAxisRangeInDays)}) + Chart.setState({columns: makeColumnInfo(setUpFertilityStatusFunc())}) } })(this) @@ -40,159 +39,37 @@ export default class CycleChart extends Component { cycleDaysSortedByDate.removeListener(this.reCalculateChartInfo) } - passDateToDayView(dateString) { - const cycleDay = getOrCreateCycleDay(dateString) - this.props.navigation.navigate('cycleDay', { cycleDay }) - } - - placeHorizontalGrid() { - return yAxis.tickPositions.map(tick => { - return ( - <Line - x1={0} - y1={tick} - x2={config.columnWidth} - y2={tick} - {...styles.horizontalGrid} - key={tick} - /> - ) - }) - } - - makeDayColumn({ dateString, cycleDay, y }, index) { - const cycleDayNumber = getCycleDayNumber(dateString) - const label = styles.column.label - const dateLabel = dateString.split('-').slice(1).join('-') - const getFhmAndLtlInfo = setUpFertilityStatusFunc() - const nfpLineInfo = getFhmAndLtlInfo(dateString, cycleDay) - - return ( - <G onPress={() => this.passDateToDayView(dateString)}> - <Rect {...styles.column.rect} /> - {nfpLineInfo.drawFhmLine ? - <Line - x1={0 + styles.nfpLine.strokeWidth / 2} - y1="20" - x2={0 + styles.nfpLine.strokeWidth / 2} - y2={config.chartHeight - 20} - {...styles.nfpLine} - /> : null} - - {this.placeHorizontalGrid()} - - <Text {...label.number} y={config.cycleDayNumberRowY}> - {cycleDayNumber} - </Text> - <Text {...label.date} y={config.dateRowY}> - {dateLabel} - </Text> - - {cycleDay && cycleDay.bleeding ? - <Path {...styles.bleedingIcon} - d="M15 3 - Q16.5 6.8 25 18 - A12.8 12.8 0 1 1 5 18 - Q13.5 6.8 15 3z" /> - : null} - - {nfpLineInfo.drawLtlAt ? - <Line - x1="0" - y1={nfpLineInfo.drawLtlAt} - x2={config.columnWidth} - y2={nfpLineInfo.drawLtlAt} - {...styles.nfpLine} - /> : null} - - {y ? - this.drawDotAndLines(y, cycleDay.temperature.exclude, index) - : null - } - {cycleDay && cycleDay.mucus ? - <Circle - {...styles.mucusIcon} - fill={styles.mucusIconShades[cycleDay.mucus.value]} - /> : null} - - {y ? - this.drawDotAndLines(y, cycleDay.temperature.exclude, index) - : null} - </G> - ) - } - - drawDotAndLines(currY, exclude, index) { - let lineToRight - let lineToLeft - const cols = this.state.columns - - function makeLine(otherColY, x, excludeLine) { - const middleY = ((otherColY - currY) / 2) + currY - const target = [x, middleY] - const lineStyle = excludeLine ? styles.curveExcluded : styles.curve - - return <Line - x1={config.columnMiddle} - y1={currY} - x2={target[0]} - y2={target[1]} - {...lineStyle} - /> - } - - const thereIsADotToTheRight = index > 0 && cols[index - 1].y - const thereIsADotToTheLeft = index < cols.length - 1 && cols[index + 1].y - - if (thereIsADotToTheRight) { - const otherDot = cols[index - 1] - const excludedLine = otherDot.cycleDay.temperature.exclude || exclude - lineToRight = makeLine(otherDot.y, config.columnWidth, excludedLine) - } - if (thereIsADotToTheLeft) { - const otherDot = cols[index + 1] - const excludedLine = otherDot.cycleDay.temperature.exclude || exclude - lineToLeft = makeLine(otherDot.y, 0, excludedLine) - } - - const dotStyle = exclude ? styles.curveDotsExcluded : styles.curveDots - return (<G> - {lineToRight} - {lineToLeft} - <Circle - cx={config.columnMiddle} - cy={currY} - {...dotStyle} - /> - </G>) - } - render() { return ( - <ScrollView contentContainerStyle={{flexDirection: 'row'}}> - <View {...styles.yAxis}>{yAxis.labels}</View> - <FlatList + <View style={{ flexDirection: 'row', marginTop: 50 }}> + {yAxisView} + {horizontalGrid} + {<FlatList horizontal={true} inverted={true} showsHorizontalScrollIndicator={false} data={this.state.columns} - renderItem={({ item, index }) => { - return ( - <Svg width={config.columnWidth} height={config.chartHeight}> - {this.makeDayColumn(item, index)} - </Svg> - ) - }} + renderItem={this.renderColumn} keyExtractor={item => item.dateString} + initialNumToRender={15} + maxToRenderPerBatch={5} > - </FlatList> - </ScrollView> + </FlatList>} + </View> ) } } -function makeColumnInfo(n) { - const xAxisDates = getPreviousDays(n).map(jsDate => { +function makeColumnInfo(getFhmAndLtlInfo) { + let amountOfCycleDays = getAmountOfCycleDays() + // if there's not much data yet, we want to show at least 30 days on the chart + if (amountOfCycleDays < 30) { + amountOfCycleDays = 30 + } else { + // we don't want the chart to end abruptly before the first data day + amountOfCycleDays += 5 + } + const xAxisDates = getTodayAndPreviousDays(amountOfCycleDays).map(jsDate => { return LocalDate.of( jsDate.getFullYear(), jsDate.getMonth() + 1, @@ -200,18 +77,29 @@ function makeColumnInfo(n) { ).toString() }) - return xAxisDates.map(dateString => { + const columns = 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, + ...getFhmAndLtlInfo(dateString, symptoms.temperature) } }) + + return columns.map((col, i) => { + const info = getInfoForNeighborColumns(i, columns) + return Object.assign(col, info) + }) } -function getPreviousDays(n) { +function getTodayAndPreviousDays(n) { const today = new Date() today.setHours(0) today.setMinutes(0) @@ -222,114 +110,22 @@ function getPreviousDays(n) { return range(earlierDate, today).reverse() } -function normalizeToScale(temp) { - const scale = config.temperatureScale - const valueRelativeToScale = (scale.high - temp) / (scale.high - scale.low) - const scaleHeight = config.chartHeight - return scaleHeight * valueRelativeToScale -} - -function makeYAxis() { - const scaleMin = config.temperatureScale.low - const scaleMax = config.temperatureScale.high - const numberOfTicks = (scaleMax - scaleMin) * 2 - const tickDistance = config.chartHeight / numberOfTicks - - const tickPositions = [] - const labels = [] - // for style reasons, we don't want the first and last tick - for (let i = 1; i < numberOfTicks - 1; i++) { - const y = tickDistance * i - const style = styles.yAxisLabel - // this eyeballing is sadly necessary because RN does not - // support percentage values for transforms, which we'd need - // to reliably place the label vertically centered to the grid - style.top = y - 8 - labels.push( - <ReactNativeText - style={{...style}} - key={i}> - {scaleMax - i * 0.5} - </ReactNativeText> - ) - tickPositions.push(y) - } - - return {labels, tickPositions} -} - -function setUpFertilityStatusFunc() { - let cycleStatus - let cycleStartDate - let noMoreCycles = false - - function updateCurrentCycle(dateString) { - cycleStatus = getCycleStatusForDay(dateString) - if(!cycleStatus) { - noMoreCycles = true - return - } - if (cycleStatus.phases.preOvulatory) { - cycleStartDate = cycleStatus.phases.preOvulatory.start.date - } else { - cycleStartDate = cycleStatus.phases.periOvulatory.start.date - } - } - - function dateIsInPeriOrPostPhase(dateString) { - return ( - dateString >= cycleStatus.phases.periOvulatory.start.date - ) - } - - function precededByAnotherTempValue(dateString) { - return ( - // we are only interested in days that have a preceding - // temp - Object.keys(cycleStatus.phases).some(phaseName => { - return cycleStatus.phases[phaseName].cycleDays.some(day => { - return day.temperature && day.date < dateString - }) - }) - // and also a following temp, so we don't draw the line - // longer than necessary - && - cycleStatus.phases.postOvulatory.cycleDays.some(day => { - return day.temperature && day.date > dateString - }) - ) +function getInfoForNeighborColumns(index, cols) { + const ret = { + rightY: null, + rightTemperatureExclude: null, + leftY: null, + leftTemperatureExclude: null } - - function isInTempMeasuringPhase(cycleDay, dateString) { - return ( - cycleDay && cycleDay.temperature - || precededByAnotherTempValue(dateString) - ) + 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 } - - return function(dateString, cycleDay) { - const ret = {} - if (!cycleStatus && !noMoreCycles) updateCurrentCycle(dateString) - if (noMoreCycles) return ret - - if (dateString < cycleStartDate) updateCurrentCycle(dateString) - if (noMoreCycles) return ret - - const tempShift = cycleStatus.temperatureShift - - if (tempShift) { - if (tempShift.firstHighMeasurementDay.date === dateString) { - ret.drawFhmLine = true - } - - if ( - dateIsInPeriOrPostPhase(dateString) && - isInTempMeasuringPhase(cycleDay, dateString) - ) { - ret.drawLtlAt = normalizeToScale(tempShift.ltl) - } - } - - return ret + if (left && left.y) { + ret.leftY = left.y + ret.leftTemperatureExclude = left.temperatureExclude } + return ret } \ No newline at end of file diff --git a/components/chart/config.js b/components/chart/config.js index d18c722ea9c97ccd58264bc7f647e7fa3afcff94..ec3509ef3d24b6cbb17d962a6703a40e357b6089 100644 --- a/components/chart/config.js +++ b/components/chart/config.js @@ -1,11 +1,11 @@ const config = { chartHeight: 350, - columnWidth: 30, + columnWidth: 25, temperatureScale: { - low: 33, - high: 40 - }, - xAxisRangeInDays: 40 + low: 35, + high: 38, + units: 0.1 + } } const margin = 3 diff --git a/components/chart/day-column.js b/components/chart/day-column.js new file mode 100644 index 0000000000000000000000000000000000000000..88eb44e54b1fea17e203387d714c9449fcdc8727 --- /dev/null +++ b/components/chart/day-column.js @@ -0,0 +1,136 @@ +import React, { Component } from 'react' +import { + Text, View, TouchableOpacity +} from 'react-native' +import Icon from 'react-native-vector-icons/Entypo' +import styles from './styles' +import config from './config' +import { getOrCreateCycleDay } from '../../db' +import cycleModule from '../../lib/cycle' +import DotAndLine from './dot-and-line' + +const getCycleDayNumber = cycleModule().getCycleDayNumber +const label = styles.column.label + +export default class DayColumn extends Component { + passDateToDayView(dateString) { + const cycleDay = getOrCreateCycleDay(dateString) + this.props.navigate('cycleDay', { cycleDay }) + } + + shouldComponentUpdate(newProps) { + return Object.keys(newProps).some(key => newProps[key] != this.props[key]) + } + + render() { + const { + dateString, + y, + temperatureExclude, + bleeding, + mucus, + drawFhmLine, + drawLtlAt, + rightY, + rightTemperatureExclude, + leftY, + leftTemperatureExclude + } = this.props + + const columnElements = [] + if (typeof bleeding === 'number') { + columnElements.push( + <Icon + name='drop' + position='absolute' + size={18} + color='#900' + style={{ marginTop: 10, marginLeft: 3 }} + key='bleeding' + /> + ) + } + + if (typeof mucus === 'number') { + const mucusIcon = ( + <View + position='absolute' + top = {40} + left = {config.columnMiddle - styles.mucusIcon.width / 2} + {...styles.mucusIcon} + backgroundColor={styles.mucusIconShades[mucus]} + key='mucus' + /> + ) + columnElements.push(mucusIcon) + } + + if(drawFhmLine) { + const fhmLine = (<View + position = 'absolute' + top={100} + width={styles.nfpLine.strokeWidth} + height={200} + {...styles.nfpLine} + key='fhm' + />) + columnElements.push(fhmLine) + } + + if(drawLtlAt) { + const ltlLine = (<View + position = 'absolute' + width={'100%'} + top={drawLtlAt} + {...styles.nfpLine} + key='ltl' + />) + columnElements.push(ltlLine) + } + + if (y) { + columnElements.push( + <DotAndLine + y={y} + exclude={temperatureExclude} + rightY={rightY} + rightTemperatureExclude={rightTemperatureExclude} + leftY={leftY} + leftTemperatureExclude={leftTemperatureExclude} + key='dotandline' + /> + ) + } + + const cycleDayNumber = getCycleDayNumber(dateString) + const shortDate = dateString.split('-').slice(1).join('-') + const cycleDayLabel = ( + <Text style={label.number} y={config.cycleDayNumberRowY}> + {cycleDayNumber} + </Text>) + const dateLabel = ( + <Text style = {label.date} y={config.dateRowY}> + {shortDate} + </Text> + ) + columnElements.push( + <View position='absolute' bottom={0} key='date'> + {cycleDayLabel} + {dateLabel} + </View> + ) + + return React.createElement( + TouchableOpacity, + { + style: styles.column.rect, + key: this.props.index.toString(), + onPress: () => { + this.passDateToDayView(dateString) + }, + activeOpacity: 1 + }, + columnElements + ) + } +} \ No newline at end of file diff --git a/components/chart/dot-and-line.js b/components/chart/dot-and-line.js new file mode 100644 index 0000000000000000000000000000000000000000..626cf02c9b401102368182442523c564f6dc84c6 --- /dev/null +++ b/components/chart/dot-and-line.js @@ -0,0 +1,71 @@ +import React, { Component } from 'react' +import { View } from 'react-native' +import styles from './styles' +import config from './config' + +export default class DotAndLine extends Component { + shouldComponentUpdate(newProps) { + return Object.keys(newProps).some(key => newProps[key] != this.props[key]) + } + + render() { + const y = this.props.y + const exclude = this.props.exclude + let lineToRight + let lineToLeft + + if (this.props.leftY) { + const middleY = ((this.props.leftY - y) / 2) + y + const excludedLine = this.props.leftTemperatureExclude || exclude + lineToLeft = makeLine(middleY, y, 'left', excludedLine) + } + if (this.props.rightY) { + const middleY = ((y - this.props.rightY) / 2) + this.props.rightY + const excludedLine = this.props.rightTemperatureExclude || exclude + lineToRight = makeLine(y, middleY, 'right', excludedLine) + } + + const dotStyle = exclude ? styles.curveDotsExcluded : styles.curveDots + const dot = ( + <View + position='absolute' + top={y - (dotStyle.height / 2)} + left={config.columnMiddle - (dotStyle.width / 2)} + style={dotStyle} + key='dot' + /> + ) + return [lineToLeft, lineToRight, dot] + } +} + +function makeLine(leftY, rightY, direction, excludeLine) { + const colWidth = config.columnWidth + const heightDiff = -leftY - -rightY + const angle = Math.atan2(heightDiff, colWidth / 2) + const lineStyle = excludeLine ? styles.curveExcluded : styles.curve + // hypotenuse, we add 3px for good measure, because otherwise the lines + // don't quite touch at the day border + const h = (colWidth / 2) / Math.cos(angle) + 10 + // the rotation by default rotates from the middle of the line, + // but we want the transform origin to be at its beginning + // react native doesn't have transformOrigin, so we do this manually + // if it's the right line, we put the pivot at 3/4 of the column + // if it's to the left, at 1/4 + const pivot = direction === 'right' ? colWidth / 4 : -(colWidth / 4) + const projectedX = -(h - colWidth) / 2 + pivot + + return (<View + width={h} + position='absolute' + top={((leftY + rightY) / 2) - lineStyle.borderWidth / 2} + left={projectedX} + style={{ + transform: [ + { rotateZ: `${angle}rad` } + ], + }} + {...lineStyle} + key ={direction} + />) +} \ No newline at end of file diff --git a/components/chart/drop.svg b/components/chart/drop.svg new file mode 100644 index 0000000000000000000000000000000000000000..809d23916599c03e5d97816ceb909d2eb6f0a09c --- /dev/null +++ b/components/chart/drop.svg @@ -0,0 +1,12 @@ +<svg version="1.1" + baseProfile="full" + width="300" height="200" + xmlns="http://www.w3.org/2000/svg"> + <path d=" + M15 3 + Q16.5 6.8 25 18 + A12.8 12.8 0 1 1 5 18 + Q13.5 6.8 15 3z + " /> +</svg> + diff --git a/components/chart/nfp-lines.js b/components/chart/nfp-lines.js new file mode 100644 index 0000000000000000000000000000000000000000..d9f4507f67ea6583762646588f7e4013f46ef192 --- /dev/null +++ b/components/chart/nfp-lines.js @@ -0,0 +1,80 @@ +import { getCycleStatusForDay } from '../../lib/sympto-adapter' +import { normalizeToScale } from './y-axis' + +export default function () { + const cycle = { + status: null + } + + function updateCurrentCycle(dateString) { + cycle.status = getCycleStatusForDay(dateString) + if(!cycle.status) { + cycle.noMoreCycles = true + return + } + if (cycle.status.phases.preOvulatory) { + cycle.startDate = cycle.status.phases.preOvulatory.start.date + } else { + cycle.startDate = cycle.status.phases.periOvulatory.start.date + } + } + + function dateIsInPeriOrPostPhase(dateString) { + return ( + dateString >= cycle.status.phases.periOvulatory.start.date + ) + } + + function precededByAnotherTempValue(dateString) { + return ( + // we are only interested in days that have a preceding + // temp + Object.keys(cycle.status.phases).some(phaseName => { + return cycle.status.phases[phaseName].cycleDays.some(day => { + return day.temperature && day.date < dateString + }) + }) + // and also a following temp, so we don't draw the line + // longer than necessary + && + cycle.status.phases.postOvulatory.cycleDays.some(day => { + return day.temperature && day.date > dateString + }) + ) + } + + function isInTempMeasuringPhase(temperature, dateString) { + return ( + temperature || precededByAnotherTempValue(dateString) + ) + } + + return function(dateString, temperature) { + const ret = { + drawLtlAt: null, + drawFhmLine: false + } + if (!cycle.status && !cycle.noMoreCycles) updateCurrentCycle(dateString) + if (cycle.noMoreCycles) return ret + + if (dateString < cycle.startDate) updateCurrentCycle(dateString) + if (cycle.noMoreCycles) return ret + + const tempShift = cycle.status.temperatureShift + + if (tempShift) { + if (tempShift.firstHighMeasurementDay.date === dateString) { + ret.drawFhmLine = true + } + + if ( + dateIsInPeriOrPostPhase(dateString) && + isInTempMeasuringPhase(temperature, dateString) + ) { + ret.drawLtlAt = normalizeToScale(tempShift.ltl) + } + } + + return ret + } +} \ No newline at end of file diff --git a/components/chart/styles.js b/components/chart/styles.js index 8c2ab2e40c719382a99ab14f7bf73cc2badd99ed..c018eb11b9ad76727979914072bb8365d7d20ea6 100644 --- a/components/chart/styles.js +++ b/components/chart/styles.js @@ -2,44 +2,46 @@ import config from './config' const styles = { curve: { - stroke: '#ffc425', - strokeWidth: 2 + borderStyle: 'solid', + borderColor: '#ffc425', + borderWidth: 2, }, curveExcluded: { - stroke: 'lightgrey', - strokeWidth: 2, - strokeDashArray: [4] + borderColor: 'lightgrey', + borderWidth: 2, + borderStyle: 'solid' }, curveDots: { - fill: '#00aedb', - r: 6 + backgroundColor: '#00aedb', + width: 12, + height: 12, + borderRadius: 50 }, curveDotsExcluded: { - fill: 'lightgrey', - r: 6 + backgroundColor: 'lightgrey', + width: 12, + height: 12, + borderRadius: 50 }, column: { label: { date: { - stroke: 'grey', - fontSize: 10, - x: 2, + color: 'grey', + fontSize: 9, fontWeight: '100' }, number: { - stroke: '#00b159', + color: '#00b159', fontSize: 13, - x: config.columnMiddle - 1 + textAlign: 'center' } }, rect: { - fill: '#f9f9f9', - strokeWidth: 1, - stroke: 'grey', - x: 0, - y: 0, width: config.columnWidth, - height: config.chartHeight + height: config.chartHeight, + borderStyle: 'solid', + borderColor: 'grey', + borderWidth: 0.5 } }, bleedingIcon: { @@ -49,9 +51,9 @@ const styles = { y: 3 }, mucusIcon: { - cx: config.columnWidth / 2, - cy: 50, - r: 10 + width: 12, + height: 12, + borderRadius: 50, }, mucusIconShades: [ '#cc99cc', @@ -63,21 +65,29 @@ const styles = { yAxis: { height: config.chartHeight, width: config.columnWidth, + borderRightWidth: 0.5, + borderColor: 'lightgrey', + borderStyle: 'solid' }, yAxisLabel: { position: 'absolute', - right: 3, + left: 3, color: 'grey', - fontSize: 12, - fontWeight: 'bold' + fontSize: 11, + textAlign: 'left' }, horizontalGrid: { - stroke: 'lightgrey', - strokeWidth: 1 + position:'absolute', + borderColor: 'lightgrey', + borderWidth: 0.5, + width: '100%', + borderStyle: 'solid', + left: config.columnWidth }, nfpLine: { - stroke: '#00b159', - strokeWidth: 3 + borderColor: '#00b159', + borderWidth: 2, + borderStyle: 'solid' } } diff --git a/components/chart/y-axis.js b/components/chart/y-axis.js new file mode 100644 index 0000000000000000000000000000000000000000..ccc9404bb13a808e0fcd439ce32a7ca6d2ee10ec --- /dev/null +++ b/components/chart/y-axis.js @@ -0,0 +1,53 @@ +import React from 'react' +import { Text, View } from 'react-native' +import config from './config' +import styles from './styles' + +function makeYAxis() { + const scale = config.temperatureScale + const scaleMin = scale.low + const scaleMax = scale.high + const numberOfTicks = (scaleMax - scaleMin) * (1 / scale.units) + const tickDistance = config.chartHeight / numberOfTicks + + const tickPositions = [] + const labels = [] + // for style reasons, we don't want the first and last tick + for (let i = 1; i < numberOfTicks - 1; i++) { + const y = tickDistance * i + const style = styles.yAxisLabel + // this eyeballing is sadly necessary because RN does not + // support percentage values for transforms, which we'd need + // to reliably place the label vertically centered to the grid + style.top = y - 8 + labels.push( + <Text + style={{...style}} + key={i}> + {scaleMax - i * scale.units} + </Text> + ) + tickPositions.push(y) + } + + return {labels, tickPositions} +} + +export const yAxis = makeYAxis() + +export const horizontalGrid = yAxis.tickPositions.map(tick => { + return ( + <View + top={tick} + {...styles.horizontalGrid} + key={tick} + /> + ) +}) + +export function normalizeToScale(temp) { + const scale = config.temperatureScale + const valueRelativeToScale = (scale.high - temp) / (scale.high - scale.low) + const scaleHeight = config.chartHeight + return scaleHeight * valueRelativeToScale +} \ No newline at end of file diff --git a/db/index.js b/db/index.js index 38b586c9c12ad61c9b02e83b9e27126284a77532..42fd320e8e30c324b841278c7786ea88b5610572 100644 --- a/db/index.js +++ b/db/index.js @@ -1,6 +1,5 @@ import Realm from 'realm' -import { LocalDate } from 'js-joda' - +import { LocalDate, ChronoUnit } from 'js-joda' import { cycleWithTempAndNoMucusShift, cycleWithFhm, @@ -211,6 +210,15 @@ function tryToCreateCycleDay(day, i) { } } +function getAmountOfCycleDays() { + const amountOfCycleDays = cycleDaysSortedByDate.length + if (!amountOfCycleDays) return 0 + const earliest = cycleDaysSortedByDate[amountOfCycleDays - 1] + const today = LocalDate.now() + const earliestAsLocalDate = LocalDate.parse(earliest.date) + return earliestAsLocalDate.until(today, ChronoUnit.DAYS) +} + function tryToImportWithDelete(cycleDays) { db.write(() => { db.delete(db.objects('CycleDay')) @@ -238,6 +246,7 @@ export { deleteAll, getPreviousTemperature, getCycleDay, + getAmountOfCycleDays, schema, tryToImportWithDelete, tryToImportWithoutDelete diff --git a/ios/drip.xcodeproj/project.pbxproj b/ios/drip.xcodeproj/project.pbxproj index 80a206a635fc603ab73264ca57737d1110299a29..25f1f7601b795048c76bb96a0d0b2d95dddf0838 100644 --- a/ios/drip.xcodeproj/project.pbxproj +++ b/ios/drip.xcodeproj/project.pbxproj @@ -37,12 +37,25 @@ 5E9157361DD0AC6A00FF2AA8 /* libRCTAnimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */; }; 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; }; ADBDB9381DFEBF1600ED6528 /* libRCTBlob.a in Frameworks */ = {isa = PBXBuildFile; fileRef = ADBDB9271DFEBF0700ED6528 /* libRCTBlob.a */; }; - EFD2F9E5E59248D9AD6EBABA /* libRNSVG.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F4A1722D79F04D5EB528E21A /* libRNSVG.a */; }; - 934282049FA3497D9062CEC1 /* libRNSVG-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5ADC07BB282A481EBD5FD2A2 /* libRNSVG-tvOS.a */; }; 089A8A31B3244EB381D3BA67 /* libRealmReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A5827160B914D2B99C47381 /* libRealmReact.a */; }; 62F2A4645AC84CDC9506FF27 /* libc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 9AEBF0735214455AAEDF56D5 /* libc++.tbd */; }; D91133DCE120440893E2FD2E /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = CD8C8B91E0A747B3883A0D56 /* libz.tbd */; }; 26DC04B498C64CE5AAA0C4F8 /* libRNShare.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A8B59389C2FC4F19BD30ABC3 /* libRNShare.a */; }; + AED64B7892744F21B3A156BB /* libRNVectorIcons.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F5039D0A572B4BBCB7995891 /* libRNVectorIcons.a */; }; + 283136C9CE964E07BD52BE20 /* Entypo.ttf in Resources */ = {isa = PBXBuildFile; fileRef = A2811C9225AC4EAC93FCD2DB /* Entypo.ttf */; }; + 87508EF4BE7548878981BE9E /* EvilIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = B41CDA1146DB4492B1796444 /* EvilIcons.ttf */; }; + 4E04B0A1FECA4915AD4A6CCF /* Feather.ttf in Resources */ = {isa = PBXBuildFile; fileRef = F59A471BDE4144A1A41D4B52 /* Feather.ttf */; }; + 20146F2E2E9E4EB289472E81 /* FontAwesome.ttf in Resources */ = {isa = PBXBuildFile; fileRef = EE8CBB8533DA48A9A78697C3 /* FontAwesome.ttf */; }; + AF2EAEC3772C41A49A4AF117 /* FontAwesome5_Brands.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 044ECCD7D9B8470782A453CA /* FontAwesome5_Brands.ttf */; }; + 3F0F9C6368674C66AEAC3807 /* FontAwesome5_Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = C783C08EEEB541D2A30FEE44 /* FontAwesome5_Regular.ttf */; }; + 7D48A7B9435741CCA9678C42 /* FontAwesome5_Solid.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 0BE71E2D5A634744A662DF44 /* FontAwesome5_Solid.ttf */; }; + 8E4308D3D8614B0BACABF058 /* Foundation.ttf in Resources */ = {isa = PBXBuildFile; fileRef = EA87C1DB160640E0907EE056 /* Foundation.ttf */; }; + DB93C03E56074FB78F7F5B7C /* Ionicons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 8F2C7294680449AEA698AF76 /* Ionicons.ttf */; }; + 96687426D3D64D0F8E15FE4B /* MaterialCommunityIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 5D8CEEF11CF346C7A641F4EC /* MaterialCommunityIcons.ttf */; }; + DF31809C83AD48569741458C /* MaterialIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = B39DD260535A4B0EB31A3E0A /* MaterialIcons.ttf */; }; + DB91E6CCC3EB4A549D947797 /* Octicons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 4902D5DCD46748BD8DC403FD /* Octicons.ttf */; }; + 3DF2498A20844F298CD84CC3 /* SimpleLineIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = E954835D62BD45F0A5FFC523 /* SimpleLineIcons.ttf */; }; + A1410AC4C98A49B2820D9E45 /* Zocial.ttf in Resources */ = {isa = PBXBuildFile; fileRef = B6F5078F7DEC470782757471 /* Zocial.ttf */; }; 29DF0CCC1AEA4C92BCA0BCCD /* libRNDocumentPicker.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D211D71BE5A8436A978770A9 /* libRNDocumentPicker.a */; }; 17AD822C42A44BADA96BD860 /* libRNFS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 84CCEBD3B2C44758853BC941 /* libRNFS.a */; }; /* End PBXBuildFile section */ @@ -350,15 +363,28 @@ 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = "<group>"; }; 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = "<group>"; }; ADBDB91F1DFEBF0600ED6528 /* RCTBlob.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTBlob.xcodeproj; path = "../node_modules/react-native/Libraries/Blob/RCTBlob.xcodeproj"; sourceTree = "<group>"; }; - 8316A5AD64274E6FBA6C9FFE /* RNSVG.xcodeproj */ = {isa = PBXFileReference; name = "RNSVG.xcodeproj"; path = "../node_modules/react-native-svg/ios/RNSVG.xcodeproj"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = wrapper.pb-project; explicitFileType = undefined; includeInIndex = 0; }; - F4A1722D79F04D5EB528E21A /* libRNSVG.a */ = {isa = PBXFileReference; name = "libRNSVG.a"; path = "libRNSVG.a"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = archive.ar; explicitFileType = undefined; includeInIndex = 0; }; - 5ADC07BB282A481EBD5FD2A2 /* libRNSVG-tvOS.a */ = {isa = PBXFileReference; name = "libRNSVG-tvOS.a"; path = "libRNSVG-tvOS.a"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = archive.ar; explicitFileType = undefined; includeInIndex = 0; }; 7F6C9FA9B66B453CA602B334 /* RealmReact.xcodeproj */ = {isa = PBXFileReference; name = "RealmReact.xcodeproj"; path = "../node_modules/realm/react-native/ios/RealmReact.xcodeproj"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = wrapper.pb-project; explicitFileType = undefined; includeInIndex = 0; }; 7A5827160B914D2B99C47381 /* libRealmReact.a */ = {isa = PBXFileReference; name = "libRealmReact.a"; path = "libRealmReact.a"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = archive.ar; explicitFileType = undefined; includeInIndex = 0; }; 9AEBF0735214455AAEDF56D5 /* libc++.tbd */ = {isa = PBXFileReference; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; fileEncoding = undefined; lastKnownFileType = sourcecode.text-based-dylib-definition; explicitFileType = undefined; includeInIndex = 0; }; CD8C8B91E0A747B3883A0D56 /* libz.tbd */ = {isa = PBXFileReference; name = "libz.tbd"; path = "usr/lib/libz.tbd"; sourceTree = SDKROOT; fileEncoding = undefined; lastKnownFileType = sourcecode.text-based-dylib-definition; explicitFileType = undefined; includeInIndex = 0; }; 4E6AB77B55F2491487B6124E /* RNShare.xcodeproj */ = {isa = PBXFileReference; name = "RNShare.xcodeproj"; path = "../node_modules/react-native-share/ios/RNShare.xcodeproj"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = wrapper.pb-project; explicitFileType = undefined; includeInIndex = 0; }; A8B59389C2FC4F19BD30ABC3 /* libRNShare.a */ = {isa = PBXFileReference; name = "libRNShare.a"; path = "libRNShare.a"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = archive.ar; explicitFileType = undefined; includeInIndex = 0; }; + D1E5ACC4B66345868F556374 /* RNVectorIcons.xcodeproj */ = {isa = PBXFileReference; name = "RNVectorIcons.xcodeproj"; path = "../node_modules/react-native-vector-icons/RNVectorIcons.xcodeproj"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = wrapper.pb-project; explicitFileType = undefined; includeInIndex = 0; }; + F5039D0A572B4BBCB7995891 /* libRNVectorIcons.a */ = {isa = PBXFileReference; name = "libRNVectorIcons.a"; path = "libRNVectorIcons.a"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = archive.ar; explicitFileType = undefined; includeInIndex = 0; }; + A2811C9225AC4EAC93FCD2DB /* Entypo.ttf */ = {isa = PBXFileReference; name = "Entypo.ttf"; path = "../node_modules/react-native-vector-icons/Fonts/Entypo.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; }; + B41CDA1146DB4492B1796444 /* EvilIcons.ttf */ = {isa = PBXFileReference; name = "EvilIcons.ttf"; path = "../node_modules/react-native-vector-icons/Fonts/EvilIcons.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; }; + F59A471BDE4144A1A41D4B52 /* Feather.ttf */ = {isa = PBXFileReference; name = "Feather.ttf"; path = "../node_modules/react-native-vector-icons/Fonts/Feather.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; }; + EE8CBB8533DA48A9A78697C3 /* FontAwesome.ttf */ = {isa = PBXFileReference; name = "FontAwesome.ttf"; path = "../node_modules/react-native-vector-icons/Fonts/FontAwesome.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; }; + 044ECCD7D9B8470782A453CA /* FontAwesome5_Brands.ttf */ = {isa = PBXFileReference; name = "FontAwesome5_Brands.ttf"; path = "../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Brands.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; }; + C783C08EEEB541D2A30FEE44 /* FontAwesome5_Regular.ttf */ = {isa = PBXFileReference; name = "FontAwesome5_Regular.ttf"; path = "../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Regular.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; }; + 0BE71E2D5A634744A662DF44 /* FontAwesome5_Solid.ttf */ = {isa = PBXFileReference; name = "FontAwesome5_Solid.ttf"; path = "../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Solid.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; }; + EA87C1DB160640E0907EE056 /* Foundation.ttf */ = {isa = PBXFileReference; name = "Foundation.ttf"; path = "../node_modules/react-native-vector-icons/Fonts/Foundation.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; }; + 8F2C7294680449AEA698AF76 /* Ionicons.ttf */ = {isa = PBXFileReference; name = "Ionicons.ttf"; path = "../node_modules/react-native-vector-icons/Fonts/Ionicons.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; }; + 5D8CEEF11CF346C7A641F4EC /* MaterialCommunityIcons.ttf */ = {isa = PBXFileReference; name = "MaterialCommunityIcons.ttf"; path = "../node_modules/react-native-vector-icons/Fonts/MaterialCommunityIcons.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; }; + B39DD260535A4B0EB31A3E0A /* MaterialIcons.ttf */ = {isa = PBXFileReference; name = "MaterialIcons.ttf"; path = "../node_modules/react-native-vector-icons/Fonts/MaterialIcons.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; }; + 4902D5DCD46748BD8DC403FD /* Octicons.ttf */ = {isa = PBXFileReference; name = "Octicons.ttf"; path = "../node_modules/react-native-vector-icons/Fonts/Octicons.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; }; + E954835D62BD45F0A5FFC523 /* SimpleLineIcons.ttf */ = {isa = PBXFileReference; name = "SimpleLineIcons.ttf"; path = "../node_modules/react-native-vector-icons/Fonts/SimpleLineIcons.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; }; + B6F5078F7DEC470782757471 /* Zocial.ttf */ = {isa = PBXFileReference; name = "Zocial.ttf"; path = "../node_modules/react-native-vector-icons/Fonts/Zocial.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; }; 1F05FE29622E4F21AF70C2B7 /* RNDocumentPicker.xcodeproj */ = {isa = PBXFileReference; name = "RNDocumentPicker.xcodeproj"; path = "../node_modules/react-native-document-picker/ios/RNDocumentPicker.xcodeproj"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = wrapper.pb-project; explicitFileType = undefined; includeInIndex = 0; }; D211D71BE5A8436A978770A9 /* libRNDocumentPicker.a */ = {isa = PBXFileReference; name = "libRNDocumentPicker.a"; path = "libRNDocumentPicker.a"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = archive.ar; explicitFileType = undefined; includeInIndex = 0; }; 49089E09BFCF4F3DB209B6E9 /* RNFS.xcodeproj */ = {isa = PBXFileReference; name = "RNFS.xcodeproj"; path = "../node_modules/react-native-fs/RNFS.xcodeproj"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = wrapper.pb-project; explicitFileType = undefined; includeInIndex = 0; }; @@ -391,11 +417,11 @@ 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */, 00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */, 139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */, - EFD2F9E5E59248D9AD6EBABA /* libRNSVG.a in Frameworks */, 089A8A31B3244EB381D3BA67 /* libRealmReact.a in Frameworks */, 62F2A4645AC84CDC9506FF27 /* libc++.tbd in Frameworks */, D91133DCE120440893E2FD2E /* libz.tbd in Frameworks */, 26DC04B498C64CE5AAA0C4F8 /* libRNShare.a in Frameworks */, + AED64B7892744F21B3A156BB /* libRNVectorIcons.a in Frameworks */, 29DF0CCC1AEA4C92BCA0BCCD /* libRNDocumentPicker.a in Frameworks */, 17AD822C42A44BADA96BD860 /* libRNFS.a in Frameworks */, ); @@ -587,9 +613,9 @@ 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */, 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */, 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */, - 8316A5AD64274E6FBA6C9FFE /* RNSVG.xcodeproj */, 7F6C9FA9B66B453CA602B334 /* RealmReact.xcodeproj */, 4E6AB77B55F2491487B6124E /* RNShare.xcodeproj */, + D1E5ACC4B66345868F556374 /* RNVectorIcons.xcodeproj */, 1F05FE29622E4F21AF70C2B7 /* RNDocumentPicker.xcodeproj */, 49089E09BFCF4F3DB209B6E9 /* RNFS.xcodeproj */, ); @@ -613,6 +639,7 @@ 00E356EF1AD99517003FC87E /* dripTests */, 83CBBA001A601CBA00E9B192 /* Products */, 2D16E6871FA4F8E400B85C8A /* Frameworks */, + 006C39A0B9774387BC5ACA43 /* Resources */, ); indentWidth = 2; sourceTree = "<group>"; @@ -639,6 +666,28 @@ name = Products; sourceTree = "<group>"; }; + 006C39A0B9774387BC5ACA43 /* Resources */ = { + isa = "PBXGroup"; + children = ( + A2811C9225AC4EAC93FCD2DB /* Entypo.ttf */, + B41CDA1146DB4492B1796444 /* EvilIcons.ttf */, + F59A471BDE4144A1A41D4B52 /* Feather.ttf */, + EE8CBB8533DA48A9A78697C3 /* FontAwesome.ttf */, + 044ECCD7D9B8470782A453CA /* FontAwesome5_Brands.ttf */, + C783C08EEEB541D2A30FEE44 /* FontAwesome5_Regular.ttf */, + 0BE71E2D5A634744A662DF44 /* FontAwesome5_Solid.ttf */, + EA87C1DB160640E0907EE056 /* Foundation.ttf */, + 8F2C7294680449AEA698AF76 /* Ionicons.ttf */, + 5D8CEEF11CF346C7A641F4EC /* MaterialCommunityIcons.ttf */, + B39DD260535A4B0EB31A3E0A /* MaterialIcons.ttf */, + 4902D5DCD46748BD8DC403FD /* Octicons.ttf */, + E954835D62BD45F0A5FFC523 /* SimpleLineIcons.ttf */, + B6F5078F7DEC470782757471 /* Zocial.ttf */, + ); + name = Resources; + sourceTree = "<group>"; + path = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -1085,6 +1134,20 @@ files = ( 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */, + 283136C9CE964E07BD52BE20 /* Entypo.ttf in Resources */, + 87508EF4BE7548878981BE9E /* EvilIcons.ttf in Resources */, + 4E04B0A1FECA4915AD4A6CCF /* Feather.ttf in Resources */, + 20146F2E2E9E4EB289472E81 /* FontAwesome.ttf in Resources */, + AF2EAEC3772C41A49A4AF117 /* FontAwesome5_Brands.ttf in Resources */, + 3F0F9C6368674C66AEAC3807 /* FontAwesome5_Regular.ttf in Resources */, + 7D48A7B9435741CCA9678C42 /* FontAwesome5_Solid.ttf in Resources */, + 8E4308D3D8614B0BACABF058 /* Foundation.ttf in Resources */, + DB93C03E56074FB78F7F5B7C /* Ionicons.ttf in Resources */, + 96687426D3D64D0F8E15FE4B /* MaterialCommunityIcons.ttf in Resources */, + DF31809C83AD48569741458C /* MaterialIcons.ttf in Resources */, + DB91E6CCC3EB4A549D947797 /* Octicons.ttf in Resources */, + 3DF2498A20844F298CD84CC3 /* SimpleLineIcons.ttf in Resources */, + A1410AC4C98A49B2820D9E45 /* Zocial.ttf in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1224,9 +1287,9 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/../node_modules/react-native-svg/ios/**", "$(SRCROOT)/../node_modules/realm/src/**", "$(SRCROOT)/../node_modules/react-native-share/ios", + "$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager", "$(SRCROOT)/../node_modules/react-native-document-picker/ios/RNDocumentPicker", "$(SRCROOT)/../node_modules/react-native-fs/**", ); @@ -1255,9 +1318,9 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/../node_modules/react-native-svg/ios/**", "$(SRCROOT)/../node_modules/realm/src/**", "$(SRCROOT)/../node_modules/react-native-share/ios", + "$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager", "$(SRCROOT)/../node_modules/react-native-document-picker/ios/RNDocumentPicker", "$(SRCROOT)/../node_modules/react-native-fs/**", ); @@ -1281,9 +1344,9 @@ VERSIONING_SYSTEM = "apple-generic"; HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/../node_modules/react-native-svg/ios/**", "$(SRCROOT)/../node_modules/realm/src/**", "$(SRCROOT)/../node_modules/react-native-share/ios", + "$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager", "$(SRCROOT)/../node_modules/react-native-document-picker/ios/RNDocumentPicker", "$(SRCROOT)/../node_modules/react-native-fs/**", ); @@ -1306,9 +1369,9 @@ VERSIONING_SYSTEM = "apple-generic"; HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/../node_modules/react-native-svg/ios/**", "$(SRCROOT)/../node_modules/realm/src/**", "$(SRCROOT)/../node_modules/react-native-share/ios", + "$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager", "$(SRCROOT)/../node_modules/react-native-document-picker/ios/RNDocumentPicker", "$(SRCROOT)/../node_modules/react-native-fs/**", ); @@ -1346,9 +1409,9 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/../node_modules/react-native-svg/ios/**", "$(SRCROOT)/../node_modules/realm/src/**", "$(SRCROOT)/../node_modules/react-native-share/ios", + "$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager", "$(SRCROOT)/../node_modules/react-native-document-picker/ios/RNDocumentPicker", "$(SRCROOT)/../node_modules/react-native-fs/**", ); @@ -1386,9 +1449,9 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/../node_modules/react-native-svg/ios/**", "$(SRCROOT)/../node_modules/realm/src/**", "$(SRCROOT)/../node_modules/react-native-share/ios", + "$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager", "$(SRCROOT)/../node_modules/react-native-document-picker/ios/RNDocumentPicker", "$(SRCROOT)/../node_modules/react-native-fs/**", ); @@ -1425,9 +1488,9 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/../node_modules/react-native-svg/ios/**", "$(SRCROOT)/../node_modules/realm/src/**", "$(SRCROOT)/../node_modules/react-native-share/ios", + "$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager", "$(SRCROOT)/../node_modules/react-native-document-picker/ios/RNDocumentPicker", "$(SRCROOT)/../node_modules/react-native-fs/**", ); @@ -1464,9 +1527,9 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/../node_modules/react-native-svg/ios/**", "$(SRCROOT)/../node_modules/realm/src/**", "$(SRCROOT)/../node_modules/react-native-share/ios", + "$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager", "$(SRCROOT)/../node_modules/react-native-document-picker/ios/RNDocumentPicker", "$(SRCROOT)/../node_modules/react-native-fs/**", ); diff --git a/ios/drip/Info.plist b/ios/drip/Info.plist index 615a3936441920bf36c089d79980b36bb4a2511a..804756fb0f77230421e4ff1fecc544ed6a90b143 100644 --- a/ios/drip/Info.plist +++ b/ios/drip/Info.plist @@ -39,9 +39,8 @@ <key>UIViewControllerBasedStatusBarAppearance</key> <false/> <key>NSLocationWhenInUseUsageDescription</key> - <string></string> + <string/> <key>NSAppTransportSecurity</key> - <!--See http://ste.vn/2015/06/10/configuring-app-transport-security-ios-9-osx-10-11/ --> <dict> <key>NSExceptionDomains</key> <dict> @@ -52,5 +51,22 @@ </dict> </dict> </dict> + <key>UIAppFonts</key> + <array> + <string>Entypo.ttf</string> + <string>EvilIcons.ttf</string> + <string>Feather.ttf</string> + <string>FontAwesome.ttf</string> + <string>FontAwesome5_Brands.ttf</string> + <string>FontAwesome5_Regular.ttf</string> + <string>FontAwesome5_Solid.ttf</string> + <string>Foundation.ttf</string> + <string>Ionicons.ttf</string> + <string>MaterialCommunityIcons.ttf</string> + <string>MaterialIcons.ttf</string> + <string>Octicons.ttf</string> + <string>SimpleLineIcons.ttf</string> + <string>Zocial.ttf</string> + </array> </dict> </plist> diff --git a/package-lock.json b/package-lock.json index 745dc7be4689d83ddf0d45e8ba83b3b34bb2b669..9823a713e6ae35c8dbfa4b2a799e41bcfce4de33 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2386,15 +2386,6 @@ "object-visit": "^1.0.0" } }, - "color": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color/-/color-2.0.1.tgz", - "integrity": "sha512-ubUCVVKfT7r2w2D3qtHakj8mbmKms+tThR8gI8zEYCbUBl8/voqFGt3kgBqGwXAopgXybnkuOq+qMYCRrp4cXw==", - "requires": { - "color-convert": "^1.9.1", - "color-string": "^1.5.2" - } - }, "color-convert": { "version": "1.9.2", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.2.tgz", @@ -2408,15 +2399,6 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.1.tgz", "integrity": "sha1-SxQVMEz1ACjqgWQ2Q72C6gWANok=" }, - "color-string": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz", - "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==", - "requires": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } - }, "color-support": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", @@ -6500,16 +6482,6 @@ "resolved": "https://registry.npmjs.org/react-native-simple-radio-button/-/react-native-simple-radio-button-2.7.2.tgz", "integrity": "sha512-BdlllHsC/gYJtxPJ2tshDWN8CzmlGg1G9uB+Lu4FRGvGkwhvMtJ/uNShMbvxu134xosH/feri6HQgLGlIT202Q==" }, - "react-native-svg": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-6.5.1.tgz", - "integrity": "sha512-Fnn89loVOeek0NrSQ9sM13eXCPn/BK16Xvx8BgzZpoTx6/SEaoxi3kPLVzAbHLiV7VHq1opSkNcvRd+2/wUOOw==", - "requires": { - "color": "^2.0.1", - "lodash": "^4.16.6", - "pegjs": "^0.10.0" - } - }, "react-native-tab-view": { "version": "0.0.77", "resolved": "https://registry.npmjs.org/react-native-tab-view/-/react-native-tab-view-0.0.77.tgz", @@ -6518,6 +6490,38 @@ "prop-types": "^15.6.0" } }, + "react-native-vector-icons": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/react-native-vector-icons/-/react-native-vector-icons-5.0.0.tgz", + "integrity": "sha512-3ZmLGhQFk5QeHuttx0tOpghXhpVMGwXzb3pVaW/M8Qj0qkcg7koVyZmoR9vABQuxFC6KbM3l6/WLYZPh2aGfuQ==", + "requires": { + "lodash": "^4.0.0", + "prop-types": "^15.5.10", + "yargs": "^8.0.2" + }, + "dependencies": { + "yargs": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", + "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=", + "requires": { + "camelcase": "^4.1.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "read-pkg-up": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^7.0.0" + } + } + } + }, "react-navigation": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/react-navigation/-/react-navigation-2.10.0.tgz", @@ -7493,21 +7497,6 @@ } } }, - "simple-swizzle": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", - "requires": { - "is-arrayish": "^0.3.1" - }, - "dependencies": { - "is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" - } - } - }, "slash": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", diff --git a/package.json b/package.json index f64413a00abcee18c209efaf51063dba76394487..4a07999ff691225c6f4e3a13a3519d973a56e896 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "react-native-modal-datetime-picker-nevo": "^4.11.0", "react-native-share": "^1.1.0", "react-native-simple-radio-button": "^2.7.1", - "react-native-svg": "^6.3.1", + "react-native-vector-icons": "^5.0.0", "react-navigation": "^2.0.4", "realm": "^2.7.1", "uuid": "^3.2.1"