mirror of
https://github.com/ecency/ecency-mobile.git
synced 2025-01-03 03:25:24 +03:00
Conflict
This commit is contained in:
commit
b91b478ab0
@ -28,7 +28,7 @@ buildscript {
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath('com.android.tools.build:gradle:3.5.0')
|
||||
classpath('com.android.tools.build:gradle:3.5.1')
|
||||
|
||||
classpath 'com.google.gms:google-services:4.0.2'
|
||||
classpath 'com.bugsnag:bugsnag-android-gradle-plugin:4.+'
|
||||
|
BIN
ios/eSteem.xcworkspace/xcuserdata/ue.xcuserdatad/UserInterfaceState.xcuserstate
generated
Normal file
BIN
ios/eSteem.xcworkspace/xcuserdata/ue.xcuserdatad/UserInterfaceState.xcuserstate
generated
Normal file
Binary file not shown.
@ -53,8 +53,8 @@
|
||||
"react-native-datepicker": "^1.7.2",
|
||||
"react-native-extended-stylesheet": "^0.10.0",
|
||||
"react-native-fast-image": "^4.0.14",
|
||||
"react-native-iap": "3.4.15",
|
||||
"react-native-gesture-handler": "^1.4.1",
|
||||
"react-native-iap": "^3.3.8",
|
||||
"react-native-image-crop-picker": "^0.25.2",
|
||||
"react-native-keyboard-aware-scroll-view": "^0.8.0",
|
||||
"react-native-linear-gradient": "^2.4.2",
|
||||
|
BIN
src/assets/estmTags.png
Normal file
BIN
src/assets/estmTags.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 44 KiB |
BIN
src/assets/estmTags@2x.png
Normal file
BIN
src/assets/estmTags@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 44 KiB |
BIN
src/assets/estmTags@3x.png
Normal file
BIN
src/assets/estmTags@3x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 44 KiB |
@ -0,0 +1,44 @@
|
||||
import React from 'react';
|
||||
import { View, Image } from 'react-native';
|
||||
|
||||
import { SpinIndicator } from '../spinIndicator/spinIndicator';
|
||||
|
||||
// Styles
|
||||
import styles from './boostIndicatorStyles';
|
||||
|
||||
const BoostIndicatorAnimation = ({ isSpinning }) => {
|
||||
return (
|
||||
<View style={styles.spinIndicatorContainer}>
|
||||
<SpinIndicator
|
||||
size={230}
|
||||
animationDuration={2400}
|
||||
color={!isSpinning ? '#f2f2f2' : '#1a509a'}
|
||||
breadth={12}
|
||||
animating={isSpinning}
|
||||
initStart={0}
|
||||
/>
|
||||
<SpinIndicator
|
||||
size={180}
|
||||
animationDuration={2000}
|
||||
color={!isSpinning ? '#f2f2f2' : '#357ce6'}
|
||||
breadth={12}
|
||||
animating={isSpinning}
|
||||
initStart={20}
|
||||
/>
|
||||
<SpinIndicator
|
||||
size={130}
|
||||
animationDuration={1700}
|
||||
color={!isSpinning ? '#f2f2f2' : '#4da1f1'}
|
||||
breadth={12}
|
||||
animating={isSpinning}
|
||||
initStart={40}
|
||||
/>
|
||||
<Image
|
||||
style={{ width: 80, height: 80 }}
|
||||
source={require('../../../assets/esteem_logo_transparent.png')}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export { BoostIndicatorAnimation };
|
@ -0,0 +1,11 @@
|
||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||
|
||||
export default EStyleSheet.create({
|
||||
spinIndicatorContainer: {
|
||||
backgroundColor: '$primaryBackgroundColor',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
width: '$deviceWidth',
|
||||
flex: 1,
|
||||
},
|
||||
});
|
@ -1,4 +1,5 @@
|
||||
import PulseAnimation from './pulse/pulseAnimation';
|
||||
import { PulseAnimation } from './pulse/pulseAnimation';
|
||||
import { SpinIndicator } from './spinIndicator/spinIndicator';
|
||||
import { BoostIndicatorAnimation } from './boostIndicator/boostIndicatorAnimation';
|
||||
|
||||
export { PulseAnimation };
|
||||
export default PulseAnimation;
|
||||
export { PulseAnimation, SpinIndicator, BoostIndicatorAnimation };
|
||||
|
@ -14,7 +14,7 @@ const styles = StyleSheet.create({
|
||||
},
|
||||
});
|
||||
|
||||
export default class PulseAnimation extends Component {
|
||||
class PulseAnimation extends Component {
|
||||
static defaultProps = {
|
||||
color: 'blue',
|
||||
diameter: 400,
|
||||
@ -151,3 +151,5 @@ export default class PulseAnimation extends Component {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export { PulseAnimation };
|
||||
|
104
src/components/animations/spinIndicator/indicator.js
Normal file
104
src/components/animations/spinIndicator/indicator.js
Normal file
@ -0,0 +1,104 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import { Animated, Easing } from 'react-native';
|
||||
|
||||
export default class Indicator extends PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
progress: new Animated.Value(0),
|
||||
};
|
||||
|
||||
this.mounted = false;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { animating } = this.props;
|
||||
|
||||
this.mounted = true;
|
||||
|
||||
if (animating) {
|
||||
this._startAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
const { animating } = this.props;
|
||||
|
||||
if (animating !== prevProps.animating) {
|
||||
if (animating) {
|
||||
this._stopAnimation();
|
||||
} else {
|
||||
this._startAnimation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.mounted = false;
|
||||
}
|
||||
|
||||
_startAnimation = ({ finished } = {}) => {
|
||||
const { progress } = this.state;
|
||||
const { interaction, animationEasing, animationDuration } = this.props;
|
||||
|
||||
if (!this.mounted || finished === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
const animation = Animated.timing(progress, {
|
||||
duration: animationDuration,
|
||||
easing: animationEasing,
|
||||
useNativeDriver: true,
|
||||
isInteraction: interaction,
|
||||
toValue: 1,
|
||||
});
|
||||
|
||||
Animated.loop(animation).start();
|
||||
|
||||
this.setState({ animation });
|
||||
};
|
||||
|
||||
_stopAnimation = () => {
|
||||
const { animation } = this.state;
|
||||
|
||||
if (animation == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
animation.stop();
|
||||
|
||||
this.setState({ animation: null });
|
||||
};
|
||||
|
||||
_renderComponent = (undefined, index) => {
|
||||
const { progress } = this.state;
|
||||
const { renderComponent } = this.props;
|
||||
|
||||
if (renderComponent) {
|
||||
return renderComponent({ index, progress });
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
render() {
|
||||
const { count, ...props } = this.props;
|
||||
|
||||
return (
|
||||
<Animated.View {...props}>
|
||||
{Array.from(new Array(count), this._renderComponent)}
|
||||
</Animated.View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Indicator.defaultProps = {
|
||||
animationEasing: Easing.linear,
|
||||
animationDuration: 1200,
|
||||
animating: true,
|
||||
interaction: true,
|
||||
count: 1,
|
||||
};
|
||||
|
||||
export { Indicator };
|
125
src/components/animations/spinIndicator/spinIndicator.js
Normal file
125
src/components/animations/spinIndicator/spinIndicator.js
Normal file
@ -0,0 +1,125 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import { View, Animated, Easing } from 'react-native';
|
||||
|
||||
import { Indicator } from './indicator';
|
||||
import styles from './spinIndicatorStyles';
|
||||
|
||||
class SpinIndicator extends PureComponent {
|
||||
_renderComponent = ({ index, progress }) => {
|
||||
const { size, color, animationDuration, breadth, animating, initStart } = this.props;
|
||||
|
||||
const frames = (60 * animationDuration) / 1000;
|
||||
const easing = Easing.bezier(0.4, 0.0, 0.7, 1.0);
|
||||
|
||||
const inputRange = Array.from(
|
||||
new Array(frames),
|
||||
(undefined, frameIndex) => frameIndex / (frames - 1),
|
||||
);
|
||||
|
||||
const outputRange = Array.from(new Array(frames), (undefined, frameIndex) => {
|
||||
let _progress = (2 * frameIndex) / (frames - 1);
|
||||
const rotation = index ? +(360 - 15) : -(180 - 15);
|
||||
|
||||
if (_progress > 1.0) {
|
||||
_progress = 2.0 - _progress;
|
||||
}
|
||||
|
||||
const direction = index ? -1 : +1;
|
||||
|
||||
return `${direction * (180 - 30) * easing(_progress) + rotation}deg`;
|
||||
});
|
||||
|
||||
const layerStyle = {
|
||||
width: size,
|
||||
height: size,
|
||||
transform: [
|
||||
{
|
||||
rotate: progress.interpolate({
|
||||
inputRange: [0, 1],
|
||||
outputRange: [`${initStart + 30 + 15}deg`, `${2 * (360 + initStart)}deg`],
|
||||
}),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const viewportStyle = {
|
||||
width: size,
|
||||
height: size,
|
||||
transform: [
|
||||
{
|
||||
translateY: index ? -size / 2 : 0,
|
||||
},
|
||||
{
|
||||
rotate: progress.interpolate({ inputRange, outputRange }),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const containerStyle = {
|
||||
width: !animating ? 300 : size,
|
||||
height: !animating ? 300 : size / 2,
|
||||
position: 'absolute',
|
||||
overflow: 'hidden',
|
||||
};
|
||||
|
||||
const offsetStyle = index ? { top: size / 2 } : null;
|
||||
|
||||
const lineStyle = {
|
||||
width: size,
|
||||
height: size,
|
||||
borderColor: color,
|
||||
borderWidth: breadth || size / 10,
|
||||
borderRadius: size / 2,
|
||||
};
|
||||
|
||||
return (
|
||||
<Animated.View style={styles.layer} {...{ key: index }}>
|
||||
<Animated.View style={layerStyle}>
|
||||
<Animated.View style={[containerStyle, offsetStyle]} collapsable={false}>
|
||||
<Animated.View style={viewportStyle}>
|
||||
<Animated.View style={containerStyle} collapsable={false}>
|
||||
<Animated.View style={lineStyle} />
|
||||
</Animated.View>
|
||||
</Animated.View>
|
||||
</Animated.View>
|
||||
</Animated.View>
|
||||
</Animated.View>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
style,
|
||||
size: width,
|
||||
size: height,
|
||||
animationDuration,
|
||||
interaction,
|
||||
animating,
|
||||
animationEasing,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<View style={[styles.container, style]}>
|
||||
<Indicator
|
||||
style={{ width, height }}
|
||||
renderComponent={this._renderComponent}
|
||||
interaction={interaction}
|
||||
animationEasing={animationEasing}
|
||||
animationDuration={animationDuration}
|
||||
animating={animating}
|
||||
count={2}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
SpinIndicator.defaultProps = {
|
||||
animationDuration: 2400,
|
||||
color: '#1a509a',
|
||||
animating: true,
|
||||
size: 40,
|
||||
initStart: 0,
|
||||
};
|
||||
|
||||
export { SpinIndicator };
|
@ -0,0 +1,14 @@
|
||||
import { StyleSheet } from 'react-native';
|
||||
|
||||
export default StyleSheet.create({
|
||||
container: {
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
position: 'absolute',
|
||||
},
|
||||
layer: {
|
||||
...StyleSheet.absoluteFillObject,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
});
|
@ -1,5 +1,6 @@
|
||||
import { AvatarHeader } from './avatarHeader';
|
||||
import { BasicHeader } from './basicHeader';
|
||||
import { BoostIndicatorAnimation } from './animations';
|
||||
import { BottomTabBar } from './bottomTabBar';
|
||||
import { CheckBox } from './checkbox';
|
||||
import { CircularButton, TextButton, SquareButton } from './buttons';
|
||||
@ -36,6 +37,7 @@ import { SearchInput } from './searchInput';
|
||||
import { SearchModal } from './searchModal';
|
||||
import { SettingsItem } from './settingsItem';
|
||||
import { SideMenu } from './sideMenu';
|
||||
import { SpinIndicator } from './animations';
|
||||
import { SummaryArea, TagArea, TextArea, TitleArea } from './editorElements';
|
||||
import { TabBar } from './tabBar';
|
||||
import { TextInput } from './textInput';
|
||||
@ -48,6 +50,7 @@ import Logo from './logo/logo';
|
||||
import PostButton from './postButton/postButtonView';
|
||||
import ProfileEditForm from './profileEditForm/profileEditFormView';
|
||||
import ScaleSlider from './scaleSlider/scaleSliderView';
|
||||
import { ProductItemLine } from './productItemLine/productItemLineView';
|
||||
|
||||
// View
|
||||
import { Comment } from './comment';
|
||||
@ -64,6 +67,7 @@ import { WalletDetails } from './walletDetails';
|
||||
import PostBoost from './postBoost/postBoostView';
|
||||
import Profile from './profile/profileView';
|
||||
import Promote from './promote/promoteView';
|
||||
import { SpinGame } from './spinGame/spinGameView';
|
||||
|
||||
// Basic UI Elements
|
||||
import {
|
||||
@ -89,30 +93,14 @@ import {
|
||||
} from './basicUIElements';
|
||||
|
||||
export {
|
||||
Card,
|
||||
Chip,
|
||||
GrayWrapper,
|
||||
LineBreak,
|
||||
ListItemPlaceHolder,
|
||||
ListPlaceHolder,
|
||||
BoostPlaceHolder,
|
||||
NoInternetConnection,
|
||||
NoPost,
|
||||
PostCardPlaceHolder,
|
||||
PostPlaceHolder,
|
||||
ProfileSummaryPlaceHolder,
|
||||
StickyBar,
|
||||
Tag,
|
||||
TextWithIcon,
|
||||
UserListItem,
|
||||
WalletDetailsPlaceHolder,
|
||||
WalletLineItem,
|
||||
WalletUnclaimedPlaceHolder,
|
||||
AvatarHeader,
|
||||
BasicHeader,
|
||||
InformationBox,
|
||||
BoostIndicatorAnimation,
|
||||
BoostPlaceHolder,
|
||||
BottomTabBar,
|
||||
Card,
|
||||
CheckBox,
|
||||
Chip,
|
||||
CircularButton,
|
||||
CollapsibleCard,
|
||||
Comment,
|
||||
@ -124,16 +112,23 @@ export {
|
||||
FilterBar,
|
||||
FormatedCurrency,
|
||||
FormInput,
|
||||
GrayWrapper,
|
||||
Header,
|
||||
Icon,
|
||||
IconButton,
|
||||
InformationArea,
|
||||
InformationBox,
|
||||
LeaderBoard,
|
||||
LineBreak,
|
||||
ListItemPlaceHolder,
|
||||
ListPlaceHolder,
|
||||
LoginHeader,
|
||||
Logo,
|
||||
MainButton,
|
||||
MarkdownEditor,
|
||||
Modal,
|
||||
NoInternetConnection,
|
||||
NoPost,
|
||||
Notification,
|
||||
NotificationLine,
|
||||
NumericKeyboard,
|
||||
@ -145,15 +140,19 @@ export {
|
||||
PostBoost,
|
||||
PostButton,
|
||||
PostCard,
|
||||
PostCardPlaceHolder,
|
||||
PostDisplay,
|
||||
PostDropdown,
|
||||
PostForm,
|
||||
PostHeaderDescription,
|
||||
PostListItem,
|
||||
PostPlaceHolder,
|
||||
Posts,
|
||||
ProductItemLine,
|
||||
Profile,
|
||||
ProfileEditForm,
|
||||
ProfileSummary,
|
||||
ProfileSummaryPlaceHolder,
|
||||
Promote,
|
||||
PulseAnimation,
|
||||
ScaleSlider,
|
||||
@ -161,14 +160,19 @@ export {
|
||||
SearchModal,
|
||||
SettingsItem,
|
||||
SideMenu,
|
||||
SpinGame,
|
||||
SpinIndicator,
|
||||
SquareButton,
|
||||
StickyBar,
|
||||
SummaryArea,
|
||||
TabBar,
|
||||
Tag,
|
||||
TagArea,
|
||||
Tags,
|
||||
TextArea,
|
||||
TextButton,
|
||||
TextInput,
|
||||
TextWithIcon,
|
||||
TitleArea,
|
||||
ToastNotification,
|
||||
ToggleSwitch,
|
||||
@ -176,7 +180,11 @@ export {
|
||||
TransferFormItem,
|
||||
Upvote,
|
||||
UserAvatar,
|
||||
UserListItem,
|
||||
VotersDisplay,
|
||||
Wallet,
|
||||
WalletDetails,
|
||||
WalletDetailsPlaceHolder,
|
||||
WalletLineItem,
|
||||
WalletUnclaimedPlaceHolder,
|
||||
};
|
||||
|
@ -26,7 +26,7 @@ export default EStyleSheet.create({
|
||||
alignSelf: 'center',
|
||||
fontSize: 14,
|
||||
paddingLeft: 10,
|
||||
paddingRight: 20,
|
||||
paddingRight: 10,
|
||||
},
|
||||
secondText: {
|
||||
fontWeight: 'bold',
|
||||
|
@ -41,7 +41,9 @@ class MainButton extends Component {
|
||||
_handleOnPress = () => {
|
||||
const { onPress } = this.props;
|
||||
|
||||
if (onPress) onPress();
|
||||
if (onPress) {
|
||||
onPress();
|
||||
}
|
||||
};
|
||||
|
||||
_getBody = () => {
|
||||
@ -57,12 +59,14 @@ class MainButton extends Component {
|
||||
{source ? (
|
||||
<Image source={source} style={styles.image} resizeMode="contain" />
|
||||
) : (
|
||||
<Icon
|
||||
iconType={iconType || 'MaterialIcons'}
|
||||
color={iconColor}
|
||||
name={iconName}
|
||||
style={styles.icon}
|
||||
/>
|
||||
iconName && (
|
||||
<Icon
|
||||
iconType={iconType || 'MaterialIcons'}
|
||||
color={iconColor}
|
||||
name={iconName}
|
||||
style={styles.icon}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
<Text style={styles.text}>
|
||||
{text}
|
||||
@ -92,7 +96,7 @@ class MainButton extends Component {
|
||||
<View style={wrapperStyle}>
|
||||
<TouchableOpacity
|
||||
disabled={isLoading || isDisable}
|
||||
onPress={() => this._handleOnPress()}
|
||||
onPress={this._handleOnPress}
|
||||
style={[
|
||||
styles.touchable,
|
||||
isDisable && styles.disableTouchable,
|
||||
|
@ -1,10 +1,11 @@
|
||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||
|
||||
export default EStyleSheet.create({
|
||||
wrapper: {
|
||||
buttonWrapper: {
|
||||
minWidth: '$deviceWidth / 2.4',
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'flex-end',
|
||||
flex: 1,
|
||||
position: 'absolute',
|
||||
top: '$deviceHeight / 3',
|
||||
},
|
||||
boostLine: {
|
||||
flexDirection: 'row',
|
||||
@ -14,16 +15,12 @@ export default EStyleSheet.create({
|
||||
button: {
|
||||
marginVertical: 12,
|
||||
paddingHorizontal: 18,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
buttonContent: {
|
||||
flexDirection: 'row',
|
||||
},
|
||||
buttonWrapper: {
|
||||
minWidth: '$deviceWidth / 2.4',
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'flex-end',
|
||||
flex: 1,
|
||||
},
|
||||
buttonText: {
|
||||
color: '$pureWhite',
|
||||
fontSize: 14,
|
59
src/components/productItemLine/productItemLineView.js
Normal file
59
src/components/productItemLine/productItemLineView.js
Normal file
@ -0,0 +1,59 @@
|
||||
import React from 'react';
|
||||
import { View, Text } from 'react-native';
|
||||
import get from 'lodash/get';
|
||||
import { useIntl } from 'react-intl';
|
||||
|
||||
// Components
|
||||
import { MainButton, Icon } from '..';
|
||||
|
||||
import styles from './productItemLineStyles';
|
||||
|
||||
// TODO: move to translation
|
||||
const DEALS = { '9999points': 'BEST DEAL!', '4999points': 'POPULAR!' };
|
||||
|
||||
const ProductItemLineView = ({ disabled, handleOnButtonPress, product, title }) => {
|
||||
const intl = useIntl();
|
||||
|
||||
return (
|
||||
<View style={styles.boostLine} key={get(product, 'productId')}>
|
||||
{_renderDeal(product)}
|
||||
<View style={styles.buttonWrapper}>
|
||||
<MainButton
|
||||
style={styles.button}
|
||||
onPress={() => handleOnButtonPress(get(product, 'productId'))}
|
||||
height={50}
|
||||
isDisable={disabled}
|
||||
isLoading={false}
|
||||
>
|
||||
<View style={styles.buttonContent}>
|
||||
<Text style={styles.buttonText}>{title}</Text>
|
||||
<View style={styles.buttonIconWrapper}>
|
||||
<Icon name="add" iconType="MaterialIcons" color="#357ce6" size={23} />
|
||||
</View>
|
||||
</View>
|
||||
</MainButton>
|
||||
</View>
|
||||
|
||||
<View style={styles.priceWrapper}>
|
||||
{get(product, 'localizedPrice', null) && (
|
||||
<Text style={styles.priceText}>{get(product, 'localizedPrice', 0)}</Text>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const _renderDeal = item => {
|
||||
if (DEALS[item.productId]) {
|
||||
return (
|
||||
<View style={styles.descriptionWrapper}>
|
||||
<Text style={styles.description}>{DEALS[item.productId]}</Text>
|
||||
<View style={styles.triangle} />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
export { ProductItemLineView as ProductItemLine };
|
86
src/components/spinGame/spinGameStyles.js
Normal file
86
src/components/spinGame/spinGameStyles.js
Normal file
@ -0,0 +1,86 @@
|
||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||
|
||||
export default EStyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: '$primaryBackgroundColor',
|
||||
alignItems: 'center',
|
||||
},
|
||||
textWrapper: {
|
||||
flex: 0.2,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
count: {
|
||||
fontSize: 72,
|
||||
fontWeight: '700',
|
||||
color: '$primaryDarkGray',
|
||||
},
|
||||
countDesc: {
|
||||
color: '$primaryDarkGray',
|
||||
fontSize: 16,
|
||||
marginTop: 5,
|
||||
fontWeight: '700',
|
||||
},
|
||||
spinnerWrapper: {
|
||||
flex: 1,
|
||||
marginTop: 10,
|
||||
},
|
||||
backgroundTags: {
|
||||
position: 'absolute',
|
||||
width: '$deviceWidth',
|
||||
height: 320,
|
||||
left: 0,
|
||||
top: 16,
|
||||
right: 0,
|
||||
zIndex: 998,
|
||||
},
|
||||
descriptionWrapper: {
|
||||
backgroundColor: '$primaryDarkBlue',
|
||||
width: 75,
|
||||
height: 30,
|
||||
justifyContent: 'center',
|
||||
paddingHorizontal: 5,
|
||||
borderTopRightRadius: 0,
|
||||
borderBottomRightRadius: 0,
|
||||
position: 'absolute',
|
||||
top: '$deviceHeight / 5',
|
||||
right: 0,
|
||||
},
|
||||
description: {
|
||||
fontSize: 10,
|
||||
color: '$pureWhite',
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
triangle: {
|
||||
width: 0,
|
||||
height: 0,
|
||||
backgroundColor: 'transparent',
|
||||
borderStyle: 'solid',
|
||||
borderLeftWidth: 15,
|
||||
borderRightWidth: 15,
|
||||
borderBottomWidth: 15,
|
||||
borderLeftColor: 'transparent',
|
||||
borderRightColor: 'transparent',
|
||||
borderBottomColor: '$primaryDarkBlue',
|
||||
transform: [{ rotate: '-90deg' }],
|
||||
position: 'absolute',
|
||||
left: -22,
|
||||
},
|
||||
productWrapper: {
|
||||
flex: 0.8,
|
||||
zIndex: 998,
|
||||
alignItems: 'center',
|
||||
},
|
||||
spinButton: {
|
||||
width: 150,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
nextDate: {
|
||||
marginTop: 50,
|
||||
color: '$primaryDarkGray',
|
||||
fontSize: 16,
|
||||
fontWeight: '600',
|
||||
},
|
||||
});
|
98
src/components/spinGame/spinGameView.js
Normal file
98
src/components/spinGame/spinGameView.js
Normal file
@ -0,0 +1,98 @@
|
||||
import React, { useState, Fragment } from 'react';
|
||||
import { Image, Text, View } from 'react-native';
|
||||
import moment from 'moment';
|
||||
import { useIntl } from 'react-intl';
|
||||
|
||||
// Components
|
||||
import { BoostIndicatorAnimation, MainButton, BasicHeader, ProductItemLine } from '..';
|
||||
import ESTM_TAGS from '../../assets/estmTags.png';
|
||||
|
||||
// Styles
|
||||
import styles from './spinGameStyles';
|
||||
|
||||
const SpinGameView = ({
|
||||
gameRight,
|
||||
score,
|
||||
isLoading,
|
||||
spinProduct,
|
||||
isProcessing,
|
||||
buyItem,
|
||||
nextDate,
|
||||
startGame,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const [isSpinning, setIsSpinning] = useState(false);
|
||||
|
||||
const _handleOnSpinPress = () => {
|
||||
startGame('spin');
|
||||
|
||||
setIsSpinning(true);
|
||||
|
||||
this.spinTimeout = setTimeout(() => {
|
||||
clearTimeout(this.spinTimeout);
|
||||
setIsSpinning(false);
|
||||
}, 8 * 1000);
|
||||
};
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<BasicHeader title={intl.formatMessage({ id: 'free_estm.title' })} />
|
||||
<View style={styles.container}>
|
||||
<View style={styles.textWrapper}>
|
||||
{!isSpinning && !isLoading && (
|
||||
<Fragment>
|
||||
<Text style={styles.count}>{gameRight}</Text>
|
||||
<Text style={styles.countDesc}>
|
||||
{intl.formatMessage({ id: 'free_estm.spin_right' })}
|
||||
</Text>
|
||||
</Fragment>
|
||||
)}
|
||||
</View>
|
||||
<View style={styles.spinnerWrapper}>
|
||||
{!isSpinning && !isLoading && gameRight > 0 && (
|
||||
<Image source={ESTM_TAGS} style={styles.backgroundTags} />
|
||||
)}
|
||||
<BoostIndicatorAnimation key={gameRight} isSpinning={isSpinning} />
|
||||
|
||||
{!isSpinning && score > 0 && (
|
||||
<View style={styles.descriptionWrapper}>
|
||||
<Fragment>
|
||||
<Text style={styles.description}>{`${score} ESTM`}</Text>
|
||||
<View style={styles.triangle} />
|
||||
</Fragment>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
<View style={styles.productWrapper}>
|
||||
{!isSpinning && !isLoading && (
|
||||
<Fragment>
|
||||
{gameRight > 0 ? (
|
||||
<MainButton
|
||||
style={styles.spinButton}
|
||||
onPress={_handleOnSpinPress}
|
||||
text={intl.formatMessage({ id: 'free_estm.button' })}
|
||||
/>
|
||||
) : (
|
||||
<Fragment>
|
||||
{spinProduct.map(product => (
|
||||
<ProductItemLine
|
||||
product={product}
|
||||
title={intl.formatMessage({ id: 'free_estm.get_spin' })}
|
||||
disabled={isProcessing}
|
||||
handleOnButtonPress={id => buyItem(id)}
|
||||
/>
|
||||
))}
|
||||
<Text style={styles.nextDate}>{`${intl.formatMessage({
|
||||
id: 'free_estm.timer_text',
|
||||
})} ${moment.utc(moment(nextDate).diff(new Date())).format('H:m')}`}</Text>
|
||||
</Fragment>
|
||||
)}
|
||||
</Fragment>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
export { SpinGameView as SpinGame };
|
@ -5,12 +5,12 @@ import { connect } from 'react-redux';
|
||||
// Styles
|
||||
import styles from './textInputStyles';
|
||||
|
||||
const TextInputView = ({ isDarkTheme, innerRef, height, ...props }) => (
|
||||
const TextInputView = ({ isDarkTheme, innerRef, height, style, ...props }) => (
|
||||
<TextInput
|
||||
style={[styles.input, { minHeight: height }]}
|
||||
ref={innerRef}
|
||||
keyboardAppearance={isDarkTheme ? 'dark' : 'light'}
|
||||
{...props}
|
||||
style={[styles.input, { minHeight: height }, style]}
|
||||
/>
|
||||
);
|
||||
|
||||
|
@ -333,6 +333,13 @@
|
||||
"buy": "GET ESTM",
|
||||
"next": "NEXT"
|
||||
},
|
||||
"free_estm": {
|
||||
"title": "Free ESTM",
|
||||
"button": "SPIN & WIN",
|
||||
"get_spin": "5 SPINS",
|
||||
"spin_right": "Spin Left",
|
||||
"timer_text": "Next free spin in"
|
||||
},
|
||||
"promote": {
|
||||
"title": "Promote",
|
||||
"days": "days",
|
||||
|
@ -10,7 +10,7 @@ export default {
|
||||
DRAFTS: `Drafts${SCREEN_SUFFIX}`,
|
||||
EDITOR: `Editor${SCREEN_SUFFIX}`,
|
||||
FOLLOWS: `Follows${SCREEN_SUFFIX}`,
|
||||
FREE_ESTM: `FreeEstm${SCREEN_SUFFIX}`,
|
||||
SPIN_GAME: `SpinGame${SCREEN_SUFFIX}`,
|
||||
HOME: `Home${SCREEN_SUFFIX}`,
|
||||
LOGIN: `Login${SCREEN_SUFFIX}`,
|
||||
PINCODE: `PinCode${SCREEN_SUFFIX}`,
|
||||
|
@ -14,12 +14,7 @@ import { purchaseOrder } from '../providers/esteem/esteem';
|
||||
// Utilities
|
||||
import { default as ROUTES } from '../constants/routeNames';
|
||||
|
||||
const ITEM_SKUS = Platform.select({
|
||||
ios: ['099points', '199points', '499points', '999points', '4999points', '9999points'],
|
||||
android: ['099points', '199points', '499points', '999points', '4999points', '9999points'],
|
||||
});
|
||||
|
||||
class BoostContainer extends Component {
|
||||
class InAppPurchaseContainer extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
@ -53,6 +48,7 @@ class BoostContainer extends Component {
|
||||
const {
|
||||
currentAccount: { name },
|
||||
intl,
|
||||
fetchData,
|
||||
} = this.props;
|
||||
|
||||
this.purchaseUpdateSubscription = purchaseUpdatedListener(purchase => {
|
||||
@ -75,6 +71,10 @@ class BoostContainer extends Component {
|
||||
RNIap.consumePurchaseAndroid(token);
|
||||
}
|
||||
this.setState({ isProcessing: false });
|
||||
|
||||
if (fetchData) {
|
||||
fetchData();
|
||||
}
|
||||
})
|
||||
.catch(err =>
|
||||
bugsnag.notify(err, report => {
|
||||
@ -109,8 +109,10 @@ class BoostContainer extends Component {
|
||||
};
|
||||
|
||||
_getItems = async () => {
|
||||
const { skus } = this.props;
|
||||
|
||||
try {
|
||||
const products = await RNIap.getProducts(ITEM_SKUS);
|
||||
const products = await RNIap.getProducts(skus);
|
||||
|
||||
products.sort((a, b) => parseFloat(a.price) - parseFloat(b.price)).reverse();
|
||||
await this.setState({ productList: products });
|
||||
@ -128,9 +130,9 @@ class BoostContainer extends Component {
|
||||
_buyItem = async sku => {
|
||||
const { navigation } = this.props;
|
||||
|
||||
await this.setState({ isProcessing: true });
|
||||
|
||||
if (sku !== 'freePoints') {
|
||||
await this.setState({ isProcessing: true });
|
||||
|
||||
try {
|
||||
RNIap.requestPurchase(sku, false);
|
||||
} catch (err) {
|
||||
@ -142,7 +144,7 @@ class BoostContainer extends Component {
|
||||
}
|
||||
} else {
|
||||
navigation.navigate({
|
||||
routeName: ROUTES.SCREENS.FREE_ESTM,
|
||||
routeName: ROUTES.SCREENS.SPIN_GAME,
|
||||
});
|
||||
}
|
||||
};
|
||||
@ -150,16 +152,17 @@ class BoostContainer extends Component {
|
||||
render() {
|
||||
const { children } = this.props;
|
||||
const { productList, isLoading, isProcessing } = this.state;
|
||||
// const FREE_ESTM = { productId: 'freePoints', title: 'free estm' };
|
||||
const FREE_ESTM = { productId: 'freePoints', title: 'free estm' };
|
||||
|
||||
return (
|
||||
children &&
|
||||
children({
|
||||
// productList: [...productList, FREE_ESTM],
|
||||
productList,
|
||||
productList: [...productList, FREE_ESTM],
|
||||
buyItem: this._buyItem,
|
||||
isLoading,
|
||||
isProcessing,
|
||||
getItems: this._getItems,
|
||||
spinProduct: productList.filter(item => item.productId.includes('spins')),
|
||||
})
|
||||
);
|
||||
}
|
||||
@ -169,4 +172,4 @@ const mapStateToProps = state => ({
|
||||
currentAccount: state.account.currentAccount,
|
||||
});
|
||||
|
||||
export default withNavigation(injectIntl(connect(mapStateToProps)(BoostContainer)));
|
||||
export default withNavigation(injectIntl(connect(mapStateToProps)(InAppPurchaseContainer)));
|
||||
|
@ -3,6 +3,7 @@ import PointsContainer from './pointsContainer';
|
||||
import ProfileContainer from './profileContainer';
|
||||
import ProfileEditContainer from './profileEditContainer';
|
||||
import RedeemContainer from './redeemContainer';
|
||||
import SpinGameContainer from './spinGameContainer';
|
||||
import TransferContainer from './transferContainer';
|
||||
|
||||
export {
|
||||
@ -11,5 +12,6 @@ export {
|
||||
ProfileContainer,
|
||||
ProfileEditContainer,
|
||||
RedeemContainer,
|
||||
SpinGameContainer,
|
||||
TransferContainer,
|
||||
};
|
||||
|
@ -42,8 +42,8 @@ class PointsContainer extends Component {
|
||||
const { username, isConnected, navigation } = this.props;
|
||||
|
||||
if (isConnected) {
|
||||
this._fetchuserPointActivities(username);
|
||||
this.fetchInterval = setInterval(this._fetchuserPointActivities, 6 * 60 * 1000);
|
||||
this._fetchUserPointActivities(username);
|
||||
this.fetchInterval = setInterval(this._fetchUserPointActivities, 6 * 60 * 1000);
|
||||
}
|
||||
|
||||
if (get(navigation, 'state.params', null)) {
|
||||
@ -62,7 +62,7 @@ class PointsContainer extends Component {
|
||||
((nextProps.activeBottomTab === ROUTES.TABBAR.POINTS && _username) ||
|
||||
(_username !== username && _username))
|
||||
) {
|
||||
this._fetchuserPointActivities(_username);
|
||||
this._fetchUserPointActivities(_username);
|
||||
}
|
||||
}
|
||||
|
||||
@ -131,8 +131,10 @@ class PointsContainer extends Component {
|
||||
textKey: get(POINTS[get(item, 'type')], 'textKey'),
|
||||
}));
|
||||
|
||||
_fetchuserPointActivities = async username => {
|
||||
if (!username) return;
|
||||
_fetchUserPointActivities = async username => {
|
||||
if (!username) {
|
||||
return;
|
||||
}
|
||||
this.setState({ refreshing: true });
|
||||
|
||||
await getUser(username)
|
||||
@ -153,7 +155,9 @@ class PointsContainer extends Component {
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
if (err) Alert.alert(get(err, 'message') || err.toString());
|
||||
if (err) {
|
||||
Alert.alert(get(err, 'message') || err.toString());
|
||||
}
|
||||
});
|
||||
|
||||
this.setState({
|
||||
@ -169,7 +173,9 @@ class PointsContainer extends Component {
|
||||
return balance;
|
||||
})
|
||||
.catch(err => {
|
||||
if (err) Alert.alert(get(err, 'message') || err.toString());
|
||||
if (err) {
|
||||
Alert.alert(get(err, 'message') || err.toString());
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@ -180,7 +186,7 @@ class PointsContainer extends Component {
|
||||
|
||||
await claim(username)
|
||||
.then(() => {
|
||||
this._fetchuserPointActivities(username);
|
||||
this._fetchUserPointActivities(username);
|
||||
})
|
||||
.catch(error => {
|
||||
if (error) {
|
||||
@ -243,7 +249,7 @@ class PointsContainer extends Component {
|
||||
claimPoints: this._claimPoints,
|
||||
currentAccount,
|
||||
currentAccountName: currentAccount.name,
|
||||
fetchUserActivity: this._fetchuserPointActivities,
|
||||
fetchUserActivity: this._fetchUserPointActivities,
|
||||
getAccount,
|
||||
getESTMPrice: this._getESTMPrice,
|
||||
getUserBalance: this._getUserBalance,
|
||||
|
103
src/containers/spinGameContainer.js
Normal file
103
src/containers/spinGameContainer.js
Normal file
@ -0,0 +1,103 @@
|
||||
import { Component } from 'react';
|
||||
import { Alert } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
import get from 'lodash/get';
|
||||
import { injectIntl } from 'react-intl';
|
||||
import { withNavigation } from 'react-navigation';
|
||||
|
||||
// Providers
|
||||
import { gameStatusCheck, gameClaim } from '../providers/esteem/ePoint';
|
||||
|
||||
class RedeemContainer extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
score: 0,
|
||||
nextDate: null,
|
||||
gameRight: 1,
|
||||
isLoading: true,
|
||||
};
|
||||
}
|
||||
|
||||
// Component Life Cycle Functions
|
||||
|
||||
componentDidMount() {
|
||||
this._statusCheck();
|
||||
}
|
||||
|
||||
// Component Functions
|
||||
_statusCheck = async () => {
|
||||
const { username } = this.props;
|
||||
|
||||
await gameStatusCheck(username, 'spin')
|
||||
.then(res => {
|
||||
this.setState({
|
||||
gameRight: get(res, 'remaining', 0),
|
||||
nextDate: get(res, 'next_date', null),
|
||||
isLoading: false,
|
||||
});
|
||||
})
|
||||
.catch(err => {
|
||||
if (err) {
|
||||
Alert.alert(get(err, 'message') || err.toString());
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
_startGame = async type => {
|
||||
const { username } = this.props;
|
||||
let gameStatus;
|
||||
|
||||
await gameStatusCheck(username, type)
|
||||
.then(res => {
|
||||
gameStatus = res;
|
||||
})
|
||||
.catch(err => {
|
||||
if (err) {
|
||||
Alert.alert(get(err, 'message') || err.toString());
|
||||
}
|
||||
});
|
||||
|
||||
if (get(gameStatus, 'status') !== 18) {
|
||||
await gameClaim(username, type, get(gameStatus, 'key'))
|
||||
.then(res => {
|
||||
this.setState(
|
||||
{
|
||||
gameRight: get(gameStatus, 'status') !== 3 ? 0 : 5,
|
||||
score: get(res, 'score'),
|
||||
},
|
||||
() => this._statusCheck(),
|
||||
);
|
||||
})
|
||||
.catch(err => {
|
||||
if (err) {
|
||||
Alert.alert(get(err, 'message') || err.toString());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.setState({ nextDate: get(gameStatus, 'next_date'), gameRight: 0 });
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const { children } = this.props;
|
||||
const { score, gameRight, nextDate, isLoading } = this.state;
|
||||
|
||||
return (
|
||||
children &&
|
||||
children({
|
||||
score,
|
||||
startGame: this._startGame,
|
||||
gameRight,
|
||||
nextDate,
|
||||
isLoading,
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
username: state.account.currentAccount.name,
|
||||
});
|
||||
|
||||
export default withNavigation(connect(mapStateToProps)(injectIntl(RedeemContainer)));
|
@ -8,10 +8,10 @@ import ROUTES from '../constants/routeNames';
|
||||
import {
|
||||
Bookmarks,
|
||||
Boost,
|
||||
BoostPost,
|
||||
Drafts,
|
||||
Editor,
|
||||
Follows,
|
||||
SpinGame,
|
||||
Login,
|
||||
PinCode,
|
||||
Post,
|
||||
@ -40,7 +40,7 @@ const mainNavigation = createDrawerNavigator(
|
||||
},
|
||||
);
|
||||
|
||||
const stackNavigatior = createStackNavigator(
|
||||
const stackNavigator = createStackNavigator(
|
||||
{
|
||||
[ROUTES.DRAWER.MAIN]: {
|
||||
screen: mainNavigation,
|
||||
@ -132,6 +132,12 @@ const stackNavigatior = createStackNavigator(
|
||||
header: () => null,
|
||||
},
|
||||
},
|
||||
[ROUTES.SCREENS.SPIN_GAME]: {
|
||||
screen: SpinGame,
|
||||
navigationOptions: {
|
||||
header: () => null,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
headerMode: 'none',
|
||||
@ -139,7 +145,7 @@ const stackNavigatior = createStackNavigator(
|
||||
);
|
||||
|
||||
export default createSwitchNavigator({
|
||||
stackNavigatior,
|
||||
stackNavigator,
|
||||
[ROUTES.SCREENS.LOGIN]: { screen: Login },
|
||||
[ROUTES.SCREENS.PINCODE]: { screen: PinCode },
|
||||
[ROUTES.SCREENS.STEEM_CONNECT]: { screen: SteemConnect },
|
||||
|
@ -60,3 +60,27 @@ export const claim = username =>
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
|
||||
export const gameStatusCheck = (username, type) =>
|
||||
new Promise((resolve, reject) => {
|
||||
ePointApi
|
||||
.get(`/game/${username}`, { params: { type } })
|
||||
.then(res => {
|
||||
resolve(res.data);
|
||||
})
|
||||
.catch(error => {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
|
||||
export const gameClaim = (username, type, key) =>
|
||||
new Promise((resolve, reject) => {
|
||||
ePointApi
|
||||
.post(`/game/${username}?type=${type}`, { key })
|
||||
.then(res => {
|
||||
resolve(res.data);
|
||||
})
|
||||
.catch(error => {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
|
@ -357,7 +357,7 @@ export const getSCAccessToken = code =>
|
||||
api.post('/sc-token-refresh', { code }).then(resp => resolve(resp.data));
|
||||
});
|
||||
|
||||
export const getPromotePosts = () => api.get(`/promoted-posts`).then(resp => resp.data);
|
||||
export const getPromotePosts = () => api.get('/promoted-posts').then(resp => resp.data);
|
||||
|
||||
export const purchaseOrder = data => api.post('/purchase-order', data).then(resp => resp.data);
|
||||
|
||||
|
@ -1,34 +1,21 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import { View, Text } from 'react-native';
|
||||
import React from 'react';
|
||||
import { View, Platform } from 'react-native';
|
||||
import get from 'lodash/get';
|
||||
import { useIntl } from 'react-intl';
|
||||
|
||||
// Components
|
||||
import { BasicHeader, Icon, MainButton, BoostPlaceHolder } from '../../../components';
|
||||
import { BasicHeader, BoostPlaceHolder, ProductItemLine } from '../../../components';
|
||||
|
||||
// Container
|
||||
import { InAppPurchaseContainer } from '../../../containers';
|
||||
|
||||
// Styles
|
||||
import globalStyles from '../../../globalStyles';
|
||||
import styles from './boostScreenStyles';
|
||||
|
||||
const DEALS = { '9999points': 'BEST DEAL!', '4999points': 'POPULAR!' };
|
||||
|
||||
const _renderDeal = item => {
|
||||
if (DEALS[item.productId]) {
|
||||
return (
|
||||
<View style={styles.descriptionWrapper}>
|
||||
<Fragment>
|
||||
<Text style={styles.description}>{DEALS[item.productId]}</Text>
|
||||
<View style={styles.triangle} />
|
||||
</Fragment>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
const ITEM_SKUS = Platform.select({
|
||||
ios: ['099points', '199points', '499points', '999points', '4999points', '9999points'],
|
||||
android: ['099points', '199points', '499points', '999points', '4999points', '9999points'],
|
||||
});
|
||||
|
||||
const _getTitle = title => {
|
||||
let _title = title.toUpperCase();
|
||||
@ -44,7 +31,7 @@ const BoostScreen = () => {
|
||||
const intl = useIntl();
|
||||
|
||||
return (
|
||||
<InAppPurchaseContainer>
|
||||
<InAppPurchaseContainer skus={ITEM_SKUS}>
|
||||
{({ buyItem, productList, isLoading, isProcessing }) => (
|
||||
<View style={globalStyles.container}>
|
||||
<BasicHeader
|
||||
@ -57,35 +44,14 @@ const BoostScreen = () => {
|
||||
{isLoading ? (
|
||||
<BoostPlaceHolder />
|
||||
) : (
|
||||
productList.map(item => (
|
||||
<View style={styles.boostLine} key={get(item, 'productId')}>
|
||||
{_renderDeal(item)}
|
||||
<View style={styles.buttonWrapper}>
|
||||
<MainButton
|
||||
style={styles.button}
|
||||
onPress={() => buyItem(item.productId)}
|
||||
height={50}
|
||||
text={intl.formatMessage({
|
||||
id: 'boost.buy',
|
||||
})}
|
||||
isDisable={isProcessing}
|
||||
isLoading={false}
|
||||
>
|
||||
<View style={styles.buttonContent}>
|
||||
<Text style={styles.buttonText}>{_getTitle(get(item, 'title'))}</Text>
|
||||
<View style={styles.buttonIconWrapper}>
|
||||
<Icon name="add" iconType="MaterialIcons" color="#357ce6" size={23} />
|
||||
</View>
|
||||
</View>
|
||||
</MainButton>
|
||||
</View>
|
||||
|
||||
<View style={styles.priceWrapper}>
|
||||
{get(item, 'localizedPrice', null) && (
|
||||
<Text style={styles.priceText}>{get(item, 'localizedPrice', 0)}</Text>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
productList.map(product => (
|
||||
<ProductItemLine
|
||||
isLoading={isLoading}
|
||||
disabled={isProcessing}
|
||||
product={product}
|
||||
title={_getTitle(get(product, 'title'))}
|
||||
handleOnButtonPress={id => buyItem(id)}
|
||||
/>
|
||||
))
|
||||
)}
|
||||
</View>
|
||||
|
@ -11,6 +11,7 @@ import { Points } from './points';
|
||||
import { Post } from './post';
|
||||
import { SearchResult } from './searchResult';
|
||||
import { Settings } from './settings';
|
||||
import { SpinGame } from './spinGame/screen/spinGameScreen';
|
||||
import Boost from './boost/screen/boostScreen';
|
||||
import Profile from './profile/screen/profileScreen';
|
||||
import ProfileEdit from './profileEdit/screen/profileEditScreen';
|
||||
@ -39,6 +40,7 @@ export {
|
||||
Redeem,
|
||||
SearchResult,
|
||||
Settings,
|
||||
SpinGame,
|
||||
SteemConnect,
|
||||
Transfer,
|
||||
Voters,
|
||||
|
32
src/screens/spinGame/screen/spinGameScreen.js
Normal file
32
src/screens/spinGame/screen/spinGameScreen.js
Normal file
@ -0,0 +1,32 @@
|
||||
import React from 'react';
|
||||
|
||||
// Container
|
||||
import { SpinGameContainer, InAppPurchaseContainer } from '../../../containers';
|
||||
|
||||
import { SpinGame } from '../../../components';
|
||||
|
||||
const SpinGameScreen = () => {
|
||||
return (
|
||||
<SpinGameContainer>
|
||||
{({ startGame, score, gameRight, nextDate, isLoading, statusCheck }) => (
|
||||
<InAppPurchaseContainer fetchData={statusCheck} skus={['499spins']}>
|
||||
{({ buyItem, getItems, spinProduct, isProcessing }) => (
|
||||
<SpinGame
|
||||
buyItem={buyItem}
|
||||
isLoading={isLoading}
|
||||
score={score}
|
||||
startGame={startGame}
|
||||
gameRight={gameRight}
|
||||
nextDate={nextDate}
|
||||
getItems={getItems}
|
||||
isProcessing={isProcessing}
|
||||
spinProduct={spinProduct}
|
||||
/>
|
||||
)}
|
||||
</InAppPurchaseContainer>
|
||||
)}
|
||||
</SpinGameContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export { SpinGameScreen as SpinGame };
|
@ -12,15 +12,21 @@ const THIS_MONTH = moment()
|
||||
.startOf('day');
|
||||
|
||||
export const getTimeFromNow = (value, isWithoutUtc) => {
|
||||
if (!value) return null;
|
||||
if (!value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isWithoutUtc) return moment(value).fromNow();
|
||||
if (isWithoutUtc) {
|
||||
return moment(value).fromNow();
|
||||
}
|
||||
|
||||
return moment.utc(value).fromNow();
|
||||
};
|
||||
|
||||
export const getFormatedCreatedDate = value => {
|
||||
if (!value) return null;
|
||||
if (!value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return moment(value).format('DD MMM, YYYY');
|
||||
};
|
||||
@ -36,7 +42,9 @@ export const isThisWeek = value => moment(value).isSameOrAfter(THIS_WEEK);
|
||||
export const isThisMonth = value => moment(value).isSameOrAfter(THIS_MONTH);
|
||||
|
||||
export const isEmptyContentDate = value => {
|
||||
if (!value) return false;
|
||||
if (!value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return parseInt(value.split('-')[0], 10) < 1980;
|
||||
};
|
||||
|
29
yarn.lock
29
yarn.lock
@ -2693,7 +2693,12 @@ command-line-args@^4.0.6:
|
||||
find-replace "^1.0.3"
|
||||
typical "^2.6.1"
|
||||
|
||||
commander@^2.11.0, commander@^2.14.1, commander@^2.19.0, commander@^2.9.0, commander@~2.20.0:
|
||||
commander@2.20.0:
|
||||
version "2.20.0"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422"
|
||||
integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==
|
||||
|
||||
commander@^2.11.0, commander@^2.14.1, commander@^2.19.0, commander@^2.9.0:
|
||||
version "2.20.1"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.1.tgz#3863ce3ca92d0831dcf2a102f5fb4b5926afd0f9"
|
||||
integrity sha512-cCuLsMhJeWQ/ZpsFTbE765kvVfoeSddc4nU3up4fV+fDBcfUXnbITJ+JzhkdjzOqhURjZgujxaioam4RM9yGUg==
|
||||
@ -4627,9 +4632,9 @@ hoist-non-react-statics@^3.0.1, hoist-non-react-statics@^3.3.0:
|
||||
react-is "^16.7.0"
|
||||
|
||||
hosted-git-info@^2.1.4:
|
||||
version "2.8.4"
|
||||
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.4.tgz#44119abaf4bc64692a16ace34700fed9c03e2546"
|
||||
integrity sha512-pzXIvANXEFrc5oFFXRMkbLPQ2rXRoDERwDLyrcUxGhaZhgP54BBSl9Oheh7Vv0T090cszWBxPjkQQ5Sq1PbBRQ==
|
||||
version "2.8.5"
|
||||
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.5.tgz#759cfcf2c4d156ade59b0b2dfabddc42a6b9c70c"
|
||||
integrity sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg==
|
||||
|
||||
html-encoding-sniffer@^1.0.2:
|
||||
version "1.0.2"
|
||||
@ -7734,10 +7739,10 @@ react-native-gesture-handler@^1.4.1:
|
||||
invariant "^2.2.4"
|
||||
prop-types "^15.7.2"
|
||||
|
||||
react-native-iap@^3.3.8:
|
||||
version "3.5.9"
|
||||
resolved "https://registry.yarnpkg.com/react-native-iap/-/react-native-iap-3.5.9.tgz#1a49702f5c5ed444da9d3c7b8db9b5e7c7066deb"
|
||||
integrity sha512-LtL6NX4y8JCg9pjUDxMz2om03r0PaJHfzpT6Wd437ck5sr+cIAbC8QH5MgXUkyoBin+MxTSX0w92TbuZAeHp1Q==
|
||||
react-native-iap@3.4.15:
|
||||
version "3.4.15"
|
||||
resolved "https://registry.yarnpkg.com/react-native-iap/-/react-native-iap-3.4.15.tgz#0bf0f83c0591634ab562a5ec14d5a2b4e9c53c1d"
|
||||
integrity sha512-hqGvG2UNWi5zrb/BLtQ0V4Hdd3Odo3s5GcAKHESv03ZzMPMoPYyTZ4rk6vRclDBnaybiij9Pb70KYH/KCWRTUA==
|
||||
dependencies:
|
||||
dooboolab-welcome "^1.1.1"
|
||||
|
||||
@ -9478,11 +9483,11 @@ uglify-es@^3.1.9:
|
||||
source-map "~0.6.1"
|
||||
|
||||
uglify-js@^3.1.4:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.6.0.tgz#704681345c53a8b2079fb6cec294b05ead242ff5"
|
||||
integrity sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg==
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.6.1.tgz#ae7688c50e1bdcf2f70a0e162410003cf9798311"
|
||||
integrity sha512-+dSJLJpXBb6oMHP+Yvw8hUgElz4gLTh82XuX68QiJVTXaE5ibl6buzhNkQdYhBlIhozWOC9ge16wyRmjG4TwVQ==
|
||||
dependencies:
|
||||
commander "~2.20.0"
|
||||
commander "2.20.0"
|
||||
source-map "~0.6.1"
|
||||
|
||||
ultron@1.0.x:
|
||||
|
Loading…
Reference in New Issue
Block a user