improve mobile style and initial blocked screen loading

This commit is contained in:
Sean Yesmunt 2021-03-04 01:03:58 -05:00
parent eb0e0cb7cc
commit 84bab875bc
9 changed files with 154 additions and 159 deletions

View file

@ -1589,5 +1589,9 @@
"Interacting as %channelName%": "Interacting as %channelName%", "Interacting as %channelName%": "Interacting as %channelName%",
"Page Not Found": "Page Not Found", "Page Not Found": "Page Not Found",
"Transaction limit reached. Try reducing the Description length.": "Transaction limit reached. Try reducing the Description length.", "Transaction limit reached. Try reducing the Description length.": "Transaction limit reached. Try reducing the Description length.",
"You do not have any muted channels": "You do not have any muted channels",
"You do not have any blocked channels": "You do not have any blocked channels",
"Blocked channels will be invisible to you in the app. They will not be able to comment on your content, or reply to you comments left on other channels' content.": "Blocked channels will be invisible to you in the app. They will not be able to comment on your content, or reply to you comments left on other channels' content.",
"Muted channels will be invisible to you in the app. They will not know they are muted and can still interact with you and your content.": "Muted channels will be invisible to you in the app. They will not know they are muted and can still interact with you and your content.",
"--end--": "--end--" "--end--": "--end--"
} }

View file

@ -10,7 +10,7 @@ function FileAuthor(props: Props) {
const { channelUri } = props; const { channelUri } = props;
return channelUri ? ( return channelUri ? (
<ClaimPreview uri={channelUri} type="inline" properties={false} /> <ClaimPreview uri={channelUri} type="inline" properties={false} hideMenu />
) : ( ) : (
<div className="claim-preview--inline claim-preview__title">{__('Anonymous')}</div> <div className="claim-preview--inline claim-preview__title">{__('Anonymous')}</div>
); );

View file

@ -176,7 +176,7 @@ const Header = (props: Props) => {
: __('Your Wallet') : __('Your Wallet')
} }
navigate={`/$/${PAGES.WALLET}`} navigate={`/$/${PAGES.WALLET}`}
className={balanceButtonProps.className} className={classnames(balanceButtonProps.className, 'header__navigation-item--balance')}
label={hideBalance || Number(roundedBalance) === 0 ? __('Your Wallet') : roundedBalance} label={hideBalance || Number(roundedBalance) === 0 ? __('Your Wallet') : roundedBalance}
icon={ICONS.LBC} icon={ICONS.LBC}
// @if TARGET='app' // @if TARGET='app'
@ -212,7 +212,7 @@ const Header = (props: Props) => {
/> />
{backTitle && <h1 className="header__auth-title">{isMobile ? simpleBackTitle || backTitle : backTitle}</h1>} {backTitle && <h1 className="header__auth-title">{isMobile ? simpleBackTitle || backTitle : backTitle}</h1>}
{authenticated || !IS_WEB ? ( {authenticated || !IS_WEB ? (
<BalanceButton className="header__navigation-item menu__title header__navigation-item--balance" /> <BalanceButton className="header__navigation-item menu__title" />
) : ( ) : (
loginButtons loginButtons
)} )}
@ -275,10 +275,6 @@ const Header = (props: Props) => {
history={history} history={history}
handleThemeToggle={handleThemeToggle} handleThemeToggle={handleThemeToggle}
currentTheme={currentTheme} currentTheme={currentTheme}
activeChannelUrl={activeChannelUrl}
openSignOutModal={openSignOutModal}
email={email}
signOut={signOut}
/> />
</div> </div>
)} )}
@ -287,10 +283,77 @@ const Header = (props: Props) => {
{!authHeader && !backout ? ( {!authHeader && !backout ? (
<div className={classnames('header__menu', { 'header__menu--with-balance': !IS_WEB || authenticated })}> <div className={classnames('header__menu', { 'header__menu--with-balance': !IS_WEB || authenticated })}>
{(!IS_WEB || authenticated) && ( {(!IS_WEB || authenticated) && (
<BalanceButton className="header__navigation-item menu__title header__navigation-item--balance mobile-hidden" /> <BalanceButton className="header__navigation-item menu__title mobile-hidden" />
)} )}
{IS_WEB && !authenticated && loginButtons} {IS_WEB && !authenticated && loginButtons}
{(authenticated || !IS_WEB) && (
<Menu>
<MenuButton
aria-label={__('Your account')}
title={__('Your account')}
className={classnames('header__navigation-item', {
'menu__title header__navigation-item--icon': !activeChannelUrl,
'header__navigation-item--profile-pic': activeChannelUrl,
})}
// @if TARGET='app'
onDoubleClick={(e) => {
e.stopPropagation();
}}
// @endif
>
{activeChannelUrl ? (
<ChannelThumbnail uri={activeChannelUrl} />
) : (
<Icon size={18} icon={ICONS.ACCOUNT} aria-hidden />
)}
</MenuButton>
<MenuList className="menu__list--header">
<MenuItem className="menu__link" onSelect={() => history.push(`/$/${PAGES.UPLOADS}`)}>
<Icon aria-hidden icon={ICONS.PUBLISH} />
{__('Uploads')}
</MenuItem>
<MenuItem className="menu__link" onSelect={() => history.push(`/$/${PAGES.CHANNELS}`)}>
<Icon aria-hidden icon={ICONS.CHANNEL} />
{__('Channels')}
</MenuItem>
<MenuItem className="menu__link" onSelect={() => history.push(`/$/${PAGES.CREATOR_DASHBOARD}`)}>
<Icon aria-hidden icon={ICONS.ANALYTICS} />
{__('Creator Analytics')}
</MenuItem>
<MenuItem className="menu__link" onSelect={() => history.push(`/$/${PAGES.REWARDS}`)}>
<Icon aria-hidden icon={ICONS.REWARDS} />
{__('Rewards')}
</MenuItem>
<MenuItem className="menu__link" onSelect={() => history.push(`/$/${PAGES.INVITE}`)}>
<Icon aria-hidden icon={ICONS.INVITE} />
{__('Invites')}
</MenuItem>
{authenticated ? (
<MenuItem onSelect={IS_WEB ? signOut : openSignOutModal}>
<div className="menu__link">
<Icon aria-hidden icon={ICONS.SIGN_OUT} />
{__('Sign Out')}
</div>
<span className="menu__link-help">{email}</span>
</MenuItem>
) : !IS_WEB ? (
<>
<MenuItem className="menu__link" onSelect={() => history.push(`/$/${PAGES.AUTH}`)}>
<Icon aria-hidden icon={ICONS.SIGN_UP} />
{__('Sign Up')}
</MenuItem>
<MenuItem className="menu__link" onSelect={() => history.push(`/$/${PAGES.AUTH_SIGNIN}`)}>
<Icon aria-hidden icon={ICONS.SIGN_IN} />
{__('Sign In')}
</MenuItem>
</>
) : null}
</MenuList>
</Menu>
)}
</div> </div>
) : ( ) : (
!isVerifyPage && !isVerifyPage &&
@ -328,24 +391,10 @@ type HeaderMenuButtonProps = {
history: { push: (string) => void }, history: { push: (string) => void },
handleThemeToggle: (string) => void, handleThemeToggle: (string) => void,
currentTheme: string, currentTheme: string,
activeChannelUrl: ?string,
openSignOutModal: () => void,
email: ?string,
signOut: () => void,
}; };
function HeaderMenuButtons(props: HeaderMenuButtonProps) { function HeaderMenuButtons(props: HeaderMenuButtonProps) {
const { const { authenticated, notificationsEnabled, history, handleThemeToggle, currentTheme } = props;
authenticated,
notificationsEnabled,
history,
handleThemeToggle,
currentTheme,
activeChannelUrl,
openSignOutModal,
email,
signOut,
} = props;
return ( return (
<div className="header__buttons"> <div className="header__buttons">
@ -407,73 +456,6 @@ function HeaderMenuButtons(props: HeaderMenuButtonProps) {
</MenuItem> </MenuItem>
</MenuList> </MenuList>
</Menu> </Menu>
{(authenticated || !IS_WEB) && (
<Menu>
<MenuButton
aria-label={__('Your account')}
title={__('Your account')}
className={classnames('header__navigation-item mobile-hidden', {
'menu__title header__navigation-item--icon': !activeChannelUrl,
'header__navigation-item--profile-pic': activeChannelUrl,
})}
// @if TARGET='app'
onDoubleClick={(e) => {
e.stopPropagation();
}}
// @endif
>
{activeChannelUrl ? (
<ChannelThumbnail uri={activeChannelUrl} />
) : (
<Icon size={18} icon={ICONS.ACCOUNT} aria-hidden />
)}
</MenuButton>
<MenuList className="menu__list--header">
<MenuItem className="menu__link" onSelect={() => history.push(`/$/${PAGES.UPLOADS}`)}>
<Icon aria-hidden icon={ICONS.PUBLISH} />
{__('Uploads')}
</MenuItem>
<MenuItem className="menu__link" onSelect={() => history.push(`/$/${PAGES.CHANNELS}`)}>
<Icon aria-hidden icon={ICONS.CHANNEL} />
{__('Channels')}
</MenuItem>
<MenuItem className="menu__link" onSelect={() => history.push(`/$/${PAGES.CREATOR_DASHBOARD}`)}>
<Icon aria-hidden icon={ICONS.ANALYTICS} />
{__('Creator Analytics')}
</MenuItem>
<MenuItem className="menu__link" onSelect={() => history.push(`/$/${PAGES.REWARDS}`)}>
<Icon aria-hidden icon={ICONS.REWARDS} />
{__('Rewards')}
</MenuItem>
<MenuItem className="menu__link" onSelect={() => history.push(`/$/${PAGES.INVITE}`)}>
<Icon aria-hidden icon={ICONS.INVITE} />
{__('Invites')}
</MenuItem>
{authenticated ? (
<MenuItem onSelect={IS_WEB ? signOut : openSignOutModal}>
<div className="menu__link">
<Icon aria-hidden icon={ICONS.SIGN_OUT} />
{__('Sign Out')}
</div>
<span className="menu__link-help">{email}</span>
</MenuItem>
) : !IS_WEB ? (
<>
<MenuItem className="menu__link" onSelect={() => history.push(`/$/${PAGES.AUTH}`)}>
<Icon aria-hidden icon={ICONS.SIGN_UP} />
{__('Sign Up')}
</MenuItem>
<MenuItem className="menu__link" onSelect={() => history.push(`/$/${PAGES.AUTH_SIGNIN}`)}>
<Icon aria-hidden icon={ICONS.SIGN_IN} />
{__('Sign In')}
</MenuItem>
</>
) : null}
</MenuList>
</Menu>
)}
</div> </div>
); );
} }

View file

@ -58,6 +58,7 @@ export default function RecommendedContent(props: Props) {
type="small" type="small"
loading={isSearching} loading={isSearching}
uris={recommendedContent} uris={recommendedContent}
hideMenu={isMobile}
injectedItem={ injectedItem={
SHOW_ADS && IS_WEB ? ( SHOW_ADS && IS_WEB ? (
SIMPLE_SITE ? ( SIMPLE_SITE ? (

View file

@ -6,10 +6,10 @@ import ClaimList from 'component/claimList';
import Page from 'component/page'; import Page from 'component/page';
import Spinner from 'component/spinner'; import Spinner from 'component/spinner';
import Button from 'component/button'; import Button from 'component/button';
import usePrevious from 'effects/use-previous';
import usePersistedState from 'effects/use-persisted-state'; import usePersistedState from 'effects/use-persisted-state';
import ChannelBlockButton from 'component/channelBlockButton'; import ChannelBlockButton from 'component/channelBlockButton';
import ChannelMuteButton from 'component/channelMuteButton'; import ChannelMuteButton from 'component/channelMuteButton';
import Yrbl from 'component/yrbl';
type Props = { type Props = {
mutedUris: ?Array<string>, mutedUris: ?Array<string>,
@ -22,27 +22,19 @@ const VIEW_MUTED = 'muted';
function ListBlocked(props: Props) { function ListBlocked(props: Props) {
const { mutedUris, blockedUris, fetchingModerationBlockList } = props; const { mutedUris, blockedUris, fetchingModerationBlockList } = props;
const [viewMode, setViewMode] = usePersistedState('blocked-muted:display', VIEW_BLOCKED); const [viewMode, setViewMode] = usePersistedState('blocked-muted:display', VIEW_BLOCKED);
const [loading, setLoading] = React.useState(!blockedUris || !blockedUris.length);
// Keep a local list to allow for undoing actions in this component // Keep a local list to allow for undoing actions in this component
const [localBlockedList, setLocalBlockedList] = React.useState(undefined); const [localBlockedList, setLocalBlockedList] = React.useState(undefined);
const [localMutedList, setLocalMutedList] = React.useState(undefined); const [localMutedList, setLocalMutedList] = React.useState(undefined);
const previousFetchingModBlockList = usePrevious(fetchingModerationBlockList);
const hasLocalMuteList = localMutedList && localMutedList.length > 0; const hasLocalMuteList = localMutedList && localMutedList.length > 0;
const hasLocalBlockList = localBlockedList && localBlockedList.length > 0; const hasLocalBlockList = localBlockedList && localBlockedList.length > 0;
const stringifiedMutedChannels = JSON.stringify(mutedUris); const stringifiedMutedChannels = JSON.stringify(mutedUris);
const justMuted = localMutedList && mutedUris && localMutedList.length < mutedUris.length; const justMuted = localMutedList && mutedUris && localMutedList.length < mutedUris.length;
const justBlocked = localBlockedList && blockedUris && localBlockedList.length < blockedUris.length; const justBlocked = localBlockedList && blockedUris && localBlockedList.length < blockedUris.length;
const stringifiedBlockedChannels = JSON.stringify(blockedUris); const stringifiedBlockedChannels = JSON.stringify(blockedUris);
const showUris = (viewMode === VIEW_MUTED && hasLocalMuteList) || (viewMode === VIEW_BLOCKED && hasLocalBlockList);
React.useEffect(() => {
if (previousFetchingModBlockList && !fetchingModerationBlockList) {
setLoading(false);
}
}, [setLoading, previousFetchingModBlockList, fetchingModerationBlockList]);
React.useEffect(() => { React.useEffect(() => {
const jsonMutedChannels = stringifiedMutedChannels && JSON.parse(stringifiedMutedChannels); const jsonMutedChannels = stringifiedMutedChannels && JSON.parse(stringifiedMutedChannels);
@ -70,15 +62,22 @@ function ListBlocked(props: Props) {
} }
}, [stringifiedBlockedChannels, justBlocked, setLocalBlockedList]); }, [stringifiedBlockedChannels, justBlocked, setLocalBlockedList]);
const mutedHelpText = __(
'Muted channels will be invisible to you in the app. They will not know they are muted and can still interact with you and your content.'
);
const blockedHelpText = __(
"Blocked channels will be invisible to you in the app. They will not be able to comment on your content, or reply to you comments left on other channels' content."
);
return ( return (
<Page> <Page>
{loading && ( {fetchingModerationBlockList && (
<div className="main--empty"> <div className="main--empty">
<Spinner /> <Spinner />
</div> </div>
)} )}
{!loading && ( {!fetchingModerationBlockList && (
<> <>
<div className="section__header--actions"> <div className="section__header--actions">
<div className="section__actions--inline"> <div className="section__actions--inline">
@ -102,38 +101,50 @@ function ListBlocked(props: Props) {
/> />
</div> </div>
</div> </div>
<div className="help--notice">
{viewMode === VIEW_MUTED {showUris && <div className="help--notice">{viewMode === VIEW_MUTED ? mutedHelpText : blockedHelpText}</div>}
? __(
'Muted channels will be invisible to you in the app. They will not know they are muted and can still interact with you and your content.' {showUris ? (
) <ClaimList
: __( uris={viewMode === VIEW_MUTED ? localMutedList : localBlockedList}
"Blocked channels will be invisible to you in the app. They will not be able to comment on your content, or reply to you comments left on other channels' content." showUnresolvedClaims
)} showHiddenByUser
</div> hideMenu
<ClaimList renderActions={(claim) => {
uris={viewMode === VIEW_MUTED ? localMutedList : localBlockedList} return (
showUnresolvedClaims <div className="section__actions">
showHiddenByUser {viewMode === VIEW_MUTED ? (
hideMenu <>
renderActions={(claim) => { <ChannelMuteButton uri={claim.permanent_url} />
return ( <ChannelBlockButton uri={claim.permanent_url} />
<div className="section__actions"> </>
{viewMode === VIEW_MUTED ? ( ) : (
<> <>
<ChannelMuteButton uri={claim.permanent_url} /> <ChannelBlockButton uri={claim.permanent_url} />
<ChannelBlockButton uri={claim.permanent_url} /> <ChannelMuteButton uri={claim.permanent_url} />
</> </>
) : ( )}
<> </div>
<ChannelBlockButton uri={claim.permanent_url} /> );
<ChannelMuteButton uri={claim.permanent_url} /> }}
</> />
)} ) : (
</div> <div className="main--empty">
); <Yrbl
}} title={
/> viewMode === VIEW_MUTED
? __('You do not have any muted channels')
: __('You do not have any blocked channels')
}
subtitle={viewMode === VIEW_MUTED ? mutedHelpText : blockedHelpText}
actions={
<div className="section__actions">
<Button button="primary" label={__('Go Home')} navigate="/" />
</div>
}
/>
</div>
)}
</> </>
)} )}
</Page> </Page>

View file

@ -561,9 +561,12 @@ export function doFetchModBlockedList() {
dispatch({ dispatch({
type: ACTIONS.COMMENT_MODERATION_BLOCK_LIST_COMPLETED, type: ACTIONS.COMMENT_MODERATION_BLOCK_LIST_COMPLETED,
data: { data: {
blockList: globalBlockList blockList:
.sort((a, b) => new Date(a.blockedAt) - new Date(b.blockedAt)) globalBlockList.length > 0
.map((blockedChannel) => blockedChannel.channelUri), ? globalBlockList
.sort((a, b) => new Date(a.blockedAt) - new Date(b.blockedAt))
.map((blockedChannel) => blockedChannel.channelUri)
: null,
}, },
}); });
}) })

View file

@ -456,9 +456,8 @@
.claim-tile__title { .claim-tile__title {
position: relative; position: relative;
padding: var(--spacing-s); padding: var(--spacing-s);
padding-right: var(--spacing-m); padding-right: var(--spacing-l);
padding-bottom: 0; padding-bottom: 0;
margin-bottom: var(--spacing-s); margin-bottom: var(--spacing-s);
@ -474,6 +473,7 @@
@media (min-width: $breakpoint-small) { @media (min-width: $breakpoint-small) {
min-height: 2.5rem; min-height: 2.5rem;
padding-right: var(--spacing-m);
} }
} }
@ -601,8 +601,10 @@
stroke: var(--color-text); stroke: var(--color-text);
} }
&:not([aria-expanded='true']) { @media (min-width: $breakpoint-small) {
display: none; &:not([aria-expanded='true']) {
display: none;
}
} }
} }

View file

@ -101,35 +101,27 @@
} }
.header__navigation-item--profile-pic { .header__navigation-item--profile-pic {
margin-left: var(--spacing-m);
.channel-thumbnail { .channel-thumbnail {
height: var(--height-button); height: var(--height-button);
width: var(--height-button); width: var(--height-button);
margin-right: 0; margin-right: 0;
transition: border-radius var(--animation-duration);
border-radius: calc(var(--height-button) / 2);
img {
transition: border-radius var(--animation-duration);
border-radius: calc(var(--height-button) / 2);
}
} }
&:hover { &:hover {
opacity: 0.7; opacity: 0.7;
.channel-thumbnail {
border-radius: var(--border-radius);
img {
border-radius: var(--border-radius);
}
}
} }
} }
.header__navigation-item--balance { .header__navigation-item--balance {
@extend .button--link; @extend .button--file-action;
margin-left: var(--spacing-m); margin: 0 var(--spacing-s);
color: var(--color-text);
&:hover {
color: var(--color-text);
}
} }
.header__navigation-item--forward { .header__navigation-item--forward {

View file

@ -49,7 +49,7 @@
--color-input-color: #111111; --color-input-color: #111111;
--color-input-label: var(--color-gray-5); --color-input-label: var(--color-gray-5);
--color-input-placeholder: #212529; --color-input-placeholder: #212529;
--color-input-bg: #f4f4f4; --color-input-bg: var(--color-gray-1);
--color-input-bg-copyable: #434b53; --color-input-bg-copyable: #434b53;
--color-input-border: var(--color-border); --color-input-border: var(--color-border);
--color-input-border-active: var(--color-secondary); --color-input-border-active: var(--color-secondary);