Merge pull request #2399 from lbryio/routing-updates

Update sidebar: combine history and downloads page
This commit is contained in:
Sean Yesmunt 2019-04-01 02:01:46 -04:00 committed by GitHub
commit a31fd62e20
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
29 changed files with 316 additions and 212 deletions

View file

@ -107,9 +107,11 @@ class Button extends React.PureComponent<Props> {
to={path} to={path}
title={title} title={title}
onClick={e => e.stopPropagation()} onClick={e => e.stopPropagation()}
getProps={({ isCurrent }) => ({ getProps={({ isCurrent, isPartiallyCurrent }) => ({
className: className:
isCurrent && activeClass ? `${combinedClassName} ${activeClass}` : combinedClassName, (path === '/' ? isCurrent : isPartiallyCurrent) && activeClass
? `${combinedClassName} ${activeClass}`
: combinedClassName,
})} })}
> >
{content} {content}

View file

@ -15,7 +15,7 @@ class CardMedia extends React.PureComponent<Props> {
style={ style={
thumbnail thumbnail
? { backgroundImage: `url('${thumbnail}')` } ? { backgroundImage: `url('${thumbnail}')` }
: { backgroundImage: `url(${Placeholder})` } : { backgroundImage: `url(/${Placeholder})` }
} }
className="media__thumb" className="media__thumb"
/> />

View file

@ -1,6 +1,7 @@
// @flow // @flow
import type { Node } from 'react';
import * as ICONS from 'constants/icons'; import * as ICONS from 'constants/icons';
import React, { Fragment } from 'react'; import React from 'react';
type IconProps = { type IconProps = {
size: number, size: number,
@ -8,7 +9,7 @@ type IconProps = {
}; };
// Returns a react component // Returns a react component
const buildIcon = iconStrokes => (props: IconProps) => { const buildIcon = (iconStrokes: Node, options?: {} = {}) => (props: IconProps) => {
const { size = 24, color = 'currentColor', ...otherProps } = props; const { size = 24, color = 'currentColor', ...otherProps } = props;
return ( return (
<svg <svg
@ -16,11 +17,12 @@ const buildIcon = iconStrokes => (props: IconProps) => {
viewBox="0 0 24 24" viewBox="0 0 24 24"
width={size} width={size}
height={size} height={size}
fill="solid" fill="none"
stroke={color} stroke={color}
strokeWidth="2" strokeWidth="2"
strokeLinecap="round" strokeLinecap="round"
strokeLinejoin="round" strokeLinejoin="round"
{...options}
{...otherProps} {...otherProps}
> >
{iconStrokes} {iconStrokes}
@ -114,16 +116,11 @@ export const customIcons = {
[ICONS.UNSUBSCRIBE]: buildIcon( [ICONS.UNSUBSCRIBE]: buildIcon(
<path d="M 12,5.67 10.94,4.61 C 5.7533356,-0.57666427 -2.0266644,7.2033357 3.16,12.39 l 1.06,1.06 7.78,7.78 7.78,-7.78 1.06,-1.06 c 2.149101,-2.148092 2.149101,-5.6319078 0,-7.78 -2.148092,-2.1491008 -5.631908,-2.1491008 -7.78,0 L 9.4481298,8.2303201 15.320603,9.2419066 11.772427,13.723825" /> <path d="M 12,5.67 10.94,4.61 C 5.7533356,-0.57666427 -2.0266644,7.2033357 3.16,12.39 l 1.06,1.06 7.78,7.78 7.78,-7.78 1.06,-1.06 c 2.149101,-2.148092 2.149101,-5.6319078 0,-7.78 -2.148092,-2.1491008 -5.631908,-2.1491008 -7.78,0 L 9.4481298,8.2303201 15.320603,9.2419066 11.772427,13.723825" />
), ),
[ICONS.LBRY]: buildIcon( // The LBRY icon is different from the base icon set so don't use buildIcon()
<Fragment> [ICONS.LBRY]: props => (
<path <svg stroke="currentColor" fill="currentColor" transform="scale(0.1)" {...props}>
transform="scale(0.15)" <path d="M296.05, 85.9l0, 14.1l-138.8, 85.3l-104.6, -51.3l0.2, -7.9l104, 51.2l132.2, -81.2l0, -5.8l-124.8, -60.2l-139.2, 86.1l0, 38.5l131.8, 65.2l137.6, -84.4l3.9, 6l-141.1, 86.4l-139.2, -68.8l0, -46.8l145.8, -90.2l132.2, 63.8Z" />
d="M296.05, 85.9l0, 14.1l-138.8, 85.3l-104.6, -51.3l0.2, -7.9l104, 51.2l132.2, -81.2l0, -5.8l-124.8, -60.2l-139.2, 86.1l0, 38.5l131.8, 65.2l137.6, -84.4l3.9, 6l-141.1, 86.4l-139.2, -68.8l0, -46.8l145.8, -90.2l132.2, 63.8Z" <path d="M294.25, 150.9l2, -12.6l-12.2, -2.1l0.8, -4.9l17.1, 2.9l-2.8, 17.5l-4.9, -0.8Z" />
/> </svg>
<path
transform="scale(0.15)"
d="M294.25, 150.9l2, -12.6l-12.2, -2.1l0.8, -4.9l17.1, 2.9l-2.8, 17.5l-4.9, -0.8Z"
/>
</Fragment>
), ),
}; };

View file

@ -2,6 +2,7 @@
import * as ICONS from 'constants/icons'; import * as ICONS from 'constants/icons';
import React from 'react'; import React from 'react';
import Tooltip from 'component/common/tooltip'; import Tooltip from 'component/common/tooltip';
import classnames from 'classnames';
import { customIcons } from './icon-custom'; import { customIcons } from './icon-custom';
let featherIcons = false; let featherIcons = false;
@ -35,6 +36,7 @@ type Props = {
tooltip?: string, // tooltip direction tooltip?: string, // tooltip direction
iconColor?: string, iconColor?: string,
size?: number, size?: number,
className?: string,
}; };
class IconComponent extends React.PureComponent<Props> { class IconComponent extends React.PureComponent<Props> {
@ -63,7 +65,7 @@ class IconComponent extends React.PureComponent<Props> {
}; };
render() { render() {
const { icon, tooltip, iconColor, size } = this.props; const { icon, tooltip, iconColor, size, className } = this.props;
const Icon = customIcons[this.props.icon] || LazyFeatherIcons[this.props.icon]; const Icon = customIcons[this.props.icon] || LazyFeatherIcons[this.props.icon];
if (!Icon) { if (!Icon) {
@ -83,9 +85,16 @@ class IconComponent extends React.PureComponent<Props> {
} }
const inner = ( const inner = (
<React.Suspense <React.Suspense
fallback={<svg height={iconSize} width={iconSize} className="icon" color={color} />} fallback={
<svg
height={iconSize}
width={iconSize}
className={classnames('icon', className)}
color={color}
/>
}
> >
<Icon size={iconSize} className="icon" color={color} /> <Icon size={iconSize} className={classnames('icon', className)} color={color} />
</React.Suspense> </React.Suspense>
); );

View file

@ -4,6 +4,7 @@ import * as React from 'react';
import Button from 'component/button'; import Button from 'component/button';
import LbcSymbol from 'component/common/lbc-symbol'; import LbcSymbol from 'component/common/lbc-symbol';
import WunderBar from 'component/wunderbar'; import WunderBar from 'component/wunderbar';
import Icon from 'component/common/icon';
type Props = { type Props = {
autoUpdateDownloaded: boolean, autoUpdateDownloaded: boolean,
@ -37,42 +38,26 @@ const Header = (props: Props) => {
<header className="header"> <header className="header">
<div className="header__navigation"> <div className="header__navigation">
{/* @if TARGET='app' */} {/* @if TARGET='app' */}
<Button <div className="header__navigation-app">
className="header__navigation-item header__navigation-item--wallet" <Icon className="lbry-icon" icon={ICONS.LBRY} />
description={__('Your wallet')} <div className="header__navigation-arrows">
title={`Your balance is ${balance} LBRY Credits`} <Button
label={ className="header__navigation-item header__navigation-item--back"
<React.Fragment> description={__('Navigate back')}
<span>{roundedBalance}</span> onClick={() => window.history.back()}
<LbcSymbol /> icon={ICONS.ARROW_LEFT}
</React.Fragment> iconSize={15}
} />
navigate="/$/wallet"
/>
<Button <Button
className="header__navigation-item header__navigation-item--back" className="header__navigation-item header__navigation-item--forward"
description={__('Navigate back')} description={__('Navigate forward')}
onClick={() => window.history.back()} onClick={() => window.history.forward()}
icon={ICONS.ARROW_LEFT} icon={ICONS.ARROW_RIGHT}
iconSize={15} iconSize={15}
/> />
</div>
<Button </div>
className="header__navigation-item header__navigation-item--forward"
description={__('Navigate forward')}
onClick={() => window.history.forward()}
icon={ICONS.ARROW_RIGHT}
iconSize={15}
/>
<Button
className="header__navigation-item header__navigation-item--home"
description={__('Home')}
icon={ICONS.HOME}
iconSize={15}
navigate="/"
/>
{/* @endif */} {/* @endif */}
{/* @if TARGET='web' */} {/* @if TARGET='web' */}
<Button <Button
@ -94,6 +79,19 @@ const Header = (props: Props) => {
iconSize={15} iconSize={15}
/> />
<Button
className="header__navigation-item header__navigation-item--wallet"
description={__('Your wallet')}
title={`Your balance is ${balance} LBRY Credits`}
label={
<React.Fragment>
<span>{roundedBalance}</span>
<LbcSymbol />
</React.Fragment>
}
navigate="/$/wallet"
/>
<Button <Button
className="header__navigation-item header__navigation-item--right-action" className="header__navigation-item header__navigation-item--right-action"
description={__('Publish content')} description={__('Publish content')}

View file

@ -1,6 +1,5 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { selectHistoryPageCount, makeSelectHistoryForPage } from 'redux/selectors/content'; import { selectHistoryPageCount, makeSelectHistoryForPage } from 'redux/selectors/content';
import { selectCurrentParams, makeSelectCurrentParam } from 'lbry-redux';
import { doClearContentHistoryUri } from 'redux/actions/content'; import { doClearContentHistoryUri } from 'redux/actions/content';
import UserHistory from './view'; import UserHistory from './view';

View file

@ -3,7 +3,7 @@ import * as React from 'react';
import Button from 'component/button'; import Button from 'component/button';
import { Form, FormField } from 'component/common/form'; import { Form, FormField } from 'component/common/form';
import ReactPaginate from 'react-paginate'; import ReactPaginate from 'react-paginate';
import UserHistoryItem from 'component/userHistoryItem'; import NavigationHistoryItem from 'component/navigationHistoryItem';
import { navigate } from '@reach/router'; import { navigate } from '@reach/router';
type HistoryItem = { type HistoryItem = {
@ -52,8 +52,7 @@ class UserHistoryPage extends React.PureComponent<Props, State> {
} }
changePage(pageNumber: number) { changePage(pageNumber: number) {
console.log('new', pageNumber); navigate(`?page=${pageNumber}`);
navigate(`/$/user_history?page=${pageNumber}`);
} }
paginate(e: SyntheticKeyboardEvent<*>) { paginate(e: SyntheticKeyboardEvent<*>) {
@ -94,7 +93,7 @@ class UserHistoryPage extends React.PureComponent<Props, State> {
render() { render() {
const { history = [], page, pageCount } = this.props; const { history = [], page, pageCount } = this.props;
console.log('this.props', this.props);
const { itemsSelected } = this.state; const { itemsSelected } = this.state;
const allSelected = Object.keys(itemsSelected).length === history.length; const allSelected = Object.keys(itemsSelected).length === history.length;
const selectHandler = allSelected ? this.unselectAll : this.selectAll; const selectHandler = allSelected ? this.unselectAll : this.selectAll;
@ -118,7 +117,7 @@ class UserHistoryPage extends React.PureComponent<Props, State> {
{!!history.length && ( {!!history.length && (
<section className="card__content item-list"> <section className="card__content item-list">
{history.map(item => ( {history.map(item => (
<UserHistoryItem <NavigationHistoryItem
key={item.uri} key={item.uri}
uri={item.uri} uri={item.uri}
lastViewed={item.lastViewed} lastViewed={item.lastViewed}

View file

@ -0,0 +1,68 @@
// @flow
import React from 'react';
import type { Claim } from 'types/claim';
import moment from 'moment';
import classnames from 'classnames';
import Button from 'component/button';
import { FormField } from 'component/common/form';
import { navigate } from '@reach/router';
import { formatLbryUriForWeb } from 'util/uri';
type Props = {
lastViewed: number,
uri: string,
claim: ?Claim,
selected: boolean,
onSelect?: () => void,
resolveUri: string => void,
slim: boolean,
};
class NavigationHistoryItem extends React.PureComponent<Props> {
static defaultProps = {
slim: false,
};
componentDidMount() {
const { claim, uri, resolveUri } = this.props;
if (!claim) {
resolveUri(uri);
}
}
render() {
const { lastViewed, selected, onSelect, claim, uri, slim } = this.props;
let name;
let title;
if (claim && claim.value && claim.value.stream) {
({ name } = claim);
({ title } = claim.value.stream.metadata);
}
const navigatePath = formatLbryUriForWeb(uri);
const onClick =
onSelect ||
function() {
navigate(navigatePath);
};
return (
<div
role="button"
onClick={onClick}
className={classnames('item-list__row', {
'item-list__row--selected': selected,
})}
>
{!slim && <FormField checked={selected} type="checkbox" onChange={onSelect} />}
<span className="time time--ago">{moment(lastViewed).from(moment())}</span>
<Button className="item-list__element" constrict button="link" label={uri} navigate={uri} />
<span className="item-list__element">{title}</span>
</div>
);
}
}
export default NavigationHistoryItem;

View file

@ -0,0 +1,12 @@
import { connect } from 'react-redux';
import { selectRecentHistory } from 'redux/selectors/content';
import RecentUserHistory from './view';
const select = (state, props) => ({
history: selectRecentHistory(state),
});
export default connect(
select,
null
)(RecentUserHistory);

View file

@ -0,0 +1,37 @@
// @flow
import React, { Fragment } from 'react';
import Button from 'component/button';
import { Form, FormField } from 'component/common/form';
import ReactPaginate from 'react-paginate';
import NavigationHistoryItem from 'component/navigationHistoryItem';
import { navigate } from '@reach/router';
type HistoryItem = {
uri: string,
lastViewed: number,
};
type Props = {
history: Array<HistoryItem>,
page: number,
pageCount: number,
clearHistoryUri: string => void,
params: { page: number },
};
export default function UserHistoryRecent(props: Props) {
const { history = [], page, pageCount } = props;
return history.length ? (
<div className="item-list">
<section className="card__content">
{history.map(({ lastViewed, uri }) => (
<NavigationHistoryItem slim key={uri} uri={uri} lastViewed={lastViewed} />
))}
</section>
<div className="card__actions">
<Button navigate="/$/history/all" button="link" label={__('See All Visited Links')} />
</div>
</div>
) : null;
}

View file

@ -4,7 +4,7 @@ import { Router } from '@reach/router';
import SettingsPage from 'page/settings'; import SettingsPage from 'page/settings';
import HelpPage from 'page/help'; import HelpPage from 'page/help';
import ReportPage from 'page/report'; import ReportPage from 'page/report';
import WalletPage from 'page/wallet'; import AccountPage from 'page/account';
import ShowPage from 'page/show'; import ShowPage from 'page/show';
import PublishPage from 'page/publish'; import PublishPage from 'page/publish';
import DiscoverPage from 'page/discover'; import DiscoverPage from 'page/discover';
@ -18,6 +18,8 @@ import BackupPage from 'page/backup';
import SubscriptionsPage from 'page/subscriptions'; import SubscriptionsPage from 'page/subscriptions';
import SearchPage from 'page/search'; import SearchPage from 'page/search';
import UserHistoryPage from 'page/userHistory'; import UserHistoryPage from 'page/userHistory';
import SendCreditsPage from 'page/sendCredits';
import NavigationHistory from 'page/navigationHistory';
export default function AppRouter(props) { export default function AppRouter(props) {
return ( return (
@ -38,9 +40,12 @@ export default function AppRouter(props) {
<SearchPage path={`$/${PAGES.SEARCH}`} /> <SearchPage path={`$/${PAGES.SEARCH}`} />
<SettingsPage path={`$/${PAGES.SETTINGS}`} /> <SettingsPage path={`$/${PAGES.SETTINGS}`} />
<SubscriptionsPage path={`$/${PAGES.SUBSCRIPTIONS}`} /> <SubscriptionsPage path={`$/${PAGES.SUBSCRIPTIONS}`} />
<TransactionHistoryPage path={`$/${PAGES.HISTORY}`} /> <TransactionHistoryPage path={`$/${PAGES.TRANSACTIONS}`} />
<UserHistoryPage path={`$/${PAGES.USER_HISTORY}`} /> <UserHistoryPage path={`$/${PAGES.HISTORY}`} />
<WalletPage path={`$/${PAGES.WALLET}`} /> <AccountPage path={`$/${PAGES.ACCOUNT}`} />
<SendCreditsPage path={`$/${PAGES.SEND}`} />
<UserHistoryPage path={`$/${PAGES.HISTORY}`} />
<NavigationHistory path={`$/${PAGES.HISTORY}/all`} />
</Router> </Router>
); );
} }

View file

@ -43,7 +43,7 @@ class SideBar extends React.PureComponent<Props> {
<ul className="navigation__links"> <ul className="navigation__links">
{[ {[
{ {
...buildLink(null, __('Home'), ICONS.HOME), ...buildLink(null, __('Discover'), ICONS.DISCOVER),
}, },
{ {
...buildLink( ...buildLink(
@ -54,53 +54,46 @@ class SideBar extends React.PureComponent<Props> {
ICONS.SUBSCRIPTION ICONS.SUBSCRIPTION
), ),
}, },
{
...buildLink(PAGES.PUBLISHED, 'Publishes', ICONS.PUBLISHED),
},
{
...buildLink(PAGES.HISTORY, 'History', ICONS.HISTORY),
},
].map(renderLink)} ].map(renderLink)}
</ul> </ul>
<div className="navigation__link navigation__link--title">Account</div>
<div className="navigation__link navigation__link--title">My LBRY</div>
<div className="navigation__links">
<ul>
{[
{
...buildLink(PAGES.DOWNLOADED, 'Downloads', ICONS.LOCAL),
},
{
...buildLink(PAGES.PUBLISHED, 'Publishes', ICONS.PUBLISHED),
},
{
...buildLink(PAGES.USER_HISTORY, 'History', ICONS.HISTORY),
},
{
...buildLink(PAGES.INVITE, 'Invite', ICONS.INVITE),
},
{
...buildLink(PAGES.REWARDS, 'Rewards', ICONS.FEATURED),
},
].map(renderLink)}
</ul>
</div>
<div className="navigation__link navigation__link--title">Wallet</div>
<ul className="navigation__links"> <ul className="navigation__links">
{[ {[
{ {
...buildLink(PAGES.WALLET, 'Overview', ICONS.WALLET), ...buildLink(PAGES.ACCOUNT, 'Overview', ICONS.ACCOUNT),
}, },
{ {
...buildLink(PAGES.HISTORY, 'Transactions', ICONS.TRANSACTIONS), ...buildLink(PAGES.INVITE, 'Invite', ICONS.INVITE),
}, },
{
...buildLink(PAGES.REWARDS, 'Rewards', ICONS.FEATURED),
},
{
...buildLink(PAGES.SEND, 'Send & Recieve', ICONS.SEND),
},
{
...buildLink(PAGES.TRANSACTIONS, 'Transactions', ICONS.TRANSACTIONS),
},
{
...buildLink(PAGES.SETTINGS, 'Settings', ICONS.SETTINGS),
},
// @if TARGET='app'
{ {
...buildLink(PAGES.BACKUP, 'Backup', ICONS.BACKUP), ...buildLink(PAGES.BACKUP, 'Backup', ICONS.BACKUP),
}, },
// @endif
].map(renderLink)} ].map(renderLink)}
</ul> </ul>
<ul className="navigation__links navigation__links--bottom"> <ul className="navigation__links navigation__links--bottom">
{[ {[
{
...buildLink(PAGES.SETTINGS, 'Settings', ICONS.SETTINGS),
},
{ {
...buildLink(PAGES.HELP, 'Help', ICONS.HELP), ...buildLink(PAGES.HELP, 'Help', ICONS.HELP),
}, },

View file

@ -35,7 +35,7 @@ class TransactionListRecent extends React.PureComponent<Props> {
<p className="card__subtitle"> <p className="card__subtitle">
{__('To view all of your transactions, navigate to the')}{' '} {__('To view all of your transactions, navigate to the')}{' '}
<Button button="link" navigate="/$/history" label={__('transactions page')} />. <Button button="link" navigate="/$/transactions" label={__('transactions page')} />.
</p> </p>
</header> </header>
@ -57,7 +57,7 @@ class TransactionListRecent extends React.PureComponent<Props> {
<div className="card__actions"> <div className="card__actions">
<Button <Button
button="primary" button="primary"
navigate="/$/history" navigate="/$/transactions"
label={__('Full History')} label={__('Full History')}
icon={icons.HISTORY} icon={icons.HISTORY}
/> />

View file

@ -1,61 +0,0 @@
// @flow
import React from 'react';
import type { Claim } from 'types/claim';
import moment from 'moment';
import classnames from 'classnames';
import Button from 'component/button';
import { FormField } from 'component/common/form';
type Props = {
lastViewed: number,
uri: string,
claim: ?Claim,
selected: boolean,
onSelect: () => void,
resolveUri: string => void,
};
class UserHistoryItem extends React.PureComponent<Props> {
componentDidMount() {
const { claim, uri, resolveUri } = this.props;
if (!claim) {
resolveUri(uri);
}
}
render() {
const { lastViewed, selected, onSelect, claim } = this.props;
let name;
let title;
let uri;
if (claim && claim.value && claim.value.stream) {
({ name } = claim);
({ title } = claim.value.stream.metadata);
uri = claim.permanent_url;
}
return (
<div
role="button"
onClick={onSelect}
className={classnames('item-list__item', {
'item-list__item--selected': selected,
})}
>
<FormField checked={selected} type="checkbox" onChange={onSelect} />
<span className="time time--ago">{moment(lastViewed).from(moment())}</span>
<span className="item-list__item--cutoff">{title}</span>
<Button
constrict
button="link"
label={name ? `lbry://${name}` : `lbry://...`}
navigate={uri}
/>
</div>
);
}
}
export default UserHistoryItem;

View file

@ -1 +0,0 @@
export const HISTORY_ITEMS_PER_PAGE = 50;

View file

@ -37,7 +37,7 @@ export const VIEW = 'Eye';
export const PLAY = 'Play'; export const PLAY = 'Play';
export const FACEBOOK = 'Facebook'; export const FACEBOOK = 'Facebook';
export const TWITTER = 'Twitter'; export const TWITTER = 'Twitter';
export const WALLET = 'CreditCard'; export const ACCOUNT = 'User';
export const SETTINGS = 'Settings'; export const SETTINGS = 'Settings';
export const INVITE = 'Users'; export const INVITE = 'Users';
export const FILE = 'File'; export const FILE = 'File';
@ -51,3 +51,5 @@ export const MENU = 'Menu';
export const BACKUP = 'Database'; export const BACKUP = 'Database';
export const TRANSACTIONS = 'FileText'; export const TRANSACTIONS = 'FileText';
export const LBRY = 'Lbry'; export const LBRY = 'Lbry';
export const SEND = 'Send';
export const DISCOVER = 'Compass';

View file

@ -14,7 +14,7 @@ export const REWARDS = 'rewards';
export const SEND = 'send'; export const SEND = 'send';
export const SETTINGS = 'settings'; export const SETTINGS = 'settings';
export const SHOW = 'show'; export const SHOW = 'show';
export const WALLET = 'wallet'; export const ACCOUNT = 'account';
export const SUBSCRIPTIONS = 'subscriptions'; export const SUBSCRIPTIONS = 'subscriptions';
export const SEARCH = 'search'; export const SEARCH = 'search';
export const USER_HISTORY = 'user_history'; export const TRANSACTIONS = 'transactions';

View file

@ -17,7 +17,9 @@ class FileListDownloaded extends React.PureComponent<Props> {
const hasDownloads = fileInfos && Object.values(fileInfos).length > 0; const hasDownloads = fileInfos && Object.values(fileInfos).length > 0;
return ( return (
<Page notContained loading={fetching}> // Removed the <Page> wapper to try combining this page with UserHistory
// This should eventually move into /components if we want to keep it this way
<React.Fragment>
{hasDownloads ? ( {hasDownloads ? (
<FileList fileInfos={fileInfos} sortBy={sortBy} page={PAGES.DOWNLOADED} /> <FileList fileInfos={fileInfos} sortBy={sortBy} page={PAGES.DOWNLOADED} />
) : ( ) : (
@ -37,7 +39,7 @@ class FileListDownloaded extends React.PureComponent<Props> {
</section> </section>
</div> </div>
)} )}
</Page> </React.Fragment>
); );
} }
} }

View file

@ -0,0 +1,3 @@
import UserHistoryPage from './view';
export default UserHistoryPage;

View file

@ -0,0 +1,13 @@
// @flow
import React from 'react';
import Page from 'component/page';
import NavigationHistory from 'component/navigationHistory';
export default function NavigationHistoryPage(props: any) {
// Pass `props` into the component for reach router props
return (
<Page>
<NavigationHistory {...props} />
</Page>
);
}

View file

@ -1,7 +1,8 @@
// @flow // @flow
import React from 'react'; import React from 'react';
import Page from 'component/page'; import Page from 'component/page';
import UserHistory from 'component/userHistory'; import UserHistory from 'component/navigationHistoryRecent';
import DownloadList from 'page/fileListDownloaded';
type Props = {}; type Props = {};
@ -10,6 +11,7 @@ class UserHistoryPage extends React.PureComponent<Props> {
return ( return (
<Page> <Page>
<UserHistory {...this.props} /> <UserHistory {...this.props} />
<DownloadList {...this.props} />
</Page> </Page>
); );
} }

View file

@ -5,7 +5,9 @@ import {
selectClaimsByUri, selectClaimsByUri,
makeSelectClaimsInChannelForCurrentPageState, makeSelectClaimsInChannelForCurrentPageState,
} from 'lbry-redux'; } from 'lbry-redux';
import { HISTORY_ITEMS_PER_PAGE } from 'constants/content';
const RECENT_HISTORY_AMOUNT = 10;
const HISTORY_ITEMS_PER_PAGE = 50;
export const selectState = (state: any) => state.content || {}; export const selectState = (state: any) => state.content || {};
@ -33,39 +35,40 @@ export const makeSelectContentPositionForUri = (uri: string) =>
} }
); );
export const selectHistoryPageCount = createSelector( export const selectHistory = createSelector(
selectState, selectState,
state => Math.ceil(state.history.length / HISTORY_ITEMS_PER_PAGE) state => state.history || []
);
export const selectHistoryPageCount = createSelector(
selectHistory,
history => Math.ceil(history.length / HISTORY_ITEMS_PER_PAGE)
); );
export const makeSelectHistoryForPage = (page: number) => export const makeSelectHistoryForPage = (page: number) =>
createSelector( createSelector(
selectState, selectHistory,
selectClaimsByUri, selectClaimsByUri,
(state, claimsByUri) => { (history, claimsByUri) => {
const left = page * HISTORY_ITEMS_PER_PAGE; const left = page * HISTORY_ITEMS_PER_PAGE;
const historyItems = state.history.slice(left, left + HISTORY_ITEMS_PER_PAGE); const historyItemsForPage = history.slice(left, left + HISTORY_ITEMS_PER_PAGE);
return historyItemsForPage;
// See if we have the claim info for the uris in your history
// If not, it will need to be fetched in the component
return historyItems.map(historyItem => {
const { uri, lastViewed } = historyItem;
const claimAtUri = claimsByUri[uri];
if (claimAtUri) {
return { lastViewed, uri, ...claimAtUri };
}
return historyItem;
});
} }
); );
export const makeSelectHistoryForUri = (uri: string) => export const makeSelectHistoryForUri = (uri: string) =>
createSelector( createSelector(
selectState, selectHistory,
state => state.history.find(i => i.uri === uri) history => history.find(i => i.uri === uri)
); );
export const selectRecentHistory = createSelector(
selectHistory,
history => {
return history.slice(0, RECENT_HISTORY_AMOUNT);
}
);
export const makeSelectCategoryListUris = (uris: ?Array<string>, channel: string) => export const makeSelectCategoryListUris = (uris: ?Array<string>, channel: string) =>
createSelector( createSelector(
makeSelectClaimsInChannelForCurrentPageState(channel), makeSelectClaimsInChannelForCurrentPageState(channel),

View file

@ -19,20 +19,10 @@
display: flex; display: flex;
&:first-of-type { &:first-of-type {
html[data-mode='dark'] & {
border-color: $lbry-gray-5;
}
// Main navigation collapses into a menu button // Main navigation collapses into a menu button
// at smaller screen widths // at smaller screen widths
@media (min-width: 601px) { @media (min-width: 601px) {
/* @if TARGET='app' */
width: 250px;
/* @endif */
/* @if TARGET='web' */
width: 170px; width: 170px;
/* @endif */
} }
@media (max-width: 600px) { @media (max-width: 600px) {
@ -41,6 +31,29 @@
} }
} }
.header__navigation-app {
flex: 1;
display: flex;
justify-content: space-between;
// LBRY logo in the top left corner
.lbry-icon {
height: 1rem;
width: 1rem;
padding-left: 3.5rem;
padding-top: 1.5rem;
margin-right: 3.6rem;
overflow: visible;
}
.header__navigation-arrows {
flex: 1;
display: flex;
justify-content: flex-end;
border-left: 1px solid $lbry-gray-1;
}
}
.header__navigation-item { .header__navigation-item {
height: var(--header-height); height: var(--header-height);
display: flex; display: flex;
@ -73,6 +86,7 @@
.header__navigation-item--home, .header__navigation-item--home,
.header__navigation-item--menu { .header__navigation-item--menu {
width: var(--header-height); width: var(--header-height);
svg { svg {
&:only-child { &:only-child {
// Header icons are a little different because they are larger // Header icons are a little different because they are larger
@ -95,7 +109,7 @@
overflow: visible; overflow: visible;
color: $lbry-white; color: $lbry-white;
opacity: 1; opacity: 1;
top: -0.2rem; top: -0.8rem;
} }
} }
@ -130,7 +144,7 @@
.header__navigation-item--wallet { .header__navigation-item--wallet {
border-right: 1px solid $lbry-gray-1; border-right: 1px solid $lbry-gray-1;
width: calc(100% - (var(--header-height) * 3)); width: 10rem;
html[data-mode='dark'] & { html[data-mode='dark'] & {
border-color: $lbry-gray-5; border-color: $lbry-gray-5;

View file

@ -1,37 +1,42 @@
.item-list { .item-list {
background-color: $lbry-white; background-color: $lbry-white;
margin-top: var(--spacing-vertical-large); margin-top: var(--spacing-vertical-large);
margin-bottom: var(--spacing-vertical-large);
padding: var(--spacing-vertical-large); padding: var(--spacing-vertical-large);
html[data-mode='dark'] & { html[data-mode='dark'] & {
background-color: rgba($lbry-white, 0.1); background-color: rgba($lbry-white, 0.1);
} }
.card__actions {
margin-top: var(--spacing-vertical-medium);
margin-left: var(--spacing-vertical-small);
}
} }
.item-list__item { .item-list__row {
align-items: center; align-items: center;
display: flex; display: flex;
padding: var(--spacing-vertical-small); padding: var(--spacing-vertical-small);
input,
.item-list__item--cutoff {
margin-right: var(--spacing-vertical-large);
}
fieldset-section { fieldset-section {
margin-bottom: 0; margin-bottom: 0;
} }
} }
.item-list__item--cutoff { .item-list__element {
max-width: 350px;
overflow-x: hidden; overflow-x: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
&:not(:first-of-type) {
padding-left: var(--spacing-vertical-small);
}
} }
.item-list__item--selected { .item-list__row:hover,
background-color: $lbry-gray-1; .item-list__row--selected {
background-color: rgba($lbry-black, 0.1);
html[data-mode='dark'] & { html[data-mode='dark'] & {
background-color: rgba($lbry-black, 0.5); background-color: rgba($lbry-black, 0.5);

View file

@ -5,6 +5,9 @@
padding-top: var(--spacing-vertical-large); padding-top: var(--spacing-vertical-large);
padding-right: var(--spacing-vertical-small); padding-right: var(--spacing-vertical-small);
position: relative; position: relative;
display: flex;
flex-direction: column;
overflow-y: overlay;
html[data-mode='dark'] & { html[data-mode='dark'] & {
background-color: $lbry-black; background-color: $lbry-black;
@ -15,7 +18,7 @@
// on smaller screen widths // on smaller screen widths
@media (min-width: 601px) { @media (min-width: 601px) {
min-width: 171px; // 1px is for the border width: 171px; // 1px is for the border
} }
@media (max-width: 600px) { @media (max-width: 600px) {
@ -53,8 +56,8 @@
} }
.navigation__links--bottom { .navigation__links--bottom {
position: absolute; margin-top: auto;
bottom: var(--spacing-vertical-large); margin-bottom: var(--spacing-vertical-large);
} }
.navigation__link { .navigation__link {

View file

@ -5,5 +5,5 @@
} }
.time--ago { .time--ago {
min-width: 160px; min-width: 140px;
} }