allow unsubscribe from deleted channels by navigating from sidebar
This commit is contained in:
parent
cba369a5ce
commit
b9fc9b6319
5 changed files with 68 additions and 31 deletions
|
@ -1886,7 +1886,6 @@
|
|||
"No replays found.": "No replays found.",
|
||||
"Replay video available": "Replay video available",
|
||||
"Check for Replays:": "Check for Replays",
|
||||
"A thumbnail is required. Please upload or provide an image URL above.": "A thumbnail is required. Please upload or provide an image URL above.",
|
||||
"You can upload your own recording or select a replay when your stream is over": "You can upload your own recording or select a replay when your stream is over",
|
||||
"This channel isn't staking enough LBRY Credits for inline image previews.": "This channel isn't staking enough LBRY Credits for inline image previews.",
|
||||
"Fromage": "Fromage",
|
||||
|
@ -1894,6 +1893,7 @@
|
|||
"Tá Rolando": "Tá Rolando",
|
||||
"Watch content and earn more Credits for each level unlocked! 10 views required for level 1 (Current Score: 0). Only up to 10 views per day count.": "Watch content and earn more Credits for each level unlocked! 10 views required for level 1 (Current Score: 0). Only up to 10 views per day count.",
|
||||
"Follow your favorite creators and earn more Credits for each level unlocked! Follow 1 creators for level 1 (Current Score: 0).": "Follow your favorite creators and earn more Credits for each level unlocked! Follow 1 creators for level 1 (Current Score: 0).",
|
||||
"Video/Audio": "Video/Audio",
|
||||
"Channel Not Found": "Channel Not Found",
|
||||
"Probably because you didn't make it.": "Probably because you didn't make it.",
|
||||
"--end--": "--end--"
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import ChannelThumbnail from 'component/channelThumbnail';
|
|||
import { parseURI } from 'lbry-redux';
|
||||
import ChannelBlockButton from 'component/channelBlockButton';
|
||||
import ChannelMuteButton from 'component/channelMuteButton';
|
||||
import SubscribeButton from 'component/subscribeButton';
|
||||
|
||||
type Props = {
|
||||
uri: string,
|
||||
|
@ -30,6 +31,7 @@ function AbandonedChannelPreview(props: Props) {
|
|||
<div className="section__actions">
|
||||
<ChannelBlockButton uri={uri} />
|
||||
<ChannelMuteButton uri={uri} />
|
||||
<SubscribeButton uri={uri} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -15,13 +15,14 @@ type SubscriptionArgs = {
|
|||
type Props = {
|
||||
permanentUrl: ?string,
|
||||
isSubscribed: boolean,
|
||||
doChannelSubscribe: SubscriptionArgs => void,
|
||||
doChannelUnsubscribe: SubscriptionArgs => void,
|
||||
doChannelSubscribe: (SubscriptionArgs) => void,
|
||||
doChannelUnsubscribe: (SubscriptionArgs) => void,
|
||||
showSnackBarOnSubscribe: boolean,
|
||||
doToast: ({ message: string }) => void,
|
||||
shrinkOnMobile: boolean,
|
||||
notificationsDisabled: boolean,
|
||||
user: ?User,
|
||||
uri: string,
|
||||
};
|
||||
|
||||
export default function SubscribeButton(props: Props) {
|
||||
|
@ -35,6 +36,7 @@ export default function SubscribeButton(props: Props) {
|
|||
shrinkOnMobile = false,
|
||||
notificationsDisabled,
|
||||
user,
|
||||
uri,
|
||||
} = props;
|
||||
|
||||
const buttonRef = useRef();
|
||||
|
@ -43,6 +45,7 @@ export default function SubscribeButton(props: Props) {
|
|||
isHovering = isMobile ? true : isHovering;
|
||||
const uiNotificationsEnabled = user && user.experimental_ui;
|
||||
|
||||
const { channelName: rawChannelName } = parseURI(uri);
|
||||
const { channelName } = parseURI(permanentUrl);
|
||||
const claimName = '@' + channelName;
|
||||
|
||||
|
@ -55,6 +58,32 @@ export default function SubscribeButton(props: Props) {
|
|||
const label = isMobile && shrinkOnMobile ? '' : unfollowOverride || subscriptionLabel;
|
||||
const titlePrefix = isSubscribed ? __('Unfollow this channel') : __('Follow this channel');
|
||||
|
||||
if (isSubscribed && !permanentUrl && rawChannelName) {
|
||||
return (
|
||||
<div className="button-group">
|
||||
<Button
|
||||
ref={buttonRef}
|
||||
iconColor="red"
|
||||
largestLabel={isMobile && shrinkOnMobile ? '' : subscriptionLabel}
|
||||
icon={ICONS.UNSUBSCRIBE}
|
||||
button={'alt'}
|
||||
requiresAuth={IS_WEB}
|
||||
label={label}
|
||||
title={titlePrefix}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
|
||||
subscriptionHandler({
|
||||
channelName: '@' + rawChannelName,
|
||||
uri: uri,
|
||||
notificationsDisabled: true,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return permanentUrl ? (
|
||||
<div className="button-group">
|
||||
<Button
|
||||
|
@ -66,7 +95,7 @@ export default function SubscribeButton(props: Props) {
|
|||
requiresAuth={IS_WEB}
|
||||
label={label}
|
||||
title={titlePrefix}
|
||||
onClick={e => {
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
|
||||
subscriptionHandler({
|
||||
|
|
|
@ -17,18 +17,18 @@ export default handleActions(
|
|||
const newSubscriptions: Array<Subscription> = state.subscriptions.slice();
|
||||
let newFollowing: Array<Following> = state.following.slice();
|
||||
// prevent duplicates in the sidebar
|
||||
if (!newSubscriptions.some(sub => sub.uri === newSubscription.uri)) {
|
||||
if (!newSubscriptions.some((sub) => sub.uri === newSubscription.uri)) {
|
||||
// $FlowFixMe
|
||||
newSubscriptions.unshift(newSubscription);
|
||||
}
|
||||
|
||||
if (!newFollowing.some(sub => sub.uri === newSubscription.uri)) {
|
||||
if (!newFollowing.some((sub) => sub.uri === newSubscription.uri)) {
|
||||
newFollowing.unshift({
|
||||
uri: newSubscription.uri,
|
||||
notificationsDisabled: newSubscription.notificationsDisabled,
|
||||
});
|
||||
} else {
|
||||
newFollowing = newFollowing.map(following => {
|
||||
newFollowing = newFollowing.map((following) => {
|
||||
if (following.uri === newSubscription.uri) {
|
||||
return {
|
||||
uri: newSubscription.uri,
|
||||
|
@ -50,10 +50,12 @@ export default handleActions(
|
|||
const subscriptionToRemove: Subscription = action.data;
|
||||
const newSubscriptions = state.subscriptions
|
||||
.slice()
|
||||
.filter(subscription => subscription.channelName !== subscriptionToRemove.channelName);
|
||||
.filter(
|
||||
(subscription) => subscription.channelName.toLowerCase() !== subscriptionToRemove.channelName.toLowerCase()
|
||||
);
|
||||
const newFollowing = state.following
|
||||
.slice()
|
||||
.filter(subscription => subscription.uri !== subscriptionToRemove.uri);
|
||||
.filter((subscription) => subscription.uri !== subscriptionToRemove.uri);
|
||||
|
||||
return {
|
||||
...state,
|
||||
|
@ -95,7 +97,7 @@ export default handleActions(
|
|||
if (!subscriptions) {
|
||||
newSubscriptions = state.subscriptions;
|
||||
} else {
|
||||
const parsedSubscriptions = subscriptions.map(uri => {
|
||||
const parsedSubscriptions = subscriptions.map((uri) => {
|
||||
const { channelName } = parseURI(uri);
|
||||
|
||||
return {
|
||||
|
|
|
@ -9,25 +9,25 @@ import {
|
|||
import { swapKeyAndValue } from 'util/swap-json';
|
||||
|
||||
// Returns the entire subscriptions state
|
||||
const selectState = state => state.subscriptions || {};
|
||||
const selectState = (state) => state.subscriptions || {};
|
||||
|
||||
// Returns the list of channel uris a user is subscribed to
|
||||
export const selectSubscriptions = createSelector(
|
||||
selectState,
|
||||
state => state.subscriptions && state.subscriptions.sort((a, b) => a.channelName.localeCompare(b.channelName))
|
||||
(state) => state.subscriptions && state.subscriptions.sort((a, b) => a.channelName.localeCompare(b.channelName))
|
||||
);
|
||||
|
||||
export const selectFollowing = createSelector(selectState, state => state.following && state.following);
|
||||
export const selectFollowing = createSelector(selectState, (state) => state.following && state.following);
|
||||
|
||||
// Fetching list of users subscriptions
|
||||
export const selectIsFetchingSubscriptions = createSelector(selectState, state => state.loading);
|
||||
export const selectIsFetchingSubscriptions = createSelector(selectState, (state) => state.loading);
|
||||
|
||||
// The current view mode on the subscriptions page
|
||||
export const selectViewMode = createSelector(selectState, state => state.viewMode);
|
||||
export const selectViewMode = createSelector(selectState, (state) => state.viewMode);
|
||||
|
||||
// Suggested subscriptions from internal apis
|
||||
export const selectSuggested = createSelector(selectState, state => state.suggested);
|
||||
export const selectIsFetchingSuggested = createSelector(selectState, state => state.loadingSuggested);
|
||||
export const selectSuggested = createSelector(selectState, (state) => state.suggested);
|
||||
export const selectIsFetchingSuggested = createSelector(selectState, (state) => state.loadingSuggested);
|
||||
export const selectSuggestedChannels = createSelector(
|
||||
selectSubscriptions,
|
||||
selectSuggested,
|
||||
|
@ -55,7 +55,7 @@ export const selectSuggestedChannels = createSelector(
|
|||
// If a uri isn't already in the suggested object, add it
|
||||
const suggestedChannels = { ...topSubscribedSuggestions };
|
||||
|
||||
Object.keys(featuredSuggestions).forEach(uri => {
|
||||
Object.keys(featuredSuggestions).forEach((uri) => {
|
||||
if (!suggestedChannels[uri]) {
|
||||
const channelLabel = featuredSuggestions[uri];
|
||||
suggestedChannels[uri] = channelLabel;
|
||||
|
@ -73,15 +73,15 @@ export const selectSuggestedChannels = createSelector(
|
|||
}
|
||||
});
|
||||
|
||||
return Object.keys(suggestedChannels).map(uri => ({
|
||||
return Object.keys(suggestedChannels).map((uri) => ({
|
||||
uri,
|
||||
label: suggestedChannels[uri],
|
||||
}));
|
||||
}
|
||||
);
|
||||
|
||||
export const selectFirstRunCompleted = createSelector(selectState, state => state.firstRunCompleted);
|
||||
export const selectshowSuggestedSubs = createSelector(selectState, state => state.showSuggestedSubs);
|
||||
export const selectFirstRunCompleted = createSelector(selectState, (state) => state.firstRunCompleted);
|
||||
export const selectshowSuggestedSubs = createSelector(selectState, (state) => state.showSuggestedSubs);
|
||||
|
||||
// Fetching any claims that are a part of a users subscriptions
|
||||
export const selectSubscriptionsBeingFetched = createSelector(
|
||||
|
@ -89,7 +89,7 @@ export const selectSubscriptionsBeingFetched = createSelector(
|
|||
selectAllFetchingChannelClaims,
|
||||
(subscriptions, fetchingChannelClaims) => {
|
||||
const fetchingSubscriptionMap = {};
|
||||
subscriptions.forEach(sub => {
|
||||
subscriptions.forEach((sub) => {
|
||||
const isFetching = fetchingChannelClaims && fetchingChannelClaims[sub.uri];
|
||||
if (isFetching) {
|
||||
fetchingSubscriptionMap[sub.uri] = true;
|
||||
|
@ -102,17 +102,17 @@ export const selectSubscriptionsBeingFetched = createSelector(
|
|||
|
||||
// Returns true if a user is subscribed to the channel associated with the uri passed in
|
||||
// Accepts content or channel uris
|
||||
export const makeSelectChannelInSubscriptions = uri =>
|
||||
createSelector(selectSubscriptions, subscriptions => subscriptions.some(sub => sub.uri === uri));
|
||||
export const makeSelectChannelInSubscriptions = (uri) =>
|
||||
createSelector(selectSubscriptions, (subscriptions) => subscriptions.some((sub) => sub.uri === uri));
|
||||
|
||||
export const makeSelectIsSubscribed = uri =>
|
||||
export const makeSelectIsSubscribed = (uri) =>
|
||||
createSelector(
|
||||
selectSubscriptions,
|
||||
makeSelectChannelForClaimUri(uri, true),
|
||||
makeSelectClaimForUri(uri),
|
||||
(subscriptions, channelUri, claim) => {
|
||||
if (channelUri) {
|
||||
return subscriptions.some(sub => sub.uri === channelUri);
|
||||
return subscriptions.some((sub) => sub.uri === channelUri);
|
||||
}
|
||||
|
||||
// If we couldn't get a channel uri from the claim uri, the uri passed in might be a channel already
|
||||
|
@ -123,21 +123,25 @@ export const makeSelectIsSubscribed = uri =>
|
|||
|
||||
if (isChannel && claim) {
|
||||
const uri = claim.permanent_url;
|
||||
return subscriptions.some(sub => sub.uri === uri);
|
||||
return subscriptions.some((sub) => sub.uri === uri);
|
||||
}
|
||||
|
||||
if (isChannel && !claim) {
|
||||
return subscriptions.some((sub) => sub.uri === uri);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
export const makeSelectNotificationsDisabled = uri =>
|
||||
export const makeSelectNotificationsDisabled = (uri) =>
|
||||
createSelector(
|
||||
selectFollowing,
|
||||
makeSelectChannelForClaimUri(uri, true),
|
||||
makeSelectClaimForUri(uri),
|
||||
(following, channelUri, claim) => {
|
||||
if (channelUri) {
|
||||
return following.some(following => following.uri === channelUri && following.notificationsDisabled);
|
||||
return following.some((following) => following.uri === channelUri && following.notificationsDisabled);
|
||||
}
|
||||
|
||||
// If we couldn't get a channel uri from the claim uri, the uri passed in might be a channel already
|
||||
|
@ -148,7 +152,7 @@ export const makeSelectNotificationsDisabled = uri =>
|
|||
|
||||
if (isChannel && claim) {
|
||||
const uri = claim.permanent_url;
|
||||
const disabled = following.some(sub => {
|
||||
const disabled = following.some((sub) => {
|
||||
return sub.uri === uri && sub.notificationsDisabled === true;
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in a new issue