Add a clear function when a channel selector component is used

- this way, you can choose an active channel for something like commenting but when that component is unmounted, you always go back to the default channel (like leaving page)
This commit is contained in:
Rafael 2022-05-04 10:07:51 -03:00 committed by Thomas Zarebczan
parent 7eb5eb9996
commit f2558f19f9
5 changed files with 55 additions and 41 deletions

View file

@ -1,9 +1,11 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import * as SETTINGS from 'constants/settings';
import { selectMyChannelClaims, selectClaimsByUri, selectOdyseeMembershipForUri } from 'redux/selectors/claims'; import { selectMyChannelClaims, selectClaimsByUri, selectOdyseeMembershipForUri } from 'redux/selectors/claims';
import { selectActiveChannelClaim, selectIncognito } from 'redux/selectors/app'; import { selectActiveChannelClaim, selectIncognito } from 'redux/selectors/app';
import { doSetActiveChannel, doSetIncognito } from 'redux/actions/app'; import { doSetActiveChannel, doSetIncognito } from 'redux/actions/app';
import { doFetchUserMemberships } from 'redux/actions/user'; import { doFetchUserMemberships } from 'redux/actions/user';
import { doSetClientSetting } from 'redux/actions/settings'; import { doSetClientSetting } from 'redux/actions/settings';
import { selectClientSetting } from 'redux/selectors/settings';
import ChannelSelector from './view'; import ChannelSelector from './view';
const select = (state, props) => { const select = (state, props) => {
@ -15,6 +17,7 @@ const select = (state, props) => {
incognito: selectIncognito(state), incognito: selectIncognito(state),
odyseeMembershipByUri: (uri) => selectOdyseeMembershipForUri(state, uri), odyseeMembershipByUri: (uri) => selectOdyseeMembershipForUri(state, uri),
claimsByUri: selectClaimsByUri(state), claimsByUri: selectClaimsByUri(state),
hasDefaultChannel: Boolean(selectClientSetting(state, SETTINGS.ACTIVE_CHANNEL_CLAIM)),
}; };
}; };

View file

@ -18,7 +18,7 @@ type Props = {
onChannelSelect: (url: string) => void, onChannelSelect: (url: string) => void,
hideAnon?: boolean, hideAnon?: boolean,
activeChannelClaim: ?ChannelClaim, activeChannelClaim: ?ChannelClaim,
doSetActiveChannel: (string) => void, doSetActiveChannel: (claimId: ?string, override?: boolean) => void,
incognito: boolean, incognito: boolean,
doSetIncognito: (boolean) => void, doSetIncognito: (boolean) => void,
claimsByUri: { [string]: any }, claimsByUri: { [string]: any },
@ -27,6 +27,7 @@ type Props = {
storeSelection?: boolean, storeSelection?: boolean,
doSetClientSetting: (key: string, value: string, pushPrefs: boolean) => void, doSetClientSetting: (key: string, value: string, pushPrefs: boolean) => void,
isHeaderMenu: boolean, isHeaderMenu: boolean,
hasDefaultChannel: boolean,
}; };
export default function ChannelSelector(props: Props) { export default function ChannelSelector(props: Props) {
@ -34,7 +35,6 @@ export default function ChannelSelector(props: Props) {
channels, channels,
activeChannelClaim, activeChannelClaim,
doSetActiveChannel, doSetActiveChannel,
hideAnon = false,
incognito, incognito,
doSetIncognito, doSetIncognito,
odyseeMembershipByUri, odyseeMembershipByUri,
@ -43,8 +43,13 @@ export default function ChannelSelector(props: Props) {
storeSelection, storeSelection,
doSetClientSetting, doSetClientSetting,
isHeaderMenu, isHeaderMenu,
hasDefaultChannel,
} = props; } = props;
const hideAnon = Boolean(props.hideAnon || storeSelection);
const defaultChannelRef = React.useRef(hasDefaultChannel);
const { const {
push, push,
location: { pathname }, location: { pathname },
@ -61,6 +66,20 @@ export default function ChannelSelector(props: Props) {
} }
} }
React.useEffect(() => {
defaultChannelRef.current = hasDefaultChannel;
}, [hasDefaultChannel]);
React.useEffect(() => {
return () => {
// has a default channel selected, clear the current active channel
if (defaultChannelRef.current) {
doSetActiveChannel(null, true);
}
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return ( return (
<div className="channel__selector"> <div className="channel__selector">
<Menu> <Menu>

View file

@ -1,17 +1,20 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import * as SETTINGS from 'constants/settings';
import SelectChannel from './view'; import SelectChannel from './view';
import { selectMyChannelClaims, selectFetchingMyChannels } from 'redux/selectors/claims'; import { selectMyChannelClaims, selectFetchingMyChannels } from 'redux/selectors/claims';
import { selectActiveChannelId } from 'redux/selectors/app'; import { selectActiveChannelClaim } from 'redux/selectors/app';
import { doSetActiveChannel } from 'redux/actions/app'; import { doSetActiveChannel } from 'redux/actions/app';
import { selectClientSetting } from 'redux/selectors/settings';
const select = (state) => ({ const select = (state) => ({
myChannelClaims: selectMyChannelClaims(state), myChannelClaims: selectMyChannelClaims(state),
fetchingChannels: selectFetchingMyChannels(state), fetchingChannels: selectFetchingMyChannels(state),
activeChannelId: selectActiveChannelId(state), activeChannelClaimId: selectActiveChannelClaim(state)?.claim_id,
hasDefaultChannel: Boolean(selectClientSetting(state, SETTINGS.ACTIVE_CHANNEL_CLAIM)),
}); });
const perform = (dispatch) => ({ const perform = (dispatch) => ({
setActiveChannel: (claimId) => dispatch(doSetActiveChannel(claimId)), setActiveChannel: (claimId, override) => dispatch(doSetActiveChannel(claimId, override)),
}); });
export default connect(select, perform)(SelectChannel); export default connect(select, perform)(SelectChannel);

View file

@ -10,8 +10,9 @@ type Props = {
// --- Redux --- // --- Redux ---
myChannelClaims: ?Array<ChannelClaim>, myChannelClaims: ?Array<ChannelClaim>,
fetchingChannels: boolean, fetchingChannels: boolean,
activeChannelId: ?string, activeChannelClaimId: ?string,
setActiveChannel: (string) => void, hasDefaultChannel: boolean,
setActiveChannel: (claimId: ?string, override?: boolean) => void,
}; };
function SelectChannel(props: Props) { function SelectChannel(props: Props) {
@ -22,10 +23,13 @@ function SelectChannel(props: Props) {
label, label,
injected = [], injected = [],
tiny, tiny,
activeChannelId, activeChannelClaimId,
hasDefaultChannel,
setActiveChannel, setActiveChannel,
} = props; } = props;
const defaultChannelRef = React.useRef(hasDefaultChannel);
function handleChannelChange(event: SyntheticInputEvent<*>) { function handleChannelChange(event: SyntheticInputEvent<*>) {
const channelClaimId = event.target.value; const channelClaimId = event.target.value;
setActiveChannel(channelClaimId); setActiveChannel(channelClaimId);
@ -36,6 +40,20 @@ function SelectChannel(props: Props) {
mine = myChannelClaims.filter((x) => channelIds.includes(x.claim_id)); mine = myChannelClaims.filter((x) => channelIds.includes(x.claim_id));
} }
React.useEffect(() => {
defaultChannelRef.current = hasDefaultChannel;
}, [hasDefaultChannel]);
React.useEffect(() => {
return () => {
// has a default channel selected, clear the current active channel
if (defaultChannelRef.current) {
setActiveChannel(null, true);
}
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return ( return (
<> <>
<FormField <FormField
@ -44,7 +62,7 @@ function SelectChannel(props: Props) {
labelOnLeft={tiny} labelOnLeft={tiny}
type={tiny ? 'select-tiny' : 'select'} type={tiny ? 'select-tiny' : 'select'}
onChange={handleChannelChange} onChange={handleChannelChange}
value={activeChannelId} value={activeChannelClaimId}
disabled={fetchingChannels} disabled={fetchingChannels}
> >
{fetchingChannels ? ( {fetchingChannels ? (

View file

@ -11,7 +11,7 @@ import * as DAEMON_SETTINGS from 'constants/daemon_settings';
import * as SHARED_PREFERENCES from 'constants/shared_preferences'; import * as SHARED_PREFERENCES from 'constants/shared_preferences';
import Lbry from 'lbry'; import Lbry from 'lbry';
import { doFetchChannelListMine, doFetchCollectionListMine, doCheckPendingClaims } from 'redux/actions/claims'; import { doFetchChannelListMine, doFetchCollectionListMine, doCheckPendingClaims } from 'redux/actions/claims';
import { selectClaimForUri, selectClaimIsMineForUri, selectMyChannelClaims } from 'redux/selectors/claims'; import { selectClaimForUri, selectClaimIsMineForUri } from 'redux/selectors/claims';
import { doFetchFileInfos } from 'redux/actions/file_info'; import { doFetchFileInfos } from 'redux/actions/file_info';
import { doClearSupport, doBalanceSubscribe } from 'redux/actions/wallet'; import { doClearSupport, doBalanceSubscribe } from 'redux/actions/wallet';
import { doClearPublish } from 'redux/actions/publish'; import { doClearPublish } from 'redux/actions/publish';
@ -686,9 +686,9 @@ export function doToggleSplashAnimation() {
}; };
} }
export function doSetActiveChannel(claimId) { export function doSetActiveChannel(claimId, override) {
return (dispatch, getState) => { return (dispatch, getState) => {
if (claimId) { if (claimId || override) {
return dispatch({ return dispatch({
type: ACTIONS.SET_ACTIVE_CHANNEL, type: ACTIONS.SET_ACTIVE_CHANNEL,
data: { data: {
@ -696,35 +696,6 @@ export function doSetActiveChannel(claimId) {
}, },
}); });
} }
// If no claimId is passed, set the active channel to the one with the highest effective_amount
const state = getState();
const myChannelClaims = selectMyChannelClaims(state);
if (!myChannelClaims || !myChannelClaims.length) {
return;
}
const myChannelClaimsByEffectiveAmount = myChannelClaims.slice().sort((a, b) => {
const effectiveAmountA = (a.meta && Number(a.meta.effective_amount)) || 0;
const effectiveAmountB = (b.meta && Number(b.meta.effective_amount)) || 0;
if (effectiveAmountA === effectiveAmountB) {
return 0;
} else if (effectiveAmountA > effectiveAmountB) {
return -1;
} else {
return 1;
}
});
const newActiveChannelClaim = myChannelClaimsByEffectiveAmount[0];
dispatch({
type: ACTIONS.SET_ACTIVE_CHANNEL,
data: {
claimId: newActiveChannelClaim.claim_id,
},
});
}; };
} }