Compare commits
2 commits
Author | SHA1 | Date | |
---|---|---|---|
|
1db0e9a09f | ||
|
63ba6ecf47 |
14 changed files with 514 additions and 15 deletions
4
package-lock.json
generated
4
package-lock.json
generated
|
@ -7076,8 +7076,8 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lbryinc": {
|
"lbryinc": {
|
||||||
"version": "github:lbryio/lbryinc#053ca52f4f7f9bf8eb62a3581b183671a475ad1c",
|
"version": "github:lbryio/lbryinc#138a053754ec8e3da8e9bf153d32f527c962f25c",
|
||||||
"from": "github:lbryio/lbryinc#053ca52f4f7f9bf8eb62a3581b183671a475ad1c",
|
"from": "github:lbryio/lbryinc#138a053754ec8e3da8e9bf153d32f527c962f25c",
|
||||||
"requires": {
|
"requires": {
|
||||||
"reselect": "^3.0.0"
|
"reselect": "^3.0.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
"@expo/vector-icons": "^8.1.0",
|
"@expo/vector-icons": "^8.1.0",
|
||||||
"gfycat-style-urls": "^1.0.3",
|
"gfycat-style-urls": "^1.0.3",
|
||||||
"lbry-redux": "lbryio/lbry-redux#c910cd2b80b165843a81fdf6ce96094429b94ec8",
|
"lbry-redux": "lbryio/lbry-redux#c910cd2b80b165843a81fdf6ce96094429b94ec8",
|
||||||
"lbryinc": "lbryio/lbryinc#053ca52f4f7f9bf8eb62a3581b183671a475ad1c",
|
"lbryinc": "lbryio/lbryinc#138a053754ec8e3da8e9bf153d32f527c962f25c",
|
||||||
"lodash": ">=4.17.11",
|
"lodash": ">=4.17.11",
|
||||||
"merge": ">=1.2.1",
|
"merge": ">=1.2.1",
|
||||||
"moment": "^2.22.1",
|
"moment": "^2.22.1",
|
||||||
|
|
|
@ -6,6 +6,7 @@ import DownloadsPage from 'page/downloads';
|
||||||
import DrawerContent from 'component/drawerContent';
|
import DrawerContent from 'component/drawerContent';
|
||||||
import FilePage from 'page/file';
|
import FilePage from 'page/file';
|
||||||
import FirstRunScreen from 'page/firstRun';
|
import FirstRunScreen from 'page/firstRun';
|
||||||
|
import InvitesPage from 'page/invites';
|
||||||
import PublishPage from 'page/publish';
|
import PublishPage from 'page/publish';
|
||||||
import PublishesPage from 'page/publishes';
|
import PublishesPage from 'page/publishes';
|
||||||
import RewardsPage from 'page/rewards';
|
import RewardsPage from 'page/rewards';
|
||||||
|
@ -210,6 +211,12 @@ const drawer = createDrawerNavigator(
|
||||||
drawerIcon: ({ tintColor }) => <Icon name="award" size={drawerIconSize} style={{ color: tintColor }} />,
|
drawerIcon: ({ tintColor }) => <Icon name="award" size={drawerIconSize} style={{ color: tintColor }} />,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Invites: {
|
||||||
|
screen: InvitesPage,
|
||||||
|
navigationOptions: {
|
||||||
|
drawerIcon: ({ tintColor }) => <Icon name="user-friends" size={drawerIconSize} style={{ color: tintColor }} />,
|
||||||
|
},
|
||||||
|
},
|
||||||
Downloads: {
|
Downloads: {
|
||||||
screen: DownloadsPage,
|
screen: DownloadsPage,
|
||||||
navigationOptions: {
|
navigationOptions: {
|
||||||
|
@ -530,7 +537,7 @@ class AppWithNavigationState extends React.Component {
|
||||||
try {
|
try {
|
||||||
verification = JSON.parse(atob(evt.url.substring(15)));
|
verification = JSON.parse(atob(evt.url.substring(15)));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
// console.log(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verification.token && verification.recaptcha) {
|
if (verification.token && verification.recaptcha) {
|
||||||
|
|
|
@ -36,10 +36,14 @@ export default class ChannelSelector extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
const { channels: prevChannels = [], channelName } = this.props;
|
const { channels: prevChannels = [], channelName: prevChannelName } = this.props;
|
||||||
const { channels = [] } = nextProps;
|
const { channels = [], channelName } = nextProps;
|
||||||
|
|
||||||
if (channels && channels.length !== prevChannels.length && channelName !== this.state.currentSelectedValue) {
|
if (channels && channels.length !== prevChannels.length && channelName !== this.state.currentSelectedValue) {
|
||||||
|
this.setState({ currentSelectedValue: prevChannelName });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (channelName !== prevChannelName) {
|
||||||
this.setState({ currentSelectedValue: channelName });
|
this.setState({ currentSelectedValue: channelName });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -189,10 +193,11 @@ export default class ChannelSelector extends React.PureComponent {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const channel = this.state.addingChannel ? 'new' : this.props.channel;
|
const channel = this.state.addingChannel ? 'new' : this.props.channel;
|
||||||
const { balance, enabled, fetchingChannels, channels = [] } = this.props;
|
const { balance, enabled, fetchingChannels, channels = [], showAnonymous } = this.props;
|
||||||
const pickerItems = [Constants.ITEM_ANONYMOUS, Constants.ITEM_CREATE_A_CHANNEL].concat(
|
const pickerItems = (showAnonymous
|
||||||
channels ? channels.map(ch => ch.name) : [],
|
? [Constants.ITEM_ANONYMOUS, Constants.ITEM_CREATE_A_CHANNEL]
|
||||||
);
|
: [Constants.ITEM_CREATE_A_CHANNEL]
|
||||||
|
).concat(channels ? channels.map(ch => ch.name) : []);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
newChannelName,
|
newChannelName,
|
||||||
|
|
|
@ -22,6 +22,7 @@ const groupedMenuItems = {
|
||||||
Wallet: [
|
Wallet: [
|
||||||
{ icon: 'wallet', label: 'Wallet', route: Constants.DRAWER_ROUTE_WALLET },
|
{ icon: 'wallet', label: 'Wallet', route: Constants.DRAWER_ROUTE_WALLET },
|
||||||
{ icon: 'award', label: 'Rewards', route: Constants.DRAWER_ROUTE_REWARDS },
|
{ icon: 'award', label: 'Rewards', route: Constants.DRAWER_ROUTE_REWARDS },
|
||||||
|
{ icon: 'user-friends', label: 'Invites', route: Constants.DRAWER_ROUTE_INVITES },
|
||||||
],
|
],
|
||||||
Settings: [
|
Settings: [
|
||||||
{ icon: 'cog', label: 'Settings', route: Constants.DRAWER_ROUTE_SETTINGS },
|
{ icon: 'cog', label: 'Settings', route: Constants.DRAWER_ROUTE_SETTINGS },
|
||||||
|
|
|
@ -90,6 +90,7 @@ const Constants = {
|
||||||
DRAWER_ROUTE_TAG: 'Tag',
|
DRAWER_ROUTE_TAG: 'Tag',
|
||||||
DRAWER_ROUTE_CHANNEL_CREATOR: 'ChannelCreator',
|
DRAWER_ROUTE_CHANNEL_CREATOR: 'ChannelCreator',
|
||||||
DRAWER_ROUTE_CHANNEL_CREATOR_FORM: 'ChannnelCreatorForm',
|
DRAWER_ROUTE_CHANNEL_CREATOR_FORM: 'ChannnelCreatorForm',
|
||||||
|
DRAWER_ROUTE_INVITES: 'Invites',
|
||||||
|
|
||||||
FULL_ROUTE_NAME_DISCOVER: 'DiscoverStack',
|
FULL_ROUTE_NAME_DISCOVER: 'DiscoverStack',
|
||||||
FULL_ROUTE_NAME_WALLET: 'WalletStack',
|
FULL_ROUTE_NAME_WALLET: 'WalletStack',
|
||||||
|
@ -165,6 +166,7 @@ export const DrawerRoutes = [
|
||||||
Constants.DRAWER_ROUTE_SEARCH,
|
Constants.DRAWER_ROUTE_SEARCH,
|
||||||
Constants.DRAWER_ROUTE_TRANSACTION_HISTORY,
|
Constants.DRAWER_ROUTE_TRANSACTION_HISTORY,
|
||||||
Constants.DRAWER_ROUTE_CHANNEL_CREATOR,
|
Constants.DRAWER_ROUTE_CHANNEL_CREATOR,
|
||||||
|
Constants.DRAWER_ROUTE_INVITES,
|
||||||
];
|
];
|
||||||
|
|
||||||
// sub-pages for main routes
|
// sub-pages for main routes
|
||||||
|
|
|
@ -931,7 +931,8 @@ export default class ChannelCreator extends React.PureComponent {
|
||||||
source={{ uri: thumbnailUrl }}
|
source={{ uri: thumbnailUrl }}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{(!!thumbnailUrl || thumbnailUrl.trim().length === 0) && newChannelName.length > 0 && (
|
{(!!thumbnailUrl || (!!thumbnailUrl && thumbnailUrl.trim().length === 0)) &&
|
||||||
|
newChannelName.length > 0 && (
|
||||||
<Text style={channelIconStyle.autothumbCharacter}>
|
<Text style={channelIconStyle.autothumbCharacter}>
|
||||||
{newChannelName.substring(0, 1).toUpperCase()}
|
{newChannelName.substring(0, 1).toUpperCase()}
|
||||||
</Text>
|
</Text>
|
||||||
|
|
46
src/page/invites/index.js
Normal file
46
src/page/invites/index.js
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { selectMyChannelClaims, selectFetchingMyChannels, doFetchChannelListMine, doToast } from 'lbry-redux';
|
||||||
|
import {
|
||||||
|
selectReferralReward,
|
||||||
|
selectUserInvitesRemaining,
|
||||||
|
selectUserInviteNewIsPending,
|
||||||
|
selectUserInviteNewErrorMessage,
|
||||||
|
selectUserInviteReferralLink,
|
||||||
|
selectUserInviteReferralCode,
|
||||||
|
selectUserInvitees,
|
||||||
|
selectUserInviteStatusIsPending,
|
||||||
|
doFetchInviteStatus,
|
||||||
|
doUserInviteNew,
|
||||||
|
} from 'lbryinc';
|
||||||
|
import { doPushDrawerStack, doPopDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
||||||
|
import { doUpdateChannelFormState, doClearChannelFormState } from 'redux/actions/form';
|
||||||
|
import { selectDrawerStack } from 'redux/selectors/drawer';
|
||||||
|
import { selectChannelFormState, selectHasChannelFormState } from 'redux/selectors/form';
|
||||||
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
|
import InvitesPage from './view';
|
||||||
|
|
||||||
|
const select = state => ({
|
||||||
|
channels: selectMyChannelClaims(state),
|
||||||
|
fetchingChannels: selectFetchingMyChannels(state),
|
||||||
|
fetchingInvitees: selectUserInviteStatusIsPending(state),
|
||||||
|
errorMessage: selectUserInviteNewErrorMessage(state),
|
||||||
|
invitesRemaining: selectUserInvitesRemaining(state),
|
||||||
|
referralCode: selectUserInviteReferralCode(state),
|
||||||
|
isPending: selectUserInviteNewIsPending(state),
|
||||||
|
invitees: selectUserInvitees(state),
|
||||||
|
referralReward: selectReferralReward(state),
|
||||||
|
});
|
||||||
|
|
||||||
|
const perform = dispatch => ({
|
||||||
|
fetchChannelListMine: () => dispatch(doFetchChannelListMine()),
|
||||||
|
fetchInviteStatus: () => dispatch(doFetchInviteStatus()),
|
||||||
|
inviteNew: email => dispatch(doUserInviteNew(email)),
|
||||||
|
pushDrawerStack: () => dispatch(doPushDrawerStack(Constants.DRAWER_ROUTE_INVITES)),
|
||||||
|
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),
|
||||||
|
notify: data => dispatch(doToast(data)),
|
||||||
|
});
|
||||||
|
|
||||||
|
export default connect(
|
||||||
|
select,
|
||||||
|
perform,
|
||||||
|
)(InvitesPage);
|
228
src/page/invites/view.js
Normal file
228
src/page/invites/view.js
Normal file
|
@ -0,0 +1,228 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { Lbry, parseURI } from 'lbry-redux';
|
||||||
|
import {
|
||||||
|
ActivityIndicator,
|
||||||
|
Clipboard,
|
||||||
|
NativeModules,
|
||||||
|
ScrollView,
|
||||||
|
Text,
|
||||||
|
TextInput,
|
||||||
|
TouchableOpacity,
|
||||||
|
View,
|
||||||
|
} from 'react-native';
|
||||||
|
import Colors from 'styles/colors';
|
||||||
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
|
import Icon from 'react-native-vector-icons/FontAwesome5';
|
||||||
|
import Link from 'component/link';
|
||||||
|
import Button from 'component/button';
|
||||||
|
import ChannelSelector from 'component/channelSelector';
|
||||||
|
import PageHeader from 'component/pageHeader';
|
||||||
|
import RewardCard from 'component/rewardCard';
|
||||||
|
import RewardEnrolment from 'component/rewardEnrolment';
|
||||||
|
import UriBar from 'component/uriBar';
|
||||||
|
import invitesStyle from 'styles/invites';
|
||||||
|
|
||||||
|
class InvitesPage extends React.PureComponent {
|
||||||
|
state = {
|
||||||
|
channelName: null,
|
||||||
|
email: null,
|
||||||
|
inviteLink: null,
|
||||||
|
selectedChannel: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
const { navigation } = this.props;
|
||||||
|
// this.didFocusListener = navigation.addListener('didFocus', this.onComponentFocused);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
if (this.didFocusListener) {
|
||||||
|
this.didFocusListener.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onComponentFocused = () => {
|
||||||
|
const { fetchChannelListMine, fetchInviteStatus, pushDrawerStack, navigation, setPlayerVisible, user } = this.props;
|
||||||
|
|
||||||
|
pushDrawerStack();
|
||||||
|
setPlayerVisible();
|
||||||
|
NativeModules.Firebase.setCurrentScreen('Invites').then(result => {
|
||||||
|
fetchChannelListMine();
|
||||||
|
fetchInviteStatus();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.onComponentFocused();
|
||||||
|
}
|
||||||
|
|
||||||
|
handleChannelChange = channelName => {
|
||||||
|
const { channels = [] } = this.props;
|
||||||
|
if (channels && channels.length > 0) {
|
||||||
|
const filtered = channels.filter(c => c.name === channelName);
|
||||||
|
if (filtered.length > 0) {
|
||||||
|
const channel = filtered[0];
|
||||||
|
this.setState({ channelName, inviteLink: this.getLinkForChannel(channel) });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
getLinkForChannel = channel => {
|
||||||
|
const { claimId, claimName } = parseURI(channel.permanent_url);
|
||||||
|
return `https://lbry.tv/$/invite/${claimName}:${claimId}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
handleInviteEmailChange = text => {
|
||||||
|
this.setState({ email: text });
|
||||||
|
};
|
||||||
|
|
||||||
|
handleInvitePress = () => {
|
||||||
|
const { inviteNew, notify } = this.props;
|
||||||
|
const { email } = this.state;
|
||||||
|
if (!email || email.indexOf('@') === -1) {
|
||||||
|
return notify({
|
||||||
|
message: __('Please enter a valid email address to send an invite to.'),
|
||||||
|
isError: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
inviteNew(email);
|
||||||
|
};
|
||||||
|
|
||||||
|
componentWillReceiveProps(nextProps) {
|
||||||
|
const { isPending: prevPending, notify } = this.props;
|
||||||
|
const { channels = [], isPending, errorMessage } = nextProps;
|
||||||
|
const { email } = this.state;
|
||||||
|
|
||||||
|
if (!this.state.channelName && channels && channels.length > 0) {
|
||||||
|
const firstChannel = channels[0];
|
||||||
|
this.setState({ channelName: firstChannel.name, inviteLink: this.getLinkForChannel(firstChannel) });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prevPending && !isPending) {
|
||||||
|
if (errorMessage && errorMessage.trim().length > 0) {
|
||||||
|
notify({ message: errorMessage, isError: true });
|
||||||
|
} else {
|
||||||
|
notify({ message: __(`${email} was invited to the LBRY party!`) });
|
||||||
|
this.setState({ email: null });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleInviteLinkPress = () => {
|
||||||
|
const { notify } = this.props;
|
||||||
|
Clipboard.setString(this.state.inviteLink);
|
||||||
|
notify({
|
||||||
|
message: __('Invite link copied'),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { fetchingInvitees, user, navigation, notify, isPending, invitees } = this.props;
|
||||||
|
const { email, inviteLink } = this.state;
|
||||||
|
const hasInvitees = invitees && invitees.length > 0;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={invitesStyle.container}>
|
||||||
|
<UriBar navigation={navigation} />
|
||||||
|
|
||||||
|
<ScrollView style={invitesStyle.scrollContainer}>
|
||||||
|
<TouchableOpacity style={invitesStyle.rewardDriverCard} onPress={() => navigation.navigate('Rewards')}>
|
||||||
|
<Icon name="award" size={16} style={invitesStyle.rewardDriverIcon} />
|
||||||
|
<Text style={invitesStyle.rewardDriverText}>{__('Earn rewards for inviting your friends.')}</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
|
||||||
|
<View style={invitesStyle.card}>
|
||||||
|
<Text style={invitesStyle.title}>{__('Invite Link')}</Text>
|
||||||
|
<Text style={invitesStyle.text}>
|
||||||
|
{__('Share this link with friends (or enemies) and get 20 LBC when they join lbry.tv')}
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<Text style={invitesStyle.subTitle}>{__('Your invite link')}</Text>
|
||||||
|
<View style={invitesStyle.row}>
|
||||||
|
<Text selectable numberOfLines={1} style={invitesStyle.inviteLink} onPress={this.handleInviteLinkPress}>
|
||||||
|
{this.state.inviteLink}
|
||||||
|
</Text>
|
||||||
|
<Button icon={'clipboard'} style={invitesStyle.button} onPress={this.handleInviteLinkPress} />
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<Text style={invitesStyle.customizeTitle}>{__('Customize invite link')}</Text>
|
||||||
|
<ChannelSelector
|
||||||
|
showAnonymous={false}
|
||||||
|
channelName={this.state.channelName}
|
||||||
|
onChannelChange={this.handleChannelChange}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={invitesStyle.card}>
|
||||||
|
<Text style={invitesStyle.title}>{__('Invite by Email')}</Text>
|
||||||
|
<Text style={invitesStyle.text}>
|
||||||
|
{__('Invite someone you know by email and earn 20 LBC when they join lbry.tv.')}
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<TextInput
|
||||||
|
style={invitesStyle.emailInput}
|
||||||
|
editable={!isPending}
|
||||||
|
value={this.state.email}
|
||||||
|
onChangeText={this.handleInviteEmailChange}
|
||||||
|
placeholder={__('imaginary@friend.com')}
|
||||||
|
underlineColorAndroid={Colors.NextLbryGreen}
|
||||||
|
/>
|
||||||
|
<View style={invitesStyle.rightRow}>
|
||||||
|
{isPending && (
|
||||||
|
<ActivityIndicator size={'small'} color={Colors.NextLbryGreen} style={invitesStyle.loading} />
|
||||||
|
)}
|
||||||
|
<Button
|
||||||
|
disabled={!email || email.indexOf('@') === -1 || isPending}
|
||||||
|
style={invitesStyle.button}
|
||||||
|
text={__('Invite')}
|
||||||
|
onPress={this.handleInvitePress}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={[invitesStyle.card, invitesStyle.lastCard]}>
|
||||||
|
<View style={invitesStyle.titleRow}>
|
||||||
|
<Text style={invitesStyle.titleCol}>{__('Invite History')}</Text>
|
||||||
|
{fetchingInvitees && <ActivityIndicator size={'small'} color={Colors.NextLbryGreen} />}
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<Text style={invitesStyle.text}>
|
||||||
|
{__(
|
||||||
|
'Earn 20 LBC for inviting a friend, an enemy, a frenemy, or an enefriend. Everyone needs content freedom.',
|
||||||
|
)}
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<View style={invitesStyle.invitees}>
|
||||||
|
{hasInvitees && (
|
||||||
|
<View style={invitesStyle.inviteesHeader}>
|
||||||
|
<Text style={invitesStyle.emailHeader} numberOfLines={1}>
|
||||||
|
{__('Email')}
|
||||||
|
</Text>
|
||||||
|
<Text style={invitesStyle.rewardHeader} numberOfLines={1}>
|
||||||
|
{__('Reward')}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
{hasInvitees &&
|
||||||
|
invitees.map(invitee => (
|
||||||
|
<View key={invitee.email} style={invitesStyle.inviteeItem}>
|
||||||
|
<Text style={invitesStyle.inviteeEmail} numberOfLines={1}>
|
||||||
|
{invitee.email}
|
||||||
|
</Text>
|
||||||
|
<Text style={invitesStyle.rewardStatus} numberOfLines={1}>
|
||||||
|
{invitee.invite_reward_claimed && __('Claimed')}
|
||||||
|
{!invitee.invite_reward_claimed &&
|
||||||
|
(invitee.invite_reward_claimable ? __('Claimable') : __('Unclaimable'))}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</ScrollView>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default InvitesPage;
|
|
@ -11,6 +11,10 @@ import RewardEnrolment from 'component/rewardEnrolment';
|
||||||
import UriBar from 'component/uriBar';
|
import UriBar from 'component/uriBar';
|
||||||
import rewardStyle from 'styles/reward';
|
import rewardStyle from 'styles/reward';
|
||||||
|
|
||||||
|
const FILTER_ALL = 'all';
|
||||||
|
const FILTER_AVAILABLE = 'available';
|
||||||
|
const FILTER_CLAIMED = 'claimed';
|
||||||
|
|
||||||
class RewardsPage extends React.PureComponent {
|
class RewardsPage extends React.PureComponent {
|
||||||
state = {
|
state = {
|
||||||
isEmailVerified: false,
|
isEmailVerified: false,
|
||||||
|
@ -19,6 +23,7 @@ class RewardsPage extends React.PureComponent {
|
||||||
verifyRequestStarted: false,
|
verifyRequestStarted: false,
|
||||||
revealVerification: true,
|
revealVerification: true,
|
||||||
firstRewardClaimed: false,
|
firstRewardClaimed: false,
|
||||||
|
currentFilter: FILTER_AVAILABLE,
|
||||||
};
|
};
|
||||||
|
|
||||||
scrollView = null;
|
scrollView = null;
|
||||||
|
@ -182,8 +187,13 @@ class RewardsPage extends React.PureComponent {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
setFilter = filter => {
|
||||||
|
this.setState({ currentFilter: filter });
|
||||||
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { user, navigation } = this.props;
|
const { user, navigation } = this.props;
|
||||||
|
const { currentFilter } = this.state;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={rewardStyle.container}>
|
<View style={rewardStyle.container}>
|
||||||
|
@ -197,8 +207,29 @@ class RewardsPage extends React.PureComponent {
|
||||||
style={rewardStyle.scrollContainer}
|
style={rewardStyle.scrollContainer}
|
||||||
contentContainerStyle={rewardStyle.scrollContentContainer}
|
contentContainerStyle={rewardStyle.scrollContentContainer}
|
||||||
>
|
>
|
||||||
{this.renderUnclaimedRewards()}
|
<View style={rewardStyle.filterHeader}>
|
||||||
{this.renderClaimedRewards()}
|
<Link
|
||||||
|
style={[rewardStyle.filterLink, currentFilter === FILTER_ALL ? rewardStyle.activeFilterLink : null]}
|
||||||
|
text={__('All')}
|
||||||
|
onPress={() => this.setFilter(FILTER_ALL)}
|
||||||
|
/>
|
||||||
|
<Link
|
||||||
|
style={[
|
||||||
|
rewardStyle.filterLink,
|
||||||
|
currentFilter === FILTER_AVAILABLE ? rewardStyle.activeFilterLink : null,
|
||||||
|
]}
|
||||||
|
text={__('Available')}
|
||||||
|
onPress={() => this.setFilter(FILTER_AVAILABLE)}
|
||||||
|
/>
|
||||||
|
<Link
|
||||||
|
style={[rewardStyle.filterLink, currentFilter === FILTER_CLAIMED ? rewardStyle.activeFilterLink : null]}
|
||||||
|
text={__('Claimed')}
|
||||||
|
onPress={() => this.setFilter(FILTER_CLAIMED)}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{(currentFilter === FILTER_AVAILABLE || currentFilter === FILTER_ALL) && this.renderUnclaimedRewards()}
|
||||||
|
{(currentFilter === FILTER_CLAIMED || currentFilter === FILTER_ALL) && this.renderClaimedRewards()}
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
|
|
@ -1,16 +1,26 @@
|
||||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
|
|
||||||
export const doPushDrawerStack = (routeName, params) => dispatch =>
|
export const doPushDrawerStack = (routeName, params) => dispatch => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: Constants.ACTION_PUSH_DRAWER_STACK,
|
type: Constants.ACTION_PUSH_DRAWER_STACK,
|
||||||
data: { routeName, params },
|
data: { routeName, params },
|
||||||
});
|
});
|
||||||
|
|
||||||
export const doPopDrawerStack = () => dispatch =>
|
if (window.persistor) {
|
||||||
|
window.persistor.flush();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const doPopDrawerStack = () => dispatch => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: Constants.ACTION_POP_DRAWER_STACK,
|
type: Constants.ACTION_POP_DRAWER_STACK,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (window.persistor) {
|
||||||
|
window.persistor.flush();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const doSetPlayerVisible = (visible, uri) => dispatch =>
|
export const doSetPlayerVisible = (visible, uri) => dispatch =>
|
||||||
dispatch({
|
dispatch({
|
||||||
type: Constants.ACTION_SET_PLAYER_VISIBLE,
|
type: Constants.ACTION_SET_PLAYER_VISIBLE,
|
||||||
|
|
150
src/styles/invites.js
Normal file
150
src/styles/invites.js
Normal file
|
@ -0,0 +1,150 @@
|
||||||
|
import { StyleSheet } from 'react-native';
|
||||||
|
import Colors from './colors';
|
||||||
|
|
||||||
|
const walletStyle = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: Colors.PageBackground,
|
||||||
|
},
|
||||||
|
scrollContainer: {
|
||||||
|
marginTop: 60,
|
||||||
|
},
|
||||||
|
row: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
button: {
|
||||||
|
backgroundColor: Colors.LbryGreen,
|
||||||
|
alignSelf: 'flex-start',
|
||||||
|
},
|
||||||
|
card: {
|
||||||
|
backgroundColor: Colors.White,
|
||||||
|
marginTop: 16,
|
||||||
|
marginLeft: 16,
|
||||||
|
marginRight: 16,
|
||||||
|
padding: 16,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
fontFamily: 'Inter-SemiBold',
|
||||||
|
fontSize: 20,
|
||||||
|
marginBottom: 8,
|
||||||
|
},
|
||||||
|
titleRow: {
|
||||||
|
alignItems: 'center',
|
||||||
|
flexDirection: 'row',
|
||||||
|
marginBottom: 8,
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
},
|
||||||
|
titleCol: {
|
||||||
|
fontFamily: 'Inter-SemiBold',
|
||||||
|
fontSize: 20,
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
fontFamily: 'Inter-Regular',
|
||||||
|
fontSize: 14,
|
||||||
|
},
|
||||||
|
link: {
|
||||||
|
color: Colors.LbryGreen,
|
||||||
|
fontFamily: 'Inter-Regular',
|
||||||
|
fontSize: 14,
|
||||||
|
},
|
||||||
|
smallText: {
|
||||||
|
fontFamily: 'Inter-Regular',
|
||||||
|
fontSize: 12,
|
||||||
|
},
|
||||||
|
rewardDriverCard: {
|
||||||
|
alignItems: 'center',
|
||||||
|
backgroundColor: Colors.RewardDriverBlue,
|
||||||
|
flexDirection: 'row',
|
||||||
|
padding: 16,
|
||||||
|
marginLeft: 16,
|
||||||
|
marginTop: 16,
|
||||||
|
marginRight: 16,
|
||||||
|
},
|
||||||
|
rewardDriverIcon: {
|
||||||
|
color: Colors.White,
|
||||||
|
marginRight: 8,
|
||||||
|
},
|
||||||
|
rewardDriverText: {
|
||||||
|
fontFamily: 'Inter-Regular',
|
||||||
|
color: Colors.White,
|
||||||
|
fontSize: 14,
|
||||||
|
},
|
||||||
|
subTitle: {
|
||||||
|
fontFamily: 'Inter-Regular',
|
||||||
|
fontSize: 14,
|
||||||
|
marginTop: 12,
|
||||||
|
marginBottom: 4,
|
||||||
|
},
|
||||||
|
customizeTitle: {
|
||||||
|
fontFamily: 'Inter-Regular',
|
||||||
|
fontSize: 14,
|
||||||
|
marginTop: 12,
|
||||||
|
},
|
||||||
|
inviteLink: {
|
||||||
|
fontFamily: 'Inter-Regular',
|
||||||
|
borderWidth: 1,
|
||||||
|
borderRadius: 16,
|
||||||
|
borderStyle: 'dashed',
|
||||||
|
borderColor: '#e1e1e1',
|
||||||
|
backgroundColor: '#f9f9f9',
|
||||||
|
paddingTop: 8,
|
||||||
|
paddingLeft: 8,
|
||||||
|
paddingRight: 8,
|
||||||
|
paddingBottom: 6,
|
||||||
|
width: '88%',
|
||||||
|
},
|
||||||
|
emailInput: {
|
||||||
|
fontFamily: 'Inter-Regular',
|
||||||
|
fontSize: 14,
|
||||||
|
},
|
||||||
|
rightRow: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'flex-end',
|
||||||
|
},
|
||||||
|
loading: {
|
||||||
|
marginRight: 8,
|
||||||
|
},
|
||||||
|
lastCard: {
|
||||||
|
marginBottom: 16,
|
||||||
|
},
|
||||||
|
invitees: {
|
||||||
|
marginTop: 8,
|
||||||
|
},
|
||||||
|
inviteesHeader: {
|
||||||
|
flex: 1,
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
marginBottom: 8,
|
||||||
|
},
|
||||||
|
emailHeader: {
|
||||||
|
fontFamily: 'Inter-SemiBold',
|
||||||
|
fontSize: 14,
|
||||||
|
width: '65%',
|
||||||
|
},
|
||||||
|
rewardHeader: {
|
||||||
|
fontFamily: 'Inter-SemiBold',
|
||||||
|
fontSize: 14,
|
||||||
|
width: '35%',
|
||||||
|
},
|
||||||
|
inviteeItem: {
|
||||||
|
flex: 1,
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
marginBottom: 8,
|
||||||
|
},
|
||||||
|
inviteeEmail: {
|
||||||
|
fontFamily: 'Inter-Regular',
|
||||||
|
fontSize: 12,
|
||||||
|
width: '65%',
|
||||||
|
},
|
||||||
|
rewardStatus: {
|
||||||
|
fontFamily: 'Inter-Regular',
|
||||||
|
fontSize: 12,
|
||||||
|
width: '35%',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default walletStyle;
|
|
@ -305,6 +305,23 @@ const rewardStyle = StyleSheet.create({
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
lineHeight: 16,
|
lineHeight: 16,
|
||||||
},
|
},
|
||||||
|
filterHeader: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
marginTop: 16,
|
||||||
|
marginLeft: 16,
|
||||||
|
marginRight: 16,
|
||||||
|
padding: 16,
|
||||||
|
backgroundColor: Colors.White,
|
||||||
|
},
|
||||||
|
filterLink: {
|
||||||
|
fontFamily: 'Inter-Regular',
|
||||||
|
fontSize: 14,
|
||||||
|
marginRight: 24,
|
||||||
|
},
|
||||||
|
activeFilterLink: {
|
||||||
|
fontFamily: 'Inter-SemiBold',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export default rewardStyle;
|
export default rewardStyle;
|
||||||
|
|
|
@ -10,6 +10,7 @@ const specialRouteMap = {
|
||||||
about: Constants.DRAWER_ROUTE_ABOUT,
|
about: Constants.DRAWER_ROUTE_ABOUT,
|
||||||
allContent: Constants.DRAWER_ROUTE_TRENDING,
|
allContent: Constants.DRAWER_ROUTE_TRENDING,
|
||||||
channels: Constants.DRAWER_ROUTE_CHANNEL_CREATOR,
|
channels: Constants.DRAWER_ROUTE_CHANNEL_CREATOR,
|
||||||
|
invites: Constants.DRAWER_ROUTE_INVITES,
|
||||||
library: Constants.DRAWER_ROUTE_MY_LBRY,
|
library: Constants.DRAWER_ROUTE_MY_LBRY,
|
||||||
publish: Constants.DRAWER_ROUTE_PUBLISH,
|
publish: Constants.DRAWER_ROUTE_PUBLISH,
|
||||||
publishes: Constants.DRAWER_ROUTE_PUBLISHES,
|
publishes: Constants.DRAWER_ROUTE_PUBLISHES,
|
||||||
|
|
Loading…
Reference in a new issue