0.8.2 rc #28
10 changed files with 180 additions and 58 deletions
8
package-lock.json
generated
8
package-lock.json
generated
|
@ -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"
|
||||||
}
|
}
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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),
|
||||||
|
},
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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)),
|
||||||
|
|
|
@ -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>
|
||||||
);
|
);
|
||||||
|
|
|
@ -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 => {
|
||||||
|
|
|
@ -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>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue