Initial prototype of multi-platform version

This commit is contained in:
2019-01-22 13:27:16 -06:00
parent 4ccda9d6f7
commit f108bc8dc1
63 changed files with 9770 additions and 0 deletions

View File

@@ -0,0 +1,7 @@
module.exports = {
"extends": "airbnb",
"rules": {
"react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }],
"import/prefer-default-export": false,
}
};

View File

@@ -0,0 +1,68 @@
/*
* Copyright (C) 2016-2019 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import React from 'react';
import {
AppRegistry,
StyleSheet,
View,
ToolbarAndroid,
StatusBar,
} from 'react-native';
import ListHabitScene from './src/components/ListHabits/index';
import { Colors } from './src/helpers/Colors';
const icAdd = require('./res/images/ic_add.png');
const icFilter = require('./res/images/ic_filter.png');
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: Colors.appBackground,
},
toolbar: {
backgroundColor: Colors.toolbarBackground,
height: 56,
alignSelf: 'stretch',
elevation: 8,
},
});
function RootComponent() {
return (
<View style={styles.container}>
<ToolbarAndroid
title="Habits"
style={styles.toolbar}
actions={[
{ title: 'Add', icon: icAdd, show: 'always' },
{ title: 'Filter', icon: icFilter, show: 'always' },
{ title: 'Settings', show: 'never' },
]}
/>
<StatusBar
backgroundColor={Colors.statusBarBackground}
barStyle={Colors.statusBarStyle}
/>
<ListHabitScene />
</View>
);
}
AppRegistry.registerComponent('LoopHabitTracker', () => RootComponent);

43
react-native/index.ios.js Normal file
View File

@@ -0,0 +1,43 @@
/*
* Copyright (C) 2016-2019 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import React from 'react';
import {
AppRegistry,
NavigatorIOS,
NativeModules,
NativeEventEmitter,
} from 'react-native';
import ListHabitsScene from './src/components/ListHabits/index';
function RootComponent() {
return (
<NavigatorIOS
translucent={false}
initialRoute={{
component: ListHabitsScene,
title: 'Habits',
rightButtonSystemIcon: 'add',
}}
style={{ flex: 1 }}
/>
);
}
AppRegistry.registerComponent('LoopHabitTracker', () => RootComponent);

6595
react-native/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

22
react-native/package.json Normal file
View File

@@ -0,0 +1,22 @@
{
"name": "LoopHabitTracker",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start"
},
"dependencies": {
"prop-types": "^15.6.2",
"react": "^16.6.3",
"react-native": "^0.57.8",
"react-native-svg": "^9.0.0",
"react-native-vector-icons": "^6.1.0"
},
"devDependencies": {
"eslint": "^5.12.1",
"eslint-config-airbnb": "^17.1.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-jsx-a11y": "^6.1.2",
"eslint-plugin-react": "^7.12.4"
}
}

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 B

View File

@@ -0,0 +1,78 @@
/*
* Copyright (C) 2016-2019 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import PropTypes from 'prop-types';
import React from 'react';
import {
StyleSheet,
Text,
View,
} from 'react-native';
import FontAwesome from '../../helpers/FontAwesome';
import { Colors } from '../../helpers/Colors';
const styles = StyleSheet.create({
checkmarkBox: {
width: 44,
height: 44,
justifyContent: 'center',
alignItems: 'center',
},
checkmark: {
fontFamily: 'FontAwesome',
fontSize: 14,
},
});
function randomInt(max) {
return Math.floor(Math.random() * Math.floor(max));
}
export default function CheckmarkButton(props) {
let text;
const { color } = props;
const value = Math.min(2, randomInt(5));
if (value === 2) {
text = (
<Text style={[styles.checkmark, { color }]}>
{FontAwesome.check}
</Text>
);
} else if (value === 1) {
text = (
<Text style={[styles.checkmark, { color: Colors.unchecked }]}>
{FontAwesome.check}
</Text>
);
} else {
text = (
<Text style={[styles.checkmark, { color: Colors.unchecked }]}>
{FontAwesome.times}
</Text>
);
}
return (
<View style={styles.checkmarkBox}>{text}</View>
);
}
CheckmarkButton.propTypes = {
color: PropTypes.string.isRequired,
};

View File

@@ -0,0 +1,107 @@
/*
* Copyright (C) 2016-2019 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import React from 'react';
import {
FlatList,
StyleSheet,
Text,
View,
} from 'react-native';
import { Colors } from '../../helpers/Colors';
import { Emitter, Backend } from '../../helpers/Backend';
import Ring from '../common/Ring';
import CheckmarkButton from './CheckmarkButton';
const styles = StyleSheet.create({
item: {
backgroundColor: Colors.itemBackground,
padding: 1,
marginTop: 0,
marginBottom: 1,
marginLeft: 0,
marginRight: 0,
elevation: 0,
flexDirection: 'row',
alignItems: 'stretch',
},
ringContainer: {
width: 35,
height: 45,
justifyContent: 'center',
alignItems: 'center',
},
labelContainer: {
width: 44,
flex: 1,
justifyContent: 'center',
},
});
export default class HabitList extends React.Component {
constructor(props) {
super(props);
this.state = { habits: [] };
}
componentDidMount() {
Emitter.addListener('onHabitList', (e) => {
this.setState({ habits: e });
});
Backend.requestHabitList();
}
render() {
const { habits } = this.state;
return (
<FlatList
style={styles.container}
data={habits}
renderItem={({ item }) => (
<View style={styles.item}>
<View style={styles.ringContainer}>
<Ring
color={Colors[item.color]}
size={14}
strokeWidth={20}
percentage={Math.random()}
/>
</View>
<View style={styles.labelContainer}>
<Text
numberOfLines={2}
style={{
fontSize: 14,
color: Colors[item.color],
}}
>
{item.name}
</Text>
</View>
<CheckmarkButton color={Colors[item.color]} />
<CheckmarkButton color={Colors[item.color]} />
<CheckmarkButton color={Colors[item.color]} />
<CheckmarkButton color={Colors[item.color]} />
<CheckmarkButton color={Colors[item.color]} />
</View>
)}
/>
);
}
}

View File

@@ -0,0 +1,106 @@
/*
* Copyright (C) 2016-2019 Álinson Santos Xavier <isoron@gmail.com>
* Copyright (C) 2019 Javier Artiles
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import React from 'react';
import { View, StyleSheet, Text } from 'react-native';
import { Colors } from '../../helpers/Colors';
const styles = StyleSheet.create({
container: {
height: 50,
paddingRight: 1,
backgroundColor: Colors.headerBackground,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'flex-end',
elevation: 4,
borderBottomColor: Colors.headerBorderColor,
borderBottomWidth: StyleSheet.hairlineWidth,
},
column: {
width: 44,
alignItems: 'center',
},
text: {
color: Colors.headerTextColor,
fontWeight: 'bold',
},
dayName: {
fontSize: 10,
},
dayNumber: {
fontSize: 12,
},
});
export default class HabitListHeader extends React.Component {
static renderColumn(dayName, dayNumber) {
return (
<View
key={dayNumber}
style={styles.column}
>
<Text style={[styles.text, styles.dayName]}>
{dayName.toUpperCase()}
</Text>
<Text style={[styles.text, styles.dayNumber]}>
{dayNumber}
</Text>
</View>
);
}
static renderColumns() {
return [
{
dayName: 'Sun',
dayNumber: '6',
},
{
dayName: 'Sat',
dayNumber: '5',
},
{
dayName: 'Fri',
dayNumber: '4',
},
{
dayName: 'Thu',
dayNumber: '3',
},
{
dayName: 'Wed',
dayNumber: '2',
},
].map((day) => {
const { dayName, dayNumber } = day;
return HabitListHeader.renderColumn(dayName, dayNumber);
});
}
render() {
return (
<View style={styles.container}>
{HabitListHeader.renderColumns()}
</View>
);
}
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright (C) 2016-2019 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import React from 'react';
import { StyleSheet, View } from 'react-native';
import { Colors } from '../../helpers/Colors';
import HabitListHeader from './HabitListHeader';
import HabitList from './HabitList';
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: Colors.appBackground,
},
});
export default function ListHabitsScene() {
return (
<View style={styles.container}>
<HabitListHeader />
<HabitList />
</View>
);
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright (C) 2016-2019 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import React from 'react';
import PropTypes from 'prop-types';
import Svg, { Circle } from 'react-native-svg';
export default function Ring(props) {
const {
size, strokeWidth, color, percentage,
} = props;
return (
<Svg
height={size}
width={size}
viewBox="0 0 100 100"
style={{ transform: [{ rotate: '-90deg' }] }}
>
<Circle
cx="50"
cy="50"
r={50 - strokeWidth / 2}
stroke="#eee"
strokeWidth={strokeWidth}
fill="transparent"
/>
<Circle
cx="50"
cy="50"
r={50 - strokeWidth / 2}
stroke={color}
strokeWidth={strokeWidth}
fill="transparent"
strokeDashoffset={`${2 * Math.PI * 45 * (1.0 - percentage)}`}
strokeDasharray={`${2 * Math.PI * 45}`}
/>
</Svg>
);
}
Ring.propTypes = {
size: PropTypes.number.isRequired,
strokeWidth: PropTypes.number.isRequired,
color: PropTypes.string.isRequired,
percentage: PropTypes.number.isRequired,
};

35
react-native/src/helpers/Backend.js vendored Normal file
View File

@@ -0,0 +1,35 @@
/*
* Copyright (C) 2016-2019 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import {
NativeEventEmitter,
DeviceEventEmitter,
NativeModules,
Platform,
} from 'react-native';
const { CoreModule } = NativeModules;
let emitter = DeviceEventEmitter;
if (Platform.OS === 'ios') {
emitter = new NativeEventEmitter(CoreModule);
}
export const Emitter = emitter;
export const Backend = NativeModules.CoreModule;

51
react-native/src/helpers/Colors.js vendored Normal file
View File

@@ -0,0 +1,51 @@
/*
* Copyright (C) 2016-2019 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
export const LIGHT_PALETTE = {
0: '#D32F2F',
1: '#512DA8',
2: '#F57C00',
3: '#FF8F00',
4: '#F9A825',
5: '#AFB42B',
6: '#7CB342',
7: '#388E3C',
8: '#00897B',
9: '#00ACC1',
10: '#039BE5',
11: '#1976D2',
12: '#303F9F',
13: '#5E35B1',
14: '#8E24AA',
15: '#D81B60',
16: '#5D4037',
17: '#000',
toolbar: '#f00',
appBackground: '#f0f0f0',
toolbarBackground: '#f4f4f4',
statusBarBackground: '#333',
statusBarStyle: 'light-content',
headerBackground: '#eee',
headerBorderColor: '#ccc',
headerTextColor: '#777',
itemBackground: '#fff',
unchecked: '#ddd',
};
export const Colors = LIGHT_PALETTE;

View File

@@ -0,0 +1,4 @@
module.exports = {
check: '\uf00c',
times: '\uf00d',
};