0.8.2 rc #28

Merged
akinwale merged 18 commits from 0.8.2-rc into master 2019-08-20 10:19:43 +02:00
10 changed files with 180 additions and 58 deletions
package-lock.jsonpackage.json
src
component
button
claimList
storageStatsCard
suggestedSubscriptions
page
downloads
file
publishes

8
package-lock.json generated
View file

@ -5562,8 +5562,8 @@
} }
}, },
"lbry-redux": { "lbry-redux": {
"version": "github:lbryio/lbry-redux#06b65b5bb474bd61aa4a6bcff2047a71575a17b0", "version": "github:lbryio/lbry-redux#4f812db1c7cdb4c08c5426d4d3f83023de5d655f",
"from": "github:lbryio/lbry-redux#06b65b5bb474bd61aa4a6bcff2047a71575a17b0", "from": "github:lbryio/lbry-redux#4f812db1c7cdb4c08c5426d4d3f83023de5d655f",
"requires": { "requires": {
"proxy-polyfill": "0.1.6", "proxy-polyfill": "0.1.6",
"reselect": "^3.0.0", "reselect": "^3.0.0",
@ -5571,8 +5571,8 @@
} }
}, },
"lbryinc": { "lbryinc": {
"version": "github:lbryio/lbryinc#430c280789a5031c2e49ca5bf8a7d90ccccc4cdb", "version": "github:lbryio/lbryinc#17868d948a160af27a375956226f8dd23fa2c37d",
"from": "github:lbryio/lbryinc#430c280789a5031c2e49ca5bf8a7d90ccccc4cdb", "from": "github:lbryio/lbryinc#17868d948a160af27a375956226f8dd23fa2c37d",
"requires": { "requires": {
"reselect": "^3.0.0" "reselect": "^3.0.0"
} }

View file

@ -12,8 +12,8 @@
"base-64": "^0.1.0", "base-64": "^0.1.0",
"@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#f6ba006cccf64b059ff9d10b9bd9796383caff98", "lbry-redux": "lbryio/lbry-redux#4f812db1c7cdb4c08c5426d4d3f83023de5d655f",
"lbryinc": "lbryio/lbryinc#430c280789a5031c2e49ca5bf8a7d90ccccc4cdb", "lbryinc": "lbryio/lbryinc#17868d948a160af27a375956226f8dd23fa2c37d",
"lodash": ">=4.17.11", "lodash": ">=4.17.11",
"merge": ">=1.2.1", "merge": ">=1.2.1",
"moment": "^2.22.1", "moment": "^2.22.1",

View file

@ -38,12 +38,7 @@ export default class Button extends React.PureComponent {
); );
if (solid) { if (solid) {
renderIcon = ( renderIcon = (
<Icon <Icon name={icon} size={16} color={iconColor || (theme === 'light' ? Colors.DarkGrey : Colors.White)} solid />
name={icon}
size={16}
color={iconColor || (theme === 'light' ? Colors.DarkGrey : Colors.White)}
solid
/>
); );
} }

View file

@ -229,7 +229,7 @@ class ClaimList extends React.PureComponent {
/> />
{loading && ( {loading && (
<View style={claimListStyle.verticalLoading}> <View style={claimListStyle.verticalLoading}>
<ActivityIndicator size={'small'} color={Colors.LbryGreen} /> <ActivityIndicator size={'small'} color={Colors.NextLbryGreen} />
</View> </View>
)} )}
</View> </View>
@ -240,7 +240,7 @@ class ClaimList extends React.PureComponent {
if (loading) { if (loading) {
return ( return (
<View style={discoverStyle.listLoading}> <View style={discoverStyle.listLoading}>
<ActivityIndicator size={'small'} color={Colors.LbryGreen} /> <ActivityIndicator size={'small'} color={Colors.NextLbryGreen} />
</View> </View>
); );
} }

View file

@ -65,7 +65,8 @@ class StorageStatsCard extends React.PureComponent {
} }
render() { render() {
if (this.state.totalBytes == 0) { const { fileInfos } = this.props;
if (fileInfos.length === 0 || this.state.totalBytes === 0) {
return null; return null;
} }

View file

@ -18,7 +18,7 @@ class SuggestedSubscriptions extends React.PureComponent {
componentDidMount() { componentDidMount() {
const { claimSearch, followedTags } = this.props; const { claimSearch, followedTags } = this.props;
const options = { const options = {
any_tags: followedTags.map(tag => tag.name), any_tags: _.shuffle(followedTags.map(tag => tag.name)).slice(0, 3),
page: 1, page: 1,
no_totals: true, no_totals: true,
claim_type: 'channel', claim_type: 'channel',
@ -34,14 +34,14 @@ class SuggestedSubscriptions extends React.PureComponent {
const suggestedUris = suggested ? suggested.map(suggested => suggested.uri) : []; const suggestedUris = suggested ? suggested.map(suggested => suggested.uri) : [];
return [ return [
{
title: __('You might like'),
data: suggestedUris,
},
{ {
title: __('Tags you follow'), title: __('Tags you follow'),
data: claimSearchUris ? claimSearchUris.filter(uri => !suggestedUris.includes(uri)) : [], data: claimSearchUris ? claimSearchUris.filter(uri => !suggestedUris.includes(uri)) : [],
}, },
{
title: __('You might also like'),
data: _.shuffle(suggestedUris),
},
]; ];
}; };

View file

@ -9,6 +9,7 @@ import {
selectIsFetchingFileList, selectIsFetchingFileList,
} from 'lbry-redux'; } from 'lbry-redux';
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer'; import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
import { doDeleteFile } from 'redux/actions/file';
import { selectCurrentRoute } from 'redux/selectors/drawer'; import { selectCurrentRoute } from 'redux/selectors/drawer';
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
import DownloadsPage from './view'; import DownloadsPage from './view';
@ -22,6 +23,9 @@ const select = state => ({
}); });
const perform = dispatch => ({ const perform = dispatch => ({
deleteFile: (fileInfo, deleteFromDevice, abandonClaim) => {
dispatch(doDeleteFile(fileInfo, deleteFromDevice, abandonClaim));
},
fetchMyClaims: () => dispatch(doFetchClaimListMine()), fetchMyClaims: () => dispatch(doFetchClaimListMine()),
fileList: () => dispatch(doFileList()), fileList: () => dispatch(doFileList()),
pushDrawerStack: () => dispatch(doPushDrawerStack(Constants.DRAWER_ROUTE_MY_LBRY)), pushDrawerStack: () => dispatch(doPushDrawerStack(Constants.DRAWER_ROUTE_MY_LBRY)),

View file

@ -1,7 +1,17 @@
import React from 'react'; import React from 'react';
import { Lbry, buildURI, normalizeURI } from 'lbry-redux'; import { Lbry, buildURI, normalizeURI } from 'lbry-redux';
import { ActivityIndicator, Button, FlatList, NativeModules, Text, TextInput, View, ScrollView } from 'react-native'; import {
import { navigateToUri, uriFromFileInfo } from 'utils/helper'; ActivityIndicator,
Alert,
Button,
FlatList,
NativeModules,
Text,
TextInput,
View,
ScrollView,
} from 'react-native';
import { __, navigateToUri, uriFromFileInfo } from 'utils/helper';
import Colors from 'styles/colors'; import Colors from 'styles/colors';
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
import PageHeader from 'component/pageHeader'; import PageHeader from 'component/pageHeader';
@ -17,6 +27,12 @@ class DownloadsPage extends React.PureComponent {
title: 'Downloads', title: 'Downloads',
}; };
state = {
selectionMode: false,
selectedUris: [],
selectedClaimsMap: {},
};
didFocusListener; didFocusListener;
componentWillMount() { componentWillMount() {
@ -58,40 +74,127 @@ class DownloadsPage extends React.PureComponent {
return downloadedUris.filter(uri => !claimUris.includes(uri)); return downloadedUris.filter(uri => !claimUris.includes(uri));
}; };
getFilteredFileInfos = () => {
const { claims, fileInfos } = this.props;
const claimUris = claims.map(claim => normalizeURI(`${claim.name}#${claim.claim_id}`));
return fileInfos.filter(
fileInfo => !claimUris.includes(normalizeURI(`${fileInfo.claim_name}#${fileInfo.claim_id}`))
);
};
addOrRemoveItem = (uri, claim) => {
const { selectedClaimsMap } = this.state;
let selectedUris = [...this.state.selectedUris];
if (selectedUris.includes(uri)) {
delete selectedClaimsMap[uri];
selectedUris.splice(selectedUris.indexOf(uri), 1);
} else {
selectedClaimsMap[uri] = claim;
selectedUris.push(uri);
}
this.setState({ selectionMode: selectedUris.length > 0, selectedUris, selectedClaimsMap });
};
handleSelectItem = (uri, claim) => {
this.addOrRemoveItem(uri, claim);
};
handleItemLongPress = (uri, claim) => {
this.addOrRemoveItem(uri, claim);
};
onExitSelectionMode = () => {
this.setState({ selectionMode: false, selectedUris: [], selectedClaimsMap: {} });
};
onDeleteActionPressed = () => {
const { deleteFile, fileList } = this.props;
const { selectedClaimsMap } = this.state;
// show confirm alert
Alert.alert(
__('Delete files'),
__('Are you sure you want to delete the selected content?'),
[
{ text: __('No') },
{
text: __('Yes'),
onPress: () => {
const uris = Object.keys(selectedClaimsMap);
uris.forEach(uri => {
const { txid, nout } = selectedClaimsMap[uri];
deleteFile(`${txid}:${nout}`, true);
});
this.onExitSelectionMode();
fileList();
},
},
],
{
cancelable: true,
}
);
};
render() { render() {
const { fetching, claims, downloadedUris, fileInfos, navigation } = this.props; const { fetching, claims, downloadedUris, fileInfos, navigation } = this.props;
const { selectionMode, selectedUris } = this.state;
const filteredUris = this.getFilteredUris(); const filteredUris = this.getFilteredUris();
const hasDownloads = filteredUris && filteredUris.length > 0; const hasDownloads = filteredUris && filteredUris.length > 0;
return ( return (
<View style={downloadsStyle.container}> <View style={downloadsStyle.container}>
<UriBar navigation={navigation} /> <UriBar
{!fetching && !hasDownloads && ( navigation={navigation}
<View style={downloadsStyle.busyContainer}> selectionMode={selectionMode}
<Text style={downloadsStyle.noDownloadsText}> selectedItemCount={selectedUris.length}
You have not watched or downloaded any content from LBRY yet. onExitSelectionMode={this.onExitSelectionMode}
</Text> onDeleteActionPressed={this.onDeleteActionPressed}
</View> />
)}
{fetching && ( <View style={downloadsStyle.subContainer}>
<View style={downloadsStyle.busyContainer}> {hasDownloads && <StorageStatsCard fileInfos={this.getFilteredFileInfos()} />}
<ActivityIndicator size="large" color={Colors.NextLbryGreen} style={downloadsStyle.loading} /> {fetching && (
</View> <View style={downloadsStyle.busyContainer}>
)} <ActivityIndicator size="large" color={Colors.NextLbryGreen} style={downloadsStyle.loading} />
{!fetching && hasDownloads && ( </View>
<View style={downloadsStyle.subContainer}> )}
<StorageStatsCard fileInfos={fileInfos} /> {!fetching && !hasDownloads && (
<View style={downloadsStyle.busyContainer}>
<Text style={downloadsStyle.noDownloadsText}>You do not have any downloaded content on this device.</Text>
</View>
)}
{!fetching && hasDownloads && (
<FlatList <FlatList
extraData={this.state}
style={downloadsStyle.scrollContainer} style={downloadsStyle.scrollContainer}
contentContainerStyle={downloadsStyle.scrollPadding} contentContainerStyle={downloadsStyle.scrollPadding}
renderItem={({ item }) => ( renderItem={({ item }) => (
<FileListItem style={fileListStyle.item} uri={item} navigation={navigation} autoplay /> <FileListItem
autoplay
key={item}
uri={item}
style={fileListStyle.item}
selected={selectedUris.includes(item)}
onPress={claim => {
if (selectionMode) {
this.handleSelectItem(item, claim);
} else {
// TODO: when shortUrl is available for my claims, navigate to that URL instead
navigateToUri(navigation, item, { autoplay: true });
}
}}
onLongPress={claim => this.handleItemLongPress(item, claim)}
navigation={navigation}
/>
)} )}
data={downloadedUris} data={downloadedUris}
keyExtractor={(item, index) => item} keyExtractor={(item, index) => item}
/> />
</View> )}
)} </View>
<FloatingWalletBalance navigation={navigation} /> <FloatingWalletBalance navigation={navigation} />
</View> </View>
); );

View file

@ -498,9 +498,23 @@ class FilePage extends React.PureComponent {
return; return;
} }
sendTip(tipAmount, claim.claim_id, uri, () => { const suffix = 'credit' + (tipAmount === 1 ? '' : 's');
this.setState({ tipAmount: 0, showTipView: false }); Alert.alert(
}); 'Send tip',
`Are you sure you want to tip ${tipAmount} ${suffix}?`,
[
{ text: 'No' },
{
text: 'Yes',
onPress: () => {
sendTip(tipAmount, claim.claim_id, false, () => {
this.setState({ tipAmount: 0, showTipView: false });
});
},
},
],
{ cancelable: true }
);
}; };
renderTags = tags => { renderTags = tags => {

View file

@ -75,20 +75,25 @@ class PublishesPage extends React.PureComponent {
const { selectedClaimsMap } = this.state; const { selectedClaimsMap } = this.state;
// show confirm alert // show confirm alert
Alert.alert(__('Unpublish'), __('Are you sure you want to unpublish the selected content?'), [ Alert.alert(
{ text: __('No') }, __('Unpublish'),
{ __('Are you sure you want to unpublish the selected content?'),
text: __('Yes'), [
onPress: () => { { text: __('No') },
const uris = Object.keys(selectedClaimsMap); {
uris.forEach(uri => { text: __('Yes'),
const { txid, nout } = selectedClaimsMap[uri]; onPress: () => {
abandonClaim(txid, nout); const uris = Object.keys(selectedClaimsMap);
}); uris.forEach(uri => {
this.onExitSelectionMode(); const { txid, nout } = selectedClaimsMap[uri];
abandonClaim(txid, nout);
});
this.onExitSelectionMode();
},
}, },
}, ],
]); { cancelable: true }
);
}; };
render() { render() {
@ -106,7 +111,7 @@ class PublishesPage extends React.PureComponent {
/> />
{fetching && ( {fetching && (
<View style={publishStyle.centered}> <View style={publishStyle.centered}>
<ActivityIndicator size={'small'} color={Colors.LbryGreen} /> <ActivityIndicator size={'large'} color={Colors.NextLbryGreen} />
</View> </View>
)} )}