Add channel selector on HeaderMenuButton
- Moved from reach/ui to material/ui menu components, because reach ui wouldn't work with 2 menus - This channel selector stores the default on settings - setActiveChannelIfNotSet was deprecated, if the account has channels, it will always return a channel even if there is no active channel or stored channel
This commit is contained in:
parent
fa1f3abbdc
commit
7eb5eb9996
11 changed files with 190 additions and 108 deletions
|
@ -23,7 +23,7 @@ import {
|
||||||
import { selectUploadCount } from 'redux/selectors/publish';
|
import { selectUploadCount } from 'redux/selectors/publish';
|
||||||
import { doSetLanguage } from 'redux/actions/settings';
|
import { doSetLanguage } from 'redux/actions/settings';
|
||||||
import { doSyncLoop } from 'redux/actions/sync';
|
import { doSyncLoop } from 'redux/actions/sync';
|
||||||
import { doDownloadUpgradeRequested, doSignIn, doSetActiveChannel, doSetIncognito } from 'redux/actions/app';
|
import { doDownloadUpgradeRequested, doSignIn, doSetIncognito } from 'redux/actions/app';
|
||||||
import { doFetchModBlockedList, doFetchCommentModAmIList } from 'redux/actions/comments';
|
import { doFetchModBlockedList, doFetchCommentModAmIList } from 'redux/actions/comments';
|
||||||
import App from './view';
|
import App from './view';
|
||||||
|
|
||||||
|
@ -57,7 +57,6 @@ const perform = (dispatch) => ({
|
||||||
requestDownloadUpgrade: () => dispatch(doDownloadUpgradeRequested()),
|
requestDownloadUpgrade: () => dispatch(doDownloadUpgradeRequested()),
|
||||||
syncLoop: (noInterval) => dispatch(doSyncLoop(noInterval)),
|
syncLoop: (noInterval) => dispatch(doSyncLoop(noInterval)),
|
||||||
setReferrer: (referrer, doClaim) => dispatch(doUserSetReferrer(referrer, doClaim)),
|
setReferrer: (referrer, doClaim) => dispatch(doUserSetReferrer(referrer, doClaim)),
|
||||||
setActiveChannelIfNotSet: () => dispatch(doSetActiveChannel()),
|
|
||||||
setIncognito: () => dispatch(doSetIncognito()),
|
setIncognito: () => dispatch(doSetIncognito()),
|
||||||
fetchModBlockedList: () => dispatch(doFetchModBlockedList()),
|
fetchModBlockedList: () => dispatch(doFetchModBlockedList()),
|
||||||
fetchModAmIList: () => dispatch(doFetchCommentModAmIList()),
|
fetchModAmIList: () => dispatch(doFetchCommentModAmIList()),
|
||||||
|
|
|
@ -86,7 +86,6 @@ type Props = {
|
||||||
activeChannelClaim: ?ChannelClaim,
|
activeChannelClaim: ?ChannelClaim,
|
||||||
myChannelClaimIds: ?Array<string>,
|
myChannelClaimIds: ?Array<string>,
|
||||||
hasPremiumPlus: ?boolean,
|
hasPremiumPlus: ?boolean,
|
||||||
setActiveChannelIfNotSet: () => void,
|
|
||||||
setIncognito: (boolean) => void,
|
setIncognito: (boolean) => void,
|
||||||
fetchModBlockedList: () => void,
|
fetchModBlockedList: () => void,
|
||||||
fetchModAmIList: () => void,
|
fetchModAmIList: () => void,
|
||||||
|
@ -120,7 +119,6 @@ function App(props: Props) {
|
||||||
syncFatalError,
|
syncFatalError,
|
||||||
myChannelClaimIds,
|
myChannelClaimIds,
|
||||||
activeChannelClaim,
|
activeChannelClaim,
|
||||||
setActiveChannelIfNotSet,
|
|
||||||
setIncognito,
|
setIncognito,
|
||||||
fetchModBlockedList,
|
fetchModBlockedList,
|
||||||
hasPremiumPlus,
|
hasPremiumPlus,
|
||||||
|
@ -312,9 +310,7 @@ function App(props: Props) {
|
||||||
}, [currentModal]);
|
}, [currentModal]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (hasMyChannels && !hasActiveChannelClaim) {
|
if (hasNoChannels) {
|
||||||
setActiveChannelIfNotSet();
|
|
||||||
} else if (hasNoChannels) {
|
|
||||||
setIncognito(true);
|
setIncognito(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,7 +319,7 @@ function App(props: Props) {
|
||||||
fetchModAmIList();
|
fetchModAmIList();
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [hasMyChannels, hasNoChannels, hasActiveChannelClaim, setActiveChannelIfNotSet, setIncognito]);
|
}, [hasMyChannels, hasNoChannels, hasActiveChannelClaim, setIncognito]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// $FlowFixMe
|
// $FlowFixMe
|
||||||
|
|
|
@ -26,49 +26,10 @@ type Props = {
|
||||||
odyseeMembershipByUri: (uri: string) => string,
|
odyseeMembershipByUri: (uri: string) => string,
|
||||||
storeSelection?: boolean,
|
storeSelection?: boolean,
|
||||||
doSetClientSetting: (key: string, value: string, pushPrefs: boolean) => void,
|
doSetClientSetting: (key: string, value: string, pushPrefs: boolean) => void,
|
||||||
|
isHeaderMenu: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
type ListItemProps = {
|
export default function ChannelSelector(props: Props) {
|
||||||
uri: string,
|
|
||||||
isSelected?: boolean,
|
|
||||||
claimsByUri: { [string]: any },
|
|
||||||
doFetchUserMemberships: (claimIdCsv: string) => void,
|
|
||||||
odyseeMembershipByUri: (uri: string) => string,
|
|
||||||
};
|
|
||||||
|
|
||||||
function ChannelListItem(props: ListItemProps) {
|
|
||||||
const { uri, isSelected = false, claimsByUri, doFetchUserMemberships, odyseeMembershipByUri } = props;
|
|
||||||
|
|
||||||
const membership = odyseeMembershipByUri(uri);
|
|
||||||
|
|
||||||
const shouldFetchUserMemberships = true;
|
|
||||||
useGetUserMemberships(shouldFetchUserMemberships, [uri], claimsByUri, doFetchUserMemberships, [uri]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={classnames('channel__list-item', { 'channel__list-item--selected': isSelected })}>
|
|
||||||
<ChannelThumbnail uri={uri} hideStakedIndicator xsmall noLazyLoad />
|
|
||||||
<ChannelTitle uri={uri} />
|
|
||||||
<PremiumBadge membership={membership} />
|
|
||||||
{isSelected && <Icon icon={ICONS.DOWN} />}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
type IncognitoSelectorProps = {
|
|
||||||
isSelected?: boolean,
|
|
||||||
};
|
|
||||||
|
|
||||||
function IncognitoSelector(props: IncognitoSelectorProps) {
|
|
||||||
return (
|
|
||||||
<div className={classnames('channel__list-item', { 'channel__list-item--selected': props.isSelected })}>
|
|
||||||
<Icon sectionIcon icon={ICONS.ANONYMOUS} />
|
|
||||||
<h2 className="channel__list-text">{__('Anonymous')}</h2>
|
|
||||||
{props.isSelected && <Icon icon={ICONS.DOWN} />}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function ChannelSelector(props: Props) {
|
|
||||||
const {
|
const {
|
||||||
channels,
|
channels,
|
||||||
activeChannelClaim,
|
activeChannelClaim,
|
||||||
|
@ -81,6 +42,7 @@ function ChannelSelector(props: Props) {
|
||||||
doFetchUserMemberships,
|
doFetchUserMemberships,
|
||||||
storeSelection,
|
storeSelection,
|
||||||
doSetClientSetting,
|
doSetClientSetting,
|
||||||
|
isHeaderMenu,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
@ -102,8 +64,14 @@ function ChannelSelector(props: Props) {
|
||||||
return (
|
return (
|
||||||
<div className="channel__selector">
|
<div className="channel__selector">
|
||||||
<Menu>
|
<Menu>
|
||||||
<MenuButton>
|
<MenuButton className={isHeaderMenu ? 'menu__link' : undefined}>
|
||||||
{(incognito && !hideAnon) || !activeChannelUrl ? (
|
{isHeaderMenu ? (
|
||||||
|
<>
|
||||||
|
<ChannelThumbnail uri={activeChannelUrl} hideStakedIndicator xxsmall noLazyLoad />
|
||||||
|
{__('Change Default Channel')}
|
||||||
|
<Icon icon={ICONS.DOWN} />
|
||||||
|
</>
|
||||||
|
) : (incognito && !hideAnon) || !activeChannelUrl ? (
|
||||||
<IncognitoSelector isSelected />
|
<IncognitoSelector isSelected />
|
||||||
) : (
|
) : (
|
||||||
<ChannelListItem
|
<ChannelListItem
|
||||||
|
@ -145,4 +113,42 @@ function ChannelSelector(props: Props) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ChannelSelector;
|
type ListItemProps = {
|
||||||
|
uri: string,
|
||||||
|
isSelected?: boolean,
|
||||||
|
claimsByUri: { [string]: any },
|
||||||
|
doFetchUserMemberships: (claimIdCsv: string) => void,
|
||||||
|
odyseeMembershipByUri: (uri: string) => string,
|
||||||
|
};
|
||||||
|
|
||||||
|
function ChannelListItem(props: ListItemProps) {
|
||||||
|
const { uri, isSelected = false, claimsByUri, doFetchUserMemberships, odyseeMembershipByUri } = props;
|
||||||
|
|
||||||
|
const membership = odyseeMembershipByUri(uri);
|
||||||
|
|
||||||
|
const shouldFetchUserMemberships = true;
|
||||||
|
useGetUserMemberships(shouldFetchUserMemberships, [uri], claimsByUri, doFetchUserMemberships, [uri]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={classnames('channel__list-item', { 'channel__list-item--selected': isSelected })}>
|
||||||
|
<ChannelThumbnail uri={uri} hideStakedIndicator xsmall noLazyLoad />
|
||||||
|
<ChannelTitle uri={uri} />
|
||||||
|
<PremiumBadge membership={membership} />
|
||||||
|
{isSelected && <Icon icon={ICONS.DOWN} />}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
type IncognitoSelectorProps = {
|
||||||
|
isSelected?: boolean,
|
||||||
|
};
|
||||||
|
|
||||||
|
function IncognitoSelector(props: IncognitoSelectorProps) {
|
||||||
|
return (
|
||||||
|
<div className={classnames('channel__list-item', { 'channel__list-item--selected': props.isSelected })}>
|
||||||
|
<Icon sectionIcon icon={ICONS.ANONYMOUS} />
|
||||||
|
<h2 className="channel__list-text">{__('Anonymous')}</h2>
|
||||||
|
{props.isSelected && <Icon icon={ICONS.DOWN} />}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ type Props = {
|
||||||
obscure?: boolean,
|
obscure?: boolean,
|
||||||
small?: boolean,
|
small?: boolean,
|
||||||
xsmall?: boolean,
|
xsmall?: boolean,
|
||||||
|
xxsmall?: boolean,
|
||||||
allowGifs?: boolean,
|
allowGifs?: boolean,
|
||||||
claim: ?ChannelClaim,
|
claim: ?ChannelClaim,
|
||||||
doResolveUri: (string) => void,
|
doResolveUri: (string) => void,
|
||||||
|
@ -44,6 +45,7 @@ function ChannelThumbnail(props: Props) {
|
||||||
obscure,
|
obscure,
|
||||||
small = false,
|
small = false,
|
||||||
xsmall = false,
|
xsmall = false,
|
||||||
|
xxsmall,
|
||||||
allowGifs = false,
|
allowGifs = false,
|
||||||
claim,
|
claim,
|
||||||
doResolveUri,
|
doResolveUri,
|
||||||
|
@ -110,6 +112,7 @@ function ChannelThumbnail(props: Props) {
|
||||||
[colorClassName]: !showThumb,
|
[colorClassName]: !showThumb,
|
||||||
'channel-thumbnail--small': small,
|
'channel-thumbnail--small': small,
|
||||||
'channel-thumbnail--xsmall': xsmall,
|
'channel-thumbnail--xsmall': xsmall,
|
||||||
|
'channel-thumbnail--xxsmall': xxsmall,
|
||||||
'channel-thumbnail--resolving': isResolving,
|
'channel-thumbnail--resolving': isResolving,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
|
@ -117,8 +120,8 @@ function ChannelThumbnail(props: Props) {
|
||||||
alt={__('Channel profile picture')}
|
alt={__('Channel profile picture')}
|
||||||
className={!channelThumbnail ? 'channel-thumbnail__default' : 'channel-thumbnail__custom'}
|
className={!channelThumbnail ? 'channel-thumbnail__default' : 'channel-thumbnail__custom'}
|
||||||
src={(!thumbLoadError && channelThumbnail) || defaultAvatar}
|
src={(!thumbLoadError && channelThumbnail) || defaultAvatar}
|
||||||
width={small || xsmall ? 64 : 160}
|
width={xxsmall ? 16 : small || xsmall ? 64 : 160}
|
||||||
quality={small || xsmall ? 85 : 95}
|
quality={xxsmall ? 16 : small || xsmall ? 85 : 95}
|
||||||
loading={noLazyLoad ? undefined : 'lazy'}
|
loading={noLazyLoad ? undefined : 'lazy'}
|
||||||
onError={() => {
|
onError={() => {
|
||||||
if (setThumbUploadError) {
|
if (setThumbUploadError) {
|
||||||
|
|
|
@ -3,6 +3,8 @@ import * as PAGES from 'constants/pages';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Link, useHistory } from 'react-router-dom';
|
import { Link, useHistory } from 'react-router-dom';
|
||||||
import { MenuLink, MenuItem } from '@reach/menu-button';
|
import { MenuLink, MenuItem } from '@reach/menu-button';
|
||||||
|
import MuiMenuItem from '@mui/material/MenuItem';
|
||||||
|
import MuiLink from '@mui/material/Link';
|
||||||
import Icon from 'component/common/icon';
|
import Icon from 'component/common/icon';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
@ -10,13 +12,23 @@ type Props = {
|
||||||
name: string,
|
name: string,
|
||||||
page: string,
|
page: string,
|
||||||
requiresAuth?: boolean,
|
requiresAuth?: boolean,
|
||||||
|
useMui?: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function HeaderMenuLink(props: Props) {
|
export default function HeaderMenuLink(props: Props) {
|
||||||
const { icon, name, page, requiresAuth } = props;
|
const { icon, name, page, requiresAuth, useMui } = props;
|
||||||
|
|
||||||
const { push } = useHistory();
|
const { push } = useHistory();
|
||||||
|
|
||||||
|
if (useMui) {
|
||||||
|
return (
|
||||||
|
<MuiMenuItem className="menu__link" component={MuiLink} href={`/$/${page}`}>
|
||||||
|
<Icon aria-hidden icon={icon} />
|
||||||
|
{name}
|
||||||
|
</MuiMenuItem>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (requiresAuth) {
|
if (requiresAuth) {
|
||||||
return (
|
return (
|
||||||
<MenuItem className="menu__link" onSelect={() => push(`/$/${PAGES.AUTH}`)}>
|
<MenuItem className="menu__link" onSelect={() => push(`/$/${PAGES.AUTH}`)}>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// @flow
|
// @flow
|
||||||
import 'scss/component/_header.scss';
|
import 'scss/component/_header.scss';
|
||||||
|
|
||||||
import { Menu, MenuList, MenuButton, MenuItem } from '@reach/menu-button';
|
import { Menu as MuiMenu, MenuItem as MuiMenuItem } from '@mui/material';
|
||||||
import * as ICONS from 'constants/icons';
|
import * as ICONS from 'constants/icons';
|
||||||
import * as PAGES from 'constants/pages';
|
import * as PAGES from 'constants/pages';
|
||||||
import ChannelThumbnail from 'component/channelThumbnail';
|
import ChannelThumbnail from 'component/channelThumbnail';
|
||||||
|
@ -10,6 +10,8 @@ import HeaderMenuLink from 'component/common/header-menu-link';
|
||||||
import Icon from 'component/common/icon';
|
import Icon from 'component/common/icon';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Skeleton from '@mui/material/Skeleton';
|
import Skeleton from '@mui/material/Skeleton';
|
||||||
|
import ChannelSelector from 'component/channelSelector';
|
||||||
|
import Button from 'component/button';
|
||||||
|
|
||||||
type HeaderMenuButtonProps = {
|
type HeaderMenuButtonProps = {
|
||||||
myChannelClaimIds: ?Array<string>,
|
myChannelClaimIds: ?Array<string>,
|
||||||
|
@ -22,6 +24,15 @@ type HeaderMenuButtonProps = {
|
||||||
export default function HeaderProfileMenuButton(props: HeaderMenuButtonProps) {
|
export default function HeaderProfileMenuButton(props: HeaderMenuButtonProps) {
|
||||||
const { myChannelClaimIds, activeChannelClaim, authenticated, email, signOut } = props;
|
const { myChannelClaimIds, activeChannelClaim, authenticated, email, signOut } = props;
|
||||||
|
|
||||||
|
const [anchorEl, setAnchorEl] = React.useState(null);
|
||||||
|
const open = Boolean(anchorEl);
|
||||||
|
const handleClick = (event) => {
|
||||||
|
setAnchorEl(!anchorEl ? event.currentTarget : null);
|
||||||
|
};
|
||||||
|
const handleClose = () => {
|
||||||
|
setAnchorEl(null);
|
||||||
|
};
|
||||||
|
|
||||||
const activeChannelUrl = activeChannelClaim && activeChannelClaim.permanent_url;
|
const activeChannelUrl = activeChannelClaim && activeChannelClaim.permanent_url;
|
||||||
// activeChannel will be: undefined = fetching, null = nothing, or { channel claim }
|
// activeChannel will be: undefined = fetching, null = nothing, or { channel claim }
|
||||||
const noActiveChannel = activeChannelUrl === null;
|
const noActiveChannel = activeChannelUrl === null;
|
||||||
|
@ -29,53 +40,74 @@ export default function HeaderProfileMenuButton(props: HeaderMenuButtonProps) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="header__buttons">
|
<div className="header__buttons">
|
||||||
<Menu>
|
{pendingChannelFetch ? (
|
||||||
{pendingChannelFetch ? (
|
<Skeleton variant="circular" animation="wave" className="header__navigationItem--iconSkeleton" />
|
||||||
<Skeleton variant="circular" animation="wave" className="header__navigationItem--iconSkeleton" />
|
) : (
|
||||||
) : (
|
<Button
|
||||||
<MenuButton
|
id="basic-button"
|
||||||
aria-label={__('Your account')}
|
aria-controls={open ? 'basic-menu' : undefined}
|
||||||
className={classnames('header__navigationItem', {
|
aria-haspopup="true"
|
||||||
'header__navigationItem--icon': !activeChannelUrl,
|
aria-expanded={open ? 'true' : undefined}
|
||||||
'header__navigationItem--profilePic': activeChannelUrl,
|
onClick={handleClick}
|
||||||
})}
|
className={classnames('header__navigationItem', {
|
||||||
>
|
'header__navigationItem--icon': !activeChannelUrl,
|
||||||
{activeChannelUrl ? (
|
'header__navigationItem--profilePic': activeChannelUrl,
|
||||||
<ChannelThumbnail uri={activeChannelUrl} hideTooltip small noLazyLoad showMemberBadge />
|
})}
|
||||||
) : (
|
>
|
||||||
<Icon size={18} icon={ICONS.ACCOUNT} aria-hidden />
|
{activeChannelUrl ? (
|
||||||
)}
|
<ChannelThumbnail uri={activeChannelUrl} hideTooltip small noLazyLoad showMemberBadge />
|
||||||
</MenuButton>
|
) : (
|
||||||
)}
|
<Icon size={18} icon={ICONS.ACCOUNT} aria-hidden />
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
<MuiMenu
|
||||||
|
id="basic-menu"
|
||||||
|
anchorEl={anchorEl}
|
||||||
|
open={open}
|
||||||
|
onClose={handleClose}
|
||||||
|
MenuListProps={{
|
||||||
|
'aria-labelledby': 'basic-button',
|
||||||
|
sx: { padding: 'var(--spacing-xs)' },
|
||||||
|
}}
|
||||||
|
className="menu__list--header"
|
||||||
|
sx={{ 'z-index': 2 }}
|
||||||
|
PaperProps={{ className: 'MuiMenu-list--paper' }}
|
||||||
|
>
|
||||||
|
{authenticated ? (
|
||||||
|
<>
|
||||||
|
<HeaderMenuLink useMui page={PAGES.UPLOADS} icon={ICONS.PUBLISH} name={__('Uploads')} />
|
||||||
|
<HeaderMenuLink useMui page={PAGES.CHANNELS} icon={ICONS.CHANNEL} name={__('Channels')} />
|
||||||
|
<HeaderMenuLink
|
||||||
|
useMui
|
||||||
|
page={PAGES.CREATOR_DASHBOARD}
|
||||||
|
icon={ICONS.ANALYTICS}
|
||||||
|
name={__('Creator Analytics')}
|
||||||
|
/>
|
||||||
|
<HeaderMenuLink useMui page={PAGES.REWARDS} icon={ICONS.REWARDS} name={__('Rewards')} />
|
||||||
|
<HeaderMenuLink useMui page={PAGES.INVITE} icon={ICONS.INVITE} name={__('Invites')} />
|
||||||
|
<HeaderMenuLink useMui page={PAGES.ODYSEE_MEMBERSHIP} icon={ICONS.UPGRADE} name={__('Odysee Premium')} />
|
||||||
|
<ChannelSelector storeSelection isHeaderMenu />
|
||||||
|
|
||||||
<MenuList className="menu__list--header">
|
<MuiMenuItem onClick={signOut} sx={{ padding: '0px' }}>
|
||||||
{authenticated ? (
|
<div className="menu__link" style={{ 'flex-direction': 'column', 'align-items': 'flex-start' }}>
|
||||||
<>
|
<div>
|
||||||
<HeaderMenuLink page={PAGES.UPLOADS} icon={ICONS.PUBLISH} name={__('Uploads')} />
|
|
||||||
<HeaderMenuLink page={PAGES.CHANNELS} icon={ICONS.CHANNEL} name={__('Channels')} />
|
|
||||||
<HeaderMenuLink page={PAGES.CREATOR_DASHBOARD} icon={ICONS.ANALYTICS} name={__('Creator Analytics')} />
|
|
||||||
<HeaderMenuLink page={PAGES.REWARDS} icon={ICONS.REWARDS} name={__('Rewards')} />
|
|
||||||
<HeaderMenuLink page={PAGES.INVITE} icon={ICONS.INVITE} name={__('Invites')} />
|
|
||||||
<HeaderMenuLink page={PAGES.ODYSEE_MEMBERSHIP} icon={ICONS.UPGRADE} name={__('Odysee Premium')} />
|
|
||||||
|
|
||||||
<MenuItem onSelect={signOut}>
|
|
||||||
<div className="menu__link">
|
|
||||||
<Icon aria-hidden icon={ICONS.SIGN_OUT} />
|
<Icon aria-hidden icon={ICONS.SIGN_OUT} />
|
||||||
{__('Sign Out')}
|
{__('Sign Out')}
|
||||||
</div>
|
</div>
|
||||||
<span className="menu__link-help">{email}</span>
|
<span className="menu__link-help">{email}</span>
|
||||||
</MenuItem>
|
</div>
|
||||||
</>
|
</MuiMenuItem>
|
||||||
) : (
|
</>
|
||||||
<>
|
) : (
|
||||||
<HeaderMenuLink page={PAGES.AUTH_SIGNIN} icon={ICONS.SIGN_IN} name={__('Log In')} />
|
<>
|
||||||
<HeaderMenuLink page={PAGES.AUTH} icon={ICONS.SIGN_UP} name={__('Sign Up')} />
|
<HeaderMenuLink useMui page={PAGES.AUTH_SIGNIN} icon={ICONS.SIGN_IN} name={__('Log In')} />
|
||||||
<HeaderMenuLink page={PAGES.SETTINGS} icon={ICONS.SETTINGS} name={__('Settings')} />
|
<HeaderMenuLink useMui page={PAGES.AUTH} icon={ICONS.SIGN_UP} name={__('Sign Up')} />
|
||||||
<HeaderMenuLink page={PAGES.HELP} icon={ICONS.HELP} name={__('Help')} />
|
<HeaderMenuLink useMui page={PAGES.SETTINGS} icon={ICONS.SETTINGS} name={__('Settings')} />
|
||||||
</>
|
<HeaderMenuLink useMui page={PAGES.HELP} icon={ICONS.HELP} name={__('Help')} />
|
||||||
)}
|
</>
|
||||||
</MenuList>
|
)}
|
||||||
</Menu>
|
</MuiMenu>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@ import {
|
||||||
selectCurrentUploads,
|
selectCurrentUploads,
|
||||||
} from 'redux/selectors/publish';
|
} from 'redux/selectors/publish';
|
||||||
import { selectActiveChannelClaim, selectIncognito } from 'redux/selectors/app';
|
import { selectActiveChannelClaim, selectIncognito } from 'redux/selectors/app';
|
||||||
import { doSetActiveChannel } from 'redux/actions/app';
|
|
||||||
import PublishPage from './view';
|
import PublishPage from './view';
|
||||||
|
|
||||||
const select = (state) => ({
|
const select = (state) => ({
|
||||||
|
@ -26,7 +25,6 @@ const select = (state) => ({
|
||||||
const perform = (dispatch) => ({
|
const perform = (dispatch) => ({
|
||||||
updatePublishForm: (value) => dispatch(doUpdatePublishForm(value)),
|
updatePublishForm: (value) => dispatch(doUpdatePublishForm(value)),
|
||||||
prepareEdit: (claim, uri) => dispatch(doPrepareEdit(claim, uri)),
|
prepareEdit: (claim, uri) => dispatch(doPrepareEdit(claim, uri)),
|
||||||
setActiveChannel: (claimId) => dispatch(doSetActiveChannel(claimId)),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, perform)(PublishPage);
|
export default connect(select, perform)(PublishPage);
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { selectHasChannels, selectFetchingMyChannels } from 'redux/selectors/claims';
|
import { selectHasChannels, selectFetchingMyChannels } from 'redux/selectors/claims';
|
||||||
import { selectActiveChannelClaim } from 'redux/selectors/app';
|
import { selectActiveChannelClaim } from 'redux/selectors/app';
|
||||||
import { doSetActiveChannel } from 'redux/actions/app';
|
|
||||||
import CreatorDashboardPage from './view';
|
import CreatorDashboardPage from './view';
|
||||||
|
|
||||||
const select = (state) => ({
|
const select = (state) => ({
|
||||||
|
@ -10,4 +9,4 @@ const select = (state) => ({
|
||||||
activeChannelClaim: selectActiveChannelClaim(state),
|
activeChannelClaim: selectActiveChannelClaim(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, { doSetActiveChannel })(CreatorDashboardPage);
|
export default connect(select)(CreatorDashboardPage);
|
||||||
|
|
|
@ -76,7 +76,7 @@ export const selectActiveChannelClaim = createSelector(
|
||||||
// Null: has none. Undefined: not resolved, default state, could have or not
|
// Null: has none. Undefined: not resolved, default state, could have or not
|
||||||
if (!userEmail || myChannelClaims === null) {
|
if (!userEmail || myChannelClaims === null) {
|
||||||
return null;
|
return null;
|
||||||
} else if (!activeChannelClaim || !myChannelClaims || !myChannelClaims.length) {
|
} else if (!myChannelClaims || !myChannelClaims.length) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -267,6 +267,12 @@ $actions-z-index: 2;
|
||||||
margin-right: var(--spacing-xs);
|
margin-right: var(--spacing-xs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.channel-thumbnail--xxsmall {
|
||||||
|
height: 16px;
|
||||||
|
width: 16px;
|
||||||
|
margin-right: var(--spacing-s) !important;
|
||||||
|
}
|
||||||
|
|
||||||
.channel-thumbnail--waiting {
|
.channel-thumbnail--waiting {
|
||||||
background-color: var(--color-gray-5);
|
background-color: var(--color-gray-5);
|
||||||
border-radius: var(--border-radius);
|
border-radius: var(--border-radius);
|
||||||
|
|
|
@ -31,16 +31,17 @@ reach-portal {
|
||||||
max-width: calc(100% - var(--height-button) - var(--spacing-xs));
|
max-width: calc(100% - var(--height-button) - var(--spacing-xs));
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-reach-menu-list] {
|
[data-reach-menu-list],
|
||||||
|
.MuiMenu-list--paper {
|
||||||
display: block;
|
display: block;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
outline: none;
|
outline: none;
|
||||||
// background-color: var(--color-header-background) !important;
|
// background-color: var(--color-header-background) !important;
|
||||||
background-color: rgba(var(--color-header-button-base), 0.9) !important;
|
background-color: rgba(var(--color-header-button-base), 0.5) !important;
|
||||||
border: 2px solid var(--color-header-background) !important;
|
border: 2px solid var(--color-header-background) !important;
|
||||||
border-top: none;
|
border-top: none;
|
||||||
-webkit-backdrop-filter: blur(4px);
|
-webkit-backdrop-filter: blur(4px) !important;
|
||||||
backdrop-filter: blur(4px);
|
backdrop-filter: blur(4px) !important;
|
||||||
|
|
||||||
&:focus-visible {
|
&:focus-visible {
|
||||||
background-color: var(--color-header-background) !important;
|
background-color: var(--color-header-background) !important;
|
||||||
|
@ -85,6 +86,13 @@ reach-portal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.menu__link:hover {
|
||||||
|
color: var(--color-odysee-contrast) !important;
|
||||||
|
background-color: var(--color-odysee) !important;
|
||||||
|
border-radius: var(--border-radius);
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
.menu__button {
|
.menu__button {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
@ -125,6 +133,22 @@ reach-portal {
|
||||||
.menu__list--header {
|
.menu__list--header {
|
||||||
@extend .menu__list;
|
@extend .menu__list;
|
||||||
|
|
||||||
|
.channel__selector {
|
||||||
|
margin: 0px !important;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
.menu__link {
|
||||||
|
margin: 0px !important;
|
||||||
|
padding: var(--spacing-xs) var(--spacing-s) !important;
|
||||||
|
width: 100%;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon--ChevronDown {
|
||||||
|
margin-left: var(--spacing-s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[data-reach-menu-item][data-selected] {
|
[data-reach-menu-item][data-selected] {
|
||||||
.menu__link {
|
.menu__link {
|
||||||
color: var(--color-odysee-contrast) !important;
|
color: var(--color-odysee-contrast) !important;
|
||||||
|
@ -155,6 +179,12 @@ reach-portal {
|
||||||
@extend .menu__list;
|
@extend .menu__list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.MuiMenuItem-root {
|
||||||
|
margin-left: 0px !important;
|
||||||
|
font-size: var(--font-small) !important;
|
||||||
|
display: block !important;
|
||||||
|
}
|
||||||
|
|
||||||
.menu__link {
|
.menu__link {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -162,6 +192,7 @@ reach-portal {
|
||||||
// padding-right: var(--spacing-l);
|
// padding-right: var(--spacing-l);
|
||||||
padding: var(--spacing-xs) var(--spacing-s) var(--spacing-xs) var(--spacing-s);
|
padding: var(--spacing-xs) var(--spacing-s) var(--spacing-xs) var(--spacing-s);
|
||||||
height: var(--button-height);
|
height: var(--button-height);
|
||||||
|
color: var(--color-primary-contrast) !important;
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
stroke: var(--color-menu-icon);
|
stroke: var(--color-menu-icon);
|
||||||
|
@ -186,7 +217,7 @@ reach-portal {
|
||||||
display: block;
|
display: block;
|
||||||
color: var(--color-text);
|
color: var(--color-text);
|
||||||
font-size: var(--font-small);
|
font-size: var(--font-small);
|
||||||
padding-top: 0;
|
padding: 0px;
|
||||||
white-space: normal;
|
white-space: normal;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
|
|
Loading…
Reference in a new issue