2018-11-21 22:20:55 +01:00
|
|
|
import { SUGGESTED_FEATURED, SUGGESTED_TOP_SUBSCRIBED } from 'constants/subscriptions';
|
2017-12-21 18:32:51 +01:00
|
|
|
import { createSelector } from 'reselect';
|
2018-05-07 06:50:55 +02:00
|
|
|
import {
|
|
|
|
selectAllFetchingChannelClaims,
|
2018-10-19 22:38:07 +02:00
|
|
|
makeSelectChannelForClaimUri,
|
|
|
|
parseURI,
|
2019-09-04 18:00:56 +02:00
|
|
|
makeSelectClaimForUri,
|
2018-05-07 06:50:55 +02:00
|
|
|
} from 'lbry-redux';
|
2018-11-21 22:20:55 +01:00
|
|
|
import { swapKeyAndValue } from 'util/swap-json';
|
2017-12-08 21:14:35 +01:00
|
|
|
|
2018-10-19 22:38:07 +02:00
|
|
|
// Returns the entire subscriptions state
|
2017-12-21 18:32:51 +01:00
|
|
|
const selectState = state => state.subscriptions || {};
|
2017-12-08 21:14:35 +01:00
|
|
|
|
2018-10-19 22:38:07 +02:00
|
|
|
// Returns the list of channel uris a user is subscribed to
|
2019-03-05 05:46:57 +01:00
|
|
|
export const selectSubscriptions = createSelector(
|
|
|
|
selectState,
|
2019-06-19 07:05:43 +02:00
|
|
|
state => state.subscriptions && state.subscriptions.sort((a, b) => a.channelName.localeCompare(b.channelName))
|
2019-03-05 05:46:57 +01:00
|
|
|
);
|
2018-10-19 22:38:07 +02:00
|
|
|
|
2020-11-02 17:51:08 +01:00
|
|
|
export const selectFollowing = createSelector(selectState, state => state.following && state.following);
|
|
|
|
|
2018-10-19 22:38:07 +02:00
|
|
|
// Fetching list of users subscriptions
|
2020-11-02 17:51:08 +01:00
|
|
|
export const selectIsFetchingSubscriptions = createSelector(selectState, state => state.loading);
|
2018-05-07 06:50:55 +02:00
|
|
|
|
2018-10-19 22:38:07 +02:00
|
|
|
// The current view mode on the subscriptions page
|
2020-11-02 17:51:08 +01:00
|
|
|
export const selectViewMode = createSelector(selectState, state => state.viewMode);
|
2018-03-26 09:31:52 +02:00
|
|
|
|
2018-11-21 22:20:55 +01:00
|
|
|
// Suggested subscriptions from internal apis
|
2020-11-02 17:51:08 +01:00
|
|
|
export const selectSuggested = createSelector(selectState, state => state.suggested);
|
|
|
|
export const selectIsFetchingSuggested = createSelector(selectState, state => state.loadingSuggested);
|
2018-11-21 22:20:55 +01:00
|
|
|
export const selectSuggestedChannels = createSelector(
|
|
|
|
selectSubscriptions,
|
|
|
|
selectSuggested,
|
|
|
|
(userSubscriptions, suggested) => {
|
|
|
|
if (!suggested) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Swap the key/value because we will use the uri for everything, this just makes it easier
|
|
|
|
// suggested is returned from the api with the form:
|
|
|
|
// {
|
|
|
|
// featured: { "Channel label": uri, ... },
|
|
|
|
// top_subscribed: { "@channel": uri, ... }
|
|
|
|
// top_bid: { "@channel": uri, ... }
|
|
|
|
// }
|
|
|
|
// To properly compare the suggested subscriptions from our current subscribed channels
|
|
|
|
// We only care about the uri, not the label
|
|
|
|
|
|
|
|
// We also only care about top_subscribed and featured
|
|
|
|
// top_bid could just be porn or a channel with no content
|
|
|
|
const topSubscribedSuggestions = swapKeyAndValue(suggested[SUGGESTED_TOP_SUBSCRIBED]);
|
|
|
|
const featuredSuggestions = swapKeyAndValue(suggested[SUGGESTED_FEATURED]);
|
|
|
|
|
|
|
|
// Make sure there are no duplicates
|
|
|
|
// If a uri isn't already in the suggested object, add it
|
|
|
|
const suggestedChannels = { ...topSubscribedSuggestions };
|
|
|
|
|
|
|
|
Object.keys(featuredSuggestions).forEach(uri => {
|
|
|
|
if (!suggestedChannels[uri]) {
|
|
|
|
const channelLabel = featuredSuggestions[uri];
|
|
|
|
suggestedChannels[uri] = channelLabel;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
userSubscriptions.forEach(({ uri }) => {
|
|
|
|
// Note to passer bys:
|
|
|
|
// Maybe we should just remove the `lbry://` prefix from subscription uris
|
|
|
|
// Most places don't store them like that
|
|
|
|
const subscribedUri = uri.slice('lbry://'.length);
|
|
|
|
|
|
|
|
if (suggestedChannels[subscribedUri]) {
|
|
|
|
delete suggestedChannels[subscribedUri];
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2019-06-11 20:10:58 +02:00
|
|
|
return Object.keys(suggestedChannels).map(uri => ({
|
|
|
|
uri,
|
|
|
|
label: suggestedChannels[uri],
|
|
|
|
}));
|
2018-11-21 22:20:55 +01:00
|
|
|
}
|
|
|
|
);
|
|
|
|
|
2020-11-02 17:51:08 +01:00
|
|
|
export const selectFirstRunCompleted = createSelector(selectState, state => state.firstRunCompleted);
|
|
|
|
export const selectshowSuggestedSubs = createSelector(selectState, state => state.showSuggestedSubs);
|
2018-11-21 22:20:55 +01:00
|
|
|
|
2018-10-19 22:38:07 +02:00
|
|
|
// Fetching any claims that are a part of a users subscriptions
|
|
|
|
export const selectSubscriptionsBeingFetched = createSelector(
|
|
|
|
selectSubscriptions,
|
|
|
|
selectAllFetchingChannelClaims,
|
|
|
|
(subscriptions, fetchingChannelClaims) => {
|
|
|
|
const fetchingSubscriptionMap = {};
|
|
|
|
subscriptions.forEach(sub => {
|
|
|
|
const isFetching = fetchingChannelClaims && fetchingChannelClaims[sub.uri];
|
|
|
|
if (isFetching) {
|
|
|
|
fetchingSubscriptionMap[sub.uri] = true;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
return fetchingSubscriptionMap;
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
// Returns true if a user is subscribed to the channel associated with the uri passed in
|
|
|
|
// Accepts content or channel uris
|
2020-02-05 07:14:37 +01:00
|
|
|
export const makeSelectChannelInSubscriptions = uri =>
|
2020-11-02 17:51:08 +01:00
|
|
|
createSelector(selectSubscriptions, subscriptions => subscriptions.some(sub => sub.uri === uri));
|
2020-02-05 07:14:37 +01:00
|
|
|
|
2018-10-19 22:38:07 +02:00
|
|
|
export const makeSelectIsSubscribed = uri =>
|
|
|
|
createSelector(
|
|
|
|
selectSubscriptions,
|
|
|
|
makeSelectChannelForClaimUri(uri, true),
|
2019-09-04 18:00:56 +02:00
|
|
|
makeSelectClaimForUri(uri),
|
|
|
|
(subscriptions, channelUri, claim) => {
|
2018-10-19 22:38:07 +02:00
|
|
|
if (channelUri) {
|
|
|
|
return subscriptions.some(sub => sub.uri === channelUri);
|
2018-05-07 06:50:55 +02:00
|
|
|
}
|
|
|
|
|
2018-10-19 22:38:07 +02:00
|
|
|
// If we couldn't get a channel uri from the claim uri, the uri passed in might be a channel already
|
2019-08-14 20:09:45 +02:00
|
|
|
let isChannel;
|
|
|
|
try {
|
|
|
|
({ isChannel } = parseURI(uri));
|
|
|
|
} catch (e) {}
|
|
|
|
|
2019-09-04 18:00:56 +02:00
|
|
|
if (isChannel && claim) {
|
|
|
|
const uri = claim.permanent_url;
|
|
|
|
return subscriptions.some(sub => sub.uri === uri);
|
2018-10-19 22:38:07 +02:00
|
|
|
}
|
2018-10-10 07:22:06 +02:00
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2018-10-19 22:38:07 +02:00
|
|
|
);
|
2018-11-27 17:49:52 +01:00
|
|
|
|
2020-11-02 17:51:08 +01:00
|
|
|
export const makeSelectNotificationsDisabled = uri =>
|
2018-11-27 17:49:52 +01:00
|
|
|
createSelector(
|
2020-11-02 17:51:08 +01:00
|
|
|
selectFollowing,
|
|
|
|
makeSelectChannelForClaimUri(uri, true),
|
|
|
|
makeSelectClaimForUri(uri),
|
|
|
|
(following, channelUri, claim) => {
|
|
|
|
if (channelUri) {
|
|
|
|
return following.some(following => following.uri === channelUri && following.notificationsDisabled);
|
2018-11-27 17:49:52 +01:00
|
|
|
}
|
2018-11-29 00:21:33 +01:00
|
|
|
|
2020-11-02 17:51:08 +01:00
|
|
|
// If we couldn't get a channel uri from the claim uri, the uri passed in might be a channel already
|
|
|
|
let isChannel;
|
|
|
|
try {
|
|
|
|
({ isChannel } = parseURI(uri));
|
|
|
|
} catch (e) {}
|
|
|
|
|
|
|
|
if (isChannel && claim) {
|
|
|
|
const uri = claim.permanent_url;
|
|
|
|
const disabled = following.some(sub => {
|
|
|
|
return sub.uri === uri && sub.notificationsDisabled === true;
|
|
|
|
});
|
|
|
|
|
|
|
|
return disabled;
|
2018-11-27 17:49:52 +01:00
|
|
|
}
|
|
|
|
|
2020-11-02 17:51:08 +01:00
|
|
|
return true;
|
2018-11-27 17:49:52 +01:00
|
|
|
}
|
|
|
|
);
|