0.8.2 rc (#28)

* enable deletion of downloads on the Library page
* tweak suggested subscriptions and library page
* pin lbryinc commit hash
This commit is contained in:
Akinwale Ariwodola 2019-08-20 09:19:42 +01:00 committed by GitHub
parent a2ee73e23e
commit 4287793d3f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 180 additions and 58 deletions

8
package-lock.json generated
View file

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

View file

@ -12,8 +12,8 @@
"base-64": "^0.1.0",
"@expo/vector-icons": "^8.1.0",
"gfycat-style-urls": "^1.0.3",
"lbry-redux": "lbryio/lbry-redux#f6ba006cccf64b059ff9d10b9bd9796383caff98",
"lbryinc": "lbryio/lbryinc#430c280789a5031c2e49ca5bf8a7d90ccccc4cdb",
"lbry-redux": "lbryio/lbry-redux#4f812db1c7cdb4c08c5426d4d3f83023de5d655f",
"lbryinc": "lbryio/lbryinc#17868d948a160af27a375956226f8dd23fa2c37d",
"lodash": ">=4.17.11",
"merge": ">=1.2.1",
"moment": "^2.22.1",

View file

@ -38,12 +38,7 @@ export default class Button extends React.PureComponent {
);
if (solid) {
renderIcon = (
<Icon
name={icon}
size={16}
color={iconColor || (theme === 'light' ? Colors.DarkGrey : Colors.White)}
solid
/>
<Icon 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 && (
<View style={claimListStyle.verticalLoading}>
<ActivityIndicator size={'small'} color={Colors.LbryGreen} />
<ActivityIndicator size={'small'} color={Colors.NextLbryGreen} />
</View>
)}
</View>
@ -240,7 +240,7 @@ class ClaimList extends React.PureComponent {
if (loading) {
return (
<View style={discoverStyle.listLoading}>
<ActivityIndicator size={'small'} color={Colors.LbryGreen} />
<ActivityIndicator size={'small'} color={Colors.NextLbryGreen} />
</View>
);
}

View file

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

View file

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

View file

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

View file

@ -1,7 +1,17 @@
import React from 'react';
import { Lbry, buildURI, normalizeURI } from 'lbry-redux';
import { ActivityIndicator, Button, FlatList, NativeModules, Text, TextInput, View, ScrollView } from 'react-native';
import { navigateToUri, uriFromFileInfo } from 'utils/helper';
import {
ActivityIndicator,
Alert,
Button,
FlatList,
NativeModules,
Text,
TextInput,
View,
ScrollView,
} from 'react-native';
import { __, navigateToUri, uriFromFileInfo } from 'utils/helper';
import Colors from 'styles/colors';
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
import PageHeader from 'component/pageHeader';
@ -17,6 +27,12 @@ class DownloadsPage extends React.PureComponent {
title: 'Downloads',
};
state = {
selectionMode: false,
selectedUris: [],
selectedClaimsMap: {},
};
didFocusListener;
componentWillMount() {
@ -58,40 +74,127 @@ class DownloadsPage extends React.PureComponent {
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() {
const { fetching, claims, downloadedUris, fileInfos, navigation } = this.props;
const { selectionMode, selectedUris } = this.state;
const filteredUris = this.getFilteredUris();
const hasDownloads = filteredUris && filteredUris.length > 0;
return (
<View style={downloadsStyle.container}>
<UriBar navigation={navigation} />
{!fetching && !hasDownloads && (
<View style={downloadsStyle.busyContainer}>
<Text style={downloadsStyle.noDownloadsText}>
You have not watched or downloaded any content from LBRY yet.
</Text>
</View>
)}
{fetching && (
<View style={downloadsStyle.busyContainer}>
<ActivityIndicator size="large" color={Colors.NextLbryGreen} style={downloadsStyle.loading} />
</View>
)}
{!fetching && hasDownloads && (
<View style={downloadsStyle.subContainer}>
<StorageStatsCard fileInfos={fileInfos} />
<UriBar
navigation={navigation}
selectionMode={selectionMode}
selectedItemCount={selectedUris.length}
onExitSelectionMode={this.onExitSelectionMode}
onDeleteActionPressed={this.onDeleteActionPressed}
/>
<View style={downloadsStyle.subContainer}>
{hasDownloads && <StorageStatsCard fileInfos={this.getFilteredFileInfos()} />}
{fetching && (
<View style={downloadsStyle.busyContainer}>
<ActivityIndicator size="large" color={Colors.NextLbryGreen} style={downloadsStyle.loading} />
</View>
)}
{!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
extraData={this.state}
style={downloadsStyle.scrollContainer}
contentContainerStyle={downloadsStyle.scrollPadding}
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}
keyExtractor={(item, index) => item}
/>
</View>
)}
)}
</View>
<FloatingWalletBalance navigation={navigation} />
</View>
);

View file

@ -498,9 +498,23 @@ class FilePage extends React.PureComponent {
return;
}
sendTip(tipAmount, claim.claim_id, uri, () => {
this.setState({ tipAmount: 0, showTipView: false });
});
const suffix = 'credit' + (tipAmount === 1 ? '' : 's');
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 => {

View file

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