Mobile subscriptions (#382)
* add subscribe button to file page * add My Subscriptions page * get module resolve babel plugin working to eliminate ugly imports
This commit is contained in:
parent
0cc2b4e368
commit
6991b99ea9
18 changed files with 414 additions and 28 deletions
8
app/.babelrc
Normal file
8
app/.babelrc
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"presets": ["react-native"],
|
||||
"plugins": [
|
||||
["module-resolver", {
|
||||
root: ["./src"],
|
||||
}],
|
||||
]
|
||||
}
|
111
app/package-lock.json
generated
111
app/package-lock.json
generated
|
@ -644,6 +644,56 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"@expo/vector-icons": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@expo/vector-icons/-/vector-icons-8.1.0.tgz",
|
||||
"integrity": "sha512-/aKa+bgp3LIcTKJWPLRYTYCL0wf/Fr4dwl4XYmNGFG092pK3McuBoDk3b8tWyZnXBnEiqnMLd6Qwr+LEX6Jc0Q==",
|
||||
"requires": {
|
||||
"lodash": "^4.17.4",
|
||||
"react-native-vector-icons": "6.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"prop-types": {
|
||||
"version": "15.6.2",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz",
|
||||
"integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==",
|
||||
"requires": {
|
||||
"loose-envify": "^1.3.1",
|
||||
"object-assign": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"react-native-vector-icons": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/react-native-vector-icons/-/react-native-vector-icons-6.0.0.tgz",
|
||||
"integrity": "sha512-uF3oWb3TV42uXi2apVOZHw9oy9Nr5SXDVwOo1umQWo/yYCrDzXyVfq14DzezgEbJ9jfc/yghBelj0agkXmOKlg==",
|
||||
"requires": {
|
||||
"lodash": "^4.0.0",
|
||||
"prop-types": "^15.6.2",
|
||||
"yargs": "^8.0.2"
|
||||
}
|
||||
},
|
||||
"yargs": {
|
||||
"version": "8.0.2",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz",
|
||||
"integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=",
|
||||
"requires": {
|
||||
"camelcase": "^4.1.0",
|
||||
"cliui": "^3.2.0",
|
||||
"decamelize": "^1.1.1",
|
||||
"get-caller-file": "^1.0.1",
|
||||
"os-locale": "^2.0.0",
|
||||
"read-pkg-up": "^2.0.0",
|
||||
"require-directory": "^2.1.1",
|
||||
"require-main-filename": "^1.0.1",
|
||||
"set-blocking": "^2.0.0",
|
||||
"string-width": "^2.0.0",
|
||||
"which-module": "^2.0.0",
|
||||
"y18n": "^3.2.1",
|
||||
"yargs-parser": "^7.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"absolute-path": {
|
||||
"version": "0.0.0",
|
||||
"resolved": "https://registry.npmjs.org/absolute-path/-/absolute-path-0.0.0.tgz",
|
||||
|
@ -1312,6 +1362,19 @@
|
|||
"babel-runtime": "^6.22.0"
|
||||
}
|
||||
},
|
||||
"babel-plugin-module-resolver": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-3.1.1.tgz",
|
||||
"integrity": "sha512-1Q77Al4ydp6nYApJ7sQ2fmgz30WuQgJZegIYuyOdbdpxenB/bSezQ3hDPsumIXGlUS4vUIv+EwFjzzXZNWtARw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"find-babel-config": "^1.1.0",
|
||||
"glob": "^7.1.2",
|
||||
"pkg-up": "^2.0.0",
|
||||
"reselect": "^3.0.1",
|
||||
"resolve": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"babel-plugin-react-transform": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-react-transform/-/babel-plugin-react-transform-3.0.0.tgz",
|
||||
|
@ -2099,6 +2162,11 @@
|
|||
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.28.tgz",
|
||||
"integrity": "sha512-OJT3rzgtsYca/5WmmEuFJDPMwROVh5SSjoEX9wIrpfbbWJ4KqRzShs8Cj6jWHaatBYAeWngBA+kmmrcHSklT1g=="
|
||||
},
|
||||
"bluebird": {
|
||||
"version": "3.5.3",
|
||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz",
|
||||
"integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw=="
|
||||
},
|
||||
"bplist-creator": {
|
||||
"version": "0.0.7",
|
||||
"resolved": "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.0.7.tgz",
|
||||
|
@ -2822,6 +2890,16 @@
|
|||
"unpipe": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"find-babel-config": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/find-babel-config/-/find-babel-config-1.1.0.tgz",
|
||||
"integrity": "sha1-rMAQQ6Z0n+w0Qpvmtk9ULrtdY1U=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"json5": "^0.5.1",
|
||||
"path-exists": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"find-cache-dir": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz",
|
||||
|
@ -3998,20 +4076,27 @@
|
|||
}
|
||||
},
|
||||
"lbryinc": {
|
||||
"version": "github:lbryio/lbryinc#82308ece97188747adbf6d71d55b6e7a6fa0bd95",
|
||||
"from": "github:lbryio/lbryinc",
|
||||
"version": "github:lbryio/lbryinc#4d24cef00106294d3e848b6c2b261e01382fce17",
|
||||
"from": "github:lbryio/lbryinc#subscriptions",
|
||||
"requires": {
|
||||
"lbry-redux": "github:lbryio/lbry-redux#2375860d6269d0369418879c2531b1d48c4e47f2",
|
||||
"bluebird": "^3.5.1",
|
||||
"lbry-redux": "github:lbryio/lbry-redux#84b7d396934d57a37802aadbef71db91230a9404",
|
||||
"reselect": "^3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"lbry-redux": {
|
||||
"version": "github:lbryio/lbry-redux#2375860d6269d0369418879c2531b1d48c4e47f2",
|
||||
"from": "github:lbryio/lbry-redux#2375860d6269d0369418879c2531b1d48c4e47f2",
|
||||
"version": "github:lbryio/lbry-redux#84b7d396934d57a37802aadbef71db91230a9404",
|
||||
"from": "github:lbryio/lbry-redux#84b7d396934d57a37802aadbef71db91230a9404",
|
||||
"requires": {
|
||||
"proxy-polyfill": "0.1.6",
|
||||
"reselect": "^3.0.0"
|
||||
"reselect": "^3.0.0",
|
||||
"uuid": "^3.3.2"
|
||||
}
|
||||
},
|
||||
"uuid": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
|
||||
"integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -4978,6 +5063,15 @@
|
|||
"find-up": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"pkg-up": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz",
|
||||
"integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"find-up": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"plist": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/plist/-/plist-1.2.0.tgz",
|
||||
|
@ -7026,6 +7120,11 @@
|
|||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
|
||||
"integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68="
|
||||
},
|
||||
"y18n": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
|
||||
"integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE="
|
||||
},
|
||||
"yallist": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
|
||||
|
|
|
@ -7,8 +7,9 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"base-64": "^0.1.0",
|
||||
"@expo/vector-icons": "^8.1.0",
|
||||
"lbry-redux": "lbryio/lbry-redux",
|
||||
"lbryinc": "lbryio/lbryinc",
|
||||
"lbryinc": "lbryio/lbryinc#subscriptions",
|
||||
"moment": "^2.22.1",
|
||||
"react": "16.2.0",
|
||||
"react-native": "0.55.3",
|
||||
|
@ -34,6 +35,7 @@
|
|||
"devDependencies": {
|
||||
"babel-preset-env": "^1.6.1",
|
||||
"babel-preset-stage-2": "^6.18.0",
|
||||
"babel-plugin-module-resolver": "^3.1.1",
|
||||
"flow-babel-webpack-plugin": "^1.1.1"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import TrendingPage from '../page/trending';
|
|||
import SearchPage from '../page/search';
|
||||
import SettingsPage from '../page/settings';
|
||||
import SplashScreen from '../page/splash';
|
||||
import SubscriptionsPage from '../page/subscriptions';
|
||||
import TransactionHistoryPage from '../page/transactionHistory';
|
||||
import WalletPage from '../page/wallet';
|
||||
import SearchInput from '../component/searchInput';
|
||||
|
@ -109,6 +110,17 @@ const myLbryStack = createStackNavigator({
|
|||
}
|
||||
});
|
||||
|
||||
const mySubscriptionsStack = createStackNavigator({
|
||||
Subscriptions: {
|
||||
screen: SubscriptionsPage,
|
||||
navigationOptions: ({ navigation }) => ({
|
||||
title: 'My Subscriptions',
|
||||
headerLeft: menuNavigationButton(navigation),
|
||||
headerTitleStyle: discoverStyle.titleText
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
const rewardsStack = createStackNavigator({
|
||||
Rewards: {
|
||||
screen: RewardsPage,
|
||||
|
@ -148,6 +160,9 @@ const drawer = createDrawerNavigator({
|
|||
TrendingStack: { screen: trendingStack, navigationOptions: {
|
||||
title: 'Trending', drawerIcon: ({ tintColor }) => <Icon name="fire" size={20} style={{ color: tintColor }} />
|
||||
}},
|
||||
MySubscriptionsStack: { screen: mySubscriptionsStack, navigationOptions: {
|
||||
title: 'My Subscriptions', drawerIcon: ({ tintColor }) => <Icon name="rss-square" size={20} style={{ color: tintColor }} />
|
||||
}},
|
||||
MyLBRYStack: { screen: myLbryStack, navigationOptions: {
|
||||
title: 'My LBRY', drawerIcon: ({ tintColor }) => <Icon name="folder" size={20} style={{ color: tintColor }} />
|
||||
}},
|
||||
|
|
|
@ -11,6 +11,8 @@ export default class Button extends React.PureComponent {
|
|||
style,
|
||||
text,
|
||||
icon,
|
||||
iconColor,
|
||||
solid,
|
||||
theme,
|
||||
onPress,
|
||||
onLayout
|
||||
|
@ -41,9 +43,14 @@ export default class Button extends React.PureComponent {
|
|||
textStyles.push(buttonStyle.textLight);
|
||||
}
|
||||
|
||||
let renderIcon = (<Icon name={icon} size={18} color={iconColor ? iconColor : ('light' === theme ? Colors.DarkGrey : Colors.White)} />);
|
||||
if (solid) {
|
||||
renderIcon = (<Icon name={icon} size={18} color={iconColor ? iconColor : ('light' === theme ? Colors.DarkGrey : Colors.White)} solid />);
|
||||
}
|
||||
|
||||
return (
|
||||
<TouchableOpacity disabled={disabled} style={styles} onPress={onPress} onLayout={onLayout}>
|
||||
{icon && <Icon name={icon} size={18} color={'light' === theme ? Colors.DarkGrey : Colors.White} />}
|
||||
{icon && renderIcon}
|
||||
{text && (text.trim().length > 0) && <Text style={textStyles}>{text}</Text>}
|
||||
</TouchableOpacity>
|
||||
);
|
||||
|
|
23
app/src/component/subscribeButton/index.js
Normal file
23
app/src/component/subscribeButton/index.js
Normal file
|
@ -0,0 +1,23 @@
|
|||
import { connect } from 'react-redux';
|
||||
import {
|
||||
doChannelSubscribe,
|
||||
doChannelUnsubscribe,
|
||||
selectSubscriptions,
|
||||
makeSelectIsSubscribed,
|
||||
} from 'lbryinc';
|
||||
import { doToast } from 'lbry-redux';
|
||||
import SubscribeButton from './view';
|
||||
|
||||
const select = (state, props) => ({
|
||||
subscriptions: selectSubscriptions(state),
|
||||
isSubscribed: makeSelectIsSubscribed(props.uri, true)(state),
|
||||
});
|
||||
|
||||
export default connect(
|
||||
select,
|
||||
{
|
||||
doChannelSubscribe,
|
||||
doChannelUnsubscribe,
|
||||
doToast,
|
||||
}
|
||||
)(SubscribeButton);
|
49
app/src/component/subscribeButton/view.js
Normal file
49
app/src/component/subscribeButton/view.js
Normal file
|
@ -0,0 +1,49 @@
|
|||
import React from 'react';
|
||||
import { parseURI } from 'lbry-redux';
|
||||
import { NativeModules, Text, View, TouchableOpacity } from 'react-native';
|
||||
import Button from '../button';
|
||||
import Colors from '../../styles/colors';
|
||||
|
||||
class SubscribeButton extends React.PureComponent {
|
||||
render() {
|
||||
const {
|
||||
uri,
|
||||
isSubscribed,
|
||||
doChannelSubscribe,
|
||||
doChannelUnsubscribe,
|
||||
style
|
||||
} = this.props;
|
||||
|
||||
let styles = [];
|
||||
if (style) {
|
||||
if (style.length) {
|
||||
styles = styles.concat(style);
|
||||
} else {
|
||||
styles.push(style);
|
||||
}
|
||||
}
|
||||
|
||||
const iconColor = isSubscribed ? null : Colors.Red;
|
||||
const subscriptionHandler = isSubscribed ? doChannelUnsubscribe : doChannelSubscribe;
|
||||
const subscriptionLabel = isSubscribed ? __('Unsubscribe') : __('Subscribe');
|
||||
const { claimName } = parseURI(uri);
|
||||
|
||||
return (
|
||||
<Button
|
||||
style={styles}
|
||||
theme={"light"}
|
||||
icon={"heart"}
|
||||
iconColor={iconColor}
|
||||
solid={isSubscribed ? false : true}
|
||||
text={subscriptionLabel}
|
||||
onPress={() => {
|
||||
subscriptionHandler({
|
||||
channelName: claimName,
|
||||
uri,
|
||||
});
|
||||
}} />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default SubscribeButton;
|
|
@ -19,7 +19,7 @@ import {
|
|||
searchReducer,
|
||||
walletReducer
|
||||
} from 'lbry-redux';
|
||||
import { authReducer, rewardsReducer, userReducer } from 'lbryinc';
|
||||
import { authReducer, rewardsReducer, subscriptionsReducer, userReducer } from 'lbryinc';
|
||||
import { createStore, applyMiddleware, compose, combineReducers } from 'redux';
|
||||
import { createLogger } from 'redux-logger';
|
||||
import { AppNavigator } from './component/AppNavigator';
|
||||
|
@ -87,6 +87,7 @@ const reducers = combineReducers({
|
|||
rewards: rewardsReducer,
|
||||
settings: settingsReducer,
|
||||
search: searchReducer,
|
||||
subscriptions: subscriptionsReducer,
|
||||
user: userReducer,
|
||||
wallet: walletReducer
|
||||
});
|
||||
|
|
|
@ -9,7 +9,7 @@ import {
|
|||
View,
|
||||
ScrollView
|
||||
} from 'react-native';
|
||||
import { navigateToUri } from '../../utils/helper';
|
||||
import { navigateToUri, uriFromFileInfo } from '../../utils/helper';
|
||||
import Colors from '../../styles/colors';
|
||||
import PageHeader from '../../component/pageHeader';
|
||||
import FileListItem from '../../component/fileListItem';
|
||||
|
@ -28,14 +28,6 @@ class DownloadsPage extends React.PureComponent {
|
|||
this.props.fileList();
|
||||
}
|
||||
|
||||
uriFromFileInfo(fileInfo) {
|
||||
const { name: claimName, claim_name: claimNameDownloaded, claim_id: claimId } = fileInfo;
|
||||
const uriParams = {};
|
||||
uriParams.contentName = claimName || claimNameDownloaded;
|
||||
uriParams.claimId = claimId;
|
||||
return buildURI(uriParams);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { fetching, fileInfos, navigation } = this.props;
|
||||
const hasDownloads = fileInfos && Object.values(fileInfos).length > 0;
|
||||
|
@ -59,9 +51,9 @@ class DownloadsPage extends React.PureComponent {
|
|||
renderItem={ ({item}) => (
|
||||
<FileListItem
|
||||
style={fileListStyle.item}
|
||||
uri={this.uriFromFileInfo(item)}
|
||||
uri={uriFromFileInfo(item)}
|
||||
navigation={navigation}
|
||||
onPress={() => navigateToUri(navigation, this.uriFromFileInfo(item), { autoplay: true })} />
|
||||
onPress={() => navigateToUri(navigation, uriFromFileInfo(item), { autoplay: true })} />
|
||||
)
|
||||
}
|
||||
data={fileInfos.sort((a, b) => {
|
||||
|
|
|
@ -8,6 +8,7 @@ import {
|
|||
makeSelectIsUriResolving,
|
||||
makeSelectCostInfoForUri,
|
||||
makeSelectFileInfoForUri,
|
||||
makeSelectChannelForClaimUri,
|
||||
makeSelectClaimForUri,
|
||||
makeSelectContentTypeForUri,
|
||||
makeSelectMetadataForUri,
|
||||
|
@ -32,6 +33,7 @@ const select = (state, props) => {
|
|||
//tab: makeSelectCurrentParam('tab')(state),
|
||||
fileInfo: makeSelectFileInfoForUri(selectProps.uri)(state),
|
||||
rewardedContentClaimIds: selectRewardContentClaimIds(state, selectProps),
|
||||
channelUri: makeSelectChannelForClaimUri(selectProps.uri, true)(state),
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ import FloatingWalletBalance from '../../component/floatingWalletBalance';
|
|||
import Link from '../../component/link';
|
||||
import MediaPlayer from '../../component/mediaPlayer';
|
||||
import RelatedContent from '../../component/relatedContent';
|
||||
import SubscribeButton from '../../component/subscribeButton';
|
||||
import UriBar from '../../component/uriBar';
|
||||
import Video from 'react-native-video';
|
||||
import filePageStyle from '../../styles/filePage';
|
||||
|
@ -332,6 +333,7 @@ class FilePage extends React.PureComponent {
|
|||
render() {
|
||||
const {
|
||||
claim,
|
||||
channelUri,
|
||||
fileInfo,
|
||||
metadata,
|
||||
contentType,
|
||||
|
@ -403,7 +405,6 @@ class FilePage extends React.PureComponent {
|
|||
value && value.publisherSignature && value.publisherSignature.certificateId;
|
||||
const canSendTip = this.state.tipAmount > 0;
|
||||
|
||||
|
||||
const playerStyle = [filePageStyle.player,
|
||||
this.state.isLandscape ? filePageStyle.containedPlayerLandscape :
|
||||
(this.state.fullscreenMode ? filePageStyle.fullscreenPlayer : filePageStyle.containedPlayer)];
|
||||
|
@ -494,11 +495,16 @@ class FilePage extends React.PureComponent {
|
|||
|
||||
{showActions &&
|
||||
<View style={filePageStyle.actions}>
|
||||
{<Button style={filePageStyle.actionButton}
|
||||
theme={"light"}
|
||||
icon={"gift"}
|
||||
text={"Send a tip"}
|
||||
onPress={() => this.setState({ showTipView: true })} />}
|
||||
<View style={filePageStyle.socialActions}>
|
||||
{channelName && <SubscribeButton
|
||||
style={[filePageStyle.actionButton, filePageStyle.subscribeButton]}
|
||||
uri={channelUri} name={channelName} />}
|
||||
{<Button style={filePageStyle.actionButton}
|
||||
theme={"light"}
|
||||
icon={"gift"}
|
||||
text={"Send a tip"}
|
||||
onPress={() => this.setState({ showTipView: true })} />}
|
||||
</View>
|
||||
{showFileActions &&
|
||||
<View style={filePageStyle.fileActions}>
|
||||
{completed && <Button style={filePageStyle.actionButton}
|
||||
|
|
|
@ -2,6 +2,7 @@ import { connect } from 'react-redux';
|
|||
import { doBalanceSubscribe, doBlackListedOutpointsSubscribe, doToast } from 'lbry-redux';
|
||||
import {
|
||||
doAuthenticate,
|
||||
doCheckSubscriptionsInit,
|
||||
doFetchRewardedContent,
|
||||
doUserEmailToVerify,
|
||||
doUserEmailVerify,
|
||||
|
@ -21,6 +22,7 @@ const perform = dispatch => ({
|
|||
authenticate: (appVersion, os) => dispatch(doAuthenticate(appVersion, os)),
|
||||
balanceSubscribe: () => dispatch(doBalanceSubscribe()),
|
||||
blacklistedOutpointsSubscribe: () => dispatch(doBlackListedOutpointsSubscribe()),
|
||||
checkSubscriptionsInit: () => dispatch(doCheckSubscriptionsInit()),
|
||||
deleteCompleteBlobs: () => dispatch(doDeleteCompleteBlobs()),
|
||||
fetchRewardedContent: () => dispatch(doFetchRewardedContent()),
|
||||
notify: data => dispatch(doToast(data)),
|
||||
|
|
|
@ -144,12 +144,14 @@ class SplashScreen extends React.PureComponent {
|
|||
authenticate,
|
||||
balanceSubscribe,
|
||||
blacklistedOutpointsSubscribe,
|
||||
checkSubscriptionsInit,
|
||||
navigation,
|
||||
notify
|
||||
} = this.props;
|
||||
|
||||
balanceSubscribe();
|
||||
blacklistedOutpointsSubscribe();
|
||||
checkSubscriptionsInit();
|
||||
NativeModules.VersionInfo.getAppVersion().then(appVersion => {
|
||||
this.setState({ shouldAuthenticate: true });
|
||||
authenticate(appVersion, Platform.OS);
|
||||
|
|
40
app/src/page/subscriptions/index.js
Normal file
40
app/src/page/subscriptions/index.js
Normal file
|
@ -0,0 +1,40 @@
|
|||
import { connect } from 'react-redux';
|
||||
import {
|
||||
doFetchMySubscriptions,
|
||||
doSetViewMode,
|
||||
doFetchRecommendedSubscriptions,
|
||||
doCompleteFirstRun,
|
||||
doShowSuggestedSubs,
|
||||
selectSubscriptionClaims,
|
||||
selectSubscriptions,
|
||||
selectSubscriptionsBeingFetched,
|
||||
selectIsFetchingSubscriptions,
|
||||
selectUnreadSubscriptions,
|
||||
selectViewMode,
|
||||
selectFirstRunCompleted,
|
||||
selectShowSuggestedSubs
|
||||
} from 'lbryinc';
|
||||
import SubscriptionsPage from './view';
|
||||
|
||||
const select = state => ({
|
||||
loading:
|
||||
selectIsFetchingSubscriptions(state) ||
|
||||
Boolean(Object.keys(selectSubscriptionsBeingFetched(state)).length),
|
||||
subscribedChannels: selectSubscriptions(state),
|
||||
allSubscriptions: selectSubscriptionClaims(state),
|
||||
unreadSubscriptions: selectUnreadSubscriptions(state),
|
||||
viewMode: selectViewMode(state),
|
||||
firstRunCompleted: selectFirstRunCompleted(state),
|
||||
showSuggestedSubs: selectShowSuggestedSubs(state),
|
||||
});
|
||||
|
||||
export default connect(
|
||||
select,
|
||||
{
|
||||
doFetchMySubscriptions,
|
||||
doSetViewMode,
|
||||
doFetchRecommendedSubscriptions,
|
||||
doCompleteFirstRun,
|
||||
doShowSuggestedSubs,
|
||||
}
|
||||
)(SubscriptionsPage);
|
89
app/src/page/subscriptions/view.js
Normal file
89
app/src/page/subscriptions/view.js
Normal file
|
@ -0,0 +1,89 @@
|
|||
import React from 'react';
|
||||
import NavigationActions from 'react-navigation';
|
||||
import {
|
||||
ActivityIndicator,
|
||||
AsyncStorage,
|
||||
FlatList,
|
||||
NativeModules,
|
||||
SectionList,
|
||||
Text,
|
||||
View
|
||||
} from 'react-native';
|
||||
import { buildURI } from 'lbry-redux';
|
||||
import { uriFromFileInfo } from 'utils/helper';
|
||||
import moment from 'moment';
|
||||
import Colors from 'styles/colors';
|
||||
import discoverStyle from 'styles/discover';
|
||||
import subscriptionsStyle from 'styles/subscriptions';
|
||||
import FloatingWalletBalance from 'component/floatingWalletBalance';
|
||||
import FileItem from 'component/fileItem';
|
||||
import UriBar from 'component/uriBar';
|
||||
|
||||
class SubscriptionsPage extends React.PureComponent {
|
||||
componentDidMount() {
|
||||
const {
|
||||
doFetchMySubscriptions,
|
||||
doFetchRecommendedSubscriptions
|
||||
} = this.props;
|
||||
doFetchMySubscriptions();
|
||||
doFetchRecommendedSubscriptions();
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
subscribedChannels,
|
||||
allSubscriptions,
|
||||
loading,
|
||||
viewMode,
|
||||
doSetViewMode,
|
||||
loadingSuggested,
|
||||
firstRunCompleted,
|
||||
doCompleteFirstRun,
|
||||
doShowSuggestedSubs,
|
||||
showSuggestedSubs,
|
||||
unreadSubscriptions,
|
||||
navigation
|
||||
} = this.props;
|
||||
const numberOfSubscriptions = subscribedChannels ? subscribedChannels.length : 0;
|
||||
const hasSubscriptions = numberOfSubscriptions > 0;
|
||||
|
||||
return (
|
||||
<View style={subscriptionsStyle.container}>
|
||||
|
||||
{hasSubscriptions && !loading &&
|
||||
<FlatList
|
||||
style={subscriptionsStyle.scrollContainer}
|
||||
contentContainerStyle={subscriptionsStyle.scrollPadding}
|
||||
renderItem={ ({item}) => (
|
||||
<FileItem
|
||||
style={subscriptionsStyle.fileItem}
|
||||
mediaStyle={discoverStyle.fileItemMedia}
|
||||
key={item}
|
||||
uri={uriFromFileInfo(item)}
|
||||
navigation={navigation} />
|
||||
)
|
||||
}
|
||||
data={allSubscriptions}
|
||||
keyExtractor={(item, index) => uriFromFileInfo(item)} />}
|
||||
|
||||
{hasSubscriptions && loading &&
|
||||
<View style={subscriptionsStyle.busyContainer}>
|
||||
<ActivityIndicator size="large" color={Colors.LbryGreen} style={subscriptionsStyle.loading} />
|
||||
</View>
|
||||
}
|
||||
|
||||
{!hasSubscriptions &&
|
||||
<View style={subscriptionsStyle.busyContainer}>
|
||||
<Text style={subscriptionsStyle.infoText}>
|
||||
You are not subscribed to any channels. Feel free to discover new channels that you can subscribe to.
|
||||
</Text>
|
||||
</View>}
|
||||
|
||||
<FloatingWalletBalance navigation={navigation} />
|
||||
<UriBar navigation={navigation} />
|
||||
</View>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default SubscriptionsPage;
|
|
@ -154,11 +154,18 @@ const filePageStyle = StyleSheet.create({
|
|||
fileActions: {
|
||||
alignSelf: 'flex-end'
|
||||
},
|
||||
socialActions: {
|
||||
alignSelf: 'flex-start',
|
||||
flexDirection: 'row'
|
||||
},
|
||||
actionButton: {
|
||||
alignSelf: 'flex-start',
|
||||
backgroundColor: Colors.White,
|
||||
paddingLeft: 24,
|
||||
paddingRight: 24
|
||||
paddingLeft: 16,
|
||||
paddingRight: 16
|
||||
},
|
||||
subscribeButton: {
|
||||
marginRight: 8
|
||||
},
|
||||
loading: {
|
||||
position: 'absolute',
|
||||
|
|
33
app/src/styles/subscriptions.js
Normal file
33
app/src/styles/subscriptions.js
Normal file
|
@ -0,0 +1,33 @@
|
|||
import { StyleSheet } from 'react-native';
|
||||
|
||||
const subscriptionsStyle = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
},
|
||||
busyContainer: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
flexDirection: 'row',
|
||||
padding: 16
|
||||
},
|
||||
scrollContainer: {
|
||||
flex: 1,
|
||||
marginBottom: 60
|
||||
},
|
||||
scrollPadding: {
|
||||
paddingTop: 24
|
||||
},
|
||||
infoText: {
|
||||
textAlign: 'center',
|
||||
fontFamily: 'Inter-UI-Regular',
|
||||
fontSize: 16,
|
||||
},
|
||||
fileItem: {
|
||||
marginLeft: 24,
|
||||
marginRight: 24,
|
||||
marginBottom: 24
|
||||
}
|
||||
});
|
||||
|
||||
export default subscriptionsStyle;
|
|
@ -1,4 +1,5 @@
|
|||
import { NavigationActions, StackActions } from 'react-navigation';
|
||||
import { buildURI } from 'lbry-redux';
|
||||
import Constants from '../constants';
|
||||
|
||||
function getRouteForSpecialUri(uri) {
|
||||
|
@ -83,3 +84,11 @@ export function navigateToUri(navigation, uri, additionalParams) {
|
|||
|
||||
navigation.navigate({ routeName: 'File', key: uri, params });
|
||||
}
|
||||
|
||||
export function uriFromFileInfo(fileInfo) {
|
||||
const { name: claimName, claim_name: claimNameDownloaded, claim_id: claimId } = fileInfo;
|
||||
const uriParams = {};
|
||||
uriParams.contentName = claimName || claimNameDownloaded;
|
||||
uriParams.claimId = claimId;
|
||||
return buildURI(uriParams);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue