mirror of
https://github.com/ecency/ecency-mobile.git
synced 2024-11-26 09:13:33 +03:00
initialize
This commit is contained in:
parent
3a4a68fa78
commit
c70112b7b6
8
.babelrc
Normal file
8
.babelrc
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"presets": ["babel-preset-expo"],
|
||||||
|
"env": {
|
||||||
|
"development": {
|
||||||
|
"plugins": ["transform-react-jsx-source"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
17
.gitignore
vendored
Normal file
17
.gitignore
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# See https://help.github.com/ignore-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# expo
|
||||||
|
.expo/
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.env.local
|
||||||
|
.env.development.local
|
||||||
|
.env.test.local
|
||||||
|
.env.production.local
|
||||||
|
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
1
.watchmanconfig
Normal file
1
.watchmanconfig
Normal file
@ -0,0 +1 @@
|
|||||||
|
{}
|
2
App.js
Normal file
2
App.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
import App from './src/screens/Drawer'
|
||||||
|
export default App;
|
9
App.test.js
Normal file
9
App.test.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import App from './App';
|
||||||
|
|
||||||
|
import renderer from 'react-test-renderer';
|
||||||
|
|
||||||
|
it('renders without crashing', () => {
|
||||||
|
const rendered = renderer.create(<App />).toJSON();
|
||||||
|
expect(rendered).toBeTruthy();
|
||||||
|
});
|
11390
package-lock.json
generated
Normal file
11390
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
37
package.json
Normal file
37
package.json
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
{
|
||||||
|
"name": "esteemreact",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"devDependencies": {
|
||||||
|
"jest-expo": "~27.0.0",
|
||||||
|
"react-native-scripts": "1.14.0",
|
||||||
|
"react-test-renderer": "16.3.1"
|
||||||
|
},
|
||||||
|
"main": "./node_modules/react-native-scripts/build/bin/crna-entry.js",
|
||||||
|
"scripts": {
|
||||||
|
"start": "react-native-scripts start",
|
||||||
|
"eject": "react-native-scripts eject",
|
||||||
|
"android": "react-native-scripts android",
|
||||||
|
"ios": "react-native-scripts ios",
|
||||||
|
"test": "jest"
|
||||||
|
},
|
||||||
|
"jest": {
|
||||||
|
"preset": "jest-expo"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"dsteem": "^0.9.0",
|
||||||
|
"expo": "^27.0.1",
|
||||||
|
"invariant": "^2.2.4",
|
||||||
|
"moment": "^2.22.2",
|
||||||
|
"native-base": "^2.7.1",
|
||||||
|
"react": "16.3.1",
|
||||||
|
"react-content-loader": "^3.1.2",
|
||||||
|
"react-native": "~0.55.2",
|
||||||
|
"react-native-iphone-x-helper": "^1.0.3",
|
||||||
|
"react-navigation": "^2.6.2",
|
||||||
|
"react-navigation-header-buttons": "^1.2.1",
|
||||||
|
"react-navigation-material-bottom-tabs": "^0.3.0",
|
||||||
|
"react-navigation-tabs": "^0.5.1",
|
||||||
|
"rn-placeholder": "^1.2.0"
|
||||||
|
}
|
||||||
|
}
|
BIN
src/assets/NavLogo.png
Executable file
BIN
src/assets/NavLogo.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 30 KiB |
BIN
src/assets/back.png
Executable file
BIN
src/assets/back.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 2.3 KiB |
BIN
src/assets/dog-back.png
Executable file
BIN
src/assets/dog-back.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 7.5 KiB |
26
src/components/PostCard.js
Normal file
26
src/components/PostCard.js
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
import { Container, Card, CardItem,
|
||||||
|
Left, Thumbnail, Image, Icon,
|
||||||
|
Body, Text } from 'native-base';
|
||||||
|
|
||||||
|
const PostCard = (props) => {
|
||||||
|
return (
|
||||||
|
<Container>
|
||||||
|
<Card>
|
||||||
|
<CardItem>
|
||||||
|
<Left>
|
||||||
|
<Thumbnail source={{ uri: props.post.avatar }} />
|
||||||
|
<Body>
|
||||||
|
<Text>{ this.props.post.title }</Text>
|
||||||
|
<Text note>April 15, 2016</Text>
|
||||||
|
</Body>
|
||||||
|
</Left>
|
||||||
|
</CardItem>
|
||||||
|
</Card>
|
||||||
|
</Container>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PostCard;
|
||||||
|
|
||||||
|
|
173
src/components/Tabs.js
Executable file
173
src/components/Tabs.js
Executable file
@ -0,0 +1,173 @@
|
|||||||
|
import {
|
||||||
|
NavigationScreenProp,
|
||||||
|
NavigationEventSubscription,
|
||||||
|
} from 'react-navigation';
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import { StyleSheet } from 'react-native';
|
||||||
|
import { createBottomTabNavigator } from 'react-navigation';
|
||||||
|
|
||||||
|
import Ionicons from 'react-native-vector-icons/Ionicons';
|
||||||
|
import Entypo from 'react-native-vector-icons/Entypo';
|
||||||
|
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||||
|
|
||||||
|
import EditorPage from '../screens/editor/editor';
|
||||||
|
import FeedPage from '../screens/home/feed';
|
||||||
|
import ProfilePage from '../screens/profile/profile';
|
||||||
|
import WalletPage from '../screens/wallet/wallet';
|
||||||
|
import NotificationPage from '../screens/notifications/notification';
|
||||||
|
|
||||||
|
const HomeScreen = ({ navigation }) => (
|
||||||
|
<FeedPage navigation={navigation}></FeedPage>
|
||||||
|
);
|
||||||
|
|
||||||
|
HomeScreen.navigationOptions = {
|
||||||
|
tabBarTestIDProps: {
|
||||||
|
testID: 'TEST_ID_HOME',
|
||||||
|
accessibilityLabel: 'TEST_ID_HOME_ACLBL',
|
||||||
|
},
|
||||||
|
tabBarLabel: 'Home',
|
||||||
|
tabBarIcon: ({ tintColor, focused }) => (
|
||||||
|
<MaterialCommunityIcons
|
||||||
|
name={focused ? 'home' : 'home'}
|
||||||
|
size={26}
|
||||||
|
style={{ color: tintColor }}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
const ProfileScreen = ({ navigation }) => (
|
||||||
|
<ProfilePage navigation={navigation}></ProfilePage>
|
||||||
|
);
|
||||||
|
|
||||||
|
ProfileScreen.navigationOptions = {
|
||||||
|
tabBarLabel: 'Profile',
|
||||||
|
tabBarIcon: ({ tintColor, focused }) => (
|
||||||
|
<Ionicons
|
||||||
|
name={focused ? 'md-contact' : 'md-contact'}
|
||||||
|
size={26}
|
||||||
|
style={{ color: tintColor }}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
const EditorScreen = ({ navigation }) => (
|
||||||
|
<EditorPage navigation={navigation}></EditorPage>
|
||||||
|
);
|
||||||
|
|
||||||
|
EditorScreen.navigationOptions = {
|
||||||
|
tabBarLabel: 'Editor',
|
||||||
|
tabBarIcon: ({ tintColor, focused }) => (
|
||||||
|
<Entypo
|
||||||
|
name={focused ? 'pencil' : 'pencil'}
|
||||||
|
size={26}
|
||||||
|
style={styles.post}
|
||||||
|
style={{ color: tintColor }}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
const WalletScreen = ({ navigation }) => (
|
||||||
|
<WalletPage navigation={navigation}></WalletPage>
|
||||||
|
);
|
||||||
|
|
||||||
|
WalletScreen.navigationOptions = {
|
||||||
|
tabBarLabel: 'Settings',
|
||||||
|
tabBarIcon: ({ tintColor, focused }) => (
|
||||||
|
<Entypo
|
||||||
|
name={focused ? 'wallet' : 'wallet'}
|
||||||
|
size={26}
|
||||||
|
style={{ color: tintColor }}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
const NotificationScreen = ({ navigation }) => (
|
||||||
|
<NotificationPage navigation={navigation}></NotificationPage>
|
||||||
|
);
|
||||||
|
|
||||||
|
NotificationScreen.navigationOptions = {
|
||||||
|
tabBarLabel: 'Notifications',
|
||||||
|
tabBarIcon: ({ tintColor, focused }) => (
|
||||||
|
<Ionicons
|
||||||
|
name={focused ? 'ios-notifications' : 'ios-notifications'}
|
||||||
|
size={26}
|
||||||
|
style={{ color: tintColor }}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const SimpleTabs = createBottomTabNavigator(
|
||||||
|
{
|
||||||
|
Home: {
|
||||||
|
screen: HomeScreen,
|
||||||
|
path: '',
|
||||||
|
},
|
||||||
|
Profile: {
|
||||||
|
screen: ProfileScreen,
|
||||||
|
path: 'profile',
|
||||||
|
},
|
||||||
|
Editor: {
|
||||||
|
screen: EditorScreen,
|
||||||
|
path: 'editor',
|
||||||
|
},
|
||||||
|
Wallet: {
|
||||||
|
screen: WalletScreen,
|
||||||
|
path: 'wallet',
|
||||||
|
},
|
||||||
|
Notifications: {
|
||||||
|
screen: NotificationScreen,
|
||||||
|
path: 'settings',
|
||||||
|
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tabBarOptions: {
|
||||||
|
activeTintColor: '#373c3f',
|
||||||
|
inactiveTintColor: '#AFB1B3',
|
||||||
|
style: {
|
||||||
|
backgroundColor: 'white',
|
||||||
|
},
|
||||||
|
showLabel: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
class Tabs extends React.Component {
|
||||||
|
static router = SimpleTabs.router;
|
||||||
|
_s0;
|
||||||
|
_s1;
|
||||||
|
_s2;
|
||||||
|
_s3;
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this._s0 = this.props.navigation.addListener('willFocus', this._onAction);
|
||||||
|
this._s1 = this.props.navigation.addListener('didFocus', this._onAction);
|
||||||
|
this._s2 = this.props.navigation.addListener('willBlur', this._onAction);
|
||||||
|
this._s3 = this.props.navigation.addListener('didBlur', this._onAction);
|
||||||
|
}
|
||||||
|
componentWillUnmount() {
|
||||||
|
this._s0.remove();
|
||||||
|
this._s1.remove();
|
||||||
|
this._s2.remove();
|
||||||
|
this._s3.remove();
|
||||||
|
}
|
||||||
|
_onAction = a => {
|
||||||
|
console.log('TABS EVENT', a.type, a);
|
||||||
|
};
|
||||||
|
render() {
|
||||||
|
return <SimpleTabs navigation={this.props.navigation} />;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
post: {
|
||||||
|
borderWidth: 22,
|
||||||
|
borderColor: 'blue',
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
export default Tabs;
|
187
src/examples/SimpleStack.js
Executable file
187
src/examples/SimpleStack.js
Executable file
@ -0,0 +1,187 @@
|
|||||||
|
import {
|
||||||
|
NavigationScreenProp,
|
||||||
|
NavigationState,
|
||||||
|
NavigationStateRoute,
|
||||||
|
NavigationEventSubscription,
|
||||||
|
} from 'react-navigation';
|
||||||
|
|
||||||
|
import * as React from 'react';
|
||||||
|
import { ScrollView, Text, StatusBar } from 'react-native';
|
||||||
|
|
||||||
|
import FeedPage from '../screens/home/feed';
|
||||||
|
|
||||||
|
import {
|
||||||
|
createStackNavigator,
|
||||||
|
SafeAreaView,
|
||||||
|
withNavigation,
|
||||||
|
NavigationActions,
|
||||||
|
StackActions,
|
||||||
|
} from 'react-navigation';
|
||||||
|
import invariant from 'invariant';
|
||||||
|
|
||||||
|
import SampleText from './SampleText';
|
||||||
|
|
||||||
|
class BackButton extends React.Component {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Text>Test</Text>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
_navigateBack = () => {
|
||||||
|
this.props.navigation.goBack(null);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const BackButtonWithNavigation = withNavigation(BackButton);
|
||||||
|
|
||||||
|
class MyNavScreen extends React.Component {
|
||||||
|
render() {
|
||||||
|
const { navigation, banner } = this.props;
|
||||||
|
const { push, replace, popToTop, pop, dismiss } = navigation;
|
||||||
|
invariant(
|
||||||
|
push && replace && popToTop && pop && dismiss,
|
||||||
|
'missing action creators for StackNavigator'
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<SafeAreaView>
|
||||||
|
<SampleText>{banner}</SampleText>
|
||||||
|
<Button
|
||||||
|
onPress={() => push('Profile', { name: 'Jane' })}
|
||||||
|
title="Push a profile screen"
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
onPress={() =>
|
||||||
|
navigation.dispatch(
|
||||||
|
StackActions.reset({
|
||||||
|
index: 0,
|
||||||
|
actions: [
|
||||||
|
NavigationActions.navigate({
|
||||||
|
routeName: 'Photos',
|
||||||
|
params: { name: 'Jane' },
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
title="Reset photos"
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
onPress={() => navigation.navigate('Photos', { name: 'Jane' })}
|
||||||
|
title="Navigate to a photos screen"
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
onPress={() => replace('Profile', { name: 'Lucy' })}
|
||||||
|
title="Replace with profile"
|
||||||
|
/>
|
||||||
|
<Button onPress={() => popToTop()} title="Pop to top" />
|
||||||
|
<Button onPress={() => pop()} title="Pop" />
|
||||||
|
<Button
|
||||||
|
onPress={() => {
|
||||||
|
if (navigation.goBack()) {
|
||||||
|
console.log('goBack handled');
|
||||||
|
} else {
|
||||||
|
console.log('goBack unhandled');
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
title="Go back"
|
||||||
|
/>
|
||||||
|
<Button onPress={() => dismiss()} title="Dismiss" />
|
||||||
|
<StatusBar barStyle="default" />
|
||||||
|
</SafeAreaView>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyPhotosScreen extends React.Component {
|
||||||
|
static navigationOptions = {
|
||||||
|
title: 'Photos',
|
||||||
|
headerLeft: <BackButtonWithNavigation />,
|
||||||
|
};
|
||||||
|
_s0;
|
||||||
|
_s1;
|
||||||
|
_s2;
|
||||||
|
_s3;
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this._s0 = this.props.navigation.addListener('willFocus', this._onWF);
|
||||||
|
this._s1 = this.props.navigation.addListener('didFocus', this._onDF);
|
||||||
|
this._s2 = this.props.navigation.addListener('willBlur', this._onWB);
|
||||||
|
this._s3 = this.props.navigation.addListener('didBlur', this._onDB);
|
||||||
|
}
|
||||||
|
componentWillUnmount() {
|
||||||
|
this._s0.remove();
|
||||||
|
this._s1.remove();
|
||||||
|
this._s2.remove();
|
||||||
|
this._s3.remove();
|
||||||
|
}
|
||||||
|
_onWF = a => {
|
||||||
|
console.log('_willFocus PhotosScreen', a);
|
||||||
|
};
|
||||||
|
_onDF = a => {
|
||||||
|
console.log('_didFocus PhotosScreen', a);
|
||||||
|
};
|
||||||
|
_onWB = a => {
|
||||||
|
console.log('_willBlur PhotosScreen', a);
|
||||||
|
};
|
||||||
|
_onDB = a => {
|
||||||
|
console.log('_didBlur PhotosScreen', a);
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { navigation } = this.props;
|
||||||
|
return (
|
||||||
|
<MyNavScreen
|
||||||
|
banner={`${navigation.getParam('name')}'s Photos`}
|
||||||
|
navigation={navigation}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const MyProfileScreen = ({ navigation }) => (
|
||||||
|
<MyNavScreen
|
||||||
|
banner={`${
|
||||||
|
navigation.getParam('mode') === 'edit' ? 'Now Editing ' : ''
|
||||||
|
}${navigation.getParam('name')}'s Profile`}
|
||||||
|
navigation={navigation}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
MyProfileScreen.navigationOptions = props => {
|
||||||
|
const { navigation } = props;
|
||||||
|
const { state, setParams } = navigation;
|
||||||
|
const { params } = state;
|
||||||
|
return {
|
||||||
|
headerBackImage: params.headerBackImage,
|
||||||
|
headerTitle: `${params.name}'s Profile!`,
|
||||||
|
// Render a button on the right side of the header.
|
||||||
|
// When pressed switches the screen to edit mode.
|
||||||
|
headerRight: (
|
||||||
|
<HeaderButtons>
|
||||||
|
<HeaderButtons.Item
|
||||||
|
title={params.mode === 'edit' ? 'Done' : 'Edit'}
|
||||||
|
onPress={() =>
|
||||||
|
setParams({ mode: params.mode === 'edit' ? '' : 'edit' })
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</HeaderButtons>
|
||||||
|
),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const SimpleStack = createStackNavigator({
|
||||||
|
Home: {
|
||||||
|
screen: FeedPage,
|
||||||
|
},
|
||||||
|
Profile: {
|
||||||
|
path: 'people/:name',
|
||||||
|
screen: MyProfileScreen,
|
||||||
|
},
|
||||||
|
Photos: {
|
||||||
|
path: 'photos/:name',
|
||||||
|
screen: MyPhotosScreen,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default SimpleStack;
|
123
src/examples/StacksOverTabs.js
Executable file
123
src/examples/StacksOverTabs.js
Executable file
@ -0,0 +1,123 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { ScrollView, StatusBar, Text } from 'react-native';
|
||||||
|
import {
|
||||||
|
SafeAreaView,
|
||||||
|
createStackNavigator,
|
||||||
|
createBottomTabNavigator,
|
||||||
|
} from 'react-navigation';
|
||||||
|
|
||||||
|
import Ionicons from 'react-native-vector-icons/Ionicons';
|
||||||
|
|
||||||
|
const MyNavScreen = ({ navigation, banner }) => (
|
||||||
|
<ScrollView>
|
||||||
|
<SafeAreaView forceInset={{ horizontal: 'always' }}>
|
||||||
|
<Text>{banner}</Text>
|
||||||
|
<Button
|
||||||
|
onPress={() => navigation.navigate('Profile', { name: 'Jordan' })}
|
||||||
|
title="Open profile screen"
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
onPress={() => navigation.navigate('NotifSettings')}
|
||||||
|
title="Open notifications screen"
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
onPress={() => navigation.navigate('SettingsTab')}
|
||||||
|
title="Go to settings tab"
|
||||||
|
/>
|
||||||
|
<Button onPress={() => navigation.goBack(null)} title="Go back" />
|
||||||
|
</SafeAreaView>
|
||||||
|
<StatusBar barStyle="default" />
|
||||||
|
</ScrollView>
|
||||||
|
);
|
||||||
|
|
||||||
|
const MyHomeScreen = ({ navigation }) => (
|
||||||
|
<MyNavScreen banner="Home Screen" navigation={navigation} />
|
||||||
|
);
|
||||||
|
|
||||||
|
const MyProfileScreen = ({ navigation }) => (
|
||||||
|
<MyNavScreen
|
||||||
|
banner={`${navigation.state.params.name}s Profile`}
|
||||||
|
navigation={navigation}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
const MyNotificationsSettingsScreen = ({ navigation }) => (
|
||||||
|
<MyNavScreen banner="Notifications Screen" navigation={navigation} />
|
||||||
|
);
|
||||||
|
|
||||||
|
const MySettingsScreen = ({ navigation }) => (
|
||||||
|
<MyNavScreen banner="Settings Screen" navigation={navigation} />
|
||||||
|
);
|
||||||
|
|
||||||
|
const TabNav = createBottomTabNavigator(
|
||||||
|
{
|
||||||
|
MainTab: {
|
||||||
|
screen: MyHomeScreen,
|
||||||
|
path: '/',
|
||||||
|
navigationOptions: {
|
||||||
|
title: 'Welcome',
|
||||||
|
tabBarLabel: 'Home',
|
||||||
|
tabBarIcon: ({ tintColor, focused }) => (
|
||||||
|
<Ionicons
|
||||||
|
name={focused ? 'ios-home' : 'ios-home-outline'}
|
||||||
|
size={26}
|
||||||
|
style={{ color: tintColor }}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
SettingsTab: {
|
||||||
|
screen: MySettingsScreen,
|
||||||
|
path: '/settings',
|
||||||
|
navigationOptions: {
|
||||||
|
title: 'Settings',
|
||||||
|
tabBarIcon: ({ tintColor, focused }) => (
|
||||||
|
<Ionicons
|
||||||
|
name={focused ? 'ios-settings' : 'ios-settings-outline'}
|
||||||
|
size={26}
|
||||||
|
style={{ color: tintColor }}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tabBarPosition: 'bottom',
|
||||||
|
animationEnabled: false,
|
||||||
|
swipeEnabled: false,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
TabNav.navigationOptions = ({ navigation }) => {
|
||||||
|
let { routeName } = navigation.state.routes[navigation.state.index];
|
||||||
|
let title;
|
||||||
|
if (routeName === 'SettingsTab') {
|
||||||
|
title = 'Settings';
|
||||||
|
} else if (routeName === 'MainTab') {
|
||||||
|
title = 'Home';
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
title,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const StacksOverTabs = createStackNavigator({
|
||||||
|
Root: {
|
||||||
|
screen: TabNav,
|
||||||
|
},
|
||||||
|
NotifSettings: {
|
||||||
|
screen: MyNotificationsSettingsScreen,
|
||||||
|
navigationOptions: {
|
||||||
|
title: 'Notifications',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Profile: {
|
||||||
|
screen: MyProfileScreen,
|
||||||
|
path: '/people/:name',
|
||||||
|
navigationOptions: ({ navigation }) => ({
|
||||||
|
title: `${navigation.state.params.name}'s Profile!`,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default StacksOverTabs;
|
102
src/providers/steem/Dsteem.js
Normal file
102
src/providers/steem/Dsteem.js
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
import { Client } from 'dsteem';
|
||||||
|
const client = new Client('https://api.steemit.com');
|
||||||
|
|
||||||
|
import moment from 'moment';
|
||||||
|
|
||||||
|
const noImage = '../../assets/imgs/noimage.png'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @method getAccount get account data
|
||||||
|
* @param user username
|
||||||
|
*/
|
||||||
|
export const getAccount = (user) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let account = client.database.getAccounts([user]);
|
||||||
|
resolve(account);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @method getPosts get posts method
|
||||||
|
* @param by get discussions by trending, created, active etc.
|
||||||
|
* @param query tag, limit, start_author?, start_permalink?
|
||||||
|
*/
|
||||||
|
export const getPosts = async (by, query) => {
|
||||||
|
let posts = await client.database.getDiscussions(by, query);
|
||||||
|
posts = await parsePosts(posts);
|
||||||
|
return posts;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO move it to Utils
|
||||||
|
*/
|
||||||
|
export const parsePosts = (posts) => {
|
||||||
|
posts.map(post => {
|
||||||
|
post.json_metadata = JSON.parse(post.json_metadata);
|
||||||
|
post.image = (post.json_metadata.image) ? post.json_metadata.image[0] : noImage;
|
||||||
|
post.pending_payout_value = parseFloat(post.pending_payout_value).toFixed(2);
|
||||||
|
post.created = moment.utc(post.created).local().fromNow();
|
||||||
|
post.vote_count = post.active_votes.length;
|
||||||
|
post.author_reputation = reputation(post.author_reputation);
|
||||||
|
post.avatar = `https://steemitimages.com/u/${post.author}/avatar/small`;
|
||||||
|
post.active_votes.sort((a,b) => {
|
||||||
|
return b.rshares - a.rshares
|
||||||
|
});
|
||||||
|
post.top_likers = [post.active_votes[0].voter, post.active_votes[1].voter, post.active_votes[2].voter]
|
||||||
|
console.log(post);
|
||||||
|
});
|
||||||
|
return posts
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO move it to Utils
|
||||||
|
*/
|
||||||
|
export const reputation = (reputation) => {
|
||||||
|
if (reputation == null) return reputation;
|
||||||
|
reputation = parseInt(reputation);
|
||||||
|
let log = Math.log10(reputation);
|
||||||
|
log = log - 9;
|
||||||
|
log = log * 9;
|
||||||
|
log = log + 25;
|
||||||
|
log = Math.floor(log);
|
||||||
|
return log;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @method getUser get user data
|
||||||
|
* @param user post author
|
||||||
|
* @param permlink post permlink
|
||||||
|
*/
|
||||||
|
export const getPost = (user, permlink) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let post = client.database.call('get_content',[user,permlink]);
|
||||||
|
resolve(post);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @method getUser get user data
|
||||||
|
* @param user post author
|
||||||
|
* @param permlink post permlink
|
||||||
|
*/
|
||||||
|
export const getComments = (user, permlink) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let comments = client.database.call('get_content_replies',[user, permlink]);
|
||||||
|
resolve(comments);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @method getPostWithComments get user data
|
||||||
|
* @param user post author
|
||||||
|
* @param permlink post permlink
|
||||||
|
*/
|
||||||
|
export const getPostWithComments = async (user, permlink) => {
|
||||||
|
let post;
|
||||||
|
let comments;
|
||||||
|
|
||||||
|
await getPost(user,permlink).then((result) => { post = result });
|
||||||
|
await getComments(user,permlink).then((result) => { comments = result });
|
||||||
|
|
||||||
|
return([post, comments])
|
||||||
|
}
|
43
src/screens/Drawer.js
Executable file
43
src/screens/Drawer.js
Executable file
@ -0,0 +1,43 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Platform, ScrollView } from 'react-native';
|
||||||
|
import { createDrawerNavigator } from 'react-navigation';
|
||||||
|
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';
|
||||||
|
|
||||||
|
import Tabs from '../components/Tabs';
|
||||||
|
import StacksOverTabs from '../examples/StacksOverTabs';
|
||||||
|
import ProfilePage from './profile/profile';
|
||||||
|
|
||||||
|
const Drawer = createDrawerNavigator({
|
||||||
|
Tabs: {
|
||||||
|
screen: Tabs,
|
||||||
|
navigationOptions: {
|
||||||
|
drawer: () => ({
|
||||||
|
label: 'Home',
|
||||||
|
icon: ({ tintColor }) => (
|
||||||
|
<MaterialIcons
|
||||||
|
name="Home"
|
||||||
|
size={24}
|
||||||
|
style={{ color: tintColor }}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Profile: {
|
||||||
|
screen: Tabs,
|
||||||
|
navigationOptions: {
|
||||||
|
drawer: () => ({
|
||||||
|
label: 'Profile',
|
||||||
|
icon: ({ tintColor }) => (
|
||||||
|
<MaterialIcons
|
||||||
|
name="user"
|
||||||
|
size={24}
|
||||||
|
style={{ color: tintColor }}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default Drawer;
|
41
src/screens/editor/editor.js
Normal file
41
src/screens/editor/editor.js
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import { Container, Header, Left, Body, Right, Button, Icon, Title } from 'native-base';
|
||||||
|
|
||||||
|
class EditorPage extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props)
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Container>
|
||||||
|
<Header>
|
||||||
|
<Left>
|
||||||
|
<Button transparent>
|
||||||
|
<Icon name='menu' />
|
||||||
|
</Button>
|
||||||
|
</Left>
|
||||||
|
<Body>
|
||||||
|
<Title>Editor</Title>
|
||||||
|
</Body>
|
||||||
|
<Right>
|
||||||
|
<Button transparent>
|
||||||
|
<Icon name='search' />
|
||||||
|
</Button>
|
||||||
|
<Button transparent>
|
||||||
|
<Icon name='heart' />
|
||||||
|
</Button>
|
||||||
|
<Button transparent>
|
||||||
|
<Icon name='more' />
|
||||||
|
</Button>
|
||||||
|
</Right>
|
||||||
|
</Header>
|
||||||
|
</Container>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default EditorPage;
|
178
src/screens/home/feed.js
Normal file
178
src/screens/home/feed.js
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
import { StyleSheet, FlatList, View } from 'react-native';
|
||||||
|
import { Container, Header, Title, Button,
|
||||||
|
Thumbnail, Left, Right, Body, Text,
|
||||||
|
Tabs, Tab, Content, Icon, Card,
|
||||||
|
CardItem, Image } from "native-base";
|
||||||
|
|
||||||
|
// DSTEEM
|
||||||
|
import { getPosts } from '../../providers/steem/Dsteem';
|
||||||
|
|
||||||
|
// LIBRARIES
|
||||||
|
import Placeholder from 'rn-placeholder';
|
||||||
|
|
||||||
|
// COMPONENTS
|
||||||
|
// import PostCard from '../../components/PostCard';
|
||||||
|
|
||||||
|
class PostCard extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
item: this.props.post
|
||||||
|
}
|
||||||
|
}
|
||||||
|
componentDidMount() {
|
||||||
|
alert(this.props.post);
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Container>
|
||||||
|
<Card>
|
||||||
|
<CardItem>
|
||||||
|
<Left>
|
||||||
|
<Body>
|
||||||
|
<Text>{ this.props.post }</Text>
|
||||||
|
<Text note>April 15, 2016</Text>
|
||||||
|
</Body>
|
||||||
|
</Left>
|
||||||
|
</CardItem>
|
||||||
|
</Card>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FeedPage extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props)
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
isReady: false,
|
||||||
|
posts: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.getTrending();
|
||||||
|
}
|
||||||
|
|
||||||
|
getTrending = () => {
|
||||||
|
getPosts('trending', { "tag": "", "limit": 3 }).then((result) => {
|
||||||
|
this.setState({ isReady: true });
|
||||||
|
this.setState({ posts: result });
|
||||||
|
console.log(this.state.posts)
|
||||||
|
}).catch((err) => {
|
||||||
|
alert(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Container>
|
||||||
|
<Header transparent>
|
||||||
|
<Left>
|
||||||
|
<Button transparent onPress={() => this.props.navigation.toggleDrawer()}>
|
||||||
|
<Thumbnail small source={{uri: 'https://steemitimages.com/u/esteemapp/avatar/small'}} />
|
||||||
|
</Button>
|
||||||
|
</Left>
|
||||||
|
<Body>
|
||||||
|
<Title></Title>
|
||||||
|
</Body>
|
||||||
|
<Right>
|
||||||
|
|
||||||
|
</Right>
|
||||||
|
</Header>
|
||||||
|
<Tabs>
|
||||||
|
<Tab heading="Feed"
|
||||||
|
tabStyle={{backgroundColor: 'white'}}
|
||||||
|
textStyle={{fontWeight: 'bold'}}
|
||||||
|
activeTabStyle={{backgroundColor: 'white'}}
|
||||||
|
activeTextStyle={{fontWeight: 'bold'}}>
|
||||||
|
</Tab>
|
||||||
|
<Tab heading="Hot"
|
||||||
|
tabStyle={{backgroundColor: 'white'}}
|
||||||
|
textStyle={{fontWeight: 'bold'}}
|
||||||
|
activeTabStyle={{backgroundColor: 'white'}}
|
||||||
|
activeTextStyle={{fontWeight: 'bold'}}>
|
||||||
|
<Text>Hot</Text>
|
||||||
|
</Tab>
|
||||||
|
<Tab heading="Trending"
|
||||||
|
tabStyle={{backgroundColor: 'white'}}
|
||||||
|
textStyle={{fontWeight: 'bold'}}
|
||||||
|
activeTabStyle={{backgroundColor: 'white'}}
|
||||||
|
activeTextStyle={{fontWeight: 'bold'}}>
|
||||||
|
<Container style={styles.container}>
|
||||||
|
{this.state.isReady ?
|
||||||
|
<FlatList
|
||||||
|
data={this.state.posts}
|
||||||
|
showsVerticalScrollIndicator={false}
|
||||||
|
renderItem={({post}) =>
|
||||||
|
<View>
|
||||||
|
<PostCard post={post}/>
|
||||||
|
</View>
|
||||||
|
}
|
||||||
|
keyExtractor={(post, index) => index.toString()}
|
||||||
|
/> :
|
||||||
|
<View>
|
||||||
|
<View style={styles.placeholder} >
|
||||||
|
<Placeholder.ImageContent
|
||||||
|
size={60}
|
||||||
|
animate="fade"
|
||||||
|
lineNumber={4}
|
||||||
|
lineSpacing={5}
|
||||||
|
lastLineWidth="30%"
|
||||||
|
onReady={this.state.isReady}
|
||||||
|
></Placeholder.ImageContent>
|
||||||
|
</View>
|
||||||
|
<View style={styles.placeholder} >
|
||||||
|
<Placeholder.ImageContent
|
||||||
|
size={60}
|
||||||
|
animate="fade"
|
||||||
|
lineNumber={4}
|
||||||
|
lineSpacing={5}
|
||||||
|
lastLineWidth="30%"
|
||||||
|
onReady={this.state.isReady}
|
||||||
|
></Placeholder.ImageContent>
|
||||||
|
</View>
|
||||||
|
<View style={styles.placeholder} >
|
||||||
|
<Placeholder.ImageContent
|
||||||
|
size={60}
|
||||||
|
animate="fade"
|
||||||
|
lineNumber={4}
|
||||||
|
lineSpacing={5}
|
||||||
|
lastLineWidth="30%"
|
||||||
|
onReady={this.state.isReady}
|
||||||
|
></Placeholder.ImageContent>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
}
|
||||||
|
</Container>
|
||||||
|
</Tab>
|
||||||
|
</Tabs>
|
||||||
|
</Container>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
backgroundColor: '#F9F9F9'
|
||||||
|
},
|
||||||
|
placeholder: {
|
||||||
|
backgroundColor: 'white',
|
||||||
|
padding: 20,
|
||||||
|
borderStyle: 'solid',
|
||||||
|
borderWidth: 1,
|
||||||
|
borderTopWidth: 1,
|
||||||
|
borderColor: '#e2e5e8',
|
||||||
|
borderRadius: 10,
|
||||||
|
marginRight: 10,
|
||||||
|
marginLeft: 10,
|
||||||
|
marginTop: 10,
|
||||||
|
},
|
||||||
|
card: {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default FeedPage;
|
37
src/screens/notifications/notification.js
Normal file
37
src/screens/notifications/notification.js
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import { Container, Header, Left, Body, Right, Button, Icon, Title } from 'native-base';
|
||||||
|
|
||||||
|
class NotificationPage extends React.Component {
|
||||||
|
static navigationOptions = {
|
||||||
|
title: 'Notifications',
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Container>
|
||||||
|
<Header>
|
||||||
|
<Left>
|
||||||
|
<Button transparent>
|
||||||
|
<Icon name='menu' />
|
||||||
|
</Button>
|
||||||
|
</Left>
|
||||||
|
<Body>
|
||||||
|
<Title>Notifications</Title>
|
||||||
|
</Body>
|
||||||
|
<Right>
|
||||||
|
<Button transparent>
|
||||||
|
<Icon name='search' />
|
||||||
|
</Button>
|
||||||
|
<Button transparent>
|
||||||
|
<Icon name='heart' />
|
||||||
|
</Button>
|
||||||
|
<Button transparent>
|
||||||
|
<Icon name='more' />
|
||||||
|
</Button>
|
||||||
|
</Right>
|
||||||
|
</Header>
|
||||||
|
</Container>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default NotificationPage;
|
38
src/screens/profile/profile.js
Normal file
38
src/screens/profile/profile.js
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import { Container, Header, Left, Body, Right, Button, Icon, Title, Text } from 'native-base';
|
||||||
|
|
||||||
|
class ProfilePage extends React.Component {
|
||||||
|
static navigationOptions = {
|
||||||
|
title: 'Profile',
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Container>
|
||||||
|
<Header>
|
||||||
|
<Left>
|
||||||
|
<Button transparent>
|
||||||
|
<Icon name='menu' />
|
||||||
|
</Button>
|
||||||
|
</Left>
|
||||||
|
<Body>
|
||||||
|
<Title>Profile</Title>
|
||||||
|
</Body>
|
||||||
|
<Right>
|
||||||
|
<Button transparent>
|
||||||
|
<Icon name='search' />
|
||||||
|
</Button>
|
||||||
|
<Button transparent>
|
||||||
|
<Icon name='heart' />
|
||||||
|
</Button>
|
||||||
|
<Button transparent>
|
||||||
|
<Icon name='more' />
|
||||||
|
</Button>
|
||||||
|
</Right>
|
||||||
|
</Header>
|
||||||
|
<Text>tesrsf</Text>
|
||||||
|
</Container>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default ProfilePage;
|
37
src/screens/wallet/wallet.js
Normal file
37
src/screens/wallet/wallet.js
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import { Container, Header, Left, Body, Right, Button, Icon, Title } from 'native-base';
|
||||||
|
|
||||||
|
class WalletPage extends React.Component {
|
||||||
|
static navigationOptions = {
|
||||||
|
title: 'Wallet',
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Container>
|
||||||
|
<Header>
|
||||||
|
<Left>
|
||||||
|
<Button transparent>
|
||||||
|
<Icon name='menu' />
|
||||||
|
</Button>
|
||||||
|
</Left>
|
||||||
|
<Body>
|
||||||
|
<Title>Wallet</Title>
|
||||||
|
</Body>
|
||||||
|
<Right>
|
||||||
|
<Button transparent>
|
||||||
|
<Icon name='search' />
|
||||||
|
</Button>
|
||||||
|
<Button transparent>
|
||||||
|
<Icon name='heart' />
|
||||||
|
</Button>
|
||||||
|
<Button transparent>
|
||||||
|
<Icon name='more' />
|
||||||
|
</Button>
|
||||||
|
</Right>
|
||||||
|
</Header>
|
||||||
|
</Container>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default WalletPage;
|
Loading…
Reference in New Issue
Block a user