additional rewards page changes and new verification flow
This commit is contained in:
parent
f1393ae707
commit
2c9c822784
11 changed files with 529 additions and 6 deletions
|
@ -11,6 +11,7 @@ import SettingsPage from 'page/settings';
|
|||
import SplashScreen from 'page/splash';
|
||||
import SubscriptionsPage from 'page/subscriptions';
|
||||
import TransactionHistoryPage from 'page/transactionHistory';
|
||||
import VerificationScreen from 'page/verification';
|
||||
import WalletPage from 'page/wallet';
|
||||
import SearchInput from 'component/searchInput';
|
||||
import {
|
||||
|
@ -212,10 +213,19 @@ const mainStackNavigator = new createStackNavigator({
|
|||
},
|
||||
Main: {
|
||||
screen: drawer
|
||||
},
|
||||
Verification: {
|
||||
screen: VerificationScreen,
|
||||
navigationOptions: {
|
||||
drawerLockMode: 'locked-closed'
|
||||
}
|
||||
}
|
||||
}, {
|
||||
headerMode: 'none'
|
||||
});
|
||||
|
||||
|
||||
|
||||
export const AppNavigator = mainStackNavigator;
|
||||
export const reactNavigationMiddleware = createReactNavigationReduxMiddleware(
|
||||
state => state.nav,
|
||||
|
|
17
app/src/component/rewardEnrolment/index.js
Normal file
17
app/src/component/rewardEnrolment/index.js
Normal file
|
@ -0,0 +1,17 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { doToast } from 'lbry-redux';
|
||||
import { doRewardList, selectUnclaimedRewardValue, selectFetchingRewards, selectUser } from 'lbryinc';
|
||||
import RewardEnrolment from './view';
|
||||
|
||||
const select = state => ({
|
||||
unclaimedRewardAmount: selectUnclaimedRewardValue(state),
|
||||
fetching: selectFetchingRewards(state),
|
||||
user: selectUser(state)
|
||||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
fetchRewards: () => dispatch(doRewardList()),
|
||||
notify: data => dispatch(doToast(data))
|
||||
});
|
||||
|
||||
export default connect(select, perform)(RewardEnrolment);
|
51
app/src/component/rewardEnrolment/view.js
Normal file
51
app/src/component/rewardEnrolment/view.js
Normal file
|
@ -0,0 +1,51 @@
|
|||
import React from 'react';
|
||||
import { NativeModules, Text, TouchableOpacity, View } from 'react-native';
|
||||
import AsyncStorage from '@react-native-community/async-storage';
|
||||
import Button from 'component/button';
|
||||
import Link from 'component/link';
|
||||
import Colors from 'styles/colors';
|
||||
import Icon from 'react-native-vector-icons/FontAwesome5';
|
||||
import rewardStyle from 'styles/reward';
|
||||
|
||||
class RewardEnrolment extends React.Component {
|
||||
componentDidMount() {
|
||||
this.props.fetchRewards();
|
||||
}
|
||||
|
||||
onNotInterestedPressed = () => {
|
||||
const { navigation } = this.props;
|
||||
navigation.navigate({ routeName: 'DiscoverStack' })
|
||||
}
|
||||
|
||||
onEnrollPressed = () => {
|
||||
const { navigation } = this.props;
|
||||
navigation.navigate({ routeName: 'Verification' })
|
||||
}
|
||||
|
||||
render() {
|
||||
const { fetching, navigation, unclaimedRewardAmount, user } = this.props;
|
||||
|
||||
return (
|
||||
<View style={rewardStyle.enrollContainer} onPress>
|
||||
<View style={rewardStyle.summaryRow}>
|
||||
<Icon name="award" size={36} color={Colors.White} />
|
||||
<Text style={rewardStyle.summaryText}>
|
||||
{unclaimedRewardAmount} unclaimed credits
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
<View style={rewardStyle.onboarding}>
|
||||
<Text style={rewardStyle.enrollDescText}>LBRY credits allow you to purchase content, publish content, and influence the network. You can start earning credits by watching videos on LBRY.</Text>
|
||||
</View>
|
||||
|
||||
<View style={rewardStyle.buttonRow}>
|
||||
<Link style={rewardStyle.notInterestedLink} text={"Not interested"} onPress={this.onNotInterestedPressed} />
|
||||
<Button style={rewardStyle.enrollButton} theme={"light"} text={"Enroll"} onPress={this.onEnrollPressed} />
|
||||
</View>
|
||||
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default RewardEnrolment;
|
|
@ -4,6 +4,12 @@ const Constants = {
|
|||
FIRST_RUN_PAGE_WALLET: "wallet",
|
||||
FIRST_RUN_PAGE_SKIP_ACCOUNT: "skip-account",
|
||||
|
||||
VERIFY_PAGE_EMAIL: "email-verify",
|
||||
VERIFY_PAGE_PHONE_NUMBER: "phone-number-verify",
|
||||
|
||||
PHASE_COLLECTION: "collection",
|
||||
PHASE_VERIFICATION: "verification",
|
||||
|
||||
CONTENT_TAB: "content",
|
||||
ABOUT_TAB: "about",
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ import PhoneNumberRewardSubcard from 'component/phoneNumberRewardSubcard';
|
|||
import EmailRewardSubcard from 'component/emailRewardSubcard';
|
||||
import PageHeader from 'component/pageHeader';
|
||||
import RewardCard from 'component/rewardCard';
|
||||
import RewardEnrolment from 'component/rewardEnrolment';
|
||||
import RewardSummary from 'component/rewardSummary';
|
||||
import UriBar from 'component/uriBar';
|
||||
import rewardStyle from 'styles/reward';
|
||||
|
@ -153,7 +154,10 @@ class RewardsPage extends React.PureComponent {
|
|||
return (
|
||||
<View style={rewardStyle.container}>
|
||||
<UriBar navigation={navigation} />
|
||||
<ScrollView
|
||||
{!this.state.isRewardApproved && <RewardEnrolment navigation={navigation} />}
|
||||
|
||||
|
||||
{this.state.isRewardApproved && <ScrollView
|
||||
ref={ref => this.scrollView = ref}
|
||||
keyboardShouldPersistTaps={'handled'}
|
||||
style={rewardStyle.scrollContainer}
|
||||
|
@ -162,7 +166,7 @@ class RewardsPage extends React.PureComponent {
|
|||
{this.state.revealVerification && this.renderVerification()}
|
||||
{this.renderUnclaimedRewards()}
|
||||
{this.renderClaimedRewards()}
|
||||
</ScrollView>
|
||||
</ScrollView>}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
|
26
app/src/page/verification/index.js
Normal file
26
app/src/page/verification/index.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { doToast } from 'lbry-redux';
|
||||
import {
|
||||
doUserEmailNew,
|
||||
doUserEmailToVerify,
|
||||
selectEmailNewErrorMessage,
|
||||
selectEmailNewIsPending,
|
||||
selectEmailToVerify,
|
||||
doUserResendVerificationEmail,
|
||||
} from 'lbryinc';
|
||||
import Verification from './view';
|
||||
|
||||
const select = (state) => ({
|
||||
emailToVerify: selectEmailToVerify(state),
|
||||
emailNewErrorMessage: selectEmailNewErrorMessage(state),
|
||||
emailNewPending: selectEmailNewIsPending(state),
|
||||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
addUserEmail: email => dispatch(doUserEmailNew(email)),
|
||||
notify: data => dispatch(doToast(data)),
|
||||
setEmailToVerify: email => dispatch(doUserEmailToVerify(email)),
|
||||
resendVerificationEmail: email => dispatch(doUserResendVerificationEmail(email))
|
||||
});
|
||||
|
||||
export default connect(select, perform)(Verification);
|
132
app/src/page/verification/internal/email-verify-page.js
Normal file
132
app/src/page/verification/internal/email-verify-page.js
Normal file
|
@ -0,0 +1,132 @@
|
|||
import React from 'react';
|
||||
import { Lbry } from 'lbry-redux';
|
||||
import { ActivityIndicator, View, Text, TextInput } from 'react-native';
|
||||
import AsyncStorage from '@react-native-community/async-storage';
|
||||
import Button from 'component/button';
|
||||
import Link from 'component/link';
|
||||
import Colors from 'styles/colors';
|
||||
import Constants from 'constants';
|
||||
import firstRunStyle from 'styles/firstRun';
|
||||
import rewardStyle from 'styles/reward';
|
||||
|
||||
class EmailVerifyPage extends React.PureComponent {
|
||||
state = {
|
||||
email: null,
|
||||
phase: Constants.PHASE_COLLECTION,
|
||||
placeholder: 'you@example.com',
|
||||
verifyStarted: false,
|
||||
previousEmail: null
|
||||
}
|
||||
|
||||
handleChangeText = (text) => {
|
||||
this.setState({ email: text });
|
||||
AsyncStorage.setItem(Constants.KEY_FIRST_RUN_EMAIL, text);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const { emailNewErrorMessage, emailNewPending, emailToVerify } = nextProps;
|
||||
const { notify } = this.props;
|
||||
|
||||
if (this.state.verifyStarted && !emailNewPending) {
|
||||
if (emailNewErrorMessage) {
|
||||
notify({ message: String(emailNewErrorMessage), isError: true });
|
||||
this.setState({ verifyStarted: false });
|
||||
} else {
|
||||
this.setState({ phase: Constants.PHASE_VERIFICATION });
|
||||
//notify({ message: 'Please follow the instructions in the email sent to your address to continue.' });
|
||||
AsyncStorage.setItem(Constants.KEY_EMAIL_VERIFY_PENDING, 'true');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onSendVerificationPressed = () => {
|
||||
const { addUserEmail, emailNewPending, notify } = this.props;
|
||||
|
||||
if (emailNewPending) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { email } = this.state;
|
||||
if (!email || email.trim().length === 0 || email.indexOf('@') === -1) {
|
||||
return notify({
|
||||
message: 'Please provide a valid email address to continue.',
|
||||
});
|
||||
}
|
||||
|
||||
if (this.state.previousEmail === this.state.email) {
|
||||
// resend
|
||||
resendVerificationEmail(this.state.email);
|
||||
AsyncStorage.setItem(Constants.KEY_EMAIL_VERIFY_PENDING, 'true');
|
||||
this.setState({ verifyStarted: true, phase: Constants.PHASE_VERIFICATION });
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({ verifyStarted: true });
|
||||
addUserEmail(email);
|
||||
}
|
||||
|
||||
onResendPressed = () => {
|
||||
const { resendVerificationEmail, notify } = this.props;
|
||||
// resend verification email if there was one previously set (and it wasn't changed)
|
||||
resendVerificationEmail(this.state.email);
|
||||
AsyncStorage.setItem(Constants.KEY_EMAIL_VERIFY_PENDING, 'true');
|
||||
notify({ message: 'Please follow the instructions in the email sent to your address to continue.' });
|
||||
}
|
||||
|
||||
onEditPressed = () => {
|
||||
this.setState({ verifyStarted: false, phase: Constants.PHASE_COLLECTION, previousEmail: this.state.email });
|
||||
}
|
||||
|
||||
render() {
|
||||
const { emailNewPending } = this.props;
|
||||
|
||||
return (
|
||||
<View style={firstRunStyle.container}>
|
||||
<Text style={rewardStyle.verificationTitle}>{(Constants.PHASE_COLLECTION === this.state.phase) ? 'Email' : 'Verify Email'}</Text>
|
||||
{(Constants.PHASE_COLLECTION === this.state.phase) &&
|
||||
<View>
|
||||
<Text style={firstRunStyle.paragraph}>Please provide an email address.</Text>
|
||||
<TextInput style={firstRunStyle.emailInput}
|
||||
placeholder={this.state.placeholder}
|
||||
underlineColorAndroid="transparent"
|
||||
value={this.state.email}
|
||||
onChangeText={text => this.handleChangeText(text)}
|
||||
onFocus={() => {
|
||||
if (!this.state.email || this.state.email.length === 0) {
|
||||
this.setState({ placeholder: '' });
|
||||
}
|
||||
}}
|
||||
onBlur={() => {
|
||||
if (!this.state.email || this.state.email.length === 0) {
|
||||
this.setState({ placeholder: 'you@example.com' });
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<View style={rewardStyle.buttonContainer}>
|
||||
{!this.state.verifyStarted &&
|
||||
<Button
|
||||
style={rewardStyle.verificationButton}
|
||||
theme={"light"}
|
||||
text={"Send verification email"}
|
||||
onPress={this.onSendVerificationPressed} />}
|
||||
{this.state.verifyStarted && emailNewPending &&
|
||||
<ActivityIndicator size={"small"} color={Colors.White} style={rewardStyle.loading} />}
|
||||
</View>
|
||||
</View>}
|
||||
|
||||
{(Constants.PHASE_VERIFICATION === this.state.phase) &&
|
||||
<View>
|
||||
<Text style={firstRunStyle.paragraph}>An email has been sent to {this.state.email}.</Text>
|
||||
|
||||
<View style={rewardStyle.buttonContainer}>
|
||||
<Button style={rewardStyle.verificationButton} theme={"light"} text={"Resend"} onPress={this.onResendPressed} />
|
||||
<Link style={rewardStyle.verificationLink} text={"Edit"} onPress={this.onEditPressed} />
|
||||
</View>
|
||||
</View>
|
||||
}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default EmailVerifyPage;
|
206
app/src/page/verification/view.js
Normal file
206
app/src/page/verification/view.js
Normal file
|
@ -0,0 +1,206 @@
|
|||
import React from 'react';
|
||||
import { Lbry } from 'lbry-redux';
|
||||
import {
|
||||
ActivityIndicator,
|
||||
Linking,
|
||||
NativeModules,
|
||||
Text,
|
||||
TouchableOpacity,
|
||||
View
|
||||
} from 'react-native';
|
||||
import { NavigationActions, StackActions } from 'react-navigation';
|
||||
import AsyncStorage from '@react-native-community/async-storage';
|
||||
import Colors from 'styles/colors';
|
||||
import Constants from 'constants';
|
||||
import EmailVerifyPage from './internal/email-verify-page';
|
||||
import firstRunStyle from 'styles/firstRun';
|
||||
|
||||
class VerificationScreen extends React.PureComponent {
|
||||
state = {
|
||||
currentPage: null,
|
||||
emailSubmitted: false,
|
||||
isFirstRun: false,
|
||||
launchUrl: null,
|
||||
showSkip: false,
|
||||
skipAccountConfirmed: false,
|
||||
showBottomContainer: true,
|
||||
walletPassword: null
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
const { navigation } = this.props;
|
||||
|
||||
this.setState({ currentPage: 'emailVerify' });
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const { emailNewErrorMessage, emailNewPending } = nextProps;
|
||||
const { notify } = this.props;
|
||||
|
||||
/*if (this.state.emailSubmitted && !emailNewPending) {
|
||||
this.setState({ emailSubmitted: false });
|
||||
if (emailNewErrorMessage) {
|
||||
notify ({ message: String(emailNewErrorMessage), isError: true });
|
||||
} else {
|
||||
// Request successful. Navigate to next page (wallet).
|
||||
this.showNextPage();
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
handleLeftButtonPressed = () => {
|
||||
/*// Go to setup account page when "Setup account" is pressed
|
||||
if (Constants.FIRST_RUN_PAGE_SKIP_ACCOUNT === this.state.currentPage) {
|
||||
return this.showPage(Constants.FIRST_RUN_PAGE_EMAIL_COLLECT);
|
||||
}
|
||||
|
||||
// Go to skip account page when "No, thanks" is pressed
|
||||
if (Constants.FIRST_RUN_PAGE_EMAIL_COLLECT === this.state.currentPage) {
|
||||
this.showPage(Constants.FIRST_RUN_PAGE_SKIP_ACCOUNT);
|
||||
}*/
|
||||
}
|
||||
|
||||
handleContinuePressed = () => {
|
||||
/*const { notify } = this.props;
|
||||
const pageIndex = FirstRunScreen.pages.indexOf(this.state.currentPage);
|
||||
if (Constants.FIRST_RUN_PAGE_WALLET === this.state.currentPage) {
|
||||
if (!this.state.walletPassword || this.state.walletPassword.trim().length < 6) {
|
||||
return notify({ message: 'Your wallet password should be at least 6 characters long' });
|
||||
}
|
||||
|
||||
this.closeFinalPage();
|
||||
return;
|
||||
}
|
||||
|
||||
if (Constants.FIRST_RUN_PAGE_SKIP_ACCOUNT === this.state.currentPage && !this.state.skipAccountConfirmed) {
|
||||
notify({ message: 'Please confirm that you want to use LBRY without creating an account.' });
|
||||
return;
|
||||
}
|
||||
|
||||
if (Constants.FIRST_RUN_PAGE_EMAIL_COLLECT !== this.state.currentPage && pageIndex === (FirstRunScreen.pages.length - 1)) {
|
||||
this.closeFinalPage();
|
||||
} else {
|
||||
// TODO: Actions and page verification for specific pages
|
||||
if (Constants.FIRST_RUN_PAGE_EMAIL_COLLECT === this.state.currentPage) {
|
||||
// handle email collect
|
||||
this.handleEmailCollectPageContinue();
|
||||
} else {
|
||||
this.showNextPage();
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
handleEmailCollectPageContinue() {
|
||||
/*const { notify, addUserEmail } = this.props;
|
||||
|
||||
AsyncStorage.getItem(Constants.KEY_FIRST_RUN_EMAIL).then(email => {
|
||||
// validate the email
|
||||
if (!email || email.indexOf('@') === -1) {
|
||||
return notify({
|
||||
message: 'Please provide a valid email address to continue.',
|
||||
});
|
||||
}
|
||||
|
||||
addUserEmail(email);
|
||||
this.setState({ emailSubmitted: true });
|
||||
});*/
|
||||
}
|
||||
|
||||
showNextPage() {
|
||||
const pageIndex = FirstRunScreen.pages.indexOf(this.state.currentPage);
|
||||
const nextPage = FirstRunScreen.pages[pageIndex + 1];
|
||||
this.setState({ currentPage: nextPage });
|
||||
if (nextPage === 'email-collect') {
|
||||
// do not show the buttons (because we're waiting to get things ready)
|
||||
this.setState({ showBottomContainer: false });
|
||||
}
|
||||
}
|
||||
|
||||
showPage(pageName) {
|
||||
const pageIndex = FirstRunScreen.pages.indexOf(pageName);
|
||||
if (pageIndex > -1) {
|
||||
this.setState({ currentPage: pageName });
|
||||
}
|
||||
}
|
||||
|
||||
closeFinalPage() {
|
||||
// Final page. Let the app know that first run experience is completed.
|
||||
if (NativeModules.FirstRun) {
|
||||
NativeModules.FirstRun.firstRunCompleted();
|
||||
}
|
||||
|
||||
// Navigate to the splash screen
|
||||
this.launchSplashScreen();
|
||||
}
|
||||
|
||||
onEmailChanged = (email) => {
|
||||
if (Constants.FIRST_RUN_PAGE_EMAIL_COLLECT == this.state.currentPage) {
|
||||
this.setState({ showSkip: (!email || email.trim().length === 0) });
|
||||
} else {
|
||||
this.setState({ showSkip: false });
|
||||
}
|
||||
}
|
||||
|
||||
onEmailViewLayout = () => {
|
||||
this.setState({ showBottomContainer: true });
|
||||
AsyncStorage.getItem('firstRunEmail').then(email => {
|
||||
this.setState({ showSkip: !email || email.trim().length === 0 });
|
||||
});
|
||||
}
|
||||
|
||||
onCloseButtonPressed = () => {
|
||||
const { navigation } = this.props;
|
||||
navigation.goBack();
|
||||
}
|
||||
|
||||
onWalletPasswordChanged = (password) => {
|
||||
this.setState({ walletPassword: password });
|
||||
}
|
||||
|
||||
onWalletViewLayout = () => {
|
||||
this.setState({ showBottomContainer: true });
|
||||
}
|
||||
|
||||
onSkipSwitchChanged = (checked) => {
|
||||
this.setState({ skipAccountConfirmed: checked });
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
addUserEmail,
|
||||
emailNewErrorMessage,
|
||||
emailNewPending,
|
||||
emailToVerify,
|
||||
notify,
|
||||
resendVerificationEmail
|
||||
} = this.props;
|
||||
|
||||
let page = null;
|
||||
switch (this.state.currentPage) {
|
||||
case 'emailVerify':
|
||||
page = (
|
||||
<EmailVerifyPage
|
||||
addUserEmail={addUserEmail}
|
||||
emailNewErrorMessage={emailNewErrorMessage}
|
||||
emailNewPending={emailNewPending}
|
||||
emailToVerify={emailToVerify}
|
||||
notify={notify}
|
||||
resendVerificationEmail={resendVerificationEmail}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={firstRunStyle.screenContainer}>
|
||||
{page}
|
||||
|
||||
<TouchableOpacity style={firstRunStyle.closeButton} onPress={this.onCloseButtonPressed}>
|
||||
<Text style={firstRunStyle.closeButtonText}>x</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default VerificationScreen;
|
|
@ -129,6 +129,20 @@ const firstRunStyle = StyleSheet.create({
|
|||
},
|
||||
titleIcon: {
|
||||
marginTop: 8
|
||||
},
|
||||
closeButton: {
|
||||
position: 'absolute',
|
||||
top: 8,
|
||||
right: 8,
|
||||
width: 48,
|
||||
height: 48,
|
||||
borderRadius: 48,
|
||||
justifyContent: 'center'
|
||||
},
|
||||
closeButtonText: {
|
||||
alignSelf: 'center',
|
||||
color: Colors.White,
|
||||
fontSize: 16
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -27,6 +27,24 @@ const rewardStyle = StyleSheet.create({
|
|||
justifyContent: 'center',
|
||||
flexDirection: 'row'
|
||||
},
|
||||
enrollContainer: {
|
||||
flex: 1,
|
||||
marginTop: 76,
|
||||
marginLeft: 16,
|
||||
marginRight: 16,
|
||||
marginBottom: 16,
|
||||
padding: 24,
|
||||
backgroundColor: Colors.LbryGreen
|
||||
},
|
||||
onboarding: {
|
||||
marginTop: 36
|
||||
},
|
||||
enrollDescText: {
|
||||
fontFamily: 'Inter-UI-Regular',
|
||||
fontSize: 18,
|
||||
lineHeight: 28,
|
||||
color: Colors.White
|
||||
},
|
||||
rewardsContainer: {
|
||||
flex: 1
|
||||
},
|
||||
|
@ -202,12 +220,24 @@ const rewardStyle = StyleSheet.create({
|
|||
smsPermissionContainer: {
|
||||
marginBottom: 32
|
||||
},
|
||||
dismissButton: {
|
||||
alignSelf: 'flex-end',
|
||||
buttonRow: {
|
||||
width: '100%',
|
||||
position: 'absolute',
|
||||
alignItems: 'center',
|
||||
left: 24,
|
||||
bottom: 24,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between'
|
||||
},
|
||||
notInterestedLink: {
|
||||
fontSize: 14,
|
||||
fontFamily: 'Inter-UI-Regular',
|
||||
color: Colors.White
|
||||
},
|
||||
enrollButton: {
|
||||
backgroundColor: Colors.White,
|
||||
paddingLeft: 16,
|
||||
paddingRight: 16,
|
||||
marginTop: 8,
|
||||
paddingRight: 16
|
||||
},
|
||||
customCodeInput: {
|
||||
fontFamily: 'Inter-UI-Regular',
|
||||
|
@ -222,6 +252,32 @@ const rewardStyle = StyleSheet.create({
|
|||
},
|
||||
failureFootnote: {
|
||||
marginTop: 12
|
||||
},
|
||||
buttonContainer: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
width: '100%',
|
||||
paddingLeft: 32,
|
||||
paddingRight: 32,
|
||||
marginTop: 24
|
||||
},
|
||||
verificationTitle: {
|
||||
fontSize: 32,
|
||||
color: Colors.White,
|
||||
fontFamily: 'Inter-UI-Regular',
|
||||
marginLeft: 32,
|
||||
marginRight: 32,
|
||||
marginBottom: 24
|
||||
},
|
||||
verificationButton: {
|
||||
backgroundColor: Colors.White,
|
||||
paddingLeft: 16,
|
||||
paddingRight: 16
|
||||
},
|
||||
verificationLink: {
|
||||
color: Colors.White,
|
||||
fontSize: 14
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -55,6 +55,7 @@ public class FirebaseModule extends ReactContextBaseJavaModule {
|
|||
@ReactMethod
|
||||
public void logException(boolean fatal, String message, ReadableMap payload) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("message", message);
|
||||
if (payload != null) {
|
||||
HashMap<String, Object> payloadMap = payload.toHashMap();
|
||||
for (Map.Entry<String, Object> entry : payloadMap.entrySet()) {
|
||||
|
|
Loading…
Add table
Reference in a new issue