Preferences #56
13 changed files with 197 additions and 68 deletions
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2018 LBRY Inc
|
||||
Copyright (c) 2017-2019 LBRY Inc
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish,distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
|
8
package-lock.json
generated
8
package-lock.json
generated
|
@ -5640,8 +5640,8 @@
|
|||
}
|
||||
},
|
||||
"lbry-redux": {
|
||||
"version": "github:lbryio/lbry-redux#23bcde0539a27fb19bf3a7d87683279194e02046",
|
||||
"from": "github:lbryio/lbry-redux#23bcde0539a27fb19bf3a7d87683279194e02046",
|
||||
"version": "github:lbryio/lbry-redux#f06e1e64a8587a183bd7333f628fca821fe81fa4",
|
||||
"from": "github:lbryio/lbry-redux#f06e1e64a8587a183bd7333f628fca821fe81fa4",
|
||||
"requires": {
|
||||
"proxy-polyfill": "0.1.6",
|
||||
"reselect": "^3.0.0",
|
||||
|
@ -5649,8 +5649,8 @@
|
|||
}
|
||||
},
|
||||
"lbryinc": {
|
||||
"version": "github:lbryio/lbryinc#67bb3e215be3f13605c5e3f9f2b0e2fb880724cf",
|
||||
"from": "github:lbryio/lbryinc#67bb3e215be3f13605c5e3f9f2b0e2fb880724cf",
|
||||
"version": "github:lbryio/lbryinc#02d8571cd7fafd00d1a60f133d884eb8c5f1a306",
|
||||
"from": "github:lbryio/lbryinc#02d8571cd7fafd00d1a60f133d884eb8c5f1a306",
|
||||
"requires": {
|
||||
"reselect": "^3.0.0"
|
||||
}
|
||||
|
|
4
src/component/modalSuggestedSubscriptions/index.js
Normal file
4
src/component/modalSuggestedSubscriptions/index.js
Normal file
|
@ -0,0 +1,4 @@
|
|||
import { connect } from 'react-redux';
|
||||
import ModalSuggestedSubscriptions from './view';
|
||||
|
||||
export default connect()(ModalSuggestedSubscriptions);
|
26
src/component/modalSuggestedSubscriptions/view.js
Normal file
26
src/component/modalSuggestedSubscriptions/view.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
import React from 'react';
|
||||
import { ScrollView, Text, TouchableOpacity, View } from 'react-native';
|
||||
import modalStyle from 'styles/modal';
|
||||
import subscriptionsStyle from 'styles/subscriptions';
|
||||
import Button from 'component/button';
|
||||
import Colors from 'styles/colors';
|
||||
import SuggestedSubscriptions from 'component/suggestedSubscriptions';
|
||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||
import Icon from 'react-native-vector-icons/FontAwesome5';
|
||||
|
||||
export default class ModalSuggestedSubcriptions extends React.PureComponent {
|
||||
render() {
|
||||
const { navigation, onDonePress, onOverlayPress } = this.props;
|
||||
|
||||
return (
|
||||
<TouchableOpacity style={modalStyle.overlay} activeOpacity={1} onPress={onOverlayPress}>
|
||||
<TouchableOpacity style={[modalStyle.container, subscriptionsStyle.modalContainer]} activeOpacity={1}>
|
||||
<SuggestedSubscriptions inModal navigation={navigation} />
|
||||
<View style={modalStyle.buttons}>
|
||||
<Button style={modalStyle.doneButton} text={'Done'} onPress={onDonePress} />
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { doClaimSearch, selectFetchingClaimSearch, selectClaimSearchByQuery, selectFollowedTags } from 'lbry-redux';
|
||||
import { selectSuggestedChannels, selectIsFetchingSuggested } from 'lbryinc';
|
||||
import { selectShowNsfw } from 'redux/selectors/settings';
|
||||
import SuggestedSubscriptions from './view';
|
||||
|
||||
const select = state => ({
|
||||
|
@ -8,6 +9,7 @@ const select = state => ({
|
|||
suggested: selectSuggestedChannels(state),
|
||||
loading: selectIsFetchingSuggested(state) || selectFetchingClaimSearch(state),
|
||||
claimSearchByQuery: selectClaimSearchByQuery(state),
|
||||
showNsfwContent: selectShowNsfw(state),
|
||||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import { ActivityIndicator, FlatList, SectionList, Text, View } from 'react-native';
|
||||
import { createNormalizedClaimSearchKey, normalizeURI } from 'lbry-redux';
|
||||
import { ActivityIndicator, SectionList, Text, View } from 'react-native';
|
||||
import { MATURE_TAGS, createNormalizedClaimSearchKey, normalizeURI } from 'lbry-redux';
|
||||
import { __, navigateToUri } from 'utils/helper';
|
||||
import SubscribeButton from 'component/subscribeButton';
|
||||
import SuggestedSubscriptionItem from 'component/suggestedSubscriptionItem';
|
||||
|
@ -16,13 +16,16 @@ class SuggestedSubscriptions extends React.PureComponent {
|
|||
};
|
||||
|
||||
componentDidMount() {
|
||||
const { claimSearch, followedTags } = this.props;
|
||||
const { claimSearch, followedTags, showNsfwContent } = this.props;
|
||||
const options = {
|
||||
any_tags: _.shuffle(followedTags.map(tag => tag.name)).slice(0, 3),
|
||||
page: 1,
|
||||
no_totals: true,
|
||||
claim_type: 'channel',
|
||||
};
|
||||
if (!showNsfwContent) {
|
||||
options.not_tags = MATURE_TAGS;
|
||||
}
|
||||
this.setState({ options });
|
||||
claimSearch(options);
|
||||
}
|
||||
|
@ -35,7 +38,7 @@ class SuggestedSubscriptions extends React.PureComponent {
|
|||
const suggestedUris = suggested ? suggested.map(suggested => suggested.uri) : [];
|
||||
return [
|
||||
{
|
||||
title: __('Tags you follow'),
|
||||
title: __('Suggested channels'),
|
||||
data: claimSearchUris ? claimSearchUris.filter(uri => !suggestedUris.includes(uri)) : [],
|
||||
},
|
||||
{
|
||||
|
@ -46,7 +49,7 @@ class SuggestedSubscriptions extends React.PureComponent {
|
|||
};
|
||||
|
||||
render() {
|
||||
const { suggested, loading, navigation } = this.props;
|
||||
const { suggested, inModal, loading, navigation } = this.props;
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
|
@ -58,8 +61,10 @@ class SuggestedSubscriptions extends React.PureComponent {
|
|||
|
||||
return (
|
||||
<SectionList
|
||||
style={subscriptionsStyle.scrollContainer}
|
||||
contentContainerStyle={subscriptionsStyle.suggestedScrollPadding}
|
||||
style={inModal ? subscriptionsStyle.modalScrollContainer : subscriptionsStyle.scrollContainer}
|
||||
contentContainerStyle={
|
||||
inModal ? subscriptionsStyle.modalSuggestedScrollContent : subscriptionsStyle.suggestedScrollContent
|
||||
}
|
||||
renderItem={({ item, index, section }) => (
|
||||
<SuggestedSubscriptionItem key={item} uri={normalizeURI(item)} navigation={navigation} />
|
||||
)}
|
||||
|
|
|
@ -61,11 +61,10 @@ class DiscoverPage extends React.PureComponent {
|
|||
}
|
||||
});
|
||||
|
||||
const { sortByItem, fetchRewardedContent, fetchSubscriptions, fileList, followedTags } = this.props;
|
||||
const { sortByItem, fetchRewardedContent, fileList, followedTags } = this.props;
|
||||
|
||||
this.buildTagCollection(followedTags);
|
||||
fetchRewardedContent();
|
||||
fetchSubscriptions();
|
||||
fileList();
|
||||
|
||||
this.handleSortByItemSelected(sortByItem);
|
||||
|
@ -88,9 +87,11 @@ class DiscoverPage extends React.PureComponent {
|
|||
}
|
||||
|
||||
onComponentFocused = () => {
|
||||
const { pushDrawerStack } = this.props;
|
||||
const { fetchSubscriptions, pushDrawerStack } = this.props;
|
||||
// pushDrawerStack();
|
||||
NativeModules.Firebase.setCurrentScreen('Your tags');
|
||||
NativeModules.Firebase.setCurrentScreen('Your tags').then(result => {
|
||||
fetchSubscriptions();
|
||||
});
|
||||
};
|
||||
|
||||
handleSortByItemSelected = item => {
|
||||
|
@ -127,44 +128,39 @@ class DiscoverPage extends React.PureComponent {
|
|||
const { unreadSubscriptions, enabledChannelNotifications } = this.props;
|
||||
|
||||
const utility = NativeModules.UtilityModule;
|
||||
if (utility) {
|
||||
const hasUnread =
|
||||
prevProps.unreadSubscriptions &&
|
||||
prevProps.unreadSubscriptions.length !== unreadSubscriptions.length &&
|
||||
unreadSubscriptions.length > 0;
|
||||
const hasUnread =
|
||||
prevProps.unreadSubscriptions &&
|
||||
prevProps.unreadSubscriptions.length !== unreadSubscriptions.length &&
|
||||
unreadSubscriptions.length > 0;
|
||||
|
||||
if (hasUnread) {
|
||||
unreadSubscriptions.map(({ channel, uris }) => {
|
||||
const { claimName: channelName } = parseURI(channel);
|
||||
if (hasUnread) {
|
||||
unreadSubscriptions.map(({ channel, uris }) => {
|
||||
const { claimName: channelName } = parseURI(channel);
|
||||
|
||||
// check if notifications are enabled for the channel
|
||||
if (enabledChannelNotifications.indexOf(channelName) > -1) {
|
||||
uris.forEach(uri => {
|
||||
Lbry.resolve({ urls: uri }).then(result => {
|
||||
const sub = result[uri].claim;
|
||||
if (sub && sub.value && sub.value.stream) {
|
||||
let isPlayable = false;
|
||||
const source = sub.value.stream.source;
|
||||
const metadata = sub.value.stream.metadata;
|
||||
if (source) {
|
||||
isPlayable =
|
||||
source.contentType && ['audio', 'video'].indexOf(source.contentType.substring(0, 5)) > -1;
|
||||
}
|
||||
if (metadata) {
|
||||
utility.showNotificationForContent(
|
||||
uri,
|
||||
metadata.title,
|
||||
channelName,
|
||||
metadata.thumbnail,
|
||||
isPlayable
|
||||
);
|
||||
}
|
||||
// check if notifications are enabled for the channel
|
||||
if (enabledChannelNotifications.includes(channelName)) {
|
||||
uris.forEach(uri => {
|
||||
Lbry.resolve({ urls: uri }).then(result => {
|
||||
const sub = result[uri];
|
||||
|
||||
if (sub && sub.value) {
|
||||
const { source, title, thumbnail } = sub.value;
|
||||
const isPlayable =
|
||||
source && source.media_type && ['audio', 'video'].includes(source.media_type.substring(0, 5));
|
||||
if (title) {
|
||||
utility.showNotificationForContent(
|
||||
uri,
|
||||
title,
|
||||
channelName,
|
||||
thumbnail ? thumbnail.url : null,
|
||||
isPlayable
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import {
|
|||
Alert,
|
||||
DeviceEventEmitter,
|
||||
Dimensions,
|
||||
Linking,
|
||||
NativeModules,
|
||||
ScrollView,
|
||||
StatusBar,
|
||||
|
@ -968,6 +969,12 @@ class FilePage extends React.PureComponent {
|
|||
onPress={this.onSaveFilePressed}
|
||||
/>
|
||||
)}
|
||||
<Button
|
||||
style={[filePageStyle.actionButton, filePageStyle.reportButton]}
|
||||
theme={'light'}
|
||||
icon={'flag'}
|
||||
onPress={() => Linking.openURL(`https://lbry.com/dmca/${claim.claim_id}`)}
|
||||
/>
|
||||
<Button
|
||||
style={[filePageStyle.actionButton, filePageStyle.tipButton]}
|
||||
theme={'light'}
|
||||
|
|
|
@ -12,7 +12,7 @@ import {
|
|||
View,
|
||||
} from 'react-native';
|
||||
import Colors from 'styles/colors';
|
||||
import Constants from 'constants';
|
||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||
import Icon from 'react-native-vector-icons/FontAwesome5';
|
||||
import firstRunStyle from 'styles/firstRun';
|
||||
|
||||
|
@ -45,8 +45,8 @@ class SkipAccountPage extends React.PureComponent {
|
|||
/>
|
||||
</View>
|
||||
<Text style={firstRunStyle.rowParagraph}>
|
||||
I understand that by uninstalling LBRY I will lose any balances or published content with no recovery
|
||||
option.
|
||||
I understand that by uninstalling LBRY I will lose any balances or published content with no recovery option
|
||||
if it is not backed up manually (see wallet page)
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
|
|
@ -25,6 +25,7 @@ import FileItem from 'component/fileItem';
|
|||
import Icon from 'react-native-vector-icons/FontAwesome5';
|
||||
import Link from 'component/link';
|
||||
import ModalPicker from 'component/modalPicker';
|
||||
import ModalSuggestedSubscriptions from 'component/modalSuggestedSubscriptions';
|
||||
import SubscribedChannelList from 'component/subscribedChannelList';
|
||||
import SuggestedSubscriptions from 'component/suggestedSubscriptions';
|
||||
import UriBar from 'component/uriBar';
|
||||
|
@ -34,6 +35,7 @@ class SubscriptionsPage extends React.PureComponent {
|
|||
showingSuggestedSubs: false,
|
||||
showSortPicker: false,
|
||||
showTimePicker: false,
|
||||
showModalSuggestedSubs: false,
|
||||
orderBy: ['release_time'],
|
||||
filteredChannels: [],
|
||||
currentSortByItem: Constants.CLAIM_SEARCH_SORT_BY_ITEMS[1], // should always default to sorting subscriptions by new
|
||||
|
@ -122,7 +124,7 @@ class SubscriptionsPage extends React.PureComponent {
|
|||
unreadSubscriptions,
|
||||
navigation,
|
||||
} = this.props;
|
||||
const { currentSortByItem, filteredChannels, showSortPicker, showTimePicker } = this.state;
|
||||
const { currentSortByItem, filteredChannels, showModalSuggestedSubs, showSortPicker, showTimePicker } = this.state;
|
||||
|
||||
const numberOfSubscriptions = subscribedChannels ? subscribedChannels.length : 0;
|
||||
const hasSubscriptions = numberOfSubscriptions > 0;
|
||||
|
@ -151,23 +153,31 @@ class SubscriptionsPage extends React.PureComponent {
|
|||
</View>
|
||||
{!this.state.showingSuggestedSubs && hasSubscriptions && (
|
||||
<View style={subscriptionsStyle.pickerRow}>
|
||||
<TouchableOpacity
|
||||
style={subscriptionsStyle.tagSortBy}
|
||||
onPress={() => this.setState({ showSortPicker: true })}
|
||||
>
|
||||
<Text style={subscriptionsStyle.tagSortText}>{currentSortByItem.label.split(' ')[0]}</Text>
|
||||
<Icon style={subscriptionsStyle.tagSortIcon} name={'sort-down'} size={14} />
|
||||
</TouchableOpacity>
|
||||
|
||||
{Constants.SORT_BY_TOP === currentSortByItem.name && (
|
||||
<View style={subscriptionsStyle.leftPickerRow}>
|
||||
<TouchableOpacity
|
||||
style={subscriptionsStyle.tagSortBy}
|
||||
onPress={() => this.setState({ showTimePicker: true })}
|
||||
onPress={() => this.setState({ showSortPicker: true })}
|
||||
>
|
||||
<Text style={subscriptionsStyle.tagSortText}>{timeItem.label}</Text>
|
||||
<Text style={subscriptionsStyle.tagSortText}>{currentSortByItem.label.split(' ')[0]}</Text>
|
||||
<Icon style={subscriptionsStyle.tagSortIcon} name={'sort-down'} size={14} />
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
|
||||
{Constants.SORT_BY_TOP === currentSortByItem.name && (
|
||||
<TouchableOpacity
|
||||
style={subscriptionsStyle.tagSortBy}
|
||||
onPress={() => this.setState({ showTimePicker: true })}
|
||||
>
|
||||
<Text style={subscriptionsStyle.tagSortText}>{timeItem.label}</Text>
|
||||
<Icon style={subscriptionsStyle.tagSortIcon} name={'sort-down'} size={14} />
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
</View>
|
||||
|
||||
<Link
|
||||
style={subscriptionsStyle.suggestedLink}
|
||||
text={'Suggested'}
|
||||
onPress={() => this.setState({ showModalSuggestedSubs: true })}
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
{!this.state.showingSuggestedSubs && hasSubscriptions && !loading && (
|
||||
|
@ -223,7 +233,9 @@ class SubscriptionsPage extends React.PureComponent {
|
|||
</View>
|
||||
)}
|
||||
|
||||
{!showSortPicker && !showTimePicker && <FloatingWalletBalance navigation={navigation} />}
|
||||
{!showSortPicker && !showTimePicker && !showModalSuggestedSubs && (
|
||||
<FloatingWalletBalance navigation={navigation} />
|
||||
)}
|
||||
{showSortPicker && (
|
||||
<ModalPicker
|
||||
title={__('Sort content by')}
|
||||
|
@ -242,6 +254,13 @@ class SubscriptionsPage extends React.PureComponent {
|
|||
items={Constants.CLAIM_SEARCH_TIME_ITEMS}
|
||||
/>
|
||||
)}
|
||||
{showModalSuggestedSubs && (
|
||||
<ModalSuggestedSubscriptions
|
||||
navigation={navigation}
|
||||
onOverlayPress={() => this.setState({ showModalSuggestedSubs: false })}
|
||||
onDonePress={() => this.setState({ showModalSuggestedSubs: false })}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -322,6 +322,9 @@ const filePageStyle = StyleSheet.create({
|
|||
saveFileButton: {
|
||||
marginRight: 8,
|
||||
},
|
||||
reportButton: {
|
||||
marginRight: 8,
|
||||
},
|
||||
tagContainer: {
|
||||
marginLeft: 12,
|
||||
marginRight: 12,
|
||||
|
|
48
src/styles/modal.js
Normal file
48
src/styles/modal.js
Normal file
|
@ -0,0 +1,48 @@
|
|||
import { StyleSheet } from 'react-native';
|
||||
import Colors from './colors';
|
||||
|
||||
const modalPickerStyle = StyleSheet.create({
|
||||
overlay: {
|
||||
backgroundColor: '#00000055',
|
||||
flex: 1,
|
||||
position: 'absolute',
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
zIndex: 300,
|
||||
},
|
||||
overlayTouchArea: {
|
||||
position: 'absolute',
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
},
|
||||
container: {
|
||||
position: 'absolute',
|
||||
left: 8,
|
||||
right: 8,
|
||||
bottom: 8,
|
||||
borderRadius: 8,
|
||||
backgroundColor: Colors.White,
|
||||
overflow: 'hidden',
|
||||
},
|
||||
paddedContatiner: {
|
||||
padding: 12,
|
||||
},
|
||||
buttons: {
|
||||
marginTop: 16,
|
||||
left: 8,
|
||||
bottom: 8,
|
||||
position: 'absolute',
|
||||
},
|
||||
doneButton: {
|
||||
alignSelf: 'flex-start',
|
||||
backgroundColor: Colors.LbryGreen,
|
||||
paddingLeft: 16,
|
||||
paddingRight: 16,
|
||||
},
|
||||
});
|
||||
|
||||
export default modalPickerStyle;
|
|
@ -13,7 +13,7 @@ const subscriptionsStyle = StyleSheet.create({
|
|||
suggestedSubsContainer: {
|
||||
flex: 1,
|
||||
},
|
||||
suggestedScrollPadding: {
|
||||
suggestedScrollContent: {
|
||||
paddingTop: 8,
|
||||
},
|
||||
button: {
|
||||
|
@ -159,6 +159,7 @@ const subscriptionsStyle = StyleSheet.create({
|
|||
pickerRow: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
marginLeft: 16,
|
||||
marginRight: 16,
|
||||
marginTop: 8,
|
||||
|
@ -245,6 +246,24 @@ const subscriptionsStyle = StyleSheet.create({
|
|||
marginRight: 4,
|
||||
marginBottom: 4,
|
||||
},
|
||||
leftPickerRow: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
},
|
||||
suggestedLink: {
|
||||
fontFamily: 'Inter-UI-Regular',
|
||||
fontSize: 14,
|
||||
},
|
||||
modalContainer: {
|
||||
height: '80%',
|
||||
backgroundColor: Colors.PageBackground,
|
||||
},
|
||||
modalScrollContainer: {
|
||||
marginBottom: 50,
|
||||
},
|
||||
modalSuggestedScrollContent: {
|
||||
paddingTop: 16,
|
||||
},
|
||||
});
|
||||
|
||||
export default subscriptionsStyle;
|
||||
|
|
Loading…
Reference in a new issue